| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- |
| ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== |
| --> |
| <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "../dtd/document-v11.dtd"> |
| |
| <document> |
| <header> |
| <title>The New Halloween Document</title> |
| <authors> |
| <person email="acoliver2@users.sourceforge.net" name="Andrew C. Oliver" id="AO"/> |
| <person email="user@poi.apache.org" name="Glen Stampoultzis" id="GJS"/> |
| <person email="nick@apache.org" name="Nick Burch" id="NB"/> |
| <person email="sergeikozello@mail.ru" name="Sergei Kozello" id="SK"/> |
| </authors> |
| </header> |
| <body> |
| <section><title>How to use the HSSF API</title> |
| |
| <section><title>Capabilities</title> |
| <p>This release of the how-to outlines functionality for the CVS HEAD. |
| Those looking for information on previous releases should |
| look in the documentation distributed with that release.</p> |
| <p> |
| HSSF allows numeric, string, date or formuala cell values to be written to |
| or read from an XLS file. Also |
| in this release is row and column sizing, cell styling (bold, |
| italics, borders,etc), and support for both built-in and user |
| defined data formats. Also available is |
| an event-based API for reading XLS files. |
| It differs greatly from the read/write API |
| and is intended for intermediate developers who need a smaller |
| memory footprint. |
| </p> |
| </section> |
| <section><title>Different APIs</title> |
| <p>There are a few different ways to access the HSSF API. These |
| have different characteristics, so you should read up on |
| all to select the best for you.</p> |
| <ul> |
| <li><link href="#user_api">User API</link></li> |
| <li><link href="#event_api">Event API</link></li> |
| <li><link href="#record_aware_event_api">Event API with extensions to be Record Aware</link></li> |
| <li><link href="#low_level_api">Low Level API</link></li> |
| </ul> |
| </section> |
| </section> |
| <section><title>General Use</title> |
| <anchor id="user_api" /> |
| <section><title>User API</title> |
| <section><title>Writing a new file</title> |
| |
| <p>The high level API (package: org.apache.poi.hssf.usermodel) |
| is what most people should use. Usage is very simple. |
| </p> |
| <p>Workbooks are created by creating an instance of |
| org.apache.poi.hssf.usermodel.HSSFWorkbook. |
| </p> |
| <p>Sheets are created by calling createSheet() from an existing |
| instance of HSSFWorkbook, the created sheet is automatically added in |
| sequence to the workbook. Sheets do not in themselves have a sheet |
| name (the tab at the bottom); you set |
| the name associated with a sheet by calling |
| HSSFWorkbook.setSheetName(sheetindex,"SheetName",encoding). |
| The name may be in 8bit format (HSSFWorkbook.ENCODING_COMPRESSED_UNICODE) |
| or Unicode (HSSFWorkbook.ENCODING_UTF_16). Default encoding is 8bit per char. |
| </p> |
| <p>Rows are created by calling createRow(rowNumber) from an existing |
| instance of HSSFSheet. Only rows that have cell values should be |
| added to the sheet. To set the row's height, you just call |
| setRowHeight(height) on the row object. The height must be given in |
| twips, or 1/20th of a point. If you prefer, there is also a |
| setRowHeightInPoints method. |
| </p> |
| <p>Cells are created by calling createCell(column, type) from an |
| existing HSSFRow. Only cells that have values should be added to the |
| row. Cells should have their cell type set to either |
| HSSFCell.CELL_TYPE_NUMERIC or HSSFCell.CELL_TYPE_STRING depending on |
| whether they contain a numeric or textual value. Cells must also have |
| a value set. Set the value by calling setCellValue with either a |
| String or double as a parameter. Individual cells do not have a |
| width; you must call setColumnWidth(colindex, width) (use units of |
| 1/256th of a character) on the HSSFSheet object. (You can't do it on |
| an individual basis in the GUI either).</p> |
| <p>Cells are styled with HSSFCellStyle objects which in turn contain |
| a reference to an HSSFFont object. These are created via the |
| HSSFWorkbook object by calling createCellStyle() and createFont(). |
| Once you create the object you must set its parameters (colors, |
| borders, etc). To set a font for an HSSFCellStyle call |
| setFont(fontobj). |
| </p> |
| <p>Once you have generated your workbook, you can write it out by |
| calling write(outputStream) from your instance of Workbook, passing |
| it an OutputStream (for instance, a FileOutputStream or |
| ServletOutputStream). You must close the OutputStream yourself. HSSF |
| does not close it for you. |
| </p> |
| <p>Here is some example code (excerpted and adapted from |
| org.apache.poi.hssf.dev.HSSF test class):</p> |
| <source><![CDATA[ |
| short rownum; |
| |
| // create a new file |
| FileOutputStream out = new FileOutputStream("workbook.xls"); |
| // create a new workbook |
| HSSFWorkbook wb = new HSSFWorkbook(); |
| // create a new sheet |
| HSSFSheet s = wb.createSheet(); |
| // declare a row object reference |
| HSSFRow r = null; |
| // declare a cell object reference |
| HSSFCell c = null; |
| // create 3 cell styles |
| HSSFCellStyle cs = wb.createCellStyle(); |
| HSSFCellStyle cs2 = wb.createCellStyle(); |
| HSSFCellStyle cs3 = wb.createCellStyle(); |
| HSSFDataFormat df = wb.createDataFormat(); |
| // create 2 fonts objects |
| HSSFFont f = wb.createFont(); |
| HSSFFont f2 = wb.createFont(); |
| |
| //set font 1 to 12 point type |
| f.setFontHeightInPoints((short) 12); |
| //make it blue |
| f.setColor( (short)0xc ); |
| // make it bold |
| //arial is the default font |
| f.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); |
| |
| //set font 2 to 10 point type |
| f2.setFontHeightInPoints((short) 10); |
| //make it red |
| f2.setColor( (short)HSSFFont.COLOR_RED ); |
| //make it bold |
| f2.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); |
| |
| f2.setStrikeout( true ); |
| |
| //set cell stlye |
| cs.setFont(f); |
| //set the cell format |
| cs.setDataFormat(df.getFormat("#,##0.0")); |
| |
| //set a thin border |
| cs2.setBorderBottom(cs2.BORDER_THIN); |
| //fill w fg fill color |
| cs2.setFillPattern((short) HSSFCellStyle.SOLID_FOREGROUND); |
| //set the cell format to text see HSSFDataFormat for a full list |
| cs2.setDataFormat(HSSFDataFormat.getBuiltinFormat("text")); |
| |
| // set the font |
| cs2.setFont(f2); |
| |
| // set the sheet name in Unicode |
| wb.setSheetName(0, "\u0422\u0435\u0441\u0442\u043E\u0432\u0430\u044F " + |
| "\u0421\u0442\u0440\u0430\u043D\u0438\u0447\u043A\u0430", |
| HSSFWorkbook.ENCODING_UTF_16 ); |
| // in case of compressed Unicode |
| // wb.setSheetName(0, "HSSF Test", HSSFWorkbook.ENCODING_COMPRESSED_UNICODE ); |
| // create a sheet with 30 rows (0-29) |
| for (rownum = (short) 0; rownum < 30; rownum++) |
| { |
| // create a row |
| r = s.createRow(rownum); |
| // on every other row |
| if ((rownum % 2) == 0) |
| { |
| // make the row height bigger (in twips - 1/20 of a point) |
| r.setHeight((short) 0x249); |
| } |
| |
| //r.setRowNum(( short ) rownum); |
| // create 10 cells (0-9) (the += 2 becomes apparent later |
| for (short cellnum = (short) 0; cellnum < 10; cellnum += 2) |
| { |
| // create a numeric cell |
| c = r.createCell(cellnum); |
| // do some goofy math to demonstrate decimals |
| c.setCellValue(rownum * 10000 + cellnum |
| + (((double) rownum / 1000) |
| + ((double) cellnum / 10000))); |
| |
| String cellValue; |
| |
| // create a string cell (see why += 2 in the |
| c = r.createCell((short) (cellnum + 1)); |
| |
| // on every other row |
| if ((rownum % 2) == 0) |
| { |
| // set this cell to the first cell style we defined |
| c.setCellStyle(cs); |
| // set the cell's string value to "Test" |
| c.setEncoding( HSSFCell.ENCODING_COMPRESSED_UNICODE ); |
| c.setCellValue( "Test" ); |
| } |
| else |
| { |
| c.setCellStyle(cs2); |
| // set the cell's string value to "\u0422\u0435\u0441\u0442" |
| c.setEncoding( HSSFCell.ENCODING_UTF_16 ); |
| c.setCellValue( "\u0422\u0435\u0441\u0442" ); |
| } |
| |
| |
| // make this column a bit wider |
| s.setColumnWidth((short) (cellnum + 1), (short) ((50 * 8) / ((double) 1 / 20))); |
| } |
| } |
| |
| //draw a thick black border on the row at the bottom using BLANKS |
| // advance 2 rows |
| rownum++; |
| rownum++; |
| |
| r = s.createRow(rownum); |
| |
| // define the third style to be the default |
| // except with a thick black border at the bottom |
| cs3.setBorderBottom(cs3.BORDER_THICK); |
| |
| //create 50 cells |
| for (short cellnum = (short) 0; cellnum < 50; cellnum++) |
| { |
| //create a blank type cell (no value) |
| c = r.createCell(cellnum); |
| // set it to the thick black border style |
| c.setCellStyle(cs3); |
| } |
| |
| //end draw thick black border |
| |
| |
| // demonstrate adding/naming and deleting a sheet |
| // create a sheet, set its title then delete it |
| s = wb.createSheet(); |
| wb.setSheetName(1, "DeletedSheet"); |
| wb.removeSheetAt(1); |
| //end deleted sheet |
| |
| // write the workbook to the output stream |
| // close our file (don't blow out our file handles |
| wb.write(out); |
| out.close(); |
| ]]></source> |
| </section> |
| <section><title>Reading or modifying an existing file</title> |
| |
| <p>Reading in a file is equally simple. To read in a file, create a |
| new instance of org.apache.poi.poifs.Filesystem, passing in an open InputStream, such as a FileInputStream |
| for your XLS, to the constructor. Construct a new instance of |
| org.apache.poi.hssf.usermodel.HSSFWorkbook passing the |
| Filesystem instance to the constructor. From there you have access to |
| all of the high level model objects through their assessor methods |
| (workbook.getSheet(sheetNum), sheet.getRow(rownum), etc). |
| </p> |
| <p>Modifying the file you have read in is simple. You retrieve the |
| object via an assessor method, remove it via a parent object's remove |
| method (sheet.removeRow(hssfrow)) and create objects just as you |
| would if creating a new xls. When you are done modifying cells just |
| call workbook.write(outputstream) just as you did above.</p> |
| <p>An example of this can be seen in |
| <link href="http://svn.apache.org/repos/asf/poi/trunk/src/java/org/apache/poi/hssf/dev/HSSF.java">org.apache.poi.hssf.dev.HSSF</link>.</p> |
| </section> |
| </section> |
| |
| <anchor id="event_api" /> |
| <section><title>Event API</title> |
| |
| <p>The event API is newer than the User API. It is intended for intermediate |
| developers who are willing to learn a little bit of the low level API |
| structures. Its relatively simple to use, but requires a basic |
| understanding of the parts of an Excel file (or willingness to |
| learn). The advantage provided is that you can read an XLS with a |
| relatively small memory footprint. |
| </p> |
| <p>One important thing to note with the basic Event API is that it |
| triggers events only for things actually stored within the file. |
| With the XLS file format, it is quite common for things that |
| have yet to be edited to simply not exist in the file. This means |
| there may well be apparent "gaps" in the record stream, which |
| you either need to work around, or use the |
| <link href="#record_aware_event_api">Record Aware</link> extension |
| to the Event API.</p> |
| <p>To use this API you construct an instance of |
| org.apache.poi.hssf.eventmodel.HSSFRequest. Register a class you |
| create that supports the |
| org.apache.poi.hssf.eventmodel.HSSFListener interface using the |
| HSSFRequest.addListener(yourlistener, recordsid). The recordsid |
| should be a static reference number (such as BOFRecord.sid) contained |
| in the classes in org.apache.poi.hssf.record. The trick is you |
| have to know what these records are. Alternatively you can call |
| HSSFRequest.addListenerForAllRecords(mylistener). In order to learn |
| about these records you can either read all of the javadoc in the |
| org.apache.poi.hssf.record package or you can just hack up a |
| copy of org.apache.poi.hssf.dev.EFHSSF and adapt it to your |
| needs. TODO: better documentation on records.</p> |
| <p>Once you've registered your listeners in the HSSFRequest object |
| you can construct an instance of |
| org.apache.poi.poifs.filesystem.FileSystem (see POIFS howto) and |
| pass it your XLS file inputstream. You can either pass this, along |
| with the request you constructed, to an instance of HSSFEventFactory |
| via the HSSFEventFactory.processWorkbookEvents(request, Filesystem) |
| method, or you can get an instance of DocumentInputStream from |
| Filesystem.createDocumentInputStream("Workbook") and pass |
| it to HSSFEventFactory.processEvents(request, inputStream). Once you |
| make this call, the listeners that you constructed receive calls to |
| their processRecord(Record) methods with each Record they are |
| registered to listen for until the file has been completely read. |
| </p> |
| <p>A code excerpt from org.apache.poi.hssf.dev.EFHSSF (which is |
| in CVS or the source distribution) is reprinted below with excessive |
| comments:</p> |
| <source><![CDATA[ |
| /** |
| * This example shows how to use the event API for reading a file. |
| */ |
| public class EventExample |
| implements HSSFListener |
| { |
| private SSTRecord sstrec; |
| |
| /** |
| * This method listens for incoming records and handles them as required. |
| * @param record The record that was found while reading. |
| */ |
| public void processRecord(Record record) |
| { |
| switch (record.getSid()) |
| { |
| // the BOFRecord can represent either the beginning of a sheet or the workbook |
| case BOFRecord.sid: |
| BOFRecord bof = (BOFRecord) record; |
| if (bof.getType() == bof.TYPE_WORKBOOK) |
| { |
| System.out.println("Encountered workbook"); |
| // assigned to the class level member |
| } else if (bof.getType() == bof.TYPE_WORKSHEET) |
| { |
| System.out.println("Encountered sheet reference"); |
| } |
| break; |
| case BoundSheetRecord.sid: |
| BoundSheetRecord bsr = (BoundSheetRecord) record; |
| System.out.println("New sheet named: " + bsr.getSheetname()); |
| break; |
| case RowRecord.sid: |
| RowRecord rowrec = (RowRecord) record; |
| System.out.println("Row found, first column at " |
| + rowrec.getFirstCol() + " last column at " + rowrec.getLastCol()); |
| break; |
| case NumberRecord.sid: |
| NumberRecord numrec = (NumberRecord) record; |
| System.out.println("Cell found with value " + numrec.getValue() |
| + " at row " + numrec.getRow() + " and column " + numrec.getColumn()); |
| break; |
| // SSTRecords store a array of unique strings used in Excel. |
| case SSTRecord.sid: |
| sstrec = (SSTRecord) record; |
| for (int k = 0; k < sstrec.getNumUniqueStrings(); k++) |
| { |
| System.out.println("String table value " + k + " = " + sstrec.getString(k)); |
| } |
| break; |
| case LabelSSTRecord.sid: |
| LabelSSTRecord lrec = (LabelSSTRecord) record; |
| System.out.println("String cell found with value " |
| + sstrec.getString(lrec.getSSTIndex())); |
| break; |
| } |
| } |
| |
| /** |
| * Read an excel file and spit out what we find. |
| * |
| * @param args Expect one argument that is the file to read. |
| * @throws IOException When there is an error processing the file. |
| */ |
| public static void main(String[] args) throws IOException |
| { |
| // create a new file input stream with the input file specified |
| // at the command line |
| FileInputStream fin = new FileInputStream(args[0]); |
| // create a new org.apache.poi.poifs.filesystem.Filesystem |
| POIFSFileSystem poifs = new POIFSFileSystem(fin); |
| // get the Workbook (excel part) stream in a InputStream |
| InputStream din = poifs.createDocumentInputStream("Workbook"); |
| // construct out HSSFRequest object |
| HSSFRequest req = new HSSFRequest(); |
| // lazy listen for ALL records with the listener shown above |
| req.addListenerForAllRecords(new EventExample()); |
| // create our event factory |
| HSSFEventFactory factory = new HSSFEventFactory(); |
| // process our events based on the document input stream |
| factory.processEvents(req, din); |
| // once all the events are processed close our file input stream |
| fin.close(); |
| // and our document input stream (don't want to leak these!) |
| din.close(); |
| System.out.println("done."); |
| } |
| } |
| ]]></source> |
| </section> |
| |
| <anchor id="record_aware_event_api" /> |
| <section><title>Record Aware Event API</title> |
| <p> |
| This is an experimental extension to the normal |
| <link href="#event_api">Event API</link>. With this, your listener |
| will be called with extra, dummy records. These dummy records should |
| alert you to records which aren't present in the file (eg cells that have |
| yet to be edited), and allow you to handle these. |
| </p> |
| <p> |
| There are three dummy records that your HSSFListener will be called with: |
| </p> |
| <ul> |
| <li>org.apache.poi.hssf.eventusermodel.dummyrecord.MissingRowDummyRecord |
| <br /> |
| This is called during the row record phase (which typically occurs before |
| the cell records), and indicates that the row record for the given |
| row is not present in the file.</li> |
| <li>org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord |
| <br /> |
| This is called during the cell record phase. It is called when a cell |
| record is encountered which leaves a gap between it an the previous one. |
| You can get multiple of these, before the real cell record.</li> |
| <li>org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord |
| <br /> |
| This is called after the last cell of a given row. It indicates that there |
| are no more cells for the row, and also tells you how many cells you have |
| had. For a row with no cells, this will be the only record you get.</li> |
| </ul> |
| <p> |
| To use the Record Aware Event API, you should create an |
| org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener, and pass |
| it your HSSFListener. Then, register the MissingRecordAwareHSSFListener |
| to the event model, and start that as normal. |
| </p> |
| <p> |
| One example use for this API is to write a CSV outputter, which always |
| outputs a minimum number of columns, even where the file doesn't contain |
| some of the rows or cells. It can be found at |
| <code>/src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/XLS2CSVmra.java</code>, |
| and may be called on the command line, or from within your own code. |
| The latest version is always available from |
| <link href="http://svn.apache.org/repos/asf/poi/trunk/src/scratchpad/examples/src/org/apache/poi/hssf/eventusermodel/examples/">subversion</link>. |
| </p> |
| <p> |
| <em>This code is currently in the scratchpad section, so you will either |
| need to include the scratchpad jar on your classpath, or build from a</em> |
| <link href="../subversion.html">subversion checkout</link>. |
| </p> |
| </section> |
| |
| <anchor id="low_level_api" /> |
| <section><title>Low Level APIs</title> |
| |
| <p>The low level API is not much to look at. It consists of lots of |
| "Records" in the org.apache.poi.hssf.record.* package, |
| and set of helper classes in org.apache.poi.hssf.model.*. The |
| record classes are consistent with the low level binary structures |
| inside a BIFF8 file (which is embedded in a POIFS file system). You |
| probably need the book: "Microsoft Excel 97 Developer's Kit" |
| from Microsoft Press in order to understand how these fit together |
| (out of print but easily obtainable from Amazon's used books). In |
| order to gain a good understanding of how to use the low level APIs |
| should view the source in org.apache.poi.hssf.usermodel.* and |
| the classes in org.apache.poi.hssf.model.*. You should read the |
| documentation for the POIFS libraries as well.</p> |
| </section> |
| <section><title>Generating XLS from XML</title> |
| <p>If you wish to generate an XLS file from some XML, it is possible to |
| write your own XML processing code, then use the User API to write out |
| the document.</p> |
| <p>The other option is to use <link href="http://cocoon.apache.org/">Cocoon</link>. |
| In Cocoon, there is the <link href="http://cocoon.apache.org/2.1/userdocs/xls-serializer.html">HSSF Serializer</link>, |
| which takes in XML (in the gnumeric format), and outputs an XLS file for you.</p> |
| </section> |
| <section><title>HSSF Class/Test Application</title> |
| |
| <p>The HSSF application is nothing more than a test for the high |
| level API (and indirectly the low level support). The main body of |
| its code is repeated above. To run it: |
| </p> |
| <ul> |
| <li>download the poi-alpha build and untar it (tar xvzf |
| tarball.tar.gz) |
| </li> |
| <li>set up your classpath as follows: |
| <code>export HSSFDIR={wherever you put HSSF's jar files} |
| export LOG4JDIR={wherever you put LOG4J's jar files} |
| export CLASSPATH=$CLASSPATH:$HSSFDIR/hssf.jar:$HSSFDIR/poi-poifs.jar:$HSSFDIR/poi-util.jar:$LOG4JDIR/jog4j.jar</code> |
| </li><li>type: |
| <code>java org.apache.poi.hssf.dev.HSSF ~/myxls.xls write</code></li> |
| </ul> |
| <p></p> |
| <p>This should generate a test sheet in your home directory called <code>"myxls.xls"</code>. </p> |
| <ul> |
| <li>Type: |
| <code>java org.apache.poi.hssf.dev.HSSF ~/input.xls output.xls</code> |
| <br/> |
| <br/> |
| This is the read/write/modify test. It reads in the spreadsheet, modifies a cell, and writes it back out. |
| Failing this test is not necessarily a bad thing. If HSSF tries to modify a non-existant sheet then this will |
| most likely fail. No big deal. </li> |
| </ul> |
| </section> |
| <section><title>Logging facility</title> |
| <p>POI can dynamically select its logging implementation. POI tries to |
| create a logger using the System property named "org.apache.poi.util.POILogger". |
| Out of the box this can be set to one of three values: |
| </p> |
| <ul> |
| <li>org.apache.poi.util.CommonsLogger</li> |
| <li>org.apache.poi.util.NullLogger</li> |
| <li>org.apache.poi.util.SystemOutLogger</li> |
| </ul> |
| <p> |
| If the property is not defined or points to an invalid classthen the NullLogger is used. |
| </p> |
| <p> |
| Refer to the commons logging package level javadoc for more information concerning how to |
| <link href="http://jakarta.apache.org/commons/logging/api/index.html">configure commons logging.</link> |
| </p> |
| </section> |
| <section><title>HSSF Developer's Tools</title> |
| |
| <p>HSSF has a number of tools useful for developers to debug/develop |
| stuff using HSSF (and more generally XLS files). We've already |
| discussed the app for testing HSSF read/write/modify capabilities; |
| now we'll talk a bit about BiffViewer. Early on in the development of |
| HSSF, it was decided that knowing what was in a record, what was |
| wrong with it, etc. was virtually impossible with the available |
| tools. So we developed BiffViewer. You can find it at |
| org.apache.poi.hssf.dev.BiffViewer. It performs two basic |
| functions and a derivative. |
| </p> |
| <p>The first is "biffview". To do this you run it (assumes |
| you have everything setup in your classpath and that you know what |
| you're doing enough to be thinking about this) with an xls file as a |
| parameter. It will give you a listing of all understood records with |
| their data and a list of not-yet-understood records with no data |
| (because it doesn't know how to interpret them). This listing is |
| useful for several things. First, you can look at the values and SEE |
| what is wrong in quasi-English. Second, you can send the output to a |
| file and compare it. |
| </p> |
| <p>The second function is "big freakin dump", just pass a |
| file and a second argument matching "bfd" exactly. This |
| will just make a big hexdump of the file. |
| </p> |
| <p>Lastly, there is "mixed" mode which does the same as |
| regular biffview, only it includes hex dumps of certain records |
| intertwined. To use that just pass a file with a second argument |
| matching "on" exactly.</p> |
| <p>In the next release cycle we'll also have something called a |
| FormulaViewer. The class is already there, but its not very useful |
| yet. When it does something, we'll document it.</p> |
| |
| </section> |
| <section><title>What's Next?</title> |
| |
| <p>Further effort on HSSF is going to focus on the following major areas: </p> |
| <ul> |
| <li>Performance: POI currently uses a lot of memory for large sheets.</li> |
| <li>Charts: This is a hard problem, with very little documentation.</li> |
| </ul> |
| <p><link href="../getinvolved/index.html"> So jump in! </link> </p> |
| |
| </section> |
| |
| </section> |
| </body> |
| </document> |