Hello,
After my previous article Example of mail generation (MSGParser, Apache POI-HSMF) concerning the generation of a mail file on server side, I would expose you an example of XLS (Excel) generation by using the Apache POI.
Introduction
The Apache POI Project’s mission is to create and maintain Java APIs for manipulating various file formats based upon the Office Open XML standards (OOXML) and Microsoft’s OLE 2 Compound Document format (OLE2). In short, you can read and write MS Excel files using Java. The Apache POI project is celebrating its 10th anniversary.
The notice in Apache POI jar precises:
02 | Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. |
04 | This product contains parts that were originally based on software from BEA. |
05 | Copyright (c) 2000-2003, BEA Systems, < http: //www.bea.com/>. |
07 | This product contains W3C XML Schema documents. Copyright 2001-2003 (c) |
08 | World Wide Web Consortium (Massachusetts Institute of technology, European |
09 | Research Consortium for Informatics and Mathematics, Keio University) |
11 | This product contains the Piccolo XML Parser for Java |
14 | This product contains the chunks_parse_cmds.tbl file from the vsdump program. |
15 | Copyright (C) 2006-2007 Valek Filippov (frob@dl.ru) |
…so, in our example we will export data Dvd entities in 2 formats : CSV and Excel (XLS). For the first format, we use directly
the java standard class (FileWriter), but for the second format, we use the Apache library POI.
Steps by steps
Create a new project named test_poi with the following libraries in test_poi\lib folder and added in the project’s build path:
- poi-3.10-FINAL.jar the POI library,
- log4j-1.2.15.jar for the logging needs,
…the Eclipse project will have the following structure:

