Processing...
Description & Source Code
  • Description
  • View
  • Controller
  • Model
    SpreadsheetData.java
    Year.java
    Quarter.java
    Month.java

The ZK grid component is enriched with spreadsheet functionalities such as frozen columns, in place editing, and merging the cells in grid. In this demo, the first three columns are frozen and cells are merged to layout the grid data.

To freeze columns, simply declare the number of frozen columns needed starting from the left hand side; in the case of this demo: <frozen columns="3">.

To merge cells in grid, declare a cell component and specify the rowspan and colspan with respect to the number of cells you wish to merge vertically, or horizontally.

Since ZK 6, all input components (intbox, combobox, etc.) support in-place editing. To enable this feature, simply set inplace="true" in the input component tags.

spreadsheet_functionalities.zul
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?>
<zk>
	<style src="/widgets/grid/spreadsheet_functionalities/style.css" />
	<div apply="demo.grid.spreadsheet_functionalities.SpreadsheetController" width="100%">
		<grid sclass="grid-spreadsheet" height="350px" width="100%"
			model="${$composer.months}">
			<frozen style="background: #DFDED8" columns="3">
				<div style="padding: 0 10px;" />
			</frozen>
			<columns>
				<column label="Year" width="80px" />
				<column label="Season" width="80px" />
				<column label="Month" width="80px" />
				<column style="text-align:right;" width="80px"
					forEach="${$composer.days}" 
					label="${forEachStatus.index + 1}" />
			</columns>
			<template name="model">
				<row>
					<cell sclass="years" rowspan="12"
						if="${each.firstMonthOfTheYear}">
						<label value="${each.quarter.year.name}" />
					</cell>

					<cell sclass="season" rowspan="3"
						if="${each.firstMonthOfTheQuarter}">
						<label value="${each.quarter.name}" />
					</cell>

					<cell sclass="month">
						<label value="${each.name}" width="100%" />
					</cell>

					<intbox forEach="${$composer.days}"
						format="#,###" constraint="no empty" width="60px"
						inplace="true"
						value="${each.days[forEachStatus.index] }"
						style="${each.days[forEachStatus.index] lt 0 ? 'color:red;text-align:right' : 'color:#373842;text-align:right'}"
						if="${each.numberOfDays gt forEachStatus.index}" />
				</row>
			</template>

		</grid>
	</div>
</zk>
SpreadsheetController.java
package demo.grid.spreadsheet_functionalities;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;

public class SpreadsheetController extends SelectorComposer<Component> {
	private static final long serialVersionUID = 1L;
	
	private final SpreadsheetData sdm = new SpreadsheetData();
	
	public ListModel<Month> getMonths() {
		return new ListModelList<Month>(sdm.getMonths(), true);
	}
	
	public String[] getDays() {
		return new String[31];
	}
}
SpreadsheetData.java
package demo.grid.spreadsheet_functionalities;

import java.util.ArrayList;
import java.util.List;

public class SpreadsheetData {
	
	private final List<Year> years = new ArrayList<Year>();
	

	public SpreadsheetData(){
		years.add(new Year(2011));
	}
	
	public List<Year> getYears() {
		return years;
	}
	
	public List<Month> getMonths() {
		List<Month> allMonths = new ArrayList<Month>();
		
		for(Year yr : getYears()) {
			for(Quarter q : yr.getQuarters()) {
				allMonths.addAll(q.getMonths());
			}
		}
		
		return allMonths;
	}
}
Year.java
package demo.grid.spreadsheet_functionalities;

import java.util.ArrayList;
import java.util.List;

public class Year {
	
	private final List<Quarter> quarters = new ArrayList<Quarter>();
	private final int year;
	private final String name;
	
	public Year(int year) {
		this.year = year;
		name = Integer.toString(year);
		
		quarters.add(new Quarter(Year.this, 1));
		quarters.add(new Quarter(Year.this, 2));
		quarters.add(new Quarter(Year.this, 3));
		quarters.add(new Quarter(Year.this, 4));
	}
	
	public List<Quarter> getQuarters() {
		return quarters;
	}
	
	public String getName() {
		return name;
	}
}
Quarter.java
package demo.grid.spreadsheet_functionalities;

import java.util.ArrayList;
import java.util.List;

public class Quarter {
	
	private final String name;
	private final List<Month> months = new ArrayList<Month>();
	private final Year year;
	
	public Quarter(Year year, int quarter) {
		this.year = year;
		name = String.format("Q%d", quarter);
		
		int start = (quarter - 1) * 3;
		for(int i=start; i< start+3; i++) {
			months.add(new Month(this, i));
		}
	}
	
	public String getName() {
		return name;
	}
	
	public Year getYear() {
		return year;
	}
	
	public List<Month> getMonths() {
		return months;
	}
	
}
Month.java
package demo.grid.spreadsheet_functionalities;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;

public class Month {

	private static final SimpleDateFormat sdf = new SimpleDateFormat("MMM");
	private static final Random random = new Random(System.currentTimeMillis());
	
	private final String name;
	private final Calendar calendar;
	private final String monthlyData[];
	private final Quarter quarter;
	
	public Month(Quarter quarter, int month) {
		this.quarter = quarter;
		
		calendar = Calendar.getInstance();
		calendar.set(Calendar.MONTH, month);
		
		name = sdf.format(calendar.getTime());
		
		monthlyData = new String[getNumberOfDays()];
		for(int i=0; i<monthlyData.length; i++) {
			int data = random.nextInt(10) == 5 ? 0 - random.nextInt(65536) : random.nextInt(65536);
			monthlyData[i] = Integer.toString(data);
		}
	}
	
	public int getNumberOfDays() {
		return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	}
	
	public String getName() {
		return name;
	}
	
	public String[] getDays() {
		return monthlyData;
	}
	
	public Quarter getQuarter() {
		return this.quarter;
	}
	
	public boolean isFirstMonthOfTheQuarter() {
		return (calendar.get(Calendar.MONTH) % 3) == 0;
	}
	
	public boolean isFirstMonthOfTheYear() {
		return calendar.get(Calendar.MONTH) == Calendar.JANUARY;
	}
}