Browse Source

Merged revisions 638786-638802,638805-638811,638813-638814,638816-639230,639233-639241,639243-639253,639255-639486,639488-639601,639603-639835,639837-639917,639919-640056,640058-640710,640712-641156,641158-641184,641186-641795,641797-641798,641800-641933,641935-641963,641965-641966,641968-641995,641997-642230,642232-642562,642564-642565,642568-642570,642572-642573,642576-642736,642739-642877,642879,642881-642890,642892-642903,642905-642945,642947-643624,643626-643653,643655-643669,643671,643673-643830,643832-643833,643835-644342,644344-644472,644474-644508,644510-645347,645349-645351,645353-645559,645561-645565,645568-645951,645953-646193,646195-646311,646313-646404,646406-646665,646667-646853,646855-646869,646871-647151,647153-647185,647187-647277,647279-647566,647568-647573,647575,647578-647711,647714-647737,647739-647823,647825-648155,648157-648202,648204-648273,648275,648277-648302,648304-648333,648335-648588,648590-648622,648625-648673,648675-649141,649144,649146-649556,649558-649795,649799,649801-649910,649912-649913,649915-650128,650131-650132,650134-650137,650140-650914,650916-651991,651993-652284,652286-652287,652289,652291,652293-652297,652299-652328,652330-652425,652427-652445,652447-652560,652562-652933,652935,652937-652993,652995-653116,653118-653124,653126-653483,653487-653519,653522-653550,653552-653607,653609-653667,653669-653674,653676-653814,653817-653830,653832-653891,653893-653944,653946-654055,654057-654355,654357-654365,654367-654648,654651-655215,655217-655277,655279-655281,655283-655911,655913-656212,656214,656216-656251,656253-656698,656700-656756,656758-656892,656894-657135,657137-657578 via svnmerge from

https://svn.apache.org:443/repos/asf/poi/trunk

........
  r657166 | josh | 2008-05-16 19:46:04 +0100 (Fri, 16 May 2008) | 1 line
  
  Simplification of BiffViewer.  Made easier to send results to file.
........
  r657167 | josh | 2008-05-16 19:55:02 +0100 (Fri, 16 May 2008) | 1 line
  
  Fix for bug 40414 - update selected/active sheet after removing sheet from workbook
........
  r657180 | josh | 2008-05-16 20:24:47 +0100 (Fri, 16 May 2008) | 1 line
  
  fixed bug number in junit msg - from r656893 bug 44523
........
  r657355 | yegor | 2008-05-17 15:00:30 +0100 (Sat, 17 May 2008) | 1 line
  
  added HSSFName.isDeleted() to check if the name points to cell that no longer exists
........
  r657358 | yegor | 2008-05-17 15:03:27 +0100 (Sat, 17 May 2008) | 1 line
  
  misc bug fixes
........


git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@657579 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_5_BETA2
Nick Burch 16 years ago
parent
commit
d0fec10d56

+ 2
- 0
src/documentation/content/xdocs/changes.xml View File

@@ -44,6 +44,8 @@
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
<release version="3.1-beta2" date="2008-05-??">
<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>

+ 14
- 0
src/documentation/content/xdocs/spreadsheet/quick-guide.xml View File

@@ -1284,6 +1284,20 @@ Examples:
Cell c = r.getCell(crefs[j].getCol());
// Do something with this corner cell
}
}
</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>

+ 2
- 0
src/documentation/content/xdocs/status.xml View File

@@ -41,6 +41,8 @@
<action dev="POI-DEVELOPERS" type="add">Created a common interface for handling Excel files, irrespective of if they are .xls or .xlsx</action>
</release>
<release version="3.1-beta2" date="2008-05-??">
<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>

+ 199
- 346
src/java/org/apache/poi/hssf/dev/BiffViewer.java View File

@@ -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 org.apache.poi.hssf.record.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.HexDump;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
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;

/**
* 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");
String inFileName = args[0];
File inputFile = new File(inFileName);
if(!inputFile.exists()) {
throw new RuntimeException("specified inputFile '" + inFileName + "' does not exist");
}
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 == 0)
{
System.out.println( "Biff viewer needs a filename" );
if (args.length > 1 && args[1].equals("on")) {
viewer.setDump(true);
}
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();
}
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));
}
}


+ 9
- 0
src/java/org/apache/poi/hssf/usermodel/HSSFName.java View File

@@ -140,4 +140,13 @@ public class HSSFName implements Name {

}

/**
* 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);
}
}

+ 44
- 4
src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java View File

@@ -157,7 +157,7 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm

protected HSSFWorkbook( Workbook book )
{
super(null, null);
super(null, null);
workbook = book;
sheets = new ArrayList( INITIAL_CAPACITY );
names = new ArrayList( INITIAL_CAPACITY );
@@ -775,14 +775,54 @@ public class HSSFWorkbook extends POIDocument implements org.apache.poi.ss.userm
}

/**
* 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);
}
}
}

/**

BIN
src/testcases/org/apache/poi/hssf/data/24207.xls View File


BIN
src/testcases/org/apache/poi/hssf/data/36947.xls View File


BIN
src/testcases/org/apache/poi/hssf/data/39634.xls View File


+ 41
- 0
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java View File

@@ -911,4 +911,45 @@ public final class TestBugs extends TestCase {
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);
}
}

+ 77
- 4
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java View File

@@ -232,11 +232,11 @@ public final class TestHSSFWorkbook extends TestCase {
// 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 44525 a");
throw new AssertionFailedError("Identified bug 44523 a");
}
wb.setActiveSheet(1);
if (sheet1.isActive()) {
throw new AssertionFailedError("Identified bug 44525 b");
throw new AssertionFailedError("Identified bug 44523 b");
}

confirmActiveSelected(sheet1, false);
@@ -299,8 +299,81 @@ public final class TestHSSFWorkbook extends TestCase {
}
}


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) {
assertEquals(expected, sheet.isActive());
assertEquals(expected, sheet.isSelected());
confirmActiveSelected(sheet, expected, expected);
}


private static void confirmActiveSelected(HSSFSheet sheet,
boolean expectedActive, boolean expectedSelected) {
assertEquals("active", expectedActive, sheet.isActive());
assertEquals("selected", expectedSelected, sheet.isSelected());
}
}

+ 24
- 0
src/testcases/org/apache/poi/hssf/usermodel/TestNamedRange.java View File

@@ -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){
;
}

}

}

Loading…
Cancel
Save