apache-poi/content/components/spreadsheet/record-generator.html
2026-02-16 20:14:18 +01:00

598 lines
21 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="Apache Forrest" name="Generator">
<meta name="Forrest-version" content="0.9">
<meta name="Forrest-skin-name" content="pelt">
<title>Record Generator HOWTO</title>
<link type="text/css" href="../../skin/basic.css" rel="stylesheet">
<link media="screen" type="text/css" href="../../skin/screen.css" rel="stylesheet">
<link media="print" type="text/css" href="../../skin/print.css" rel="stylesheet">
<link type="text/css" href="../../skin/profile.css" rel="stylesheet">
<script src="../../skin/getBlank.js" language="javascript" type="text/javascript"></script><script src="../../skin/getMenu.js" language="javascript" type="text/javascript"></script><script src="../../skin/fontsize.js" language="javascript" type="text/javascript"></script>
<link rel="shortcut icon" href="../../images/favicon.ico">
</head>
<body onload="init()">
<script type="text/javascript">ndeSetTextSize();</script>
<div id="top">
<!--+
|breadtrail
+-->
<div class="breadtrail">
<a href="https://www.apache.org">Apache Software Foundation</a> &gt; <a href="https://poi.apache.org">Apache POI</a><script src="../../skin/breadcrumbs.js" language="JavaScript" type="text/javascript"></script>
</div>
<!--+
|header
+-->
<div class="header">
<!--+
|start group logo
+-->
<div class="grouplogo">
<a href="https://www.apache.org"><img class="logoImage" alt="Apache Software Foundation" src="../../images/asflogo_horizontal_color.svg" title="The Apache Software Foundation is a cornerstone of the modern Open Source software ecosystem &ndash; supporting some of the most widely used and important software solutions powering today's Internet economy."></a>
</div>
<!--+
|end group logo
+-->
<!--+
|start Project Logo
+-->
<div class="projectlogo">
<a href="https://poi.apache.org"><img class="logoImage" alt="Apache POI" src="../../images/project-header.png" title="Apache POI is well-known in the Java field as a library for reading and writing Microsoft Office file formats, such as Excel, PowerPoint, Word, Visio, Publisher and Outlook. It supports both the older (OLE2) and new (OOXML - Office Open XML) formats."></a>
</div>
<!--+
|end Project Logo
+-->
<!--+
|start Search
+-->
<div class="searchbox">
<form action="https://www.google.com/search" method="get" class="roundtopsmall">
<input value="poi.apache.org" name="sitesearch" type="hidden"><input onFocus="getBlank (this, 'Search the site with google');" size="25" name="q" id="query" type="text" value="Search the site with google">&nbsp;
<input name="Search" value="Search" type="submit">
</form>
</div>
<!--+
|end search
+-->
<!--+
|start Tabs
+-->
<ul id="tabs">
<li>
<a class="unselected" href="../../index.html">Home</a>
</li>
<li>
<a class="unselected" href="../../help/index.html">Help</a>
</li>
<li class="current">
<a class="selected" href="../../components/index.html">Component APIs</a>
</li>
<li>
<a class="unselected" href="../../devel/index.html">Getting Involved</a>
</li>
</ul>
<!--+
|end Tabs
+-->
</div>
</div>
<div id="main">
<div id="publishedStrip">
<!--+
|start Subtabs
+-->
<div id="level2tabs"></div>
<!--+
|end Endtabs
+-->
<script type="text/javascript"><!--
document.write("Last Published: " + document.lastModified);
// --></script>
</div>
<!--+
|breadtrail
+-->
<div class="breadtrail">
&nbsp;
</div>
<!--+
|start Menu, mainarea
+-->
<!--+
|start Menu
+-->
<div id="menu">
<div onclick="SwitchMenu('menu_selected_1.1', '../../skin/')" id="menu_selected_1.1Title" class="menutitle" style="background-image: url('../../skin/images/chapter_open.gif');">Component APIs</div>
<div id="menu_selected_1.1" class="selectedmenuitemgroup" style="display: block;">
<div class="menuitem">
<a href="../../components/index.html">Overview</a>
</div>
<div class="menuitem">
<a href="../../apidocs/index.html">Javadocs</a>
</div>
<div onclick="SwitchMenu('menu_selected_1.1.3', '../../skin/')" id="menu_selected_1.1.3Title" class="menutitle" style="background-image: url('../../skin/images/chapter_open.gif');">Excel (HSSF/XSSF)</div>
<div id="menu_selected_1.1.3" class="selectedmenuitemgroup" style="display: block;">
<div class="menuitem">
<a href="../../components/spreadsheet/index.html">Overview</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/quick-guide.html">Quick Guide</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/how-to.html">HOWTO</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/converting.html">HSSF to SS Converting</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/formula.html">Formula Support</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/eval.html">Formula Evaluation</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/eval-devguide.html">Eval Dev Guide</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/examples.html">Examples</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/use-case.html">Use Case</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/diagrams.html">Pictorial Docs</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/limitations.html">Limitations</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/user-defined-functions.html">User Defined Functions</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/excelant.html">ExcelAnt Tests</a>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/hacking-hssf.html">Hacking HSSF</a>
</div>
<div class="menupage">
<div class="menupagetitle">Record Generator</div>
</div>
<div class="menuitem">
<a href="../../components/spreadsheet/chart.html">Charts</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.4', '../../skin/')" id="menu_1.1.4Title" class="menutitle">PowerPoint (HSLF/XSLF)</div>
<div id="menu_1.1.4" class="menuitemgroup">
<div class="menuitem">
<a href="../../components/slideshow/index.html">Overview</a>
</div>
<div class="menuitem">
<a href="../../components/slideshow/quick-guide.html">Quick Guide</a>
</div>
<div class="menuitem">
<a href="../../components/slideshow/how-to-shapes.html">HSLF Cookbook</a>
</div>
<div class="menuitem">
<a href="../../components/slideshow/xslf-cookbook.html">XSLF Cookbook</a>
</div>
<div class="menuitem">
<a href="../../components/slideshow/ppt-wmf-emf-renderer.html">Render SL/WMF/EMF</a>
</div>
<div class="menuitem">
<a href="../../components/slideshow/ppt-file-format.html">PPT File Format</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.5', '../../skin/')" id="menu_1.1.5Title" class="menutitle">Word (HWPF/XWPF)</div>
<div id="menu_1.1.5" class="menuitemgroup">
<div class="menuitem">
<a href="../../components/document/index.html">Overview</a>
</div>
<div class="menuitem">
<a href="../../components/document/quick-guide.html">HWPF Quick Guide</a>
</div>
<div class="menuitem">
<a href="../../components/document/quick-guide-xwpf.html">XWPF Quick Guide</a>
</div>
<div class="menuitem">
<a href="../../components/document/docoverview.html">HWPF Format</a>
</div>
<div class="menuitem">
<a href="../../components/document/projectplan.html">HWPF Project plan</a>
</div>
</div>
<div class="menuitem">
<a href="../../components/hsmf/index.html">Outlook (HSMF)</a>
</div>
<div class="menuitem">
<a href="../../components/diagram/index.html">Visio (HDGF+XDGF)</a>
</div>
<div onclick="SwitchMenu('menu_1.1.8', '../../skin/')" id="menu_1.1.8Title" class="menutitle">Publisher (HPBF)</div>
<div id="menu_1.1.8" class="menuitemgroup">
<div class="menuitem">
<a href="../../components/hpbf/index.html">Overview</a>
</div>
<div class="menuitem">
<a href="../../components/hpbf/file-format.html">File Format</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.9', '../../skin/')" id="menu_1.1.9Title" class="menutitle">OLE2 Filesystem (POIFS)</div>
<div id="menu_1.1.9" class="menuitemgroup">
<div class="menuitem">
<a href="../../components/poifs/index.html">Overview</a>
</div>
<div class="menuitem">
<a href="../../components/poifs/how-to.html">How To</a>
</div>
<div class="menuitem">
<a href="../../components/poifs/embeded.html">Embedded Documents</a>
</div>
<div class="menuitem">
<a href="../../components/poifs/fileformat.html">File System Documentation</a>
</div>
<div class="menuitem">
<a href="../../components/poifs/usecases.html">Use Cases</a>
</div>
<div class="menuitem">
<a href="../../components/poifs/design.html">Design</a>
</div>
</div>
<div onclick="SwitchMenu('menu_1.1.10', '../../skin/')" id="menu_1.1.10Title" class="menutitle">OLE2 Document Props (HPSF)</div>
<div id="menu_1.1.10" class="menuitemgroup">
<div class="menuitem">
<a href="../../components/hpsf/index.html">Overview</a>
</div>
<div class="menuitem">
<a href="../../components/hpsf/how-to.html">How To</a>
</div>
<div class="menuitem">
<a href="../../components/hpsf/thumbnails.html">Thumbnails</a>
</div>
<div class="menuitem">
<a href="../../components/hpsf/internals.html">Internals</a>
</div>
<div class="menuitem">
<a href="../../components/hpsf/todo.html">To Do</a>
</div>
</div>
<div class="menuitem">
<a href="../../components/hmef/index.html">TNEF (HMEF) for winmail.dat</a>
</div>
<div class="menuitem">
<a href="../../components/oxml4j/index.html">OpenXML4J (OOXML)</a>
</div>
<div class="menuitem">
<a href="../../components/logging.html">Logging framework</a>
</div>
<div class="menuitem">
<a href="../../components/configuration.html">Configuration</a>
</div>
</div>
<div id="credit"></div>
<div id="roundbottom">
<img style="display: none" class="corner" height="15" width="15" alt="" src="../../skin/images/rc-b-l-15-1body-2menu-3menu.png"></div>
<!--+
|alternative credits
+-->
<div id="credit2">
<a href="https://donate.apache.org/"><img border="0" title="Support Apache" alt="Support Apache - logo" src="../../images/support-asf.png" style="width: 125px;height: 125px;"></a><a href="https://www.apache.org/foundation/press/kit/#poweredby"><img border="0" title="powered by POI" alt="powered by POI - logo" src="../../images/poweredby-poi-logo.png" style="width: 125px;height: 125px;"></a>
</div>
</div>
<!--+
|end Menu
+-->
<!--+
|start content
+-->
<div id="content">
<h1>Record Generator HOWTO</h1>
<div id="front-matter"></div>
<a name="How+to+Use+the+Record+Generator"></a>
<h2 class="boxed">How to Use the Record Generator</h2>
<div class="section">
<a name="History"></a>
<h3 class="boxed">History</h3>
<p>
The record generator was born from frustration with translating
the Excel records to Java classes. Doing this manually is a time
consuming process. It's also very easy to make mistakes.
</p>
<p>
A utility was needed to take the definition of what a
record looked like and do all the boring and repetitive work.
</p>
<a name="Capabilities"></a>
<h3 class="boxed">Capabilities</h3>
<p>
The record generator takes XML as input and produces the following
output:
</p>
<ul>
<li>A Java file capable of decoding and encoding the record.</li>
<li>A test class that provides a fill-in-the-blanks implementation
of a test case for ensuring the record operates as
designed.</li>
</ul>
<a name="Usage"></a>
<h3 class="boxed">Usage</h3>
<p>
The record generator is invoked as an Ant target
(generate-records). It goes through looking for all files in
<span class="codefrag">src/records/definitions</span> ending with _record.xml.
It then creates two files; the Java record definition and the
Java test case template.
</p>
<p>
The records themselves have the following general layout:
</p>
<div class="code">
<div class="codeline">
<span class="lineno"></span><span class="codebody"></span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody">&lt;record id="0x1032" name="Frame" package="org.apache.poi.hssf.record"</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> excel-record-id="FRAME"&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;description&gt;The frame record indicates whether there is a border</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> around the displayed text of a chart.&lt;/description&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;author&gt;Glen Stampoultzis (glens at apache.org)&lt;/author&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;fields&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;field type="int" size="2" name="border type"&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;const name="regular" value="0" description="regular rectangle or no border"/&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;const name="shadow" value="1" description="rectangle with shadow"/&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;/field&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;field type="int" size="2" name="options"&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;bit number="0" name="auto size"</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> description="excel calculates the size automatically if true"/&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;bit number="1" name="auto position"</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> description="excel calculates the position automatically"/&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;/field&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> &lt;/fields&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody">&lt;/record&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> </span>
</div>
</div>
<p>
The following table details the allowable types and sizes for
the fields.
</p>
<table class="ForrestTable" cellspacing="1" cellpadding="4">
<tr>
<th colspan="1" rowspan="1">Type</th>
<th colspan="1" rowspan="1">Size</th>
<th colspan="1" rowspan="1">Java Type</th>
</tr>
<tr>
<td colspan="1" rowspan="1">int</td>
<td colspan="1" rowspan="1">1</td>
<td colspan="1" rowspan="1">byte</td>
</tr>
<tr>
<td colspan="1" rowspan="1">int</td>
<td colspan="1" rowspan="1">2</td>
<td colspan="1" rowspan="1">short</td>
</tr>
<tr>
<td colspan="1" rowspan="1">int</td>
<td colspan="1" rowspan="1">4</td>
<td colspan="1" rowspan="1">int</td>
</tr>
<tr>
<td colspan="1" rowspan="1">int</td>
<td colspan="1" rowspan="1">8</td>
<td colspan="1" rowspan="1">long</td>
</tr>
<tr>
<td colspan="1" rowspan="1">int</td>
<td colspan="1" rowspan="1">varword</td>
<td colspan="1" rowspan="1">array of shorts</td>
</tr>
<tr>
<td colspan="1" rowspan="1">bits</td>
<td colspan="1" rowspan="1">1</td>
<td colspan="1" rowspan="1">A byte comprising of a bits (defined by the bit element)
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">bits</td>
<td colspan="1" rowspan="1">2</td>
<td colspan="1" rowspan="1">An short comprising of a bits</td>
</tr>
<tr>
<td colspan="1" rowspan="1">bits</td>
<td colspan="1" rowspan="1">4</td>
<td colspan="1" rowspan="1">A int comprising of a bits</td>
</tr>
<tr>
<td colspan="1" rowspan="1">float</td>
<td colspan="1" rowspan="1">8</td>
<td colspan="1" rowspan="1">double</td>
</tr>
<tr>
<td colspan="1" rowspan="1">hbstring</td>
<td colspan="1" rowspan="1">java expression</td>
<td colspan="1" rowspan="1">String</td>
</tr>
</table>
<p>
The Java records are regenerated each time the record generator is
run, however the test stubs are only created if the test stub does
not already exist. What this means is that you may change test
stubs but not the generated records.
</p>
<a name="Custom+Field+Types"></a>
<h3 class="boxed">Custom Field Types</h3>
<p>
Occasionally the builtin types are not enough. More control
over the encoding and decoding of the streams is required. This
can be achieved using a custom type.
</p>
<p>
A custom type lets you escape to java to define the way in which
the field encodes and decodes. To code a custom type you
declare your field like this:
</p>
<div class="code">
<div class="codeline">
<span class="lineno"></span><span class="codebody"></span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody">&lt;field type="custom:org.apache.poi.hssf.record.LinkedDataFormulaField"</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> size="var" name="formula of link" description="formula"/&gt;</span>
</div>
<div class="codeline">
<span class="lineno"></span><span class="codebody"> </span>
</div>
</div>
<p>
Where the class name specified after <span class="codefrag">custom:</span> is a
class implementing the interface <span class="codefrag">CustomField</span>.
</p>
<p>
You can then implement the encoding yourself.
</p>
<a name="How+it+Works"></a>
<h3 class="boxed">How it Works</h3>
<p>
The record generation works by taking an XML file and styling it
using XSLT. Given that XSLT is a little limited in some ways it was
necessary to add a little Java code to the mix.
</p>
<p>
See record.xsl, record_test.xsl, FieldIterator.java,
RecordUtil.java, RecordGenerator.java
</p>
<p>
There is a corresponding "type" generator for HWPF.
See the HWPF documentation for details.
</p>
<a name="Limitations"></a>
<h3 class="boxed">Limitations</h3>
<p>
The record generator does not handle all possible record types and
goes not intend to perform this function. When dealing with a
non-standard record sometimes the cost-benefit of coding the
record by hand will be greater than attempting modify the
generator. The main point of the record generator is to save
time, so keep that in mind.
</p>
<p>
Currently the XSL file that generates the record calls out to
Java objects. The Java code for the record generation is
currently quite messy with minimal comments.
</p>
</div>
<p align="right">
<font size="-2">by&nbsp;Glen Stampoultzis,&nbsp;Andrew C. Oliver</font>
</p>
</div>
<!--+
|end content
+-->
<div class="clearboth">&nbsp;</div>
</div>
<div id="footer">
<!--+
|start bottomstrip
+-->
<div class="lastmodified">
<script type="text/javascript"><!--
document.write("Last Published: " + document.lastModified);
// --></script>
</div>
<div class="copyright">
Copyright &copy;
2001-2026 <a href="https://www.apache.org/">The Apache Software Foundation</a>
<br>
Apache POI, POI, Apache, the Apache logo, and the Apache
POI project logo are trademarks of The Apache Software Foundation.
</div>
<div id="feedback">
Send feedback about the website to:
<a id="feedbackto" href="mailto:dev@poi.apache.org?subject=Feedback%C2%A0components/spreadsheet/record-generator.html">dev@poi.apache.org</a>
</div>
<!--+
|end bottomstrip
+-->
</div>
</body>
</html>