merged with trunk r657726
git-svn-id: https://svn.apache.org/repos/asf/poi/tags/REL_3_1_BETA2@657731 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
28b6f4e2a3
commit
294932abb8
|
@ -55,10 +55,10 @@ public class HSSFCellUtil
|
|||
*/
|
||||
public static HSSFRow getRow( int rowCounter, HSSFSheet sheet )
|
||||
{
|
||||
HSSFRow row = sheet.getRow( (short) rowCounter );
|
||||
HSSFRow row = sheet.getRow( rowCounter );
|
||||
if ( row == null )
|
||||
{
|
||||
row = sheet.createRow( (short) rowCounter );
|
||||
row = sheet.createRow( rowCounter );
|
||||
}
|
||||
|
||||
return row;
|
||||
|
@ -66,7 +66,8 @@ public class HSSFCellUtil
|
|||
|
||||
|
||||
/**
|
||||
* Get a specific cell from a row. If the cell doesn't exist, then create it.
|
||||
* Get a specific cell from a row. If the cell doesn't exist,
|
||||
* then create it.
|
||||
*
|
||||
*@param row The row that the cell is part of
|
||||
*@param column The column index that the cell is in.
|
||||
|
@ -74,11 +75,11 @@ public class HSSFCellUtil
|
|||
*/
|
||||
public static HSSFCell getCell( HSSFRow row, int column )
|
||||
{
|
||||
HSSFCell cell = row.getCell( (short) column );
|
||||
HSSFCell cell = row.getCell( column );
|
||||
|
||||
if ( cell == null )
|
||||
{
|
||||
cell = row.createCell( (short) column );
|
||||
cell = row.createCell( (short)column );
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
@ -98,7 +99,7 @@ public class HSSFCellUtil
|
|||
{
|
||||
HSSFCell cell = getCell( row, column );
|
||||
|
||||
cell.setCellValue( value );
|
||||
cell.setCellValue(new HSSFRichTextString(value));
|
||||
if ( style != null )
|
||||
{
|
||||
cell.setCellStyle( style );
|
||||
|
@ -222,7 +223,7 @@ public class HSSFCellUtil
|
|||
public static HSSFCell translateUnicodeValues( HSSFCell cell )
|
||||
{
|
||||
|
||||
String s = cell.getStringCellValue();
|
||||
String s = cell.getRichStringCellValue().getString();
|
||||
boolean foundUnicode = false;
|
||||
|
||||
for ( Iterator i = unicodeMappings.entrySet().iterator(); i.hasNext(); )
|
||||
|
|
|
@ -37,6 +37,17 @@
|
|||
|
||||
<!-- Don't forget to update status.xml too! -->
|
||||
<release version="3.1-beta2" date="2008-05-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">44306 - fixed reading/writing of AttrPtg(type=choose) and method toFormulaString() for CHOOSE formulas</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">24207 - added HSSFName.isDeleted() to check if the name points to cell that no longer exists</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">40414 - fixed selected/active sheet after removing sheet from workbook</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44523 - fixed workbook sheet selection and focus</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45000 - Fixed NPE in ListLevel when numberText is null</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44985 - Properly update TextSpecInfoAtom when the parent text is changed</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">41187 - fixed HSSFSheet to properly read xls files without ROW records</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44950 - fixed HSSFFormulaEvaluator.evaluateInCell() and Area3DEval.getValue() also added validation for number of elements in AreaEvals</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">42570 - fixed LabelRecord to use empty string instead of null when the length is zero.</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">42564 - fixed ArrayPtg to use ConstantValueParser. Fixed a few other ArrayPtg encoding issues.</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Follow-on from 28754 - StringPtg.toFormulaString() should escape double quotes</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44929 - Improved error handling in HSSFWorkbook when attempting to read a BIFF5 file</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44675 - Parameter operand classes (function metadata) required to encode SUM() etc properly. Added parse validation for number of parameters</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44921 - allow Ptg.writeBytes() to be called on relative ref Ptgs (RefN* and AreaN*)</action>
|
||||
|
|
|
@ -1225,7 +1225,19 @@ Examples:
|
|||
// Do something with this corner cell
|
||||
}
|
||||
}
|
||||
</source>
|
||||
</source>
|
||||
<p>
|
||||
Note, when a cell is deleted, Excel does not delete the attached named range.
|
||||
As result, workbook can contain named ranges that point to cells that no longer exist.
|
||||
You should check the validity of a reference before constructing AreaReference
|
||||
</p>
|
||||
<source>
|
||||
if(hssfName.isDeleted()){
|
||||
//named range points to a deleted cell.
|
||||
} else {
|
||||
AreaReference ref = new AreaReference(hssfName.getReference());
|
||||
}
|
||||
</source>
|
||||
</section>
|
||||
<anchor id="CellComments"/>
|
||||
<section><title>Cell Comments</title>
|
||||
|
|
|
@ -34,6 +34,17 @@
|
|||
<!-- Don't forget to update changes.xml too! -->
|
||||
<changes>
|
||||
<release version="3.1-beta2" date="2008-05-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">44306 - fixed reading/writing of AttrPtg(type=choose) and method toFormulaString() for CHOOSE formulas</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">24207 - added HSSFName.isDeleted() to check if the name points to cell that no longer exists</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">40414 - fixed selected/active sheet after removing sheet from workbook</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44523 - fixed workbook sheet selection and focus</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45000 - Fixed NPE in ListLevel when numberText is null</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44985 - Properly update TextSpecInfoAtom when the parent text is changed</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">41187 - fixed HSSFSheet to properly read xls files without ROW records</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44950 - fixed HSSFFormulaEvaluator.evaluateInCell() and Area3DEval.getValue() also added validation for number of elements in AreaEvals</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">42570 - fixed LabelRecord to use empty string instead of null when the length is zero.</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">42564 - fixed ArrayPtg to use ConstantValueParser. Fixed a few other ArrayPtg encoding issues.</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Follow-on from 28754 - StringPtg.toFormulaString() should escape double quotes</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44929 - Improved error handling in HSSFWorkbook when attempting to read a BIFF5 file</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44675 - Parameter operand classes (function metadata) required to encode SUM() etc properly. Added parse validation for number of parameters</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">44921 - allow Ptg.writeBytes() to be called on relative ref Ptgs (RefN* and AreaN*)</action>
|
||||
|
|
|
@ -37,14 +37,14 @@ where $TAG is the release tag, for example, REL_3_1_BETA1
|
|||
3. Checkout the tagged version
|
||||
{code}
|
||||
cd tags
|
||||
svn checkout https://svn.apache.org/repos/asf/poi/tags/TAG
|
||||
svn checkout https://svn.apache.org/repos/asf/poi/tags/$TAG
|
||||
{code}
|
||||
|
||||
4. Merge (if required)
|
||||
|
||||
{code}
|
||||
cd $TAG
|
||||
$ svn merge https://svn.apache.org/repos/asf/poi/tags/TAG \
|
||||
$ svn merge https://svn.apache.org/repos/asf/poi/tags/$TAG \
|
||||
https://svn.apache.org/repos/asf/poi/trunk
|
||||
{code}
|
||||
|
||||
|
|
|
@ -15,22 +15,20 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
/*
|
||||
* BiffViewer.java
|
||||
*
|
||||
* Created on November 13, 2001, 9:23 AM
|
||||
*/
|
||||
package org.apache.poi.hssf.dev;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.poi.hssf.record.*;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.HexDump;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Utillity for reading in BIFF8 records and displaying data from them.
|
||||
*
|
||||
|
@ -38,38 +36,26 @@ import java.util.ArrayList;
|
|||
*@author Glen Stampoultzis (glens at apache.org)
|
||||
*@see #main
|
||||
*/
|
||||
|
||||
public class BiffViewer {
|
||||
String filename;
|
||||
public final class BiffViewer {
|
||||
private final File _inputFile;
|
||||
private boolean dump;
|
||||
private final PrintStream _ps;
|
||||
|
||||
|
||||
/**
|
||||
* Creates new BiffViewer
|
||||
*
|
||||
*@param args
|
||||
*/
|
||||
|
||||
public BiffViewer(String[] args) {
|
||||
if (args.length > 0) {
|
||||
filename = args[0];
|
||||
} else {
|
||||
System.out.println("BIFFVIEWER REQUIRES A FILENAME***");
|
||||
}
|
||||
public BiffViewer(File inFile, PrintStream ps) {
|
||||
_inputFile = inFile;
|
||||
_ps = ps;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method run starts up BiffViewer...
|
||||
*/
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
POIFSFileSystem fs =
|
||||
new POIFSFileSystem(new FileInputStream(filename));
|
||||
InputStream stream =
|
||||
fs.createDocumentInputStream("Workbook");
|
||||
createRecords(stream, dump);
|
||||
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(_inputFile));
|
||||
InputStream stream = fs.createDocumentInputStream("Workbook");
|
||||
createRecords(stream, dump, _ps);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -86,451 +72,306 @@ public class BiffViewer {
|
|||
* InputStream
|
||||
*@exception RecordFormatException on error processing the InputStream
|
||||
*/
|
||||
|
||||
public static Record[] createRecords(InputStream in, boolean dump)
|
||||
public static Record[] createRecords(InputStream in, boolean dump, PrintStream ps)
|
||||
throws RecordFormatException {
|
||||
ArrayList records = new ArrayList();
|
||||
RecordDetails activeRecord = null;
|
||||
|
||||
try {
|
||||
BiffviewRecordInputStream recStream = new BiffviewRecordInputStream(in);
|
||||
while (recStream.hasNextRecord()) {
|
||||
BiffviewRecordInputStream recStream = new BiffviewRecordInputStream(in);
|
||||
while (recStream.hasNextRecord()) {
|
||||
recStream.nextRecord();
|
||||
if (recStream.getSid() != 0) {
|
||||
Record record = createRecord (recStream);
|
||||
Record record = createRecord (recStream);
|
||||
if (record.getSid() != ContinueRecord.sid)
|
||||
{
|
||||
records.add(record);
|
||||
if (activeRecord != null)
|
||||
activeRecord.dump();
|
||||
activeRecord = new RecordDetails(recStream.getSid(), recStream.getLength(), (int)recStream.getPos(), record);
|
||||
activeRecord.dump(ps);
|
||||
activeRecord = new RecordDetails(recStream.getSid(), recStream.getLength(), (int)recStream.getPos(), record);
|
||||
}
|
||||
if (dump) {
|
||||
recStream.dumpBytes();
|
||||
}
|
||||
recStream.dumpBytes(ps);
|
||||
}
|
||||
}
|
||||
activeRecord.dump();
|
||||
} catch (IOException e) {
|
||||
throw new RecordFormatException("Error reading bytes", e);
|
||||
}
|
||||
}
|
||||
if (activeRecord != null) {
|
||||
activeRecord.dump(ps);
|
||||
}
|
||||
Record[] retval = new Record[records.size()];
|
||||
|
||||
retval = (Record[]) records.toArray(retval);
|
||||
records.toArray(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
private static void dumpNormal(Record record, int startloc, short rectype, short recsize)
|
||||
{
|
||||
//System.out.println("Offset 0x" + Integer.toHexString(startloc) + " (" + startloc + ")");
|
||||
System.out.println( "recordid = 0x" + Integer.toHexString( rectype ) + ", size = " + recsize );
|
||||
System.out.println( record.toString() );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Essentially a duplicate of RecordFactory. Kept seperate as not to screw
|
||||
* Essentially a duplicate of RecordFactory. Kept separate as not to screw
|
||||
* up non-debug operations.
|
||||
*
|
||||
*/
|
||||
private static Record createRecord( RecordInputStream in )
|
||||
{
|
||||
Record retval = null;
|
||||
|
||||
switch ( in.getSid() )
|
||||
{
|
||||
|
||||
case ChartRecord.sid:
|
||||
retval = new ChartRecord( in );
|
||||
break;
|
||||
return new ChartRecord( in );
|
||||
case ChartFormatRecord.sid:
|
||||
retval = new ChartFormatRecord( in );
|
||||
break;
|
||||
return new ChartFormatRecord( in );
|
||||
case SeriesRecord.sid:
|
||||
retval = new SeriesRecord( in );
|
||||
break;
|
||||
return new SeriesRecord( in );
|
||||
case BeginRecord.sid:
|
||||
retval = new BeginRecord( in );
|
||||
break;
|
||||
return new BeginRecord( in );
|
||||
case EndRecord.sid:
|
||||
retval = new EndRecord( in );
|
||||
break;
|
||||
return new EndRecord( in );
|
||||
case BOFRecord.sid:
|
||||
retval = new BOFRecord( in );
|
||||
break;
|
||||
return new BOFRecord( in );
|
||||
case InterfaceHdrRecord.sid:
|
||||
retval = new InterfaceHdrRecord( in );
|
||||
break;
|
||||
return new InterfaceHdrRecord( in );
|
||||
case MMSRecord.sid:
|
||||
retval = new MMSRecord( in );
|
||||
break;
|
||||
return new MMSRecord( in );
|
||||
case InterfaceEndRecord.sid:
|
||||
retval = new InterfaceEndRecord( in );
|
||||
break;
|
||||
return new InterfaceEndRecord( in );
|
||||
case WriteAccessRecord.sid:
|
||||
retval = new WriteAccessRecord( in );
|
||||
break;
|
||||
return new WriteAccessRecord( in );
|
||||
case CodepageRecord.sid:
|
||||
retval = new CodepageRecord( in );
|
||||
break;
|
||||
return new CodepageRecord( in );
|
||||
case DSFRecord.sid:
|
||||
retval = new DSFRecord( in );
|
||||
break;
|
||||
return new DSFRecord( in );
|
||||
case TabIdRecord.sid:
|
||||
retval = new TabIdRecord( in );
|
||||
break;
|
||||
return new TabIdRecord( in );
|
||||
case FnGroupCountRecord.sid:
|
||||
retval = new FnGroupCountRecord( in );
|
||||
break;
|
||||
return new FnGroupCountRecord( in );
|
||||
case WindowProtectRecord.sid:
|
||||
retval = new WindowProtectRecord( in );
|
||||
break;
|
||||
return new WindowProtectRecord( in );
|
||||
case ProtectRecord.sid:
|
||||
retval = new ProtectRecord( in );
|
||||
break;
|
||||
return new ProtectRecord( in );
|
||||
case PasswordRecord.sid:
|
||||
retval = new PasswordRecord( in );
|
||||
break;
|
||||
return new PasswordRecord( in );
|
||||
case ProtectionRev4Record.sid:
|
||||
retval = new ProtectionRev4Record( in );
|
||||
break;
|
||||
return new ProtectionRev4Record( in );
|
||||
case PasswordRev4Record.sid:
|
||||
retval = new PasswordRev4Record( in );
|
||||
break;
|
||||
return new PasswordRev4Record( in );
|
||||
case WindowOneRecord.sid:
|
||||
retval = new WindowOneRecord( in );
|
||||
break;
|
||||
return new WindowOneRecord( in );
|
||||
case BackupRecord.sid:
|
||||
retval = new BackupRecord( in );
|
||||
break;
|
||||
return new BackupRecord( in );
|
||||
case HideObjRecord.sid:
|
||||
retval = new HideObjRecord( in );
|
||||
break;
|
||||
return new HideObjRecord( in );
|
||||
case DateWindow1904Record.sid:
|
||||
retval = new DateWindow1904Record( in );
|
||||
break;
|
||||
return new DateWindow1904Record( in );
|
||||
case PrecisionRecord.sid:
|
||||
retval = new PrecisionRecord( in );
|
||||
break;
|
||||
return new PrecisionRecord( in );
|
||||
case RefreshAllRecord.sid:
|
||||
retval = new RefreshAllRecord( in );
|
||||
break;
|
||||
return new RefreshAllRecord( in );
|
||||
case BookBoolRecord.sid:
|
||||
retval = new BookBoolRecord( in );
|
||||
break;
|
||||
return new BookBoolRecord( in );
|
||||
case FontRecord.sid:
|
||||
retval = new FontRecord( in );
|
||||
break;
|
||||
return new FontRecord( in );
|
||||
case FormatRecord.sid:
|
||||
retval = new FormatRecord( in );
|
||||
break;
|
||||
return new FormatRecord( in );
|
||||
case ExtendedFormatRecord.sid:
|
||||
retval = new ExtendedFormatRecord( in );
|
||||
break;
|
||||
return new ExtendedFormatRecord( in );
|
||||
case StyleRecord.sid:
|
||||
retval = new StyleRecord( in );
|
||||
break;
|
||||
return new StyleRecord( in );
|
||||
case UseSelFSRecord.sid:
|
||||
retval = new UseSelFSRecord( in );
|
||||
break;
|
||||
return new UseSelFSRecord( in );
|
||||
case BoundSheetRecord.sid:
|
||||
retval = new BoundSheetRecord( in );
|
||||
break;
|
||||
return new BoundSheetRecord( in );
|
||||
case CountryRecord.sid:
|
||||
retval = new CountryRecord( in );
|
||||
break;
|
||||
return new CountryRecord( in );
|
||||
case SSTRecord.sid:
|
||||
retval = new SSTRecord( in );
|
||||
break;
|
||||
return new SSTRecord( in );
|
||||
case ExtSSTRecord.sid:
|
||||
retval = new ExtSSTRecord( in );
|
||||
break;
|
||||
return new ExtSSTRecord( in );
|
||||
case EOFRecord.sid:
|
||||
retval = new EOFRecord( in );
|
||||
break;
|
||||
return new EOFRecord( in );
|
||||
case IndexRecord.sid:
|
||||
retval = new IndexRecord( in );
|
||||
break;
|
||||
return new IndexRecord( in );
|
||||
case CalcModeRecord.sid:
|
||||
retval = new CalcModeRecord( in );
|
||||
break;
|
||||
return new CalcModeRecord( in );
|
||||
case CalcCountRecord.sid:
|
||||
retval = new CalcCountRecord( in );
|
||||
break;
|
||||
return new CalcCountRecord( in );
|
||||
case RefModeRecord.sid:
|
||||
retval = new RefModeRecord( in );
|
||||
break;
|
||||
return new RefModeRecord( in );
|
||||
case IterationRecord.sid:
|
||||
retval = new IterationRecord( in );
|
||||
break;
|
||||
return new IterationRecord( in );
|
||||
case DeltaRecord.sid:
|
||||
retval = new DeltaRecord( in );
|
||||
break;
|
||||
return new DeltaRecord( in );
|
||||
case SaveRecalcRecord.sid:
|
||||
retval = new SaveRecalcRecord( in );
|
||||
break;
|
||||
return new SaveRecalcRecord( in );
|
||||
case PrintHeadersRecord.sid:
|
||||
retval = new PrintHeadersRecord( in );
|
||||
break;
|
||||
return new PrintHeadersRecord( in );
|
||||
case PrintGridlinesRecord.sid:
|
||||
retval = new PrintGridlinesRecord( in );
|
||||
break;
|
||||
return new PrintGridlinesRecord( in );
|
||||
case GridsetRecord.sid:
|
||||
retval = new GridsetRecord( in );
|
||||
break;
|
||||
return new GridsetRecord( in );
|
||||
case DrawingGroupRecord.sid:
|
||||
retval = new DrawingGroupRecord( in );
|
||||
break;
|
||||
return new DrawingGroupRecord( in );
|
||||
case DrawingRecordForBiffViewer.sid:
|
||||
retval = new DrawingRecordForBiffViewer( in );
|
||||
break;
|
||||
return new DrawingRecordForBiffViewer( in );
|
||||
case DrawingSelectionRecord.sid:
|
||||
retval = new DrawingSelectionRecord( in );
|
||||
break;
|
||||
return new DrawingSelectionRecord( in );
|
||||
case GutsRecord.sid:
|
||||
retval = new GutsRecord( in );
|
||||
break;
|
||||
return new GutsRecord( in );
|
||||
case DefaultRowHeightRecord.sid:
|
||||
retval = new DefaultRowHeightRecord( in );
|
||||
break;
|
||||
return new DefaultRowHeightRecord( in );
|
||||
case WSBoolRecord.sid:
|
||||
retval = new WSBoolRecord( in );
|
||||
break;
|
||||
return new WSBoolRecord( in );
|
||||
case HeaderRecord.sid:
|
||||
retval = new HeaderRecord( in );
|
||||
break;
|
||||
return new HeaderRecord( in );
|
||||
case FooterRecord.sid:
|
||||
retval = new FooterRecord( in );
|
||||
break;
|
||||
return new FooterRecord( in );
|
||||
case HCenterRecord.sid:
|
||||
retval = new HCenterRecord( in );
|
||||
break;
|
||||
return new HCenterRecord( in );
|
||||
case VCenterRecord.sid:
|
||||
retval = new VCenterRecord( in );
|
||||
break;
|
||||
return new VCenterRecord( in );
|
||||
case PrintSetupRecord.sid:
|
||||
retval = new PrintSetupRecord( in );
|
||||
break;
|
||||
return new PrintSetupRecord( in );
|
||||
case DefaultColWidthRecord.sid:
|
||||
retval = new DefaultColWidthRecord( in );
|
||||
break;
|
||||
return new DefaultColWidthRecord( in );
|
||||
case DimensionsRecord.sid:
|
||||
retval = new DimensionsRecord( in );
|
||||
break;
|
||||
return new DimensionsRecord( in );
|
||||
case RowRecord.sid:
|
||||
retval = new RowRecord( in );
|
||||
break;
|
||||
return new RowRecord( in );
|
||||
case LabelSSTRecord.sid:
|
||||
retval = new LabelSSTRecord( in );
|
||||
break;
|
||||
return new LabelSSTRecord( in );
|
||||
case RKRecord.sid:
|
||||
retval = new RKRecord( in );
|
||||
break;
|
||||
return new RKRecord( in );
|
||||
case NumberRecord.sid:
|
||||
retval = new NumberRecord( in );
|
||||
break;
|
||||
return new NumberRecord( in );
|
||||
case DBCellRecord.sid:
|
||||
retval = new DBCellRecord( in );
|
||||
break;
|
||||
return new DBCellRecord( in );
|
||||
case WindowTwoRecord.sid:
|
||||
retval = new WindowTwoRecord( in );
|
||||
break;
|
||||
return new WindowTwoRecord( in );
|
||||
case SelectionRecord.sid:
|
||||
retval = new SelectionRecord( in );
|
||||
break;
|
||||
return new SelectionRecord( in );
|
||||
case ContinueRecord.sid:
|
||||
retval = new ContinueRecord( in );
|
||||
break;
|
||||
return new ContinueRecord( in );
|
||||
case LabelRecord.sid:
|
||||
retval = new LabelRecord( in );
|
||||
break;
|
||||
return new LabelRecord( in );
|
||||
case MulRKRecord.sid:
|
||||
retval = new MulRKRecord( in );
|
||||
break;
|
||||
return new MulRKRecord( in );
|
||||
case MulBlankRecord.sid:
|
||||
retval = new MulBlankRecord( in );
|
||||
break;
|
||||
return new MulBlankRecord( in );
|
||||
case BlankRecord.sid:
|
||||
retval = new BlankRecord( in );
|
||||
break;
|
||||
return new BlankRecord( in );
|
||||
case BoolErrRecord.sid:
|
||||
retval = new BoolErrRecord( in );
|
||||
break;
|
||||
return new BoolErrRecord( in );
|
||||
case ColumnInfoRecord.sid:
|
||||
retval = new ColumnInfoRecord( in );
|
||||
break;
|
||||
return new ColumnInfoRecord( in );
|
||||
case MergeCellsRecord.sid:
|
||||
retval = new MergeCellsRecord( in );
|
||||
break;
|
||||
return new MergeCellsRecord( in );
|
||||
case AreaRecord.sid:
|
||||
retval = new AreaRecord( in );
|
||||
break;
|
||||
return new AreaRecord( in );
|
||||
case DataFormatRecord.sid:
|
||||
retval = new DataFormatRecord( in );
|
||||
break;
|
||||
return new DataFormatRecord( in );
|
||||
case BarRecord.sid:
|
||||
retval = new BarRecord( in );
|
||||
break;
|
||||
return new BarRecord( in );
|
||||
case DatRecord.sid:
|
||||
retval = new DatRecord( in );
|
||||
break;
|
||||
return new DatRecord( in );
|
||||
case PlotGrowthRecord.sid:
|
||||
retval = new PlotGrowthRecord( in );
|
||||
break;
|
||||
return new PlotGrowthRecord( in );
|
||||
case UnitsRecord.sid:
|
||||
retval = new UnitsRecord( in );
|
||||
break;
|
||||
return new UnitsRecord( in );
|
||||
case FrameRecord.sid:
|
||||
retval = new FrameRecord( in );
|
||||
break;
|
||||
return new FrameRecord( in );
|
||||
case ValueRangeRecord.sid:
|
||||
retval = new ValueRangeRecord( in );
|
||||
break;
|
||||
return new ValueRangeRecord( in );
|
||||
case SeriesListRecord.sid:
|
||||
retval = new SeriesListRecord( in );
|
||||
break;
|
||||
return new SeriesListRecord( in );
|
||||
case FontBasisRecord.sid:
|
||||
retval = new FontBasisRecord( in );
|
||||
break;
|
||||
return new FontBasisRecord( in );
|
||||
case FontIndexRecord.sid:
|
||||
retval = new FontIndexRecord( in );
|
||||
break;
|
||||
return new FontIndexRecord( in );
|
||||
case LineFormatRecord.sid:
|
||||
retval = new LineFormatRecord( in );
|
||||
break;
|
||||
return new LineFormatRecord( in );
|
||||
case AreaFormatRecord.sid:
|
||||
retval = new AreaFormatRecord( in );
|
||||
break;
|
||||
return new AreaFormatRecord( in );
|
||||
case LinkedDataRecord.sid:
|
||||
retval = new LinkedDataRecord( in );
|
||||
break;
|
||||
return new LinkedDataRecord( in );
|
||||
case FormulaRecord.sid:
|
||||
retval = new FormulaRecord( in );
|
||||
break;
|
||||
return new FormulaRecord( in );
|
||||
case SheetPropertiesRecord.sid:
|
||||
retval = new SheetPropertiesRecord( in );
|
||||
break;
|
||||
return new SheetPropertiesRecord( in );
|
||||
case DefaultDataLabelTextPropertiesRecord.sid:
|
||||
retval = new DefaultDataLabelTextPropertiesRecord( in );
|
||||
break;
|
||||
return new DefaultDataLabelTextPropertiesRecord( in );
|
||||
case TextRecord.sid:
|
||||
retval = new TextRecord( in );
|
||||
break;
|
||||
return new TextRecord( in );
|
||||
case AxisParentRecord.sid:
|
||||
retval = new AxisParentRecord( in );
|
||||
break;
|
||||
return new AxisParentRecord( in );
|
||||
case AxisLineFormatRecord.sid:
|
||||
retval = new AxisLineFormatRecord( in );
|
||||
break;
|
||||
return new AxisLineFormatRecord( in );
|
||||
case SupBookRecord.sid:
|
||||
retval = new SupBookRecord( in );
|
||||
break;
|
||||
return new SupBookRecord( in );
|
||||
case ExternSheetRecord.sid:
|
||||
retval = new ExternSheetRecord( in );
|
||||
break;
|
||||
return new ExternSheetRecord( in );
|
||||
case SCLRecord.sid:
|
||||
retval = new SCLRecord( in );
|
||||
break;
|
||||
return new SCLRecord( in );
|
||||
case SeriesToChartGroupRecord.sid:
|
||||
retval = new SeriesToChartGroupRecord( in );
|
||||
break;
|
||||
return new SeriesToChartGroupRecord( in );
|
||||
case AxisUsedRecord.sid:
|
||||
retval = new AxisUsedRecord( in );
|
||||
break;
|
||||
return new AxisUsedRecord( in );
|
||||
case AxisRecord.sid:
|
||||
retval = new AxisRecord( in );
|
||||
break;
|
||||
return new AxisRecord( in );
|
||||
case CategorySeriesAxisRecord.sid:
|
||||
retval = new CategorySeriesAxisRecord( in );
|
||||
break;
|
||||
return new CategorySeriesAxisRecord( in );
|
||||
case AxisOptionsRecord.sid:
|
||||
retval = new AxisOptionsRecord( in );
|
||||
break;
|
||||
return new AxisOptionsRecord( in );
|
||||
case TickRecord.sid:
|
||||
retval = new TickRecord( in );
|
||||
break;
|
||||
return new TickRecord( in );
|
||||
case SeriesTextRecord.sid:
|
||||
retval = new SeriesTextRecord( in );
|
||||
break;
|
||||
return new SeriesTextRecord( in );
|
||||
case ObjectLinkRecord.sid:
|
||||
retval = new ObjectLinkRecord( in );
|
||||
break;
|
||||
return new ObjectLinkRecord( in );
|
||||
case PlotAreaRecord.sid:
|
||||
retval = new PlotAreaRecord( in );
|
||||
break;
|
||||
return new PlotAreaRecord( in );
|
||||
case SeriesIndexRecord.sid:
|
||||
retval = new SeriesIndexRecord( in );
|
||||
break;
|
||||
return new SeriesIndexRecord( in );
|
||||
case LegendRecord.sid:
|
||||
retval = new LegendRecord( in );
|
||||
break;
|
||||
return new LegendRecord( in );
|
||||
case LeftMarginRecord.sid:
|
||||
retval = new LeftMarginRecord( in );
|
||||
break;
|
||||
return new LeftMarginRecord( in );
|
||||
case RightMarginRecord.sid:
|
||||
retval = new RightMarginRecord( in );
|
||||
break;
|
||||
return new RightMarginRecord( in );
|
||||
case TopMarginRecord.sid:
|
||||
retval = new TopMarginRecord( in );
|
||||
break;
|
||||
return new TopMarginRecord( in );
|
||||
case BottomMarginRecord.sid:
|
||||
retval = new BottomMarginRecord( in );
|
||||
break;
|
||||
return new BottomMarginRecord( in );
|
||||
case PaletteRecord.sid:
|
||||
retval = new PaletteRecord( in );
|
||||
break;
|
||||
return new PaletteRecord( in );
|
||||
case StringRecord.sid:
|
||||
retval = new StringRecord( in );
|
||||
break;
|
||||
return new StringRecord( in );
|
||||
case NameRecord.sid:
|
||||
retval = new NameRecord( in );
|
||||
break;
|
||||
return new NameRecord( in );
|
||||
case PaneRecord.sid:
|
||||
retval = new PaneRecord( in );
|
||||
break;
|
||||
return new PaneRecord( in );
|
||||
case SharedFormulaRecord.sid:
|
||||
retval = new SharedFormulaRecord( in);
|
||||
break;
|
||||
return new SharedFormulaRecord( in);
|
||||
case ObjRecord.sid:
|
||||
retval = new ObjRecord( in);
|
||||
break;
|
||||
return new ObjRecord( in);
|
||||
case TextObjectRecord.sid:
|
||||
retval = new TextObjectRecord( in);
|
||||
break;
|
||||
return new TextObjectRecord( in);
|
||||
case HorizontalPageBreakRecord.sid:
|
||||
retval = new HorizontalPageBreakRecord( in);
|
||||
break;
|
||||
return new HorizontalPageBreakRecord( in);
|
||||
case VerticalPageBreakRecord.sid:
|
||||
retval = new VerticalPageBreakRecord( in);
|
||||
break;
|
||||
return new VerticalPageBreakRecord( in);
|
||||
case WriteProtectRecord.sid:
|
||||
retval = new WriteProtectRecord( in);
|
||||
break;
|
||||
return new WriteProtectRecord( in);
|
||||
case FilePassRecord.sid:
|
||||
retval = new FilePassRecord(in);
|
||||
break;
|
||||
return new FilePassRecord(in);
|
||||
case NoteRecord.sid:
|
||||
retval = new NoteRecord( in );
|
||||
break;
|
||||
return new NoteRecord( in );
|
||||
case FileSharingRecord.sid:
|
||||
retval = new FileSharingRecord( in );
|
||||
break;
|
||||
return new FileSharingRecord( in );
|
||||
case HyperlinkRecord.sid:
|
||||
retval = new HyperlinkRecord( in );
|
||||
break;
|
||||
default:
|
||||
retval = new UnknownRecord( in );
|
||||
return new HyperlinkRecord( in );
|
||||
}
|
||||
return retval;
|
||||
return new UnknownRecord( in );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method setDump - hex dump out data or not.
|
||||
*
|
||||
*@param dump
|
||||
*/
|
||||
|
||||
public void setDump(boolean dump) {
|
||||
this.dump = dump;
|
||||
}
|
||||
|
@ -552,33 +393,44 @@ public class BiffViewer {
|
|||
*
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.setProperty("poi.deserialize.escher", "true");
|
||||
|
||||
if (args.length == 0) {
|
||||
System.out.println( "Biff viewer needs a filename" );
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
System.setProperty("poi.deserialize.escher", "true");
|
||||
|
||||
if (args.length == 0)
|
||||
{
|
||||
System.out.println( "Biff viewer needs a filename" );
|
||||
String inFileName = args[0];
|
||||
File inputFile = new File(inFileName);
|
||||
if(!inputFile.exists()) {
|
||||
throw new RuntimeException("specified inputFile '" + inFileName + "' does not exist");
|
||||
}
|
||||
else
|
||||
{
|
||||
BiffViewer viewer = new BiffViewer(args);
|
||||
if ((args.length > 1) && args[1].equals("on")) {
|
||||
viewer.setDump(true);
|
||||
}
|
||||
if ((args.length > 1) && args[1].equals("bfd")) {
|
||||
POIFSFileSystem fs =
|
||||
new POIFSFileSystem(new FileInputStream(args[0]));
|
||||
InputStream stream =
|
||||
fs.createDocumentInputStream("Workbook");
|
||||
int size = stream.available();
|
||||
byte[] data = new byte[size];
|
||||
|
||||
stream.read(data);
|
||||
HexDump.dump(data, 0, System.out, 0);
|
||||
} else {
|
||||
viewer.run();
|
||||
}
|
||||
PrintStream ps;
|
||||
if (false) { // set to true to output to file
|
||||
OutputStream os = new FileOutputStream(inFileName + ".out");
|
||||
ps = new PrintStream(os);
|
||||
} else {
|
||||
ps = System.out;
|
||||
}
|
||||
BiffViewer viewer = new BiffViewer(inputFile, ps);
|
||||
|
||||
if (args.length > 1 && args[1].equals("on")) {
|
||||
viewer.setDump(true);
|
||||
}
|
||||
if (args.length > 1 && args[1].equals("bfd")) {
|
||||
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(inputFile));
|
||||
InputStream stream = fs.createDocumentInputStream("Workbook");
|
||||
int size = stream.available();
|
||||
byte[] data = new byte[size];
|
||||
|
||||
stream.read(data);
|
||||
HexDump.dump(data, 0, System.out, 0);
|
||||
} else {
|
||||
viewer.run();
|
||||
}
|
||||
ps.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -587,7 +439,7 @@ public class BiffViewer {
|
|||
/**
|
||||
* This record supports dumping of completed continue records.
|
||||
*/
|
||||
static class RecordDetails
|
||||
private static final class RecordDetails
|
||||
{
|
||||
short rectype, recsize;
|
||||
int startloc;
|
||||
|
@ -616,18 +468,19 @@ public class BiffViewer {
|
|||
return record;
|
||||
}
|
||||
|
||||
public void dump() throws IOException
|
||||
{
|
||||
dumpNormal(record, startloc, rectype, recsize);
|
||||
public void dump(PrintStream ps) {
|
||||
ps.println("Offset 0x" + Integer.toHexString(startloc) + " (" + startloc + ")");
|
||||
ps.println( "recordid = 0x" + Integer.toHexString( rectype ) + ", size = " + recsize );
|
||||
ps.println( record.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
static class BiffviewRecordInputStream extends RecordInputStream {
|
||||
private static final class BiffviewRecordInputStream extends RecordInputStream {
|
||||
public BiffviewRecordInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
public void dumpBytes() {
|
||||
HexDump.dump(this.data, 0, this.currentLength);
|
||||
public void dumpBytes(PrintStream ps) {
|
||||
ps.println(HexDump.dump(this.data, 0, this.currentLength));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1000,7 +1000,7 @@ end;
|
|||
|
||||
if (ptg instanceof AttrPtg) {
|
||||
AttrPtg attrPtg = ((AttrPtg) ptg);
|
||||
if (attrPtg.isOptimizedIf()) {
|
||||
if (attrPtg.isOptimizedIf() || attrPtg.isOptimizedChoose() || attrPtg.isGoto()) {
|
||||
continue;
|
||||
}
|
||||
if (attrPtg.isSpace()) {
|
||||
|
@ -1014,6 +1014,9 @@ end;
|
|||
// similar to tAttrSpace - RPN is violated
|
||||
continue;
|
||||
}
|
||||
if (!attrPtg.isSum()) {
|
||||
throw new RuntimeException("Unexpected tAttr: " + attrPtg.toString());
|
||||
}
|
||||
}
|
||||
|
||||
final OperationPtg o = (OperationPtg) ptg;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -15,13 +14,7 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
* LabelRecord.java
|
||||
*
|
||||
* Created on November 11, 2001, 12:51 PM
|
||||
*/
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
/**
|
||||
|
@ -33,14 +26,10 @@ package org.apache.poi.hssf.record;
|
|||
* @version 2.0-pre
|
||||
* @see org.apache.poi.hssf.record.LabelSSTRecord
|
||||
*/
|
||||
|
||||
public class LabelRecord
|
||||
extends Record
|
||||
implements CellValueRecordInterface
|
||||
{
|
||||
public final class LabelRecord extends Record implements CellValueRecordInterface {
|
||||
public final static short sid = 0x204;
|
||||
//private short field_1_row;
|
||||
private int field_1_row;
|
||||
|
||||
private int field_1_row;
|
||||
private short field_2_column;
|
||||
private short field_3_xf_index;
|
||||
private short field_4_string_len;
|
||||
|
@ -85,35 +74,30 @@ public class LabelRecord
|
|||
|
||||
protected void fillFields(RecordInputStream in)
|
||||
{
|
||||
//field_1_row = LittleEndian.getShort(data, 0 + offset);
|
||||
field_1_row = in.readUShort();
|
||||
field_2_column = in.readShort();
|
||||
field_3_xf_index = in.readShort();
|
||||
field_4_string_len = in.readShort();
|
||||
field_5_unicode_flag = in.readByte();
|
||||
if (field_4_string_len > 0) {
|
||||
if (isUnCompressedUnicode()) {
|
||||
field_6_value = in.readUnicodeLEString(field_4_string_len);
|
||||
} else {
|
||||
field_6_value = in.readCompressedUnicode(field_4_string_len);
|
||||
if (isUnCompressedUnicode()) {
|
||||
field_6_value = in.readUnicodeLEString(field_4_string_len);
|
||||
} else {
|
||||
field_6_value = in.readCompressedUnicode(field_4_string_len);
|
||||
}
|
||||
} else {
|
||||
field_6_value = "";
|
||||
}
|
||||
} else field_6_value = null;
|
||||
}
|
||||
|
||||
/* READ ONLY ACCESS... THIS IS FOR COMPATIBILITY ONLY...USE LABELSST!
|
||||
public void setRow(short row) {
|
||||
field_1_row = row;
|
||||
}
|
||||
|
||||
public void setColumn(short col) {
|
||||
field_2_column = col;
|
||||
}
|
||||
|
||||
public void setXFIndex(short index) {
|
||||
field_3_xf_index = index;
|
||||
}
|
||||
*/
|
||||
//public short getRow()
|
||||
/*
|
||||
* READ ONLY ACCESS... THIS IS FOR COMPATIBILITY ONLY...USE LABELSST! public
|
||||
* void setRow(short row) { field_1_row = row; }
|
||||
*
|
||||
* public void setColumn(short col) { field_2_column = col; }
|
||||
*
|
||||
* public void setXFIndex(short index) { field_3_xf_index = index; }
|
||||
*/
|
||||
public int getRow()
|
||||
{
|
||||
return field_1_row;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -15,13 +14,12 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
|
||||
|
||||
import org.apache.poi.util.*;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Describes the frozen and unfozen panes.
|
||||
|
@ -30,9 +28,7 @@ import org.apache.poi.util.*;
|
|||
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
*/
|
||||
public class PaneRecord
|
||||
extends Record
|
||||
{
|
||||
public final class PaneRecord extends Record {
|
||||
public final static short sid = 0x41;
|
||||
private short field_1_x;
|
||||
private short field_2_y;
|
||||
|
@ -42,7 +38,10 @@ public class PaneRecord
|
|||
public final static short ACTIVE_PANE_LOWER_RIGHT = 0;
|
||||
public final static short ACTIVE_PANE_UPPER_RIGHT = 1;
|
||||
public final static short ACTIVE_PANE_LOWER_LEFT = 2;
|
||||
// TODO - remove obsolete field (it was deprecated May-2008 v3.1)
|
||||
/** @deprecated use ACTIVE_PANE_UPPER_LEFT */
|
||||
public final static short ACTIVE_PANE_UPER_LEFT = 3;
|
||||
public final static short ACTIVE_PANE_UPPER_LEFT = 3;
|
||||
|
||||
|
||||
public PaneRecord()
|
||||
|
@ -82,7 +81,6 @@ public class PaneRecord
|
|||
field_3_topRow = in.readShort();
|
||||
field_4_leftColumn = in.readShort();
|
||||
field_5_activePane = in.readShort();
|
||||
|
||||
}
|
||||
|
||||
public String toString()
|
||||
|
@ -229,7 +227,7 @@ public class PaneRecord
|
|||
* ACTIVE_PANE_LOWER_RIGHT
|
||||
* ACTIVE_PANE_UPPER_RIGHT
|
||||
* ACTIVE_PANE_LOWER_LEFT
|
||||
* ACTIVE_PANE_UPER_LEFT
|
||||
* ACTIVE_PANE_UPPER_LEFT
|
||||
*/
|
||||
public short getActivePane()
|
||||
{
|
||||
|
@ -244,16 +242,10 @@ public class PaneRecord
|
|||
* ACTIVE_PANE_LOWER_RIGHT
|
||||
* ACTIVE_PANE_UPPER_RIGHT
|
||||
* ACTIVE_PANE_LOWER_LEFT
|
||||
* ACTIVE_PANE_UPER_LEFT
|
||||
* ACTIVE_PANE_UPPER_LEFT
|
||||
*/
|
||||
public void setActivePane(short field_5_activePane)
|
||||
{
|
||||
this.field_5_activePane = field_5_activePane;
|
||||
}
|
||||
|
||||
|
||||
} // END OF CLASS
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -15,7 +14,6 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
|
@ -31,20 +29,18 @@ import org.apache.poi.util.LittleEndian;
|
|||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
* @version 2.0-pre
|
||||
*/
|
||||
|
||||
public class RowRecord
|
||||
extends Record
|
||||
implements Comparable
|
||||
{
|
||||
public final static short sid = 0x208;
|
||||
public final class RowRecord extends Record implements Comparable {
|
||||
public final static short sid = 0x208;
|
||||
|
||||
/** The maximum row number that excel can handle (zero bazed) ie 65536 rows is
|
||||
private static final int OPTION_BITS_ALWAYS_SET = 0x0100;
|
||||
private static final int DEFAULT_HEIGHT_BIT = 0x8000;
|
||||
|
||||
/** The maximum row number that excel can handle (zero based) ie 65536 rows is
|
||||
* max number of rows.
|
||||
*/
|
||||
public final static int MAX_ROW_NUMBER = 65535;
|
||||
|
||||
//private short field_1_row_number;
|
||||
private int field_1_row_number;
|
||||
private int field_1_row_number;
|
||||
private short field_2_first_col;
|
||||
private short field_3_last_col; // plus 1
|
||||
private short field_4_height;
|
||||
|
@ -52,7 +48,8 @@ public class RowRecord
|
|||
|
||||
// for generated sheets.
|
||||
private short field_6_reserved;
|
||||
private short field_7_option_flags;
|
||||
/** 16 bit options flags */
|
||||
private int field_7_option_flags;
|
||||
private static final BitField outlineLevel = BitFieldFactory.getInstance(0x07);
|
||||
|
||||
// bit 3 reserved
|
||||
|
@ -62,8 +59,17 @@ public class RowRecord
|
|||
private static final BitField formatted = BitFieldFactory.getInstance(0x80);
|
||||
private short field_8_xf_index; // only if isFormatted
|
||||
|
||||
public RowRecord()
|
||||
{
|
||||
public RowRecord(int rowNumber) {
|
||||
field_1_row_number = rowNumber;
|
||||
field_2_first_col = -1;
|
||||
field_3_last_col = -1;
|
||||
field_4_height = (short)DEFAULT_HEIGHT_BIT;
|
||||
field_4_height = (short)DEFAULT_HEIGHT_BIT;
|
||||
field_5_optimize = ( short ) 0;
|
||||
field_6_reserved = ( short ) 0;
|
||||
field_7_option_flags = OPTION_BITS_ALWAYS_SET; // seems necessary for outlining
|
||||
|
||||
field_8_xf_index = ( short ) 0xf;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,7 +92,6 @@ public class RowRecord
|
|||
|
||||
protected void fillFields(RecordInputStream in)
|
||||
{
|
||||
//field_1_row_number = LittleEndian.getShort(data, 0 + offset);
|
||||
field_1_row_number = in.readUShort();
|
||||
field_2_first_col = in.readShort();
|
||||
field_3_last_col = in.readShort();
|
||||
|
@ -156,7 +161,7 @@ public class RowRecord
|
|||
|
||||
public void setOptionFlags(short options)
|
||||
{
|
||||
field_7_option_flags = options;
|
||||
field_7_option_flags = options | OPTION_BITS_ALWAYS_SET;
|
||||
}
|
||||
|
||||
// option bitfields
|
||||
|
@ -169,20 +174,18 @@ public class RowRecord
|
|||
|
||||
public void setOutlineLevel(short ol)
|
||||
{
|
||||
field_7_option_flags =
|
||||
outlineLevel.setShortValue(field_7_option_flags, ol);
|
||||
field_7_option_flags = outlineLevel.setValue(field_7_option_flags, ol);
|
||||
}
|
||||
|
||||
/**
|
||||
* set whether or not to colapse this row
|
||||
* @param c - colapse or not
|
||||
* set whether or not to collapse this row
|
||||
* @param c - collapse or not
|
||||
* @see #setOptionFlags(short)
|
||||
*/
|
||||
|
||||
public void setColapsed(boolean c)
|
||||
{
|
||||
field_7_option_flags = colapsed.setShortBoolean(field_7_option_flags,
|
||||
c);
|
||||
field_7_option_flags = colapsed.setBoolean(field_7_option_flags, c);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,8 +196,7 @@ public class RowRecord
|
|||
|
||||
public void setZeroHeight(boolean z)
|
||||
{
|
||||
field_7_option_flags =
|
||||
zeroHeight.setShortBoolean(field_7_option_flags, z);
|
||||
field_7_option_flags = zeroHeight.setBoolean(field_7_option_flags, z);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,8 +207,7 @@ public class RowRecord
|
|||
|
||||
public void setBadFontHeight(boolean f)
|
||||
{
|
||||
field_7_option_flags =
|
||||
badFontHeight.setShortBoolean(field_7_option_flags, f);
|
||||
field_7_option_flags = badFontHeight.setBoolean(field_7_option_flags, f);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -217,8 +218,7 @@ public class RowRecord
|
|||
|
||||
public void setFormatted(boolean f)
|
||||
{
|
||||
field_7_option_flags = formatted.setShortBoolean(field_7_option_flags,
|
||||
f);
|
||||
field_7_option_flags = formatted.setBoolean(field_7_option_flags, f);
|
||||
}
|
||||
|
||||
// end bitfields
|
||||
|
@ -293,7 +293,7 @@ public class RowRecord
|
|||
|
||||
public short getOptionFlags()
|
||||
{
|
||||
return field_7_option_flags;
|
||||
return (short)field_7_option_flags;
|
||||
}
|
||||
|
||||
// option bitfields
|
||||
|
@ -306,7 +306,7 @@ public class RowRecord
|
|||
|
||||
public short getOutlineLevel()
|
||||
{
|
||||
return outlineLevel.getShortValue(field_7_option_flags);
|
||||
return (short)outlineLevel.getValue(field_7_option_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -410,7 +410,6 @@ public class RowRecord
|
|||
{
|
||||
LittleEndian.putShort(data, 0 + offset, sid);
|
||||
LittleEndian.putShort(data, 2 + offset, ( short ) 16);
|
||||
//LittleEndian.putShort(data, 4 + offset, getRowNumber());
|
||||
LittleEndian.putShort(data, 4 + offset, ( short ) getRowNumber());
|
||||
LittleEndian.putShort(data, 6 + offset, getFirstCol() == -1 ? (short)0 : getFirstCol());
|
||||
LittleEndian.putShort(data, 8 + offset, getLastCol() == -1 ? (short)0 : getLastCol());
|
||||
|
@ -419,7 +418,6 @@ public class RowRecord
|
|||
LittleEndian.putShort(data, 14 + offset, field_6_reserved);
|
||||
LittleEndian.putShort(data, 16 + offset, getOptionFlags());
|
||||
|
||||
// LittleEndian.putShort(data,18,getOutlineLevel());
|
||||
LittleEndian.putShort(data, 18 + offset, getXFIndex());
|
||||
return getRecordSize();
|
||||
}
|
||||
|
@ -469,8 +467,7 @@ public class RowRecord
|
|||
}
|
||||
|
||||
public Object clone() {
|
||||
RowRecord rec = new RowRecord();
|
||||
rec.field_1_row_number = field_1_row_number;
|
||||
RowRecord rec = new RowRecord(field_1_row_number);
|
||||
rec.field_2_first_col = field_2_first_col;
|
||||
rec.field_3_last_col = field_3_last_col;
|
||||
rec.field_4_height = field_4_height;
|
||||
|
|
|
@ -57,8 +57,8 @@ public class WindowOneRecord
|
|||
BitFieldFactory.getInstance(0x20); // display tabs at the bottom
|
||||
|
||||
// all the rest are "reserved"
|
||||
private short field_6_selected_tab;
|
||||
private short field_7_displayed_tab;
|
||||
private int field_6_active_sheet;
|
||||
private int field_7_first_visible_tab;
|
||||
private short field_8_num_selected_tabs;
|
||||
private short field_9_tab_width_ratio;
|
||||
|
||||
|
@ -91,8 +91,8 @@ public class WindowOneRecord
|
|||
field_3_width = in.readShort();
|
||||
field_4_height = in.readShort();
|
||||
field_5_options = in.readShort();
|
||||
field_6_selected_tab = in.readShort();
|
||||
field_7_displayed_tab = in.readShort();
|
||||
field_6_active_sheet = in.readShort();
|
||||
field_7_first_visible_tab = in.readShort();
|
||||
field_8_num_selected_tabs = in.readShort();
|
||||
field_9_tab_width_ratio = in.readShort();
|
||||
}
|
||||
|
@ -202,24 +202,33 @@ public class WindowOneRecord
|
|||
|
||||
// end bitfields
|
||||
|
||||
public void setActiveSheetIndex(int index) {
|
||||
field_6_active_sheet = index;
|
||||
}
|
||||
/**
|
||||
* set the selected tab number
|
||||
* @param s tab number
|
||||
* deprecated May 2008
|
||||
* @deprecated - Misleading name - use setActiveSheetIndex()
|
||||
*/
|
||||
|
||||
public void setSelectedTab(short s)
|
||||
{
|
||||
field_6_selected_tab = s;
|
||||
setActiveSheetIndex(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the displayed tab number
|
||||
* @param t tab number
|
||||
* Sets the first visible sheet in the worksheet tab-bar. This method does <b>not</b>
|
||||
* hide, select or focus sheets. It just sets the scroll position in the tab-bar.
|
||||
* @param t the sheet index of the tab that will become the first in the tab-bar
|
||||
*/
|
||||
public void setFirstVisibleTab(int t) {
|
||||
field_7_first_visible_tab = t;
|
||||
}
|
||||
|
||||
public void setDisplayedTab(short t)
|
||||
{
|
||||
field_7_displayed_tab = t;
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated - Misleading name - use setFirstVisibleTab()
|
||||
*/
|
||||
public void setDisplayedTab(short t) {
|
||||
setFirstVisibleTab(t);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,24 +356,36 @@ public class WindowOneRecord
|
|||
|
||||
// end options bitfields
|
||||
|
||||
|
||||
/**
|
||||
* get the selected tab number
|
||||
* @return Tab number
|
||||
* @return the index of the currently displayed sheet
|
||||
*/
|
||||
public int getActiveSheetIndex() {
|
||||
return field_6_active_sheet;
|
||||
}
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated - Misleading name - use getActiveSheetIndex()
|
||||
*/
|
||||
|
||||
public short getSelectedTab()
|
||||
{
|
||||
return field_6_selected_tab;
|
||||
return (short) getActiveSheetIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the displayed tab number
|
||||
* @return Tab number
|
||||
* @return the first visible sheet in the worksheet tab-bar.
|
||||
* I.E. the scroll position of the tab-bar.
|
||||
*/
|
||||
public int getFirstVisibleTab() {
|
||||
return field_7_first_visible_tab;
|
||||
}
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated - Misleading name - use getFirstVisibleTab()
|
||||
*/
|
||||
|
||||
public short getDisplayedTab()
|
||||
{
|
||||
return field_7_displayed_tab;
|
||||
return (short) getFirstVisibleTab();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -412,10 +433,10 @@ public class WindowOneRecord
|
|||
.append(getDisplayVerticalScrollbar()).append("\n");
|
||||
buffer.append(" .tabs = ").append(getDisplayTabs())
|
||||
.append("\n");
|
||||
buffer.append(" .selectedtab = ")
|
||||
.append(Integer.toHexString(getSelectedTab())).append("\n");
|
||||
buffer.append(" .displayedtab = ")
|
||||
.append(Integer.toHexString(getDisplayedTab())).append("\n");
|
||||
buffer.append(" .activeSheet = ")
|
||||
.append(Integer.toHexString(getActiveSheetIndex())).append("\n");
|
||||
buffer.append(" .firstVisibleTab = ")
|
||||
.append(Integer.toHexString(getFirstVisibleTab())).append("\n");
|
||||
buffer.append(" .numselectedtabs = ")
|
||||
.append(Integer.toHexString(getNumSelectedTabs())).append("\n");
|
||||
buffer.append(" .tabwidthratio = ")
|
||||
|
@ -434,8 +455,8 @@ public class WindowOneRecord
|
|||
LittleEndian.putShort(data, 8 + offset, getWidth());
|
||||
LittleEndian.putShort(data, 10 + offset, getHeight());
|
||||
LittleEndian.putShort(data, 12 + offset, getOptions());
|
||||
LittleEndian.putShort(data, 14 + offset, getSelectedTab());
|
||||
LittleEndian.putShort(data, 16 + offset, getDisplayedTab());
|
||||
LittleEndian.putUShort(data, 14 + offset, getActiveSheetIndex());
|
||||
LittleEndian.putUShort(data, 16 + offset, getFirstVisibleTab());
|
||||
LittleEndian.putShort(data, 18 + offset, getNumSelectedTabs());
|
||||
LittleEndian.putShort(data, 20 + offset, getTabWidthRatio());
|
||||
return getRecordSize();
|
||||
|
|
|
@ -54,7 +54,7 @@ public class WindowTwoRecord
|
|||
private BitField displayGuts = BitFieldFactory.getInstance(0x80);
|
||||
private BitField freezePanesNoSplit = BitFieldFactory.getInstance(0x100);
|
||||
private BitField selected = BitFieldFactory.getInstance(0x200);
|
||||
private BitField paged = BitFieldFactory.getInstance(0x400);
|
||||
private BitField active = BitFieldFactory.getInstance(0x400);
|
||||
private BitField savedInPageBreakPreview = BitFieldFactory.getInstance(0x800);
|
||||
|
||||
// 4-7 reserved
|
||||
|
@ -222,12 +222,16 @@ public class WindowTwoRecord
|
|||
* is the sheet currently displayed in the window
|
||||
* @param p displayed or not
|
||||
*/
|
||||
|
||||
public void setPaged(boolean p)
|
||||
{
|
||||
field_1_options = paged.setShortBoolean(field_1_options, p);
|
||||
public void setActive(boolean p) {
|
||||
field_1_options = active.setShortBoolean(field_1_options, p);
|
||||
}
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated use setActive()
|
||||
*/
|
||||
public void setPaged(boolean p) {
|
||||
setActive(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* was the sheet saved in page break view
|
||||
* @param p pagebreaksaved or not
|
||||
|
@ -416,9 +420,15 @@ public class WindowTwoRecord
|
|||
* @return displayed or not
|
||||
*/
|
||||
|
||||
public boolean getPaged()
|
||||
{
|
||||
return paged.isSet(field_1_options);
|
||||
public boolean isActive() {
|
||||
return active.isSet(field_1_options);
|
||||
}
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated use isActive()
|
||||
*/
|
||||
public boolean getPaged() {
|
||||
return isActive();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -520,7 +530,7 @@ public class WindowTwoRecord
|
|||
.append(getFreezePanesNoSplit()).append("\n");
|
||||
buffer.append(" .selected = ").append(getSelected())
|
||||
.append("\n");
|
||||
buffer.append(" .paged = ").append(getPaged())
|
||||
buffer.append(" .active = ").append(isActive())
|
||||
.append("\n");
|
||||
buffer.append(" .svdinpgbrkpv= ")
|
||||
.append(getSavedInPageBreakPreview()).append("\n");
|
||||
|
|
|
@ -35,19 +35,17 @@ import java.util.TreeMap;
|
|||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class RowRecordsAggregate
|
||||
extends Record
|
||||
{
|
||||
int firstrow = -1;
|
||||
int lastrow = -1;
|
||||
Map records = null;
|
||||
int size = 0;
|
||||
public final class RowRecordsAggregate extends Record {
|
||||
private int firstrow = -1;
|
||||
private int lastrow = -1;
|
||||
private Map records = null; // TODO - use a proper key in this map
|
||||
private int size = 0;
|
||||
|
||||
/** Creates a new instance of ValueRecordsAggregate */
|
||||
|
||||
public RowRecordsAggregate()
|
||||
{
|
||||
records = new TreeMap();
|
||||
records = new TreeMap();
|
||||
}
|
||||
|
||||
public void insertRow(RowRecord row)
|
||||
|
@ -74,15 +72,13 @@ public class RowRecordsAggregate
|
|||
records.remove(row);
|
||||
}
|
||||
|
||||
public RowRecord getRow(int rownum)
|
||||
{
|
||||
// Row must be between 0 and 65535
|
||||
if(rownum < 0 || rownum > 65535) {
|
||||
throw new IllegalArgumentException("The row number must be between 0 and 65535");
|
||||
}
|
||||
public RowRecord getRow(int rownum) {
|
||||
// Row must be between 0 and 65535
|
||||
if(rownum < 0 || rownum > 65535) {
|
||||
throw new IllegalArgumentException("The row number must be between 0 and 65535");
|
||||
}
|
||||
|
||||
RowRecord row = new RowRecord();
|
||||
row.setRowNumber(rownum);
|
||||
RowRecord row = new RowRecord(rownum);
|
||||
return ( RowRecord ) records.get(row);
|
||||
}
|
||||
|
||||
|
@ -333,7 +329,7 @@ public class RowRecordsAggregate
|
|||
|
||||
// Find the start of the group.
|
||||
int startRow = findStartOfRowOutlineGroup( rowNumber );
|
||||
RowRecord rowRecord = (RowRecord) getRow( startRow );
|
||||
RowRecord rowRecord = getRow( startRow );
|
||||
|
||||
// Hide all the columns until the end of the group
|
||||
int lastRow = writeHidden( rowRecord, startRow, true );
|
||||
|
@ -358,17 +354,8 @@ public class RowRecordsAggregate
|
|||
* @return RowRecord created for the passed in row number
|
||||
* @see org.apache.poi.hssf.record.RowRecord
|
||||
*/
|
||||
public static RowRecord createRow(int row)
|
||||
{
|
||||
RowRecord rowrec = new RowRecord();
|
||||
|
||||
//rowrec.setRowNumber(( short ) row);
|
||||
rowrec.setRowNumber(row);
|
||||
rowrec.setHeight(( short ) 0xff);
|
||||
rowrec.setOptimize(( short ) 0x0);
|
||||
rowrec.setOptionFlags(( short ) 0x100); // seems necessary for outlining
|
||||
rowrec.setXFIndex(( short ) 0xf);
|
||||
return rowrec;
|
||||
public static RowRecord createRow(int rowNumber) {
|
||||
return new RowRecord(rowNumber);
|
||||
}
|
||||
|
||||
public boolean isRowGroupCollapsed( int row )
|
||||
|
@ -399,12 +386,12 @@ public class RowRecordsAggregate
|
|||
int endIdx = findEndOfRowOutlineGroup( idx );
|
||||
|
||||
// expand:
|
||||
// colapsed bit must be unset
|
||||
// collapsed bit must be unset
|
||||
// hidden bit gets unset _if_ surrounding groups are expanded you can determine
|
||||
// this by looking at the hidden bit of the enclosing group. You will have
|
||||
// to look at the start and the end of the current group to determine which
|
||||
// is the enclosing group
|
||||
// hidden bit only is altered for this outline level. ie. don't uncollapse contained groups
|
||||
// hidden bit only is altered for this outline level. ie. don't un-collapse contained groups
|
||||
if ( !isRowGroupHiddenByParent( idx ) )
|
||||
{
|
||||
for ( int i = startIdx; i <= endIdx; i++ )
|
||||
|
|
|
@ -24,9 +24,8 @@ import org.apache.poi.util.LittleEndian;
|
|||
|
||||
/**
|
||||
* To support Constant Values (2.5.7) as required by the CRN record.
|
||||
* This class should probably also be used for two dimensional arrays which are encoded by
|
||||
* This class is also used for two dimensional arrays which are encoded by
|
||||
* EXTERNALNAME (5.39) records and Array tokens.<p/>
|
||||
* TODO - code in ArrayPtg should be merged with this code. It currently supports only 2 of the constant types
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
|
|
|
@ -47,18 +47,31 @@ public class ErrorConstant {
|
|||
public int getErrorCode() {
|
||||
return _errorCode;
|
||||
}
|
||||
public String getText() {
|
||||
if(HSSFErrorConstants.isValidCode(_errorCode)) {
|
||||
return HSSFErrorConstants.getText(_errorCode);
|
||||
}
|
||||
return "unknown error code (" + _errorCode + ")";
|
||||
}
|
||||
|
||||
public static ErrorConstant valueOf(int errorCode) {
|
||||
switch (errorCode) {
|
||||
case HSSFErrorConstants.ERROR_NULL: return NULL;
|
||||
case HSSFErrorConstants.ERROR_DIV_0: return DIV_0;
|
||||
case HSSFErrorConstants.ERROR_VALUE: return VALUE;
|
||||
case HSSFErrorConstants.ERROR_REF: return REF;
|
||||
case HSSFErrorConstants.ERROR_NAME: return NAME;
|
||||
case HSSFErrorConstants.ERROR_NUM: return NUM;
|
||||
case HSSFErrorConstants.ERROR_NA: return NA;
|
||||
case HSSFErrorConstants.ERROR_NULL: return NULL;
|
||||
case HSSFErrorConstants.ERROR_DIV_0: return DIV_0;
|
||||
case HSSFErrorConstants.ERROR_VALUE: return VALUE;
|
||||
case HSSFErrorConstants.ERROR_REF: return REF;
|
||||
case HSSFErrorConstants.ERROR_NAME: return NAME;
|
||||
case HSSFErrorConstants.ERROR_NUM: return NUM;
|
||||
case HSSFErrorConstants.ERROR_NA: return NA;
|
||||
}
|
||||
System.err.println("Warning - unexpected error code (" + errorCode + ")");
|
||||
return new ErrorConstant(errorCode);
|
||||
}
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(getText());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,22 +17,17 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.record.SSTRecord;
|
||||
import org.apache.poi.hssf.record.UnicodeString;
|
||||
import org.apache.poi.hssf.record.constant.ConstantValueParser;
|
||||
import org.apache.poi.hssf.record.constant.ErrorConstant;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* ArrayPtg - handles arrays
|
||||
*
|
||||
* The ArrayPtg is a little wierd, the size of the Ptg when parsing initially only
|
||||
* The ArrayPtg is a little weird, the size of the Ptg when parsing initially only
|
||||
* includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
|
||||
* It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
|
||||
* held after this. So Ptg.createParsedExpression keeps track of the number of
|
||||
|
@ -40,209 +35,160 @@ import org.apache.poi.hssf.record.UnicodeString;
|
|||
*
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
public class ArrayPtg extends Ptg {
|
||||
public static final byte sid = 0x20;
|
||||
|
||||
public class ArrayPtg extends Ptg
|
||||
{
|
||||
public final static byte sid = 0x20;
|
||||
protected byte field_1_reserved;
|
||||
protected byte field_2_reserved;
|
||||
protected byte field_3_reserved;
|
||||
protected byte field_4_reserved;
|
||||
protected byte field_5_reserved;
|
||||
protected byte field_6_reserved;
|
||||
protected byte field_7_reserved;
|
||||
|
||||
|
||||
protected short token_1_columns;
|
||||
protected short token_2_rows;
|
||||
protected Object[][] token_3_arrayValues;
|
||||
private static final int RESERVED_FIELD_LEN = 7;
|
||||
// TODO - fix up field visibility and subclasses
|
||||
protected byte[] field_1_reserved;
|
||||
// data from these fields comes after the Ptg data of all tokens in current formula
|
||||
protected short token_1_columns;
|
||||
protected short token_2_rows;
|
||||
protected Object[] token_3_arrayValues;
|
||||
|
||||
protected ArrayPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
protected ArrayPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public ArrayPtg(RecordInputStream in)
|
||||
{
|
||||
field_1_reserved = in.readByte();
|
||||
field_2_reserved = in.readByte();
|
||||
field_3_reserved = in.readByte();
|
||||
field_4_reserved = in.readByte();
|
||||
field_5_reserved = in.readByte();
|
||||
field_6_reserved = in.readByte();
|
||||
field_7_reserved = in.readByte();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read in the actual token (array) values. This occurs
|
||||
* AFTER the last Ptg in the expression.
|
||||
* See page 304-305 of Excel97-2007BinaryFileFormat(xls)Specification.pdf
|
||||
*/
|
||||
public void readTokenValues(RecordInputStream in) {
|
||||
token_1_columns = (short)(0x00ff & in.readByte());
|
||||
token_2_rows = in.readShort();
|
||||
|
||||
//The token_1_columns and token_2_rows do not follow the documentation.
|
||||
//The number of physical rows and columns is actually +1 of these values.
|
||||
//Which is not explicitly documented.
|
||||
token_1_columns++;
|
||||
token_2_rows++;
|
||||
|
||||
token_3_arrayValues = new Object[token_1_columns][token_2_rows];
|
||||
|
||||
for (int x=0;x<token_1_columns;x++) {
|
||||
for (int y=0;y<token_2_rows;y++) {
|
||||
byte grbit = in.readByte();
|
||||
if (grbit == 0x01) {
|
||||
token_3_arrayValues[x][y] = new Double(in.readDouble());
|
||||
} else if (grbit == 0x02) {
|
||||
//Ignore the doco, it is actually a unicode string with all the
|
||||
//trimmings ie 16 bit size, option byte etc
|
||||
token_3_arrayValues[x][y] = in.readUnicodeString();
|
||||
} else throw new RecordFormatException("Unknown grbit '"+grbit+"' at " + x + "," + y + " with " + in.remaining() + " bytes left");
|
||||
public ArrayPtg(RecordInputStream in)
|
||||
{
|
||||
field_1_reserved = new byte[RESERVED_FIELD_LEN];
|
||||
// TODO - add readFully method to RecordInputStream
|
||||
for(int i=0; i< RESERVED_FIELD_LEN; i++) {
|
||||
field_1_reserved[i] = in.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read in the actual token (array) values. This occurs
|
||||
* AFTER the last Ptg in the expression.
|
||||
* See page 304-305 of Excel97-2007BinaryFileFormat(xls)Specification.pdf
|
||||
*/
|
||||
public void readTokenValues(RecordInputStream in) {
|
||||
short nColumns = in.readUByte();
|
||||
short nRows = in.readShort();
|
||||
//The token_1_columns and token_2_rows do not follow the documentation.
|
||||
//The number of physical rows and columns is actually +1 of these values.
|
||||
//Which is not explicitly documented.
|
||||
nColumns++;
|
||||
nRows++;
|
||||
|
||||
token_1_columns = nColumns;
|
||||
token_2_rows = nRows;
|
||||
|
||||
int totalCount = nRows * nColumns;
|
||||
token_3_arrayValues = ConstantValueParser.parse(in, totalCount);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer("[ArrayPtg]\n");
|
||||
|
||||
buffer.append("columns = ").append(getColumnCount()).append("\n");
|
||||
buffer.append("rows = ").append(getRowCount()).append("\n");
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
Object o = token_3_arrayValues[getValueIndex(x, y)];
|
||||
buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer("[ArrayPtg]\n");
|
||||
/* package */ int getValueIndex(int colIx, int rowIx) {
|
||||
if(colIx < 0 || colIx >= token_1_columns) {
|
||||
throw new IllegalArgumentException("Specified colIx (" + colIx
|
||||
+ ") is outside the allowed range (0.." + (token_1_columns-1) + ")");
|
||||
}
|
||||
if(rowIx < 0 || rowIx >= token_2_rows) {
|
||||
throw new IllegalArgumentException("Specified rowIx (" + rowIx
|
||||
+ ") is outside the allowed range (0.." + (token_2_rows-1) + ")");
|
||||
}
|
||||
return rowIx * token_1_columns + colIx;
|
||||
}
|
||||
|
||||
buffer.append("columns = ").append(getColumnCount()).append("\n");
|
||||
buffer.append("rows = ").append(getRowCount()).append("\n");
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
Object o = token_3_arrayValues[x][y];
|
||||
buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n");
|
||||
}
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
public void writeBytes(byte[] data, int offset) {
|
||||
|
||||
LittleEndian.putByte(data, offset + 0, sid + ptgClass);
|
||||
System.arraycopy(field_1_reserved, 0, data, offset+1, RESERVED_FIELD_LEN);
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset++] = (byte) (sid + ptgClass);
|
||||
array[offset++] = field_1_reserved;
|
||||
array[offset++] = field_2_reserved;
|
||||
array[offset++] = field_3_reserved;
|
||||
array[offset++] = field_4_reserved;
|
||||
array[offset++] = field_5_reserved;
|
||||
array[offset++] = field_6_reserved;
|
||||
array[offset++] = field_7_reserved;
|
||||
|
||||
}
|
||||
public int writeTokenValueBytes(byte [] array, int offset) {
|
||||
int pos = 0;
|
||||
array[pos + offset] = (byte)(token_1_columns-1);
|
||||
pos++;
|
||||
LittleEndian.putShort(array, pos+offset, (short)(token_2_rows-1));
|
||||
pos += 2;
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
Object o = token_3_arrayValues[x][y];
|
||||
if (o instanceof Double) {
|
||||
array[pos+offset] = 0x01;
|
||||
pos++;
|
||||
LittleEndian.putDouble(array, pos+offset, ((Double)o).doubleValue());
|
||||
pos+=8;
|
||||
} else if (o instanceof UnicodeString) {
|
||||
array[pos+offset] = 0x02;
|
||||
pos++;
|
||||
UnicodeString s = (UnicodeString)o;
|
||||
//JMH TBD Handle string continuation. Id do it now but its 4am.
|
||||
UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
|
||||
s.serialize(stats, pos + offset, array);
|
||||
pos += stats.recordSize;
|
||||
} else throw new RuntimeException("Coding error");
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
public int writeTokenValueBytes(byte[] data, int offset) {
|
||||
|
||||
public void setRowCount(short row)
|
||||
{
|
||||
token_2_rows = row;
|
||||
}
|
||||
LittleEndian.putByte(data, offset + 0, token_1_columns-1);
|
||||
LittleEndian.putShort(data, offset + 1, (short)(token_2_rows-1));
|
||||
ConstantValueParser.encode(data, offset + 3, token_3_arrayValues);
|
||||
return 3 + ConstantValueParser.getEncodedSize(token_3_arrayValues);
|
||||
}
|
||||
|
||||
public short getRowCount()
|
||||
{
|
||||
return token_2_rows;
|
||||
}
|
||||
public short getRowCount() {
|
||||
return token_2_rows;
|
||||
}
|
||||
|
||||
public void setColumnCount(short col)
|
||||
{
|
||||
token_1_columns = (byte)col;
|
||||
}
|
||||
public short getColumnCount() {
|
||||
return token_1_columns;
|
||||
}
|
||||
|
||||
public short getColumnCount()
|
||||
{
|
||||
return token_1_columns;
|
||||
}
|
||||
/** This size includes the size of the array Ptg plus the Array Ptg Token value size*/
|
||||
public int getSize()
|
||||
{
|
||||
int size = 1+7+1+2;
|
||||
size += ConstantValueParser.getEncodedSize(token_3_arrayValues);
|
||||
return size;
|
||||
}
|
||||
|
||||
/** This size includes the size of the array Ptg plus the Array Ptg Token value size*/
|
||||
public int getSize()
|
||||
{
|
||||
int size = 1+7+1+2;
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
Object o = token_3_arrayValues[x][y];
|
||||
if (o instanceof UnicodeString) {
|
||||
size++;
|
||||
UnicodeString.UnicodeRecordStats rs = new UnicodeString.UnicodeRecordStats();
|
||||
((UnicodeString)o).getRecordSize(rs);
|
||||
size += rs.recordSize;
|
||||
} else if (o instanceof Double) {
|
||||
size += 9;
|
||||
}
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
StringBuffer b = new StringBuffer();
|
||||
b.append("{");
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
if (x > 0) {
|
||||
b.append(";");
|
||||
}
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
if (y > 0) {
|
||||
b.append(",");
|
||||
}
|
||||
Object o = token_3_arrayValues[getValueIndex(x, y)];
|
||||
b.append(getConstantText(o));
|
||||
}
|
||||
}
|
||||
b.append("}");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
private static String getConstantText(Object o) {
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
StringBuffer b = new StringBuffer();
|
||||
b.append("{");
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
Object o = token_3_arrayValues[x][y];
|
||||
if (o instanceof String) {
|
||||
b.append((String)o);
|
||||
} else if (o instanceof Double) {
|
||||
b.append(((Double)o).doubleValue());
|
||||
}
|
||||
if (y != getRowCount())
|
||||
b.append(",");
|
||||
}
|
||||
if (x != getColumnCount())
|
||||
b.append(";");
|
||||
}
|
||||
b.append("}");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_ARRAY;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
ArrayPtg ptg = new ArrayPtg();
|
||||
ptg.field_1_reserved = field_1_reserved;
|
||||
ptg.field_2_reserved = field_2_reserved;
|
||||
ptg.field_3_reserved = field_3_reserved;
|
||||
ptg.field_4_reserved = field_4_reserved;
|
||||
ptg.field_5_reserved = field_5_reserved;
|
||||
ptg.field_6_reserved = field_6_reserved;
|
||||
ptg.field_7_reserved = field_7_reserved;
|
||||
|
||||
ptg.token_1_columns = token_1_columns;
|
||||
ptg.token_2_rows = token_2_rows;
|
||||
ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
|
||||
}
|
||||
}
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
if (o == null) {
|
||||
return ""; // TODO - how is 'empty value' represented in formulas?
|
||||
}
|
||||
if (o instanceof UnicodeString) {
|
||||
return "\"" + ((UnicodeString)o).getString() + "\"";
|
||||
}
|
||||
if (o instanceof Double) {
|
||||
return ((Double)o).toString();
|
||||
}
|
||||
if (o instanceof Boolean) {
|
||||
((Boolean)o).toString();
|
||||
}
|
||||
if (o instanceof ErrorConstant) {
|
||||
return ((ErrorConstant)o).getText();
|
||||
}
|
||||
throw new IllegalArgumentException("Unexpected constant class (" + o.getClass().getName() + ")");
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_ARRAY;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
ArrayPtg ptg = new ArrayPtg();
|
||||
ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
|
||||
|
||||
ptg.token_1_columns = token_1_columns;
|
||||
ptg.token_2_rows = token_2_rows;
|
||||
ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,56 +17,31 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.record.SSTRecord;
|
||||
import org.apache.poi.hssf.record.UnicodeString;
|
||||
|
||||
/**
|
||||
* ArrayPtgA - handles arrays
|
||||
*
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class ArrayPtgA extends ArrayPtg
|
||||
{
|
||||
public final class ArrayPtgA extends ArrayPtg {
|
||||
public final static byte sid = 0x60;
|
||||
|
||||
protected ArrayPtgA() {
|
||||
super();
|
||||
private ArrayPtgA() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public ArrayPtgA(RecordInputStream in)
|
||||
{
|
||||
public ArrayPtgA(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
ArrayPtgA ptg = new ArrayPtgA();
|
||||
ptg.field_1_reserved = field_1_reserved;
|
||||
ptg.field_2_reserved = field_2_reserved;
|
||||
ptg.field_3_reserved = field_3_reserved;
|
||||
ptg.field_4_reserved = field_4_reserved;
|
||||
ptg.field_5_reserved = field_5_reserved;
|
||||
ptg.field_6_reserved = field_6_reserved;
|
||||
ptg.field_7_reserved = field_7_reserved;
|
||||
ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
|
||||
|
||||
ptg.token_1_columns = token_1_columns;
|
||||
ptg.token_2_rows = token_2_rows;
|
||||
ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
|
||||
}
|
||||
}
|
||||
ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
|
|
|
@ -17,22 +17,12 @@
|
|||
|
||||
package org.apache.poi.hssf.record.formula;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
import org.apache.poi.hssf.record.SSTRecord;
|
||||
import org.apache.poi.hssf.record.UnicodeString;
|
||||
|
||||
/**
|
||||
* ArrayPtg - handles arrays
|
||||
*
|
||||
* The ArrayPtg is a little wierd, the size of the Ptg when parsing initially only
|
||||
* The ArrayPtg is a little weird, the size of the Ptg when parsing initially only
|
||||
* includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
|
||||
* It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
|
||||
* held after this. So Ptg.createParsedExpression keeps track of the number of
|
||||
|
@ -40,38 +30,24 @@ import org.apache.poi.hssf.record.UnicodeString;
|
|||
*
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
*/
|
||||
|
||||
public class ArrayPtgV extends ArrayPtg
|
||||
{
|
||||
public final class ArrayPtgV extends ArrayPtg {
|
||||
public final static byte sid = 0x40;
|
||||
|
||||
protected ArrayPtgV() {
|
||||
private ArrayPtgV() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
public ArrayPtgV(RecordInputStream in)
|
||||
{
|
||||
public ArrayPtgV(RecordInputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
ArrayPtgV ptg = new ArrayPtgV();
|
||||
ptg.field_1_reserved = field_1_reserved;
|
||||
ptg.field_2_reserved = field_2_reserved;
|
||||
ptg.field_3_reserved = field_3_reserved;
|
||||
ptg.field_4_reserved = field_4_reserved;
|
||||
ptg.field_5_reserved = field_5_reserved;
|
||||
ptg.field_6_reserved = field_6_reserved;
|
||||
ptg.field_7_reserved = field_7_reserved;
|
||||
ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
|
||||
|
||||
ptg.token_1_columns = token_1_columns;
|
||||
ptg.token_2_rows = token_2_rows;
|
||||
ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
|
||||
for (int x=0;x<getColumnCount();x++) {
|
||||
for (int y=0;y<getRowCount();y++) {
|
||||
ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
|
||||
}
|
||||
}
|
||||
ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,11 @@ public final class AttrPtg extends OperationPtg {
|
|||
private byte field_1_options;
|
||||
private short field_2_data;
|
||||
|
||||
/** only used for tAttrChoose: table of offsets to starts of args */
|
||||
private final int[] _jumpTable;
|
||||
/** only used for tAttrChoose: offset to the tFuncVar for CHOOSE() */
|
||||
private final int _chooseFuncOffset;
|
||||
|
||||
// flags 'volatile' and 'space', can be combined.
|
||||
// OOO spec says other combinations are theoretically possible but not likely to occur.
|
||||
private static final BitField semiVolatile = BitFieldFactory.getInstance(0x01);
|
||||
|
@ -63,7 +68,7 @@ public final class AttrPtg extends OperationPtg {
|
|||
/** 03H = Carriage returns before opening parenthesis (only allowed before tParen token) */
|
||||
public static final int CR_BEFORE_OPEN_PAREN = 0x03;
|
||||
/** 04H = Spaces before closing parenthesis (only allowed before tParen, tFunc, and tFuncVar tokens) */
|
||||
public static final int SPACE_BEFORE_CLOSE_PAERN = 0x04;
|
||||
public static final int SPACE_BEFORE_CLOSE_PAREN = 0x04;
|
||||
/** 05H = Carriage returns before closing parenthesis (only allowed before tParen, tFunc, and tFuncVar tokens) */
|
||||
public static final int CR_BEFORE_CLOSE_PAREN = 0x05;
|
||||
/** 06H = Spaces following the equality sign (only in macro sheets) */
|
||||
|
@ -71,16 +76,33 @@ public final class AttrPtg extends OperationPtg {
|
|||
}
|
||||
|
||||
public AttrPtg() {
|
||||
_jumpTable = null;
|
||||
_chooseFuncOffset = -1;
|
||||
}
|
||||
|
||||
public AttrPtg(RecordInputStream in)
|
||||
{
|
||||
field_1_options = in.readByte();
|
||||
field_2_data = in.readShort();
|
||||
if (isOptimizedChoose()) {
|
||||
int nCases = field_2_data;
|
||||
int[] jumpTable = new int[nCases];
|
||||
for (int i = 0; i < jumpTable.length; i++) {
|
||||
jumpTable[i] = in.readUShort();
|
||||
}
|
||||
_jumpTable = jumpTable;
|
||||
_chooseFuncOffset = in.readUShort();
|
||||
} else {
|
||||
_jumpTable = null;
|
||||
_chooseFuncOffset = -1;
|
||||
}
|
||||
|
||||
}
|
||||
private AttrPtg(int options, int data) {
|
||||
private AttrPtg(int options, int data, int[] jt, int chooseFuncOffset) {
|
||||
field_1_options = (byte) options;
|
||||
field_2_data = (short) data;
|
||||
_jumpTable = jt;
|
||||
_chooseFuncOffset = chooseFuncOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,7 +111,7 @@ public final class AttrPtg extends OperationPtg {
|
|||
*/
|
||||
public static AttrPtg createSpace(int type, int count) {
|
||||
int data = type & 0x00FF | (count << 8) & 0x00FFFF;
|
||||
return new AttrPtg(space.set(0), data);
|
||||
return new AttrPtg(space.set(0), data, null, -1);
|
||||
}
|
||||
|
||||
public void setOptions(byte options)
|
||||
|
@ -136,14 +158,14 @@ public final class AttrPtg extends OperationPtg {
|
|||
field_1_options=optiIf.setByteBoolean(field_1_options,bif);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags this ptg as a goto/jump
|
||||
* @param isGoto
|
||||
*/
|
||||
public void setGoto(boolean isGoto) {
|
||||
field_1_options=optGoto.setByteBoolean(field_1_options, isGoto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags this ptg as a goto/jump
|
||||
* @param isGoto
|
||||
*/
|
||||
public void setGoto(boolean isGoto) {
|
||||
field_1_options=optGoto.setByteBoolean(field_1_options, isGoto);
|
||||
}
|
||||
|
||||
// lets hope no one uses this anymore
|
||||
public boolean isBaxcel()
|
||||
{
|
||||
|
@ -181,7 +203,7 @@ public final class AttrPtg extends OperationPtg {
|
|||
if(isOptimizedIf()) {
|
||||
sb.append("if dist=").append(getData());
|
||||
} else if(isOptimizedChoose()) {
|
||||
sb.append("choose dist=").append(getData());
|
||||
sb.append("choose nCases=").append(getData());
|
||||
} else if(isGoto()) {
|
||||
sb.append("skip dist=").append(getData());
|
||||
} else if(isSum()) {
|
||||
|
@ -195,13 +217,28 @@ public final class AttrPtg extends OperationPtg {
|
|||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[offset]=sid;
|
||||
array[offset+1]=field_1_options;
|
||||
LittleEndian.putShort(array,offset+2,field_2_data);
|
||||
LittleEndian.putByte(array, offset+0, sid);
|
||||
LittleEndian.putByte(array, offset+1, field_1_options);
|
||||
LittleEndian.putShort(array,offset+2, field_2_data);
|
||||
int[] jt = _jumpTable;
|
||||
if (jt != null) {
|
||||
int joff = offset+4;
|
||||
LittleEndian.putUShort(array, joff, _chooseFuncOffset);
|
||||
joff+=2;
|
||||
for (int i = 0; i < jt.length; i++) {
|
||||
LittleEndian.putUShort(array, joff, jt[i]);
|
||||
joff+=2;
|
||||
}
|
||||
LittleEndian.putUShort(array, joff, _chooseFuncOffset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
if (_jumpTable != null) {
|
||||
return SIZE + (_jumpTable.length + 1) * LittleEndian.SHORT_SIZE;
|
||||
}
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
|
@ -255,12 +292,17 @@ public final class AttrPtg extends OperationPtg {
|
|||
|
||||
|
||||
|
||||
public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;}
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
AttrPtg ptg = new AttrPtg();
|
||||
ptg.field_1_options = field_1_options;
|
||||
ptg.field_2_data = field_2_data;
|
||||
return ptg;
|
||||
int[] jt;
|
||||
if (_jumpTable == null) {
|
||||
jt = null;
|
||||
} else {
|
||||
jt = (int[]) _jumpTable.clone();
|
||||
}
|
||||
return new AttrPtg(field_1_options, field_2_data, jt, _chooseFuncOffset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,18 +32,6 @@ public final class FuncPtg extends AbstractFunctionPtg {
|
|||
public final static int SIZE = 3;
|
||||
private int numParams=0;
|
||||
|
||||
/**
|
||||
* FuncPtgs are defined to be 4 bytes but the actual FuncPtg uses only 2 bytes.
|
||||
* If we have leftOvers that are read from the file we should serialize them back out.
|
||||
* <p>
|
||||
* If the leftovers are removed, a prompt "Warning: Data may have been lost occurs in Excel"
|
||||
*/
|
||||
//protected byte[] leftOvers = null;
|
||||
|
||||
private FuncPtg() {
|
||||
//Required for clone methods
|
||||
}
|
||||
|
||||
/**Creates new function pointer from a byte array
|
||||
* usually called while reading an excel file.
|
||||
*/
|
||||
|
@ -75,11 +63,9 @@ public final class FuncPtg extends AbstractFunctionPtg {
|
|||
}
|
||||
|
||||
public Object clone() {
|
||||
FuncPtg ptg = new FuncPtg();
|
||||
//ptg.field_1_num_args = field_1_num_args;
|
||||
ptg.field_2_fnc_index = field_2_fnc_index;
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
FuncPtg ptg = new FuncPtg(field_2_fnc_index);
|
||||
ptg.setClass(ptgClass);
|
||||
return ptg;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
|
|
|
@ -24,106 +24,123 @@ import org.apache.poi.util.StringUtil;
|
|||
import org.apache.poi.hssf.record.RecordInputStream;
|
||||
|
||||
/**
|
||||
* Number
|
||||
* Stores a String value in a formula value stored in the format <length 2 bytes>char[]
|
||||
* @author Werner Froidevaux
|
||||
* String Stores a String value in a formula value stored in the format
|
||||
* <length 2 bytes>char[]
|
||||
*
|
||||
* @author Werner Froidevaux
|
||||
* @author Jason Height (jheight at chariot dot net dot au)
|
||||
* @author Bernard Chesnoy
|
||||
*/
|
||||
public final class StringPtg extends Ptg {
|
||||
public final static int SIZE = 9;
|
||||
public final static byte sid = 0x17;
|
||||
private static final BitField fHighByte = BitFieldFactory.getInstance(0x01);
|
||||
/** the character (")used in formulas to delimit string literals */
|
||||
private static final char FORMULA_DELIMITER = '"';
|
||||
|
||||
public class StringPtg
|
||||
extends Ptg
|
||||
{
|
||||
public final static int SIZE = 9;
|
||||
public final static byte sid = 0x17;
|
||||
//NOTE: OO doc says 16bit lenght, but BiffViewer says 8
|
||||
// Book says something totally different, so dont look there!
|
||||
int field_1_length;
|
||||
byte field_2_options;
|
||||
BitField fHighByte = BitFieldFactory.getInstance(0x01);
|
||||
private String field_3_string;
|
||||
/**
|
||||
* NOTE: OO doc says 16bit length, but BiffViewer says 8 Book says something
|
||||
* totally different, so don't look there!
|
||||
*/
|
||||
private int field_1_length;
|
||||
private byte field_2_options;
|
||||
private String field_3_string;
|
||||
|
||||
private StringPtg() {
|
||||
//Required for clone methods
|
||||
// Required for clone methods
|
||||
}
|
||||
|
||||
/** Create a StringPtg from a byte array read from disk */
|
||||
public StringPtg(RecordInputStream in)
|
||||
{
|
||||
field_1_length = in.readByte() & 0xFF;
|
||||
public StringPtg(RecordInputStream in) {
|
||||
field_1_length = in.readUByte();
|
||||
field_2_options = in.readByte();
|
||||
if (fHighByte.isSet(field_2_options)) {
|
||||
field_3_string= in.readUnicodeLEString(field_1_length);
|
||||
}else {
|
||||
field_3_string=in.readCompressedUnicode(field_1_length);
|
||||
field_3_string = in.readUnicodeLEString(field_1_length);
|
||||
} else {
|
||||
field_3_string = in.readCompressedUnicode(field_1_length);
|
||||
}
|
||||
|
||||
//setValue(new String(data, offset+3, data[offset+1] + 256*data[offset+2]));
|
||||
// setValue(new String(data, offset+3, data[offset+1] + 256*data[offset+2]));
|
||||
}
|
||||
|
||||
/** Create a StringPtg from a string representation of the number
|
||||
* Number format is not checked, it is expected to be validated in the parser
|
||||
* that calls this method.
|
||||
* @param value : String representation of a floating point number
|
||||
/**
|
||||
* Create a StringPtg from a string representation of the number Number
|
||||
* format is not checked, it is expected to be validated in the parser that
|
||||
* calls this method.
|
||||
*
|
||||
* @param value :
|
||||
* String representation of a floating point number
|
||||
*/
|
||||
public StringPtg(String value) {
|
||||
if (value.length() >255) {
|
||||
throw new IllegalArgumentException("String literals in formulas cant be bigger than 255 characters ASCII");
|
||||
if (value.length() > 255) {
|
||||
throw new IllegalArgumentException(
|
||||
"String literals in formulas can't be bigger than 255 characters ASCII");
|
||||
}
|
||||
this.field_2_options=0;
|
||||
field_2_options = (byte)this.fHighByte.setBoolean(field_2_options, StringUtil.hasMultibyte(value));
|
||||
this.field_3_string=value;
|
||||
this.field_1_length=value.length(); //for the moment, we support only ASCII strings in formulas we create
|
||||
field_2_options = 0;
|
||||
field_2_options = (byte) fHighByte.setBoolean(field_2_options, StringUtil
|
||||
.hasMultibyte(value));
|
||||
field_3_string = value;
|
||||
field_1_length = value.length(); // for the moment, we support only ASCII strings in formulas we create
|
||||
}
|
||||
|
||||
/*
|
||||
public void setValue(String value)
|
||||
{
|
||||
field_1_value = value;
|
||||
}*/
|
||||
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
public String getValue() {
|
||||
return field_3_string;
|
||||
}
|
||||
|
||||
public void writeBytes(byte [] array, int offset)
|
||||
{
|
||||
array[ offset + 0 ] = sid;
|
||||
array[ offset + 1 ] = (byte)field_1_length;
|
||||
array[ offset + 2 ] = field_2_options;
|
||||
public void writeBytes(byte[] array, int offset) {
|
||||
array[offset + 0] = sid;
|
||||
array[offset + 1] = (byte) field_1_length;
|
||||
array[offset + 2] = field_2_options;
|
||||
if (fHighByte.isSet(field_2_options)) {
|
||||
StringUtil.putUnicodeLE(getValue(),array,offset+3);
|
||||
}else {
|
||||
StringUtil.putCompressedUnicode(getValue(),array,offset+3);
|
||||
}
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
if (fHighByte.isSet(field_2_options)) {
|
||||
return 2*field_1_length+3;
|
||||
StringUtil.putUnicodeLE(getValue(), array, offset + 3);
|
||||
} else {
|
||||
return field_1_length+3;
|
||||
StringUtil.putCompressedUnicode(getValue(), array, offset + 3);
|
||||
}
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book)
|
||||
{
|
||||
return "\""+getValue()+"\"";
|
||||
public int getSize() {
|
||||
if (fHighByte.isSet(field_2_options)) {
|
||||
return 2 * field_1_length + 3;
|
||||
} else {
|
||||
return field_1_length + 3;
|
||||
}
|
||||
}
|
||||
|
||||
public String toFormulaString(HSSFWorkbook book) {
|
||||
String value = field_3_string;
|
||||
int len = value.length();
|
||||
StringBuffer sb = new StringBuffer(len + 4);
|
||||
sb.append(FORMULA_DELIMITER);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = value.charAt(i);
|
||||
if (c == FORMULA_DELIMITER) {
|
||||
sb.append(FORMULA_DELIMITER);
|
||||
}
|
||||
sb.append(c);
|
||||
}
|
||||
|
||||
sb.append(FORMULA_DELIMITER);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public byte getDefaultOperandClass() {
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
return Ptg.CLASS_VALUE;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
StringPtg ptg = new StringPtg();
|
||||
ptg.field_1_length = field_1_length;
|
||||
ptg.field_2_options=field_2_options;
|
||||
ptg.field_3_string=field_3_string;
|
||||
return ptg;
|
||||
}
|
||||
public Object clone() {
|
||||
StringPtg ptg = new StringPtg();
|
||||
ptg.field_1_length = field_1_length;
|
||||
ptg.field_2_options = field_2_options;
|
||||
ptg.field_3_string = field_3_string;
|
||||
return ptg;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append(field_3_string);
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,79 +22,11 @@ import org.apache.poi.hssf.record.formula.Ptg;
|
|||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class Area2DEval implements AreaEval {
|
||||
// TODO -refactor with Area3DEval
|
||||
private final AreaPtg _delegate;
|
||||
public final class Area2DEval extends AreaEvalBase {
|
||||
|
||||
private final ValueEval[] _values;
|
||||
|
||||
public Area2DEval(Ptg ptg, ValueEval[] values) {
|
||||
if(ptg == null) {
|
||||
throw new IllegalArgumentException("ptg must not be null");
|
||||
}
|
||||
if(values == null) {
|
||||
throw new IllegalArgumentException("values must not be null");
|
||||
}
|
||||
for(int i=values.length-1; i>=0; i--) {
|
||||
if(values[i] == null) {
|
||||
throw new IllegalArgumentException("value array elements must not be null");
|
||||
}
|
||||
}
|
||||
// TODO - check size of array vs size of AreaPtg
|
||||
_delegate = (AreaPtg) ptg;
|
||||
_values = values;
|
||||
}
|
||||
|
||||
public int getFirstColumn() {
|
||||
return _delegate.getFirstColumn();
|
||||
}
|
||||
|
||||
public int getFirstRow() {
|
||||
return _delegate.getFirstRow();
|
||||
}
|
||||
|
||||
public int getLastColumn() {
|
||||
return _delegate.getLastColumn();
|
||||
}
|
||||
|
||||
public int getLastRow() {
|
||||
return _delegate.getLastRow();
|
||||
}
|
||||
|
||||
public ValueEval[] getValues() {
|
||||
return _values;
|
||||
}
|
||||
|
||||
public ValueEval getValueAt(int row, int col) {
|
||||
ValueEval retval;
|
||||
int index = ((row-getFirstRow())*(getLastColumn()-getFirstColumn()+1))+(col-getFirstColumn());
|
||||
if (index <0 || index >= _values.length)
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
else
|
||||
retval = _values[index];
|
||||
return retval;
|
||||
}
|
||||
|
||||
public boolean contains(int row, int col) {
|
||||
return (getFirstRow() <= row) && (getLastRow() >= row)
|
||||
&& (getFirstColumn() <= col) && (getLastColumn() >= col);
|
||||
}
|
||||
|
||||
public boolean containsRow(int row) {
|
||||
return (getFirstRow() <= row) && (getLastRow() >= row);
|
||||
}
|
||||
|
||||
public boolean containsColumn(short col) {
|
||||
return (getFirstColumn() <= col) && (getLastColumn() >= col);
|
||||
}
|
||||
|
||||
public boolean isColumn() {
|
||||
return _delegate.getFirstColumn() == _delegate.getLastColumn();
|
||||
}
|
||||
|
||||
public boolean isRow() {
|
||||
return _delegate.getFirstRow() == _delegate.getLastRow();
|
||||
}
|
||||
}
|
||||
public Area2DEval(Ptg ptg, ValueEval[] values) {
|
||||
super((AreaPtg) ptg, values);
|
||||
}
|
||||
}
|
|
@ -22,84 +22,18 @@ import org.apache.poi.hssf.record.formula.Ptg;
|
|||
|
||||
/**
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class Area3DEval implements AreaEval {
|
||||
// TODO -refactor with Area3DEval
|
||||
private final Area3DPtg _delegate;
|
||||
public final class Area3DEval extends AreaEvalBase {
|
||||
|
||||
private final ValueEval[] _values;
|
||||
private final int _externSheetIndex;
|
||||
|
||||
public Area3DEval(Ptg ptg, ValueEval[] values) {
|
||||
if(ptg == null) {
|
||||
throw new IllegalArgumentException("ptg must not be null");
|
||||
}
|
||||
if(values == null) {
|
||||
throw new IllegalArgumentException("values must not be null");
|
||||
}
|
||||
for(int i=values.length-1; i>=0; i--) {
|
||||
if(values[i] == null) {
|
||||
throw new IllegalArgumentException("value array elements must not be null");
|
||||
}
|
||||
}
|
||||
// TODO - check size of array vs size of AreaPtg
|
||||
_values = values;
|
||||
_delegate = (Area3DPtg) ptg;
|
||||
}
|
||||
public Area3DEval(Ptg ptg, ValueEval[] values) {
|
||||
super((Area3DPtg) ptg, values);
|
||||
_externSheetIndex = ((Area3DPtg) ptg).getExternSheetIndex();
|
||||
}
|
||||
|
||||
public int getFirstColumn() {
|
||||
return _delegate.getFirstColumn();
|
||||
}
|
||||
|
||||
public int getFirstRow() {
|
||||
return _delegate.getFirstRow();
|
||||
}
|
||||
|
||||
public int getLastColumn() {
|
||||
return (short) _delegate.getLastColumn();
|
||||
}
|
||||
|
||||
public int getLastRow() {
|
||||
return _delegate.getLastRow();
|
||||
}
|
||||
|
||||
public ValueEval[] getValues() {
|
||||
return _values;
|
||||
}
|
||||
|
||||
public ValueEval getValueAt(int row, int col) {
|
||||
ValueEval retval;
|
||||
int index = (row-getFirstRow())*(col-getFirstColumn());
|
||||
if (index <0 || index >= _values.length)
|
||||
retval = ErrorEval.VALUE_INVALID;
|
||||
else
|
||||
retval = _values[index];
|
||||
return retval;
|
||||
}
|
||||
|
||||
public boolean contains(int row, int col) {
|
||||
return (getFirstRow() <= row) && (getLastRow() >= row)
|
||||
&& (getFirstColumn() <= col) && (getLastColumn() >= col);
|
||||
}
|
||||
|
||||
public boolean containsRow(int row) {
|
||||
return (getFirstRow() <= row) && (getLastRow() >= row);
|
||||
}
|
||||
|
||||
public boolean containsColumn(short col) {
|
||||
return (getFirstColumn() <= col) && (getLastColumn() >= col);
|
||||
}
|
||||
|
||||
|
||||
public boolean isColumn() {
|
||||
return _delegate.getFirstColumn() == _delegate.getLastColumn();
|
||||
}
|
||||
|
||||
public boolean isRow() {
|
||||
return _delegate.getFirstRow() == _delegate.getLastRow();
|
||||
}
|
||||
|
||||
public int getExternSheetIndex() {
|
||||
return _delegate.getExternSheetIndex();
|
||||
}
|
||||
public int getExternSheetIndex() {
|
||||
return _externSheetIndex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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.formula.eval;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaI;
|
||||
|
||||
/**
|
||||
* @author Josh Micich
|
||||
*/
|
||||
abstract class AreaEvalBase implements AreaEval {
|
||||
|
||||
private final int _firstColumn;
|
||||
private final int _firstRow;
|
||||
private final int _lastColumn;
|
||||
private final int _lastRow;
|
||||
private final ValueEval[] _values;
|
||||
private final int _nColumns;
|
||||
private final int _nRows;
|
||||
|
||||
protected AreaEvalBase(AreaI ptg, ValueEval[] values) {
|
||||
if (values == null) {
|
||||
throw new IllegalArgumentException("values must not be null");
|
||||
}
|
||||
_firstRow = ptg.getFirstRow();
|
||||
_firstColumn = ptg.getFirstColumn();
|
||||
_lastRow = ptg.getLastRow();
|
||||
_lastColumn = ptg.getLastColumn();
|
||||
|
||||
_nColumns = _lastColumn - _firstColumn + 1;
|
||||
_nRows = _lastRow - _firstRow + 1;
|
||||
|
||||
int expectedItemCount = _nRows * _nColumns;
|
||||
if ((values.length != expectedItemCount)) {
|
||||
// Note - this math may need alteration when POI starts to support full column or full row refs
|
||||
throw new IllegalArgumentException("Array size should be (" + expectedItemCount
|
||||
+ ") but was (" + values.length + ")");
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (int i = values.length - 1; i >= 0; i--) {
|
||||
if (values[i] == null) {
|
||||
throw new IllegalArgumentException("value array elements must not be null");
|
||||
}
|
||||
}
|
||||
_values = values;
|
||||
}
|
||||
|
||||
public final int getFirstColumn() {
|
||||
return _firstColumn;
|
||||
}
|
||||
|
||||
public final int getFirstRow() {
|
||||
return _firstRow;
|
||||
}
|
||||
|
||||
public final int getLastColumn() {
|
||||
return _lastColumn;
|
||||
}
|
||||
|
||||
public final int getLastRow() {
|
||||
return _lastRow;
|
||||
}
|
||||
|
||||
public final ValueEval[] getValues() {
|
||||
// TODO - clone() - but some junits rely on not cloning at the moment
|
||||
return _values;
|
||||
}
|
||||
|
||||
public final ValueEval getValueAt(int row, int col) {
|
||||
int rowOffsetIx = row - _firstRow;
|
||||
int colOffsetIx = col - _firstColumn;
|
||||
|
||||
if(rowOffsetIx < 0 || rowOffsetIx >= _nRows) {
|
||||
throw new IllegalArgumentException("Specified row index (" + row
|
||||
+ ") is outside the allowed range (" + _firstRow + ".." + _lastRow + ")");
|
||||
}
|
||||
if(colOffsetIx < 0 || colOffsetIx >= _nColumns) {
|
||||
throw new IllegalArgumentException("Specified column index (" + col
|
||||
+ ") is outside the allowed range (" + _firstColumn + ".." + col + ")");
|
||||
}
|
||||
|
||||
int index = rowOffsetIx * _nColumns + colOffsetIx;
|
||||
return _values[index];
|
||||
}
|
||||
|
||||
public final boolean contains(int row, int col) {
|
||||
return _firstRow <= row && _lastRow >= row
|
||||
&& _firstColumn <= col && _lastColumn >= col;
|
||||
}
|
||||
|
||||
public final boolean containsRow(int row) {
|
||||
return (_firstRow <= row) && (_lastRow >= row);
|
||||
}
|
||||
|
||||
public final boolean containsColumn(short col) {
|
||||
return (_firstColumn <= col) && (_lastColumn >= col);
|
||||
}
|
||||
|
||||
public final boolean isColumn() {
|
||||
return _firstColumn == _lastColumn;
|
||||
}
|
||||
|
||||
public final boolean isRow() {
|
||||
return _firstRow == _lastRow;
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import java.io.BufferedReader;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
@ -36,15 +37,14 @@ import org.apache.poi.hssf.record.formula.Ptg;
|
|||
final class FunctionMetadataReader {
|
||||
|
||||
private static final String METADATA_FILE_NAME = "functionMetadata.txt";
|
||||
|
||||
/** plain ASCII text metadata file uses three dots for ellipsis */
|
||||
private static final String ELLIPSIS = "...";
|
||||
|
||||
private static final Pattern TAB_DELIM_PATTERN = Pattern.compile("\t");
|
||||
private static final Pattern SPACE_DELIM_PATTERN = Pattern.compile(" ");
|
||||
private static final byte[] EMPTY_BYTE_ARRAY = { };
|
||||
|
||||
// special characters from the ooo document
|
||||
private static final int CHAR_ELLIPSIS_8230 = 8230;
|
||||
private static final int CHAR_NDASH_8211 = 8211;
|
||||
|
||||
private static final String[] DIGIT_ENDING_FUNCTION_NAMES = {
|
||||
// Digits at the end of a function might be due to a left-over footnote marker.
|
||||
// except in these cases
|
||||
|
@ -58,7 +58,12 @@ final class FunctionMetadataReader {
|
|||
throw new RuntimeException("resource '" + METADATA_FILE_NAME + "' not found");
|
||||
}
|
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||
BufferedReader br;
|
||||
try {
|
||||
br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
|
||||
} catch(UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
FunctionDataBuilder fdb = new FunctionDataBuilder(400);
|
||||
|
||||
try {
|
||||
|
@ -123,7 +128,9 @@ final class FunctionMetadataReader {
|
|||
}
|
||||
String[] array = SPACE_DELIM_PATTERN.split(codes);
|
||||
int nItems = array.length;
|
||||
if(array[nItems-1].charAt(0) == CHAR_ELLIPSIS_8230) {
|
||||
if(ELLIPSIS.equals(array[nItems-1])) {
|
||||
// final ellipsis is optional, and ignored
|
||||
// (all unspecified params are assumed to be the same as the last)
|
||||
nItems --;
|
||||
}
|
||||
byte[] result = new byte[nItems];
|
||||
|
@ -137,7 +144,6 @@ final class FunctionMetadataReader {
|
|||
if(codes.length() == 1) {
|
||||
switch (codes.charAt(0)) {
|
||||
case '-':
|
||||
case CHAR_NDASH_8211: // this is what the ooo doc has
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +159,7 @@ final class FunctionMetadataReader {
|
|||
case 'R': return Ptg.CLASS_REF;
|
||||
case 'A': return Ptg.CLASS_ARRAY;
|
||||
}
|
||||
throw new IllegalArgumentException("Unexpected operand type code '" + code + "'");
|
||||
throw new IllegalArgumentException("Unexpected operand type code '" + code + "' (" + (int)code.charAt(0) + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -817,8 +817,7 @@ public class HSSFCell
|
|||
int row=record.getRow();
|
||||
short col=record.getColumn();
|
||||
short styleIndex=record.getXFIndex();
|
||||
if ((cellType != CELL_TYPE_ERROR) && (cellType != CELL_TYPE_FORMULA))
|
||||
{
|
||||
if (cellType != CELL_TYPE_ERROR) {
|
||||
setCellType(CELL_TYPE_ERROR, false, row, col, styleIndex);
|
||||
}
|
||||
(( BoolErrRecord ) record).setValue(value);
|
||||
|
|
|
@ -232,8 +232,7 @@ public class HSSFFormulaEvaluator {
|
|||
cell.setCellValue(cv.getBooleanValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
cell.setCellType(HSSFCell.CELL_TYPE_ERROR);
|
||||
cell.setCellValue(cv.getErrorValue());
|
||||
cell.setCellErrorValue(cv.getErrorValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
|
||||
|
|
|
@ -139,4 +139,13 @@ public class HSSFName {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if this name points to a cell that no longer exists
|
||||
*
|
||||
* @return true if the name refers to a deleted cell, false otherwise
|
||||
*/
|
||||
public boolean isDeleted(){
|
||||
String ref = getReference();
|
||||
return "#REF!".endsWith(ref);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.util.Iterator;
|
|||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.apache.poi.hssf.model.Sheet;
|
||||
import org.apache.poi.hssf.model.Workbook;
|
||||
import org.apache.poi.hssf.record.CellValueRecordInterface;
|
||||
import org.apache.poi.hssf.record.RowRecord;
|
||||
|
||||
|
@ -37,11 +36,9 @@ public final class HSSFRow implements Comparable {
|
|||
|
||||
// used for collections
|
||||
public final static int INITIAL_CAPACITY = 5;
|
||||
//private short rowNum;
|
||||
|
||||
private int rowNum;
|
||||
private HSSFCell[] cells=new HSSFCell[INITIAL_CAPACITY];
|
||||
// private short firstcell = -1;
|
||||
// private short lastcell = -1;
|
||||
|
||||
/**
|
||||
* reference to low level representation
|
||||
|
@ -61,7 +58,8 @@ public final class HSSFRow implements Comparable {
|
|||
|
||||
private Sheet sheet;
|
||||
|
||||
protected HSSFRow()
|
||||
// TODO - ditch this constructor
|
||||
HSSFRow()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -73,18 +71,12 @@ public final class HSSFRow implements Comparable {
|
|||
* @param rowNum the row number of this row (0 based)
|
||||
* @see org.apache.poi.hssf.usermodel.HSSFSheet#createRow(int)
|
||||
*/
|
||||
|
||||
//protected HSSFRow(Workbook book, Sheet sheet, short rowNum)
|
||||
protected HSSFRow(HSSFWorkbook book, Sheet sheet, int rowNum)
|
||||
HSSFRow(HSSFWorkbook book, Sheet sheet, int rowNum)
|
||||
{
|
||||
this.rowNum = rowNum;
|
||||
this.book = book;
|
||||
this.sheet = sheet;
|
||||
row = new RowRecord();
|
||||
row.setOptionFlags( (short)0x100 ); // seems necessary for outlining to work.
|
||||
row.setHeight((short) 0xff);
|
||||
row.setLastCol((short) -1);
|
||||
row.setFirstCol((short) -1);
|
||||
row = new RowRecord(rowNum);
|
||||
|
||||
setRowNum(rowNum);
|
||||
}
|
||||
|
@ -98,8 +90,7 @@ public final class HSSFRow implements Comparable {
|
|||
* @param record the low level api object this row should represent
|
||||
* @see org.apache.poi.hssf.usermodel.HSSFSheet#createRow(int)
|
||||
*/
|
||||
|
||||
protected HSSFRow(HSSFWorkbook book, Sheet sheet, RowRecord record)
|
||||
HSSFRow(HSSFWorkbook book, Sheet sheet, RowRecord record)
|
||||
{
|
||||
this.book = book;
|
||||
this.sheet = sheet;
|
||||
|
@ -200,12 +191,11 @@ public final class HSSFRow implements Comparable {
|
|||
* @param rowNum the row number (0-based)
|
||||
* @throws IndexOutOfBoundsException if the row number is not within the range 0-65535.
|
||||
*/
|
||||
|
||||
//public void setRowNum(short rowNum)
|
||||
public void setRowNum(int rowNum)
|
||||
{
|
||||
if ((rowNum < 0) || (rowNum > RowRecord.MAX_ROW_NUMBER))
|
||||
throw new IndexOutOfBoundsException("Row number must be between 0 and "+RowRecord.MAX_ROW_NUMBER+", was <"+rowNum+">");
|
||||
public void setRowNum(int rowNum) {
|
||||
if ((rowNum < 0) || (rowNum > RowRecord.MAX_ROW_NUMBER)) {
|
||||
throw new IllegalArgumentException("Invalid row number (" + rowNum
|
||||
+ ") outside allowable range (0.." + RowRecord.MAX_ROW_NUMBER + ")");
|
||||
}
|
||||
this.rowNum = rowNum;
|
||||
if (row != null)
|
||||
{
|
||||
|
@ -217,8 +207,6 @@ public final class HSSFRow implements Comparable {
|
|||
* get row number this row represents
|
||||
* @return the row number (0 based)
|
||||
*/
|
||||
|
||||
//public short getRowNum()
|
||||
public int getRowNum()
|
||||
{
|
||||
return rowNum;
|
||||
|
@ -479,8 +467,10 @@ public final class HSSFRow implements Comparable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return cell iterator of the physically defined cells. Note element 4 may
|
||||
* actually be row cell depending on how many are defined!
|
||||
* @return cell iterator of the physically defined cells.
|
||||
* Note that the 4th element might well not be cell 4, as the iterator
|
||||
* will not return un-defined (null) cells.
|
||||
* Call getCellNum() on the returned cells to know which cell they are.
|
||||
*/
|
||||
public Iterator cellIterator()
|
||||
{
|
||||
|
|
|
@ -136,6 +136,7 @@ public final class HSSFSheet {
|
|||
{
|
||||
int sloc = sheet.getLoc();
|
||||
RowRecord row = sheet.getNextRow();
|
||||
boolean rowRecordsAlreadyPresent = row!=null;
|
||||
|
||||
while (row != null)
|
||||
{
|
||||
|
@ -160,6 +161,18 @@ public final class HSSFSheet {
|
|||
if ( ( lastrow == null ) || ( lastrow.getRowNum() != cval.getRow() ) )
|
||||
{
|
||||
hrow = getRow( cval.getRow() );
|
||||
if (hrow == null) {
|
||||
// Some tools (like Perl module Spreadsheet::WriteExcel - bug 41187) skip the RowRecords
|
||||
// Excel, OpenOffice.org and GoogleDocs are all OK with this, so POI should be too.
|
||||
if (rowRecordsAlreadyPresent) {
|
||||
// if at least one row record is present, all should be present.
|
||||
throw new RuntimeException("Unexpected missing row when some rows already present");
|
||||
}
|
||||
// create the row record on the fly now.
|
||||
RowRecord rowRec = new RowRecord(cval.getRow());
|
||||
sheet.addRow(rowRec);
|
||||
hrow = createRowFromRecord(rowRec);
|
||||
}
|
||||
}
|
||||
if ( hrow != null )
|
||||
{
|
||||
|
@ -699,6 +712,7 @@ public final class HSSFSheet {
|
|||
/**
|
||||
* @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not
|
||||
* be the third row if say for instance the second row is undefined.
|
||||
* Call getRowNum() on each row if you care which one it is.
|
||||
*/
|
||||
public Iterator rowIterator()
|
||||
{
|
||||
|
@ -963,13 +977,34 @@ public final class HSSFSheet {
|
|||
return new HSSFFooter( getSheet().getFooter() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Note - this is not the same as whether the sheet is focused (isActive)
|
||||
* @return <code>true</code> if this sheet is currently selected
|
||||
*/
|
||||
public boolean isSelected() {
|
||||
return getSheet().getWindowTwo().getSelected();
|
||||
}
|
||||
/**
|
||||
* Sets whether sheet is selected.
|
||||
* @param sel Whether to select the sheet or deselect the sheet.
|
||||
*/
|
||||
public void setSelected( boolean sel )
|
||||
{
|
||||
getSheet().setSelected( sel );
|
||||
getSheet().getWindowTwo().setSelected(sel);
|
||||
}
|
||||
/**
|
||||
* @return <code>true</code> if this sheet is currently focused
|
||||
*/
|
||||
public boolean isActive() {
|
||||
return getSheet().getWindowTwo().isActive();
|
||||
}
|
||||
/**
|
||||
* Sets whether sheet is selected.
|
||||
* @param sel Whether to select the sheet or deselect the sheet.
|
||||
*/
|
||||
public void setActive(boolean sel )
|
||||
{
|
||||
getSheet().getWindowTwo().setActive(sel);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1671,6 +1706,23 @@ public final class HSSFSheet {
|
|||
* @param column the column index
|
||||
*/
|
||||
public void autoSizeColumn(short column) {
|
||||
autoSizeColumn(column, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the column width to fit the contents.
|
||||
*
|
||||
* This process can be relatively slow on large sheets, so this should
|
||||
* normally only be called once per column, at the end of your
|
||||
* processing.
|
||||
*
|
||||
* You can specify whether the content of merged cells should be considered or ignored.
|
||||
* Default is to ignore merged cells.
|
||||
*
|
||||
* @param column the column index
|
||||
* @param useMergedCells whether to use the contents of merged cells when calculating the width of the column
|
||||
*/
|
||||
public void autoSizeColumn(short column, boolean useMergedCells) {
|
||||
AttributedString str;
|
||||
TextLayout layout;
|
||||
/**
|
||||
|
@ -1679,13 +1731,13 @@ public final class HSSFSheet {
|
|||
* '0' looks to be a good choice.
|
||||
*/
|
||||
char defaultChar = '0';
|
||||
|
||||
|
||||
/**
|
||||
* This is the multiple that the font height is scaled by when determining the
|
||||
* boundary of rotated text.
|
||||
*/
|
||||
double fontHeightMultiple = 2.0;
|
||||
|
||||
|
||||
FontRenderContext frc = new FontRenderContext(null, true, true);
|
||||
|
||||
HSSFWorkbook wb = new HSSFWorkbook(book);
|
||||
|
@ -1697,21 +1749,27 @@ public final class HSSFSheet {
|
|||
int defaultCharWidth = (int)layout.getAdvance();
|
||||
|
||||
double width = -1;
|
||||
rows:
|
||||
for (Iterator it = rowIterator(); it.hasNext();) {
|
||||
HSSFRow row = (HSSFRow) it.next();
|
||||
HSSFCell cell = row.getCell(column);
|
||||
|
||||
boolean isCellInMergedRegion = false;
|
||||
for (int i = 0 ; i < getNumMergedRegions() && ! isCellInMergedRegion; i++) {
|
||||
isCellInMergedRegion = getMergedRegionAt(i).contains(row.getRowNum(), column);
|
||||
}
|
||||
if (cell == null) continue;
|
||||
|
||||
if (cell == null | isCellInMergedRegion) continue;
|
||||
int colspan = 1;
|
||||
for (int i = 0 ; i < getNumMergedRegions(); i++) {
|
||||
if (getMergedRegionAt(i).contains(row.getRowNum(), column)) {
|
||||
if (!useMergedCells) {
|
||||
// If we're not using merged cells, skip this one and move on to the next.
|
||||
continue rows;
|
||||
}
|
||||
cell = row.getCell(getMergedRegionAt(i).getColumnFrom());
|
||||
colspan = 1+ getMergedRegionAt(i).getColumnTo() - getMergedRegionAt(i).getColumnFrom();
|
||||
}
|
||||
}
|
||||
|
||||
HSSFCellStyle style = cell.getCellStyle();
|
||||
HSSFFont font = wb.getFontAt(style.getFontIndex());
|
||||
//the number of spaces to indent the text in the cell
|
||||
int indention = style.getIndention();
|
||||
|
||||
if (cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
|
||||
HSSFRichTextString rt = cell.getRichStringCellValue();
|
||||
|
@ -1744,9 +1802,9 @@ public final class HSSFSheet {
|
|||
trans.concatenate(
|
||||
AffineTransform.getScaleInstance(1, fontHeightMultiple)
|
||||
);
|
||||
width = Math.max(width, layout.getOutline(trans).getBounds().getWidth() / defaultCharWidth + indention);
|
||||
width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention());
|
||||
} else {
|
||||
width = Math.max(width, layout.getBounds().getWidth() / defaultCharWidth + indention);
|
||||
width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1789,19 +1847,19 @@ public final class HSSFSheet {
|
|||
trans.concatenate(
|
||||
AffineTransform.getScaleInstance(1, fontHeightMultiple)
|
||||
);
|
||||
width = Math.max(width, layout.getOutline(trans).getBounds().getWidth() / defaultCharWidth + indention);
|
||||
width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention());
|
||||
} else {
|
||||
width = Math.max(width, layout.getBounds().getWidth() / defaultCharWidth + indention);
|
||||
width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (width != -1) {
|
||||
if (width > Short.MAX_VALUE) { //calculated width can be greater that Short.MAX_VALUE!
|
||||
width = Short.MAX_VALUE;
|
||||
}
|
||||
sheet.setColumnWidth(column, (short) (width * 256));
|
||||
}
|
||||
if (width != -1) {
|
||||
if (width > Short.MAX_VALUE) { //width can be bigger that Short.MAX_VALUE!
|
||||
width = Short.MAX_VALUE;
|
||||
}
|
||||
sheet.setColumnWidth(column, (short) (width * 256));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
protected HSSFWorkbook( Workbook book )
|
||||
{
|
||||
super(null, null);
|
||||
super(null, null);
|
||||
workbook = book;
|
||||
sheets = new ArrayList( INITIAL_CAPACITY );
|
||||
names = new ArrayList( INITIAL_CAPACITY );
|
||||
|
@ -365,16 +365,66 @@ public class HSSFWorkbook extends POIDocument
|
|||
workbook.setSheetOrder(sheetname, pos);
|
||||
}
|
||||
|
||||
private void validateSheetIndex(int index) {
|
||||
int lastSheetIx = sheets.size() - 1;
|
||||
if (index < 0 || index > lastSheetIx) {
|
||||
throw new IllegalArgumentException("Sheet index ("
|
||||
+ index +") is out of range (0.." + lastSheetIx + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the tab whose data is actually seen when the sheet is opened.
|
||||
* This may be different from the "selected sheet" since excel seems to
|
||||
* allow you to show the data of one sheet when another is seen "selected"
|
||||
* in the tabs (at the bottom).
|
||||
* @see org.apache.poi.hssf.usermodel.HSSFSheet#setSelected(boolean)
|
||||
* @param index
|
||||
* Selects a single sheet. This may be different to
|
||||
* the 'active' sheet (which is the sheet with focus).
|
||||
*/
|
||||
public void setSelectedTab(int index) {
|
||||
|
||||
validateSheetIndex(index);
|
||||
int nSheets = sheets.size();
|
||||
for (int i=0; i<nSheets; i++) {
|
||||
getSheetAt(i).setSelected(i == index);
|
||||
}
|
||||
workbook.getWindowOne().setNumSelectedTabs((short)1);
|
||||
}
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated use setSelectedTab(int)
|
||||
*/
|
||||
public void setSelectedTab(short index) {
|
||||
workbook.getWindowOne().setSelectedTab(index);
|
||||
setSelectedTab((int)index);
|
||||
}
|
||||
public void setSelectedTabs(int[] indexes) {
|
||||
|
||||
for (int i = 0; i < indexes.length; i++) {
|
||||
validateSheetIndex(indexes[i]);
|
||||
}
|
||||
int nSheets = sheets.size();
|
||||
for (int i=0; i<nSheets; i++) {
|
||||
boolean bSelect = false;
|
||||
for (int j = 0; j < indexes.length; j++) {
|
||||
if (indexes[j] == i) {
|
||||
bSelect = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
getSheetAt(i).setSelected(bSelect);
|
||||
}
|
||||
workbook.getWindowOne().setNumSelectedTabs((short)indexes.length);
|
||||
}
|
||||
/**
|
||||
* Convenience method to set the active sheet. The active sheet is is the sheet
|
||||
* which is currently displayed when the workbook is viewed in Excel.
|
||||
* 'Selected' sheet(s) is a distinct concept.
|
||||
*/
|
||||
public void setActiveSheet(int index) {
|
||||
|
||||
validateSheetIndex(index);
|
||||
int nSheets = sheets.size();
|
||||
for (int i=0; i<nSheets; i++) {
|
||||
getSheetAt(i).setActive(i == index);
|
||||
}
|
||||
workbook.getWindowOne().setActiveSheetIndex(index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -384,25 +434,46 @@ public class HSSFWorkbook extends POIDocument
|
|||
* in the tabs (at the bottom).
|
||||
* @see org.apache.poi.hssf.usermodel.HSSFSheet#setSelected(boolean)
|
||||
*/
|
||||
public int getActiveSheetIndex() {
|
||||
return workbook.getWindowOne().getActiveSheetIndex();
|
||||
}
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated - Misleading name - use getActiveSheetIndex()
|
||||
*/
|
||||
public short getSelectedTab() {
|
||||
return workbook.getWindowOne().getSelectedTab();
|
||||
return (short) getActiveSheetIndex();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sets the first tab that is displayed in the list of tabs
|
||||
* in excel.
|
||||
* @param index
|
||||
*/
|
||||
public void setFirstVisibleTab(int index) {
|
||||
workbook.getWindowOne().setFirstVisibleTab(index);
|
||||
}
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated - Misleading name - use setFirstVisibleTab()
|
||||
*/
|
||||
public void setDisplayedTab(short index) {
|
||||
workbook.getWindowOne().setDisplayedTab(index);
|
||||
setFirstVisibleTab(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the first tab that is displayed in the list of tabs
|
||||
* in excel.
|
||||
* sets the first tab that is displayed in the list of tabs in excel.
|
||||
*/
|
||||
public int getFirstVisibleTab() {
|
||||
return workbook.getWindowOne().getFirstVisibleTab();
|
||||
}
|
||||
/**
|
||||
* deprecated May 2008
|
||||
* @deprecated - Misleading name - use getFirstVisibleTab()
|
||||
*/
|
||||
public short getDisplayedTab() {
|
||||
return workbook.getWindowOne().getDisplayedTab();
|
||||
return (short) getFirstVisibleTab();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -563,17 +634,13 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
public HSSFSheet createSheet()
|
||||
{
|
||||
|
||||
// if (getNumberOfSheets() == 3)
|
||||
// throw new RuntimeException("You cannot have more than three sheets in HSSF 1.0");
|
||||
HSSFSheet sheet = new HSSFSheet(this);
|
||||
|
||||
sheets.add(sheet);
|
||||
workbook.setSheetName(sheets.size() - 1,
|
||||
"Sheet" + (sheets.size() - 1));
|
||||
WindowTwoRecord windowTwo = (WindowTwoRecord) sheet.getSheet().findFirstRecordBySid(WindowTwoRecord.sid);
|
||||
windowTwo.setSelected(sheets.size() == 1);
|
||||
windowTwo.setPaged(sheets.size() == 1);
|
||||
workbook.setSheetName(sheets.size() - 1, "Sheet" + (sheets.size() - 1));
|
||||
boolean isOnlySheet = sheets.size() == 1;
|
||||
sheet.setSelected(isOnlySheet);
|
||||
sheet.setActive(isOnlySheet);
|
||||
return sheet;
|
||||
}
|
||||
|
||||
|
@ -584,23 +651,24 @@ public class HSSFWorkbook extends POIDocument
|
|||
*/
|
||||
|
||||
public HSSFSheet cloneSheet(int sheetNum) {
|
||||
HSSFSheet srcSheet = (HSSFSheet)sheets.get(sheetNum);
|
||||
String srcName = workbook.getSheetName(sheetNum);
|
||||
if (srcSheet != null) {
|
||||
validateSheetIndex(sheetNum);
|
||||
HSSFSheet srcSheet = (HSSFSheet) sheets.get(sheetNum);
|
||||
String srcName = workbook.getSheetName(sheetNum);
|
||||
HSSFSheet clonedSheet = srcSheet.cloneSheet(this);
|
||||
WindowTwoRecord windowTwo = (WindowTwoRecord) clonedSheet.getSheet().findFirstRecordBySid(WindowTwoRecord.sid);
|
||||
windowTwo.setSelected(sheets.size() == 1);
|
||||
windowTwo.setPaged(sheets.size() == 1);
|
||||
clonedSheet.setSelected(false);
|
||||
clonedSheet.setActive(false);
|
||||
|
||||
sheets.add(clonedSheet);
|
||||
int i=1;
|
||||
int i = 1;
|
||||
while (true) {
|
||||
//Try and find the next sheet name that is unique
|
||||
// Try and find the next sheet name that is unique
|
||||
String name = srcName;
|
||||
String index = Integer.toString(i++);
|
||||
if (name.length()+index.length()+2<31)
|
||||
name = name + "("+index+")";
|
||||
else name = name.substring(0, 31-index.length()-2)+"("+index+")";
|
||||
if (name.length() + index.length() + 2 < 31) {
|
||||
name = name + "(" + index + ")";
|
||||
} else {
|
||||
name = name.substring(0, 31 - index.length() - 2) + "(" + index + ")";
|
||||
}
|
||||
|
||||
//If the sheet name is unique, then set it otherwise move on to the next number.
|
||||
if (workbook.getSheetIndex(name) == -1) {
|
||||
|
@ -609,18 +677,18 @@ public class HSSFWorkbook extends POIDocument
|
|||
}
|
||||
}
|
||||
return clonedSheet;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and returns
|
||||
* the high level representation. Use this to create new sheets.
|
||||
*
|
||||
* @param sheetname sheetname to set for the sheet.
|
||||
* create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and
|
||||
* returns the high level representation. Use this to create new sheets.
|
||||
*
|
||||
* @param sheetname
|
||||
* sheetname to set for the sheet.
|
||||
* @return HSSFSheet representing the new sheet.
|
||||
* @throws IllegalArgumentException if there is already a sheet present with a case-insensitive
|
||||
* match for the specified name.
|
||||
* @throws IllegalArgumentException
|
||||
* if there is already a sheet present with a case-insensitive
|
||||
* match for the specified name.
|
||||
*/
|
||||
|
||||
public HSSFSheet createSheet(String sheetname)
|
||||
|
@ -632,9 +700,9 @@ public class HSSFWorkbook extends POIDocument
|
|||
|
||||
sheets.add(sheet);
|
||||
workbook.setSheetName(sheets.size() - 1, sheetname);
|
||||
WindowTwoRecord windowTwo = (WindowTwoRecord) sheet.getSheet().findFirstRecordBySid(WindowTwoRecord.sid);
|
||||
windowTwo.setSelected(sheets.size() == 1);
|
||||
windowTwo.setPaged(sheets.size() == 1);
|
||||
boolean isOnlySheet = sheets.size() == 1;
|
||||
sheet.setSelected(isOnlySheet);
|
||||
sheet.setActive(isOnlySheet);
|
||||
return sheet;
|
||||
}
|
||||
|
||||
|
@ -686,14 +754,54 @@ public class HSSFWorkbook extends POIDocument
|
|||
}
|
||||
|
||||
/**
|
||||
* removes sheet at the given index
|
||||
* Removes sheet at the given index.<p/>
|
||||
*
|
||||
* Care must be taken if the removed sheet is the currently active or only selected sheet in
|
||||
* the workbook. There are a few situations when Excel must have a selection and/or active
|
||||
* sheet. (For example when printing - see Bug 40414).<br/>
|
||||
*
|
||||
* This method makes sure that if the removed sheet was active, another sheet will become
|
||||
* active in its place. Furthermore, if the removed sheet was the only selected sheet, another
|
||||
* sheet will become selected. The newly active/selected sheet will have the same index, or
|
||||
* one less if the removed sheet was the last in the workbook.
|
||||
*
|
||||
* @param index of the sheet (0-based)
|
||||
*/
|
||||
public void removeSheetAt(int index) {
|
||||
validateSheetIndex(index);
|
||||
boolean wasActive = getSheetAt(index).isActive();
|
||||
boolean wasSelected = getSheetAt(index).isSelected();
|
||||
|
||||
public void removeSheetAt(int index)
|
||||
{
|
||||
sheets.remove(index);
|
||||
workbook.removeSheet(index);
|
||||
|
||||
// set the remaining active/selected sheet
|
||||
int nSheets = sheets.size();
|
||||
if (nSheets < 1) {
|
||||
// nothing more to do if there are no sheets left
|
||||
return;
|
||||
}
|
||||
// the index of the closest remaining sheet to the one just deleted
|
||||
int newSheetIndex = index;
|
||||
if (newSheetIndex >= nSheets) {
|
||||
newSheetIndex = nSheets-1;
|
||||
}
|
||||
if (wasActive) {
|
||||
setActiveSheet(newSheetIndex);
|
||||
}
|
||||
|
||||
if (wasSelected) {
|
||||
boolean someOtherSheetIsStillSelected = false;
|
||||
for (int i =0; i < nSheets; i++) {
|
||||
if (getSheetAt(i).isSelected()) {
|
||||
someOtherSheetIsStillSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!someOtherSheetIsStillSelected) {
|
||||
setSelectedTab(newSheetIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -834,8 +942,7 @@ public class HSSFWorkbook extends POIDocument
|
|||
HSSFPrintSetup printSetup = sheet.getPrintSetup();
|
||||
printSetup.setValidSettings(false);
|
||||
|
||||
WindowTwoRecord w2 = (WindowTwoRecord) sheet.getSheet().findFirstRecordBySid(WindowTwoRecord.sid);
|
||||
w2.setPaged(true);
|
||||
sheet.setActive(true);
|
||||
}
|
||||
|
||||
private NameRecord findExistingRowColHeaderNameRecord( int sheetIndex )
|
||||
|
|
|
@ -102,7 +102,8 @@ class BlockListImpl
|
|||
catch (ArrayIndexOutOfBoundsException ignored)
|
||||
{
|
||||
throw new IOException("Cannot remove block[ " + index
|
||||
+ " ]; out of range");
|
||||
+ " ]; out of range[ 0 - " +
|
||||
(_blocks.length-1) + " ]");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -81,8 +81,9 @@ public class RawDataBlock
|
|||
log.log(POILogger.ERROR,
|
||||
"Unable to read entire block; " + count
|
||||
+ type + " read before EOF; expected "
|
||||
+ blockSize + " bytes. Your document"
|
||||
+ " has probably been truncated!"
|
||||
+ blockSize + " bytes. Your document "
|
||||
+ "was either written by software that "
|
||||
+ "ignores the spec, or has been truncated!"
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<const name="lower right" value="0"/>
|
||||
<const name="upper right" value="1"/>
|
||||
<const name="lower left" value="2"/>
|
||||
<const name="uper left" value="3"/>
|
||||
<const name="upper left" value="3"/>
|
||||
</field>
|
||||
</fields>
|
||||
</record>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
7 MAX 1 30 V R
|
||||
8 ROW 0 1 V R
|
||||
9 COLUMN 0 1 V R
|
||||
10 NA 0 0 V –
|
||||
10 NA 0 0 V -
|
||||
11 NPV 2 30 V V R
|
||||
12 STDEV 1 30 V R
|
||||
13 DOLLAR 1 2 V V V
|
||||
|
@ -38,7 +38,7 @@
|
|||
16 COS 1 1 V V
|
||||
17 TAN 1 1 V V
|
||||
18 ARCTAN 1 1 V V
|
||||
19 PI 0 0 V –
|
||||
19 PI 0 0 V -
|
||||
20 SQRT 1 1 V V
|
||||
21 EXP 1 1 V V
|
||||
22 LN 1 1 V V
|
||||
|
@ -53,8 +53,8 @@
|
|||
31 MID 3 3 V V V V
|
||||
32 LEN 1 1 V V
|
||||
33 VALUE 1 1 V V
|
||||
34 TRUE 0 0 V –
|
||||
35 FALSE 0 0 V –
|
||||
34 TRUE 0 0 V -
|
||||
35 FALSE 0 0 V -
|
||||
36 AND 1 30 V R
|
||||
37 OR 1 30 V R
|
||||
38 NOT 1 1 V V
|
||||
|
@ -80,7 +80,7 @@
|
|||
60 RATE 3 6 V V V V V V V
|
||||
61 MIRR 3 3 V R V V
|
||||
62 IRR 1 2 V R V
|
||||
63 RAND 0 0 V – x
|
||||
63 RAND 0 0 V - x
|
||||
64 MATCH 2 3 V V R R
|
||||
65 DATE 3 3 V V V V
|
||||
66 TIME 3 3 V V V V
|
||||
|
@ -91,7 +91,7 @@
|
|||
71 HOUR 1 1 V V
|
||||
72 MINUTE 1 1 V V
|
||||
73 SECOND 1 1 V V
|
||||
74 NOW 0 0 V – x
|
||||
74 NOW 0 0 V - x
|
||||
75 AREAS 1 1 V R
|
||||
76 ROWS 1 1 V R
|
||||
77 COLUMNS 1 1 V R
|
||||
|
@ -170,10 +170,10 @@
|
|||
215 JIS 1 1 V V x
|
||||
219 ADDRESS 2 5 V V V V V V
|
||||
220 DAYS360 2 2 V V V x
|
||||
221 TODAY 0 0 V – x
|
||||
221 TODAY 0 0 V - x
|
||||
222 VDB 5 7 V V V V V V V V
|
||||
227 MEDIAN 1 30 V R …
|
||||
228 SUMPRODUCT 1 30 V A …
|
||||
227 MEDIAN 1 30 V R ...
|
||||
228 SUMPRODUCT 1 30 V A ...
|
||||
229 SINH 1 1 V V
|
||||
230 COSH 1 1 V V
|
||||
231 TANH 1 1 V V
|
||||
|
@ -188,7 +188,7 @@
|
|||
247 DB 4 5 V V V V V V
|
||||
252 FREQUENCY 2 2 A R R
|
||||
261 ERROR.TYPE 1 1 V V
|
||||
269 AVEDEV 1 30 V R …
|
||||
269 AVEDEV 1 30 V R ...
|
||||
270 BETADIST 3 5 V V V V V V
|
||||
271 GAMMALN 1 1 V V
|
||||
272 BETAINV 3 5 V V V V V V
|
||||
|
@ -237,12 +237,12 @@
|
|||
315 SLOPE 2 2 V A A
|
||||
316 TTEST 4 4 V A A V V
|
||||
317 PROB 3 4 V A A V V
|
||||
318 DEVSQ 1 30 V R …
|
||||
319 GEOMEAN 1 30 V R …
|
||||
320 HARMEAN 1 30 V R …
|
||||
321 SUMSQ 0 30 V R …
|
||||
322 KURT 1 30 V R …
|
||||
323 SKEW 1 30 V R …
|
||||
318 DEVSQ 1 30 V R ...
|
||||
319 GEOMEAN 1 30 V R ...
|
||||
320 HARMEAN 1 30 V R ...
|
||||
321 SUMSQ 0 30 V R ...
|
||||
322 KURT 1 30 V R ...
|
||||
323 SKEW 1 30 V R ...
|
||||
324 ZTEST 2 3 V R V V
|
||||
325 LARGE 2 2 V R V
|
||||
326 SMALL 2 2 V R V
|
||||
|
@ -274,10 +274,10 @@
|
|||
358 GETPIVOTDATA 2 30
|
||||
359 HYPERLINK 1 2 V V V
|
||||
360 PHONETIC 1 1 V R
|
||||
361 AVERAGEA 1 30 V R …
|
||||
362 MAXA 1 30 V R …
|
||||
363 MINA 1 30 V R …
|
||||
364 STDEVPA 1 30 V R …
|
||||
365 VARPA 1 30 V R …
|
||||
366 STDEVA 1 30 V R …
|
||||
367 VARA 1 30 V R …
|
||||
361 AVERAGEA 1 30 V R ...
|
||||
362 MAXA 1 30 V R ...
|
||||
363 MINA 1 30 V R ...
|
||||
364 STDEVPA 1 30 V R ...
|
||||
365 VARPA 1 30 V R ...
|
||||
366 STDEVA 1 30 V R ...
|
||||
367 VARA 1 30 V R ...
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
7 MAX 1 30 V R
|
||||
8 ROW 0 1 V R
|
||||
9 COLUMN 0 1 V R
|
||||
10 NA 0 0 V –
|
||||
10 NA 0 0 V -
|
||||
11 NPV 2 30 V V R
|
||||
12 STDEV 1 30 V R
|
||||
13 DOLLAR 1 2 V V V
|
||||
|
@ -40,7 +40,7 @@
|
|||
16 COS 1 1 V V
|
||||
17 TAN 1 1 V V
|
||||
18 ATAN 1 1 V V
|
||||
19 PI 0 0 V –
|
||||
19 PI 0 0 V -
|
||||
20 SQRT 1 1 V V
|
||||
21 EXP 1 1 V V
|
||||
22 LN 1 1 V V
|
||||
|
@ -55,8 +55,8 @@
|
|||
31 MID 3 3 V V V V
|
||||
32 LEN 1 1 V V
|
||||
33 VALUE 1 1 V V
|
||||
34 TRUE 0 0 V –
|
||||
35 FALSE 0 0 V –
|
||||
34 TRUE 0 0 V -
|
||||
35 FALSE 0 0 V -
|
||||
36 AND 1 30 V R
|
||||
37 OR 1 30 V R
|
||||
38 NOT 1 1 V V
|
||||
|
@ -82,7 +82,7 @@
|
|||
60 RATE 3 6 V V V V V V V
|
||||
61 MIRR 3 3 V R V V
|
||||
62 IRR 1 2 V R V
|
||||
63 RAND 0 0 V – x
|
||||
63 RAND 0 0 V - x
|
||||
64 MATCH 2 3 V V R R
|
||||
65 DATE 3 3 V V V V
|
||||
66 TIME 3 3 V V V V
|
||||
|
@ -93,7 +93,7 @@
|
|||
71 HOUR 1 1 V V
|
||||
72 MINUTE 1 1 V V
|
||||
73 SECOND 1 1 V V
|
||||
74 NOW 0 0 V – x
|
||||
74 NOW 0 0 V - x
|
||||
75 AREAS 1 1 V R
|
||||
76 ROWS 1 1 V R
|
||||
77 COLUMNS 1 1 V R
|
||||
|
@ -172,10 +172,10 @@
|
|||
215 JIS 1 1 V V x
|
||||
219 ADDRESS 2 5 V V V V V V
|
||||
220 DAYS360 2 2 V V V x
|
||||
221 TODAY 0 0 V – x
|
||||
221 TODAY 0 0 V - x
|
||||
222 VDB 5 7 V V V V V V V V
|
||||
227 MEDIAN 1 30 V R …
|
||||
228 SUMPRODUCT 1 30 V A …
|
||||
227 MEDIAN 1 30 V R ...
|
||||
228 SUMPRODUCT 1 30 V A ...
|
||||
229 SINH 1 1 V V
|
||||
230 COSH 1 1 V V
|
||||
231 TANH 1 1 V V
|
||||
|
@ -192,7 +192,7 @@
|
|||
247 DB 4 5 V V V V V V
|
||||
252 FREQUENCY 2 2 A R R
|
||||
261 ERROR.TYPE 1 1 V V
|
||||
269 AVEDEV 1 30 V R …
|
||||
269 AVEDEV 1 30 V R ...
|
||||
270 BETADIST 3 5 V V V V V V
|
||||
271 GAMMALN 1 1 V V
|
||||
272 BETAINV 3 5 V V V V V V
|
||||
|
@ -241,12 +241,12 @@
|
|||
315 SLOPE 2 2 V A A
|
||||
316 TTEST 4 4 V A A V V
|
||||
317 PROB 3 4 V A A V V
|
||||
318 DEVSQ 1 30 V R …
|
||||
319 GEOMEAN 1 30 V R …
|
||||
320 HARMEAN 1 30 V R …
|
||||
321 SUMSQ 0 30 V R …
|
||||
322 KURT 1 30 V R …
|
||||
323 SKEW 1 30 V R …
|
||||
318 DEVSQ 1 30 V R ...
|
||||
319 GEOMEAN 1 30 V R ...
|
||||
320 HARMEAN 1 30 V R ...
|
||||
321 SUMSQ 0 30 V R ...
|
||||
322 KURT 1 30 V R ...
|
||||
323 SKEW 1 30 V R ...
|
||||
324 ZTEST 2 3 V R V V
|
||||
325 LARGE 2 2 V R V
|
||||
326 SMALL 2 2 V R V
|
||||
|
@ -278,10 +278,10 @@
|
|||
358 GETPIVOTDATA 2 30
|
||||
359 HYPERLINK 1 2 V V V
|
||||
360 PHONETIC 1 1 V R
|
||||
361 AVERAGEA 1 30 V R …
|
||||
362 MAXA 1 30 V R …
|
||||
363 MINA 1 30 V R …
|
||||
364 STDEVPA 1 30 V R …
|
||||
365 VARPA 1 30 V R …
|
||||
366 STDEVA 1 30 V R …
|
||||
367 VARA 1 30 V R …
|
||||
361 AVERAGEA 1 30 V R ...
|
||||
362 MAXA 1 30 V R ...
|
||||
363 MINA 1 30 V R ...
|
||||
364 STDEVPA 1 30 V R ...
|
||||
365 VARPA 1 30 V R ...
|
||||
366 STDEVA 1 30 V R ...
|
||||
367 VARA 1 30 V R ...
|
||||
|
|
|
@ -69,16 +69,9 @@ public class DataExtraction {
|
|||
String name = ole.getInstanceName();
|
||||
if ("Worksheet".equals(name)) {
|
||||
|
||||
//save xls on disk
|
||||
FileOutputStream out = new FileOutputStream(name + "-("+(j)+").xls");
|
||||
InputStream dis = data.getData();
|
||||
byte[] chunk = new byte[2048];
|
||||
int count;
|
||||
while ((count = dis.read(chunk)) >= 0) {
|
||||
out.write(chunk,0,count);
|
||||
}
|
||||
is.close();
|
||||
out.close();
|
||||
//read xls
|
||||
HSSFWorkbook wb = new HSSFWorkbook(data.getData());
|
||||
|
||||
} else if ("Document".equals(name)) {
|
||||
HWPFDocument doc = new HWPFDocument(data.getData());
|
||||
//read the word document
|
||||
|
@ -93,7 +86,15 @@ public class DataExtraction {
|
|||
doc.write(out);
|
||||
out.close();
|
||||
} else {
|
||||
System.err.println("Processing " + name);
|
||||
FileOutputStream out = new FileOutputStream(ole.getProgID() + "-"+(j+1)+".dat");
|
||||
InputStream dis = data.getData();
|
||||
byte[] chunk = new byte[2048];
|
||||
int count;
|
||||
while ((count = dis.read(chunk)) >= 0) {
|
||||
out.write(chunk,0,count);
|
||||
}
|
||||
is.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ public class ShapeFactory {
|
|||
case ShapeTypes.TextBox:
|
||||
shape = new TextBox(spContainer, parent);
|
||||
break;
|
||||
case ShapeTypes.HostControl:
|
||||
case ShapeTypes.PictureFrame: {
|
||||
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
|
||||
EscherProperty prop = Shape.getEscherProperty(opt, EscherProperties.BLIP__PICTUREID);
|
||||
|
|
|
@ -45,7 +45,6 @@ public class TextRun
|
|||
protected TextBytesAtom _byteAtom;
|
||||
protected TextCharsAtom _charAtom;
|
||||
protected StyleTextPropAtom _styleAtom;
|
||||
protected TextSpecInfoAtom _specAtom;
|
||||
protected boolean _isUnicode;
|
||||
protected RichTextRun[] _rtRuns;
|
||||
private SlideShow slideShow;
|
||||
|
@ -319,9 +318,9 @@ public class TextRun
|
|||
* touch the stylings.
|
||||
*/
|
||||
private void storeText(String s) {
|
||||
// Remove a single trailing \n, as there is an implicit one at the
|
||||
// Remove a single trailing \r, as there is an implicit one at the
|
||||
// end of every record
|
||||
if(s.endsWith("\n")) {
|
||||
if(s.endsWith("\r")) {
|
||||
s = s.substring(0, s.length()-1);
|
||||
}
|
||||
|
||||
|
@ -361,6 +360,18 @@ public class TextRun
|
|||
_isUnicode = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* If TextSpecInfoAtom is present, we must update the text size in it,
|
||||
* otherwise the ppt will be corrupted
|
||||
*/
|
||||
if(_records != null) for (int i = 0; i < _records.length; i++) {
|
||||
if(_records[i] instanceof TextSpecInfoAtom){
|
||||
TextSpecInfoAtom specAtom = (TextSpecInfoAtom)_records[i];
|
||||
if((s.length() + 1) != specAtom.getCharactersCovered()){
|
||||
specAtom.reset(s.length() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -446,7 +457,7 @@ public class TextRun
|
|||
* as the the first character has.
|
||||
* If you care about styling, do setText on a RichTextRun instead
|
||||
*/
|
||||
public synchronized void setText(String s) {
|
||||
public synchronized void setRawText(String s) {
|
||||
// Save the new text to the atoms
|
||||
storeText(s);
|
||||
RichTextRun fst = _rtRuns[0];
|
||||
|
@ -474,20 +485,18 @@ public class TextRun
|
|||
_rtRuns[0] = new RichTextRun(this,0,s.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* If TextSpecInfoAtom is present, we must update the text size,
|
||||
* otherwise the ppt will be corrupted
|
||||
*/
|
||||
if(_records != null) for (int i = 0; i < _records.length; i++) {
|
||||
if(_records[i] instanceof TextSpecInfoAtom){
|
||||
TextSpecInfoAtom specAtom = (TextSpecInfoAtom)_records[i];
|
||||
specAtom.setTextSize(s.length());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Changes the text.
|
||||
* Converts '\r' into '\n'
|
||||
*/
|
||||
public synchronized void setText(String s) {
|
||||
String text = normalize(s);
|
||||
setRawText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure a StyleTextPropAtom is present for this run,
|
||||
* by adding if required. Normally for internal TextRun use.
|
||||
*/
|
||||
|
@ -666,4 +675,12 @@ public class TextRun
|
|||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new string with line breaks converted into internal ppt representation
|
||||
*/
|
||||
public String normalize(String s){
|
||||
String ns = s.replaceAll("\\r?\\n", "\r");
|
||||
return ns;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* ====================================================================
|
||||
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.hslf.record;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
/**
|
||||
* Container for OLE Control object. It contains:
|
||||
* <p>
|
||||
* 1. ExControlAtom (4091)
|
||||
* 2. ExOleObjAtom (4035)
|
||||
* 3. CString (4026), Instance MenuName (1) used for menus and the Links dialog box.
|
||||
* 4. CString (4026), Instance ProgID (2) that stores the OLE Programmatic Identifier.
|
||||
* A ProgID is a string that uniquely identifies a given object.
|
||||
* 5. CString (4026), Instance ClipboardName (3) that appears in the paste special dialog.
|
||||
* 6. MetaFile( 4033), optional
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Yegor kozlov
|
||||
*/
|
||||
public class ExControl extends ExEmbed {
|
||||
|
||||
// Links to our more interesting children
|
||||
private ExControlAtom ctrlAtom;
|
||||
|
||||
/**
|
||||
* Set things up, and find our more interesting children
|
||||
*
|
||||
* @param source the source data as a byte array.
|
||||
* @param start the start offset into the byte array.
|
||||
* @param len the length of the slice in the byte array.
|
||||
*/
|
||||
protected ExControl(byte[] source, int start, int len) {
|
||||
super(source, start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ExEmbed, with blank fields
|
||||
*/
|
||||
public ExControl() {
|
||||
super();
|
||||
|
||||
_children[0] = ctrlAtom = new ExControlAtom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ExControlAtom}.
|
||||
*
|
||||
* @return the {@link ExControlAtom}.
|
||||
*/
|
||||
public ExControlAtom getExControlAtom()
|
||||
{
|
||||
return ctrlAtom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type (held as a little endian in bytes 3 and 4)
|
||||
* that this class handles.
|
||||
*
|
||||
* @return the record type.
|
||||
*/
|
||||
public long getRecordType() {
|
||||
return RecordTypes.ExControl.typeID;
|
||||
}
|
||||
|
||||
protected RecordAtom getEmbedAtom(Record[] children){
|
||||
RecordAtom atom = null;
|
||||
if(_children[0] instanceof ExControlAtom) {
|
||||
atom = (ExControlAtom)_children[0];
|
||||
} else {
|
||||
logger.log(POILogger.ERROR, "First child record wasn't a ExControlAtom, was of type " + _children[0].getRecordType());
|
||||
}
|
||||
return atom;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/* ====================================================================
|
||||
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.hslf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Contains a long integer, slideID, which stores the unique slide identifier of the slide
|
||||
* where this control resides.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class ExControlAtom extends RecordAtom {
|
||||
|
||||
|
||||
/**
|
||||
* Record header.
|
||||
*/
|
||||
private byte[] _header;
|
||||
|
||||
/**
|
||||
* slideId.
|
||||
*/
|
||||
private int _id;
|
||||
|
||||
/**
|
||||
* Constructs a brand new embedded object atom record.
|
||||
*/
|
||||
protected ExControlAtom() {
|
||||
_header = new byte[8];
|
||||
|
||||
LittleEndian.putShort(_header, 2, (short) getRecordType());
|
||||
LittleEndian.putInt(_header, 4, 4);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the ExControlAtom record from its source data.
|
||||
*
|
||||
* @param source the source data as a byte array.
|
||||
* @param start the start offset into the byte array.
|
||||
* @param len the length of the slice in the byte array.
|
||||
*/
|
||||
protected ExControlAtom(byte[] source, int start, int len) {
|
||||
// Get the header.
|
||||
_header = new byte[8];
|
||||
System.arraycopy(source, start, _header, 0, 8);
|
||||
|
||||
_id = LittleEndian.getInt(source, start + 8);
|
||||
}
|
||||
|
||||
public int getSlideId() {
|
||||
return _id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the record type.
|
||||
* @return the record type.
|
||||
*/
|
||||
public long getRecordType() {
|
||||
return RecordTypes.ExControlAtom.typeID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
* to disk
|
||||
*
|
||||
* @param out the output stream to write to.
|
||||
* @throws java.io.IOException if an error occurs.
|
||||
*/
|
||||
public void writeOut(OutputStream out) throws IOException {
|
||||
out.write(_header);
|
||||
byte[] data = new byte[4];
|
||||
LittleEndian.putInt(data, _id);
|
||||
out.write(data);
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,7 @@ public class ExEmbed extends RecordContainer {
|
|||
private byte[] _header;
|
||||
|
||||
// Links to our more interesting children
|
||||
private ExEmbedAtom embedAtom;
|
||||
private RecordAtom embedAtom;
|
||||
private ExOleObjAtom oleObjAtom;
|
||||
private CString menuName;
|
||||
private CString progId;
|
||||
|
@ -91,11 +91,7 @@ public class ExEmbed extends RecordContainer {
|
|||
private void findInterestingChildren() {
|
||||
|
||||
// First child should be the ExHyperlinkAtom
|
||||
if(_children[0] instanceof ExEmbedAtom) {
|
||||
embedAtom = (ExEmbedAtom)_children[0];
|
||||
} else {
|
||||
logger.log(POILogger.ERROR, "First child record wasn't a ExEmbedAtom, was of type " + _children[0].getRecordType());
|
||||
}
|
||||
embedAtom = getEmbedAtom(_children);
|
||||
|
||||
// Second child should be the ExOleObjAtom
|
||||
if (_children[1] instanceof ExOleObjAtom) {
|
||||
|
@ -115,6 +111,16 @@ public class ExEmbed extends RecordContainer {
|
|||
}
|
||||
}
|
||||
|
||||
protected RecordAtom getEmbedAtom(Record[] children){
|
||||
RecordAtom atom = null;
|
||||
if(_children[0] instanceof ExEmbedAtom) {
|
||||
atom = (ExEmbedAtom)_children[0];
|
||||
} else {
|
||||
logger.log(POILogger.ERROR, "First child record wasn't a ExEmbedAtom, was of type " + _children[0].getRecordType());
|
||||
}
|
||||
return atom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ExEmbedAtom}.
|
||||
*
|
||||
|
@ -122,7 +128,7 @@ public class ExEmbed extends RecordContainer {
|
|||
*/
|
||||
public ExEmbedAtom getExEmbedAtom()
|
||||
{
|
||||
return embedAtom;
|
||||
return (ExEmbedAtom)embedAtom;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.*;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -92,6 +90,25 @@ public class ExOleObjStg extends RecordAtom implements PersistRecord {
|
|||
return new InflaterInputStream(compressedStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the embedded data.
|
||||
*
|
||||
* @param data the embedded data.
|
||||
*/
|
||||
public void setData(byte[] data) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
//first four bytes is the length of the raw data
|
||||
byte[] b = new byte[4];
|
||||
LittleEndian.putInt(b, data.length);
|
||||
out.write(b);
|
||||
|
||||
DeflaterOutputStream def = new DeflaterOutputStream(out);
|
||||
def.write(data, 0, data.length);
|
||||
def.finish();
|
||||
_data = out.toByteArray();
|
||||
LittleEndian.putInt(_header, 4, _data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the record type.
|
||||
*
|
||||
|
|
|
@ -119,7 +119,7 @@ public class RecordTypes {
|
|||
public static final Type RecolorInfoAtom = new Type(4071,null);
|
||||
public static final Type ExQuickTimeMovie = new Type(4074,null);
|
||||
public static final Type ExQuickTimeMovieData = new Type(4075,null);
|
||||
public static final Type ExControl = new Type(4078,null);
|
||||
public static final Type ExControl = new Type(4078,ExControl.class);
|
||||
public static final Type SlideListWithText = new Type(4080,SlideListWithText.class);
|
||||
public static final Type InteractiveInfo = new Type(4082,InteractiveInfo.class);
|
||||
public static final Type InteractiveInfoAtom = new Type(4083,InteractiveInfoAtom.class);
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* The special info runs contained in this text.
|
||||
|
@ -82,4 +83,118 @@ public class TextSpecInfoAtom extends RecordAtom {
|
|||
public void setTextSize(int size){
|
||||
LittleEndian.putInt(_data, 0, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the content to one info run with the default values
|
||||
* @param size the site of parent text
|
||||
*/
|
||||
public void reset(int size){
|
||||
_data = new byte[10];
|
||||
// 01 00 00 00
|
||||
LittleEndian.putInt(_data, 0, size);
|
||||
// 01 00 00 00
|
||||
LittleEndian.putInt(_data, 4, 1); //mask
|
||||
// 00 00
|
||||
LittleEndian.putShort(_data, 8, (short)0); //langId
|
||||
|
||||
// Update the size (header bytes 5-8)
|
||||
LittleEndian.putInt(_header, 4, _data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of characters covered by this records
|
||||
*
|
||||
* @return the number of characters covered by this records
|
||||
*/
|
||||
public int getCharactersCovered(){
|
||||
int covered = 0;
|
||||
TextSpecInfoRun[] runs = getTextSpecInfoRuns();
|
||||
for (int i = 0; i < runs.length; i++) covered += runs[i].len;
|
||||
return covered;
|
||||
}
|
||||
|
||||
public TextSpecInfoRun[] getTextSpecInfoRuns(){
|
||||
ArrayList lst = new ArrayList();
|
||||
int pos = 0;
|
||||
int[] bits = {1, 0, 2};
|
||||
while(pos < _data.length) {
|
||||
TextSpecInfoRun run = new TextSpecInfoRun();
|
||||
run.len = LittleEndian.getInt(_data, pos); pos += 4;
|
||||
run.mask = LittleEndian.getInt(_data, pos); pos += 4;
|
||||
for (int i = 0; i < bits.length; i++) {
|
||||
if((run.mask & 1 << bits[i]) != 0){
|
||||
switch (bits[i]){
|
||||
case 0:
|
||||
run.spellInfo = LittleEndian.getShort(_data, pos); pos += 2;
|
||||
break;
|
||||
case 1:
|
||||
run.langId = LittleEndian.getShort(_data, pos); pos += 2;
|
||||
break;
|
||||
case 2:
|
||||
run.altLangId = LittleEndian.getShort(_data, pos); pos += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lst.add(run);
|
||||
}
|
||||
return (TextSpecInfoRun[])lst.toArray(new TextSpecInfoRun[lst.size()]);
|
||||
|
||||
}
|
||||
|
||||
public static class TextSpecInfoRun {
|
||||
//Length of special info run.
|
||||
protected int len;
|
||||
|
||||
//Special info mask of this run;
|
||||
protected int mask;
|
||||
|
||||
// info fields as indicated by the mask.
|
||||
// -1 means the bit is not set
|
||||
protected short spellInfo = -1;
|
||||
protected short langId = -1;
|
||||
protected short altLangId = -1;
|
||||
|
||||
/**
|
||||
* Spelling status of this text. See Spell Info table below.
|
||||
*
|
||||
* <p>Spell Info Types:</p>
|
||||
* <li>0 Unchecked
|
||||
* <li>1 Previously incorrect, needs rechecking
|
||||
* <li>2 Correct
|
||||
* <li>3 Incorrect
|
||||
*
|
||||
* @return Spelling status of this text
|
||||
*/
|
||||
public short getSpellInfo(){
|
||||
return spellInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Windows LANGID for this text.
|
||||
*
|
||||
* @return Windows LANGID for this text.
|
||||
*/
|
||||
public short getLangId(){
|
||||
return spellInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternate Windows LANGID of this text;
|
||||
* must be a valid non-East Asian LANGID if the text has an East Asian language,
|
||||
* otherwise may be an East Asian LANGID or language neutral (zero).
|
||||
*
|
||||
* @return Alternate Windows LANGID of this text
|
||||
*/
|
||||
public short getAltLangId(){
|
||||
return altLangId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Length of special info run.
|
||||
*/
|
||||
public int length(){
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.apache.poi.hslf.usermodel;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hslf.record.ExOleObjStg;
|
||||
|
||||
|
@ -49,6 +50,15 @@ public class ObjectData {
|
|||
return storage.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the embedded data.
|
||||
*
|
||||
* @param data the embedded data.
|
||||
*/
|
||||
public void setData(byte[] data) throws IOException {
|
||||
storage.setData(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the record that contains the object data.
|
||||
*
|
||||
|
|
|
@ -162,10 +162,18 @@ public class RichTextRun {
|
|||
* Change the text
|
||||
*/
|
||||
public void setText(String text) {
|
||||
length = text.length();
|
||||
parentRun.changeTextInRichTextRun(this,text);
|
||||
String s = parentRun.normalize(text);
|
||||
setRawText(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the text
|
||||
*/
|
||||
public void setRawText(String text) {
|
||||
length = text.length();
|
||||
parentRun.changeTextInRichTextRun(this,text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the RichTextRun its new position in the parent TextRun
|
||||
* @param startAt
|
||||
|
|
|
@ -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,22 +15,20 @@
|
|||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hwpf.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
import org.apache.poi.hwpf.usermodel.CharacterProperties;
|
||||
import org.apache.poi.hwpf.usermodel.ParagraphProperties;
|
||||
|
||||
import org.apache.poi.hwpf.sprm.ParagraphSprmCompressor;
|
||||
import org.apache.poi.hwpf.sprm.CharacterSprmCompressor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ListLevel
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final class ListLevel
|
||||
{
|
||||
private static final int RGBXCH_NUMS_SIZE = 9;
|
||||
|
||||
private int _iStartAt;
|
||||
private byte _nfc;
|
||||
private byte _info;
|
||||
|
@ -70,7 +67,7 @@ public class ListLevel
|
|||
_grpprlPapx = new byte[0];
|
||||
_grpprlChpx = new byte[0];
|
||||
_numberText = new char[0];
|
||||
_rgbxchNums = new byte[9];
|
||||
_rgbxchNums = new byte[RGBXCH_NUMS_SIZE];
|
||||
|
||||
if (numbered)
|
||||
{
|
||||
|
@ -90,12 +87,11 @@ public class ListLevel
|
|||
_nfc = buf[offset++];
|
||||
_info = buf[offset++];
|
||||
|
||||
_rgbxchNums = new byte[9];
|
||||
for (int x = 0; x < 9; x++)
|
||||
{
|
||||
_rgbxchNums[x] = buf[offset++];
|
||||
}
|
||||
_ixchFollow = buf[offset++];
|
||||
_rgbxchNums = new byte[RGBXCH_NUMS_SIZE];
|
||||
System.arraycopy(buf, offset, _rgbxchNums, 0, RGBXCH_NUMS_SIZE);
|
||||
offset += RGBXCH_NUMS_SIZE;
|
||||
|
||||
_ixchFollow = buf[offset++];
|
||||
_dxaSpace = LittleEndian.getInt(buf, offset);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
_dxaIndent = LittleEndian.getInt(buf, offset);
|
||||
|
@ -207,8 +203,8 @@ public class ListLevel
|
|||
offset += LittleEndian.INT_SIZE;
|
||||
buf[offset++] = _nfc;
|
||||
buf[offset++] = _info;
|
||||
System.arraycopy(_rgbxchNums, 0, buf, offset, _rgbxchNums.length);
|
||||
offset += _rgbxchNums.length;
|
||||
System.arraycopy(_rgbxchNums, 0, buf, offset, RGBXCH_NUMS_SIZE);
|
||||
offset += RGBXCH_NUMS_SIZE;
|
||||
buf[offset++] = _ixchFollow;
|
||||
LittleEndian.putInt(buf, offset, _dxaSpace);
|
||||
offset += LittleEndian.INT_SIZE;
|
||||
|
@ -225,23 +221,33 @@ public class ListLevel
|
|||
System.arraycopy(_grpprlPapx, 0, buf, offset, _cbGrpprlPapx);
|
||||
offset += _cbGrpprlPapx;
|
||||
|
||||
LittleEndian.putShort(buf, offset, (short)_numberText.length);
|
||||
offset += LittleEndian.SHORT_SIZE;
|
||||
for (int x = 0; x < _numberText.length; x++)
|
||||
{
|
||||
LittleEndian.putShort(buf, offset, (short)_numberText[x]);
|
||||
if (_numberText == null) {
|
||||
// TODO - write junit to test this flow
|
||||
LittleEndian.putUShort(buf, offset, 0);
|
||||
} else {
|
||||
LittleEndian.putUShort(buf, offset, _numberText.length);
|
||||
offset += LittleEndian.SHORT_SIZE;
|
||||
for (int x = 0; x < _numberText.length; x++)
|
||||
{
|
||||
LittleEndian.putUShort(buf, offset, _numberText[x]);
|
||||
offset += LittleEndian.SHORT_SIZE;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
public int getSizeInBytes()
|
||||
{
|
||||
if (_numberText!=null)
|
||||
{
|
||||
return 28 + _cbGrpprlChpx + _cbGrpprlPapx + (_numberText.length * LittleEndian.SHORT_SIZE) + 2;
|
||||
} else {
|
||||
return 28 + _cbGrpprlChpx + _cbGrpprlPapx + 2;
|
||||
}
|
||||
int result =
|
||||
6 // int byte byte
|
||||
+ RGBXCH_NUMS_SIZE
|
||||
+ 13 // byte int int byte byte short
|
||||
+ _cbGrpprlChpx
|
||||
+ _cbGrpprlPapx
|
||||
+ 2; // numberText length
|
||||
if (_numberText != null) {
|
||||
result += _numberText.length * LittleEndian.SHORT_SIZE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
|
||||
/* ====================================================================
|
||||
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.hslf.record;
|
||||
|
||||
import org.apache.poi.hslf.HSLFSlideShow;
|
||||
import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextProp;
|
||||
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.util.HexDump;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Tests TextSpecInfoAtom
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestTextSpecInfoAtom extends TestCase {
|
||||
|
||||
//from a real file
|
||||
private byte[] data_1 = new byte[] {
|
||||
0x00, 0x00, (byte)0xAA, 0x0F, 0x2C, 0x00, 0x00, 0x00,
|
||||
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
public void testRead() throws Exception {
|
||||
TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);
|
||||
TextSpecInfoAtom.TextSpecInfoRun[] run = spec.getTextSpecInfoRuns();
|
||||
assertEquals(5, run.length);
|
||||
|
||||
assertEquals(10, run[0].length());
|
||||
assertEquals(1, run[1].length());
|
||||
assertEquals(70, run[2].length());
|
||||
assertEquals(9, run[3].length());
|
||||
assertEquals(32, run[4].length());
|
||||
|
||||
}
|
||||
|
||||
public void testWrite() throws Exception {
|
||||
TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
spec.writeOut(out);
|
||||
|
||||
byte[] result = out.toByteArray();
|
||||
assertTrue(Arrays.equals(result, data_1));
|
||||
}
|
||||
|
||||
public void testReset() throws Exception {
|
||||
TextSpecInfoAtom spec = new TextSpecInfoAtom(data_1, 0, data_1.length);
|
||||
spec.reset(32); //length of the parent text
|
||||
|
||||
TextSpecInfoAtom.TextSpecInfoRun[] run = spec.getTextSpecInfoRuns();
|
||||
assertEquals(1, run.length);
|
||||
|
||||
assertEquals(32, run[0].length());
|
||||
|
||||
//serialize and read again
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
spec.writeOut(out);
|
||||
|
||||
byte[] result = out.toByteArray();
|
||||
TextSpecInfoAtom spec2 = new TextSpecInfoAtom(result, 0, result.length);
|
||||
TextSpecInfoAtom.TextSpecInfoRun[] run2 = spec2.getTextSpecInfoRuns();
|
||||
assertEquals(1, run2.length);
|
||||
|
||||
assertEquals(32, run2[0].length());
|
||||
}
|
||||
}
|
|
@ -22,9 +22,7 @@ import junit.framework.TestSuite;
|
|||
|
||||
import org.apache.poi.hssf.eventmodel.TestEventRecordFactory;
|
||||
import org.apache.poi.hssf.eventmodel.TestModelFactory;
|
||||
import org.apache.poi.hssf.model.TestDrawingManager;
|
||||
import org.apache.poi.hssf.model.TestFormulaParser;
|
||||
import org.apache.poi.hssf.model.TestSheet;
|
||||
import org.apache.poi.hssf.model.AllModelTests;
|
||||
import org.apache.poi.hssf.record.AllRecordTests;
|
||||
import org.apache.poi.hssf.usermodel.AllUserModelTests;
|
||||
import org.apache.poi.hssf.util.TestAreaReference;
|
||||
|
@ -50,10 +48,10 @@ public final class HSSFTests {
|
|||
TestSuite suite = new TestSuite("Tests for org.apache.poi.hssf");
|
||||
// $JUnit-BEGIN$
|
||||
|
||||
suite.addTest(AllModelTests.suite());
|
||||
suite.addTest(AllUserModelTests.suite());
|
||||
suite.addTest(AllRecordTests.suite());
|
||||
|
||||
suite.addTest(new TestSuite(TestFormulaParser.class));
|
||||
suite.addTest(new TestSuite(TestAreaReference.class));
|
||||
suite.addTest(new TestSuite(TestCellReference.class));
|
||||
suite.addTest(new TestSuite(TestRangeAddress.class));
|
||||
|
@ -61,8 +59,6 @@ public final class HSSFTests {
|
|||
suite.addTest(new TestSuite(TestSheetReferences.class));
|
||||
suite.addTest(new TestSuite(TestEventRecordFactory.class));
|
||||
suite.addTest(new TestSuite(TestModelFactory.class));
|
||||
suite.addTest(new TestSuite(TestDrawingManager.class));
|
||||
suite.addTest(new TestSuite(TestSheet.class));
|
||||
// $JUnit-END$
|
||||
return suite;
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,40 @@
|
|||
/* ====================================================================
|
||||
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.model;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
/**
|
||||
* Collects all tests for <tt>org.apache.poi.hssf.model</tt>.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class AllModelTests {
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite result = new TestSuite(AllModelTests.class.getName());
|
||||
result.addTestSuite(TestDrawingManager.class);
|
||||
result.addTestSuite(TestDrawingManager2.class);
|
||||
result.addTestSuite(TestFormulaParser.class);
|
||||
result.addTestSuite(TestFormulaParserEval.class);
|
||||
result.addTestSuite(TestSheet.class);
|
||||
result.addTestSuite(TestSheetAdditional.class);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -65,6 +65,7 @@ public final class TestFormulaParser extends TestCase {
|
|||
* @return parsed token array already confirmed not <code>null</code>
|
||||
*/
|
||||
private static Ptg[] parseFormula(String s) {
|
||||
// TODO - replace multiple copies of this code with calls to this method
|
||||
FormulaParser fp = new FormulaParser(s, null);
|
||||
fp.parse();
|
||||
Ptg[] result = fp.getRPNPtg();
|
||||
|
@ -86,7 +87,6 @@ public final class TestFormulaParser extends TestCase {
|
|||
assertTrue("",(ptgs[0] instanceof IntPtg));
|
||||
assertTrue("",(ptgs[1] instanceof IntPtg));
|
||||
assertTrue("",(ptgs[2] instanceof AddPtg));
|
||||
|
||||
}
|
||||
|
||||
public void testFormulaWithSpace2() {
|
||||
|
@ -169,8 +169,6 @@ public final class TestFormulaParser extends TestCase {
|
|||
assertEquals("If FALSE offset", (short)7, ifPtg.getData());
|
||||
|
||||
FuncVarPtg funcPtg = (FuncVarPtg)asts[8];
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,8 +188,6 @@ public final class TestFormulaParser extends TestCase {
|
|||
assertTrue("It is not an if", ifFunc.isOptimizedIf());
|
||||
|
||||
assertTrue("Average Function set correctly", (asts[5] instanceof FuncVarPtg));
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testIfSingleCondition(){
|
||||
|
@ -213,8 +209,6 @@ public final class TestFormulaParser extends TestCase {
|
|||
assertTrue("Ptg is not a Variable Function", (asts[6] instanceof FuncVarPtg));
|
||||
FuncVarPtg funcPtg = (FuncVarPtg)asts[6];
|
||||
assertEquals("Arguments", 2, funcPtg.getNumberOfOperands());
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testSumIf() {
|
||||
|
@ -223,7 +217,6 @@ public final class TestFormulaParser extends TestCase {
|
|||
fp.parse();
|
||||
Ptg[] asts = fp.getRPNPtg();
|
||||
assertEquals("4 Ptgs expected", 4, asts.length);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -235,51 +228,35 @@ public final class TestFormulaParser extends TestCase {
|
|||
String currencyCell = "F3";
|
||||
String function="\"TOTAL[\"&"+currencyCell+"&\"]\"";
|
||||
|
||||
FormulaParser fp = new FormulaParser(function, null);
|
||||
fp.parse();
|
||||
Ptg[] asts = fp.getRPNPtg();
|
||||
Ptg[] asts = parseFormula(function);
|
||||
assertEquals("5 ptgs expected", 5, asts.length);
|
||||
assertTrue ("Ptg[0] is a string", (asts[0] instanceof StringPtg));
|
||||
StringPtg firstString = (StringPtg)asts[0];
|
||||
|
||||
assertEquals("TOTAL[", firstString.getValue());
|
||||
//the PTG order isn't 100% correct but it still works - dmui
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void testSimpleLogical() {
|
||||
FormulaParser fp=new FormulaParser("IF(A1<A2,B1,B2)",null);
|
||||
fp.parse();
|
||||
Ptg[] ptgs = fp.getRPNPtg();
|
||||
assertTrue("Ptg array should not be null", ptgs !=null);
|
||||
Ptg[] ptgs = parseFormula("IF(A1<A2,B1,B2)");
|
||||
assertEquals("Ptg array length", 9, ptgs.length);
|
||||
assertEquals("3rd Ptg is less than",LessThanPtg.class,ptgs[2].getClass());
|
||||
|
||||
|
||||
assertEquals("3rd Ptg is less than", LessThanPtg.class, ptgs[2].getClass());
|
||||
}
|
||||
|
||||
public void testParenIf() {
|
||||
FormulaParser fp=new FormulaParser("IF((A1+A2)<=3,\"yes\",\"no\")",null);
|
||||
fp.parse();
|
||||
Ptg[] ptgs = fp.getRPNPtg();
|
||||
assertTrue("Ptg array should not be null", ptgs !=null);
|
||||
Ptg[] ptgs = parseFormula("IF((A1+A2)<=3,\"yes\",\"no\")");
|
||||
assertEquals("Ptg array length", 12, ptgs.length);
|
||||
assertEquals("6th Ptg is less than equal",LessEqualPtg.class,ptgs[5].getClass());
|
||||
assertEquals("11th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[10].getClass());
|
||||
}
|
||||
|
||||
public void testEmbeddedIf() {
|
||||
FormulaParser fp=new FormulaParser("IF(3>=1,\"*\",IF(4<>1,\"first\",\"second\"))",null);
|
||||
fp.parse();
|
||||
Ptg[] ptgs = fp.getRPNPtg();
|
||||
assertTrue("Ptg array should not be null", ptgs !=null);
|
||||
Ptg[] ptgs = parseFormula("IF(3>=1,\"*\",IF(4<>1,\"first\",\"second\"))");
|
||||
assertEquals("Ptg array length", 17, ptgs.length);
|
||||
|
||||
assertEquals("6th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[5].getClass());
|
||||
assertEquals("9th Ptg is not a not equal ptg",NotEqualPtg.class,ptgs[8].getClass());
|
||||
assertEquals("15th Ptg is not the inner IF variable function ptg",FuncVarPtg.class,ptgs[14].getClass());
|
||||
|
||||
}
|
||||
|
||||
public void testMacroFunction() {
|
||||
|
@ -302,16 +279,15 @@ public final class TestFormulaParser extends TestCase {
|
|||
Ptg[] ptg = fp.getRPNPtg();
|
||||
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
|
||||
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
|
||||
|
||||
}
|
||||
|
||||
public void testConcatenate(){
|
||||
FormulaParser fp = new FormulaParser("CONCATENATE(\"first\",\"second\")",null);
|
||||
fp.parse();
|
||||
Ptg[] ptg = fp.getRPNPtg();
|
||||
assertTrue("first ptg is string",ptg[0] instanceof StringPtg);
|
||||
assertTrue("second ptg is string",ptg[1] instanceof StringPtg);
|
||||
}
|
||||
public void testConcatenate() {
|
||||
FormulaParser fp = new FormulaParser("CONCATENATE(\"first\",\"second\")", null);
|
||||
fp.parse();
|
||||
Ptg[] ptg = fp.getRPNPtg();
|
||||
assertTrue("first ptg is string", ptg[0] instanceof StringPtg);
|
||||
assertTrue("second ptg is string", ptg[1] instanceof StringPtg);
|
||||
}
|
||||
|
||||
public void testWorksheetReferences()
|
||||
{
|
||||
|
@ -395,16 +371,16 @@ public final class TestFormulaParser extends TestCase {
|
|||
|
||||
/** bug 33160, testcase by Amol Deshmukh*/
|
||||
public void testSimpleLongFormula() {
|
||||
FormulaParser fp = new FormulaParser("40000/2", null);
|
||||
fp.parse();
|
||||
Ptg[] ptgs = fp.getRPNPtg();
|
||||
assertTrue("three tokens expected, got "+ptgs.length,ptgs.length == 3);
|
||||
assertTrue("IntPtg",(ptgs[0] instanceof IntPtg));
|
||||
assertTrue("IntPtg",(ptgs[1] instanceof IntPtg));
|
||||
assertTrue("DividePtg",(ptgs[2] instanceof DividePtg));
|
||||
FormulaParser fp = new FormulaParser("40000/2", null);
|
||||
fp.parse();
|
||||
Ptg[] ptgs = fp.getRPNPtg();
|
||||
assertTrue("three tokens expected, got " + ptgs.length, ptgs.length == 3);
|
||||
assertTrue("IntPtg", (ptgs[0] instanceof IntPtg));
|
||||
assertTrue("IntPtg", (ptgs[1] instanceof IntPtg));
|
||||
assertTrue("DividePtg", (ptgs[2] instanceof DividePtg));
|
||||
}
|
||||
|
||||
/** bug 35027, underscore in sheet name*/
|
||||
/** bug 35027, underscore in sheet name */
|
||||
public void testUnderscore() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
|
||||
|
@ -775,8 +751,34 @@ public final class TestFormulaParser extends TestCase {
|
|||
StringPtg sp = (StringPtg) parseSingleToken(formula, StringPtg.class);
|
||||
assertEquals(expectedValue, sp.getValue());
|
||||
}
|
||||
public void testParseStringLiterals_bug28754() {
|
||||
|
||||
public void testPaseStringLiterals() {
|
||||
StringPtg sp;
|
||||
try {
|
||||
sp = (StringPtg) parseSingleToken("\"test\"\"ing\"", StringPtg.class);
|
||||
} catch (RuntimeException e) {
|
||||
if(e.getMessage().startsWith("Cannot Parse")) {
|
||||
throw new AssertionFailedError("Identified bug 28754a");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
assertEquals("test\"ing", sp.getValue());
|
||||
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet sheet = wb.createSheet();
|
||||
wb.setSheetName(0, "Sheet1");
|
||||
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
HSSFCell cell = row.createCell((short)0);
|
||||
cell.setCellFormula("right(\"test\"\"ing\", 3)");
|
||||
String actualCellFormula = cell.getCellFormula();
|
||||
if("RIGHT(\"test\"ing\",3)".equals(actualCellFormula)) {
|
||||
throw new AssertionFailedError("Identified bug 28754b");
|
||||
}
|
||||
assertEquals("RIGHT(\"test\"\"ing\",3)", actualCellFormula);
|
||||
}
|
||||
|
||||
public void testParseStringLiterals() {
|
||||
confirmStringParse("goto considered harmful");
|
||||
|
||||
confirmStringParse("goto 'considered' harmful");
|
||||
|
@ -810,10 +812,8 @@ public final class TestFormulaParser extends TestCase {
|
|||
parseExpectedException("#DIV/ 0+2");
|
||||
|
||||
|
||||
if (false) { // TODO - add functionality to detect func arg count mismatch
|
||||
parseExpectedException("IF(TRUE)");
|
||||
parseExpectedException("countif(A1:B5, C1, D1)");
|
||||
}
|
||||
parseExpectedException("IF(TRUE)");
|
||||
parseExpectedException("countif(A1:B5, C1, D1)");
|
||||
}
|
||||
|
||||
private static void parseExpectedException(String formula) {
|
||||
|
@ -887,8 +887,16 @@ public final class TestFormulaParser extends TestCase {
|
|||
assertTrue(e.getMessage().startsWith("Too few arguments suppled to operation token"));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Make sure that POI uses the right Func Ptg when encoding formulas. Functions with variable
|
||||
* number of args should get FuncVarPtg, functions with fixed args should get FuncPtg.<p/>
|
||||
*
|
||||
* Prior to the fix for bug 44675 POI would encode FuncVarPtg for all functions. In many cases
|
||||
* Excel tolerates the wrong Ptg and evaluates the formula OK (e.g. SIN), but in some cases
|
||||
* (e.g. COUNTIF) Excel fails to evaluate the formula, giving '#VALUE!' instead.
|
||||
*/
|
||||
public void testFuncPtgSelection() {
|
||||
HSSFWorkbook book = new HSSFWorkbook();
|
||||
HSSFWorkbook book = new HSSFWorkbook();
|
||||
Ptg[] ptgs;
|
||||
ptgs = FormulaParser.parse("countif(A1:A2, 1)", book);
|
||||
assertEquals(3, ptgs.length);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -15,7 +14,6 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.model;
|
||||
|
||||
|
@ -34,8 +32,7 @@ import java.util.List;
|
|||
*
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
*/
|
||||
public class TestSheet extends TestCase
|
||||
{
|
||||
public final class TestSheet extends TestCase {
|
||||
public void testCreateSheet() throws Exception
|
||||
{
|
||||
// Check we're adding row and cell aggregates
|
||||
|
@ -76,6 +73,21 @@ public class TestSheet extends TestCase
|
|||
if ((regionsToAdd % 1027) != 0)
|
||||
recordsExpected++;
|
||||
assertTrue("The " + regionsToAdd + " merged regions should have been spread out over " + recordsExpected + " records, not " + recordsAdded, recordsAdded == recordsExpected);
|
||||
// Check we can't add one with invalid date
|
||||
try {
|
||||
sheet.addMergedRegion(10, (short)10, 9, (short)12);
|
||||
fail("Expected an exception to occur");
|
||||
} catch(IllegalArgumentException e) {
|
||||
// occurs during successful test
|
||||
assertEquals("The 'to' row (9) must not be less than the 'from' row (10)", e.getMessage());
|
||||
}
|
||||
try {
|
||||
sheet.addMergedRegion(10, (short)10, 12, (short)9);
|
||||
fail("Expected an exception to occur");
|
||||
} catch(IllegalArgumentException e) {
|
||||
// occurs during successful test
|
||||
assertEquals("The 'to' col (9) must not be less than the 'from' col (10)", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testRemoveMergedRegion()
|
||||
|
@ -113,9 +125,9 @@ public class TestSheet extends TestCase
|
|||
|
||||
MergeCellsRecord merged = new MergeCellsRecord();
|
||||
merged.addArea(0, (short)0, 1, (short)2);
|
||||
records.add(new RowRecord());
|
||||
records.add(new RowRecord());
|
||||
records.add(new RowRecord());
|
||||
records.add(new RowRecord(0));
|
||||
records.add(new RowRecord(1));
|
||||
records.add(new RowRecord(2));
|
||||
records.add(merged);
|
||||
|
||||
Sheet sheet = Sheet.createSheet(records, 0);
|
||||
|
@ -142,20 +154,11 @@ public class TestSheet extends TestCase
|
|||
*/
|
||||
public void testRowAggregation() {
|
||||
List records = new ArrayList();
|
||||
RowRecord row = new RowRecord();
|
||||
row.setRowNumber(0);
|
||||
records.add(row);
|
||||
|
||||
row = new RowRecord();
|
||||
row.setRowNumber(1);
|
||||
records.add(row);
|
||||
|
||||
records.add(new RowRecord(0));
|
||||
records.add(new RowRecord(1));
|
||||
records.add(new StringRecord());
|
||||
|
||||
row = new RowRecord();
|
||||
row.setRowNumber(2);
|
||||
records.add(row);
|
||||
|
||||
records.add(new RowRecord(2));
|
||||
|
||||
Sheet sheet = Sheet.createSheet(records, 0);
|
||||
assertNotNull("Row [2] was skipped", sheet.getRow(2));
|
||||
|
@ -197,9 +200,9 @@ public class TestSheet extends TestCase
|
|||
Iterator iterator = sheet.getRowBreaks();
|
||||
while (iterator.hasNext()) {
|
||||
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
|
||||
int main = (int)breakItem.main;
|
||||
int main = breakItem.main;
|
||||
if (main != 0 && main != 10 && main != 11) fail("Invalid page break");
|
||||
if (main == 0) is0 = true;
|
||||
if (main == 0) is0 = true;
|
||||
if (main == 10) is10= true;
|
||||
if (main == 11) is11 = true;
|
||||
}
|
||||
|
@ -216,8 +219,6 @@ public class TestSheet extends TestCase
|
|||
assertFalse("row should be removed", sheet.isRowBroken(10));
|
||||
|
||||
assertEquals("no more breaks", 0, sheet.getNumRowBreaks());
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -256,10 +257,10 @@ public class TestSheet extends TestCase
|
|||
Iterator iterator = sheet.getColumnBreaks();
|
||||
while (iterator.hasNext()) {
|
||||
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
|
||||
int main = (int)breakItem.main;
|
||||
int main = breakItem.main;
|
||||
if (main != 0 && main != 1 && main != 10 && main != 15) fail("Invalid page break");
|
||||
if (main == 0) is0 = true;
|
||||
if (main == 1) is1 = true;
|
||||
if (main == 0) is0 = true;
|
||||
if (main == 1) is1 = true;
|
||||
if (main == 10) is10= true;
|
||||
if (main == 15) is15 = true;
|
||||
}
|
||||
|
@ -286,72 +287,69 @@ public class TestSheet extends TestCase
|
|||
* works as designed.
|
||||
*/
|
||||
public void testXFIndexForColumn() {
|
||||
try{
|
||||
final short TEST_IDX = 10;
|
||||
final short DEFAULT_IDX = 0xF; // 15
|
||||
short xfindex = Short.MIN_VALUE;
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
|
||||
// without ColumnInfoRecord
|
||||
xfindex = sheet.getXFIndexForColAt((short) 0);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 1);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
|
||||
ColumnInfoRecord nci = ( ColumnInfoRecord ) sheet.createColInfo();
|
||||
sheet.columns.insertColumn(nci);
|
||||
|
||||
// single column ColumnInfoRecord
|
||||
nci.setFirstColumn((short) 2);
|
||||
nci.setLastColumn((short) 2);
|
||||
nci.setXFIndex(TEST_IDX);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 0);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 1);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 2);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 3);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
final short TEST_IDX = 10;
|
||||
final short DEFAULT_IDX = 0xF; // 15
|
||||
short xfindex = Short.MIN_VALUE;
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
|
||||
// without ColumnInfoRecord
|
||||
xfindex = sheet.getXFIndexForColAt((short) 0);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 1);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
|
||||
ColumnInfoRecord nci = ( ColumnInfoRecord ) sheet.createColInfo();
|
||||
sheet.columns.insertColumn(nci);
|
||||
|
||||
// single column ColumnInfoRecord
|
||||
nci.setFirstColumn((short) 2);
|
||||
nci.setLastColumn((short) 2);
|
||||
nci.setXFIndex(TEST_IDX);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 0);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 1);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 2);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 3);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
|
||||
// ten column ColumnInfoRecord
|
||||
nci.setFirstColumn((short) 2);
|
||||
nci.setLastColumn((short) 11);
|
||||
nci.setXFIndex(TEST_IDX);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 1);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 2);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 6);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 11);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 12);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
// ten column ColumnInfoRecord
|
||||
nci.setFirstColumn((short) 2);
|
||||
nci.setLastColumn((short) 11);
|
||||
nci.setXFIndex(TEST_IDX);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 1);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 2);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 6);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 11);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 12);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
|
||||
// single column ColumnInfoRecord starting at index 0
|
||||
nci.setFirstColumn((short) 0);
|
||||
nci.setLastColumn((short) 0);
|
||||
nci.setXFIndex(TEST_IDX);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 0);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 1);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
// single column ColumnInfoRecord starting at index 0
|
||||
nci.setFirstColumn((short) 0);
|
||||
nci.setLastColumn((short) 0);
|
||||
nci.setXFIndex(TEST_IDX);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 0);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 1);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
|
||||
// ten column ColumnInfoRecord starting at index 0
|
||||
nci.setFirstColumn((short) 0);
|
||||
nci.setLastColumn((short) 9);
|
||||
nci.setXFIndex(TEST_IDX);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 0);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 7);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 9);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 10);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
}
|
||||
catch(Exception e){e.printStackTrace();fail(e.getMessage());}
|
||||
// ten column ColumnInfoRecord starting at index 0
|
||||
nci.setFirstColumn((short) 0);
|
||||
nci.setLastColumn((short) 9);
|
||||
nci.setXFIndex(TEST_IDX);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 0);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 7);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 9);
|
||||
assertEquals(TEST_IDX, xfindex);
|
||||
xfindex = sheet.getXFIndexForColAt((short) 10);
|
||||
assertEquals(DEFAULT_IDX, xfindex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -19,125 +19,18 @@ package org.apache.poi.hssf.model;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.ColumnInfoRecord;
|
||||
import org.apache.poi.hssf.record.MergeCellsRecord;
|
||||
import org.apache.poi.hssf.record.PageBreakRecord;
|
||||
import org.apache.poi.hssf.record.RowRecord;
|
||||
import org.apache.poi.hssf.record.StringRecord;
|
||||
|
||||
/**
|
||||
* @author Tony Poppleton
|
||||
*/
|
||||
public class TestSheetAdditional extends TestCase
|
||||
{
|
||||
/**
|
||||
* Constructor for SheetTest.
|
||||
* @param arg0
|
||||
*/
|
||||
public TestSheetAdditional(String arg0)
|
||||
{
|
||||
super(arg0);
|
||||
}
|
||||
public final class TestSheetAdditional extends TestCase {
|
||||
|
||||
public void testAddMergedRegion()
|
||||
{
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
int regionsToAdd = 4096;
|
||||
int startRecords = sheet.getRecords().size();
|
||||
|
||||
//simple test that adds a load of regions
|
||||
for (int n = 0; n < regionsToAdd; n++)
|
||||
{
|
||||
int index = sheet.addMergedRegion(0, (short) 0, 1, (short) 1);
|
||||
assertTrue("Merged region index expected to be " + n + " got " + index, index == n);
|
||||
}
|
||||
|
||||
//test all the regions were indeed added
|
||||
assertTrue(sheet.getNumMergedRegions() == regionsToAdd);
|
||||
|
||||
//test that the regions were spread out over the appropriate number of records
|
||||
int recordsAdded = sheet.getRecords().size() - startRecords;
|
||||
int recordsExpected = regionsToAdd/1027;
|
||||
if ((regionsToAdd % 1027) != 0)
|
||||
recordsExpected++;
|
||||
assertTrue("The " + regionsToAdd + " merged regions should have been spread out over " + recordsExpected + " records, not " + recordsAdded, recordsAdded == recordsExpected);
|
||||
|
||||
// Check we can't add one with invalud date
|
||||
try {
|
||||
sheet.addMergedRegion(10, (short)10, 9, (short)12);
|
||||
fail();
|
||||
} catch(IllegalArgumentException e) {}
|
||||
try {
|
||||
sheet.addMergedRegion(10, (short)10, 12, (short)9);
|
||||
fail();
|
||||
} catch(IllegalArgumentException e) {}
|
||||
}
|
||||
|
||||
public void testRemoveMergedRegion()
|
||||
{
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
int regionsToAdd = 4096;
|
||||
|
||||
for (int n = 0; n < regionsToAdd; n++)
|
||||
sheet.addMergedRegion(0, (short) 0, 1, (short) 1);
|
||||
|
||||
int records = sheet.getRecords().size();
|
||||
|
||||
//remove a third from the beginning
|
||||
for (int n = 0; n < regionsToAdd/3; n++)
|
||||
{
|
||||
sheet.removeMergedRegion(0);
|
||||
//assert they have been deleted
|
||||
assertTrue("Num of regions should be " + (regionsToAdd - n - 1) + " not " + sheet.getNumMergedRegions(), sheet.getNumMergedRegions() == regionsToAdd - n - 1);
|
||||
}
|
||||
|
||||
//assert any record removing was done
|
||||
int recordsRemoved = (regionsToAdd/3)/1027; //doesn't work for particular values of regionsToAdd
|
||||
assertTrue("Expected " + recordsRemoved + " record to be removed from the starting " + records + ". Currently there are " + sheet.getRecords().size() + " records", records - sheet.getRecords().size() == recordsRemoved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug: 22922 (Reported by Xuemin Guan)
|
||||
* <p>
|
||||
* Remove mergedregion fails when a sheet loses records after an initial CreateSheet
|
||||
* fills up the records.
|
||||
*
|
||||
*/
|
||||
public void testMovingMergedRegion() {
|
||||
List records = new ArrayList();
|
||||
|
||||
MergeCellsRecord merged = new MergeCellsRecord();
|
||||
merged.addArea(0, (short)0, 1, (short)2);
|
||||
records.add(new RowRecord());
|
||||
records.add(new RowRecord());
|
||||
records.add(new RowRecord());
|
||||
records.add(merged);
|
||||
|
||||
Sheet sheet = Sheet.createSheet(records, 0);
|
||||
sheet.records.remove(0);
|
||||
|
||||
//stub object to throw off list INDEX operations
|
||||
sheet.removeMergedRegion(0);
|
||||
assertEquals("Should be no more merged regions", 0, sheet.getNumMergedRegions());
|
||||
}
|
||||
|
||||
public void testGetMergedRegionAt()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void testGetNumMergedRegions()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void DISBALEDtestGetCellWidth() throws Exception
|
||||
{
|
||||
public void testGetCellWidth() {
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
ColumnInfoRecord nci = ( ColumnInfoRecord ) sheet.createColInfo();
|
||||
|
||||
|
@ -146,14 +39,8 @@ public class TestSheetAdditional extends TestCase
|
|||
nci.setLastColumn((short)10);
|
||||
nci.setColumnWidth((short)100);
|
||||
|
||||
Field f = null;
|
||||
f = Sheet.class.getDeclaredField("columnSizes");
|
||||
f.setAccessible(true);
|
||||
List columnSizes = new ArrayList();
|
||||
f.set(sheet,columnSizes);
|
||||
columnSizes.add(nci);
|
||||
sheet.records.add(1 + sheet.dimsloc, nci);
|
||||
sheet.dimsloc++;
|
||||
|
||||
sheet.columns.insertColumn(nci);
|
||||
|
||||
assertEquals((short)100,sheet.getColumnWidth((short)5));
|
||||
assertEquals((short)100,sheet.getColumnWidth((short)6));
|
||||
|
@ -172,151 +59,6 @@ public class TestSheetAdditional extends TestCase
|
|||
assertEquals((short)100,sheet.getColumnWidth((short)10));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure all rows registered for this sheet are aggregated, they were being skipped
|
||||
*
|
||||
*/
|
||||
public void testRowAggregation() {
|
||||
List records = new ArrayList();
|
||||
RowRecord row = new RowRecord();
|
||||
row.setRowNumber(0);
|
||||
records.add(row);
|
||||
|
||||
row = new RowRecord();
|
||||
row.setRowNumber(1);
|
||||
records.add(row);
|
||||
|
||||
records.add(new StringRecord());
|
||||
|
||||
row = new RowRecord();
|
||||
row.setRowNumber(2);
|
||||
records.add(row);
|
||||
|
||||
|
||||
Sheet sheet = Sheet.createSheet(records, 0);
|
||||
assertNotNull("Row [2] was skipped", sheet.getRow(2));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure page break functionality works (in memory)
|
||||
*
|
||||
*/
|
||||
public void testRowPageBreaks(){
|
||||
short colFrom = 0;
|
||||
short colTo = 255;
|
||||
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
sheet.setRowBreak(0, colFrom, colTo);
|
||||
|
||||
assertTrue("no row break at 0", sheet.isRowBroken(0));
|
||||
assertEquals("1 row break available", 1, sheet.getNumRowBreaks());
|
||||
|
||||
sheet.setRowBreak(0, colFrom, colTo);
|
||||
sheet.setRowBreak(0, colFrom, colTo);
|
||||
|
||||
assertTrue("no row break at 0", sheet.isRowBroken(0));
|
||||
assertEquals("1 row break available", 1, sheet.getNumRowBreaks());
|
||||
|
||||
sheet.setRowBreak(10, colFrom, colTo);
|
||||
sheet.setRowBreak(11, colFrom, colTo);
|
||||
|
||||
assertTrue("no row break at 10", sheet.isRowBroken(10));
|
||||
assertTrue("no row break at 11", sheet.isRowBroken(11));
|
||||
assertEquals("3 row break available", 3, sheet.getNumRowBreaks());
|
||||
|
||||
|
||||
boolean is10 = false;
|
||||
boolean is0 = false;
|
||||
boolean is11 = false;
|
||||
|
||||
Iterator iterator = sheet.getRowBreaks();
|
||||
while (iterator.hasNext()) {
|
||||
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
|
||||
int main = (int)breakItem.main;
|
||||
if (main != 0 && main != 10 && main != 11) fail("Invalid page break");
|
||||
if (main == 0) is0 = true;
|
||||
if (main == 10) is10= true;
|
||||
if (main == 11) is11 = true;
|
||||
}
|
||||
|
||||
assertTrue("one of the breaks didnt make it", is0 && is10 && is11);
|
||||
|
||||
sheet.removeRowBreak(11);
|
||||
assertFalse("row should be removed", sheet.isRowBroken(11));
|
||||
|
||||
sheet.removeRowBreak(0);
|
||||
assertFalse("row should be removed", sheet.isRowBroken(0));
|
||||
|
||||
sheet.removeRowBreak(10);
|
||||
assertFalse("row should be removed", sheet.isRowBroken(10));
|
||||
|
||||
assertEquals("no more breaks", 0, sheet.getNumRowBreaks());
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure column pag breaks works properly (in-memory)
|
||||
*
|
||||
*/
|
||||
public void testColPageBreaks(){
|
||||
short rowFrom = 0;
|
||||
short rowTo = (short)65535;
|
||||
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
sheet.setColumnBreak((short)0, rowFrom, rowTo);
|
||||
|
||||
assertTrue("no col break at 0", sheet.isColumnBroken((short)0));
|
||||
assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());
|
||||
|
||||
sheet.setColumnBreak((short)0, rowFrom, rowTo);
|
||||
|
||||
assertTrue("no col break at 0", sheet.isColumnBroken((short)0));
|
||||
assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());
|
||||
|
||||
sheet.setColumnBreak((short)1, rowFrom, rowTo);
|
||||
sheet.setColumnBreak((short)10, rowFrom, rowTo);
|
||||
sheet.setColumnBreak((short)15, rowFrom, rowTo);
|
||||
|
||||
assertTrue("no col break at 1", sheet.isColumnBroken((short)1));
|
||||
assertTrue("no col break at 10", sheet.isColumnBroken((short)10));
|
||||
assertTrue("no col break at 15", sheet.isColumnBroken((short)15));
|
||||
assertEquals("4 col break available", 4, sheet.getNumColumnBreaks());
|
||||
|
||||
boolean is10 = false;
|
||||
boolean is0 = false;
|
||||
boolean is1 = false;
|
||||
boolean is15 = false;
|
||||
|
||||
Iterator iterator = sheet.getColumnBreaks();
|
||||
while (iterator.hasNext()) {
|
||||
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
|
||||
int main = (int)breakItem.main;
|
||||
if (main != 0 && main != 1 && main != 10 && main != 15) fail("Invalid page break");
|
||||
if (main == 0) is0 = true;
|
||||
if (main == 1) is1 = true;
|
||||
if (main == 10) is10= true;
|
||||
if (main == 15) is15 = true;
|
||||
}
|
||||
|
||||
assertTrue("one of the breaks didnt make it", is0 && is1 && is10 && is15);
|
||||
|
||||
sheet.removeColumnBreak((short)15);
|
||||
assertFalse("column break should not be there", sheet.isColumnBroken((short)15));
|
||||
|
||||
sheet.removeColumnBreak((short)0);
|
||||
assertFalse("column break should not be there", sheet.isColumnBroken((short)0));
|
||||
|
||||
sheet.removeColumnBreak((short)1);
|
||||
assertFalse("column break should not be there", sheet.isColumnBroken((short)1));
|
||||
|
||||
sheet.removeColumnBreak((short)10);
|
||||
assertFalse("column break should not be there", sheet.isColumnBroken((short)10));
|
||||
|
||||
assertEquals("no more breaks", 0, sheet.getNumColumnBreaks());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ public final class AllRecordTests {
|
|||
result.addTestSuite(TestFormulaRecord.class);
|
||||
result.addTestSuite(TestFrameRecord.class);
|
||||
result.addTestSuite(TestHyperlinkRecord.class);
|
||||
result.addTestSuite(TestLabelRecord.class);
|
||||
result.addTestSuite(TestLegendRecord.class);
|
||||
result.addTestSuite(TestLineFormatRecord.class);
|
||||
result.addTestSuite(TestLinkedDataRecord.class);
|
||||
|
|
|
@ -38,6 +38,8 @@ public final class TestExternalNameRecord extends TestCase {
|
|||
// data taken from bugzilla 44774 att 21790
|
||||
private static final byte[] dataPlainName = {
|
||||
0, 0, 0, 0, 0, 0, 9, 0, 82, 97, 116, 101, 95, 68, 97, 116, 101, 9, 0, 58, 0, 0, 0, 0, 4, 0, 8, 0
|
||||
// TODO - the last 2 bytes of formula data (8,0) seem weird. They encode to ConcatPtg, UnknownPtg
|
||||
// UnknownPtg is otherwise not created by any other test cases
|
||||
};
|
||||
|
||||
private static ExternalNameRecord createSimpleENR(byte[] data) {
|
||||
|
|
|
@ -19,17 +19,15 @@ package org.apache.poi.hssf.record;
|
|||
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AttrPtg;
|
||||
import org.apache.poi.hssf.record.formula.ConcatPtg;
|
||||
import org.apache.poi.hssf.record.formula.FuncVarPtg;
|
||||
import org.apache.poi.hssf.record.formula.IntPtg;
|
||||
import org.apache.poi.hssf.record.formula.RangePtg;
|
||||
import org.apache.poi.hssf.record.formula.ReferencePtg;
|
||||
import org.apache.poi.hssf.record.formula.UnknownPtg;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AttrPtg;
|
||||
import org.apache.poi.hssf.record.formula.FuncVarPtg;
|
||||
import org.apache.poi.hssf.record.formula.IntPtg;
|
||||
import org.apache.poi.hssf.record.formula.ReferencePtg;
|
||||
|
||||
/**
|
||||
* Tests the serialization and deserialization of the FormulaRecord
|
||||
* class works correctly.
|
||||
|
@ -57,7 +55,7 @@ public final class TestFormulaRecord extends TestCase {
|
|||
*/
|
||||
public void testCheckNanPreserve() {
|
||||
byte[] formulaByte = new byte[29];
|
||||
for (int i = 0; i < formulaByte.length; i++) formulaByte[i] = (byte)0;
|
||||
|
||||
formulaByte[4] = (byte)0x0F;
|
||||
formulaByte[6] = (byte)0x02;
|
||||
formulaByte[8] = (byte)0x07;
|
||||
|
@ -91,8 +89,6 @@ public final class TestFormulaRecord extends TestCase {
|
|||
public void testExpFormula() {
|
||||
byte[] formulaByte = new byte[27];
|
||||
|
||||
for (int i = 0; i < formulaByte.length; i++) formulaByte[i] = (byte)0;
|
||||
|
||||
formulaByte[4] =(byte)0x0F;
|
||||
formulaByte[14]=(byte)0x08;
|
||||
formulaByte[18]=(byte)0xE0;
|
||||
|
@ -109,15 +105,14 @@ public final class TestFormulaRecord extends TestCase {
|
|||
|
||||
public void testWithConcat() throws Exception {
|
||||
// =CHOOSE(2,A2,A3,A4)
|
||||
byte[] data = new byte[] {
|
||||
byte[] data = {
|
||||
6, 0, 68, 0,
|
||||
1, 0, 1, 0, 15, 0, 0, 0, 0, 0, 0, 0, 57,
|
||||
64, 0, 0, 12, 0, 12, -4, 46, 0,
|
||||
30, 2, 0, // Int - 2
|
||||
25, 4, 3, 0, // Attr
|
||||
8, 0, // Concat
|
||||
17, 0, // Range
|
||||
26, 0, 35, 0, // Bit like an attr
|
||||
8, 0, 17, 0, 26, 0, // jumpTable
|
||||
35, 0, // chooseOffset
|
||||
36, 1, 0, 0, -64, // Ref - A2
|
||||
25, 8, 21, 0, // Attr
|
||||
36, 2, 0, 0, -64, // Ref - A3
|
||||
|
@ -126,30 +121,24 @@ public final class TestFormulaRecord extends TestCase {
|
|||
25, 8, 3, 0, // Attr
|
||||
66, 4, 100, 0 // CHOOSE
|
||||
};
|
||||
RecordInputStream inp = new RecordInputStream(
|
||||
new ByteArrayInputStream(data)
|
||||
);
|
||||
RecordInputStream inp = new RecordInputStream( new ByteArrayInputStream(data));
|
||||
inp.nextRecord();
|
||||
|
||||
FormulaRecord fr = new FormulaRecord(inp);
|
||||
|
||||
assertEquals(14, fr.getNumberOfExpressionTokens());
|
||||
assertEquals(IntPtg.class, fr.getParsedExpression().get(0).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(1).getClass());
|
||||
assertEquals(ConcatPtg.class, fr.getParsedExpression().get(2).getClass());
|
||||
assertEquals(UnknownPtg.class, fr.getParsedExpression().get(3).getClass());
|
||||
assertEquals(RangePtg.class, fr.getParsedExpression().get(4).getClass());
|
||||
assertEquals(UnknownPtg.class, fr.getParsedExpression().get(5).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(6).getClass());
|
||||
assertEquals(ReferencePtg.class, fr.getParsedExpression().get(7).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(8).getClass());
|
||||
assertEquals(ReferencePtg.class, fr.getParsedExpression().get(9).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(10).getClass());
|
||||
assertEquals(ReferencePtg.class, fr.getParsedExpression().get(11).getClass());
|
||||
assertEquals(AttrPtg.class, fr.getParsedExpression().get(12).getClass());
|
||||
assertEquals(FuncVarPtg.class, fr.getParsedExpression().get(13).getClass());
|
||||
List ptgs = fr.getParsedExpression();
|
||||
assertEquals(9, ptgs.size());
|
||||
assertEquals(IntPtg.class, ptgs.get(0).getClass());
|
||||
assertEquals(AttrPtg.class, ptgs.get(1).getClass());
|
||||
assertEquals(ReferencePtg.class, ptgs.get(2).getClass());
|
||||
assertEquals(AttrPtg.class, ptgs.get(3).getClass());
|
||||
assertEquals(ReferencePtg.class, ptgs.get(4).getClass());
|
||||
assertEquals(AttrPtg.class, ptgs.get(5).getClass());
|
||||
assertEquals(ReferencePtg.class, ptgs.get(6).getClass());
|
||||
assertEquals(AttrPtg.class, ptgs.get(7).getClass());
|
||||
assertEquals(FuncVarPtg.class, ptgs.get(8).getClass());
|
||||
|
||||
FuncVarPtg choose = (FuncVarPtg)fr.getParsedExpression().get(13);
|
||||
FuncVarPtg choose = (FuncVarPtg)ptgs.get(8);
|
||||
assertEquals("CHOOSE", choose.getName());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* ====================================================================
|
||||
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.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
/**
|
||||
* Tests for <tt>LabelRecord</tt>
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class TestLabelRecord extends TestCase {
|
||||
|
||||
public void testEmptyString() {
|
||||
HSSFWorkbook wb;
|
||||
try {
|
||||
wb = HSSFTestDataSamples.openSampleWorkbook("ex42570-20305.xls");
|
||||
} catch (NullPointerException e) {
|
||||
throw new AssertionFailedError("Identified bug 42570");
|
||||
}
|
||||
HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -15,34 +14,28 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.aggregates;
|
||||
|
||||
import org.apache.poi.hssf.record.*;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class TestRowRecordsAggregate extends junit.framework.TestCase {
|
||||
public TestRowRecordsAggregate(String name) {
|
||||
super (name);
|
||||
}
|
||||
import org.apache.poi.hssf.record.RowRecord;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final class TestRowRecordsAggregate extends TestCase {
|
||||
|
||||
public void testRowGet() {
|
||||
RowRecordsAggregate rra = new RowRecordsAggregate();
|
||||
RowRecord rr = new RowRecord();
|
||||
rr.setRowNumber(( short ) 4);
|
||||
RowRecord rr = new RowRecord(4);
|
||||
rra.insertRow(rr);
|
||||
RowRecord rr2 = new RowRecord(); rr2.setRowNumber((short) 1);
|
||||
rra.insertRow(rr2);
|
||||
rra.insertRow(new RowRecord(1));
|
||||
|
||||
RowRecord rr1 = rra.getRow(4);
|
||||
|
||||
assertTrue("Row Record should not be null", rr1!=null);
|
||||
assertTrue("Row number is 1",rr1.getRowNumber() == 4);
|
||||
assertNotNull(rr1);
|
||||
assertEquals("Row number is 1", 4, rr1.getRowNumber());
|
||||
assertTrue("Row record retrieved is identical ", rr1 == rr);
|
||||
}
|
||||
|
||||
public static void main(String [] args) {
|
||||
System.out
|
||||
.println("Testing org.apache.poi.hssf.record.aggregates.RowRecordAggregate");
|
||||
junit.textui.TestRunner.run(TestRowRecordsAggregate.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public final class AllFormulaTests {
|
|||
result.addTestSuite(TestArea3DPtg.class);
|
||||
result.addTestSuite(TestAreaErrPtg.class);
|
||||
result.addTestSuite(TestAreaPtg.class);
|
||||
result.addTestSuite(TestArrayPtg.class);
|
||||
result.addTestSuite(TestErrPtg.class);
|
||||
result.addTestSuite(TestExternalFunctionFormulas.class);
|
||||
result.addTestSuite(TestFuncPtg.class);
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* ====================================================================
|
||||
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.formula;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
|
||||
import org.apache.poi.hssf.record.UnicodeString;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
/**
|
||||
* Tests for <tt>ArrayPtg</tt>
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class TestArrayPtg extends TestCase {
|
||||
|
||||
private static final byte[] ENCODED_PTG_DATA = {
|
||||
0x40, 0x00,
|
||||
0x08, 0x00,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
private static final byte[] ENCODED_CONSTANT_DATA = {
|
||||
2, // 3 columns
|
||||
1, 0, // 2 rows
|
||||
4, 1, 0, 0, 0, 0, 0, 0, 0, // TRUE
|
||||
2, 4, 0, 0, 65, 66, 67, 68, // "ABCD"
|
||||
2, 1, 0, 0, 69, // "E"
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, // 0
|
||||
4, 0, 0, 0, 0, 0, 0, 0, 0, // FALSE
|
||||
2, 2, 0, 0, 70, 71, // "FG"
|
||||
};
|
||||
|
||||
/**
|
||||
* Lots of problems with ArrayPtg's encoding of
|
||||
*/
|
||||
public void testReadWriteTokenValueBytes() {
|
||||
|
||||
ArrayPtg ptg = new ArrayPtgV(new TestcaseRecordInputStream(ArrayPtgV.sid, ENCODED_PTG_DATA));
|
||||
|
||||
ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
|
||||
assertEquals(3, ptg.getColumnCount());
|
||||
assertEquals(2, ptg.getRowCount());
|
||||
Object[] values = ptg.token_3_arrayValues;
|
||||
assertEquals(6, values.length);
|
||||
|
||||
|
||||
assertEquals(Boolean.TRUE, values[0]);
|
||||
assertEquals(new UnicodeString("ABCD"), values[1]);
|
||||
assertEquals(new Double(0), values[3]);
|
||||
assertEquals(Boolean.FALSE, values[4]);
|
||||
assertEquals(new UnicodeString("FG"), values[5]);
|
||||
|
||||
byte[] outBuf = new byte[ENCODED_CONSTANT_DATA.length];
|
||||
ptg.writeTokenValueBytes(outBuf, 0);
|
||||
|
||||
if(outBuf[0] == 4) {
|
||||
throw new AssertionFailedError("Identified bug 42564b");
|
||||
}
|
||||
assertTrue(Arrays.equals(ENCODED_CONSTANT_DATA, outBuf));
|
||||
}
|
||||
|
||||
/**
|
||||
* make sure constant elements are stored row by row
|
||||
*/
|
||||
public void testElementOrdering() {
|
||||
ArrayPtg ptg = new ArrayPtgV(new TestcaseRecordInputStream(ArrayPtgV.sid, ENCODED_PTG_DATA));
|
||||
ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
|
||||
assertEquals(3, ptg.getColumnCount());
|
||||
assertEquals(2, ptg.getRowCount());
|
||||
|
||||
assertEquals(0, ptg.getValueIndex(0, 0));
|
||||
assertEquals(1, ptg.getValueIndex(1, 0));
|
||||
assertEquals(2, ptg.getValueIndex(2, 0));
|
||||
assertEquals(3, ptg.getValueIndex(0, 1));
|
||||
assertEquals(4, ptg.getValueIndex(1, 1));
|
||||
assertEquals(5, ptg.getValueIndex(2, 1));
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -26,45 +25,31 @@ import org.apache.poi.hssf.record.TestcaseRecordInputStream;
|
|||
*
|
||||
* @author Danny Mui (dmui at apache dot org)
|
||||
*/
|
||||
public final class TestFuncPtg extends TestCase {
|
||||
|
||||
public class TestFuncPtg extends TestCase
|
||||
{
|
||||
|
||||
public TestFuncPtg( String name )
|
||||
{
|
||||
super( name );
|
||||
}
|
||||
|
||||
|
||||
public static void main( java.lang.String[] args )
|
||||
{
|
||||
junit.textui.TestRunner.run( TestFuncPtg.class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the left overs are re-serialized on excel file reads to avoid
|
||||
* the "Warning: Data may have been lost" prompt in excel.
|
||||
* <p/>
|
||||
* This ptg represents a LEN function extracted from excel
|
||||
*/
|
||||
|
||||
public void testLeftOvers()
|
||||
{
|
||||
byte[] fakeData = new byte[4];
|
||||
|
||||
//fakeData[0] = (byte) 0x41;
|
||||
fakeData[0] = (byte) 0x20; //function index
|
||||
fakeData[1] = (byte) 0;
|
||||
fakeData[2] = (byte) 8;
|
||||
public void testRead() {
|
||||
// This ptg represents a LEN function extracted from excel
|
||||
byte[] fakeData = {
|
||||
0x20, //function index
|
||||
0,
|
||||
};
|
||||
|
||||
FuncPtg ptg = new FuncPtg( new TestcaseRecordInputStream((short)0, (short)fakeData.length, fakeData) );
|
||||
assertEquals( "Len formula index is not 32(20H)", (int) 0x20, ptg.getFunctionIndex() );
|
||||
assertEquals( "Len formula index is not 32(20H)", 0x20, ptg.getFunctionIndex() );
|
||||
assertEquals( "Number of operands in the len formula", 1, ptg.getNumberOfOperands() );
|
||||
assertEquals( "Function Name", "LEN", ptg.getName() );
|
||||
assertEquals( "Ptg Size", 3, ptg.getSize() );
|
||||
//assertEquals("first leftover byte is not 0", (byte)0, ptg.leftOvers[0]);
|
||||
//assertEquals("second leftover byte is not 8", (byte)8, ptg.leftOvers[1]);
|
||||
}
|
||||
|
||||
public void testClone() {
|
||||
FuncPtg funcPtg = new FuncPtg(27); // ROUND() - takes 2 args
|
||||
|
||||
FuncPtg clone = (FuncPtg) funcPtg.clone();
|
||||
if (clone.getNumberOfOperands() == 0) {
|
||||
fail("clone() did copy field numberOfOperands");
|
||||
}
|
||||
assertEquals(2, clone.getNumberOfOperands());
|
||||
assertEquals("ROUND", clone.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@ import junit.framework.TestSuite;
|
|||
public class AllFormulaEvalTests {
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.record.formula.eval");
|
||||
TestSuite result = new TestSuite(AllFormulaEvalTests.class.getName());
|
||||
result.addTestSuite(TestAreaEval.class);
|
||||
result.addTestSuite(TestCircularReferences.class);
|
||||
result.addTestSuite(TestExternalFunction.class);
|
||||
result.addTestSuite(TestFormulaBugs.class);
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* ====================================================================
|
||||
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.formula.eval;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.Area3DPtg;
|
||||
|
||||
/**
|
||||
* Tests for <tt>AreaEval</tt>
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class TestAreaEval extends TestCase {
|
||||
|
||||
public void testGetValue_bug44950() {
|
||||
|
||||
Area3DPtg ptg = new Area3DPtg("B2:D3", (short)0);
|
||||
NumberEval one = new NumberEval(1);
|
||||
ValueEval[] values = {
|
||||
one,
|
||||
new NumberEval(2),
|
||||
new NumberEval(3),
|
||||
new NumberEval(4),
|
||||
new NumberEval(5),
|
||||
new NumberEval(6),
|
||||
};
|
||||
AreaEval ae = new Area3DEval(ptg, values);
|
||||
if (one == ae.getValueAt(1, 2)) {
|
||||
throw new AssertionFailedError("Identified bug 44950 a");
|
||||
}
|
||||
confirm(1, ae, 1, 1);
|
||||
confirm(2, ae, 1, 2);
|
||||
confirm(3, ae, 1, 3);
|
||||
confirm(4, ae, 2, 1);
|
||||
confirm(5, ae, 2, 2);
|
||||
confirm(6, ae, 2, 3);
|
||||
|
||||
}
|
||||
|
||||
private static void confirm(int expectedValue, AreaEval ae, int row, int col) {
|
||||
NumberEval v = (NumberEval) ae.getValueAt(row, col);
|
||||
assertEquals(expectedValue, v.getNumberValue(), 0.0);
|
||||
}
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
@ -60,7 +61,32 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
|||
|
||||
private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt";
|
||||
|
||||
/**
|
||||
* For simplicity, the output file is strictly simple ASCII.
|
||||
* This method detects any unexpected characters.
|
||||
*/
|
||||
/* package */ static boolean isSimpleAscii(char c) {
|
||||
|
||||
if (c>=0x21 && c<=0x7E) {
|
||||
// everything from '!' to '~' (includes letters, digits, punctuation
|
||||
return true;
|
||||
}
|
||||
// some specific whitespace chars below 0x21:
|
||||
switch(c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static final class FunctionData {
|
||||
// special characters from the ooo document
|
||||
private static final int CHAR_ELLIPSIS_8230 = 8230;
|
||||
private static final int CHAR_NDASH_8211 = 8211;
|
||||
|
||||
private final int _index;
|
||||
private final boolean _hasFootnote;
|
||||
|
@ -78,10 +104,30 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
|||
_name = funcName;
|
||||
_minParams = minParams;
|
||||
_maxParams = maxParams;
|
||||
_returnClass = returnClass;
|
||||
_paramClasses = paramClasses;
|
||||
_returnClass = convertSpecialChars(returnClass);
|
||||
_paramClasses = convertSpecialChars(paramClasses);
|
||||
_isVolatile = isVolatile;
|
||||
}
|
||||
private static String convertSpecialChars(String ss) {
|
||||
StringBuffer sb = new StringBuffer(ss.length() + 4);
|
||||
for(int i=0; i<ss.length(); i++) {
|
||||
char c = ss.charAt(i);
|
||||
if (isSimpleAscii(c)) {
|
||||
sb.append(c);
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case CHAR_NDASH_8211:
|
||||
sb.append('-');
|
||||
continue;
|
||||
case CHAR_ELLIPSIS_8230:
|
||||
sb.append("...");
|
||||
continue;
|
||||
}
|
||||
throw new RuntimeException("bad char (" + ((int)c) + ") in string '" + ss + "'");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
public int getIndex() {
|
||||
return _index;
|
||||
}
|
||||
|
@ -354,13 +400,19 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
|||
}
|
||||
|
||||
private static void extractFunctionData(FunctionDataCollector fdc, InputStream is) {
|
||||
System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
|
||||
|
||||
XMLReader xr;
|
||||
|
||||
try {
|
||||
// First up, try the default one
|
||||
xr = XMLReaderFactory.createXMLReader();
|
||||
} catch (SAXException e) {
|
||||
throw new RuntimeException(e);
|
||||
// Try one for java 1.4
|
||||
System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
|
||||
try {
|
||||
xr = XMLReaderFactory.createXMLReader();
|
||||
} catch (SAXException e2) {
|
||||
throw new RuntimeException(e2);
|
||||
}
|
||||
}
|
||||
xr.setContentHandler(new EFFDocHandler(fdc));
|
||||
|
||||
|
@ -375,6 +427,33 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* To be sure that no tricky unicode chars make it through to the output file.
|
||||
*/
|
||||
private static final class SimpleAsciiOutputStream extends OutputStream {
|
||||
|
||||
private final OutputStream _os;
|
||||
|
||||
public SimpleAsciiOutputStream(OutputStream os) {
|
||||
_os = os;
|
||||
}
|
||||
public void write(int b) throws IOException {
|
||||
checkByte(b);
|
||||
_os.write(b);
|
||||
}
|
||||
private static void checkByte(int b) {
|
||||
if (!isSimpleAscii((char)b)) {
|
||||
throw new RuntimeException("Encountered char (" + b + ") which was not simple ascii as expected");
|
||||
}
|
||||
}
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
for (int i = 0; i < len; i++) {
|
||||
checkByte(b[i + off]);
|
||||
|
||||
}
|
||||
_os.write(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
private static void processFile(File effDocFile, File outFile) {
|
||||
OutputStream os;
|
||||
|
@ -383,7 +462,14 @@ public final class ExcelFileFormatDocFunctionExtractor {
|
|||
} catch (FileNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
PrintStream ps = new PrintStream(os);
|
||||
os = new SimpleAsciiOutputStream(os);
|
||||
PrintStream ps;
|
||||
try {
|
||||
ps = new PrintStream(os, true, "UTF-8");
|
||||
} catch(UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
outputLicenseHeader(ps);
|
||||
Class genClass = ExcelFileFormatDocFunctionExtractor.class;
|
||||
ps.println("# Created by (" + genClass.getName() + ")");
|
||||
|
|
|
@ -67,7 +67,7 @@ public final class TestCountFuncs extends TestCase {
|
|||
args = new Eval[] {
|
||||
EvalFactory.createAreaEval("D1:F5", 3, 5), // 15
|
||||
EvalFactory.createRefEval("A1"),
|
||||
EvalFactory.createAreaEval("A1:F6", 7, 6), // 42
|
||||
EvalFactory.createAreaEval("A1:G6", 7, 6), // 42
|
||||
new NumberEval(0),
|
||||
};
|
||||
confirmCountA(59, args);
|
||||
|
@ -87,7 +87,7 @@ public final class TestCountFuncs extends TestCase {
|
|||
BoolEval.TRUE,
|
||||
BlankEval.INSTANCE,
|
||||
};
|
||||
range = createAreaEval("A1:B2", values);
|
||||
range = createAreaEval("A1:B3", values);
|
||||
confirmCountIf(2, range, BoolEval.TRUE);
|
||||
|
||||
// when criteria is numeric
|
||||
|
@ -98,9 +98,8 @@ public final class TestCountFuncs extends TestCase {
|
|||
new NumberEval(2),
|
||||
new NumberEval(2),
|
||||
BoolEval.TRUE,
|
||||
BlankEval.INSTANCE,
|
||||
};
|
||||
range = createAreaEval("A1:B2", values);
|
||||
range = createAreaEval("A1:B3", values);
|
||||
confirmCountIf(3, range, new NumberEval(2));
|
||||
// note - same results when criteria is a string that parses as the number with the same value
|
||||
confirmCountIf(3, range, new StringEval("2.00"));
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record.formula.functions;
|
||||
|
||||
|
@ -33,10 +32,6 @@ import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
|||
*/
|
||||
public final class TestIndex extends TestCase {
|
||||
|
||||
public TestIndex(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
private static final double[] TEST_VALUES0 = {
|
||||
1, 2,
|
||||
3, 4,
|
||||
|
@ -44,7 +39,6 @@ public final class TestIndex extends TestCase {
|
|||
7, 8,
|
||||
9, 10,
|
||||
11, 12,
|
||||
13, // excess array element. TODO - Area2DEval currently has no validation to ensure correct size of values array
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,10 +38,12 @@ public class AllUserModelTests {
|
|||
result.addTestSuite(TestEscherGraphics2d.class);
|
||||
result.addTestSuite(TestFontDetails.class);
|
||||
result.addTestSuite(TestFormulas.class);
|
||||
result.addTestSuite(TestFormulaEvaluatorBugs.class);
|
||||
result.addTestSuite(TestFormulaEvaluatorDocs.class);
|
||||
result.addTestSuite(TestHSSFCell.class);
|
||||
result.addTestSuite(TestHSSFClientAnchor.class);
|
||||
result.addTestSuite(TestHSSFConditionalFormatting.class);
|
||||
result.addTestSuite(TestHSSFComment.class);
|
||||
result.addTestSuite(TestHSSFConditionalFormatting.class);
|
||||
result.addTestSuite(TestHSSFDateUtil.class);
|
||||
result.addTestSuite(TestHSSFHeaderFooter.class);
|
||||
result.addTestSuite(TestHSSFHyperlink.class);
|
||||
|
@ -54,17 +56,19 @@ public class AllUserModelTests {
|
|||
result.addTestSuite(TestHSSFSheet.class);
|
||||
result.addTestSuite(TestHSSFSheetOrder.class);
|
||||
result.addTestSuite(TestHSSFSheetSetOrder.class);
|
||||
result.addTestSuite(TestHSSFTextbox.class);
|
||||
result.addTestSuite(TestHSSFWorkbook.class);
|
||||
result.addTestSuite(TestNamedRange.class);
|
||||
result.addTestSuite(TestOLE2Embeding.class);
|
||||
result.addTestSuite(TestPOIFSProperties.class);
|
||||
result.addTestSuite(TestReadWriteChart.class);
|
||||
result.addTestSuite(TestSanityChecker.class);
|
||||
result.addTestSuite(TestSheetHiding.class);
|
||||
result.addTestSuite(TestSheetShiftRows.class);
|
||||
if (false) { // deliberately avoiding this one
|
||||
result.addTestSuite(TestUnfixedBugs.class);
|
||||
}
|
||||
result.addTestSuite(TestUnicodeWorkbook.class);
|
||||
result.addTestSuite(TestUnfixedBugs.class);
|
||||
}
|
||||
result.addTestSuite(TestUnicodeWorkbook.class);
|
||||
result.addTestSuite(TestUppercaseWorkbook.class);
|
||||
result.addTestSuite(TestWorkbook.class);
|
||||
|
||||
|
|
|
@ -17,17 +17,18 @@
|
|||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.hssf.util.Region;
|
||||
import org.apache.poi.util.TempFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Testcases for bugs entered in bugzilla
|
||||
* the Test name contains the bugzilla bug id
|
||||
|
@ -80,13 +81,7 @@ public final class TestBugs extends TestCase {
|
|||
HSSFRow r = s.createRow(0);
|
||||
HSSFCell c = r.createCell((short)0);
|
||||
c.setCellValue(10);
|
||||
try {
|
||||
writeOutAndReadBack(wb);
|
||||
} catch (RecordFormatException e) {
|
||||
if (false) { // TODO (Apr-2008) this file does not read back ok. create bugzilla bug & fix.
|
||||
throw new AssertionFailedError("Identified bug XXXX");
|
||||
}
|
||||
}
|
||||
writeOutAndReadBack(wb);
|
||||
}
|
||||
/**Test writing a hyperlink
|
||||
* Open resulting sheet in Excel and check that A1 contains a hyperlink*/
|
||||
|
@ -732,7 +727,7 @@ public final class TestBugs extends TestCase {
|
|||
* with the NameRecord, once you get past the BOFRecord
|
||||
* issue.
|
||||
*/
|
||||
public void DISABLEDtest42564Alt() {
|
||||
public void test42564Alt() {
|
||||
HSSFWorkbook wb = openSample("42564-2.xls");
|
||||
writeOutAndReadBack(wb);
|
||||
}
|
||||
|
@ -757,9 +752,13 @@ public final class TestBugs extends TestCase {
|
|||
HSSFCell c2 = r2.getCell((short)1);
|
||||
assertEquals(25, (int)c2.getNumericCellValue());
|
||||
|
||||
if (false) { // TODO (Apr-2008) This will blow up with IllegalStateException (stack underflow)
|
||||
// excel function "CHOOSE" probably needs some special handling in FormulaParser.toFormulaString()
|
||||
assertEquals("=CHOOSE(2,A2,A3,A4)", c2.getCellFormula());
|
||||
try {
|
||||
assertEquals("CHOOSE(2,A2,A3,A4)", c2.getCellFormula());
|
||||
} catch (IllegalStateException e) {
|
||||
if (e.getMessage().startsWith("Too few arguments")
|
||||
&& e.getMessage().indexOf("ConcatPtg") > 0) {
|
||||
throw new AssertionFailedError("identified bug 44306");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -887,13 +886,66 @@ public final class TestBugs extends TestCase {
|
|||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Had a problem apparently, not sure what as it
|
||||
* works just fine...
|
||||
*/
|
||||
public void test44891() throws Exception {
|
||||
HSSFWorkbook wb = openSample("44891.xls");
|
||||
HSSFWorkbook wb = openSample("44891.xls");
|
||||
assertTrue("no errors reading sample xls", true);
|
||||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug 44235: Ms Excel can't open save as excel file
|
||||
*
|
||||
* Works fine with poi-3.1-beta1.
|
||||
*/
|
||||
public void test44235() throws Exception {
|
||||
HSSFWorkbook wb = openSample("44235.xls");
|
||||
assertTrue("no errors reading sample xls", true);
|
||||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug 21334: "File error: data may have been lost" with a file
|
||||
* that contains macros and this formula:
|
||||
* {=SUM(IF(FREQUENCY(IF(LEN(V4:V220)>0,MATCH(V4:V220,V4:V220,0),""),IF(LEN(V4:V220)>0,MATCH(V4:V220,V4:V220,0),""))>0,1))}
|
||||
*/
|
||||
public void test21334() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet sh = wb.createSheet();
|
||||
HSSFCell cell = sh.createRow(0).createCell((short)0);
|
||||
String formula = "SUM(IF(FREQUENCY(IF(LEN(V4:V220)>0,MATCH(V4:V220,V4:V220,0),\"\"),IF(LEN(V4:V220)>0,MATCH(V4:V220,V4:V220,0),\"\"))>0,1))";
|
||||
cell.setCellFormula(formula);
|
||||
|
||||
HSSFWorkbook wb_sv = writeOutAndReadBack(wb);
|
||||
HSSFCell cell_sv = wb_sv.getSheetAt(0).getRow(0).getCell((short)0);
|
||||
assertEquals(formula, cell_sv.getCellFormula());
|
||||
}
|
||||
|
||||
public void test36947() throws Exception {
|
||||
HSSFWorkbook wb = openSample("36947.xls");
|
||||
assertTrue("no errors reading sample xls", true);
|
||||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug 42448: Can't parse SUMPRODUCT(A!C7:A!C67, B8:B68) / B69
|
||||
*/
|
||||
public void test42448(){
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFCell cell = wb.createSheet().createRow(0).createCell((short)0);
|
||||
cell.setCellFormula("SUMPRODUCT(A!C7:A!C67, B8:B68) / B69");
|
||||
assertTrue("no errors parsing formula", true);
|
||||
}
|
||||
|
||||
public void test39634() throws Exception {
|
||||
HSSFWorkbook wb = openSample("39634.xls");
|
||||
assertTrue("no errors reading sample xls", true);
|
||||
writeOutAndReadBack(wb);
|
||||
assertTrue("no errors writing sample xls", true);
|
||||
|
|
|
@ -22,12 +22,14 @@ import java.io.FileOutputStream;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||
import org.apache.poi.hssf.record.formula.AreaPtg;
|
||||
import org.apache.poi.hssf.record.formula.FuncVarPtg;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -51,42 +53,41 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||
*/
|
||||
public void test44636() throws Exception {
|
||||
// Open the existing file, tweak one value and
|
||||
// re-calculate
|
||||
// re-calculate
|
||||
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44636.xls");
|
||||
HSSFSheet sheet = wb.getSheetAt (0);
|
||||
HSSFRow row = sheet.getRow (0);
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
HSSFRow row = sheet.getRow(0);
|
||||
|
||||
row.getCell((short)0).setCellValue(4.2);
|
||||
row.getCell((short)2).setCellValue(25);
|
||||
row.getCell((short) 0).setCellValue(4.2);
|
||||
row.getCell((short) 2).setCellValue(25);
|
||||
|
||||
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
||||
assertEquals(4.2*25, row.getCell((short)3).getNumericCellValue(), 0.0001);
|
||||
assertEquals(4.2 * 25, row.getCell((short) 3).getNumericCellValue(), 0.0001);
|
||||
|
||||
// Save
|
||||
File existing = new File(tmpDirName,"44636-existing.xls");
|
||||
File existing = new File(tmpDirName, "44636-existing.xls");
|
||||
FileOutputStream out = new FileOutputStream(existing);
|
||||
wb.write(out);
|
||||
out.close();
|
||||
System.err.println("Existing file for bug #44636 written to " + existing.toString());
|
||||
|
||||
|
||||
// Now, do a new file from scratch
|
||||
wb = new HSSFWorkbook();
|
||||
sheet = wb.createSheet();
|
||||
|
||||
row = sheet.createRow(0);
|
||||
row.createCell((short)0).setCellValue(1.2);
|
||||
row.createCell((short)1).setCellValue(4.2);
|
||||
row.createCell((short) 0).setCellValue(1.2);
|
||||
row.createCell((short) 1).setCellValue(4.2);
|
||||
|
||||
row = sheet.createRow(1);
|
||||
row.createCell((short)0).setCellFormula("SUM(A1:B1)");
|
||||
row.createCell((short) 0).setCellFormula("SUM(A1:B1)");
|
||||
|
||||
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
||||
assertEquals(5.4, row.getCell((short)0).getNumericCellValue(), 0.0001);
|
||||
assertEquals(5.4, row.getCell((short) 0).getNumericCellValue(), 0.0001);
|
||||
|
||||
// Save
|
||||
File scratch = new File(tmpDirName,"44636-scratch.xls");
|
||||
File scratch = new File(tmpDirName, "44636-scratch.xls");
|
||||
out = new FileOutputStream(scratch);
|
||||
wb.write(out);
|
||||
out.close();
|
||||
|
@ -105,62 +106,62 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44297.xls");
|
||||
|
||||
HSSFRow row;
|
||||
HSSFCell cell;
|
||||
HSSFCell cell;
|
||||
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
|
||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(sheet, wb);
|
||||
|
||||
row = sheet.getRow(0);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("31+46", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(77, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
||||
row = sheet.getRow(1);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("30+53", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(83, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
||||
row = sheet.getRow(2);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("SUM(A1:A2)", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(160, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
||||
row = sheet.getRow(4);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("32767+32768", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(65535, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
||||
row = sheet.getRow(7);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("32744+42333", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(75077, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
||||
row = sheet.getRow(8);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("327680.0/32768", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(10, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
||||
row = sheet.getRow(9);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("32767+32769", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(65536, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
||||
row = sheet.getRow(10);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("35000+36000", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(71000, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
||||
row = sheet.getRow(11);
|
||||
cell = row.getCell((short)0);
|
||||
cell = row.getCell((short) 0);
|
||||
assertEquals("-1000000.0-3000000.0", cell.getCellFormula());
|
||||
eva.setCurrentRow(row);
|
||||
assertEquals(-4000000, eva.evaluate(cell).getNumberValue(), 0);
|
||||
|
@ -176,30 +177,29 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SingleLetterRanges.xls");
|
||||
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
|
||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(sheet, wb);
|
||||
|
||||
// =index(C:C,2,1) -> 2
|
||||
// =index(C:C,2,1) -> 2
|
||||
HSSFRow rowIDX = sheet.getRow(3);
|
||||
// =sum(C:C) -> 6
|
||||
// =sum(C:C) -> 6
|
||||
HSSFRow rowSUM = sheet.getRow(4);
|
||||
// =sum(C:D) -> 66
|
||||
// =sum(C:D) -> 66
|
||||
HSSFRow rowSUM2D = sheet.getRow(5);
|
||||
|
||||
// Test the sum
|
||||
HSSFCell cellSUM = rowSUM.getCell((short)0);
|
||||
HSSFCell cellSUM = rowSUM.getCell((short) 0);
|
||||
|
||||
FormulaRecordAggregate frec =
|
||||
(FormulaRecordAggregate)cellSUM.getCellValueRecord();
|
||||
FormulaRecordAggregate frec = (FormulaRecordAggregate) cellSUM.getCellValueRecord();
|
||||
List ops = frec.getFormulaRecord().getParsedExpression();
|
||||
assertEquals(2, ops.size());
|
||||
assertEquals(AreaPtg.class, ops.get(0).getClass());
|
||||
assertEquals(FuncVarPtg.class, ops.get(1).getClass());
|
||||
|
||||
// Actually stored as C1 to C65536
|
||||
// (last row is -1 === 65535)
|
||||
AreaPtg ptg = (AreaPtg)ops.get(0);
|
||||
// Actually stored as C1 to C65536
|
||||
// (last row is -1 === 65535)
|
||||
AreaPtg ptg = (AreaPtg) ops.get(0);
|
||||
assertEquals(2, ptg.getFirstColumn());
|
||||
assertEquals(2, ptg.getLastColumn());
|
||||
assertEquals(0, ptg.getFirstRow());
|
||||
|
@ -207,26 +207,25 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||
assertEquals("C:C", ptg.toFormulaString(wb));
|
||||
|
||||
// Will show as C:C, but won't know how many
|
||||
// rows it covers as we don't have the sheet
|
||||
// to hand when turning the Ptgs into a string
|
||||
// rows it covers as we don't have the sheet
|
||||
// to hand when turning the Ptgs into a string
|
||||
assertEquals("SUM(C:C)", cellSUM.getCellFormula());
|
||||
eva.setCurrentRow(rowSUM);
|
||||
|
||||
// But the evaluator knows the sheet, so it
|
||||
// can do it properly
|
||||
// can do it properly
|
||||
assertEquals(6, eva.evaluate(cellSUM).getNumberValue(), 0);
|
||||
|
||||
|
||||
// Test the index
|
||||
// Again, the formula string will be right but
|
||||
// lacking row count, evaluated will be right
|
||||
HSSFCell cellIDX = rowIDX.getCell((short)0);
|
||||
// lacking row count, evaluated will be right
|
||||
HSSFCell cellIDX = rowIDX.getCell((short) 0);
|
||||
assertEquals("INDEX(C:C,2,1)", cellIDX.getCellFormula());
|
||||
eva.setCurrentRow(rowIDX);
|
||||
assertEquals(2, eva.evaluate(cellIDX).getNumberValue(), 0);
|
||||
|
||||
// Across two colums
|
||||
HSSFCell cellSUM2D = rowSUM2D.getCell((short)0);
|
||||
HSSFCell cellSUM2D = rowSUM2D.getCell((short) 0);
|
||||
assertEquals("SUM(C:D)", cellSUM2D.getCellFormula());
|
||||
eva.setCurrentRow(rowSUM2D);
|
||||
assertEquals(66, eva.evaluate(cellSUM2D).getNumberValue(), 0);
|
||||
|
@ -240,7 +239,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||
HSSFSheet sheet = wb.createSheet();
|
||||
wb.setSheetName(0, "Sheet1");
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
HSSFCell cell = row.createCell((short)0);
|
||||
HSSFCell cell = row.createCell((short) 0);
|
||||
|
||||
cell.setCellFormula("1=1");
|
||||
|
||||
|
@ -253,29 +252,46 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
|||
}
|
||||
assertEquals(true, cell.getBooleanCellValue());
|
||||
}
|
||||
|
||||
|
||||
public void testClassCast_bug44861() throws Exception {
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.
|
||||
openSampleWorkbook("44861.xls");
|
||||
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44861.xls");
|
||||
|
||||
// Check direct
|
||||
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
|
||||
|
||||
|
||||
// And via calls
|
||||
int numSheets = wb.getNumberOfSheets();
|
||||
for(int i=0; i<numSheets; i++) {
|
||||
for (int i = 0; i < numSheets; i++) {
|
||||
HSSFSheet s = wb.getSheetAt(i);
|
||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(s,wb);
|
||||
|
||||
for(Iterator rows = s.rowIterator(); rows.hasNext();) {
|
||||
HSSFRow r = (HSSFRow)rows.next();
|
||||
eval.setCurrentRow(r);
|
||||
|
||||
for(Iterator cells = r.cellIterator(); cells.hasNext();) {
|
||||
HSSFCell c = (HSSFCell)cells.next();
|
||||
eval.evaluateFormulaCell(c);
|
||||
}
|
||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(s, wb);
|
||||
|
||||
for (Iterator rows = s.rowIterator(); rows.hasNext();) {
|
||||
HSSFRow r = (HSSFRow) rows.next();
|
||||
eval.setCurrentRow(r);
|
||||
|
||||
for (Iterator cells = r.cellIterator(); cells.hasNext();) {
|
||||
HSSFCell c = (HSSFCell) cells.next();
|
||||
eval.evaluateFormulaCell(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testEvaluateInCellWithErrorCode_bug44950() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet sheet = wb.createSheet("Sheet1");
|
||||
HSSFRow row = sheet.createRow(1);
|
||||
HSSFCell cell = row.createCell((short) 0);
|
||||
cell.setCellFormula("na()"); // this formula evaluates to an Excel error code '#N/A'
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
fe.setCurrentRow(row);
|
||||
try {
|
||||
fe.evaluateInCell(cell);
|
||||
} catch (NumberFormatException e) {
|
||||
if (e.getMessage().equals("You cannot get an error value from a non-error cell")) {
|
||||
throw new AssertionFailedError("Identified bug 44950 b");
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,11 +17,10 @@
|
|||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
|
||||
/**
|
||||
* Test HSSFRow is okay.
|
||||
*
|
||||
|
@ -32,7 +31,7 @@ public final class TestHSSFRow extends TestCase {
|
|||
public void testLastAndFirstColumns() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
HSSFRow row = sheet.createRow((short) 0);
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
assertEquals(-1, row.getFirstCellNum());
|
||||
assertEquals(-1, row.getLastCellNum());
|
||||
|
||||
|
@ -50,7 +49,35 @@ public final class TestHSSFRow extends TestCase {
|
|||
assertEquals(4, row.getLastCellNum());
|
||||
}
|
||||
|
||||
public void testRemoveCell() throws Exception {
|
||||
/**
|
||||
* Make sure that there is no cross-talk between rows especially with getFirstCellNum and getLastCellNum
|
||||
* This test was added in response to bug report 44987.
|
||||
*/
|
||||
public void testBoundsInMultipleRows() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
HSSFRow rowA = sheet.createRow(0);
|
||||
|
||||
rowA.createCell((short) 10);
|
||||
rowA.createCell((short) 5);
|
||||
assertEquals(5, rowA.getFirstCellNum());
|
||||
assertEquals(11, rowA.getLastCellNum());
|
||||
|
||||
HSSFRow rowB = sheet.createRow(1);
|
||||
rowB.createCell((short) 15);
|
||||
rowB.createCell((short) 30);
|
||||
assertEquals(15, rowB.getFirstCellNum());
|
||||
assertEquals(31, rowB.getLastCellNum());
|
||||
|
||||
assertEquals(5, rowA.getFirstCellNum());
|
||||
assertEquals(11, rowA.getLastCellNum());
|
||||
rowA.createCell((short) 50);
|
||||
assertEquals(51, rowA.getLastCellNum());
|
||||
|
||||
assertEquals(31, rowB.getLastCellNum());
|
||||
}
|
||||
|
||||
public void testRemoveCell() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
HSSFRow row = sheet.createRow((short) 0);
|
||||
|
@ -76,16 +103,11 @@ public final class TestHSSFRow extends TestCase {
|
|||
assertEquals(0, data[6]);
|
||||
assertEquals(0, data[8]);
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
workbook.write(baos);
|
||||
baos.close();
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
|
||||
workbook = new HSSFWorkbook(inputStream);
|
||||
workbook = HSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
sheet = workbook.getSheetAt(0);
|
||||
inputStream.close();
|
||||
|
||||
assertEquals(-1, sheet.getRow((short) 0).getLastCellNum());
|
||||
assertEquals(-1, sheet.getRow((short) 0).getFirstCellNum());
|
||||
assertEquals(-1, sheet.getRow(0).getLastCellNum());
|
||||
assertEquals(-1, sheet.getRow(0).getFirstCellNum());
|
||||
}
|
||||
|
||||
public void testMoveCell() {
|
||||
|
@ -143,8 +165,9 @@ public final class TestHSSFRow extends TestCase {
|
|||
try {
|
||||
sheet.createRow(-1);
|
||||
fail("IndexOutOfBoundsException should have been thrown");
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected during successful test
|
||||
assertEquals("Invalid row number (-1) outside allowable range (0..65535)", e.getMessage());
|
||||
}
|
||||
|
||||
//Test high row bound
|
||||
|
@ -153,8 +176,9 @@ public final class TestHSSFRow extends TestCase {
|
|||
try {
|
||||
sheet.createRow(65536);
|
||||
fail("IndexOutOfBoundsException should have been thrown");
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected during successful test
|
||||
assertEquals("Invalid row number (65536) outside allowable range (0..65535)", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
|
@ -193,17 +194,29 @@ public final class TestHSSFSheet extends TestCase {
|
|||
public void testCloneSheet() {
|
||||
HSSFWorkbook workbook = new HSSFWorkbook();
|
||||
HSSFSheet sheet = workbook.createSheet("Test Clone");
|
||||
HSSFRow row = sheet.createRow((short) 0);
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
HSSFCell cell = row.createCell((short) 0);
|
||||
cell.setCellValue("clone_test");
|
||||
HSSFSheet cloned = workbook.cloneSheet(0);
|
||||
|
||||
HSSFCell cell2 = row.createCell((short) 1);
|
||||
cell.setCellValue(new HSSFRichTextString("clone_test"));
|
||||
cell2.setCellFormula("sin(1)");
|
||||
|
||||
HSSFSheet clonedSheet = workbook.cloneSheet(0);
|
||||
HSSFRow clonedRow = clonedSheet.getRow(0);
|
||||
|
||||
//Check for a good clone
|
||||
assertEquals(cloned.getRow((short)0).getCell((short)0).getStringCellValue(), "clone_test");
|
||||
assertEquals(clonedRow.getCell(0).getRichStringCellValue().getString(), "clone_test");
|
||||
|
||||
//Check that the cells are not somehow linked
|
||||
cell.setCellValue("Difference Check");
|
||||
assertEquals(cloned.getRow((short)0).getCell((short)0).getStringCellValue(), "clone_test");
|
||||
cell.setCellValue(new HSSFRichTextString("Difference Check"));
|
||||
cell2.setCellFormula("cos(2)");
|
||||
if ("Difference Check".equals(clonedRow.getCell(0).getRichStringCellValue().getString())) {
|
||||
fail("string cell not properly cloned");
|
||||
}
|
||||
if ("COS(2)".equals(clonedRow.getCell(1).getCellFormula())) {
|
||||
fail("formula cell not properly cloned");
|
||||
}
|
||||
assertEquals(clonedRow.getCell(0).getRichStringCellValue().getString(), "clone_test");
|
||||
assertEquals(clonedRow.getCell(1).getCellFormula(), "SIN(1)");
|
||||
}
|
||||
|
||||
/** tests that the sheet name for multiple clones of the same sheet is unique
|
||||
|
@ -214,7 +227,7 @@ public final class TestHSSFSheet extends TestCase {
|
|||
HSSFSheet sheet = workbook.createSheet("Test Clone");
|
||||
HSSFRow row = sheet.createRow((short) 0);
|
||||
HSSFCell cell = row.createCell((short) 0);
|
||||
cell.setCellValue("clone_test");
|
||||
cell.setCellValue(new HSSFRichTextString("clone_test"));
|
||||
//Clone the sheet multiple times
|
||||
workbook.cloneSheet(0);
|
||||
workbook.cloneSheet(0);
|
||||
|
@ -517,11 +530,11 @@ public final class TestHSSFSheet extends TestCase {
|
|||
HSSFSheet sheet = wb.createSheet();
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
HSSFCell cell = row.createCell((short)0);
|
||||
cell.setCellValue("first row, first cell");
|
||||
cell.setCellValue(new HSSFRichTextString("first row, first cell"));
|
||||
|
||||
row = sheet.createRow(1);
|
||||
cell = row.createCell((short)1);
|
||||
cell.setCellValue("second row, second cell");
|
||||
cell.setCellValue(new HSSFRichTextString("second row, second cell"));
|
||||
|
||||
Region region = new Region(1, (short)0, 1, (short)1);
|
||||
sheet.addMergedRegion(region);
|
||||
|
@ -643,28 +656,28 @@ public final class TestHSSFSheet extends TestCase {
|
|||
|
||||
/** cell with formula becomes null on cloning a sheet*/
|
||||
public void test35084() {
|
||||
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet s =wb.createSheet("Sheet1");
|
||||
HSSFRow r = s.createRow(0);
|
||||
r.createCell((short)0).setCellValue(1);
|
||||
r.createCell((short)1).setCellFormula("A1*2");
|
||||
HSSFSheet s1 = wb.cloneSheet(0);
|
||||
r=s1.getRow(0);
|
||||
assertEquals("double" ,r.getCell((short)0).getNumericCellValue(),(double)1,0); //sanity check
|
||||
assertNotNull(r.getCell((short)1));
|
||||
assertEquals("formula", r.getCell((short)1).getCellFormula(), "A1*2");
|
||||
}
|
||||
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFSheet s = wb.createSheet("Sheet1");
|
||||
HSSFRow r = s.createRow(0);
|
||||
r.createCell((short) 0).setCellValue(1);
|
||||
r.createCell((short) 1).setCellFormula("A1*2");
|
||||
HSSFSheet s1 = wb.cloneSheet(0);
|
||||
r = s1.getRow(0);
|
||||
assertEquals("double", r.getCell((short) 0).getNumericCellValue(), 1, 0); // sanity check
|
||||
assertNotNull(r.getCell((short) 1));
|
||||
assertEquals("formula", r.getCell((short) 1).getCellFormula(), "A1*2");
|
||||
}
|
||||
|
||||
/** test that new default column styles get applied */
|
||||
public void testDefaultColumnStyle() {
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFCellStyle style = wb.createCellStyle();
|
||||
HSSFSheet s = wb.createSheet();
|
||||
s.setDefaultColumnStyle((short)0, style);
|
||||
HSSFRow r = s.createRow(0);
|
||||
HSSFCell c = r.createCell((short)0);
|
||||
assertEquals("style should match", style.getIndex(), c.getCellStyle().getIndex());
|
||||
HSSFWorkbook wb = new HSSFWorkbook();
|
||||
HSSFCellStyle style = wb.createCellStyle();
|
||||
HSSFSheet s = wb.createSheet();
|
||||
s.setDefaultColumnStyle((short) 0, style);
|
||||
HSSFRow r = s.createRow(0);
|
||||
HSSFCell c = r.createCell((short) 0);
|
||||
assertEquals("style should match", style.getIndex(), c.getCellStyle().getIndex());
|
||||
}
|
||||
|
||||
|
||||
|
@ -814,11 +827,6 @@ public final class TestHSSFSheet extends TestCase {
|
|||
assertTrue(wb3.getSheetAt(3).getForceFormulaRecalculation());
|
||||
}
|
||||
|
||||
|
||||
public static void main(java.lang.String[] args) {
|
||||
junit.textui.TestRunner.run(TestHSSFSheet.class);
|
||||
}
|
||||
|
||||
public void testColumnWidth() throws Exception {
|
||||
//check we can correctly read column widths from a reference workbook
|
||||
HSSFWorkbook wb = openSample("colwidth.xls");
|
||||
|
@ -870,11 +878,33 @@ public final class TestHSSFSheet extends TestCase {
|
|||
assertEquals(256*10, sh.getColumnWidth((short)0));
|
||||
assertEquals(256*10, sh.getColumnWidth((short)1));
|
||||
assertEquals(256*10, sh.getColumnWidth((short)2));
|
||||
//columns D-F have custom wodth
|
||||
//columns D-F have custom width
|
||||
for (char i = 'D'; i <= 'F'; i++) {
|
||||
short w = (short)(256*12);
|
||||
assertEquals(w, sh.getColumnWidth((short)i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some utilities write Excel files without the ROW records.
|
||||
* Excel, ooo, and google docs are OK with this.
|
||||
* Now POI is too.
|
||||
*/
|
||||
public void testMissingRowRecords_bug41187() {
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("ex41187-19267.xls");
|
||||
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
HSSFRow row = sheet.getRow(0);
|
||||
if(row == null) {
|
||||
throw new AssertionFailedError("Identified bug 41187 a");
|
||||
}
|
||||
if (row.getHeight() == 0) {
|
||||
throw new AssertionFailedError("Identified bug 41187 b");
|
||||
}
|
||||
assertEquals("Hi Excel!", row.getCell(0).getRichStringCellValue().getString());
|
||||
// check row height for 'default' flag
|
||||
assertEquals((short)0x8000, row.getHeight());
|
||||
|
||||
HSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,18 @@
|
|||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.record.NameRecord;
|
||||
import org.apache.poi.util.TempFile;
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class TestHSSFWorkbook extends TestCase {
|
||||
private static HSSFWorkbook openSample(String sampleFileName) {
|
||||
|
@ -93,7 +98,7 @@ public final class TestHSSFWorkbook extends TestCase {
|
|||
b.setSheetName( 3, "name2" );
|
||||
b.setSheetName( 3, "name2" );
|
||||
b.setSheetName( 3, "name2" );
|
||||
|
||||
|
||||
HSSFWorkbook c = new HSSFWorkbook( );
|
||||
c.createSheet("Sheet1");
|
||||
c.createSheet("Sheet2");
|
||||
|
@ -101,109 +106,274 @@ public final class TestHSSFWorkbook extends TestCase {
|
|||
c.createSheet("Sheet4");
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testWindowOneDefaults() {
|
||||
HSSFWorkbook b = new HSSFWorkbook( );
|
||||
try {
|
||||
assertEquals(b.getSelectedTab(), 0);
|
||||
assertEquals(b.getDisplayedTab(), 0);
|
||||
assertEquals(b.getActiveSheetIndex(), 0);
|
||||
assertEquals(b.getFirstVisibleTab(), 0);
|
||||
} catch (NullPointerException npe) {
|
||||
fail("WindowOneRecord in Workbook is probably not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testSheetSelection() {
|
||||
HSSFWorkbook b = new HSSFWorkbook();
|
||||
b.createSheet("Sheet One");
|
||||
b.createSheet("Sheet Two");
|
||||
b.setSelectedTab((short) 1);
|
||||
b.setDisplayedTab((short) 1);
|
||||
assertEquals(b.getSelectedTab(), 1);
|
||||
assertEquals(b.getDisplayedTab(), 1);
|
||||
b.setActiveSheet(1);
|
||||
b.setSelectedTab(1);
|
||||
b.setFirstVisibleTab(1);
|
||||
assertEquals(1, b.getActiveSheetIndex());
|
||||
assertEquals(1, b.getFirstVisibleTab());
|
||||
}
|
||||
|
||||
|
||||
public void testSheetClone() {
|
||||
// First up, try a simple file
|
||||
HSSFWorkbook b = new HSSFWorkbook();
|
||||
assertEquals(0, b.getNumberOfSheets());
|
||||
b.createSheet("Sheet One");
|
||||
b.createSheet("Sheet Two");
|
||||
|
||||
|
||||
assertEquals(2, b.getNumberOfSheets());
|
||||
b.cloneSheet(0);
|
||||
assertEquals(3, b.getNumberOfSheets());
|
||||
|
||||
|
||||
// Now try a problem one with drawing records in it
|
||||
b = openSample("SheetWithDrawing.xls");
|
||||
assertEquals(1, b.getNumberOfSheets());
|
||||
b.cloneSheet(0);
|
||||
assertEquals(2, b.getNumberOfSheets());
|
||||
}
|
||||
|
||||
|
||||
public void testReadWriteWithCharts() {
|
||||
HSSFWorkbook b;
|
||||
HSSFSheet s;
|
||||
|
||||
|
||||
// Single chart, two sheets
|
||||
b = openSample("44010-SingleChart.xls");
|
||||
assertEquals(2, b.getNumberOfSheets());
|
||||
assertEquals("Graph2", b.getSheetName(1));
|
||||
s = b.getSheetAt(1);
|
||||
assertEquals(0, s.getFirstRowNum());
|
||||
assertEquals(0, s.getLastRowNum());
|
||||
|
||||
assertEquals(8, s.getLastRowNum());
|
||||
|
||||
// Has chart on 1st sheet??
|
||||
// FIXME
|
||||
assertNotNull(b.getSheetAt(0).getDrawingPatriarch());
|
||||
assertNull(b.getSheetAt(1).getDrawingPatriarch());
|
||||
assertFalse(b.getSheetAt(0).getDrawingPatriarch().containsChart());
|
||||
|
||||
// We've now called getDrawingPatriarch() so
|
||||
|
||||
// We've now called getDrawingPatriarch() so
|
||||
// everything will be all screwy
|
||||
// So, start again
|
||||
b = openSample("44010-SingleChart.xls");
|
||||
|
||||
|
||||
b = writeRead(b);
|
||||
assertEquals(2, b.getNumberOfSheets());
|
||||
s = b.getSheetAt(1);
|
||||
assertEquals(0, s.getFirstRowNum());
|
||||
assertEquals(0, s.getLastRowNum());
|
||||
assertEquals(8, s.getLastRowNum());
|
||||
|
||||
|
||||
|
||||
// Two charts, three sheets
|
||||
b = openSample("44010-TwoCharts.xls");
|
||||
assertEquals(3, b.getNumberOfSheets());
|
||||
|
||||
|
||||
s = b.getSheetAt(1);
|
||||
assertEquals(0, s.getFirstRowNum());
|
||||
assertEquals(0, s.getLastRowNum());
|
||||
assertEquals(8, s.getLastRowNum());
|
||||
s = b.getSheetAt(2);
|
||||
assertEquals(0, s.getFirstRowNum());
|
||||
assertEquals(0, s.getLastRowNum());
|
||||
|
||||
assertEquals(8, s.getLastRowNum());
|
||||
|
||||
// Has chart on 1st sheet??
|
||||
// FIXME
|
||||
assertNotNull(b.getSheetAt(0).getDrawingPatriarch());
|
||||
assertNull(b.getSheetAt(1).getDrawingPatriarch());
|
||||
assertNull(b.getSheetAt(2).getDrawingPatriarch());
|
||||
assertFalse(b.getSheetAt(0).getDrawingPatriarch().containsChart());
|
||||
|
||||
// We've now called getDrawingPatriarch() so
|
||||
|
||||
// We've now called getDrawingPatriarch() so
|
||||
// everything will be all screwy
|
||||
// So, start again
|
||||
b = openSample("44010-TwoCharts.xls");
|
||||
|
||||
|
||||
b = writeRead(b);
|
||||
assertEquals(3, b.getNumberOfSheets());
|
||||
|
||||
|
||||
s = b.getSheetAt(1);
|
||||
assertEquals(0, s.getFirstRowNum());
|
||||
assertEquals(0, s.getLastRowNum());
|
||||
assertEquals(8, s.getLastRowNum());
|
||||
s = b.getSheetAt(2);
|
||||
assertEquals(0, s.getFirstRowNum());
|
||||
assertEquals(0, s.getLastRowNum());
|
||||
assertEquals(8, s.getLastRowNum());
|
||||
}
|
||||
|
||||
|
||||
private static HSSFWorkbook writeRead(HSSFWorkbook b) {
|
||||
return HSSFTestDataSamples.writeOutAndReadBack(b);
|
||||
return HSSFTestDataSamples.writeOutAndReadBack(b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testSelectedSheet_bug44523() {
|
||||
HSSFWorkbook wb=new HSSFWorkbook();
|
||||
HSSFSheet sheet1 = wb.createSheet("Sheet1");
|
||||
HSSFSheet sheet2 = wb.createSheet("Sheet2");
|
||||
HSSFSheet sheet3 = wb.createSheet("Sheet3");
|
||||
HSSFSheet sheet4 = wb.createSheet("Sheet4");
|
||||
|
||||
confirmActiveSelected(sheet1, true);
|
||||
confirmActiveSelected(sheet2, false);
|
||||
confirmActiveSelected(sheet3, false);
|
||||
confirmActiveSelected(sheet4, false);
|
||||
|
||||
wb.setSelectedTab(1);
|
||||
|
||||
// Demonstrate bug 44525:
|
||||
// Well... not quite, since isActive + isSelected were also added in the same bug fix
|
||||
if (sheet1.isSelected()) {
|
||||
throw new AssertionFailedError("Identified bug 44523 a");
|
||||
}
|
||||
wb.setActiveSheet(1);
|
||||
if (sheet1.isActive()) {
|
||||
throw new AssertionFailedError("Identified bug 44523 b");
|
||||
}
|
||||
|
||||
confirmActiveSelected(sheet1, false);
|
||||
confirmActiveSelected(sheet2, true);
|
||||
confirmActiveSelected(sheet3, false);
|
||||
confirmActiveSelected(sheet4, false);
|
||||
}
|
||||
|
||||
public void testSelectMultiple() {
|
||||
HSSFWorkbook wb=new HSSFWorkbook();
|
||||
HSSFSheet sheet1 = wb.createSheet("Sheet1");
|
||||
HSSFSheet sheet2 = wb.createSheet("Sheet2");
|
||||
HSSFSheet sheet3 = wb.createSheet("Sheet3");
|
||||
HSSFSheet sheet4 = wb.createSheet("Sheet4");
|
||||
HSSFSheet sheet5 = wb.createSheet("Sheet5");
|
||||
HSSFSheet sheet6 = wb.createSheet("Sheet6");
|
||||
|
||||
wb.setSelectedTabs(new int[] { 0, 2, 3});
|
||||
|
||||
assertEquals(true, sheet1.isSelected());
|
||||
assertEquals(false, sheet2.isSelected());
|
||||
assertEquals(true, sheet3.isSelected());
|
||||
assertEquals(true, sheet4.isSelected());
|
||||
assertEquals(false, sheet5.isSelected());
|
||||
assertEquals(false, sheet6.isSelected());
|
||||
|
||||
wb.setSelectedTabs(new int[] { 1, 3, 5});
|
||||
|
||||
assertEquals(false, sheet1.isSelected());
|
||||
assertEquals(true, sheet2.isSelected());
|
||||
assertEquals(false, sheet3.isSelected());
|
||||
assertEquals(true, sheet4.isSelected());
|
||||
assertEquals(false, sheet5.isSelected());
|
||||
assertEquals(true, sheet6.isSelected());
|
||||
|
||||
assertEquals(true, sheet1.isActive());
|
||||
assertEquals(false, sheet2.isActive());
|
||||
|
||||
|
||||
assertEquals(true, sheet1.isActive());
|
||||
assertEquals(false, sheet3.isActive());
|
||||
wb.setActiveSheet(2);
|
||||
assertEquals(false, sheet1.isActive());
|
||||
assertEquals(true, sheet3.isActive());
|
||||
|
||||
if (false) { // helpful if viewing this workbook in excel:
|
||||
sheet1.createRow(0).createCell((short)0).setCellValue(new HSSFRichTextString("Sheet1"));
|
||||
sheet2.createRow(0).createCell((short)0).setCellValue(new HSSFRichTextString("Sheet2"));
|
||||
sheet3.createRow(0).createCell((short)0).setCellValue(new HSSFRichTextString("Sheet3"));
|
||||
sheet4.createRow(0).createCell((short)0).setCellValue(new HSSFRichTextString("Sheet4"));
|
||||
|
||||
try {
|
||||
File fOut = TempFile.createTempFile("sheetMultiSelect", ".xls");
|
||||
FileOutputStream os = new FileOutputStream(fOut);
|
||||
wb.write(os);
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testActiveSheetAfterDelete_bug40414() {
|
||||
HSSFWorkbook wb=new HSSFWorkbook();
|
||||
HSSFSheet sheet0 = wb.createSheet("Sheet0");
|
||||
HSSFSheet sheet1 = wb.createSheet("Sheet1");
|
||||
HSSFSheet sheet2 = wb.createSheet("Sheet2");
|
||||
HSSFSheet sheet3 = wb.createSheet("Sheet3");
|
||||
HSSFSheet sheet4 = wb.createSheet("Sheet4");
|
||||
|
||||
// confirm default activation/selection
|
||||
confirmActiveSelected(sheet0, true);
|
||||
confirmActiveSelected(sheet1, false);
|
||||
confirmActiveSelected(sheet2, false);
|
||||
confirmActiveSelected(sheet3, false);
|
||||
confirmActiveSelected(sheet4, false);
|
||||
|
||||
wb.setActiveSheet(3);
|
||||
wb.setSelectedTab(3);
|
||||
|
||||
confirmActiveSelected(sheet0, false);
|
||||
confirmActiveSelected(sheet1, false);
|
||||
confirmActiveSelected(sheet2, false);
|
||||
confirmActiveSelected(sheet3, true);
|
||||
confirmActiveSelected(sheet4, false);
|
||||
|
||||
wb.removeSheetAt(3);
|
||||
// after removing the only active/selected sheet, another should be active/selected in its place
|
||||
if (!sheet4.isSelected()) {
|
||||
throw new AssertionFailedError("identified bug 40414 a");
|
||||
}
|
||||
if (!sheet4.isActive()) {
|
||||
throw new AssertionFailedError("identified bug 40414 b");
|
||||
}
|
||||
|
||||
confirmActiveSelected(sheet0, false);
|
||||
confirmActiveSelected(sheet1, false);
|
||||
confirmActiveSelected(sheet2, false);
|
||||
confirmActiveSelected(sheet4, true);
|
||||
|
||||
sheet3 = sheet4; // re-align local vars in this test case
|
||||
|
||||
// Some more cases of removing sheets
|
||||
|
||||
// Starting with a multiple selection, and different active sheet
|
||||
wb.setSelectedTabs(new int[] { 1, 3, });
|
||||
wb.setActiveSheet(2);
|
||||
confirmActiveSelected(sheet0, false, false);
|
||||
confirmActiveSelected(sheet1, false, true);
|
||||
confirmActiveSelected(sheet2, true, false);
|
||||
confirmActiveSelected(sheet3, false, true);
|
||||
|
||||
// removing a sheet that is not active, and not the only selected sheet
|
||||
wb.removeSheetAt(3);
|
||||
confirmActiveSelected(sheet0, false, false);
|
||||
confirmActiveSelected(sheet1, false, true);
|
||||
confirmActiveSelected(sheet2, true, false);
|
||||
|
||||
// removing the only selected sheet
|
||||
wb.removeSheetAt(1);
|
||||
confirmActiveSelected(sheet0, false, false);
|
||||
confirmActiveSelected(sheet2, true, true);
|
||||
|
||||
// The last remaining sheet should always be active+selected
|
||||
wb.removeSheetAt(1);
|
||||
confirmActiveSelected(sheet0, true, true);
|
||||
}
|
||||
|
||||
private static void confirmActiveSelected(HSSFSheet sheet, boolean expected) {
|
||||
confirmActiveSelected(sheet, expected, expected);
|
||||
}
|
||||
|
||||
|
||||
private static void confirmActiveSelected(HSSFSheet sheet,
|
||||
boolean expectedActive, boolean expectedSelected) {
|
||||
assertEquals("active", expectedActive, sheet.isActive());
|
||||
assertEquals("selected", expectedSelected, sheet.isSelected());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -533,4 +533,28 @@ public final class TestNamedRange extends TestCase {
|
|||
String contents = c.getStringCellValue();
|
||||
assertEquals("Contents of cell retrieved by its named reference", contents, cvalue);
|
||||
}
|
||||
|
||||
public void testDeletedReference() throws Exception {
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("24207.xls");
|
||||
assertEquals(2, wb.getNumberOfNames());
|
||||
|
||||
HSSFName name1 = wb.getNameAt(0);
|
||||
assertEquals("a", name1.getNameName());
|
||||
assertEquals("Sheet1!$A$1", name1.getReference());
|
||||
AreaReference ref1 = new AreaReference(name1.getReference());
|
||||
assertTrue("Successfully constructed first reference", true);
|
||||
|
||||
HSSFName name2 = wb.getNameAt(1);
|
||||
assertEquals("b", name2.getNameName());
|
||||
assertEquals("#REF!", name2.getReference());
|
||||
assertTrue(name2.isDeleted());
|
||||
try {
|
||||
AreaReference ref2 = new AreaReference(name2.getReference());
|
||||
fail("attempt to supply an invalid reference to AreaReference constructor results in exception");
|
||||
} catch (Exception e){
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -17,6 +17,9 @@
|
|||
|
||||
package org.apache.poi.poifs.filesystem;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
|
@ -115,6 +118,40 @@ public final class TestPOIFSFileSystem extends TestCase {
|
|||
assertTrue("input stream was not closed", testIS.isClosed()); // but still should close
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for bug # 48898 - problem opening an OLE2
|
||||
* file where the last block is short (i.e. not a full
|
||||
* multiple of 512 bytes)
|
||||
*
|
||||
* As yet, this problem remains. One school of thought is
|
||||
* not not issue an EOF when we discover the last block
|
||||
* is short, but this seems a bit wrong.
|
||||
* The other is to fix the handling of the last block in
|
||||
* POIFS, since it seems to be slight wrong
|
||||
*/
|
||||
public void DISABLEDtestShortLastBlock() throws Exception {
|
||||
String[] files = new String[] {
|
||||
"ShortLastBlock.qwp", "ShortLastBlock.wps"
|
||||
};
|
||||
String pdirname = System.getProperty("POIFS.testdata.path");
|
||||
|
||||
for(int i=0; i<files.length; i++) {
|
||||
File f = new File(pdirname, files[i]);
|
||||
assertTrue(f.exists());
|
||||
|
||||
// Open the file up
|
||||
POIFSFileSystem fs = new POIFSFileSystem(
|
||||
new FileInputStream(f)
|
||||
);
|
||||
|
||||
// Write it into a temp output array
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
fs.writeFilesystem(baos);
|
||||
|
||||
// Check sizes
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream openSampleStream(String sampleFileName) {
|
||||
return HSSFTestDataSamples.openSampleFileStream(sampleFileName);
|
||||
|
|
|
@ -152,7 +152,7 @@ public class TestRawDataBlock
|
|||
}
|
||||
|
||||
assertEquals(
|
||||
"7 - Unable to read entire block; "+bts+" read before EOF; expected 512 bytes. Your document has probably been truncated!",
|
||||
"7 - Unable to read entire block; "+bts+" read before EOF; expected 512 bytes. Your document was either written by software that ignores the spec, or has been truncated!",
|
||||
(String)(logger.logged.get(0))
|
||||
);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue