From: Dominik Stadler Date: Wed, 21 Aug 2013 22:08:20 +0000 (+0000) Subject: Bug 50298: Fix corruption of Workbook when setting sheet order. The X-Git-Tag: REL_3_10_BETA2~15 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=324a36e170d9cfadb02f33a0667f9049ec7a9e60;p=poi.git Bug 50298: Fix corruption of Workbook when setting sheet order. The boundssheets themselves were adjusted, but not the corresponding records. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1516313 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java index a989c32b98..0a489d29cf 100644 --- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -26,61 +26,8 @@ import java.util.Locale; import java.util.Map; import java.util.Map.Entry; -import org.apache.poi.ddf.EscherBSERecord; -import org.apache.poi.ddf.EscherBoolProperty; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherDgRecord; -import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherRGBProperty; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.ddf.EscherSplitMenuColorsRecord; -import org.apache.poi.hssf.record.BOFRecord; -import org.apache.poi.hssf.record.BackupRecord; -import org.apache.poi.hssf.record.BookBoolRecord; -import org.apache.poi.hssf.record.BoundSheetRecord; -import org.apache.poi.hssf.record.CodepageRecord; -import org.apache.poi.hssf.record.CountryRecord; -import org.apache.poi.hssf.record.DSFRecord; -import org.apache.poi.hssf.record.DateWindow1904Record; -import org.apache.poi.hssf.record.DrawingGroupRecord; -import org.apache.poi.hssf.record.EOFRecord; -import org.apache.poi.hssf.record.EscherAggregate; -import org.apache.poi.hssf.record.ExtSSTRecord; -import org.apache.poi.hssf.record.ExtendedFormatRecord; -import org.apache.poi.hssf.record.ExternSheetRecord; -import org.apache.poi.hssf.record.FileSharingRecord; -import org.apache.poi.hssf.record.FnGroupCountRecord; -import org.apache.poi.hssf.record.FontRecord; -import org.apache.poi.hssf.record.FormatRecord; -import org.apache.poi.hssf.record.HideObjRecord; -import org.apache.poi.hssf.record.HyperlinkRecord; -import org.apache.poi.hssf.record.InterfaceEndRecord; -import org.apache.poi.hssf.record.InterfaceHdrRecord; -import org.apache.poi.hssf.record.MMSRecord; -import org.apache.poi.hssf.record.NameCommentRecord; -import org.apache.poi.hssf.record.NameRecord; -import org.apache.poi.hssf.record.PaletteRecord; -import org.apache.poi.hssf.record.PasswordRecord; -import org.apache.poi.hssf.record.PasswordRev4Record; -import org.apache.poi.hssf.record.PrecisionRecord; -import org.apache.poi.hssf.record.ProtectRecord; -import org.apache.poi.hssf.record.ProtectionRev4Record; -import org.apache.poi.hssf.record.RecalcIdRecord; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.RefreshAllRecord; -import org.apache.poi.hssf.record.SSTRecord; -import org.apache.poi.hssf.record.StyleRecord; -import org.apache.poi.hssf.record.SupBookRecord; -import org.apache.poi.hssf.record.TabIdRecord; -import org.apache.poi.hssf.record.UseSelFSRecord; -import org.apache.poi.hssf.record.WindowOneRecord; -import org.apache.poi.hssf.record.WindowProtectRecord; -import org.apache.poi.hssf.record.WriteAccessRecord; -import org.apache.poi.hssf.record.WriteProtectRecord; +import org.apache.poi.ddf.*; +import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName; @@ -405,14 +352,14 @@ public final class InternalWorkbook { } for (int k = 0; k < 21; k++) { - records.add(retval.createExtendedFormat(k)); + records.add(InternalWorkbook.createExtendedFormat(k)); retval.numxfs++; } retval.records.setXfpos( records.size() - 1 ); for (int k = 0; k < 6; k++) { - records.add(retval.createStyle(k)); + records.add(InternalWorkbook.createStyle(k)); } - records.add(retval.createUseSelFS()); + records.add(InternalWorkbook.createUseSelFS()); int nBoundSheets = 1; // now just do 1 for (int k = 0; k < nBoundSheets; k++) { @@ -422,13 +369,13 @@ public final class InternalWorkbook { retval.boundsheets.add(bsr); retval.records.setBspos(records.size() - 1); } - records.add( retval.createCountry() ); + records.add( InternalWorkbook.createCountry() ); for ( int k = 0; k < nBoundSheets; k++ ) { retval.getOrCreateLinkTable().checkExternSheet(k); } retval.sst = new SSTRecord(); records.add(retval.sst); - records.add(retval.createExtendedSST()); + records.add(InternalWorkbook.createExtendedSST()); records.add(EOFRecord.instance); if (log.check( POILogger.DEBUG )) @@ -628,9 +575,15 @@ public final class InternalWorkbook { */ public void setSheetOrder(String sheetname, int pos ) { - int sheetNumber = getSheetIndex(sheetname); - //remove the sheet that needs to be reordered and place it in the spot we want - boundsheets.add(pos, boundsheets.remove(sheetNumber)); + int sheetNumber = getSheetIndex(sheetname); + //remove the sheet that needs to be reordered and place it in the spot we want + boundsheets.add(pos, boundsheets.remove(sheetNumber)); + + // also adjust order of Records, calculate the position of the Boundsheets via getBspos()... + int pos0 = records.getBspos() - (boundsheets.size() - 1); + Record removed = records.get(pos0 + sheetNumber); + records.remove(pos0 + sheetNumber); + records.add(pos0 + pos, removed); } /** @@ -1087,11 +1040,13 @@ public final class InternalWorkbook { Record record = records.get( k ); if (record instanceof SSTRecord) sst = (SSTRecord)record; + if (record.getSid() == ExtSSTRecord.sid && sst != null) retval += sst.calcExtSSTRecordSize(); else retval += record.getRecordSize(); } + return retval; } @@ -2320,10 +2275,9 @@ public final class InternalWorkbook { * @param password to set */ public void writeProtectWorkbook( String password, String username ) { - int protIdx = -1; FileSharingRecord frec = getFileSharing(); WriteAccessRecord waccess = getWriteAccess(); - WriteProtectRecord wprotect = getWriteProtect(); + /* WriteProtectRecord wprotect =*/ getWriteProtect(); frec.setReadOnly((short)1); frec.setPassword(FileSharingRecord.hashPassword(password)); frec.setUsername(username); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java index eab7b57dac..c1b226b87f 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java @@ -17,29 +17,40 @@ package org.apache.poi.hssf.usermodel; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.List; import junit.framework.AssertionFailedError; -import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.POIDataSamples; +import org.apache.poi.ddf.EscherBSERecord; +import org.apache.poi.hpsf.ClassID; import org.apache.poi.hssf.HSSFITestDataProvider; +import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.model.HSSFFormulaParser; -import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.model.InternalSheet; -import org.apache.poi.hssf.record.*; -import org.apache.poi.ss.formula.ptg.Area3DPtg; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.TempFile; -import org.apache.poi.ss.usermodel.BaseTestWorkbook; -import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.hssf.model.InternalWorkbook; +import org.apache.poi.hssf.record.CFRuleRecord; +import org.apache.poi.hssf.record.NameRecord; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RecordBase; +import org.apache.poi.hssf.record.RecordFormatException; +import org.apache.poi.hssf.record.WindowOneRecord; import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.POIDataSamples; -import org.apache.poi.ddf.EscherBSERecord; -import org.apache.poi.hpsf.ClassID; +import org.apache.poi.ss.formula.ptg.Area3DPtg; +import org.apache.poi.ss.usermodel.BaseTestWorkbook; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.TempFile; /** * Tests for {@link HSSFWorkbook} @@ -455,13 +466,16 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook { public BadlyBehavedRecord() { // } - public short getSid() { + @Override + public short getSid() { return 0x777; } - public int serialize(int offset, byte[] data) { + @Override + public int serialize(int offset, byte[] data) { return 4; } - public int getRecordSize() { + @Override + public int getRecordSize() { return 8; } } @@ -598,6 +612,8 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook { wb = HSSFTestDataSamples.writeOutAndReadBack(wb); assertEquals(3, wb.getNumberOfSheets()); assertEquals("Root xls", wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue()); + + fs.close(); } public void testCellStylesLimit() { @@ -606,12 +622,12 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook { int MAX_STYLES = 4030; int limit = MAX_STYLES - numBuiltInStyles; for(int i=0; i < limit; i++){ - HSSFCellStyle style = wb.createCellStyle(); + /* HSSFCellStyle style =*/ wb.createCellStyle(); } assertEquals(MAX_STYLES, wb.getNumCellStyles()); try { - HSSFCellStyle style = wb.createCellStyle(); + /*HSSFCellStyle style =*/ wb.createCellStyle(); fail("expected exception"); } catch (IllegalStateException e){ assertEquals("The maximum number of cell styles was exceeded. " + @@ -877,4 +893,31 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook { wb.unwriteProtectWorkbook(); assertFalse(wb.isWriteProtected()); } + + public void testBug50298() throws Exception { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("50298.xls"); + + + HSSFSheet sheet = wb.cloneSheet(0); + + wb.setSheetName(wb.getSheetIndex(sheet), "copy"); + + wb.setSheetOrder("copy", 0); + + wb.removeSheetAt(0); + + // check that the overall workbook serializes with its correct size + int expected = wb.getWorkbook().getSize(); + int written = wb.getWorkbook().serialize(0, new byte[expected*2]); + + assertEquals("Did not have the expected size when writing the workbook: written: " + written + ", but expected: " + expected, + expected, written); + + FileOutputStream fileOut = new FileOutputStream("/tmp/workbook.xls"); + try { + wb.write(fileOut); + } finally { + fileOut.close(); + } + } } diff --git a/test-data/spreadsheet/50298.xls b/test-data/spreadsheet/50298.xls new file mode 100644 index 0000000000..99eb7643e6 Binary files /dev/null and b/test-data/spreadsheet/50298.xls differ