On Ben Forta's blog, many have been asking for "Blackstone" (next version of CFMX) to be able to export data to .xls format. Over the past few years, there have been a variety of ways to do this, however none of them have been able to unlock most of the features of the Excel workbook file format. One easy way is to export the data to a comma-separated or tab-delimited format, which would typically open in Excel on the end user's workstation. Another way is to generate an html table and save it with a .xls extension, which excel will also open. Neither method gives you full control over excel's features, but there are other ways. One option is to install excel on the server and automate the spreadsheet generation using COM. Should you not be able (or want) to do this, another option (which is becoming the common theme on this blog) is to use Java, more specifically the Apache Jakarta Project's POI, a "Java API To Access Microsoft Format Files".

The POI API is quite large, and includes many sub-projects. The section we are interested in is called HSSF, a "Java API To Access Microsoft Excel Format Files". HSSF provides a way to create, modify, read and write XLS spreadsheets. Using HSSF from CFMX is more or less a snap. The first step is to download the POI library and place it somewhere in CFMX's classpath. I typically use <cfusionmx-dir>/wwwroot/WEB-INF/lib.

The code to write an excel spreadsheet is pretty straight forward.

First, we create an instance of HSSFWorkbook.

<cfset workBook = createObject("java","org.apache.poi.hssf.usermodel.HSSFWorkbook").init()/>

Should you be browsing the POI documentation, the package we will be using most often to generate excel spreadsheets is org.apache.poi.hssf.usermodel. At this point, we are free to use the HSSF libary to write whatever we want into our new excel workbook. On Ben's blog,  Hien asked "In generating content to an Excel spreadsheet, will it be possible to have the output stored in different worksheets (tabs) within the same workbook?". In POI-HSSF's case, you can't even do anything until you add a worksheet to the workbook, and you can add as many as you want, so the answer is YES.

<cfset newSheet = workBook.createSheet()/>

If you want to name your new sheet, you can reference it by the order it was added to the workbook (starting with 0):

<cfset workBook.setSheetName(0, "My First Sheet")/>

Creating rows in a sheet is really easy too, the number you pass into createRow is the zero-based index of the row you want to create. HSSF needs a row created in order to add data to the spreadsheet. For instance, if you wanted to add information to the third row in the sheet, you would do this:

<cfset row = newSheet.createRow(3)/>

Cells work in the same fashion: in order to add information to a cell, you must first use the HSSFRow's createCell function.

<cfset cell = row.createCell(0)/>

You can place a variety of information in the cell, from strings:

<cfset cell.setCellValue("hello world!")/>

numbers:

<cfset cell.setCellValue(1.25145285)/>

even formulas:

<cfset cell.setCellFormula("A1 * A2")/>
(keep in mind that formulas should be exactly as they were if you were putting them in the cell sheet, e.g. you must reference other cells using the A1, B4 etc. format. Also, make sure you omit the "=" in the formula)

Setting the style of cells is a bit harder, you first need to create a style (which can later be applied to any number of cells):

<cfset uglyStyle = workBook.createCellStyle()/>

Then you can set properties of the cellStyle:

<cfset uglyStyle.setBorderBottom(uglyStyle.BORDER_MEDIUM)/>

Setting colors is even more difficult, I guess because excel has some complex underlying color implementation. To set the background color of a cell, you have to do this: (notice that you use the dollar sign to access an inner class of a java object, like HSSFColor)

<cfset green = createObject("java","org.apache.poi.hssf.util.HSSFColor$LIGHT_GREEN").init()/>
<cfset uglyStyle.setFillBackgroundColor(green.getIndex())/>


Now, we can set the style of a cell like this:

<cfset cell.setCellStyle(uglyStyle)/>

Finally, to write our workbook out to a file, we need an output stream for the written file:

<cfset fileOutStream = createObject("java","java.io.FileOutputStream").init("C:\cfusionmx\wwwroot\#CreateUUID()#.xls")/>

Then we write our workbook to this stream:

<cfset workBook.write(fileOutStream)/>

And close the stream:

<cfset fileOutStream.close()/>

As you can see, there's a lot you can do in terms of generating .xls format documents using POI-HSSF. While no excel export implementation is perfect, HSSF probably is one of the most robust and easiest to use from CFMX.


11/04/2004 02:00 P - Jonathan Nickle said...

Is the java in this case portable? 

I am a bit unclear because this says "Apache Jakarta Project's POI"...  can these classes be imported to CFMX on a machine not running Apache? 


11/04/2004 04:04 P - Dave Ross said...

