Export Tree to PDF or Excel
Neil Lee, Engineer, Potix Corporation
January XX, 2014
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
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.
@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.
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. |