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());
+
+ }
}