Export Tree to PDF or Excel

From Documentation
Revision as of 04:21, 31 December 2013 by Neillee2 (talk | contribs) (Created page with "{{Template:Smalltalk_Author| |author=Neil Lee, Engineer, Potix Corporation |date=January XX, 2014 |version=ZK 6.0 and later }} __TOC__ == Introduction == In an earlier [http:/...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
DocumentationSmall Talks2014JanuaryExport Tree to PDF or Excel
Export Tree to PDF or Excel

Author
Neil Lee, Engineer, Potix Corporation
Date
January XX, 2014
Version
ZK 6.0 and later

Introduction

In an earlier article, the PdfExporter and ExcelExporter utilities were introduced to convert ZK Grid or Listbox to PDF/Excel document.

This small talk is going to extend that library to handle conversion from ZK Tree to PDF/Excel document as well.

Demo

Let's first take a look at the source Tree and the resulting output before diving into the codes.

We are exporting the Tree below to PDF and Excel
Tree to be exported.png

Resulting PDF
Export Tree to PDF Format.png

Resulting Excel
Export Tree to Excel Format.png

Usage

Export Tree with PdfExporter and ExcelExporter

The two utilities, PdfExporter and ExcelExporter, have been extended from the previous article to also handle ZK Tree. As you can see in the following sample code, exporting Tree to PDF or Excel with these utilities is the same for ZK Grid/Listbox. The resulting outputs are demonstrated as the screenshots in the previous section.

PDF

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

Excel

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

Export data by Renderer

Although exporting Tree to PDF or Excel format with PdfExporter and ExcelExporter is quite straightforward, it does have several limitation. For instance, when ROD (Render on Demand) is enabled, they can only export the part of the tree that is expanded. If you need to export the tree in its entirety when ROD is enabled, or if you wish to customize the rendered result, you can use a custom renderer to render the data model to PDF/Excel directly. In the following subsections I will demonstrate the use of a renderer to export the tree.

PDF

PdfExporter is based on iText library to create PDF documents. Please see the previous article for more detail.

  • Render header/footer using Interceptor interface
	@Command
    public void exportTreeToPdfByDataModel() throws Exception {
    	final PdfExporter exporter = new PdfExporter();
		...		
		final String[] headers = new String[]{"Path", "Description", "Size" };
		final String[] footers = new String[]{"footer1", "footer2", "footer3" };

		exporter.setInterceptor(new Interceptor <PdfPTable> () {

			// Render header
			@Override
			public void beforeRendering(PdfPTable table) {
				for (int i = 0; i < headers.length; i++) {
					String header = headers[i];
					Font font = exporter.getFontFactory().getFont(FontFactory.FONT_TYPE_HEADER);
					
					PdfPCell cell = exporter.getPdfPCellFactory().getHeaderCell();
					cell.setPhrase(new Phrase(header, font));
					if ("Size".equals(header)) {
						cell.setHorizontalAlignment(Element.ALIGN_CENTER);
					}
					table.addCell(cell);
				}
				table.completeRow();
			}
			
			// Render footer
			@Override
			public void afterRendering(PdfPTable table) {
				for (String footer : footers) {
					Font font = exporter.getFontFactory().getFont(FontFactory.FONT_TYPE_FOOTER);
					
					PdfPCell cell = exporter.getPdfPCellFactory().getFooterCell();
					cell.setPhrase(new Phrase(footer, font));
					table.addCell(cell);
				}
				table.completeRow();
			}
		});
		...
	}
  • Obtain tree data to export

It is important to retain the list of tree nodes, not just data themselves so we can infer the depth information of the data in order to perform indentation later.

    private List<TreeNode<PackageData>> getTreeData(TreeNode<PackageData> root) {
    	List<TreeNode<PackageData>> data = new ArrayList<TreeNode<PackageData>>();
    	
    	List<TreeNode<PackageData>> children = root.getChildren();
    	for (TreeNode<PackageData> child : children) {
   			data.add(child);
    		if (!child.isLeaf())
    			data.addAll(getTreeData(child));
    	}
    	
    	return data;
    }
  • Indentation

The following two supporting methods are utilized to indent 2 spaces per tree level.

	...
    private int getLevel(TreeNode<?> node) {
    	TreeNode<?> parent = node.getParent();
    	if (parent == null)
    		return -1;
    	else
    		return getLevel(parent) + 1;
    }
    ...
    private String indent(int level) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < level; i++)
			sb.append("  ");
		return sb.toString();
	}
  • Render contents using RowRenderer
	@Command
    public void exportTreeToPdfByDataModel() throws Exception {
		...		
		exporter.export(headers.length, getTreeData(_model.getRoot()), new RowRenderer<PdfPTable, TreeNode<PackageData>>() {
			
			private String indent(int level) {
				StringBuffer sb = new StringBuffer();
				for (int i = 0; i < level; i++)
					sb.append("  ");
				return sb.toString();
			}

			@Override
			public void render(PdfPTable table, TreeNode<PackageData> node, boolean isOddRow) {
				Font font = fontFactory.getFont(FontFactory.FONT_TYPE_CELL);
				
				PackageData pkg = node.getData();
				
				PdfPCell cell = cellFactory.getCell(isOddRow);
				cell.setPhrase(new Phrase(indent(getLevel(node)) + pkg.getPath(), font));
				table.addCell(cell);
				
				cell = cellFactory.getCell(isOddRow);
				cell.setPhrase(new Phrase(pkg.getDescription(), font));
				table.addCell(cell);
				
				cell = cellFactory.getCell(isOddRow);
				cell.setPhrase(new Phrase(pkg.getSize(), font));
				cell.setHorizontalAlignment(Element.ALIGN_CENTER);
				table.addCell(cell);
				
				table.completeRow();
			}

		}, out);
		...
    }

