Export Grid or Listbox to PDF or Excel"

From Documentation
m
Line 267: Line 267:
 
==Download==
 
==Download==
 
*The demo web application can be downloaded here - [https://github.com/downloads/samchuang/exporter/exporter.war Github]
 
*The demo web application can be downloaded here - [https://github.com/downloads/samchuang/exporter/exporter.war Github]
*The export.jar can be downloaded here- [https://github.com/downloads/samchuang/exporter/exporter.jar Github]
+
*The exporter.jar can be downloaded here- [https://github.com/downloads/samchuang/exporter/exporter.jar Github]
  
 
{{Template:CommentedSmalltalk_Footer|
 
{{Template:CommentedSmalltalk_Footer|
 
|name=Potix Corporation
 
|name=Potix Corporation
 
}}
 
}}

Revision as of 04:27, 29 November 2012

Export Grid or Listbox to PDF or Excel

WarningTriangle-32x32.png This page is under construction, so we cannot guarantee the accuracy of the content!

DocumentationSmall Talks2012DecemberExport Grid or Listbox to PDF or Excel
Export Grid or Listbox to PDF or Excel

Author
Sam Chuang, Engineer, Potix Corporation
Date
November 26, 2012
Version
ZK 6.0 and later

Introduction

Web application developers often require to transform data into different format. For instance, to PDF format that enhance read accessibility and to Excel format that can further analyze data. This smalltalk is going to introduce a easy way that can transform from Grid or Listbox to PDF/Excel.

Demo

Grid/Listbox
Export Grid or Listbox to PDF or Excel demo.png

PDF
Export Grid or Listbox to PDF or Excel PDF Format.png

Excel
Export Grid or Listbox to PDF or Excel Excel Format.png

Usage

Export Listbox/Grid

As you can see the following sample code, export Listbox/Grid to PDF or Excel is quite straightforward.

PDF

	@Command
	public void exportGrid(@BindingParam("ref") Grid grid) throws Exception {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		
		PdfExporter exporter = new PdfExporter();
		exporter.export(grid, out);
		
		AMedia amedia = new AMedia("FirstReport.pdf", "pdf", "application/pdf", out.toByteArray());
		Filedownload.save(amedia);		
		out.close();
	}

Excel

	@Command
	public void exportListboxToExcel(@BindingParam("ref") Listbox listbox) throws Exception {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		
		ExcelExporter exporter = new ExcelExporter();
		exporter.export(listbox, out);
		
		AMedia amedia = new AMedia("FirstReport.xlsx", "xls", "application/file", out.toByteArray());
		Filedownload.save(amedia);
		out.close();
	}

Export data by Renderer

Although export Listbox/Grid to PDF or Excel is quite straightforward. However, it does have some limitation. For instance, it cannot export full contents with Grid/Listbox with ROD enabled. In such use case, you can use renderer to render raw data to PDF/Excel directly. Another advantage of renderer is that you can highly customize the rendering result.

PDF

The PdfExporter leverage the famous iText library to create PDF documents. Hence, the renderer will use iText API directly.


The PdfExporter contains Factories that help create necessary instances that iText needed.
1. DocumentFactory to create Document
2. PdfWriterFactory to get PdfWriter instance
3. PdfPTableFactory to get PdfPTable instance
4. FontFactory to get Font
5. PdfPCellFactory to create PdfPCell

The following sample code will demonstrate the usage of FontFactory and PdfPCellFactory

  • Render header using Interceptor.beforeRendering API
		final PdfExporter exporter = new PdfExporter();
		final PdfPCellFactory cellFactory = exporter.getPdfPCellFactory();
		final FontFactory fontFactory = exporter.getFontFactory();
		
		final String[] headers = new String[]{"Name", "Top Nutrients", "% of Daily", "Calories", "Quantity"};
		exporter.setInterceptor(new Interceptor <PdfPTable> () {
			
			@Override
			public void beforeRendering(PdfPTable table) {
				for (int i = 0; i < headers.length; i++) {
					String header = headers[i];
					Font font = fontFactory.getFont(FontFactory.FONT_TYPE_HEADER);
					
					PdfPCell cell = cellFactory.getHeaderCell();
					cell.setPhrase(new Phrase(header, font));
					if ("% of Daily".equals(header) || "Calories".equals(header)) {
						cell.setHorizontalAlignment(Element.ALIGN_CENTER);
					}
					table.addCell(cell);
				}
				table.completeRow();
			}
			
			@Override
			public void afterRendering(PdfPTable table) {
			}
		});
  • Render contents using RowRenderer or GroupRenderer
		exporter.export(headers.length, _model.getData(), new GroupRenderer<PdfPTable, Food>() {

			@Override
			public void render(PdfPTable table, Food food, boolean isOddRow) {
				Font font = fontFactory.getFont(FontFactory.FONT_TYPE_CELL);

				PdfPCell cell = cellFactory.getCell(isOddRow);
				cell.setPhrase(new Phrase(food.getName(), font));
				table.addCell(cell);
				
				cell = cellFactory.getCell(isOddRow);
				cell.setPhrase(new Phrase(food.getTopNutrients(), font));
				table.addCell(cell);
				
				cell = cellFactory.getCell(isOddRow);
				cell.setPhrase(new Phrase("" + food.getDailyPercent(), font));
				cell.setHorizontalAlignment(Element.ALIGN_CENTER);
				table.addCell(cell);
				
				cell = cellFactory.getCell(isOddRow);
				cell.setPhrase(new Phrase("" + food.getCalories(), font));
				cell.setHorizontalAlignment(Element.ALIGN_CENTER);
				table.addCell(cell);
				
				cell = cellFactory.getCell(isOddRow);
				cell.setPhrase(new Phrase(food.getQuantity(), font));
				table.addCell(cell);
				
				table.completeRow();
			}

			@Override
			public void renderGroup(PdfPTable table, Collection<Food> foods) {
				Iterator<Food> iterator = foods.iterator();
				if (iterator.hasNext()) {
					Food food = iterator.next();
					Font font = fontFactory.getFont(FontFactory.FONT_TYPE_GROUP);

					PdfPCell cell = cellFactory.getGroupCell();					
					cell.setPhrase(new Phrase(food.getCategory(), font));
					cell.setColspan(headers.length);
					table.addCell(cell);
					
					table.completeRow();
				}
			}

			@Override
			public void renderGroupfoot(PdfPTable table, Collection<Food> foods) {
				Font font = fontFactory.getFont(FontFactory.FONT_TYPE_GROUPFOOT);

				PdfPCell cell = cellFactory.getGroupCell();
				cell.setPhrase(new Phrase("Total size: " + (foods != null ? foods.size() : 0), font));
				table.addCell(cell);
				
				cell = cellFactory.getCell(false);
				cell.setColspan(headers.length - 1);
				table.addCell(cell);
				table.completeRow();
			}
		}, out);

Excel

The ExcelExporter is based on Apache POI, the renderer will use Apache POI API directly to create excel document. Refer to the quick guide here to get started with POI.

  • Render header using Interceptor.beforeRendering API
		final ExcelExporter exporter = new ExcelExporter();
		final String[] headers = new String[]{"Name", "Top Nutrients", "% of Daily", "Calories", "Quantity"};
		exporter.setInterceptor(new Interceptor<XSSFWorkbook>() {
			
			@Override
			public void beforeRendering(XSSFWorkbook target) {
				ExportContext context = exporter.getExportContext();
				
				for (String header : headers) {
					Cell cell = exporter.getOrCreateCell(context.moveToNextCell(), context.getSheet());
					cell.setCellValue(header);
					
					if ("% of Daily".equals(header) || "Calories".equals(header)) {
						CellStyle srcStyle = cell.getCellStyle();
						if (srcStyle.getAlignment() != CellStyle.ALIGN_CENTER) {
							XSSFCellStyle newCellStyle = book.createCellStyle();
							newCellStyle.cloneStyleFrom(srcStyle);
							newCellStyle.setAlignment(CellStyle.ALIGN_CENTER);
							cell.setCellStyle(newCellStyle);
						}
					}
				}
			}
			
			@Override
			public void afterRendering(XSSFWorkbook target) {
			}
		});
  • Render contents using RowRenderer or GroupRenderer
		exporter.export(headers.length, _model.getData(), new org.zkoss.exporter.GroupRenderer<Row, Food>() {

			@Override
			public void render(Row row, Food food, boolean oddRow) {
				ExportContext context = exporter.getExportContext();
				XSSFSheet sheet = context.getSheet();
				
				exporter
				.getOrCreateCell(context.moveToNextCell(), sheet)
				.setCellValue(food.getName());
				
				exporter
				.getOrCreateCell(context.moveToNextCell(), sheet)
				.setCellValue(food.getTopNutrients());
				
				Cell cell = exporter.getOrCreateCell(context.moveToNextCell(), sheet);
				cell.setCellValue(food.getDailyPercent());
				CellStyle cellStyle = sheet.getWorkbook().createCellStyle();
				cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
				cell.setCellStyle(cellStyle);
				
				cell = exporter.getOrCreateCell(context.moveToNextCell(), sheet);
				cell.setCellValue(food.getCalories());
				cellStyle = sheet.getWorkbook().createCellStyle();
				cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
				cell.setCellStyle(cellStyle);
				
				exporter
				.getOrCreateCell(context.moveToNextCell(), sheet)
				.setCellValue(food.getQuantity());
			}

			@Override
			public void renderGroup(Row row, Collection<Food> foods) {
				ExportContext context = exporter.getExportContext();
				XSSFSheet sheet = context.getSheet();
				
				exporter
				.getOrCreateCell(context.moveToNextCell(), sheet)
				.setCellValue(foods.iterator().next().getCategory());
			}

			@Override
			public void renderGroupfoot(Row row, Collection<Food> foods) {
				ExportContext context = exporter.getExportContext();
				XSSFSheet sheet = context.getSheet();
				
				exporter
				.getOrCreateCell(context.moveToNextCell(), sheet)
				.setCellValue("Total " + foods.size() + " items");
			}
		}, out);

For complete source code, please refer to here

Summary

Download

  • The demo web application can be downloaded here - Github
  • The exporter.jar can be downloaded here- Github


Comments



Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.