diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java index 67e51b950e..0470e66eeb 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java @@ -34,6 +34,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.ss.usermodel.Table; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr; +import org.apache.poi.util.Internal; import org.apache.poi.util.StringUtil; import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable; @@ -113,6 +114,10 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { out.close(); } + /** + * get the underlying CTTable XML bean + */ + @Internal public CTTable getCTTable() { return ctTable; } @@ -262,15 +267,12 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref) * * Does not track updates to underlying changes to CTTable + * To synchronize with changes to the underlying CTTable, + * call {@link #updateReferences()}. */ public CellReference getStartCellReference() { if (startCellReference==null) { - String ref = ctTable.getRef(); - if (ref != null) { - String[] boundaries = ref.split(":"); - String from = boundaries[0]; - startCellReference = new CellReference(from); - } + setCellReferences(); } return startCellReference; } @@ -280,22 +282,53 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref) * * Does not track updates to underlying changes to CTTable + * To synchronize with changes to the underlying CTTable, + * call {@link #updateReferences()}. */ public CellReference getEndCellReference() { if (endCellReference==null) { - String ref = ctTable.getRef(); - String[] boundaries = ref.split(":"); - String from = boundaries[1]; - endCellReference = new CellReference(from); + setCellReferences(); } return endCellReference; } + + /** + * @since POI 3.15 beta 3 + */ + private void setCellReferences() { + String ref = ctTable.getRef(); + if (ref != null) { + String[] boundaries = ref.split(":", 2); + String from = boundaries[0]; + String to = boundaries[1]; + startCellReference = new CellReference(from); + endCellReference = new CellReference(to); + } + } + + /** + * Clears the cached values set by {@link #getStartCellReference()} + * and {@link #getEndCellReference()}. + * The next call to {@link #getStartCellReference()} and + * {@link #getEndCellReference()} will synchronize the + * cell references with the underlying CTTable. + * Thus, {@link #updateReferences()} is inexpensive. + * + * @since POI 3.15 beta 3 + */ + public void updateReferences() { + startCellReference = null; + endCellReference = null; + } + /** * @return the total number of rows in the selection. (Note: in this version autofiltering is ignored) * * Does not track updates to underlying changes to CTTable + * To synchronize with changes to the underlying CTTable, + * call {@link #updateReferences()}. */ public int getRowCount() { CellReference from = getStartCellReference(); @@ -303,6 +336,7 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { int rowCount = -1; if (from!=null && to!=null) { + // FIXME: shouldn't this be to-from+1? rowCount = to.getRow()-from.getRow(); } return rowCount; @@ -312,6 +346,10 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { * Synchronize table headers with cell values in the parent sheet. * Headers must be in sync, otherwise Excel will display a * "Found unreadable content" message on startup. + * + * If calling both {@link #updateReferences()} and + * {@link #updateHeaders()}, {@link #updateReferences()} + * should be called first. */ public void updateHeaders() { XSSFSheet sheet = (XSSFSheet)getParent(); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java index 57ae3c221f..38edcbf6a5 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java @@ -238,4 +238,33 @@ public final class TestXSSFTable { wb.close(); } + + @Test + public void getCellReferences() { + // make sure that cached start and end cell references + // can be synchronized with the underlying CTTable + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet sh = wb.createSheet(); + XSSFTable table = sh.createTable(); + CTTable ctTable = table.getCTTable(); + ctTable.setRef("B2:E8"); + + assertEquals(new CellReference("B2"), table.getStartCellReference()); + assertEquals(new CellReference("E8"), table.getEndCellReference()); + + // At this point start and end cell reference are cached + // and may not follow changes to the underlying CTTable + ctTable.setRef("C1:M3"); + + assertEquals(new CellReference("B2"), table.getStartCellReference()); + assertEquals(new CellReference("E8"), table.getEndCellReference()); + + // Force a synchronization between CTTable and XSSFTable + // start and end cell references + table.updateReferences(); + + assertEquals(new CellReference("C1"), table.getStartCellReference()); + assertEquals(new CellReference("M3"), table.getEndCellReference()); + + } }