Merged revisions 638786-638802,638805-638811,638813-638814,638816-639230,639233-639241,639243-639253,639255-639486,639488-639601,639603-639835,639837-639917,639919-640056,640058-640710,640712-641156,641158-641184,641186-641795,641797-641798,641800-641933,641935-641963,641965-641966,641968-641995,641997-642230,642232-642562,642564-642565,642568-642570,642572-642573,642576-642736,642739-642877,642879,642881-642890,642892-642903,642905-642945,642947-643624,643626-643653,643655-643669,643671,643673-643830,643832-643833,643835-644342,644344-644472,644474-644508,644510-645347,645349-645351,645353-645559,645561-645565,645568-645951,645953-646193,646195-646311,646313-646404,646406-646665,646667-646853,646855-646869,646871-647151,647153-647185,647187-647277,647279-647566,647568-647573,647575,647578-647711,647714-647737,647739-647823,647825-648155,648157-648202,648204-648273,648275,648277-648302,648304-648333,648335-648588,648590-648622,648625-648673,648675-649141,649144,649146-649556,649558-649795,649799,649801-649910,649912-649913,649915-650128,650131-650132,650134-650137,650140-650914,650916-651991,651993-652284,652286-652287,652289,652291,652293-652297,652299-652328,652330-652425,652427-652445,652447-652560,652562-652933,652935,652937-652993,652995-653116,653118-653124,653126-653483,653487-653519,653522-653550,653552-653607,653609-653667,653669-653674,653676-653814,653817-653830,653832-653891,653893-653944,653946-654055,654057-654355,654357-654365,654367-654648,654651-655215,655217-655277,655279-655281,655283-655911,655913-656212,656214,656216-656251,656253-656698,656700-656756,656758-656892,656894-657135,657137-657165,657168-657179,657181-657354,657356-657357,657359-657701,657703-657874,657876-658032,658034-658284,658286,658288-658301,658303-658307,658309-658321,658323-658335,658337-658348,658351,658353-658832,658834-658983,658985,658987-659066,659068-659402,659404-659428,659430-659451,659453-659454,659456-659461,659463-659477,659479-659524,659526-659571,659574,659576-660255,660257-660262,660264-660279,660281-660343,660345-660473,660475-660827,660829-660833,660835-660888,660890-663321,663323-663435,663437-663764,663766-663854,663856-664219,664221-664489,664494-664514,664516-668013,668015-668142,668144-668152,668154,668156-668256,668258,668260-669139,669141-669455,669457-669657,669659-669808,669810-670189,670191-671321,671323-672229,672231-672549,672551-672552,672554-672561,672563-672566,672568,672571-673049,673051-673852,673854-673862,673864-673986,673988-673996,673998-674347,674349-674890,674892-674910,674912-674936,674938-674952,674954-675078,675080-675085,675087-675217,675219-675660,675662-675670,675672-675716,675718-675726,675728-675733,675735-675775,675777-675782,675784,675786-675791,675794-675852,675854-676200,676202,676204,676206-676220,676222-676309,676311-676456,676458-676994,676996-677027,677030-677040,677042-677056,677058-677375,677377-677968,677970-677971,677973,677975-677994,677996-678286,678288-678538,678540-680393,680395-680469,680471-680529,680531-680852,680854-681529,681531-681571,681573-682224,682226,682228,682231-682281,682283-682335,682337-682511 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk ........ r682508 | josh | 2008-08-04 22:08:11 +0100 (Mon, 04 Aug 2008) | 1 line Patch 44894 - refactoring duplicate logic from EventRecordFactory to RecordFactory ........ r682510 | josh | 2008-08-04 22:14:37 +0100 (Mon, 04 Aug 2008) | 1 line removed debugging code leftover from r682508 (patch 44894) ........ r682511 | nick | 2008-08-04 22:21:16 +0100 (Mon, 04 Aug 2008) | 1 line Fix bug #45538 - Include excel headers and footers in the output of ExcelExtractor ........ git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@682516 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cfdf265975
commit
946dea40a7
@ -52,6 +52,8 @@
|
|||||||
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
|
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">45538 - Include excel headers and footers in the output of ExcelExtractor</action>
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">44894 - refactor duplicate logic from EventRecordFactory to RecordFactory</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">Support for Headers / Footers in HSLF</action>
|
<action dev="POI-DEVELOPERS" type="add">Support for Headers / Footers in HSLF</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">44953 - Extensive fixes for data validation</action>
|
<action dev="POI-DEVELOPERS" type="fix">44953 - Extensive fixes for data validation</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45519 - Fixed to keep datavalidation records together</action>
|
<action dev="POI-DEVELOPERS" type="fix">45519 - Fixed to keep datavalidation records together</action>
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
|
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">45538 - Include excel headers and footers in the output of ExcelExtractor</action>
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">44894 - refactor duplicate logic from EventRecordFactory to RecordFactory</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">Support for Headers / Footers in HSLF</action>
|
<action dev="POI-DEVELOPERS" type="add">Support for Headers / Footers in HSLF</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">44953 - Extensive fixes for data validation</action>
|
<action dev="POI-DEVELOPERS" type="fix">44953 - Extensive fixes for data validation</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45519 - Fixed to keep datavalidation records together</action>
|
<action dev="POI-DEVELOPERS" type="fix">45519 - Fixed to keep datavalidation records together</action>
|
||||||
|
@ -18,241 +18,60 @@
|
|||||||
package org.apache.poi.hssf.eventmodel;
|
package org.apache.poi.hssf.eventmodel;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Constructor;
|
import java.util.Arrays;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.BOFRecord;
|
|
||||||
import org.apache.poi.hssf.record.BackupRecord;
|
|
||||||
import org.apache.poi.hssf.record.BlankRecord;
|
|
||||||
import org.apache.poi.hssf.record.BookBoolRecord;
|
|
||||||
import org.apache.poi.hssf.record.BoolErrRecord;
|
|
||||||
import org.apache.poi.hssf.record.BottomMarginRecord;
|
|
||||||
import org.apache.poi.hssf.record.BoundSheetRecord;
|
|
||||||
import org.apache.poi.hssf.record.CalcCountRecord;
|
|
||||||
import org.apache.poi.hssf.record.CalcModeRecord;
|
|
||||||
import org.apache.poi.hssf.record.CodepageRecord;
|
|
||||||
import org.apache.poi.hssf.record.ColumnInfoRecord;
|
|
||||||
import org.apache.poi.hssf.record.ContinueRecord;
|
|
||||||
import org.apache.poi.hssf.record.CountryRecord;
|
|
||||||
import org.apache.poi.hssf.record.DBCellRecord;
|
|
||||||
import org.apache.poi.hssf.record.DSFRecord;
|
|
||||||
import org.apache.poi.hssf.record.DateWindow1904Record;
|
|
||||||
import org.apache.poi.hssf.record.DefaultColWidthRecord;
|
|
||||||
import org.apache.poi.hssf.record.DefaultRowHeightRecord;
|
|
||||||
import org.apache.poi.hssf.record.DeltaRecord;
|
|
||||||
import org.apache.poi.hssf.record.DimensionsRecord;
|
|
||||||
import org.apache.poi.hssf.record.EOFRecord;
|
|
||||||
import org.apache.poi.hssf.record.ExtSSTRecord;
|
|
||||||
import org.apache.poi.hssf.record.ExtendedFormatRecord;
|
|
||||||
import org.apache.poi.hssf.record.ExternSheetRecord;
|
|
||||||
import org.apache.poi.hssf.record.FnGroupCountRecord;
|
|
||||||
import org.apache.poi.hssf.record.FontRecord;
|
|
||||||
import org.apache.poi.hssf.record.FooterRecord;
|
|
||||||
import org.apache.poi.hssf.record.FormatRecord;
|
|
||||||
import org.apache.poi.hssf.record.GridsetRecord;
|
|
||||||
import org.apache.poi.hssf.record.GutsRecord;
|
|
||||||
import org.apache.poi.hssf.record.HCenterRecord;
|
|
||||||
import org.apache.poi.hssf.record.HeaderRecord;
|
|
||||||
import org.apache.poi.hssf.record.HideObjRecord;
|
|
||||||
import org.apache.poi.hssf.record.IndexRecord;
|
|
||||||
import org.apache.poi.hssf.record.InterfaceEndRecord;
|
|
||||||
import org.apache.poi.hssf.record.InterfaceHdrRecord;
|
|
||||||
import org.apache.poi.hssf.record.IterationRecord;
|
|
||||||
import org.apache.poi.hssf.record.LabelRecord;
|
|
||||||
import org.apache.poi.hssf.record.LabelSSTRecord;
|
|
||||||
import org.apache.poi.hssf.record.LeftMarginRecord;
|
|
||||||
import org.apache.poi.hssf.record.MMSRecord;
|
|
||||||
import org.apache.poi.hssf.record.MergeCellsRecord;
|
|
||||||
import org.apache.poi.hssf.record.MulBlankRecord;
|
|
||||||
import org.apache.poi.hssf.record.MulRKRecord;
|
|
||||||
import org.apache.poi.hssf.record.NameRecord;
|
|
||||||
import org.apache.poi.hssf.record.NumberRecord;
|
|
||||||
import org.apache.poi.hssf.record.PaneRecord;
|
|
||||||
import org.apache.poi.hssf.record.PaletteRecord;
|
|
||||||
import org.apache.poi.hssf.record.PasswordRecord;
|
|
||||||
import org.apache.poi.hssf.record.PasswordRev4Record;
|
|
||||||
import org.apache.poi.hssf.record.PrecisionRecord;
|
|
||||||
import org.apache.poi.hssf.record.PrintGridlinesRecord;
|
|
||||||
import org.apache.poi.hssf.record.PrintHeadersRecord;
|
|
||||||
import org.apache.poi.hssf.record.PrintSetupRecord;
|
|
||||||
import org.apache.poi.hssf.record.ProtectRecord;
|
|
||||||
import org.apache.poi.hssf.record.ProtectionRev4Record;
|
|
||||||
import org.apache.poi.hssf.record.RKRecord;
|
|
||||||
import org.apache.poi.hssf.record.Record;
|
|
||||||
import org.apache.poi.hssf.record.RecordFormatException;
|
|
||||||
import org.apache.poi.hssf.record.RecordInputStream;
|
|
||||||
import org.apache.poi.hssf.record.RefModeRecord;
|
|
||||||
import org.apache.poi.hssf.record.RefreshAllRecord;
|
|
||||||
import org.apache.poi.hssf.record.RightMarginRecord;
|
|
||||||
import org.apache.poi.hssf.record.RowRecord;
|
|
||||||
import org.apache.poi.hssf.record.SSTRecord;
|
|
||||||
import org.apache.poi.hssf.record.SaveRecalcRecord;
|
|
||||||
import org.apache.poi.hssf.record.SelectionRecord;
|
|
||||||
import org.apache.poi.hssf.record.SharedFormulaRecord;
|
|
||||||
import org.apache.poi.hssf.record.StringRecord;
|
|
||||||
import org.apache.poi.hssf.record.StyleRecord;
|
|
||||||
import org.apache.poi.hssf.record.TabIdRecord;
|
|
||||||
import org.apache.poi.hssf.record.TableRecord;
|
|
||||||
import org.apache.poi.hssf.record.TopMarginRecord;
|
|
||||||
import org.apache.poi.hssf.record.UnknownRecord;
|
|
||||||
import org.apache.poi.hssf.record.UseSelFSRecord;
|
|
||||||
import org.apache.poi.hssf.record.VCenterRecord;
|
|
||||||
import org.apache.poi.hssf.record.WSBoolRecord;
|
|
||||||
import org.apache.poi.hssf.record.WindowOneRecord;
|
|
||||||
import org.apache.poi.hssf.record.WindowProtectRecord;
|
|
||||||
import org.apache.poi.hssf.record.WindowTwoRecord;
|
|
||||||
import org.apache.poi.hssf.record.WriteAccessRecord;
|
|
||||||
import org.apache.poi.hssf.record.WriteProtectRecord;
|
|
||||||
import org.apache.poi.hssf.record.FilePassRecord;
|
|
||||||
import org.apache.poi.hssf.record.NoteRecord;
|
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event-based record factory. As opposed to RecordFactory
|
* Event-based record factory. As opposed to RecordFactory
|
||||||
* this refactored version throws record events as it comes
|
* this version sends {@link ERFListener#processRecord(Record) } messages to
|
||||||
* accross the records. I throws the "lazily" one record behind
|
* the supplied listener. Record notifications are sent one record behind
|
||||||
* to ensure that ContinueRecords are processed first.
|
* to ensure that {@link ContinueRecord}s are processed first.
|
||||||
*
|
*
|
||||||
* @author Andrew C. Oliver (acoliver@apache.org) - probably to blame for the bugs (so yank his chain on the list)
|
* @author Andrew C. Oliver (acoliver@apache.org) - probably to blame for the bugs (so yank his chain on the list)
|
||||||
* @author Marc Johnson (mjohnson at apache dot org) - methods taken from RecordFactory
|
* @author Marc Johnson (mjohnson at apache dot org) - methods taken from RecordFactory
|
||||||
* @author Glen Stampoultzis (glens at apache.org) - methods taken from RecordFactory
|
* @author Glen Stampoultzis (glens at apache.org) - methods taken from RecordFactory
|
||||||
* @author Csaba Nagy (ncsaba at yahoo dot com)
|
* @author Csaba Nagy (ncsaba at yahoo dot com)
|
||||||
*/
|
*/
|
||||||
public class EventRecordFactory
|
public final class EventRecordFactory {
|
||||||
{
|
|
||||||
|
private final ERFListener _listener;
|
||||||
|
private final short[] _sids;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* contains the classes for all the records we want to parse.
|
|
||||||
*/
|
|
||||||
private static final Class[] records;
|
|
||||||
|
|
||||||
static {
|
|
||||||
records = new Class[]
|
|
||||||
{
|
|
||||||
BOFRecord.class, InterfaceHdrRecord.class, MMSRecord.class,
|
|
||||||
InterfaceEndRecord.class, WriteAccessRecord.class,
|
|
||||||
CodepageRecord.class, DSFRecord.class, TabIdRecord.class,
|
|
||||||
FnGroupCountRecord.class, WindowProtectRecord.class,
|
|
||||||
ProtectRecord.class, PasswordRecord.class, ProtectionRev4Record.class,
|
|
||||||
PasswordRev4Record.class, WindowOneRecord.class, BackupRecord.class,
|
|
||||||
HideObjRecord.class, DateWindow1904Record.class,
|
|
||||||
PrecisionRecord.class, RefreshAllRecord.class, BookBoolRecord.class,
|
|
||||||
FontRecord.class, FormatRecord.class, ExtendedFormatRecord.class,
|
|
||||||
StyleRecord.class, UseSelFSRecord.class, BoundSheetRecord.class,
|
|
||||||
CountryRecord.class, SSTRecord.class, ExtSSTRecord.class,
|
|
||||||
EOFRecord.class, IndexRecord.class, CalcModeRecord.class,
|
|
||||||
CalcCountRecord.class, RefModeRecord.class, IterationRecord.class,
|
|
||||||
DeltaRecord.class, SaveRecalcRecord.class, PrintHeadersRecord.class,
|
|
||||||
PrintGridlinesRecord.class, GridsetRecord.class, GutsRecord.class,
|
|
||||||
DefaultRowHeightRecord.class, WSBoolRecord.class, HeaderRecord.class,
|
|
||||||
FooterRecord.class, HCenterRecord.class, VCenterRecord.class,
|
|
||||||
PrintSetupRecord.class, DefaultColWidthRecord.class,
|
|
||||||
DimensionsRecord.class, RowRecord.class, LabelSSTRecord.class,
|
|
||||||
RKRecord.class, NumberRecord.class, DBCellRecord.class,
|
|
||||||
WindowTwoRecord.class, SelectionRecord.class, ContinueRecord.class,
|
|
||||||
LabelRecord.class, BlankRecord.class, ColumnInfoRecord.class,
|
|
||||||
MulRKRecord.class, MulBlankRecord.class, MergeCellsRecord.class,
|
|
||||||
BoolErrRecord.class, ExternSheetRecord.class, NameRecord.class,
|
|
||||||
LeftMarginRecord.class, RightMarginRecord.class,
|
|
||||||
TopMarginRecord.class, BottomMarginRecord.class,
|
|
||||||
PaletteRecord.class, StringRecord.class, SharedFormulaRecord.class,
|
|
||||||
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
|
|
||||||
NoteRecord.class, TableRecord.class
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cache of the recordsToMap();
|
|
||||||
*/
|
|
||||||
private static Map recordsMap = recordsToMap(records);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cache of the return of getAllKnownSids so that we don't have to
|
|
||||||
* expensively get them every time.
|
|
||||||
*/
|
|
||||||
private static short[] sidscache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of the listners that are registred. should all be ERFListener
|
|
||||||
*/
|
|
||||||
private List listeners;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* instance is abortable or not
|
|
||||||
*/
|
|
||||||
private boolean abortable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct an abortable EventRecordFactory.
|
|
||||||
* The same as calling new EventRecordFactory(true)
|
|
||||||
* @see #EventRecordFactory(boolean)
|
|
||||||
*/
|
|
||||||
public EventRecordFactory() {
|
|
||||||
this(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an EventRecordFactory
|
|
||||||
* @param abortable specifies whether the return from the listener
|
|
||||||
* handler functions are obeyed. False means they are ignored. True
|
|
||||||
* means the event loop exits on error.
|
|
||||||
*/
|
|
||||||
public EventRecordFactory(boolean abortable) {
|
|
||||||
this.abortable = abortable;
|
|
||||||
listeners = new ArrayList(recordsMap.size());
|
|
||||||
|
|
||||||
if (sidscache == null) {
|
|
||||||
sidscache = getAllKnownRecordSIDs();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a listener for records. These can be for all records
|
|
||||||
* or just a subset.
|
|
||||||
*
|
*
|
||||||
* @param sids an array of Record.sid values identifying the records
|
* @param sids an array of Record.sid values identifying the records
|
||||||
* the listener will work with. Alternatively if this is "null" then
|
* the listener will work with. Alternatively if this is "null" then
|
||||||
* all records are passed.
|
* all records are passed. For all 'known' record types use {@link RecordFactory#getAllKnownRecordSIDs()}
|
||||||
*/
|
*/
|
||||||
public void registerListener(ERFListener listener, short[] sids) {
|
public EventRecordFactory(ERFListener listener, short[] sids) {
|
||||||
if (sids == null)
|
_listener = listener;
|
||||||
sids = sidscache;
|
if (sids == null) {
|
||||||
ERFListener wrapped = new ListenerWrapper(listener, sids, abortable);
|
_sids = null;
|
||||||
listeners.add(wrapped);
|
} else {
|
||||||
|
_sids = (short[]) sids.clone();
|
||||||
|
Arrays.sort(_sids); // for faster binary search
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
private boolean isSidIncluded(short sid) {
|
||||||
|
if (_sids == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Arrays.binarySearch(_sids, sid) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* used for unit tests to test the registration of record listeners.
|
|
||||||
* @return Iterator of ERFListeners
|
|
||||||
*/
|
|
||||||
protected Iterator listeners() {
|
|
||||||
return listeners.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sends the record event to all registered listeners.
|
* sends the record event to all registered listeners.
|
||||||
* @param record the record to be thrown.
|
* @param record the record to be thrown.
|
||||||
* @return boolean abort. If exitability is turned on this aborts
|
* @return <code>false</code> to abort. This aborts
|
||||||
* out of the event loop should any listener specify to do so.
|
* out of the event loop should the listener return false
|
||||||
*/
|
*/
|
||||||
private boolean throwRecordEvent(Record record)
|
private boolean processRecord(Record record) {
|
||||||
{
|
if (!isSidIncluded(record.getSid())) {
|
||||||
boolean result = true;
|
return true;
|
||||||
Iterator i = listeners.iterator();
|
}
|
||||||
|
return _listener.processRecord(record);
|
||||||
while (i.hasNext()) {
|
|
||||||
result = ((ERFListener) i.next()).processRecord(record);
|
|
||||||
if (abortable == true && result == false) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,220 +83,39 @@ public class EventRecordFactory
|
|||||||
* @exception RecordFormatException on error processing the
|
* @exception RecordFormatException on error processing the
|
||||||
* InputStream
|
* InputStream
|
||||||
*/
|
*/
|
||||||
public void processRecords(InputStream in)
|
public void processRecords(InputStream in) throws RecordFormatException {
|
||||||
throws RecordFormatException
|
Record last_record = null;
|
||||||
{
|
|
||||||
Record last_record = null;
|
|
||||||
|
|
||||||
RecordInputStream recStream = new RecordInputStream(in);
|
RecordInputStream recStream = new RecordInputStream(in);
|
||||||
|
|
||||||
while (recStream.hasNextRecord()) {
|
while (recStream.hasNextRecord()) {
|
||||||
recStream.nextRecord();
|
recStream.nextRecord();
|
||||||
Record[] recs = createRecord(recStream); // handle MulRK records
|
Record[] recs = RecordFactory.createRecord(recStream); // handle MulRK records
|
||||||
if (recs.length > 1)
|
if (recs.length > 1) {
|
||||||
{
|
for (int k = 0; k < recs.length; k++) {
|
||||||
for (int k = 0; k < recs.length; k++)
|
if ( last_record != null ) {
|
||||||
{
|
if (!processRecord(last_record)) {
|
||||||
if ( last_record != null ) {
|
return;
|
||||||
if (throwRecordEvent(last_record) == false && abortable == true) {
|
|
||||||
last_record = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
last_record =
|
|
||||||
recs[ k ]; // do to keep the algorythm homogenous...you can't
|
|
||||||
} // actually continue a number record anyhow.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Record record = recs[ 0 ];
|
|
||||||
|
|
||||||
if (record != null)
|
|
||||||
{
|
|
||||||
if (last_record != null) {
|
|
||||||
if (throwRecordEvent(last_record) == false && abortable == true) {
|
|
||||||
last_record = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last_record = record;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
last_record = recs[ k ]; // do to keep the algorithm homogeneous...you can't
|
||||||
|
} // actually continue a number record anyhow.
|
||||||
|
} else {
|
||||||
|
Record record = recs[ 0 ];
|
||||||
|
|
||||||
|
if (record != null) {
|
||||||
if (last_record != null) {
|
if (last_record != null) {
|
||||||
throwRecordEvent(last_record);
|
if (!processRecord(last_record)) {
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
last_record = record;
|
||||||
* create a record, if there are MUL records than multiple records
|
|
||||||
* are returned digested into the non-mul form.
|
|
||||||
*/
|
|
||||||
public static Record [] createRecord(RecordInputStream in)
|
|
||||||
{
|
|
||||||
Record retval = null;
|
|
||||||
Record[] realretval = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Constructor constructor =
|
|
||||||
( Constructor ) recordsMap.get(new Short(in.getSid()));
|
|
||||||
|
|
||||||
if (constructor != null)
|
|
||||||
{
|
|
||||||
retval = ( Record ) constructor.newInstance(new Object[]
|
|
||||||
{
|
|
||||||
in
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retval = new UnknownRecord(in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception introspectionException)
|
|
||||||
{
|
|
||||||
throw new RecordFormatException("Unable to construct record instance" , introspectionException);
|
|
||||||
}
|
|
||||||
if (retval instanceof RKRecord)
|
|
||||||
{
|
|
||||||
RKRecord rk = ( RKRecord ) retval;
|
|
||||||
NumberRecord num = new NumberRecord();
|
|
||||||
|
|
||||||
num.setColumn(rk.getColumn());
|
|
||||||
num.setRow(rk.getRow());
|
|
||||||
num.setXFIndex(rk.getXFIndex());
|
|
||||||
num.setValue(rk.getRKNumber());
|
|
||||||
retval = num;
|
|
||||||
}
|
|
||||||
else if (retval instanceof DBCellRecord)
|
|
||||||
{
|
|
||||||
retval = null;
|
|
||||||
}
|
|
||||||
else if (retval instanceof MulRKRecord)
|
|
||||||
{
|
|
||||||
MulRKRecord mrk = ( MulRKRecord ) retval;
|
|
||||||
|
|
||||||
realretval = new Record[ mrk.getNumColumns() ];
|
|
||||||
for (int k = 0; k < mrk.getNumColumns(); k++)
|
|
||||||
{
|
|
||||||
NumberRecord nr = new NumberRecord();
|
|
||||||
|
|
||||||
nr.setColumn(( short ) (k + mrk.getFirstColumn()));
|
|
||||||
nr.setRow(mrk.getRow());
|
|
||||||
nr.setXFIndex(mrk.getXFAt(k));
|
|
||||||
nr.setValue(mrk.getRKNumberAt(k));
|
|
||||||
realretval[ k ] = nr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (retval instanceof MulBlankRecord)
|
|
||||||
{
|
|
||||||
MulBlankRecord mb = ( MulBlankRecord ) retval;
|
|
||||||
|
|
||||||
realretval = new Record[ mb.getNumColumns() ];
|
|
||||||
for (int k = 0; k < mb.getNumColumns(); k++)
|
|
||||||
{
|
|
||||||
BlankRecord br = new BlankRecord();
|
|
||||||
|
|
||||||
br.setColumn(( short ) (k + mb.getFirstColumn()));
|
|
||||||
br.setRow(mb.getRow());
|
|
||||||
br.setXFIndex(mb.getXFAt(k));
|
|
||||||
realretval[ k ] = br;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (realretval == null)
|
|
||||||
{
|
|
||||||
realretval = new Record[ 1 ];
|
|
||||||
realretval[ 0 ] = retval;
|
|
||||||
}
|
|
||||||
return realretval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return an array of all the SIDS for all known records
|
|
||||||
*/
|
|
||||||
public static short [] getAllKnownRecordSIDs()
|
|
||||||
{
|
|
||||||
short[] results = new short[ recordsMap.size() ];
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (Iterator iterator = recordsMap.keySet().iterator();
|
|
||||||
iterator.hasNext(); )
|
|
||||||
{
|
|
||||||
Short sid = ( Short ) iterator.next();
|
|
||||||
|
|
||||||
results[ i++ ] = sid.shortValue();
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets the record constructors and sticks them in the map by SID
|
|
||||||
* @return map of SIDs to short,short,byte[] constructors for Record classes
|
|
||||||
* most of org.apache.poi.hssf.record.*
|
|
||||||
*/
|
|
||||||
private static Map recordsToMap(Class [] records)
|
|
||||||
{
|
|
||||||
Map result = new HashMap();
|
|
||||||
Constructor constructor;
|
|
||||||
|
|
||||||
for (int i = 0; i < records.length; i++)
|
|
||||||
{
|
|
||||||
Class record = null;
|
|
||||||
short sid = 0;
|
|
||||||
|
|
||||||
record = records[ i ];
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sid = record.getField("sid").getShort(null);
|
|
||||||
constructor = record.getConstructor(new Class[]
|
|
||||||
{
|
|
||||||
RecordInputStream.class
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception illegalArgumentException)
|
|
||||||
{
|
|
||||||
throw new RecordFormatException(
|
|
||||||
"Unable to determine record types");
|
|
||||||
}
|
|
||||||
result.put(new Short(sid), constructor);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ListenerWrapper just wraps an ERFListener and adds support for throwing
|
|
||||||
* the event to multiple SIDs
|
|
||||||
*/
|
|
||||||
class ListenerWrapper implements ERFListener {
|
|
||||||
private ERFListener listener;
|
|
||||||
private short[] sids;
|
|
||||||
private boolean abortable;
|
|
||||||
|
|
||||||
ListenerWrapper(ERFListener listener, short[] sids, boolean abortable) {
|
|
||||||
this.listener = listener;
|
|
||||||
this.sids = sids;
|
|
||||||
this.abortable = abortable;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean processRecord(Record rec)
|
|
||||||
{
|
|
||||||
boolean result = true;
|
|
||||||
for (int k = 0; k < sids.length; k++) {
|
|
||||||
if (sids[k] == rec.getSid()) {
|
|
||||||
result = listener.processRecord(rec);
|
|
||||||
|
|
||||||
if (abortable == true && result == false) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
if (last_record != null) {
|
||||||
|
processRecord(last_record);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -65,8 +65,7 @@ public class ModelFactory implements ERFListener
|
|||||||
* Start processing the Workbook stream into Model events.
|
* Start processing the Workbook stream into Model events.
|
||||||
*/
|
*/
|
||||||
public void run(InputStream stream) {
|
public void run(InputStream stream) {
|
||||||
EventRecordFactory factory = new EventRecordFactory(true);
|
EventRecordFactory factory = new EventRecordFactory(this,null);
|
||||||
factory.registerListener(this,null);
|
|
||||||
lastEOF = true;
|
lastEOF = true;
|
||||||
factory.processRecords(stream);
|
factory.processRecords(stream);
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,11 @@ package org.apache.poi.hssf.extractor;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.poi.POIOLE2TextExtractor;
|
import org.apache.poi.POIOLE2TextExtractor;
|
||||||
|
import org.apache.poi.hssf.usermodel.HeaderFooter;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFComment;
|
import org.apache.poi.hssf.usermodel.HSSFComment;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFFooter;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFHeader;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||||
@ -89,6 +92,13 @@ public class ExcelExtractor extends POIOLE2TextExtractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Header text, if there is any
|
||||||
|
if(sheet.getHeader() != null) {
|
||||||
|
text.append(
|
||||||
|
extractHeaderFooter(sheet.getHeader())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
int firstRow = sheet.getFirstRowNum();
|
int firstRow = sheet.getFirstRowNum();
|
||||||
int lastRow = sheet.getLastRowNum();
|
int lastRow = sheet.getLastRowNum();
|
||||||
for(int j=firstRow;j<=lastRow;j++) {
|
for(int j=firstRow;j<=lastRow;j++) {
|
||||||
@ -154,8 +164,37 @@ public class ExcelExtractor extends POIOLE2TextExtractor {
|
|||||||
// Finish off the row
|
// Finish off the row
|
||||||
text.append("\n");
|
text.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally Feader text, if there is any
|
||||||
|
if(sheet.getFooter() != null) {
|
||||||
|
text.append(
|
||||||
|
extractHeaderFooter(sheet.getFooter())
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return text.toString();
|
return text.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String extractHeaderFooter(HeaderFooter hf) {
|
||||||
|
StringBuffer text = new StringBuffer();
|
||||||
|
|
||||||
|
if(hf.getLeft() != null) {
|
||||||
|
text.append(hf.getLeft());
|
||||||
|
}
|
||||||
|
if(hf.getCenter() != null) {
|
||||||
|
if(text.length() > 0)
|
||||||
|
text.append("\t");
|
||||||
|
text.append(hf.getCenter());
|
||||||
|
}
|
||||||
|
if(hf.getRight() != null) {
|
||||||
|
if(text.length() > 0)
|
||||||
|
text.append("\t");
|
||||||
|
text.append(hf.getRight());
|
||||||
|
}
|
||||||
|
if(text.length() > 0)
|
||||||
|
text.append("\n");
|
||||||
|
|
||||||
|
return text.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
@ -16,293 +15,358 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|
||||||
|
|
||||||
package org.apache.poi.hssf.record;
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.*;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title: Record Factory<P>
|
* Title: Record Factory<P>
|
||||||
* Description: Takes a stream and outputs an array of Record objects.<P>
|
* Description: Takes a stream and outputs an array of Record objects.<P>
|
||||||
*
|
*
|
||||||
* @deprecated use {@link org.apache.poi.hssf.eventmodel.EventRecordFactory} instead
|
|
||||||
* @see org.apache.poi.hssf.eventmodel.EventRecordFactory
|
* @see org.apache.poi.hssf.eventmodel.EventRecordFactory
|
||||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||||
* @author Marc Johnson (mjohnson at apache dot org)
|
* @author Marc Johnson (mjohnson at apache dot org)
|
||||||
* @author Glen Stampoultzis (glens at apache.org)
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
* @author Csaba Nagy (ncsaba at yahoo dot com)
|
* @author Csaba Nagy (ncsaba at yahoo dot com)
|
||||||
*/
|
*/
|
||||||
|
public final class RecordFactory {
|
||||||
|
private static final int NUM_RECORDS = 512;
|
||||||
|
|
||||||
public class RecordFactory
|
private static final Class[] CONSTRUCTOR_ARGS = { RecordInputStream.class, };
|
||||||
{
|
|
||||||
private static int NUM_RECORDS = 10000;
|
|
||||||
private static final Class[] records;
|
|
||||||
|
|
||||||
static {
|
/**
|
||||||
records = new Class[]
|
* contains the classes for all the records we want to parse.<br/>
|
||||||
{
|
* Note - this most but not *every* subclass of Record.
|
||||||
BOFRecord.class, InterfaceHdrRecord.class, MMSRecord.class,
|
*/
|
||||||
InterfaceEndRecord.class, WriteAccessRecord.class,
|
private static final Class[] records = {
|
||||||
CodepageRecord.class, DSFRecord.class, TabIdRecord.class,
|
BackupRecord.class,
|
||||||
FnGroupCountRecord.class, WindowProtectRecord.class,
|
BlankRecord.class,
|
||||||
ProtectRecord.class, PasswordRecord.class, ProtectionRev4Record.class,
|
BOFRecord.class,
|
||||||
PasswordRev4Record.class, WindowOneRecord.class, BackupRecord.class,
|
BookBoolRecord.class,
|
||||||
HideObjRecord.class, DateWindow1904Record.class,
|
BoolErrRecord.class,
|
||||||
PrecisionRecord.class, RefreshAllRecord.class, BookBoolRecord.class,
|
BottomMarginRecord.class,
|
||||||
FontRecord.class, FormatRecord.class, ExtendedFormatRecord.class,
|
BoundSheetRecord.class,
|
||||||
StyleRecord.class, UseSelFSRecord.class, BoundSheetRecord.class,
|
CalcCountRecord.class,
|
||||||
CountryRecord.class, SSTRecord.class, ExtSSTRecord.class,
|
CalcModeRecord.class,
|
||||||
EOFRecord.class, IndexRecord.class, CalcModeRecord.class,
|
CFHeaderRecord.class,
|
||||||
CalcCountRecord.class, RefModeRecord.class, IterationRecord.class,
|
CFRuleRecord.class,
|
||||||
DeltaRecord.class, SaveRecalcRecord.class, PrintHeadersRecord.class,
|
ChartRecord.class,
|
||||||
PrintGridlinesRecord.class, GridsetRecord.class, GutsRecord.class,
|
ChartTitleFormatRecord.class,
|
||||||
DefaultRowHeightRecord.class, WSBoolRecord.class, HeaderRecord.class,
|
CodepageRecord.class,
|
||||||
FooterRecord.class, HCenterRecord.class, VCenterRecord.class,
|
ColumnInfoRecord.class,
|
||||||
PrintSetupRecord.class, DefaultColWidthRecord.class,
|
ContinueRecord.class,
|
||||||
DimensionsRecord.class, RowRecord.class, LabelSSTRecord.class,
|
CountryRecord.class,
|
||||||
RKRecord.class, NumberRecord.class, DBCellRecord.class,
|
CRNCountRecord.class,
|
||||||
WindowTwoRecord.class, SelectionRecord.class, ContinueRecord.class,
|
CRNRecord.class,
|
||||||
LabelRecord.class, BlankRecord.class, ColumnInfoRecord.class,
|
DateWindow1904Record.class,
|
||||||
MulRKRecord.class, MulBlankRecord.class, MergeCellsRecord.class,
|
DBCellRecord.class,
|
||||||
FormulaRecord.class, BoolErrRecord.class, ExternSheetRecord.class,
|
DefaultColWidthRecord.class,
|
||||||
NameRecord.class, LeftMarginRecord.class, RightMarginRecord.class,
|
DefaultRowHeightRecord.class,
|
||||||
TopMarginRecord.class, BottomMarginRecord.class,
|
DeltaRecord.class,
|
||||||
DrawingRecord.class, DrawingGroupRecord.class, DrawingSelectionRecord.class,
|
DimensionsRecord.class,
|
||||||
ObjRecord.class, TextObjectRecord.class,
|
DrawingGroupRecord.class,
|
||||||
PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class,
|
DrawingRecord.class,
|
||||||
HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class,
|
DrawingSelectionRecord.class,
|
||||||
WriteProtectRecord.class, FilePassRecord.class, PaneRecord.class,
|
DSFRecord.class,
|
||||||
NoteRecord.class, ObjectProtectRecord.class, ScenarioProtectRecord.class,
|
DVALRecord.class,
|
||||||
FileSharingRecord.class, ChartTitleFormatRecord.class,
|
DVRecord.class,
|
||||||
DVRecord.class, DVALRecord.class, UncalcedRecord.class,
|
EOFRecord.class,
|
||||||
ChartRecord.class, LegendRecord.class, ChartTitleFormatRecord.class,
|
ExtendedFormatRecord.class,
|
||||||
SeriesRecord.class, SeriesTextRecord.class,
|
ExternalNameRecord.class,
|
||||||
HyperlinkRecord.class,
|
ExternSheetRecord.class,
|
||||||
ExternalNameRecord.class, // TODO - same changes in non-@deprecated version of this class
|
ExtSSTRecord.class,
|
||||||
SupBookRecord.class,
|
FilePassRecord.class,
|
||||||
CRNCountRecord.class,
|
FileSharingRecord.class,
|
||||||
CRNRecord.class,
|
FnGroupCountRecord.class,
|
||||||
CFHeaderRecord.class,
|
FontRecord.class,
|
||||||
CFRuleRecord.class,
|
FooterRecord.class,
|
||||||
TableRecord.class
|
FormatRecord.class,
|
||||||
};
|
FormulaRecord.class,
|
||||||
}
|
GridsetRecord.class,
|
||||||
private static Map recordsMap = recordsToMap(records);
|
GutsRecord.class,
|
||||||
|
HCenterRecord.class,
|
||||||
|
HeaderRecord.class,
|
||||||
|
HideObjRecord.class,
|
||||||
|
HorizontalPageBreakRecord.class,
|
||||||
|
HyperlinkRecord.class,
|
||||||
|
IndexRecord.class,
|
||||||
|
InterfaceEndRecord.class,
|
||||||
|
InterfaceHdrRecord.class,
|
||||||
|
IterationRecord.class,
|
||||||
|
LabelRecord.class,
|
||||||
|
LabelSSTRecord.class,
|
||||||
|
LeftMarginRecord.class,
|
||||||
|
LegendRecord.class,
|
||||||
|
MergeCellsRecord.class,
|
||||||
|
MMSRecord.class,
|
||||||
|
MulBlankRecord.class,
|
||||||
|
MulRKRecord.class,
|
||||||
|
NameRecord.class,
|
||||||
|
NoteRecord.class,
|
||||||
|
NumberRecord.class,
|
||||||
|
ObjectProtectRecord.class,
|
||||||
|
ObjRecord.class,
|
||||||
|
PaletteRecord.class,
|
||||||
|
PaneRecord.class,
|
||||||
|
PasswordRecord.class,
|
||||||
|
PasswordRev4Record.class,
|
||||||
|
PrecisionRecord.class,
|
||||||
|
PrintGridlinesRecord.class,
|
||||||
|
PrintHeadersRecord.class,
|
||||||
|
PrintSetupRecord.class,
|
||||||
|
ProtectionRev4Record.class,
|
||||||
|
ProtectRecord.class,
|
||||||
|
RecalcIdRecord.class,
|
||||||
|
RefModeRecord.class,
|
||||||
|
RefreshAllRecord.class,
|
||||||
|
RightMarginRecord.class,
|
||||||
|
RKRecord.class,
|
||||||
|
RowRecord.class,
|
||||||
|
SaveRecalcRecord.class,
|
||||||
|
ScenarioProtectRecord.class,
|
||||||
|
SelectionRecord.class,
|
||||||
|
SeriesRecord.class,
|
||||||
|
SeriesTextRecord.class,
|
||||||
|
SharedFormulaRecord.class,
|
||||||
|
SSTRecord.class,
|
||||||
|
StringRecord.class,
|
||||||
|
StyleRecord.class,
|
||||||
|
SupBookRecord.class,
|
||||||
|
TabIdRecord.class,
|
||||||
|
TableRecord.class,
|
||||||
|
TextObjectRecord.class,
|
||||||
|
TopMarginRecord.class,
|
||||||
|
UncalcedRecord.class,
|
||||||
|
UseSelFSRecord.class,
|
||||||
|
VCenterRecord.class,
|
||||||
|
VerticalPageBreakRecord.class,
|
||||||
|
WindowOneRecord.class,
|
||||||
|
WindowProtectRecord.class,
|
||||||
|
WindowTwoRecord.class,
|
||||||
|
WriteAccessRecord.class,
|
||||||
|
WriteProtectRecord.class,
|
||||||
|
WSBoolRecord.class,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* changes the default capacity (10000) to handle larger files
|
* cache of the recordsToMap();
|
||||||
*/
|
*/
|
||||||
|
private static Map recordsMap = recordsToMap(records);
|
||||||
|
|
||||||
public static void setCapacity(int capacity)
|
private static short[] _allKnownRecordSIDs;
|
||||||
{
|
|
||||||
NUM_RECORDS = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an array of records from an input stream
|
* create a record, if there are MUL records than multiple records
|
||||||
*
|
* are returned digested into the non-mul form.
|
||||||
* @param in the InputStream from which the records will be
|
*/
|
||||||
* obtained
|
public static Record [] createRecord(RecordInputStream in) {
|
||||||
*
|
Constructor constructor = (Constructor) recordsMap.get(new Short(in.getSid()));
|
||||||
* @return an array of Records created from the InputStream
|
|
||||||
*
|
|
||||||
* @exception RecordFormatException on error processing the
|
|
||||||
* InputStream
|
|
||||||
*/
|
|
||||||
|
|
||||||
public static List createRecords(InputStream in)
|
if (constructor == null) {
|
||||||
throws RecordFormatException
|
return new Record[] { new UnknownRecord(in), };
|
||||||
{
|
}
|
||||||
ArrayList records = new ArrayList(NUM_RECORDS);
|
|
||||||
|
|
||||||
RecordInputStream recStream = new RecordInputStream(in);
|
Record retval;
|
||||||
DrawingRecord lastDrawingRecord = new DrawingRecord( );
|
|
||||||
Record lastRecord = null;
|
|
||||||
while (recStream.hasNextRecord()) {
|
|
||||||
recStream.nextRecord();
|
|
||||||
if (recStream.getSid() != 0)
|
|
||||||
{
|
|
||||||
Record[] recs = createRecord(recStream); // handle MulRK records
|
|
||||||
|
|
||||||
if (recs.length > 1)
|
try {
|
||||||
{
|
retval = ( Record ) constructor.newInstance(new Object[] { in });
|
||||||
for (int k = 0; k < recs.length; k++)
|
} catch (InvocationTargetException e) {
|
||||||
{
|
throw new RecordFormatException("Unable to construct record instance" , e.getTargetException());
|
||||||
records.add(
|
} catch (IllegalArgumentException e) {
|
||||||
recs[ k ]); // these will be number records
|
throw new RuntimeException(e);
|
||||||
}
|
} catch (InstantiationException e) {
|
||||||
}
|
throw new RuntimeException(e);
|
||||||
else
|
} catch (IllegalAccessException e) {
|
||||||
{
|
throw new RuntimeException(e);
|
||||||
Record record = recs[ 0 ];
|
}
|
||||||
|
|
||||||
if (record != null)
|
if (retval instanceof RKRecord) {
|
||||||
{
|
// RK record is a slightly smaller alternative to NumberRecord
|
||||||
if (record.getSid() == DrawingGroupRecord.sid
|
// POI likes NumberRecord better
|
||||||
&& lastRecord instanceof DrawingGroupRecord)
|
RKRecord rk = ( RKRecord ) retval;
|
||||||
{
|
NumberRecord num = new NumberRecord();
|
||||||
DrawingGroupRecord lastDGRecord = (DrawingGroupRecord) lastRecord;
|
|
||||||
lastDGRecord.join((AbstractEscherHolderRecord) record);
|
|
||||||
}
|
|
||||||
else if (record.getSid() == ContinueRecord.sid &&
|
|
||||||
((lastRecord instanceof ObjRecord) || (lastRecord instanceof TextObjectRecord))) {
|
|
||||||
// Drawing records have a very strange continue behaviour.
|
|
||||||
//There can actually be OBJ records mixed between the continues.
|
|
||||||
lastDrawingRecord.processContinueRecord( ((ContinueRecord)record).getData() );
|
|
||||||
//we must rememeber the position of the continue record.
|
|
||||||
//in the serialization procedure the original structure of records must be preserved
|
|
||||||
records.add(record);
|
|
||||||
} else if (record.getSid() == ContinueRecord.sid &&
|
|
||||||
(lastRecord instanceof DrawingGroupRecord)) {
|
|
||||||
((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
|
|
||||||
} else if (record.getSid() == ContinueRecord.sid &&
|
|
||||||
(lastRecord instanceof StringRecord)) {
|
|
||||||
((StringRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
|
|
||||||
} else if (record.getSid() == ContinueRecord.sid) {
|
|
||||||
if (lastRecord instanceof UnknownRecord) {
|
|
||||||
//Gracefully handle records that we dont know about,
|
|
||||||
//that happen to be continued
|
|
||||||
records.add(record);
|
|
||||||
} else
|
|
||||||
throw new RecordFormatException("Unhandled Continue Record");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lastRecord = record;
|
|
||||||
if (record instanceof DrawingRecord)
|
|
||||||
lastDrawingRecord = (DrawingRecord) record;
|
|
||||||
records.add(record);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return records;
|
num.setColumn(rk.getColumn());
|
||||||
}
|
num.setRow(rk.getRow());
|
||||||
|
num.setXFIndex(rk.getXFIndex());
|
||||||
|
num.setValue(rk.getRKNumber());
|
||||||
|
return new Record[] { num, };
|
||||||
|
}
|
||||||
|
if (retval instanceof DBCellRecord) {
|
||||||
|
// Not needed by POI. Regenerated from scratch by POI when spreadsheet is written
|
||||||
|
return new Record[] { null, };
|
||||||
|
}
|
||||||
|
// expand multiple records where necessary
|
||||||
|
if (retval instanceof MulRKRecord) {
|
||||||
|
MulRKRecord mrk = ( MulRKRecord ) retval;
|
||||||
|
|
||||||
public static Record [] createRecord(RecordInputStream in)
|
Record[] mulRecs = new Record[ mrk.getNumColumns() ];
|
||||||
{
|
for (int k = 0; k < mrk.getNumColumns(); k++) {
|
||||||
Record retval;
|
NumberRecord nr = new NumberRecord();
|
||||||
Record[] realretval = null;
|
|
||||||
|
|
||||||
try
|
nr.setColumn(( short ) (k + mrk.getFirstColumn()));
|
||||||
{
|
nr.setRow(mrk.getRow());
|
||||||
Constructor constructor =
|
nr.setXFIndex(mrk.getXFAt(k));
|
||||||
( Constructor ) recordsMap.get(new Short(in.getSid()));
|
nr.setValue(mrk.getRKNumberAt(k));
|
||||||
|
mulRecs[ k ] = nr;
|
||||||
|
}
|
||||||
|
return mulRecs;
|
||||||
|
}
|
||||||
|
if (retval instanceof MulBlankRecord) {
|
||||||
|
MulBlankRecord mb = ( MulBlankRecord ) retval;
|
||||||
|
|
||||||
if (constructor != null)
|
Record[] mulRecs = new Record[ mb.getNumColumns() ];
|
||||||
{
|
for (int k = 0; k < mb.getNumColumns(); k++) {
|
||||||
retval = ( Record ) constructor.newInstance(new Object[]
|
BlankRecord br = new BlankRecord();
|
||||||
{
|
|
||||||
in
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retval = new UnknownRecord(in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception introspectionException)
|
|
||||||
{
|
|
||||||
throw new RecordFormatException("Unable to construct record instance",introspectionException);
|
|
||||||
}
|
|
||||||
if (retval instanceof RKRecord)
|
|
||||||
{
|
|
||||||
RKRecord rk = ( RKRecord ) retval;
|
|
||||||
NumberRecord num = new NumberRecord();
|
|
||||||
|
|
||||||
num.setColumn(rk.getColumn());
|
br.setColumn(( short ) (k + mb.getFirstColumn()));
|
||||||
num.setRow(rk.getRow());
|
br.setRow(mb.getRow());
|
||||||
num.setXFIndex(rk.getXFIndex());
|
br.setXFIndex(mb.getXFAt(k));
|
||||||
num.setValue(rk.getRKNumber());
|
mulRecs[ k ] = br;
|
||||||
retval = num;
|
}
|
||||||
}
|
return mulRecs;
|
||||||
else if (retval instanceof DBCellRecord)
|
}
|
||||||
{
|
return new Record[] { retval, };
|
||||||
retval = null;
|
}
|
||||||
}
|
|
||||||
else if (retval instanceof MulRKRecord)
|
|
||||||
{
|
|
||||||
MulRKRecord mrk = ( MulRKRecord ) retval;
|
|
||||||
|
|
||||||
realretval = new Record[ mrk.getNumColumns() ];
|
/**
|
||||||
for (int k = 0; k < mrk.getNumColumns(); k++)
|
* @return an array of all the SIDS for all known records
|
||||||
{
|
*/
|
||||||
NumberRecord nr = new NumberRecord();
|
public static short[] getAllKnownRecordSIDs() {
|
||||||
|
if (_allKnownRecordSIDs == null) {
|
||||||
|
short[] results = new short[ recordsMap.size() ];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
nr.setColumn(( short ) (k + mrk.getFirstColumn()));
|
for (Iterator iterator = recordsMap.keySet().iterator(); iterator.hasNext(); ) {
|
||||||
nr.setRow(mrk.getRow());
|
Short sid = (Short) iterator.next();
|
||||||
nr.setXFIndex(mrk.getXFAt(k));
|
|
||||||
nr.setValue(mrk.getRKNumberAt(k));
|
|
||||||
realretval[ k ] = nr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (retval instanceof MulBlankRecord)
|
|
||||||
{
|
|
||||||
MulBlankRecord mb = ( MulBlankRecord ) retval;
|
|
||||||
|
|
||||||
realretval = new Record[ mb.getNumColumns() ];
|
results[i++] = sid.shortValue();
|
||||||
for (int k = 0; k < mb.getNumColumns(); k++)
|
}
|
||||||
{
|
Arrays.sort(results);
|
||||||
BlankRecord br = new BlankRecord();
|
_allKnownRecordSIDs = results;
|
||||||
|
}
|
||||||
|
|
||||||
br.setColumn(( short ) (k + mb.getFirstColumn()));
|
return (short[]) _allKnownRecordSIDs.clone();
|
||||||
br.setRow(mb.getRow());
|
}
|
||||||
br.setXFIndex(mb.getXFAt(k));
|
|
||||||
realretval[ k ] = br;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (realretval == null)
|
|
||||||
{
|
|
||||||
realretval = new Record[ 1 ];
|
|
||||||
realretval[ 0 ] = retval;
|
|
||||||
}
|
|
||||||
return realretval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static short [] getAllKnownRecordSIDs()
|
/**
|
||||||
{
|
* gets the record constructors and sticks them in the map by SID
|
||||||
short[] results = new short[ recordsMap.size() ];
|
* @return map of SIDs to short,short,byte[] constructors for Record classes
|
||||||
int i = 0;
|
* most of org.apache.poi.hssf.record.*
|
||||||
|
*/
|
||||||
|
private static Map recordsToMap(Class [] records) {
|
||||||
|
Map result = new HashMap();
|
||||||
|
Set uniqueRecClasses = new HashSet(records.length * 3 / 2);
|
||||||
|
|
||||||
for (Iterator iterator = recordsMap.keySet().iterator();
|
for (int i = 0; i < records.length; i++) {
|
||||||
iterator.hasNext(); )
|
|
||||||
{
|
|
||||||
Short sid = ( Short ) iterator.next();
|
|
||||||
|
|
||||||
results[ i++ ] = sid.shortValue();
|
Class recClass = records[ i ];
|
||||||
}
|
if(!Record.class.isAssignableFrom(recClass)) {
|
||||||
return results;
|
throw new RuntimeException("Invalid record sub-class (" + recClass.getName() + ")");
|
||||||
}
|
}
|
||||||
|
if(Modifier.isAbstract(recClass.getModifiers())) {
|
||||||
|
throw new RuntimeException("Invalid record class (" + recClass.getName() + ") - must not be abstract");
|
||||||
|
}
|
||||||
|
if(!uniqueRecClasses.add(recClass)) {
|
||||||
|
throw new RuntimeException("duplicate record class (" + recClass.getName() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
private static Map recordsToMap(Class [] records)
|
short sid;
|
||||||
{
|
Constructor constructor;
|
||||||
Map result = new HashMap();
|
try {
|
||||||
Constructor constructor;
|
sid = recClass.getField("sid").getShort(null);
|
||||||
|
constructor = recClass.getConstructor(CONSTRUCTOR_ARGS);
|
||||||
|
} catch (Exception illegalArgumentException) {
|
||||||
|
throw new RecordFormatException(
|
||||||
|
"Unable to determine record types");
|
||||||
|
}
|
||||||
|
Short key = new Short(sid);
|
||||||
|
if (result.containsKey(key)) {
|
||||||
|
Class prev = (Class)result.get(key);
|
||||||
|
throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase()
|
||||||
|
+ " for classes (" + recClass.getName() + ") and (" + prev.getName() + ")");
|
||||||
|
}
|
||||||
|
result.put(key, constructor);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < records.length; i++)
|
/**
|
||||||
{
|
* Create an array of records from an input stream
|
||||||
Class record;
|
*
|
||||||
short sid;
|
* @param in the InputStream from which the records will be obtained
|
||||||
|
*
|
||||||
|
* @return an array of Records created from the InputStream
|
||||||
|
*
|
||||||
|
* @exception RecordFormatException on error processing the InputStream
|
||||||
|
*/
|
||||||
|
public static List createRecords(InputStream in) throws RecordFormatException {
|
||||||
|
|
||||||
record = records[ i ];
|
List records = new ArrayList(NUM_RECORDS);
|
||||||
try
|
|
||||||
{
|
RecordInputStream recStream = new RecordInputStream(in);
|
||||||
sid = record.getField("sid").getShort(null);
|
DrawingRecord lastDrawingRecord = new DrawingRecord( );
|
||||||
constructor = record.getConstructor(new Class[]
|
Record lastRecord = null;
|
||||||
{
|
while (recStream.hasNextRecord()) {
|
||||||
RecordInputStream.class
|
recStream.nextRecord();
|
||||||
});
|
if (recStream.getSid() != 0) {
|
||||||
}
|
Record[] recs = createRecord(recStream); // handle MulRK records
|
||||||
catch (Exception illegalArgumentException)
|
|
||||||
{
|
if (recs.length > 1) {
|
||||||
throw new RecordFormatException(
|
for (int k = 0; k < recs.length; k++) {
|
||||||
"Unable to determine record types", illegalArgumentException);
|
records.add(recs[ k ]); // these will be number records
|
||||||
}
|
}
|
||||||
result.put(new Short(sid), constructor);
|
} else {
|
||||||
}
|
Record record = recs[ 0 ];
|
||||||
return result;
|
|
||||||
}
|
if (record != null) {
|
||||||
|
if (record.getSid() == DrawingGroupRecord.sid
|
||||||
|
&& lastRecord instanceof DrawingGroupRecord) {
|
||||||
|
DrawingGroupRecord lastDGRecord = (DrawingGroupRecord) lastRecord;
|
||||||
|
lastDGRecord.join((AbstractEscherHolderRecord) record);
|
||||||
|
} else if (record.getSid() == ContinueRecord.sid &&
|
||||||
|
((lastRecord instanceof ObjRecord) || (lastRecord instanceof TextObjectRecord))) {
|
||||||
|
// Drawing records have a very strange continue behaviour.
|
||||||
|
//There can actually be OBJ records mixed between the continues.
|
||||||
|
lastDrawingRecord.processContinueRecord( ((ContinueRecord)record).getData() );
|
||||||
|
//we must remember the position of the continue record.
|
||||||
|
//in the serialization procedure the original structure of records must be preserved
|
||||||
|
records.add(record);
|
||||||
|
} else if (record.getSid() == ContinueRecord.sid &&
|
||||||
|
(lastRecord instanceof DrawingGroupRecord)) {
|
||||||
|
((DrawingGroupRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
|
||||||
|
} else if (record.getSid() == ContinueRecord.sid &&
|
||||||
|
(lastRecord instanceof StringRecord)) {
|
||||||
|
((StringRecord)lastRecord).processContinueRecord(((ContinueRecord)record).getData());
|
||||||
|
} else if (record.getSid() == ContinueRecord.sid) {
|
||||||
|
if (lastRecord instanceof UnknownRecord) {
|
||||||
|
//Gracefully handle records that we dont know about,
|
||||||
|
//that happen to be continued
|
||||||
|
records.add(record);
|
||||||
|
} else
|
||||||
|
throw new RecordFormatException("Unhandled Continue Record");
|
||||||
|
} else {
|
||||||
|
lastRecord = record;
|
||||||
|
if (record instanceof DrawingRecord) {
|
||||||
|
lastDrawingRecord = (DrawingRecord) record;
|
||||||
|
}
|
||||||
|
records.add(record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return records;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,7 @@ import org.apache.poi.ss.usermodel.Footer;
|
|||||||
* <P>
|
* <P>
|
||||||
* @author Shawn Laubach (slaubach at apache dot org)
|
* @author Shawn Laubach (slaubach at apache dot org)
|
||||||
*/
|
*/
|
||||||
public class HSSFFooter implements Footer {
|
public class HSSFFooter implements Footer, HeaderFooter {
|
||||||
|
|
||||||
FooterRecord footerRecord;
|
FooterRecord footerRecord;
|
||||||
String left;
|
String left;
|
||||||
String center;
|
String center;
|
||||||
|
@ -33,7 +33,7 @@ import org.apache.poi.ss.usermodel.Header;
|
|||||||
*
|
*
|
||||||
* @author Shawn Laubach (slaubach at apache dot org)
|
* @author Shawn Laubach (slaubach at apache dot org)
|
||||||
*/
|
*/
|
||||||
public class HSSFHeader implements Header
|
public class HSSFHeader implements Header, HeaderFooter
|
||||||
{
|
{
|
||||||
|
|
||||||
HeaderRecord headerRecord;
|
HeaderRecord headerRecord;
|
||||||
|
@ -34,7 +34,6 @@ import org.apache.poi.ddf.EscherBSERecord;
|
|||||||
import org.apache.poi.ddf.EscherBitmapBlip;
|
import org.apache.poi.ddf.EscherBitmapBlip;
|
||||||
import org.apache.poi.ddf.EscherBlipRecord;
|
import org.apache.poi.ddf.EscherBlipRecord;
|
||||||
import org.apache.poi.ddf.EscherRecord;
|
import org.apache.poi.ddf.EscherRecord;
|
||||||
import org.apache.poi.hssf.eventmodel.EventRecordFactory;
|
|
||||||
import org.apache.poi.hssf.model.Sheet;
|
import org.apache.poi.hssf.model.Sheet;
|
||||||
import org.apache.poi.hssf.model.Workbook;
|
import org.apache.poi.hssf.model.Workbook;
|
||||||
import org.apache.poi.hssf.record.AbstractEscherHolderRecord;
|
import org.apache.poi.hssf.record.AbstractEscherHolderRecord;
|
||||||
@ -264,8 +263,6 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
|
|||||||
// it happens to be spelled.
|
// it happens to be spelled.
|
||||||
InputStream stream = directory.createDocumentInputStream(workbookName);
|
InputStream stream = directory.createDocumentInputStream(workbookName);
|
||||||
|
|
||||||
EventRecordFactory factory = new EventRecordFactory();
|
|
||||||
|
|
||||||
List records = RecordFactory.createRecords(stream);
|
List records = RecordFactory.createRecords(stream);
|
||||||
|
|
||||||
workbook = Workbook.createWorkbook(records);
|
workbook = Workbook.createWorkbook(records);
|
||||||
|
24
src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java
Normal file
24
src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.
|
||||||
|
==================================================================== */
|
||||||
|
package org.apache.poi.hssf.usermodel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common interface for {@link HSSFHeader} and
|
||||||
|
* {@link HSSFFooter}.
|
||||||
|
*/
|
||||||
|
public interface HeaderFooter extends org.apache.poi.ss.usermodel.HeaderFooter {
|
||||||
|
}
|
32
src/java/org/apache/poi/ss/usermodel/HeaderFooter.java
Normal file
32
src/java/org/apache/poi/ss/usermodel/HeaderFooter.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.
|
||||||
|
==================================================================== */
|
||||||
|
package org.apache.poi.ss.usermodel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common interface for {@link Header} and
|
||||||
|
* {@link Footer}.
|
||||||
|
*/
|
||||||
|
public interface HeaderFooter {
|
||||||
|
public String getLeft();
|
||||||
|
public void setLeft( String newLeft );
|
||||||
|
|
||||||
|
public String getCenter();
|
||||||
|
public void setCenter( String newCenter );
|
||||||
|
|
||||||
|
public String getRight();
|
||||||
|
public void setRight( String newRight );
|
||||||
|
}
|
BIN
src/testcases/org/apache/poi/hssf/data/45538_classic_Footer.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/45538_classic_Footer.xls
Normal file
Binary file not shown.
BIN
src/testcases/org/apache/poi/hssf/data/45538_classic_Header.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/45538_classic_Header.xls
Normal file
Binary file not shown.
BIN
src/testcases/org/apache/poi/hssf/data/45538_form_Footer.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/45538_form_Footer.xls
Normal file
Binary file not shown.
BIN
src/testcases/org/apache/poi/hssf/data/45538_form_Header.xls
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/45538_form_Header.xls
Normal file
Binary file not shown.
@ -18,80 +18,24 @@
|
|||||||
package org.apache.poi.hssf.eventmodel;
|
package org.apache.poi.hssf.eventmodel;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.BOFRecord;
|
|
||||||
import org.apache.poi.hssf.record.EOFRecord;
|
|
||||||
import org.apache.poi.hssf.record.Record;
|
|
||||||
import org.apache.poi.hssf.record.UnknownRecord;
|
|
||||||
import org.apache.poi.hssf.record.ContinueRecord;
|
|
||||||
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.BOFRecord;
|
||||||
|
import org.apache.poi.hssf.record.ContinueRecord;
|
||||||
|
import org.apache.poi.hssf.record.EOFRecord;
|
||||||
|
import org.apache.poi.hssf.record.Record;
|
||||||
|
import org.apache.poi.hssf.record.RecordFactory;
|
||||||
|
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
|
||||||
|
import org.apache.poi.hssf.record.UnknownRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enclosing_type describe the purpose here
|
* enclosing_type describe the purpose here
|
||||||
*
|
*
|
||||||
* @author Andrew C. Oliver acoliver@apache.org
|
* @author Andrew C. Oliver acoliver@apache.org
|
||||||
* @author Csaba Nagy (ncsaba at yahoo dot com)
|
* @author Csaba Nagy (ncsaba at yahoo dot com)
|
||||||
*/
|
*/
|
||||||
public class TestEventRecordFactory extends TestCase
|
public final class TestEventRecordFactory extends TestCase {
|
||||||
{
|
|
||||||
boolean wascalled;
|
|
||||||
|
|
||||||
private EventRecordFactory factory;
|
|
||||||
/**
|
|
||||||
* Constructor for TestEventRecordFactory.
|
|
||||||
* @param arg0
|
|
||||||
*/
|
|
||||||
public TestEventRecordFactory(String arg0)
|
|
||||||
{
|
|
||||||
super(arg0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
junit.textui.TestRunner.run(TestEventRecordFactory.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setUp() throws Exception
|
|
||||||
{
|
|
||||||
super.setUp();
|
|
||||||
factory = new EventRecordFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void tearDown() throws Exception
|
|
||||||
{
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tests that a listener can be registered and that once
|
|
||||||
* registered can be returned as expected.
|
|
||||||
*/
|
|
||||||
public void testRegisterListener()
|
|
||||||
{
|
|
||||||
factory.registerListener(new ERFListener() {
|
|
||||||
public boolean processRecord(Record rec) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},null);
|
|
||||||
|
|
||||||
Iterator i = factory.listeners();
|
|
||||||
assertTrue("iterator must have one",i.hasNext());
|
|
||||||
|
|
||||||
factory.registerListener(new ERFListener() {
|
|
||||||
public boolean processRecord(Record rec) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},null);
|
|
||||||
|
|
||||||
i = factory.listeners();
|
|
||||||
|
|
||||||
i.next();
|
|
||||||
assertTrue("iterator must have two",i.hasNext());
|
|
||||||
factory = new EventRecordFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tests that the records can be processed and properly return
|
* tests that the records can be processed and properly return
|
||||||
@ -99,17 +43,17 @@ public class TestEventRecordFactory extends TestCase
|
|||||||
*/
|
*/
|
||||||
public void testProcessRecords()
|
public void testProcessRecords()
|
||||||
{
|
{
|
||||||
byte[] bytes = null;
|
final boolean[] wascalled = { false, }; // hack to pass boolean by ref into inner class
|
||||||
int offset = 0;
|
|
||||||
//boolean wascalled = false;
|
ERFListener listener = new ERFListener() {
|
||||||
factory.registerListener(new ERFListener() {
|
|
||||||
public boolean processRecord(Record rec) {
|
public boolean processRecord(Record rec) {
|
||||||
wascalled = true;
|
wascalled[0] = true;
|
||||||
assertTrue("must be BOFRecord got SID="+rec.getSid(),
|
assertTrue("must be BOFRecord got SID="+rec.getSid(),
|
||||||
(rec.getSid() == BOFRecord.sid));
|
(rec.getSid() == BOFRecord.sid));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}, new short[] {BOFRecord.sid});
|
};
|
||||||
|
EventRecordFactory factory = new EventRecordFactory(listener, new short[] {BOFRecord.sid});
|
||||||
|
|
||||||
BOFRecord bof = new BOFRecord();
|
BOFRecord bof = new BOFRecord();
|
||||||
bof.setBuild((short)0);
|
bof.setBuild((short)0);
|
||||||
@ -120,23 +64,20 @@ public class TestEventRecordFactory extends TestCase
|
|||||||
bof.setHistoryBitMask(BOFRecord.HISTORY_MASK);
|
bof.setHistoryBitMask(BOFRecord.HISTORY_MASK);
|
||||||
|
|
||||||
EOFRecord eof = new EOFRecord();
|
EOFRecord eof = new EOFRecord();
|
||||||
bytes = new byte[bof.getRecordSize() + eof.getRecordSize()];
|
byte[] bytes = new byte[bof.getRecordSize() + eof.getRecordSize()];
|
||||||
|
int offset = 0;
|
||||||
offset = bof.serialize(offset,bytes);
|
offset = bof.serialize(offset,bytes);
|
||||||
offset = eof.serialize(offset,bytes);
|
offset = eof.serialize(offset,bytes);
|
||||||
|
|
||||||
factory.processRecords(new ByteArrayInputStream(bytes));
|
factory.processRecords(new ByteArrayInputStream(bytes));
|
||||||
assertTrue("The record listener must be called",wascalled);
|
assertTrue("The record listener must be called", wascalled[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tests that the create record function returns a properly
|
* tests that the create record function returns a properly
|
||||||
* constructed record in the simple case.
|
* constructed record in the simple case.
|
||||||
*/
|
*/
|
||||||
public void testCreateRecord()
|
public void testCreateRecord() {
|
||||||
{
|
|
||||||
byte[] bytes = null;
|
|
||||||
byte[] nbytes = null;
|
|
||||||
Record[] records = null;
|
|
||||||
BOFRecord bof = new BOFRecord();
|
BOFRecord bof = new BOFRecord();
|
||||||
bof.setBuild((short)0);
|
bof.setBuild((short)0);
|
||||||
bof.setBuildYear((short)1999);
|
bof.setBuildYear((short)1999);
|
||||||
@ -145,11 +86,11 @@ public class TestEventRecordFactory extends TestCase
|
|||||||
bof.setVersion((short)0x06);
|
bof.setVersion((short)0x06);
|
||||||
bof.setHistoryBitMask(BOFRecord.HISTORY_MASK);
|
bof.setHistoryBitMask(BOFRecord.HISTORY_MASK);
|
||||||
|
|
||||||
bytes = bof.serialize();
|
byte[] bytes = bof.serialize();
|
||||||
nbytes = new byte[bytes.length - 4];
|
byte[] nbytes = new byte[bytes.length - 4];
|
||||||
System.arraycopy(bytes,4,nbytes,0,nbytes.length);
|
System.arraycopy(bytes,4,nbytes,0,nbytes.length);
|
||||||
|
|
||||||
records = factory.createRecord(new TestcaseRecordInputStream(bof.getSid(),(short)nbytes.length,nbytes));
|
Record[] records = RecordFactory.createRecord(new TestcaseRecordInputStream(bof.getSid(),(short)nbytes.length,nbytes));
|
||||||
|
|
||||||
assertTrue("record.length must be 1, was ="+records.length,records.length == 1);
|
assertTrue("record.length must be 1, was ="+records.length,records.length == 1);
|
||||||
assertTrue("record is the same", compareRec(bof,records[0]));
|
assertTrue("record is the same", compareRec(bof,records[0]));
|
||||||
@ -162,24 +103,19 @@ public class TestEventRecordFactory extends TestCase
|
|||||||
* @param second the second record to compare
|
* @param second the second record to compare
|
||||||
* @return boolean whether or not the record where equal
|
* @return boolean whether or not the record where equal
|
||||||
*/
|
*/
|
||||||
private boolean compareRec(Record first, Record second)
|
private static boolean compareRec(Record first, Record second) {
|
||||||
{
|
|
||||||
boolean retval = true;
|
|
||||||
byte[] rec1 = first.serialize();
|
byte[] rec1 = first.serialize();
|
||||||
byte[] rec2 = second.serialize();
|
byte[] rec2 = second.serialize();
|
||||||
|
|
||||||
if (rec1.length == rec2.length) {
|
if (rec1.length != rec2.length) {
|
||||||
for (int k=0; k<rec1.length; k++) {
|
return false;
|
||||||
if (rec1[k] != rec2[k]) {
|
|
||||||
retval = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
retval = false;
|
|
||||||
}
|
}
|
||||||
|
for (int k=0; k<rec1.length; k++) {
|
||||||
return retval;
|
if (rec1[k] != rec2[k]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,10 +138,8 @@ public class TestEventRecordFactory extends TestCase
|
|||||||
* FAILURE: The wrong records are created or contain the wrong values <P>
|
* FAILURE: The wrong records are created or contain the wrong values <P>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void testContinuedUnknownRecord()
|
public void testContinuedUnknownRecord() {
|
||||||
{
|
final byte[] data = {
|
||||||
final byte[] data = new byte[]
|
|
||||||
{
|
|
||||||
0, -1, 0, 0, // an unknown record with 0 length
|
0, -1, 0, 0, // an unknown record with 0 length
|
||||||
0x3C , 0, 3, 0, 1, 2, 3, // a continuation record with 3 bytes of data
|
0x3C , 0, 3, 0, 1, 2, 3, // a continuation record with 3 bytes of data
|
||||||
0x3C , 0, 1, 0, 4 // one more continuation record with 1 byte of data
|
0x3C , 0, 1, 0, 4 // one more continuation record with 1 byte of data
|
||||||
@ -213,8 +147,7 @@ public class TestEventRecordFactory extends TestCase
|
|||||||
|
|
||||||
final int[] recCnt = { 0 };
|
final int[] recCnt = { 0 };
|
||||||
final int[] offset = { 0 };
|
final int[] offset = { 0 };
|
||||||
factory.registerListener(
|
ERFListener listener = new ERFListener() {
|
||||||
new ERFListener() {
|
|
||||||
private String[] expectedRecordTypes = {
|
private String[] expectedRecordTypes = {
|
||||||
UnknownRecord.class.getName(),
|
UnknownRecord.class.getName(),
|
||||||
ContinueRecord.class.getName(),
|
ContinueRecord.class.getName(),
|
||||||
@ -238,14 +171,11 @@ public class TestEventRecordFactory extends TestCase
|
|||||||
assertEquals(message + " data byte " + i, data[offset[0]++], recData[i]);
|
assertEquals(message + " data byte " + i, data[offset[0]++], recData[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
new short[] {-256, 0x3C}
|
EventRecordFactory factory = new EventRecordFactory(listener, new short[] {-256, 0x3C});
|
||||||
);
|
|
||||||
|
|
||||||
factory.processRecords(new ByteArrayInputStream(data));
|
factory.processRecords(new ByteArrayInputStream(data));
|
||||||
assertEquals("nr. of processed records", 3, recCnt[0]);
|
assertEquals("nr. of processed records", 3, recCnt[0]);
|
||||||
assertEquals("nr. of processed bytes", data.length, offset[0]);
|
assertEquals("nr. of processed bytes", data.length, offset[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -255,4 +255,20 @@ public final class TestExcelExtractor extends TestCase {
|
|||||||
ex.getText());
|
ex.getText());
|
||||||
assertEquals("Excel With Embeded", ex.getSummaryInformation().getTitle());
|
assertEquals("Excel With Embeded", ex.getSummaryInformation().getTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we get text from headers and footers
|
||||||
|
*/
|
||||||
|
public void test45538() throws Exception {
|
||||||
|
String[] files = new String[] {
|
||||||
|
"45538_classic_Footer.xls", "45538_form_Footer.xls",
|
||||||
|
"45538_classic_Header.xls", "45538_form_Header.xls"
|
||||||
|
};
|
||||||
|
for(int i=0; i<files.length; i++) {
|
||||||
|
ExcelExtractor extractor = createExtractor(files[i]);
|
||||||
|
String text = extractor.getText();
|
||||||
|
assertTrue("Unable to find expected word in text\n" + text, text.contains("testdoc"));
|
||||||
|
assertTrue("Unable to find expected word in text\n" + text, text.contains("test phrase"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,9 +416,9 @@ public final class TestSheet extends TestCase {
|
|||||||
int size = sheet.getSize();
|
int size = sheet.getSize();
|
||||||
byte[] data = new byte[size];
|
byte[] data = new byte[size];
|
||||||
sheet.serialize(0, data);
|
sheet.serialize(0, data);
|
||||||
EventRecordFactory erf = new EventRecordFactory();
|
|
||||||
MyIndexRecordListener myIndexListener = new MyIndexRecordListener();
|
MyIndexRecordListener myIndexListener = new MyIndexRecordListener();
|
||||||
erf.registerListener(myIndexListener, new short[] { IndexRecord.sid, });
|
EventRecordFactory erf = new EventRecordFactory(myIndexListener, new short[] { IndexRecord.sid, });
|
||||||
erf.processRecords(new ByteArrayInputStream(data));
|
erf.processRecords(new ByteArrayInputStream(data));
|
||||||
IndexRecord indexRecord = myIndexListener.getIndexRecord();
|
IndexRecord indexRecord = myIndexListener.getIndexRecord();
|
||||||
int dbCellRecordPos = indexRecord.getDbcellAt(0);
|
int dbCellRecordPos = indexRecord.getDbcellAt(0);
|
||||||
|
@ -594,9 +594,9 @@ public final class TestDataValidation extends TestCase {
|
|||||||
byte[] wbData = baos.toByteArray();
|
byte[] wbData = baos.toByteArray();
|
||||||
|
|
||||||
if (false) { // TODO (Jul 2008) fix EventRecordFactory to process unknown records, (and DV records for that matter)
|
if (false) { // TODO (Jul 2008) fix EventRecordFactory to process unknown records, (and DV records for that matter)
|
||||||
EventRecordFactory erf = new EventRecordFactory();
|
|
||||||
ERFListener erfListener = null; // new MyERFListener();
|
ERFListener erfListener = null; // new MyERFListener();
|
||||||
erf.registerListener(erfListener, null);
|
EventRecordFactory erf = new EventRecordFactory(erfListener, null);
|
||||||
try {
|
try {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(baos.toByteArray()));
|
POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(baos.toByteArray()));
|
||||||
erf.processRecords(fs.createDocumentInputStream("Workbook"));
|
erf.processRecords(fs.createDocumentInputStream("Workbook"));
|
||||||
|
Loading…
Reference in New Issue
Block a user