diff --git a/src/ooxml/java/org/apache/poi/POIXMLDocument.java b/src/ooxml/java/org/apache/poi/POIXMLDocument.java index 8b4dc84d9a..f84418545a 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLDocument.java +++ b/src/ooxml/java/org/apache/poi/POIXMLDocument.java @@ -22,8 +22,10 @@ import org.openxml4j.exceptions.InvalidFormatException; import org.openxml4j.exceptions.OpenXML4JException; import org.openxml4j.opc.Package; import org.openxml4j.opc.PackagePart; +import org.openxml4j.opc.PackagePartName; import org.openxml4j.opc.PackageRelationship; import org.openxml4j.opc.PackageRelationshipTypes; +import org.openxml4j.opc.PackagingURIHelper; public abstract class POIXMLDocument { @@ -62,4 +64,13 @@ public abstract class POIXMLDocument { protected PackagePart getCorePart() { return this.corePart; } + + protected PackagePart getPart(PackageRelationship rel) throws InvalidFormatException { + PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); + PackagePart part = getPackage().getPart(relName); + if (part == null) { + throw new IllegalArgumentException("No part found for relationship " + rel); + } + return part; + } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index aed5b6463e..0eb6384e9b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -37,8 +37,8 @@ public class XSSFCell implements Cell { private static final String TRUE_AS_STRING = "1"; private final CTCell cell; private final XSSFRow row; - private SharedStringSource sharedStringSource; private short cellNum; + private SharedStringSource sharedStringSource; /** * Create a new XSSFCell. This method is protected to be used only by @@ -54,10 +54,11 @@ public class XSSFCell implements Cell { if (cell.getR() != null) { this.cellNum = parseCellNum(cell.getR()); } + this.sharedStringSource = row.getSheet().getWorkbook().getSharedStringSource(); } - - protected void setSharedStringSource(SharedStringSource sharedStringSource) { - this.sharedStringSource = sharedStringSource; + + protected SharedStringSource getSharedStringSource() { + return this.sharedStringSource; } public boolean getBooleanCellValue() { @@ -154,7 +155,7 @@ public class XSSFCell implements Cell { if(this.cell.getT() == STCellType.S) { if(this.cell.isSetV()) { int sRef = Integer.parseInt(this.cell.getV()); - return new XSSFRichTextString(sharedStringSource.getSharedStringAt(sRef)); + return new XSSFRichTextString(getSharedStringSource().getSharedStringAt(sRef)); } else { return new XSSFRichTextString(""); } @@ -273,7 +274,7 @@ public class XSSFCell implements Cell { if(this.cell.getT() != STCellType.S) { this.cell.setT(STCellType.S); } - int sRef = sharedStringSource.putSharedString(value.getString()); + int sRef = getSharedStringSource().putSharedString(value.getString()); this.cell.setV(Integer.toString(sRef)); } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java index 0d155502ec..fc372de585 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java @@ -33,22 +33,35 @@ public class XSSFRow implements Row { private List cells; + private XSSFSheet sheet; + /** * Create a new XSSFRow. This method is protected to be used only by * tests. */ - protected XSSFRow() { - this(CTRow.Factory.newInstance()); + protected XSSFRow(XSSFSheet sheet) { + this(CTRow.Factory.newInstance(), sheet); } - public XSSFRow(CTRow row) { + /** + * Create a new XSSFRow. + * + * @param row The underlying XMLBeans row. + * @param sheet The parent sheet. + */ + public XSSFRow(CTRow row, XSSFSheet sheet) { this.row = row; + this.sheet = sheet; this.cells = new LinkedList(); for (CTCell c : row.getCArray()) { this.cells.add(new XSSFCell(this, c)); } } + + public XSSFSheet getSheet() { + return this.sheet; + } public Iterator cellIterator() { return cells.iterator(); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index 5884f7439a..c1e0c05af7 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -53,6 +53,7 @@ public class XSSFSheet implements Sheet { private CTWorksheet worksheet; private List rows; private ColumnHelper columnHelper; + private XSSFWorkbook workbook; public static final short LeftMargin = 0; public static final short RightMargin = 1; @@ -61,9 +62,10 @@ public class XSSFSheet implements Sheet { public static final short HeaderMargin = 4; public static final short FooterMargin = 5; - public XSSFSheet(CTSheet sheet) { + public XSSFSheet(CTSheet sheet, XSSFWorkbook workbook) { this.sheet = sheet; this.worksheet = CTWorksheet.Factory.newInstance(); + this.workbook = workbook; this.worksheet.addNewSheetData(); initRows(worksheet); @@ -102,17 +104,26 @@ public class XSSFSheet implements Sheet { initColumns(worksheet); } - public XSSFSheet(CTSheet sheet, CTWorksheet worksheet) { + public XSSFSheet(CTSheet sheet, CTWorksheet worksheet, XSSFWorkbook workbook) { this.sheet = sheet; this.worksheet = worksheet; + this.workbook = workbook; initRows(worksheet); initColumns(worksheet); } + public XSSFSheet(XSSFWorkbook workbook) { + this.workbook = workbook; + } + + public XSSFWorkbook getWorkbook() { + return this.workbook; + } + private void initRows(CTWorksheet worksheet) { this.rows = new LinkedList(); for (CTRow row : worksheet.getSheetData().getRowArray()) { - this.rows.add(new XSSFRow(row)); + this.rows.add(new XSSFRow(row, this)); } } @@ -153,13 +164,12 @@ public class XSSFSheet implements Sheet { } - protected XSSFRow addRow(int index, int rownum) { - CTRow row = this.worksheet.getSheetData().insertNewRow(index); - XSSFRow xrow = new XSSFRow(row); - xrow.setRowNum(rownum); -// xrow.setHeight(13.41); - return xrow; - } + protected XSSFRow addRow(int index, int rownum) { + CTRow row = this.worksheet.getSheetData().insertNewRow(index); + XSSFRow xrow = new XSSFRow(row, this); + xrow.setRowNum(rownum); + return xrow; + } public Row createRow(int rownum) { int index = 0; @@ -760,7 +770,7 @@ public class XSSFSheet implements Sheet { } protected XSSFSheet cloneSheet() { - return new XSSFSheet((CTSheet) sheet.copy()); + return new XSSFSheet((CTSheet) sheet.copy(), this.workbook); } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java index 44ad5aed24..309225b3a6 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java @@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel; import java.io.IOException; import java.io.OutputStream; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -30,8 +31,10 @@ import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.Palette; +import org.apache.poi.ss.usermodel.SharedStringSource; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.strings.SharedStringsTable; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; @@ -40,6 +43,7 @@ import org.openxml4j.opc.Package; import org.openxml4j.opc.PackagePart; import org.openxml4j.opc.PackagePartName; import org.openxml4j.opc.PackageRelationship; +import org.openxml4j.opc.PackageRelationshipCollection; import org.openxml4j.opc.PackageRelationshipTypes; import org.openxml4j.opc.PackagingURIHelper; import org.openxml4j.opc.TargetMode; @@ -58,10 +62,14 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { private static final String WORKSHEET_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; + private static final String SHARED_STRINGS_RELATIONSHIP = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; + private CTWorkbook workbook; private List sheets = new LinkedList(); - + + private SharedStringSource sharedStringSource; + public XSSFWorkbook() { this.workbook = CTWorkbook.Factory.newInstance(); CTBookViews bvs = this.workbook.addNewBookViews(); @@ -75,25 +83,26 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { try { WorkbookDocument doc = WorkbookDocument.Factory.parse(getCorePart().getInputStream()); this.workbook = doc.getWorkbook(); + // Load shared strings + PackageRelationshipCollection prc = getCorePart().getRelationshipsByType(SHARED_STRINGS_RELATIONSHIP); + Iterator it = prc.iterator(); + if (it.hasNext()) { + PackageRelationship rel = it.next(); + PackagePart part = getPart(rel); + this.sharedStringSource = new SharedStringsTable(part); + } + // Load individual sheets for (CTSheet ctSheet : this.workbook.getSheets().getSheetArray()) { PackageRelationship rel = this.getCorePart().getRelationship(ctSheet.getId()); - PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); - PackagePart part = getPackage().getPart(relName); - if (part == null) { - throw new IllegalArgumentException("No part found for relationship " + rel); - } + PackagePart part = getPart(rel); WorksheetDocument worksheetDoc = WorksheetDocument.Factory.parse(part.getInputStream()); - XSSFSheet sheet = new XSSFSheet(ctSheet, worksheetDoc.getWorksheet()); + XSSFSheet sheet = new XSSFSheet(ctSheet, worksheetDoc.getWorksheet(), this); this.sheets.add(sheet); } } catch (XmlException e) { throw new IOException(e.toString()); } catch (InvalidFormatException e) { throw new IOException(e.toString()); -/* - } catch (OpenXML4JException e) { - throw new IOException(e.toString()); -*/ } } @@ -172,7 +181,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { if (sheetname != null) { sheet.setName(sheetname); } - XSSFSheet wrapper = new XSSFSheet(sheet); + XSSFSheet wrapper = new XSSFSheet(sheet, this); this.sheets.add(wrapper); return wrapper; } @@ -448,4 +457,12 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook { } + public SharedStringSource getSharedStringSource() { + return this.sharedStringSource; + } + + protected void setSharedStringSource(SharedStringSource sharedStringSource) { + this.sharedStringSource = sharedStringSource; + } + } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/io/TestLoadSaveXSSF.java b/src/ooxml/testcases/org/apache/poi/xssf/io/TestLoadSaveXSSF.java index 291856ccea..1c445f2b07 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/io/TestLoadSaveXSSF.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/io/TestLoadSaveXSSF.java @@ -48,6 +48,8 @@ public class TestLoadSaveXSSF extends TestCase { Cell cell = row.getCell((short) 1); assertNotNull(cell); assertEquals(111.0, cell.getNumericCellValue()); + cell = row.getCell((short) 0); + assertEquals("Lorem", cell.getRichStringCellValue().getString()); } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java index fdd3c1e1ca..2bfe164ea7 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java @@ -35,7 +35,8 @@ public class TestXSSFCell extends TestCase { * Test setting and getting boolean values. */ public void testSetGetBoolean() throws Exception { - XSSFCell cell = new XSSFCell(new XSSFRow()); + XSSFRow row = createParentObjects(); + XSSFCell cell = new XSSFCell(row); cell.setCellValue(true); assertEquals(Cell.CELL_TYPE_BOOLEAN, cell.getCellType()); assertTrue(cell.getBooleanCellValue()); @@ -54,7 +55,8 @@ public class TestXSSFCell extends TestCase { * Test setting and getting numeric values. */ public void testSetGetNumeric() throws Exception { - XSSFCell cell = new XSSFCell(new XSSFRow()); + XSSFRow row = createParentObjects(); + XSSFCell cell = new XSSFCell(row); cell.setCellValue(10d); assertEquals(Cell.CELL_TYPE_NUMERIC, cell.getCellType()); assertEquals(10d, cell.getNumericCellValue()); @@ -66,7 +68,8 @@ public class TestXSSFCell extends TestCase { * Test setting and getting numeric values. */ public void testSetGetDate() throws Exception { - XSSFCell cell = new XSSFCell(new XSSFRow()); + XSSFRow row = createParentObjects(); + XSSFCell cell = new XSSFCell(row); Date now = new Date(); cell.setCellValue(now); assertEquals(Cell.CELL_TYPE_NUMERIC, cell.getCellType()); @@ -89,7 +92,8 @@ public class TestXSSFCell extends TestCase { } public void testSetGetError() throws Exception { - XSSFCell cell = new XSSFCell(new XSSFRow()); + XSSFRow row = createParentObjects(); + XSSFCell cell = new XSSFCell(row); cell.setCellErrorValue((byte)255); assertEquals(Cell.CELL_TYPE_ERROR, cell.getCellType()); @@ -97,7 +101,8 @@ public class TestXSSFCell extends TestCase { } public void testSetGetFormula() throws Exception { - XSSFCell cell = new XSSFCell(new XSSFRow()); + XSSFRow row = createParentObjects(); + XSSFCell cell = new XSSFCell(row); String formula = "SQRT(C2^2+D2^2)"; cell.setCellFormula(formula); @@ -109,8 +114,8 @@ public class TestXSSFCell extends TestCase { public void testSetGetStringInline() throws Exception { CTCell rawCell = CTCell.Factory.newInstance(); - XSSFCell cell = new XSSFCell(new XSSFRow(), rawCell); - cell.setSharedStringSource(new DummySharedStringSource()); + XSSFRow row = createParentObjects(); + XSSFCell cell = new XSSFCell(row, rawCell); // Default is shared string mode, so have to do this explicitly rawCell.setT(STCellType.INLINE_STR); @@ -133,8 +138,8 @@ public class TestXSSFCell extends TestCase { } public void testSetGetStringShared() throws Exception { - XSSFCell cell = new XSSFCell(new XSSFRow()); - cell.setSharedStringSource(new DummySharedStringSource()); + XSSFRow row = createParentObjects(); + XSSFCell cell = new XSSFCell(row); cell.setCellValue(new XSSFRichTextString("")); assertEquals(Cell.CELL_TYPE_STRING, cell.getCellType()); @@ -149,7 +154,8 @@ public class TestXSSFCell extends TestCase { * Test that empty cells (no v element) return default values. */ public void testGetEmptyCellValue() throws Exception { - XSSFCell cell = new XSSFCell(new XSSFRow()); + XSSFRow row = createParentObjects(); + XSSFCell cell = new XSSFCell(row); cell.setCellType(Cell.CELL_TYPE_BOOLEAN); assertFalse(cell.getBooleanCellValue()); cell.setCellType(Cell.CELL_TYPE_NUMERIC); @@ -171,7 +177,7 @@ public class TestXSSFCell extends TestCase { } public void testFormatPosition() { - XSSFRow row = new XSSFRow(); + XSSFRow row = createParentObjects(); row.setRowNum(0); XSSFCell cell = new XSSFCell(row); cell.setCellNum((short) 0); @@ -185,6 +191,14 @@ public class TestXSSFCell extends TestCase { row.setRowNum(32767); assertEquals("IV32768", cell.formatPosition()); } + + private XSSFRow createParentObjects() { + XSSFWorkbook wb = new XSSFWorkbook(); + wb.setSharedStringSource(new DummySharedStringSource()); + XSSFSheet sheet = new XSSFSheet(wb); + XSSFRow row = new XSSFRow(sheet); + return row; + } public static class DummySharedStringSource implements SharedStringSource { ArrayList strs = new ArrayList(); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java index 571e0f4c77..314d49c51a 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFRow.java @@ -22,6 +22,7 @@ import java.util.Iterator; import junit.framework.TestCase; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.xssf.usermodel.TestXSSFCell.DummySharedStringSource; public class TestXSSFRow extends TestCase { @@ -30,7 +31,7 @@ public class TestXSSFRow extends TestCase { * Test adding cells to a row in various places and see if we can find them again. */ public void testAddAndIterateCells() { - XSSFRow row = new XSSFRow(); + XSSFRow row = new XSSFRow(createParentObjects()); // One cell at the beginning Cell cell1 = row.createCell((short) 1); @@ -110,7 +111,7 @@ public class TestXSSFRow extends TestCase { assertFalse(row.getFirstCellNum() == (short) 2); // Test a row without cells - XSSFRow emptyRow = new XSSFRow(); + XSSFRow emptyRow = new XSSFRow(createParentObjects()); assertEquals(-1, emptyRow.getFirstCellNum()); } @@ -167,8 +168,8 @@ public class TestXSSFRow extends TestCase { * Method that returns a row with some sample cells * @return row */ - public static XSSFRow getSampleRow() { - XSSFRow row = new XSSFRow(); + public XSSFRow getSampleRow() { + XSSFRow row = new XSSFRow(createParentObjects()); row.createCell((short) 2); row.createCell((short) 3, Cell.CELL_TYPE_NUMERIC); row.createCell((short) 4); @@ -178,4 +179,10 @@ public class TestXSSFRow extends TestCase { row.createCell((short) 100); return row; } + + private XSSFSheet createParentObjects() { + XSSFWorkbook wb = new XSSFWorkbook(); + wb.setSharedStringSource(new DummySharedStringSource()); + return new XSSFSheet(wb); + } }