Excel

ExcelExporter is based on Apache POI to create excel documents. Please refer to the quick guide to get started with POI.

  • Render header/footer using Interceptor interface
    @Command
    public void exportTreeToExcelByDataModel() throws Exception {
		final ExcelExporter exporter = new ExcelExporter();

		final String[] headers = new String[]{"Path", "Description", "Size"};
		final String[] footers = new String[]{"footer 1", "footer 2", "footer 3"};
		...
		exporter.setInterceptor(new Interceptor<XSSFWorkbook>() {
			
			// Render header
			@Override
			public void beforeRendering(XSSFWorkbook target) {
				ExportContext ctx = exporter.getExportContext();
				
				for (String header : headers) {
					Cell cell = exporter.getOrCreateCell(ctx.moveToNextCell(), ctx.getSheet());
					cell.setCellValue(header);
					
					if ("Size".equals(header)) {
						CellStyle srcStyle = cell.getCellStyle();
						if (srcStyle.getAlignment() != CellStyle.ALIGN_CENTER) {
							XSSFCellStyle newCellStyle = ctx.getSheet().getWorkbook().createCellStyle();
							newCellStyle.cloneStyleFrom(srcStyle);
							newCellStyle.setAlignment(CellStyle.ALIGN_CENTER);
							cell.setCellStyle(newCellStyle);
						}
					}
				}
			}
			
			// Render footer
			@Override
			public void afterRendering(XSSFWorkbook target) {
				ExportContext ctx = exporter.getExportContext();

				ctx.moveToNextRow();
				for (String footer : footers) {
					Cell cell = exporter.getOrCreateCell(ctx.moveToNextCell(), ctx.getSheet());
					cell.setCellValue(footer);
				}
			}
		});
		...
	}
  • Obtain tree data to export

The source code is the same as that for PDF format.

  • Indentation

The source code is the same as that for PDF format.

  • Render contents using RowRenderer
    @Command
    public void exportTreeToExcelByDataModel() throws Exception {
    	final ExcelExporter exporter = new ExcelExporter();
    	...
		exporter.export(headers.length, getTreeData(_model.getRoot()), new RowRenderer<Row, TreeNode<PackageData>>() {

			private String indent(int level) {
				StringBuffer sb = new StringBuffer();
				for (int i = 0; i < level; i++)
					sb.append("  ");
				return sb.toString();
			}
			
			@Override
			public void render(Row row, TreeNode<PackageData> node, boolean oddRow) {
				ExportContext ctx = exporter.getExportContext();
				XSSFSheet sheet = ctx.getSheet();
				
				PackageData pkg = node.getData();
				
				exporter
				.getOrCreateCell(ctx.moveToNextCell(), sheet)
				.setCellValue(indent(getLevel(node)) + pkg.getPath());
				
				exporter
				.getOrCreateCell(ctx.moveToNextCell(), sheet)
				.setCellValue(pkg.getDescription());
				
				Cell cell = exporter.getOrCreateCell(ctx.moveToNextCell(), sheet);
				cell.setCellValue(pkg.getSize());
				CellStyle cellStyle = sheet.getWorkbook().createCellStyle();
				cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
				cell.setCellStyle(cellStyle);
			}

		}, out);
		...
	}

For complete source code, please refer to here

Summary

In this smalltalk, I have showed it is also easy for developers to export a ZK Tree to PDF or Excel documents either from the component itself or from the underlying data model directly. Explore the project and enjoy it.


Comments



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