Yes, absolutely. Don't confuse Apache, the http server, with the Apache software foundation. While the latter produced the former, the apache software foundation is responsible for a magnitude of open source software projects. Visit www.apache.org for more detail.

Yes, the Java is portable... you download the POI .jar file, place it in CFMX's classpath, bounce the service, and away you go. It's as simple as that.


12/29/2004 10:46 A - David Copper said...
This is fantastically useful and I have it running thanks to the info here.  Many thanks.  David

01/07/2005 04:43 A - Shibu Narayanan said...

Every thing looks to be quite impresive.

I have some poblem while readng the xl document.

I can't loop through the cells while trying to read the document.

   <CFLOOP from="0" to="5" index="i_loopCell" >
   <CFSET obj_cell = obj_row.getCell(i_loopCell)>
    <CFSET str_cellValue= obj_cell.getStringCellValue()>
<cfoutput>#str_cellValue#<./cfoutput>   </CFLOOP>

Can u please adv on this.


01/21/2005 11:21 A - Pillai said...

Try this....

<cfoutput>

   <CFLOOP from="0" to="5" index="i_loopCell" >
   <CFSET obj_cell = obj_row.getCell(i_loopCell)>
    <CFSET str_cellValue= obj_cell.getStringCellValue()>
#str_cellValue# </CFLOOP>

</cfoutput> 

regards

pillai 


01/28/2005 11:30 A - Jorge Pereira said...
Does anyone know of a way to copy  worksheets between workbooks using POI.

01/28/2005 12:45 P - Dave Ross said...

Jorge,

Take a look at this. Looks as though you are out of luck, in terms of having an easy way to do that.

-Dave


10/24/2005 02:08 A - samon said...

obj_row.getCell(javacast("int",i_loopCell)

try it


11/20/2005 09:20 P - wb009 said...
how to creat excel formate file to download,from <cfquery>

11/22/2005 08:18 P - wb009 said...

can you tell me how to set hssfcell.encoding_utf-16,

because we are chinese


05/16/2006 12:59 P - Dave said...
I am trying to get this to work in Solaris/Apache/MX7. When I run the above code, it always saves the files in

<cfusionserver>/runtime/bin/
with owner "nobody|other"

i need the files to read and write from
<cfusionserver>/wwwroot/
owner "www|www"

any suggestions?




05/23/2006 10:41 A - Joe Buszkiewic said...
Do you know of a way to output the file to the user as soon as it is created, instead of saving it on the server then sending the file to the user? Right now everything that I try results in a blank excel file. I would just rather not have a build of of files on the server and have to write something to remove all the files. Thanks for the help.

08/18/2006 06:05 P - simlough said...

Does Excel need to be installed on the computer that is running hssf?


09/05/2006 02:19 P - Dan Plesse said...
I found an error in your code:

<cfset cell.setCellStyle(uglyStyle)/>

should be

<cfset row.getCell(0).setCellStyle(uglyStyle)>

02/01/2007 11:21 A - Catalina said...

Does this work developing in RAD6 (Webpshere) in JSP?


09/28/2007 08:51 P - Harvey said...

Thanks on that,I have here some update on CMFX and Apache,hope this would serve to be helpful..=)

CFMX on IIS and Apache2 on the same machine

Well with a new machine in the works for my company i've been thinking about running Apahce (on windows) for our server. Anyway what with mappings etc i really wanted to give this a bash at home first. At first i thought this was gonna mean me, notepad and a bunch of text files had to get friendly. Actually its couldn't of been easier thanks to CF.

  • Download and install Apache. I needed to change the port to 81 so it didnt interfere with IIS which meant i changed the "Listen" port to 81 in the httpd.conf file
  • Edit C:\CFusionMX\bin\connectors\Apache_connector.bat to look at "apache2" folder instead of "Apache". Then run the bat file.
  • Restart Apache and all is well, easy.


Do remember though that they are using the same CF engine. If you have the enterprise version you could most likely set up a different instance for each web server, but i dont so i can't ;o(

Afterthought:If you want to administer CF from Apache then you will need to add the following to the Mazda tail lights-ScriptAlias section of httpd.cong


03/12/2009 05:38 A - Balu said...
How can we make a row of cells with font BOLD?

And also is there any way to to output the file to the user as soon as it is created, instead of saving it on the server and then sending the file to the user

03/12/2009 05:38 A - Balu said...
How can we make a row of cells with font BOLD?

And also is there any way to to output the file to the user as soon as it is created, instead of saving it on the server and then sending the file to the user

Post a comment:

(required, will not be displayed)
 


   You will be sent an email asking you to validate your comment.



Driven by Farcry Open Source CMS. Dressed in Aura.
Powered by ColdFusion MX.