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-682507,682509,682512-682517,682519-682532,682534-682619,682622-682777,682779-682998,683000-683019,683021-683022,683024-683080,683082-683092,683094-683095,683097-683127,683129-683131,683133-683166,683168-683698,683700-683705,683707-683757,683759-683787,683789-683870,683872-683879,683881-683900,683902-684066,684068-684074,684076-684222,684224-684254,684257-684281,684283-684286,684288-684292,684294-684298,684300-684301,684303-684308,684310-684317,684320,684323-684335,684337-684348,684350-684354,684356-684361,684363-684369,684371-684453,684455-684883,684885-684937,684940-684958,684960-684970,684972-684985,684987-685053,685055-685063,685065-685259,685261-685262,685264-685266,685268-685282,685285-686035,686037-686045,686047-686052,686054-686206,686208-686215,686217-686277,686279-686289,686291-686620,686622-686623,686626-686627,686629-686639,686641-686843,686845-686976,686978-687402,687404-687422,687424-687428,687430-687442,687444-688425,688427-688641,688643-688649,688651-688654,688656-688824,688826-688909,688911-689543,689545-689558,689560-689635,689637-689703,689705-689715,689717-689718,689720,689722-689972,689974-690090,690092-690093,690095-690111,690113-690258,690260-690261,690263-690517 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk ........ r690404 | josh | 2008-08-29 23:08:42 +0100 (Fri, 29 Aug 2008) | 1 line Clean-up toString() and inner class ........ r690411 | josh | 2008-08-29 23:21:10 +0100 (Fri, 29 Aug 2008) | 1 line Added ArrayRecord and CellRangeAddress8Bit ........ r690461 | josh | 2008-08-30 05:34:01 +0100 (Sat, 30 Aug 2008) | 1 line Fixed decoding of operand class for ArrayPtg ........ r690517 | nick | 2008-08-30 15:47:33 +0100 (Sat, 30 Aug 2008) | 1 line Various bug fixes, and hpbf updates ........ git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@690533 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
555b6980ab
commit
d45000201f
@ -64,6 +64,11 @@
|
||||
<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 version="3.1.1-alpha1" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">Impove empty header or footer handling in HWPF HeaderStories</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Avoid NPE in hssf.usermodel.HeaderFooter when stripping fields out</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Avoid NPE in EscherBSERecord on older escher records</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Basic text extractraction support in HPBF</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Initial, low level support for Publisher files, in the form of HPBF</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45699 - Fix RowRecordsAggregate to tolerate intervening MERGEDCELLS records</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45698 - Fix LinkTable to tolerate multiple EXTERNSHEET records</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45682 - Fix for cloning of CFRecordsAggregate</action>
|
||||
|
@ -165,6 +165,12 @@ PL 62 1a 00 00 48 00 00 00 // PL from: 1a62 (6754), len: 48 (72)
|
||||
|
||||
(the text will then start)
|
||||
</source>
|
||||
<p>We think that the first 4 bytes of text describes the
|
||||
the function of the data at the offset. The first short is
|
||||
then the count of that type, eg the 2nd will have 1. We
|
||||
think that the second 4 bytes of text describes the format
|
||||
of data block at the offset. The format of the text block
|
||||
is easy, but we're still trying to figure out the others.</p>
|
||||
</section>
|
||||
</body>
|
||||
</document>
|
||||
|
@ -33,11 +33,20 @@
|
||||
<title>Overview</title>
|
||||
|
||||
<p>HPBF is the POI Project's pure Java implementation of the Visio file format.</p>
|
||||
<p>Currently, HPBF is in the experimental stage, while we try
|
||||
to figure out the file format. Our initial aim is to provide
|
||||
a text extractor for the format, with low level code following
|
||||
after that if demand and developer interest warrant it.</p>
|
||||
<p>At this time, there is no <em>usermodel</em> api or similar.</p>
|
||||
<p>Currently, HPBF is in an early stage, whilst we try to
|
||||
figure out the file format. So far, we have basic text
|
||||
extraction support, and are able to read some parts within
|
||||
the file. Writing is not yet supported, as we are unable
|
||||
to make sense of the Contents stream, which we think has
|
||||
lots of offsets to other parts of the file.</p>
|
||||
<p>Our initial aim is to provude a text extractor for the format
|
||||
(now done), and be able to extract hyperlinks from within
|
||||
the document (not yet supported). Additional low level
|
||||
code to process the file format may follow, if there
|
||||
is demand and developer interest warrant it.</p>
|
||||
<p>At this time, there is no <em>usermodel</em> api or similar.
|
||||
There is only low level support for certain parts of
|
||||
the file, but by no means all of it.</p>
|
||||
<p>Our current understanding of the file format is documented
|
||||
<link href="file-format.html">here</link>.</p>
|
||||
<note>
|
||||
|
@ -160,8 +160,8 @@
|
||||
</section>
|
||||
<section><title>HPBF for Publisher Documents</title>
|
||||
<p>HPBF is our port of the Microsoft Publisher 98(-2007) file format to pure
|
||||
Java. At the moment, we are still figuring out the file format, but we hope
|
||||
to have simple text extraction shortly. Please see <link
|
||||
Java. It currently only supports reading at a low level for around
|
||||
half of the file parts, and simple text extraction. Please see <link
|
||||
href="./hpbf/index.html">the HPBF project page for more
|
||||
information</link>.</p>
|
||||
</section>
|
||||
|
@ -61,6 +61,11 @@
|
||||
<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 version="3.1.1-alpha1" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">Impove empty header or footer handling in HWPF HeaderStories</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Avoid NPE in hssf.usermodel.HeaderFooter when stripping fields out</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Avoid NPE in EscherBSERecord on older escher records</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Basic text extractraction support in HPBF</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Initial, low level support for Publisher files, in the form of HPBF</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45699 - Fix RowRecordsAggregate to tolerate intervening MERGEDCELLS records</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45698 - Fix LinkTable to tolerate multiple EXTERNSHEET records</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45682 - Fix for cloning of CFRecordsAggregate</action>
|
||||
|
@ -87,9 +87,10 @@ public class EscherBSERecord
|
||||
field_10_unused2 = data[pos + 34];
|
||||
field_11_unused3 = data[pos + 35];
|
||||
bytesRemaining -= 36;
|
||||
|
||||
int bytesRead = 0;
|
||||
if (bytesRemaining > 0)
|
||||
{
|
||||
if (bytesRemaining > 0) {
|
||||
// Some older escher formats skip this last record
|
||||
field_12_blipRecord = (EscherBlipRecord) recordFactory.createRecord( data, pos + 36 );
|
||||
bytesRead = field_12_blipRecord.fillFields( data, pos + 36, recordFactory );
|
||||
}
|
||||
@ -168,7 +169,16 @@ public class EscherBSERecord
|
||||
*/
|
||||
public int getRecordSize()
|
||||
{
|
||||
return 8 + 1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 + 1 + 1 + field_12_blipRecord.getRecordSize() + (remainingData == null ? 0 : remainingData.length);
|
||||
int field_12_size = 0;
|
||||
if(field_12_blipRecord != null) {
|
||||
field_12_size = field_12_blipRecord.getRecordSize();
|
||||
}
|
||||
int remaining_size = 0;
|
||||
if(remainingData != null) {
|
||||
remaining_size = remainingData.length;
|
||||
}
|
||||
return 8 + 1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 +
|
||||
1 + 1 + field_12_size + remaining_size;
|
||||
}
|
||||
|
||||
/**
|
||||
|
126
src/java/org/apache/poi/hssf/record/ArrayRecord.java
Normal file
126
src/java/org/apache/poi/hssf/record/ArrayRecord.java
Normal file
@ -0,0 +1,126 @@
|
||||
/* ====================================================================
|
||||
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.record;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* ARRAY (0x0221)<p/>
|
||||
*
|
||||
* Treated in a similar way to SharedFormulaRecord
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class ArrayRecord extends Record {
|
||||
|
||||
public final static short sid = 0x0221;
|
||||
private static final int OPT_ALWAYS_RECALCULATE = 0x0001;
|
||||
private static final int OPT_CALCULATE_ON_OPEN = 0x0002;
|
||||
|
||||
private CellRangeAddress8Bit _range;
|
||||
|
||||
private int _options;
|
||||
private int _field3notUsed;
|
||||
private Ptg[] _formulaTokens;
|
||||
|
||||
public ArrayRecord(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public boolean isAlwaysRecalculate() {
|
||||
return (_options & OPT_ALWAYS_RECALCULATE) != 0;
|
||||
}
|
||||
public boolean isCalculateOnOpen() {
|
||||
return (_options & OPT_CALCULATE_ON_OPEN) != 0;
|
||||
}
|
||||
|
||||
protected void validateSid(short id) {
|
||||
if (id != sid) {
|
||||
throw new RecordFormatException("NOT A valid Array RECORD");
|
||||
}
|
||||
}
|
||||
|
||||
private int getDataSize(){
|
||||
return CellRangeAddress8Bit.ENCODED_SIZE
|
||||
+ 2 + 4
|
||||
+ getFormulaSize();
|
||||
}
|
||||
|
||||
public int serialize( int offset, byte[] data ) {
|
||||
int dataSize = getDataSize();
|
||||
|
||||
LittleEndian.putShort(data, 0 + offset, sid);
|
||||
LittleEndian.putUShort(data, 2 + offset, dataSize);
|
||||
|
||||
int pos = offset+4;
|
||||
_range.serialize(pos, data);
|
||||
pos += CellRangeAddress8Bit.ENCODED_SIZE;
|
||||
LittleEndian.putUShort(data, pos, _options);
|
||||
pos+=2;
|
||||
LittleEndian.putInt(data, pos, _field3notUsed);
|
||||
pos+=4;
|
||||
int tokenSize = Ptg.getEncodedSizeWithoutArrayData(_formulaTokens);
|
||||
LittleEndian.putUShort(data, pos, tokenSize);
|
||||
pos+=2;
|
||||
Ptg.serializePtgs(_formulaTokens, data, pos);
|
||||
return dataSize + 4;
|
||||
}
|
||||
|
||||
private int getFormulaSize() {
|
||||
int result = 0;
|
||||
for (int i = 0; i < _formulaTokens.length; i++) {
|
||||
result += _formulaTokens[i].getSize();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public int getRecordSize(){
|
||||
return 4 + getDataSize();
|
||||
}
|
||||
|
||||
|
||||
protected void fillFields(RecordInputStream in) {
|
||||
_range = new CellRangeAddress8Bit(in);
|
||||
_options = in.readUShort();
|
||||
_field3notUsed = in.readInt();
|
||||
int formulaLen = in.readUShort();
|
||||
_formulaTokens = Ptg.readTokens(formulaLen, in);
|
||||
}
|
||||
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(getClass().getName()).append(" [ARRAY]\n");
|
||||
sb.append(" range=").append(_range.toString()).append("\n");
|
||||
sb.append(" options=").append(HexDump.shortToHex(_options)).append("\n");
|
||||
sb.append(" notUsed=").append(HexDump.intToHex(_field3notUsed)).append("\n");
|
||||
sb.append(" formula:").append("\n");
|
||||
for (int i = 0; i < _formulaTokens.length; i++) {
|
||||
sb.append(_formulaTokens[i].toString());
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
@ -16,56 +15,38 @@
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* MulRKRecord.java
|
||||
*
|
||||
* Created on November 9, 2001, 4:53 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.poi.hssf.util.RKUtil;
|
||||
import org.apache.poi.util.HexDump;
|
||||
|
||||
/**
|
||||
* MULRK (0x00BD) <p/>
|
||||
*
|
||||
* Used to store multiple RK numbers on a row. 1 MulRk = Multiple Cell values.
|
||||
* HSSF just converts this into multiple NUMBER records. READ-ONLY SUPPORT!<P>
|
||||
* REFERENCE: PG 330 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
|
||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @version 2.0-pre
|
||||
*/
|
||||
public final class MulRKRecord extends Record {
|
||||
public final static short sid = 0x00BD;
|
||||
|
||||
public class MulRKRecord
|
||||
extends Record
|
||||
{
|
||||
public final static short sid = 0xbd;
|
||||
//private short field_1_row;
|
||||
private int field_1_row;
|
||||
private short field_2_first_col;
|
||||
private ArrayList field_3_rks;
|
||||
private RkRec[] field_3_rks;
|
||||
private short field_4_last_col;
|
||||
|
||||
/** Creates new MulRKRecord */
|
||||
|
||||
public MulRKRecord()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a MulRK record and sets its fields appropriately.
|
||||
*
|
||||
* @param in the RecordInputstream to read the record from
|
||||
*/
|
||||
|
||||
public MulRKRecord(RecordInputStream in)
|
||||
{
|
||||
public MulRKRecord(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
//public short getRow()
|
||||
public int getRow()
|
||||
{
|
||||
public int getRow() {
|
||||
return field_1_row;
|
||||
}
|
||||
|
||||
@ -73,9 +54,7 @@ public class MulRKRecord
|
||||
* starting column (first cell this holds in the row)
|
||||
* @return first column number
|
||||
*/
|
||||
|
||||
public short getFirstColumn()
|
||||
{
|
||||
public short getFirstColumn() {
|
||||
return field_2_first_col;
|
||||
}
|
||||
|
||||
@ -83,9 +62,7 @@ public class MulRKRecord
|
||||
* ending column (last cell this holds in the row)
|
||||
* @return first column number
|
||||
*/
|
||||
|
||||
public short getLastColumn()
|
||||
{
|
||||
public short getLastColumn() {
|
||||
return field_4_last_col;
|
||||
}
|
||||
|
||||
@ -93,9 +70,7 @@ public class MulRKRecord
|
||||
* get the number of columns this contains (last-first +1)
|
||||
* @return number of columns (last - first +1)
|
||||
*/
|
||||
|
||||
public int getNumColumns()
|
||||
{
|
||||
public int getNumColumns() {
|
||||
return field_4_last_col - field_2_first_col + 1;
|
||||
}
|
||||
|
||||
@ -103,62 +78,40 @@ public class MulRKRecord
|
||||
* returns the xf index for column (coffset = column - field_2_first_col)
|
||||
* @return the XF index for the column
|
||||
*/
|
||||
|
||||
public short getXFAt(int coffset)
|
||||
{
|
||||
return (( RkRec ) field_3_rks.get(coffset)).xf;
|
||||
public short getXFAt(int coffset) {
|
||||
return field_3_rks[coffset].xf;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the rk number for column (coffset = column - field_2_first_col)
|
||||
* @return the value (decoded into a double)
|
||||
*/
|
||||
|
||||
public double getRKNumberAt(int coffset)
|
||||
{
|
||||
return RKUtil.decodeNumber((( RkRec ) field_3_rks.get(coffset)).rk);
|
||||
public double getRKNumberAt(int coffset) {
|
||||
return RKUtil.decodeNumber(field_3_rks[coffset].rk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in the RecordInputstream to read the record from
|
||||
*/
|
||||
protected void fillFields(RecordInputStream in)
|
||||
{
|
||||
//field_1_row = LittleEndian.getShort(data, 0 + offset);
|
||||
protected void fillFields(RecordInputStream in) {
|
||||
field_1_row = in.readUShort();
|
||||
field_2_first_col = in.readShort();
|
||||
field_3_rks = parseRKs(in);
|
||||
field_3_rks = RkRec.parseRKs(in);
|
||||
field_4_last_col = in.readShort();
|
||||
}
|
||||
|
||||
private ArrayList parseRKs(RecordInputStream in)
|
||||
{
|
||||
ArrayList retval = new ArrayList();
|
||||
while ((in.remaining()-2) > 0) {
|
||||
RkRec rec = new RkRec();
|
||||
|
||||
rec.xf = in.readShort();
|
||||
rec.rk = in.readInt();
|
||||
retval.add(rec);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("[MULRK]\n");
|
||||
buffer.append("firstcol = ")
|
||||
.append(Integer.toHexString(getFirstColumn())).append("\n");
|
||||
buffer.append(" lastcol = ")
|
||||
.append(Integer.toHexString(getLastColumn())).append("\n");
|
||||
for (int k = 0; k < getNumColumns(); k++)
|
||||
{
|
||||
buffer.append("xf").append(k).append(" = ")
|
||||
.append(Integer.toHexString(getXFAt(k))).append("\n");
|
||||
buffer.append("rk").append(k).append(" = ")
|
||||
.append(getRKNumberAt(k)).append("\n");
|
||||
buffer.append(" .row = ").append(HexDump.shortToHex(getRow())).append("\n");
|
||||
buffer.append(" .firstcol= ").append(HexDump.shortToHex(getFirstColumn())).append("\n");
|
||||
buffer.append(" .lastcol = ").append(HexDump.shortToHex(getLastColumn())).append("\n");
|
||||
|
||||
for (int k = 0; k < getNumColumns(); k++) {
|
||||
buffer.append(" xf[").append(k).append("] = ").append(HexDump.shortToHex(getXFAt(k))).append("\n");
|
||||
buffer.append(" rk[").append(k).append("] = ").append(getRKNumberAt(k)).append("\n");
|
||||
}
|
||||
buffer.append("[/MULRK]\n");
|
||||
return buffer.toString();
|
||||
@ -189,10 +142,24 @@ public class MulRKRecord
|
||||
throw new RecordFormatException(
|
||||
"Sorry, you can't serialize a MulRK in this release");
|
||||
}
|
||||
}
|
||||
|
||||
class RkRec
|
||||
{
|
||||
public short xf;
|
||||
public int rk;
|
||||
private static final class RkRec {
|
||||
public static final int ENCODED_SIZE = 6;
|
||||
public final short xf;
|
||||
public final int rk;
|
||||
|
||||
private RkRec(RecordInputStream in) {
|
||||
xf = in.readShort();
|
||||
rk = in.readInt();
|
||||
}
|
||||
|
||||
public static RkRec[] parseRKs(RecordInputStream in) {
|
||||
int nItems = (in.remaining()-2) / ENCODED_SIZE;
|
||||
RkRec[] retval = new RkRec[nItems];
|
||||
for (int i=0; i<nItems; i++) {
|
||||
retval[i] = new RkRec(in);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
@ -35,47 +36,7 @@ public final class SelectionRecord extends Record {
|
||||
private int field_2_row_active_cell;
|
||||
private int field_3_col_active_cell;
|
||||
private int field_4_active_cell_ref_index;
|
||||
private Reference[] field_6_refs;
|
||||
|
||||
/**
|
||||
* Note - column values are 8-bit so cannot use <tt>CellRangeAddressList</tt>
|
||||
*/
|
||||
public class Reference {
|
||||
/* package */ static final int ENCODED_SIZE = 6;
|
||||
private int _firstRow;
|
||||
private int _lastRow;
|
||||
private int _firstCol;
|
||||
private int _lastCol;
|
||||
|
||||
/* package */ Reference(int firstRow, int lastRow, int firstColumn, int lastColumn) {
|
||||
_firstRow = firstRow;
|
||||
_lastRow = lastRow;
|
||||
_firstCol = firstColumn;
|
||||
_lastCol = lastColumn;
|
||||
}
|
||||
/* package */ Reference(RecordInputStream in) {
|
||||
this(in.readUShort(), in.readUShort(), in.readUByte(), in.readUByte());
|
||||
}
|
||||
public void serialize(int offset, byte[] data) {
|
||||
LittleEndian.putUShort(data, offset + 0, _firstRow);
|
||||
LittleEndian.putUShort(data, offset + 2, _lastRow);
|
||||
LittleEndian.putByte(data, offset + 4, _firstCol);
|
||||
LittleEndian.putByte(data, offset + 6, _lastCol);
|
||||
}
|
||||
|
||||
public int getFirstRow() {
|
||||
return _firstRow;
|
||||
}
|
||||
public int getLastRow() {
|
||||
return _lastRow;
|
||||
}
|
||||
public int getFirstColumn() {
|
||||
return _firstCol;
|
||||
}
|
||||
public int getLastColumn() {
|
||||
return _lastCol;
|
||||
}
|
||||
}
|
||||
private CellRangeAddress8Bit[] field_6_refs;
|
||||
|
||||
/**
|
||||
* Creates a default selection record (cell A1, in pane ID 3)
|
||||
@ -85,8 +46,8 @@ public final class SelectionRecord extends Record {
|
||||
field_2_row_active_cell = activeCellRow;
|
||||
field_3_col_active_cell = activeCellCol;
|
||||
field_4_active_cell_ref_index = 0;
|
||||
field_6_refs = new Reference[] {
|
||||
new Reference(activeCellRow, activeCellRow, activeCellCol, activeCellCol),
|
||||
field_6_refs = new CellRangeAddress8Bit[] {
|
||||
new CellRangeAddress8Bit(activeCellRow, activeCellRow, activeCellCol, activeCellCol),
|
||||
};
|
||||
}
|
||||
|
||||
@ -94,7 +55,6 @@ public final class SelectionRecord extends Record {
|
||||
* Constructs a Selection record and sets its fields appropriately.
|
||||
* @param in the RecordInputstream to read the record from
|
||||
*/
|
||||
|
||||
public SelectionRecord(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
@ -112,9 +72,9 @@ public final class SelectionRecord extends Record {
|
||||
field_4_active_cell_ref_index = in.readShort();
|
||||
int field_5_num_refs = in.readUShort();
|
||||
|
||||
field_6_refs = new Reference[field_5_num_refs];
|
||||
field_6_refs = new CellRangeAddress8Bit[field_5_num_refs];
|
||||
for (int i = 0; i < field_6_refs.length; i++) {
|
||||
field_6_refs[i] = new Reference(in);
|
||||
field_6_refs[i] = new CellRangeAddress8Bit(in);
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,8 +140,7 @@ public final class SelectionRecord extends Record {
|
||||
return (short)field_4_active_cell_ref_index;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("[SELECTION]\n");
|
||||
@ -200,7 +159,7 @@ public final class SelectionRecord extends Record {
|
||||
}
|
||||
private int getDataSize() {
|
||||
return 9 // 1 byte + 4 shorts
|
||||
+ field_6_refs.length * Reference.ENCODED_SIZE;
|
||||
+ CellRangeAddress8Bit.getEncodedSize(field_6_refs.length);
|
||||
}
|
||||
public int serialize(int offset, byte [] data) {
|
||||
int dataSize = getDataSize();
|
||||
@ -213,8 +172,8 @@ public final class SelectionRecord extends Record {
|
||||
int nRefs = field_6_refs.length;
|
||||
LittleEndian.putUShort(data, 11 + offset, nRefs);
|
||||
for (int i = 0; i < field_6_refs.length; i++) {
|
||||
Reference r = field_6_refs[i];
|
||||
r.serialize(offset + 13 + i * Reference.ENCODED_SIZE, data);
|
||||
CellRangeAddress8Bit r = field_6_refs[i];
|
||||
r.serialize(offset + 13 + i * CellRangeAddress8Bit.ENCODED_SIZE, data);
|
||||
}
|
||||
return 4 + dataSize;
|
||||
}
|
||||
|
@ -17,17 +17,16 @@
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaNPtg;
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.hssf.record.formula.RefNPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
|
||||
import org.apache.poi.util.HexDump;
|
||||
|
||||
/**
|
||||
* Title: SharedFormulaRecord
|
||||
* Title: SHAREDFMLA (0x04BC) SharedFormulaRecord
|
||||
* Description: Primarily used as an excel optimization so that multiple similar formulas
|
||||
* are not written out too many times. We should recognize this record and
|
||||
* serialize as is since this is used when reading templates.
|
||||
@ -40,58 +39,46 @@ import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
public final class SharedFormulaRecord extends Record {
|
||||
public final static short sid = 0x04BC;
|
||||
|
||||
private int field_1_first_row;
|
||||
private int field_2_last_row;
|
||||
private short field_3_first_column;
|
||||
private short field_4_last_column;
|
||||
private CellRangeAddress8Bit _range;
|
||||
private int field_5_reserved;
|
||||
private short field_6_expression_len;
|
||||
private Stack field_7_parsed_expr;
|
||||
private Ptg[] field_7_parsed_expr;
|
||||
|
||||
public SharedFormulaRecord()
|
||||
{
|
||||
public SharedFormulaRecord() {
|
||||
_range = new CellRangeAddress8Bit(0, 0, 0, 0);
|
||||
field_7_parsed_expr = Ptg.EMPTY_PTG_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in the RecordInputstream to read the record from
|
||||
*/
|
||||
|
||||
public SharedFormulaRecord(RecordInputStream in)
|
||||
{
|
||||
public SharedFormulaRecord(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
protected void validateSid(short id)
|
||||
{
|
||||
if (id != this.sid)
|
||||
{
|
||||
protected void validateSid(short id) {
|
||||
if (id != this.sid) {
|
||||
throw new RecordFormatException("Not a valid SharedFormula");
|
||||
}
|
||||
}
|
||||
|
||||
public int getFirstRow() {
|
||||
return field_1_first_row;
|
||||
return _range.getFirstRow();
|
||||
}
|
||||
|
||||
public int getLastRow() {
|
||||
return field_2_last_row;
|
||||
return _range.getLastRow();
|
||||
}
|
||||
|
||||
public short getFirstColumn() {
|
||||
return field_3_first_column;
|
||||
return (short) _range.getFirstColumn();
|
||||
}
|
||||
|
||||
public short getLastColumn() {
|
||||
return field_4_last_column;
|
||||
}
|
||||
|
||||
public short getExpressionLength()
|
||||
{
|
||||
return field_6_expression_len;
|
||||
return (short) _range.getLastColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* spit the record out AS IS. no interperatation or identification
|
||||
* spit the record out AS IS. no interpretation or identification
|
||||
*/
|
||||
|
||||
public int serialize(int offset, byte [] data)
|
||||
@ -115,65 +102,28 @@ public final class SharedFormulaRecord extends Record {
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("[SHARED FORMULA RECORD:" + Integer.toHexString(sid) + "]\n");
|
||||
buffer.append(" .id = ").append(Integer.toHexString(sid))
|
||||
.append("\n");
|
||||
buffer.append(" .first_row = ")
|
||||
.append(Integer.toHexString(getFirstRow())).append("\n");
|
||||
buffer.append(" .last_row = ")
|
||||
.append(Integer.toHexString(getLastRow()))
|
||||
.append("\n");
|
||||
buffer.append(" .first_column = ")
|
||||
.append(Integer.toHexString(getFirstColumn())).append("\n");
|
||||
buffer.append(" .last_column = ")
|
||||
.append(Integer.toHexString(getLastColumn()))
|
||||
.append("\n");
|
||||
buffer.append(" .reserved = ")
|
||||
.append(Integer.toHexString(field_5_reserved))
|
||||
.append("\n");
|
||||
buffer.append(" .expressionlength= ").append(getExpressionLength())
|
||||
.append("\n");
|
||||
buffer.append("[SHARED FORMULA (").append(HexDump.intToHex(sid)).append("]\n");
|
||||
buffer.append(" .range = ").append(_range.toString()).append("\n");
|
||||
buffer.append(" .reserved = ").append(HexDump.shortToHex(field_5_reserved)).append("\n");
|
||||
|
||||
buffer.append(" .numptgsinarray = ").append(field_7_parsed_expr.size())
|
||||
.append("\n");
|
||||
|
||||
for (int k = 0; k < field_7_parsed_expr.size(); k++ ) {
|
||||
buffer.append("Formula ")
|
||||
.append(k)
|
||||
.append("\n")
|
||||
.append(field_7_parsed_expr.get(k).toString())
|
||||
.append("\n");
|
||||
for (int k = 0; k < field_7_parsed_expr.length; k++ ) {
|
||||
buffer.append("Formula[").append(k).append("]");
|
||||
buffer.append(field_7_parsed_expr[k].toString()).append("\n");
|
||||
}
|
||||
|
||||
buffer.append("[/SHARED FORMULA RECORD]\n");
|
||||
buffer.append("[/SHARED FORMULA]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public short getSid()
|
||||
{
|
||||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
protected void fillFields(RecordInputStream in)
|
||||
{
|
||||
field_1_first_row = in.readUShort();
|
||||
field_2_last_row = in.readUShort();
|
||||
field_3_first_column = in.readUByte();
|
||||
field_4_last_column = in.readUByte();
|
||||
protected void fillFields(RecordInputStream in) {
|
||||
_range = new CellRangeAddress8Bit(in);
|
||||
field_5_reserved = in.readShort();
|
||||
field_6_expression_len = in.readShort();
|
||||
field_7_parsed_expr = getParsedExpressionTokens(in);
|
||||
}
|
||||
|
||||
private Stack getParsedExpressionTokens(RecordInputStream in)
|
||||
{
|
||||
Stack stack = new Stack();
|
||||
|
||||
while (in.remaining() != 0) {
|
||||
Ptg ptg = Ptg.createPtg(in);
|
||||
stack.push(ptg);
|
||||
}
|
||||
return stack;
|
||||
int field_6_expression_len = in.readShort();
|
||||
field_7_parsed_expr = Ptg.readTokens(field_6_expression_len, in);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,7 +140,7 @@ public final class SharedFormulaRecord extends Record {
|
||||
* Creates a non shared formula from the shared formula
|
||||
* counter part
|
||||
*/
|
||||
protected static Stack convertSharedFormulas(Stack ptgs, int formulaRow, int formulaColumn) {
|
||||
protected static Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) {
|
||||
if(false) {
|
||||
/*
|
||||
* TODO - (May-2008) Stop converting relative ref Ptgs in shared formula records.
|
||||
@ -201,11 +151,10 @@ public final class SharedFormulaRecord extends Record {
|
||||
*/
|
||||
return ptgs;
|
||||
}
|
||||
Stack newPtgStack = new Stack();
|
||||
Ptg[] newPtgStack = new Ptg[ptgs.length];
|
||||
|
||||
if (ptgs != null)
|
||||
for (int k = 0; k < ptgs.size(); k++) {
|
||||
Ptg ptg = (Ptg) ptgs.get(k);
|
||||
for (int k = 0; k < ptgs.length; k++) {
|
||||
Ptg ptg = ptgs[k];
|
||||
byte originalOperandClass = -1;
|
||||
if (!ptg.isBaseToken()) {
|
||||
originalOperandClass = ptg.getPtgClass();
|
||||
@ -226,12 +175,16 @@ public final class SharedFormulaRecord extends Record {
|
||||
areaNPtg.isLastRowRelative(),
|
||||
areaNPtg.isFirstColRelative(),
|
||||
areaNPtg.isLastColRelative());
|
||||
} else {
|
||||
if (false) {// do we need a ptg clone here?
|
||||
ptg = ptg.copy();
|
||||
}
|
||||
}
|
||||
if (!ptg.isBaseToken()) {
|
||||
ptg.setClass(originalOperandClass);
|
||||
}
|
||||
|
||||
newPtgStack.add(ptg);
|
||||
newPtgStack[k] = ptg;
|
||||
}
|
||||
return newPtgStack;
|
||||
}
|
||||
@ -248,9 +201,7 @@ public final class SharedFormulaRecord extends Record {
|
||||
final int formulaRow = formula.getRow();
|
||||
final int formulaColumn = formula.getColumn();
|
||||
|
||||
List ptgList = convertSharedFormulas(field_7_parsed_expr, formulaRow, formulaColumn);
|
||||
Ptg[] ptgs = new Ptg[ptgList.size()];
|
||||
ptgList.toArray(ptgs);
|
||||
Ptg[] ptgs = convertSharedFormulas(field_7_parsed_expr, formulaRow, formulaColumn);
|
||||
formula.setParsedExpression(ptgs);
|
||||
//Now its not shared!
|
||||
formula.setSharedFormula(false);
|
||||
|
@ -18,10 +18,15 @@
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.TblPtg;
|
||||
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
/**
|
||||
* DATATABLE (0x0236)<p/>
|
||||
*
|
||||
* TableRecord - The record specifies a data table.
|
||||
* This record is preceded by a single Formula record that
|
||||
* defines the first cell in the data table, which should
|
||||
@ -30,7 +35,7 @@ import org.apache.poi.util.LittleEndian;
|
||||
* See p536 of the June 08 binary docs
|
||||
*/
|
||||
public final class TableRecord extends Record {
|
||||
public static final short sid = 566;
|
||||
public static final short sid = 0x0236;
|
||||
|
||||
private static final BitField alwaysCalc = BitFieldFactory.getInstance(0x0001);
|
||||
private static final BitField reserved1 = BitFieldFactory.getInstance(0x0002);
|
||||
@ -41,24 +46,18 @@ public final class TableRecord extends Record {
|
||||
private static final BitField reserved2 = BitFieldFactory.getInstance(0x0040);
|
||||
private static final BitField reserved3 = BitFieldFactory.getInstance(0x0080);
|
||||
|
||||
private short field_1_ref_rowFirst;
|
||||
private short field_2_ref_rowLast;
|
||||
private short field_3_ref_colFirst;
|
||||
private short field_4_ref_colLast;
|
||||
private CellRangeAddress8Bit _range;
|
||||
|
||||
private byte field_5_flags;
|
||||
private byte field_6_res;
|
||||
private short field_7_rowInputRow;
|
||||
private short field_8_colInputRow;
|
||||
private short field_9_rowInputCol;
|
||||
private short field_10_colInputCol;
|
||||
private int field_5_flags;
|
||||
private int field_6_res;
|
||||
private int field_7_rowInputRow;
|
||||
private int field_8_colInputRow;
|
||||
private int field_9_rowInputCol;
|
||||
private int field_10_colInputCol;
|
||||
|
||||
|
||||
protected void fillFields(RecordInputStream in) {
|
||||
field_1_ref_rowFirst = in.readShort();
|
||||
field_2_ref_rowLast = in.readShort();
|
||||
field_3_ref_colFirst = in.readUByte();
|
||||
field_4_ref_colLast = in.readUByte();
|
||||
_range = new CellRangeAddress8Bit(in);
|
||||
field_5_flags = in.readByte();
|
||||
field_6_res = in.readByte();
|
||||
field_7_rowInputRow = in.readShort();
|
||||
@ -70,79 +69,48 @@ public final class TableRecord extends Record {
|
||||
public TableRecord(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
public TableRecord() {
|
||||
super();
|
||||
public TableRecord(CellRangeAddress8Bit range) {
|
||||
_range = range;
|
||||
field_6_res = 0;
|
||||
}
|
||||
|
||||
|
||||
public short getRowFirst() {
|
||||
return field_1_ref_rowFirst;
|
||||
}
|
||||
public void setRowFirst(short field_1_ref_rowFirst) {
|
||||
this.field_1_ref_rowFirst = field_1_ref_rowFirst;
|
||||
public CellRangeAddress8Bit getRange() {
|
||||
return _range;
|
||||
}
|
||||
|
||||
public short getRowLast() {
|
||||
return field_2_ref_rowLast;
|
||||
}
|
||||
public void setRowLast(short field_2_ref_rowLast) {
|
||||
this.field_2_ref_rowLast = field_2_ref_rowLast;
|
||||
}
|
||||
|
||||
public short getColFirst() {
|
||||
return field_3_ref_colFirst;
|
||||
}
|
||||
public void setColFirst(short field_3_ref_colFirst) {
|
||||
this.field_3_ref_colFirst = field_3_ref_colFirst;
|
||||
}
|
||||
|
||||
public short getColLast() {
|
||||
return field_4_ref_colLast;
|
||||
}
|
||||
public void setColLast(short field_4_ref_colLast) {
|
||||
this.field_4_ref_colLast = field_4_ref_colLast;
|
||||
}
|
||||
|
||||
public byte getFlags() {
|
||||
public int getFlags() {
|
||||
return field_5_flags;
|
||||
}
|
||||
public void setFlags(byte field_5_flags) {
|
||||
this.field_5_flags = field_5_flags;
|
||||
public void setFlags(int flags) {
|
||||
field_5_flags = flags;
|
||||
}
|
||||
|
||||
public byte getReserved() {
|
||||
return field_6_res;
|
||||
}
|
||||
public void setReserved(byte field_6_res) {
|
||||
this.field_6_res = field_6_res;
|
||||
}
|
||||
|
||||
public short getRowInputRow() {
|
||||
public int getRowInputRow() {
|
||||
return field_7_rowInputRow;
|
||||
}
|
||||
public void setRowInputRow(short field_7_rowInputRow) {
|
||||
this.field_7_rowInputRow = field_7_rowInputRow;
|
||||
public void setRowInputRow(int rowInputRow) {
|
||||
field_7_rowInputRow = rowInputRow;
|
||||
}
|
||||
|
||||
public short getColInputRow() {
|
||||
public int getColInputRow() {
|
||||
return field_8_colInputRow;
|
||||
}
|
||||
public void setColInputRow(short field_8_colInputRow) {
|
||||
this.field_8_colInputRow = field_8_colInputRow;
|
||||
public void setColInputRow(int colInputRow) {
|
||||
field_8_colInputRow = colInputRow;
|
||||
}
|
||||
|
||||
public short getRowInputCol() {
|
||||
public int getRowInputCol() {
|
||||
return field_9_rowInputCol;
|
||||
}
|
||||
public void setRowInputCol(short field_9_rowInputCol) {
|
||||
this.field_9_rowInputCol = field_9_rowInputCol;
|
||||
public void setRowInputCol(int rowInputCol) {
|
||||
field_9_rowInputCol = rowInputCol;
|
||||
}
|
||||
|
||||
public short getColInputCol() {
|
||||
public int getColInputCol() {
|
||||
return field_10_colInputCol;
|
||||
}
|
||||
public void setColInputCol(short field_10_colInputCol) {
|
||||
this.field_10_colInputCol = field_10_colInputCol;
|
||||
public void setColInputCol(int colInputCol) {
|
||||
field_10_colInputCol = colInputCol;
|
||||
}
|
||||
|
||||
|
||||
@ -150,35 +118,35 @@ public final class TableRecord extends Record {
|
||||
return alwaysCalc.isSet(field_5_flags);
|
||||
}
|
||||
public void setAlwaysCalc(boolean flag) {
|
||||
field_5_flags = alwaysCalc.setByteBoolean(field_5_flags, flag);
|
||||
field_5_flags = alwaysCalc.setBoolean(field_5_flags, flag);
|
||||
}
|
||||
|
||||
public boolean isRowOrColInpCell() {
|
||||
return rowOrColInpCell.isSet(field_5_flags);
|
||||
}
|
||||
public void setRowOrColInpCell(boolean flag) {
|
||||
field_5_flags = rowOrColInpCell.setByteBoolean(field_5_flags, flag);
|
||||
field_5_flags = rowOrColInpCell.setBoolean(field_5_flags, flag);
|
||||
}
|
||||
|
||||
public boolean isOneNotTwoVar() {
|
||||
return oneOrTwoVar.isSet(field_5_flags);
|
||||
}
|
||||
public void setOneNotTwoVar(boolean flag) {
|
||||
field_5_flags = oneOrTwoVar.setByteBoolean(field_5_flags, flag);
|
||||
field_5_flags = oneOrTwoVar.setBoolean(field_5_flags, flag);
|
||||
}
|
||||
|
||||
public boolean isColDeleted() {
|
||||
return colDeleted.isSet(field_5_flags);
|
||||
}
|
||||
public void setColDeleted(boolean flag) {
|
||||
field_5_flags = colDeleted.setByteBoolean(field_5_flags, flag);
|
||||
field_5_flags = colDeleted.setBoolean(field_5_flags, flag);
|
||||
}
|
||||
|
||||
public boolean isRowDeleted() {
|
||||
return rowDeleted.isSet(field_5_flags);
|
||||
}
|
||||
public void setRowDeleted(boolean flag) {
|
||||
field_5_flags = rowDeleted.setByteBoolean(field_5_flags, flag);
|
||||
field_5_flags = rowDeleted.setBoolean(field_5_flags, flag);
|
||||
}
|
||||
|
||||
|
||||
@ -187,24 +155,28 @@ public final class TableRecord extends Record {
|
||||
}
|
||||
|
||||
public int serialize(int offset, byte[] data) {
|
||||
int dataSize = getDataSize();
|
||||
LittleEndian.putShort(data, 0 + offset, sid);
|
||||
LittleEndian.putShort(data, 2 + offset, ( short ) (16));
|
||||
LittleEndian.putUShort(data, 2 + offset, dataSize);
|
||||
|
||||
LittleEndian.putShort(data, 4 + offset, field_1_ref_rowFirst);
|
||||
LittleEndian.putShort(data, 6 + offset, field_2_ref_rowLast);
|
||||
LittleEndian.putByte(data, 8 + offset, field_3_ref_colFirst);
|
||||
LittleEndian.putByte(data, 9 + offset, field_4_ref_colLast);
|
||||
_range.serialize(4 + offset, data);
|
||||
LittleEndian.putByte(data, 10 + offset, field_5_flags);
|
||||
LittleEndian.putByte(data, 11 + offset, field_6_res);
|
||||
LittleEndian.putShort(data, 12 + offset, field_7_rowInputRow);
|
||||
LittleEndian.putShort(data, 14 + offset, field_8_colInputRow);
|
||||
LittleEndian.putShort(data, 16 + offset, field_9_rowInputCol);
|
||||
LittleEndian.putShort(data, 18 + offset, field_10_colInputCol);
|
||||
LittleEndian.putUShort(data, 12 + offset, field_7_rowInputRow);
|
||||
LittleEndian.putUShort(data, 14 + offset, field_8_colInputRow);
|
||||
LittleEndian.putUShort(data, 16 + offset, field_9_rowInputCol);
|
||||
LittleEndian.putUShort(data, 18 + offset, field_10_colInputCol);
|
||||
|
||||
return getRecordSize();
|
||||
return 4 + dataSize;
|
||||
}
|
||||
private int getDataSize() {
|
||||
return CellRangeAddress8Bit.ENCODED_SIZE
|
||||
+ 2 // 2 byte fields
|
||||
+ 8; // 4 short fields
|
||||
}
|
||||
|
||||
public int getRecordSize() {
|
||||
return 4+16;
|
||||
return 4+getDataSize();
|
||||
}
|
||||
|
||||
protected void validateSid(short id) {
|
||||
@ -214,35 +186,25 @@ public final class TableRecord extends Record {
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("[TABLE]\n");
|
||||
buffer.append(" .row from = ")
|
||||
.append(Integer.toHexString(field_1_ref_rowFirst)).append("\n");
|
||||
buffer.append(" .row to = ")
|
||||
.append(Integer.toHexString(field_2_ref_rowLast)).append("\n");
|
||||
buffer.append(" .column from = ")
|
||||
.append(Integer.toHexString(field_3_ref_colFirst)).append("\n");
|
||||
buffer.append(" .column to = ")
|
||||
.append(Integer.toHexString(field_4_ref_colLast)).append("\n");
|
||||
|
||||
buffer.append(" .flags = ")
|
||||
.append(Integer.toHexString(field_5_flags)).append("\n");
|
||||
buffer.append(" .always calc =")
|
||||
.append(isAlwaysCalc()).append("\n");
|
||||
|
||||
buffer.append(" .reserved = ")
|
||||
.append(Integer.toHexString(field_6_res)).append("\n");
|
||||
buffer.append(" .row input row = ")
|
||||
.append(Integer.toHexString(field_7_rowInputRow)).append("\n");
|
||||
buffer.append(" .col input row = ")
|
||||
.append(Integer.toHexString(field_8_colInputRow)).append("\n");
|
||||
buffer.append(" .row input col = ")
|
||||
.append(Integer.toHexString(field_9_rowInputCol)).append("\n");
|
||||
buffer.append(" .col input col = ")
|
||||
.append(Integer.toHexString(field_10_colInputCol)).append("\n");
|
||||
buffer.append(" .range = ").append(_range.toString()).append("\n");
|
||||
buffer.append(" .flags = ") .append(HexDump.byteToHex(field_5_flags)).append("\n");
|
||||
buffer.append(" .alwaysClc= ").append(isAlwaysCalc()).append("\n");
|
||||
buffer.append(" .reserved = ").append(HexDump.intToHex(field_6_res)).append("\n");
|
||||
CellReference crRowInput = cr(field_7_rowInputRow, field_8_colInputRow);
|
||||
CellReference crColInput = cr(field_9_rowInputCol, field_10_colInputCol);
|
||||
buffer.append(" .rowInput = ").append(crRowInput.formatAsString()).append("\n");
|
||||
buffer.append(" .colInput = ").append(crColInput.formatAsString()).append("\n");
|
||||
buffer.append("[/TABLE]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private static CellReference cr(int rowIx, int colIxAndFlags) {
|
||||
int colIx = colIxAndFlags & 0x00FF;
|
||||
boolean isRowAbs = (colIxAndFlags & 0x8000) == 0;
|
||||
boolean isColAbs = (colIxAndFlags & 0x4000) == 0;
|
||||
return new CellReference(rowIx, colIx, isRowAbs, isColAbs);
|
||||
}
|
||||
}
|
||||
|
@ -43,58 +43,6 @@ import org.apache.poi.ss.usermodel.Workbook;
|
||||
public abstract class Ptg implements Cloneable {
|
||||
public static final Ptg[] EMPTY_PTG_ARRAY = { };
|
||||
|
||||
/* convert infix order ptg list to rpn order ptg list
|
||||
* @return List ptgs in RPN order
|
||||
* @param infixPtgs List of ptgs in infix order
|
||||
*/
|
||||
|
||||
/* DO NOT REMOVE
|
||||
*we keep this method in case we wish to change the way we parse
|
||||
*It needs a getPrecedence in OperationsPtg
|
||||
|
||||
public static List ptgsToRpn(List infixPtgs) {
|
||||
java.util.Stack operands = new java.util.Stack();
|
||||
java.util.List retval = new java.util.Stack();
|
||||
|
||||
java.util.ListIterator i = infixPtgs.listIterator();
|
||||
Object p;
|
||||
OperationPtg o ;
|
||||
boolean weHaveABracket = false;
|
||||
while (i.hasNext()) {
|
||||
p=i.next();
|
||||
if (p instanceof OperationPtg) {
|
||||
if (p instanceof ParenthesisPtg) {
|
||||
if (!weHaveABracket) {
|
||||
operands.push(p);
|
||||
weHaveABracket = true;
|
||||
} else {
|
||||
o = (OperationPtg) operands.pop();
|
||||
while (!(o instanceof ParenthesisPtg)) {
|
||||
retval.add(o);
|
||||
}
|
||||
weHaveABracket = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
while (!operands.isEmpty() && ((OperationPtg) operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO handle ^ since it is right associative
|
||||
retval.add(operands.pop());
|
||||
}
|
||||
operands.push(p);
|
||||
}
|
||||
} else {
|
||||
retval.add(p);
|
||||
}
|
||||
}
|
||||
while (!operands.isEmpty()) {
|
||||
if (operands.peek() instanceof ParenthesisPtg ){
|
||||
//throw some error
|
||||
} else {
|
||||
retval.add(operands.pop());
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reads <tt>size</tt> bytes of the input stream, to create an array of <tt>Ptg</tt>s.
|
||||
@ -145,9 +93,9 @@ public abstract class Ptg implements Cloneable {
|
||||
|
||||
Ptg retval = createClassifiedPtg(id, in);
|
||||
|
||||
if (id > 0x60) {
|
||||
if (id >= 0x60) {
|
||||
retval.setClass(CLASS_ARRAY);
|
||||
} else if (id > 0x40) {
|
||||
} else if (id >= 0x40) {
|
||||
retval.setClass(CLASS_VALUE);
|
||||
} else {
|
||||
retval.setClass(CLASS_REF);
|
||||
@ -397,6 +345,22 @@ public abstract class Ptg implements Cloneable {
|
||||
return ptgClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug / diagnostic method to get this token's 'operand class' type.
|
||||
* @return 'R' for 'reference', 'V' for 'value', 'A' for 'array' and '.' for base tokens
|
||||
*/
|
||||
public final char getRVAType() {
|
||||
if (isBaseToken()) {
|
||||
return '.';
|
||||
}
|
||||
switch (ptgClass) {
|
||||
case Ptg.CLASS_REF: return 'R';
|
||||
case Ptg.CLASS_VALUE: return 'V';
|
||||
case Ptg.CLASS_ARRAY: return 'A';
|
||||
}
|
||||
throw new RuntimeException("Unknown operand class (" + ptgClass + ")");
|
||||
}
|
||||
|
||||
public abstract byte getDefaultOperandClass();
|
||||
|
||||
/**
|
||||
|
@ -245,6 +245,11 @@ public abstract class HeaderFooter implements org.apache.poi.ss.usermodel.Header
|
||||
public static String stripFields(String text) {
|
||||
int pos;
|
||||
|
||||
// Check we really got something to work on
|
||||
if(text == null || text.length() == 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
// Firstly, do the easy ones which are static
|
||||
for(int i=0; i<Field.ALL_FIELDS.size(); i++) {
|
||||
String seq = ((Field)Field.ALL_FIELDS.get(i)).sequence;
|
||||
@ -255,6 +260,7 @@ public abstract class HeaderFooter implements org.apache.poi.ss.usermodel.Header
|
||||
}
|
||||
|
||||
// Now do the tricky, dynamic ones
|
||||
// These are things like font sizes and font names
|
||||
text = text.replaceAll("\\&\\d+", "");
|
||||
text = text.replaceAll("\\&\".*?,.*?\"", "");
|
||||
|
||||
@ -290,9 +296,9 @@ public abstract class HeaderFooter implements org.apache.poi.ss.usermodel.Header
|
||||
public static final Field TIME_FIELD = new Field("&T");
|
||||
public static final Field NUM_PAGES_FIELD = new Field("&N");
|
||||
|
||||
public static final Field PICTURE_FIELD = new Field("&P");
|
||||
public static final Field PICTURE_FIELD = new Field("&G");
|
||||
|
||||
public static final PairField BOLD_FIELD = new PairField("&B"); // PAID
|
||||
public static final PairField BOLD_FIELD = new PairField("&B");
|
||||
public static final PairField ITALIC_FIELD = new PairField("&I");
|
||||
public static final PairField STRIKETHROUGH_FIELD = new PairField("&S");
|
||||
public static final PairField SUBSCRIPT_FIELD = new PairField("&Y");
|
||||
|
@ -27,20 +27,23 @@ import org.apache.poi.util.LittleEndian;
|
||||
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
|
||||
*/
|
||||
public class CellRangeAddress extends org.apache.poi.ss.util.CellRangeAddress {
|
||||
/*
|
||||
* TODO - replace org.apache.poi.hssf.util.Region
|
||||
*/
|
||||
public static final int ENCODED_SIZE = 8;
|
||||
|
||||
public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
super(firstRow, lastRow, firstCol, lastCol);
|
||||
}
|
||||
public CellRangeAddress() {
|
||||
super();
|
||||
}
|
||||
public CellRangeAddress(RecordInputStream in) {
|
||||
super(readUShortAndCheck(in), in.readUShort(), in.readUShort(), in.readUShort());
|
||||
}
|
||||
|
||||
private static int readUShortAndCheck(RecordInputStream in) {
|
||||
if (in.remaining() < ENCODED_SIZE) {
|
||||
// Ran out of data
|
||||
throw new RuntimeException("Ran out of data reading CellRangeAddress");
|
||||
}
|
||||
_firstRow = in.readUShort();
|
||||
_lastRow = in.readUShort();
|
||||
_firstCol = in.readUShort();
|
||||
_lastCol = in.readUShort();
|
||||
return in.readUShort();
|
||||
}
|
||||
}
|
||||
|
65
src/java/org/apache/poi/hssf/util/CellRangeAddress8Bit.java
Normal file
65
src/java/org/apache/poi/hssf/util/CellRangeAddress8Bit.java
Normal file
@ -0,0 +1,65 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.util;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.ss.util.CellRangeAddressBase;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
|
||||
*
|
||||
* Like {@link CellRangeAddress} except column fields are 8-bit.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class CellRangeAddress8Bit extends CellRangeAddressBase {
|
||||
|
||||
public static final int ENCODED_SIZE = 6;
|
||||
|
||||
public CellRangeAddress8Bit(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
super(firstRow, lastRow, firstCol, lastCol);
|
||||
}
|
||||
|
||||
public CellRangeAddress8Bit(RecordInputStream in) {
|
||||
super(readUShortAndCheck(in), in.readUShort(), in.readUByte(), in.readUByte());
|
||||
}
|
||||
|
||||
private static int readUShortAndCheck(RecordInputStream in) {
|
||||
if (in.remaining() < ENCODED_SIZE) {
|
||||
// Ran out of data
|
||||
throw new RuntimeException("Ran out of data reading CellRangeAddress");
|
||||
}
|
||||
return in.readUShort();
|
||||
}
|
||||
|
||||
public int serialize(int offset, byte[] data) {
|
||||
LittleEndian.putUShort(data, offset + 0, getFirstRow());
|
||||
LittleEndian.putUShort(data, offset + 2, getLastRow());
|
||||
LittleEndian.putByte(data, offset + 4, getFirstColumn());
|
||||
LittleEndian.putByte(data, offset + 5, getLastColumn());
|
||||
return ENCODED_SIZE;
|
||||
}
|
||||
|
||||
public CellRangeAddress8Bit copy() {
|
||||
return new CellRangeAddress8Bit(getFirstRow(), getLastRow(), getFirstColumn(), getLastColumn());
|
||||
}
|
||||
|
||||
public static int getEncodedSize(int numberOfItems) {
|
||||
return numberOfItems * ENCODED_SIZE;
|
||||
}
|
||||
}
|
@ -25,143 +25,29 @@ import org.apache.poi.util.LittleEndian;
|
||||
* Note - {@link SelectionRecord} uses the BIFF5 version of this structure
|
||||
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
|
||||
*/
|
||||
public class CellRangeAddress {
|
||||
public class CellRangeAddress extends CellRangeAddressBase {
|
||||
/*
|
||||
* TODO - replace org.apache.poi.hssf.util.Region
|
||||
*/
|
||||
public static final int ENCODED_SIZE = 8;
|
||||
|
||||
/** max 65536 rows in BIFF8 */
|
||||
public static final int LAST_ROW_INDEX = 0x00FFFF;
|
||||
/** max 256 columns in BIFF8 */
|
||||
public static final int LAST_COLUMN_INDEX = 0x00FF;
|
||||
|
||||
|
||||
protected int _firstRow;
|
||||
protected int _firstCol;
|
||||
protected int _lastRow;
|
||||
protected int _lastCol;
|
||||
|
||||
protected CellRangeAddress() {}
|
||||
public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
if(!isValid(firstRow, lastRow, firstCol, lastCol)) {
|
||||
throw new IllegalArgumentException("invalid cell range (" + firstRow + ", " + lastRow
|
||||
+ ", " + firstCol + ", " + lastCol + ")");
|
||||
}
|
||||
_firstRow = firstRow;
|
||||
_lastRow = convertM1ToMax(lastRow, LAST_ROW_INDEX);
|
||||
_firstCol = firstCol;
|
||||
_lastCol = convertM1ToMax(lastCol, LAST_COLUMN_INDEX);
|
||||
super(firstRow, lastRow, firstCol, lastCol);
|
||||
}
|
||||
|
||||
private static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn)
|
||||
{
|
||||
if(lastRow < 0 || lastRow > LAST_ROW_INDEX) {
|
||||
return false;
|
||||
}
|
||||
if(firstRow < 0 || firstRow > LAST_ROW_INDEX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(lastColumn < 0 || lastColumn > LAST_COLUMN_INDEX) {
|
||||
return false;
|
||||
}
|
||||
if(firstColumn < 0 || firstColumn > LAST_COLUMN_INDEX) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Range arithmetic is easier when using a large positive number for 'max row or column'
|
||||
* instead of <tt>-1</tt>.
|
||||
*/
|
||||
private static int convertM1ToMax(int lastIx, int maxIndex) {
|
||||
if(lastIx < 0) {
|
||||
return maxIndex;
|
||||
}
|
||||
return lastIx;
|
||||
}
|
||||
|
||||
public boolean isFullColumnRange() {
|
||||
return _firstRow == 0 && _lastRow == LAST_ROW_INDEX;
|
||||
}
|
||||
public boolean isFullRowRange() {
|
||||
return _firstCol == 0 && _lastCol == LAST_COLUMN_INDEX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return column number for the upper left hand corner
|
||||
*/
|
||||
public int getFirstColumn() {
|
||||
return _firstCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return row number for the upper left hand corner
|
||||
*/
|
||||
public int getFirstRow() {
|
||||
return _firstRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return column number for the lower right hand corner
|
||||
*/
|
||||
public int getLastColumn() {
|
||||
return _lastCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return row number for the lower right hand corner
|
||||
*/
|
||||
public int getLastRow() {
|
||||
return _lastRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _firstCol column number for the upper left hand corner
|
||||
*/
|
||||
public void setFirstColumn(int firstCol) {
|
||||
_firstCol = firstCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rowFrom row number for the upper left hand corner
|
||||
*/
|
||||
public void setFirstRow(int firstRow) {
|
||||
_firstRow = firstRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param colTo column number for the lower right hand corner
|
||||
*/
|
||||
public void setLastColumn(int lastCol) {
|
||||
_lastCol = lastCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rowTo row number for the lower right hand corner
|
||||
*/
|
||||
public void setLastRow(int lastRow) {
|
||||
_lastRow = lastRow;
|
||||
public int serialize(int offset, byte[] data) {
|
||||
LittleEndian.putUShort(data, offset + 0, getFirstRow());
|
||||
LittleEndian.putUShort(data, offset + 2, getLastRow());
|
||||
LittleEndian.putUShort(data, offset + 4, getFirstColumn());
|
||||
LittleEndian.putUShort(data, offset + 6, getLastColumn());
|
||||
return ENCODED_SIZE;
|
||||
}
|
||||
|
||||
public CellRangeAddress copy() {
|
||||
return new CellRangeAddress(_firstRow, _lastRow, _firstCol, _lastCol);
|
||||
return new CellRangeAddress(getFirstRow(), getLastRow(), getFirstColumn(), getLastColumn());
|
||||
}
|
||||
|
||||
public static int getEncodedSize(int numberOfItems) {
|
||||
return numberOfItems * ENCODED_SIZE;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getClass().getName() + " ["+_firstRow+", "+_lastRow+", "+_firstCol+", "+_lastCol+"]";
|
||||
}
|
||||
|
||||
public int serialize(int offset, byte[] data) {
|
||||
LittleEndian.putUShort(data, offset + 0, _firstRow);
|
||||
LittleEndian.putUShort(data, offset + 2, _lastRow);
|
||||
LittleEndian.putUShort(data, offset + 4, _firstCol);
|
||||
LittleEndian.putUShort(data, offset + 6, _lastCol);
|
||||
return ENCODED_SIZE;
|
||||
}
|
||||
}
|
||||
|
134
src/java/org/apache/poi/ss/util/CellRangeAddressBase.java
Normal file
134
src/java/org/apache/poi/ss/util/CellRangeAddressBase.java
Normal file
@ -0,0 +1,134 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.util;
|
||||
|
||||
|
||||
/**
|
||||
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
|
||||
*
|
||||
* Common subclass of 8-bit and 16-bit versions
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public abstract class CellRangeAddressBase {
|
||||
|
||||
/** max 65536 rows in BIFF8 */
|
||||
private static final int LAST_ROW_INDEX = 0x00FFFF;
|
||||
/** max 256 columns in BIFF8 */
|
||||
private static final int LAST_COLUMN_INDEX = 0x00FF;
|
||||
|
||||
private int _firstRow;
|
||||
private int _firstCol;
|
||||
private int _lastRow;
|
||||
private int _lastCol;
|
||||
|
||||
protected CellRangeAddressBase(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
if(!isValid(firstRow, lastRow, firstCol, lastCol)) {
|
||||
throw new IllegalArgumentException("invalid cell range (" + firstRow + ", " + lastRow
|
||||
+ ", " + firstCol + ", " + lastCol + ")");
|
||||
}
|
||||
_firstRow = firstRow;
|
||||
_lastRow =lastRow;
|
||||
_firstCol = firstCol;
|
||||
_lastCol = lastCol;
|
||||
}
|
||||
private static boolean isValid(int firstRow, int lastRow, int firstColumn, int lastColumn)
|
||||
{
|
||||
if(lastRow < 0 || lastRow > LAST_ROW_INDEX) {
|
||||
return false;
|
||||
}
|
||||
if(firstRow < 0 || firstRow > LAST_ROW_INDEX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(lastColumn < 0 || lastColumn > LAST_COLUMN_INDEX) {
|
||||
return false;
|
||||
}
|
||||
if(firstColumn < 0 || firstColumn > LAST_COLUMN_INDEX) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public final boolean isFullColumnRange() {
|
||||
return _firstRow == 0 && _lastRow == LAST_ROW_INDEX;
|
||||
}
|
||||
public final boolean isFullRowRange() {
|
||||
return _firstCol == 0 && _lastCol == LAST_COLUMN_INDEX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return column number for the upper left hand corner
|
||||
*/
|
||||
public final int getFirstColumn() {
|
||||
return _firstCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return row number for the upper left hand corner
|
||||
*/
|
||||
public final int getFirstRow() {
|
||||
return _firstRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return column number for the lower right hand corner
|
||||
*/
|
||||
public final int getLastColumn() {
|
||||
return _lastCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return row number for the lower right hand corner
|
||||
*/
|
||||
public final int getLastRow() {
|
||||
return _lastRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _firstCol column number for the upper left hand corner
|
||||
*/
|
||||
public final void setFirstColumn(int firstCol) {
|
||||
_firstCol = firstCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rowFrom row number for the upper left hand corner
|
||||
*/
|
||||
public final void setFirstRow(int firstRow) {
|
||||
_firstRow = firstRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param colTo column number for the lower right hand corner
|
||||
*/
|
||||
public final void setLastColumn(int lastCol) {
|
||||
_lastCol = lastCol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rowTo row number for the lower right hand corner
|
||||
*/
|
||||
public final void setLastRow(int lastRow) {
|
||||
_lastRow = lastRow;
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
return getClass().getName() + " ["+_firstRow+", "+_lastRow+", "+_firstCol+", "+_lastCol+"]";
|
||||
}
|
||||
}
|
90
src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java
Normal file
90
src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java
Normal file
@ -0,0 +1,90 @@
|
||||
/* ====================================================================
|
||||
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.hpbf.dev;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.ddf.DefaultEscherRecordFactory;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.hpbf.HPBFDocument;
|
||||
import org.apache.poi.hpbf.model.QuillContents;
|
||||
import org.apache.poi.hpbf.model.qcbits.QCBit;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
/**
|
||||
* For dumping out the PLC contents of QC Bits of a
|
||||
* HPBF (Publisher) file, while we try to figure out
|
||||
* what the format of them is.
|
||||
*/
|
||||
public class PLCDumper {
|
||||
private HPBFDocument doc;
|
||||
private QuillContents qc;
|
||||
|
||||
public PLCDumper(HPBFDocument doc) {
|
||||
this.doc = doc;
|
||||
qc = doc.getQuillContents();
|
||||
}
|
||||
public PLCDumper(POIFSFileSystem fs) throws IOException {
|
||||
this(new HPBFDocument(fs));
|
||||
}
|
||||
public PLCDumper(InputStream inp) throws IOException {
|
||||
this(new POIFSFileSystem(inp));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if(args.length < 1) {
|
||||
System.err.println("Use:");
|
||||
System.err.println(" PLCDumper <filename>");
|
||||
System.exit(1);
|
||||
}
|
||||
PLCDumper dump = new PLCDumper(
|
||||
new FileInputStream(args[0])
|
||||
);
|
||||
|
||||
System.out.println("Dumping " + args[0]);
|
||||
dump.dumpPLC();
|
||||
}
|
||||
|
||||
private void dumpPLC() {
|
||||
QuillContents qc = doc.getQuillContents();
|
||||
QCBit[] bits = qc.getBits();
|
||||
|
||||
for(int i=0; i<bits.length; i++) {
|
||||
if(bits[i] == null) continue;
|
||||
if(bits[i].getBitType().equals("PLC ")) {
|
||||
dumpBit(bits[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpBit(QCBit bit, int index) {
|
||||
System.out.println("");
|
||||
System.out.println("Dumping " + bit.getBitType() + " bit at " + index);
|
||||
System.out.println(" Is a " + bit.getThingType() + ", number is " + bit.getOptA());
|
||||
System.out.println(" Starts at " + bit.getDataOffset() + " (" + Integer.toHexString(bit.getDataOffset()) + ")");
|
||||
System.out.println(" Runs for " + bit.getLength() + " (" + Integer.toHexString(bit.getLength()) + ")");
|
||||
|
||||
System.out.println(HexDump.dump(bit.getData(), 0, 0));
|
||||
}
|
||||
}
|
@ -70,6 +70,7 @@ public final class QuillContents extends HPBFPart {
|
||||
bits[i].setOptA(optA);
|
||||
bits[i].setOptB(optB);
|
||||
bits[i].setOptC(optC);
|
||||
bits[i].setDataOffset(from);
|
||||
} else {
|
||||
// Doesn't have data
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ public abstract class QCBit {
|
||||
protected int optB;
|
||||
protected int optC;
|
||||
|
||||
protected int dataOffset;
|
||||
|
||||
public QCBit(String thingType, String bitType, byte[] data) {
|
||||
this.thingType = thingType;
|
||||
this.bitType = bitType;
|
||||
@ -66,4 +68,15 @@ public abstract class QCBit {
|
||||
public void setOptC(int optC) {
|
||||
this.optC = optC;
|
||||
}
|
||||
|
||||
public int getDataOffset() {
|
||||
return dataOffset;
|
||||
}
|
||||
public void setDataOffset(int offset) {
|
||||
this.dataOffset = offset;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return data.length;
|
||||
}
|
||||
}
|
||||
|
@ -167,6 +167,13 @@ public class HeaderStories {
|
||||
if(stripFields) {
|
||||
return Range.stripFields(text);
|
||||
}
|
||||
// If you create a header/footer, then remove it again, word
|
||||
// will leave \r\r. Turn these back into an empty string,
|
||||
// which is more what you'd expect
|
||||
if(text.equals("\r\r")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -59,11 +59,11 @@ public class TextPublisherTextExtractor extends TestCase {
|
||||
|
||||
assertEquals(
|
||||
"This is some text on the first page\n" +
|
||||
"It’s in times new roman, font size 10, all normal\n" +
|
||||
"It\u2019s in times new roman, font size 10, all normal\n" +
|
||||
"" +
|
||||
"This is in bold and italic\n" +
|
||||
"It’s Arial, 20 point font\n" +
|
||||
"It’s in the second textbox on the first page\n" +
|
||||
"It\u2019s Arial, 20 point font\n" +
|
||||
"It\u2019s in the second textbox on the first page\n" +
|
||||
"" +
|
||||
"This is the second page\n\n" +
|
||||
"" +
|
||||
@ -102,4 +102,36 @@ public class TextPublisherTextExtractor extends TestCase {
|
||||
, text
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* We have the same file saved for Publisher 98, Publisher
|
||||
* 2000 and Publisher 2007. Check they all agree.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testMultipleVersions() throws Exception {
|
||||
File f;
|
||||
HPBFDocument doc;
|
||||
|
||||
f = new File(dir, "Sample.pub");
|
||||
doc = new HPBFDocument(
|
||||
new FileInputStream(f)
|
||||
);
|
||||
String s2007 = (new PublisherTextExtractor(doc)).getText();
|
||||
|
||||
f = new File(dir, "Sample2000.pub");
|
||||
doc = new HPBFDocument(
|
||||
new FileInputStream(f)
|
||||
);
|
||||
String s2000 = (new PublisherTextExtractor(doc)).getText();
|
||||
|
||||
f = new File(dir, "Sample98.pub");
|
||||
doc = new HPBFDocument(
|
||||
new FileInputStream(f)
|
||||
);
|
||||
String s98 = (new PublisherTextExtractor(doc)).getText();
|
||||
|
||||
// Check they all agree
|
||||
assertEquals(s2007, s2000);
|
||||
assertEquals(s2007, s98);
|
||||
}
|
||||
}
|
||||
|
@ -47,4 +47,38 @@ public class TestEscherParts extends TestCase {
|
||||
|
||||
// TODO - check the contents
|
||||
}
|
||||
|
||||
public void testComplex() throws Exception {
|
||||
File f = new File(dir, "SampleBrochure.pub");
|
||||
HPBFDocument doc = new HPBFDocument(
|
||||
new FileInputStream(f)
|
||||
);
|
||||
|
||||
EscherStm es = doc.getEscherStm();
|
||||
EscherDelayStm eds = doc.getEscherDelayStm();
|
||||
|
||||
assertNotNull(es);
|
||||
assertNotNull(eds);
|
||||
|
||||
assertEquals(30, es.getEscherRecords().length);
|
||||
assertEquals(19, eds.getEscherRecords().length);
|
||||
|
||||
// TODO - check contents
|
||||
|
||||
|
||||
// Now do another complex file
|
||||
f = new File(dir, "SampleNewsletter.pub");
|
||||
doc = new HPBFDocument(
|
||||
new FileInputStream(f)
|
||||
);
|
||||
|
||||
es = doc.getEscherStm();
|
||||
eds = doc.getEscherDelayStm();
|
||||
|
||||
assertNotNull(es);
|
||||
assertNotNull(eds);
|
||||
|
||||
assertEquals(51, es.getEscherRecords().length);
|
||||
assertEquals(92, eds.getEscherRecords().length);
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ public class TestWordExtractor extends TestCase {
|
||||
extractor = new WordExtractor(doc);
|
||||
|
||||
assertEquals(
|
||||
"\n\nThis is a simple header, with a \u20ac euro symbol in it.\n\n",
|
||||
"This is a simple header, with a \u20ac euro symbol in it.\n\n",
|
||||
extractor.getHeaderText()
|
||||
);
|
||||
text = extractor.getText();
|
||||
@ -217,7 +217,7 @@ public class TestWordExtractor extends TestCase {
|
||||
extractor = new WordExtractor(doc);
|
||||
|
||||
assertEquals(
|
||||
"\n\nThe footer, with Moli\u00e8re, has Unicode in it.\n",
|
||||
"The footer, with Moli\u00e8re, has Unicode in it.\n",
|
||||
extractor.getFooterText()
|
||||
);
|
||||
text = extractor.getText();
|
||||
|
@ -123,7 +123,7 @@ public class TestHeaderStories extends TestCase {
|
||||
|
||||
assertEquals("", hs.getFirstHeader());
|
||||
assertEquals("", hs.getEvenHeader());
|
||||
assertEquals("\r\r", hs.getOddHeader());
|
||||
assertEquals("", hs.getOddHeader()); // Was \r\r but gets emptied
|
||||
|
||||
|
||||
assertEquals("", hs.getFirstFooter());
|
||||
@ -181,13 +181,13 @@ public class TestHeaderStories extends TestCase {
|
||||
public void testUnicode() throws Exception {
|
||||
HeaderStories hs = new HeaderStories(unicode);
|
||||
|
||||
assertEquals("\r\r", hs.getFirstHeader());
|
||||
assertEquals("\r\r", hs.getEvenHeader());
|
||||
assertEquals("", hs.getFirstHeader());
|
||||
assertEquals("", hs.getEvenHeader());
|
||||
assertEquals("This is a simple header, with a \u20ac euro symbol in it.\r\r\r", hs.getOddHeader());
|
||||
|
||||
|
||||
assertEquals("\r\r", hs.getFirstFooter());
|
||||
assertEquals("\r\r", hs.getEvenFooter());
|
||||
assertEquals("", hs.getFirstFooter());
|
||||
assertEquals("", hs.getEvenFooter());
|
||||
assertEquals("The footer, with Moli\u00e8re, has Unicode in it.\r\r", hs.getOddFooter());
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.ComparisonFailure;
|
||||
import junit.framework.TestCase;
|
||||
@ -63,18 +60,18 @@ public final class TestSharedFormulaRecord extends TestCase {
|
||||
public void testConvertSharedFormulasOperandClasses_bug45123() {
|
||||
|
||||
TestcaseRecordInputStream in = new TestcaseRecordInputStream(0, SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
|
||||
short encodedLen = in.readShort();
|
||||
Stack sharedFormula = Ptg.createParsedExpressionTokens(encodedLen, in);
|
||||
int encodedLen = in.readUShort();
|
||||
Ptg[] sharedFormula = Ptg.readTokens(encodedLen, in);
|
||||
|
||||
Stack convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 100, 200);
|
||||
Ptg[] convertedFormula = SharedFormulaRecord.convertSharedFormulas(sharedFormula, 100, 200);
|
||||
|
||||
RefPtg refPtg = (RefPtg) convertedFormula.get(1);
|
||||
RefPtg refPtg = (RefPtg) convertedFormula[1];
|
||||
assertEquals("$C101", refPtg.toFormulaString(null));
|
||||
if (refPtg.getPtgClass() == Ptg.CLASS_REF) {
|
||||
throw new AssertionFailedError("Identified bug 45123");
|
||||
}
|
||||
|
||||
confirmOperandClasses(toPtgArray(sharedFormula), toPtgArray(convertedFormula));
|
||||
confirmOperandClasses(sharedFormula, convertedFormula);
|
||||
}
|
||||
|
||||
private static void confirmOperandClasses(Ptg[] originalPtgs, Ptg[] convertedPtgs) {
|
||||
@ -88,10 +85,4 @@ public final class TestSharedFormulaRecord extends TestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Ptg[] toPtgArray(List list) {
|
||||
Ptg[] result = new Ptg[list.size()];
|
||||
list.toArray(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
@ -18,6 +17,7 @@
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@ -26,9 +26,7 @@ import junit.framework.TestCase;
|
||||
* class works correctly. Test data taken directly from a real
|
||||
* Excel file.
|
||||
*/
|
||||
public class TestTableRecord
|
||||
extends TestCase
|
||||
{
|
||||
public final class TestTableRecord extends TestCase {
|
||||
byte[] header = new byte[] {
|
||||
0x36, 02, 0x10, 00, // sid=x236, 16 bytes long
|
||||
};
|
||||
@ -44,21 +42,15 @@ public class TestTableRecord
|
||||
00, 00 // col inp col 0
|
||||
};
|
||||
|
||||
public TestTableRecord(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void testLoad()
|
||||
throws Exception
|
||||
{
|
||||
public void testLoad() {
|
||||
|
||||
TableRecord record = new TableRecord(new TestcaseRecordInputStream((short)0x236, (short)data.length, data));
|
||||
|
||||
assertEquals(3, record.getRowFirst());
|
||||
assertEquals(8, record.getRowLast());
|
||||
assertEquals(4, record.getColFirst());
|
||||
assertEquals(6, record.getColLast());
|
||||
CellRangeAddress8Bit range = record.getRange();
|
||||
assertEquals(3, range.getFirstRow());
|
||||
assertEquals(8, range.getLastRow());
|
||||
assertEquals(4, range.getFirstColumn());
|
||||
assertEquals(6, range.getLastColumn());
|
||||
assertEquals(0, record.getFlags());
|
||||
assertEquals(4, record.getRowInputRow());
|
||||
assertEquals(1, record.getColInputRow());
|
||||
@ -87,17 +79,13 @@ public class TestTableRecord
|
||||
// .col input col = 0
|
||||
// [/TABLE]
|
||||
|
||||
TableRecord record = new TableRecord();
|
||||
record.setRowFirst((short)3);
|
||||
record.setRowLast((short)8);
|
||||
record.setColFirst((short)4);
|
||||
record.setColLast((short)6);
|
||||
CellRangeAddress8Bit crab = new CellRangeAddress8Bit(3, 8, 4, 6);
|
||||
TableRecord record = new TableRecord(crab);
|
||||
record.setFlags((byte)0);
|
||||
record.setReserved((byte)0);
|
||||
record.setRowInputRow((short)4);
|
||||
record.setColInputRow((short)1);
|
||||
record.setRowInputCol((short)0x4076);
|
||||
record.setColInputCol((short)0);
|
||||
record.setRowInputRow(4);
|
||||
record.setColInputRow(1);
|
||||
record.setRowInputCol(0x4076);
|
||||
record.setColInputCol(0);
|
||||
|
||||
byte [] recordBytes = record.serialize();
|
||||
assertEquals(recordBytes.length - 4, data.length);
|
||||
|
@ -20,6 +20,7 @@ package org.apache.poi.hssf.record.formula;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
|
||||
import org.apache.poi.hssf.record.UnicodeString;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
@ -128,4 +129,28 @@ public final class TestArrayPtg extends TestCase {
|
||||
}
|
||||
assertEquals("{TRUE,\"ABCD\";\"E\",0.0;FALSE,\"FG\"}", actualFormula);
|
||||
}
|
||||
|
||||
/**
|
||||
* worth checking since AttrPtg.sid=0x20 and Ptg.CLASS_* = (0x00, 0x20, and 0x40)
|
||||
*/
|
||||
public void testOperandClassDecoding() {
|
||||
confirmOperandClassDecoding(Ptg.CLASS_REF);
|
||||
confirmOperandClassDecoding(Ptg.CLASS_VALUE);
|
||||
confirmOperandClassDecoding(Ptg.CLASS_ARRAY);
|
||||
}
|
||||
|
||||
private static void confirmOperandClassDecoding(byte operandClass) {
|
||||
byte[] fullData = new byte[ENCODED_PTG_DATA.length + ENCODED_CONSTANT_DATA.length];
|
||||
System.arraycopy(ENCODED_PTG_DATA, 0, fullData, 0, ENCODED_PTG_DATA.length);
|
||||
System.arraycopy(ENCODED_CONSTANT_DATA, 0, fullData, ENCODED_PTG_DATA.length, ENCODED_CONSTANT_DATA.length);
|
||||
|
||||
// Force encoded operand class for tArray
|
||||
fullData[0] = (byte) (ArrayPtg.sid + operandClass);
|
||||
|
||||
RecordInputStream in = new TestcaseRecordInputStream(ArrayPtg.sid, fullData);
|
||||
|
||||
Ptg[] ptgs = Ptg.readTokens(ENCODED_PTG_DATA.length, in);
|
||||
ArrayPtg aPtg = (ArrayPtg) ptgs[0];
|
||||
assertEquals(operandClass, aPtg.getPtgClass());
|
||||
}
|
||||
}
|
||||
|
@ -87,8 +87,8 @@ public final class TestHSSFHeaderFooter extends TestCase {
|
||||
assertTrue(head.areFieldsStripped());
|
||||
|
||||
// Now even more complex
|
||||
head.setCenter("HEADER TEXT &P&N&D&T&Z&F&F&A&G");
|
||||
assertEquals("HEADER TEXT &G", head.getCenter());
|
||||
head.setCenter("HEADER TEXT &P&N&D&T&Z&F&F&A&G&X END");
|
||||
assertEquals("HEADER TEXT END", head.getCenter());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user