…and the test_poi\src source folder with the log4j.properties:
02 | log4j.rootCategory=INFO , console |
04 | ! WRITE TO CONSOLE (stdout or stderr) |
05 | log4j.appender.console.Threshold=INFO |
06 | log4j.appender.console=org.apache.log4j.ConsoleAppender |
07 | log4j.appender.console.ImmediateFlush=true |
08 | log4j.appender.console.layout=org.apache.log4j.PatternLayout |
09 | log4j.appender.console.layout.ConversionPattern=[%d{HH:mm:ss}]%-5p - %m (%F:%L) %n |
11 | !----------------------------------------------------------------------------- |
12 | ! PATTERN FORMATS GLOSSARY |
13 | !----------------------------------------------------------------------------- |
15 | ! %m - your log message |
16 | ! %p - message priority (FATAL, ERROR, WARN, INFO, DEBUG of custom) |
17 | ! %r - millisecs since program started running |
18 | ! %% - percent sign in output |
20 | ! ------------------------- SOME MORE CLUTTER IN YOUR LOG -------------------- |
21 | ! %c - name of your category (logger), %c{2} will outputs last two components |
22 | ! %t - name of current thread |
23 | ! %x - Nested Diagnostic Context (NDC) (you supply it!) |
25 | ! ------------------------- SLOW PERFORMANCE FORMATS ------------------------- |
26 | ! %d - date and time, also %d{ISO8601}, %d{DATE}, %d{ABSOLUTE}, |
27 | ! %d{HH:mm:ss, SSS}, %d{dd MMM yyyy HH:mm:ss,SSS} and so on |
28 | ! %l - Shortcut for %F%L%C%M |
29 | ! %F - Java source file name |
30 | ! %L - Java source line number |
31 | ! %C - Java class name, %C{1} will output the last one component |
32 | ! %M - Java method name |
34 | ! ------------------------- FORMAT MODIFIERS --------------------------------- |
35 | ! %-any_letter_above - Left-justify in min. width (default is right-justify) |
36 | ! %20any_letter_above - 20 char. min. width (pad with spaces if regd.) |
37 | ! %.30any_letter_above - 30 char. max. width (truncate beginning if regd.) |
38 | ! %-10.10r - Example. Left-justify time elapsed within 10-wide filed. |
39 | ! Truncate from beginning if wider than 10 characters. |
40 | ! ---------------------------------------------------------------------------- |
POJO
Create a POJO class named DvdEntity in the new package com.ho.apache.poi.test. This class will contain the objects to export.
02 | * Entity containing the Dvd object. |
06 | public class DvdEntity { |
09 | public static enum DvdCategory{ |
28 | private Integer numberOfViewing; |
31 | private Calendar lastViewingDateTime; |
34 | private String[] actors; |
37 | private DvdCategory dvdCategory; |
40 | private String comments; |
48 | public String toString(){ |
49 | return this .getClass().getName() |
54 | + ", numberOfViewing=" +numberOfViewing |
55 | + ", lastViewingDateTime=" +lastViewingDateTime |
56 | + ", dvdCategory=" +dvdCategory |
57 | + ", comments=" +comments |
62 | public Color getColor(){ |
65 | if (dvdCategory == DvdEntity.DvdCategory.ANIMATION){ |
66 | color = Color.BRIGHT_GREEN; |
67 | } else if (dvdCategory == DvdEntity.DvdCategory.POLAR){ |
69 | } else if (dvdCategory == DvdEntity.DvdCategory.SCIENCE_FICTION){ |
71 | } else if (dvdCategory == DvdEntity.DvdCategory.THRILLER){ |
72 | color = Color.DARK_YELLOW; |
80 | public Integer getId() { |
84 | public void setId(Integer id) { |
CSV File Exporter
– Create a new package com.ho.standard.exporter.csv,
– Create a new class named NullSafeCSVFileWriter extending java.io.FileWriter which is a NUllSave implementation of FileWriter in order to calling write with a null argument won’t throw any exception, but nothing will be written.
This class also provides utility methods to write Calendar, formated as timestamp, time, date, according to the DateFormats provided when creating the instance. Same goes for Double / Integer values.
01 | public class NullSafeCSVFileWriter extends FileWriter{ |
04 | private NumberFormat decimalFormat; |
05 | private String separator; |
08 | public NullSafeCSVFileWriter (File file, NumberFormat decimalFormat, String separator) throws IOException{ |
10 | this .separator = separator; |
11 | this .decimalFormat = decimalFormat; |
15 | public void write(Calendar cal, DateFormat format) throws IOException{ |
17 | super .write(format.format(cal.getTime())); |
21 | public void writeField(Calendar cal, DateFormat format) throws IOException{ |
23 | this .write(cal, format); |
25 | this .write(separator); |
– Create a new class named DvdCSVExporter in the package com.ho.apache.poi.test which provides utility methods specific to our example (write headers, write Dvd entity,..) by using the previous class NullSafeCSVFileWriter. So, this class handles the generation of the CSV file via private methods to write headers and dvd entity.
01 | public class DvdCSVExporter { |
04 | private static final Logger LOG = Logger.getLogger(DvdCSVExporter. class ); |
05 | private final TimeZone timeZone = TimeZone.getTimeZone( "GMT" ); |
06 | public static final String NEW_LINE = "\n" ; |
07 | public static final String SEPARATOR = ";" ; |
08 | private static final String[] COLUMN_LIST = { "Id" , "Name" , "Price" , "Number of Viewing" , "Last Viewing Datetime" , "Actors/Actress" , "Category" , "Comment" }; |
12 | * Exports the list of entities into the specified file. |
17 | public void exportFile(List<DvdEntity> dvdList, File exportFile) throws Exception{ |
19 | LOG.info( "Exporting CSV File: " + dvdList.size() + " entries to export to the file " + exportFile.getPath()); |
22 | final NumberFormat decimalFormat = DecimalFormat.getInstance(Locale.ENGLISH); |
23 | decimalFormat.setMaximumFractionDigits( 8 ); |
24 | decimalFormat.setGroupingUsed( false ); |
26 | final SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd" ); |
28 | final SimpleDateFormat timestampFormat = new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss" ); |
29 | timestampFormat.setTimeZone(timeZone); |
31 | final SimpleDateFormat timeFormat = new SimpleDateFormat( "hh:mm:ss" ); |
32 | timeFormat.setTimeZone(timeZone); |
34 | NullSafeCSVFileWriter fw = null ; |
36 | fw = new NullSafeCSVFileWriter(exportFile, decimalFormat, SEPARATOR); |
39 | writeHeader(fw, timestampFormat, Calendar.getInstance()); |
42 | for (DvdEntity dvd : dvdList) { |
43 | writeDvd(dvd, fw, decimalFormat, dateFormat, timestampFormat, timeFormat); |
47 | fw.write( "File generated with standard classes" ); |
51 | LOG.info( "Exporting CSV File: Done" ); |
62 | * Write the headers in the CSV file. |
64 | * @param timestampFormat |
68 | private void writeHeader( final NullSafeCSVFileWriter fw, final DateFormat timestampFormat, final Calendar creationDate) throws IOException{ |
69 | fw.write( "File created at " +timestampFormat.format(creationDate.getTime())); |
73 | for ( int i = 0 ; i < COLUMN_LIST.length - 1 ; i++) { |
74 | fw.write(COLUMN_LIST[i]); |
79 | fw.write(COLUMN_LIST[COLUMN_LIST.length- 1 ]); |
XLS File Exporter
– Create a new package com.ho.apache.poi.exporter.xls,
– Create new interface IXLSFileBuilder provides utility methods to write headers, Calendar, formatted as timestamp, time, date to an excel file.
01 | public interface IXLSFileBuilder { |
04 | * Define the headers of the file. This does not prevent you from calling addHeader() in addition |
05 | * (before, after or both). |
07 | * @param headers : Header labels |
09 | public void setHeaders(String... headers); |
12 | * Add a single header, after the last one defined |
13 | * @param header : Header label |
15 | public void addHeader(String header); |
18 | * Set value at the given column, for the current row of data. |
19 | * @param col : Index of the column (0-based) |
20 | * @param value : Value to store. |
22 | public void setDatavalue( int col, Calendar value); |
23 | public void setDatavalue( int col, String value); |
24 | public void setDatavalue( int col, Double value); |
25 | public void setDatavalue( int col, Integer value); |
26 | public void setDatavalue( int col, boolean value); |
29 | * Change the current row of data. |
31 | public void nextRow(); |
– Create a new class XLSFileBuilder implementing previous interface IXLSFileBuilder.
This class is the heart class of using Apache POI in order to create new sheet, add headers, add new row, set values in cell, set style to cell…etc.
001 | public class XLSFileBuilder implements IXLSFileBuilder { |
004 | protected final Workbook workbook = new HSSFWorkbook(); |
005 | protected Sheet sheet; |
006 | protected final CellStyle normalStyle; |
007 | protected final CellStyle dateStyle; |
008 | protected final CellStyle timestampStyle; |
009 | protected final CellStyle integerStyle; |
010 | protected final CellStyle doubleStyle; |
011 | protected final CellStyle boolStyle; |
012 | protected final CellStyle headerStyle; |
013 | protected int rowNum = 1 ; |
014 | protected int headerCol = 0 ; |
017 | private Map<Class<?>, HashMap<Color, CellStyle>> cellStyleMap; |
018 | private HSSFPatriarch drawingPatriach; |
019 | private CreationHelper createHelper; |
023 | BLACK(HSSFColor.BLACK.index), |
024 | RED(HSSFColor.RED.index), |
025 | ORANGE(HSSFColor.ORANGE.index), |
026 | LIGHT_ORANGE(HSSFColor.LIGHT_ORANGE.index), |
027 | BLUE(HSSFColor.BLUE.index), |
028 | YELLOW(HSSFColor.YELLOW.index), |
029 | TURQUOISE(HSSFColor.TURQUOISE.index), |
030 | DARK_YELLOW(HSSFColor.DARK_YELLOW.index), |
031 | BRIGHT_GREEN(HSSFColor.BRIGHT_GREEN.index), |
035 | private Color( short index){ |
038 | public short getIndex(){ |
044 | public XLSFileBuilder(){ |
046 | normalStyle = workbook.createCellStyle(); |
048 | timestampStyle = workbook.createCellStyle(); |
049 | timestampStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat( "m/d/yy h:mm" )); |
051 | dateStyle = workbook.createCellStyle(); |
052 | dateStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat( "m/d/yy" )); |
054 | integerStyle = workbook.createCellStyle(); |
055 | integerStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat( "0" )); |
057 | doubleStyle = workbook.createCellStyle(); |
058 | doubleStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat( "#,##0.00" )); |
060 | boolStyle = workbook.createCellStyle(); |
063 | headerStyle = workbook.createCellStyle(); |
064 | headerStyle.setAlignment(CellStyle.ALIGN_CENTER); |
065 | headerStyle.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index); |
066 | headerStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); |
067 | headerStyle.setBorderTop(CellStyle.BORDER_MEDIUM); |
068 | headerStyle.setBorderBottom(CellStyle.BORDER_MEDIUM); |
069 | headerStyle.setBorderLeft(CellStyle.BORDER_MEDIUM); |
070 | headerStyle.setBorderRight(CellStyle.BORDER_MEDIUM); |
073 | final Font font = workbook.createFont(); |
074 | font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); |
075 | headerStyle.setFont(font); |
078 | final Font errorFont = workbook.createFont(); |
079 | errorFont.setColor(HSSFColor.WHITE.index); |
080 | errorFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); |
081 | errorFont.setFontHeightInPoints(( short ) 10 ); |
084 | cellStyleMap = new HashMap<Class<?>, HashMap<Color, CellStyle>>(); |
085 | cellStyleMap.put(String. class , new HashMap<Color, CellStyle>()); |
086 | cellStyleMap.put(Calendar. class , new HashMap<Color, CellStyle>()); |
087 | cellStyleMap.put(Integer. class , new HashMap<Color, CellStyle>()); |
088 | cellStyleMap.put(Double. class , new HashMap<Color, CellStyle>()); |
089 | cellStyleMap.put(Boolean. class , new HashMap<Color, CellStyle>()); |
090 | cellStyleMap.put(Timestamp. class , new HashMap<Color, CellStyle>()); |
094 | cellStyleMap.get(String. class ).put( null , this .normalStyle); |
095 | cellStyleMap.get(Calendar. class ).put( null , this .normalStyle); |
096 | cellStyleMap.get(Integer. class ).put( null , this .normalStyle); |
097 | cellStyleMap.get(Double. class ).put( null , this .normalStyle); |
098 | cellStyleMap.get(Boolean. class ).put( null , this .normalStyle); |
102 | final CellStyle timestampStyle = workbook.createCellStyle(); |
103 | timestampStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat( "m/d/yy h:mm" )); |
104 | cellStyleMap.get(Timestamp. class ).put( null , timestampStyle); |
109 | for (Color color : Color.values()){ |
110 | CellStyle normalColorStyle = copyAndColor(normalStyle, errorFont, color); |
111 | cellStyleMap.get(String. class ).put(color, normalColorStyle); |
113 | CellStyle dateColorStyle = copyAndColor(dateStyle, errorFont, color); |
114 | cellStyleMap.get(Calendar. class ).put(color, dateColorStyle); |
116 | CellStyle integerColorStyle = copyAndColor(integerStyle, errorFont, color); |
117 | cellStyleMap.get(Integer. class ).put(color, integerColorStyle); |
119 | CellStyle doubleColorStyle = copyAndColor(doubleStyle, errorFont, color); |
120 | cellStyleMap.get(Double. class ).put(color, doubleColorStyle); |
122 | CellStyle boolColorStyle = copyAndColor(boolStyle, errorFont, color); |
123 | cellStyleMap.get(Boolean. class ).put(color, boolColorStyle); |
125 | CellStyle timestampColorStyle = copyAndColor(timestampStyle, errorFont, color); |
126 | cellStyleMap.get(Timestamp. class ).put(color, timestampColorStyle); |
129 | createHelper = workbook.getCreationHelper(); |
131 | drawingPatriach = (HSSFPatriarch) sheet.createDrawingPatriarch(); |
136 | * Constructs a new excel file builder, adding automatically a new sheet. |
137 | * The given sheet name is cleaned (removing forbidden characters: /,\,*,?,[,],:,!) |
138 | * and truncated if necessary (max length = 31 characters). |
142 | public XLSFileBuilder(String sheetName){ |
146 | drawingPatriach = (HSSFPatriarch) sheet.createDrawingPatriarch(); |
– Create a new class named DvdXLSExporter in the package com.ho.apache.poi.test which provides utility methods specific to our example (write headers, write Dvd entity,..) by using the previous class XLSFileBuilder. So, this class handles the generation of the XLS file via private methods to write headers and dvd entity.
01 | public class DvdXLSExporter { |
04 | private static final Logger LOG = Logger.getLogger(DvdXLSExporter. class ); |
05 | private static final String[] COLUMN_LIST = { "Id" , "Name" , "Price" , "Number of Viewing" , "Last Viewing Datetime" , "Actors/Actress" , "Category" , "Comment" }; |
09 | * Exports the list of entities into the specified file. |
14 | public void exportFile(List<DvdEntity> dvdList, File exportFile) throws Exception{ |
16 | LOG.info( "Exporting XLS File: " + dvdList.size() + " entries to export to the file " + exportFile.getPath()); |
18 | final XLSFileBuilder excelFileBuilder = new XLSFileBuilder( "My Dvds" ); |
19 | excelFileBuilder.setHeaders(COLUMN_LIST); |
21 | for (DvdEntity dvd : dvdList){ |
22 | writeDvd(dvd, excelFileBuilder); |
23 | excelFileBuilder.nextRow(); |
27 | excelFileBuilder.autoSizeColumns(); |
29 | excelFileBuilder.save(exportFile); |
30 | LOG.info( "Exporting XLS File: Done" ); |
33 | private void writeDvd( final DvdEntity dvd, final XLSFileBuilder excelFileBuilder) throws IOException{ |
36 | excelFileBuilder.setDataValue(col++, dvd.getId(), dvd.getColor(), null ); |
38 | excelFileBuilder.setDataValue(col++, dvd.getName(), dvd.getColor(), dvd.getComments()); |
40 | excelFileBuilder.setDataValue(col++, dvd.getPrice(), dvd.getColor(), null ); |
42 | excelFileBuilder.setDataValue(col++, dvd.getNumberOfViewing(), dvd.getColor(), null ); |
44 | excelFileBuilder.setDataValue(col++, dvd.getLastViewingDateTime(), true , dvd.getColor(), null ); |
46 | excelFileBuilder.setDataValue(col++, dvd.getActors(), dvd.getColor(), null ); |
48 | excelFileBuilder.setDataValue(col++, dvd.getDvdCategory().toString(), dvd.getColor(), null ); |
50 | excelFileBuilder.setDataValue(col++, dvd.getComments(), dvd.getColor(), null ); |
Main method
Finally, create a new class named TestExporter in the package com.ho.apache.poi.test containing the main method to launch the DvdCSVExporter and DvdXLSExporter in order to create the files CSV and XLS of DVD entities.
01 | public class TestExporter { |
04 | private static final Logger LOG = Logger.getLogger(TestExporter. class ); |
07 | private TestExporter(){ } |
11 | public static void main(String[] args) { |
15 | String defaultFilename = "data/test_poi_" + new SimpleDateFormat( "yyyyMMdd_HHmmss" ).format(Calendar.getInstance().getTime()); |
16 | File xlsExport = new File(defaultFilename + ".xls" ); |
17 | File csvExport = new File(defaultFilename + ".csv" ); |
18 | List<DvdEntity> entities = new ArrayList<DvdEntity>(); |
21 | for ( int i = 0 ; i < DvdCategory.values().length; i++) { |
22 | for ( int j = 0 ; j < 5 ; j++, idCounter++) { |
23 | DvdEntity dvd = new DvdEntity(); |
25 | dvd.setName( "Dvd " +idCounter); |
26 | dvd.setPrice((Math.random()% 10 )); |
27 | dvd.setNumberOfViewing(( int )(Math.random()% 10 )); |
28 | dvd.setLastViewingDateTime(GregorianCalendar.getInstance()); |
29 | dvd.setActors( new String[]{ "Actor " +idCounter+j, "Actress " +idCounter+j}); |
30 | dvd.setDvdCategory(DvdCategory.values()[i]); |
31 | dvd.setComments( "a comment for the dvd " +idCounter); |
39 | final DvdXLSExporter dvdXLSExporter = new DvdXLSExporter(); |
40 | dvdXLSExporter.exportFile(entities, xlsExport); |
43 | final DvdCSVExporter dvdCSVExporter = new DvdCSVExporter(); |
44 | dvdCSVExporter.exportFile(entities, csvExport); |
51 | LOG.error( "Exception caught:" , ex); |
53 | System.exit(exitStatus); |
The outputs are:
1 | [00:52:19]INFO - Exporting XLS File: 20 entries to export to the file data\test_poi_20140521_005219.xls (DvdXLSExporter.java:32) |
2 | [00:52:21]INFO - Exporting XLS File: Done (DvdXLSExporter.java:46) |
3 | [00:52:21]INFO - Exporting CSV File: 20 entries to export to the file data\test_poi_20140521_005219.csv (DvdCSVExporter.java:41) |
4 | [00:52:21]INFO - Exporting CSV File: Done (DvdCSVExporter.java:73) |



That’s all!!!
Download: test_poi.zip
Best regards,
Huseyin OZVEREN
Related