You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2018/02/25 17:06:19 UTC

svn commit: r1825315 - in /poi/trunk: src/examples/src/org/apache/poi/xssf/usermodel/examples/ src/ooxml/java/org/apache/poi/xssf/extractor/ src/ooxml/java/org/apache/poi/xssf/usermodel/ src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ src/ooxml/t...

Author: fanningpj
Date: Sun Feb 25 17:06:19 2018
New Revision: 1825315

URL: http://svn.apache.org/viewvc?rev=1825315&view=rev
Log:
[bug-62055] Fix XSSFImportFromXML table resize. Thanks to Leonard Kappe. This closes #99

Added:
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java   (with props)
    poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTableColumn.java   (with props)
Modified:
    poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateTable.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFImportFromXML.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java
    poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java
    poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFImportFromXML.java
    poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java
    poi/trunk/test-data/spreadsheet/CustomXMLMappings-complex-type.xlsx

Modified: poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateTable.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateTable.java?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
--- poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateTable.java (original)
+++ poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateTable.java Sun Feb 25 17:06:19 2018
@@ -75,9 +75,9 @@ public class CreateTable {
                 }
             }
             // Create the columns
-            table.addColumn();
-            table.addColumn();
-            table.addColumn();
+            table.createColumn("Column 1");
+            table.createColumn("Column 2");
+            table.createColumn("Column 3");
 
             // Set which area the table should be placed in
             AreaReference reference = wb.getCreationHelper().createAreaReference(

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java Sun Feb 25 17:06:19 2018
@@ -50,9 +50,9 @@ import org.apache.poi.xssf.usermodel.XSS
 import org.apache.poi.xssf.usermodel.XSSFRow;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.apache.poi.xssf.usermodel.XSSFTable;
+import org.apache.poi.xssf.usermodel.XSSFTableColumn;
 import org.apache.poi.xssf.usermodel.helpers.XSSFSingleXmlCell;
 import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
@@ -175,35 +175,27 @@ public class XSSFExportToXml implements
                 // Exports elements and attributes mapped with tables
                 if (table!=null) {
 
-                    List<CTTableColumn> tableColumns = table.getCTTable().getTableColumns().getTableColumnList();
+                    List<XSSFTableColumn> tableColumns = table.getColumns();
 
                     XSSFSheet sheet = table.getXSSFSheet();
 
-                    int startRow = table.getStartCellReference().getRow();
-                    // In mappings created with Microsoft Excel the first row contains the table header and must be skipped
-                    startRow +=1;
-
+                    int startRow = table.getStartCellReference().getRow() + table.getHeaderRowCount();
                     int endRow = table.getEndCellReference().getRow();
 
                     for(int i = startRow; i<= endRow; i++) {
                         XSSFRow row = sheet.getRow(i);
 
-                        Node tableRootNode = getNodeByXPath(table.getCommonXpath(),doc.getFirstChild(),doc,true);
+                        Node tableRootNode = getNodeByXPath(table.getCommonXpath(), doc.getFirstChild(), doc, true);
 
                         short startColumnIndex = table.getStartCellReference().getCol();
-                        for (int j = startColumnIndex; j <= table.getEndCellReference().getCol(); j++) {
-                            XSSFCell cell = row.getCell(j);
+                        for (XSSFTableColumn tableColumn : tableColumns) {
+                            XSSFCell cell = row.getCell(startColumnIndex + tableColumn.getColumnIndex());
                             if (cell != null) {
-                                int tableColumnIndex = j - startColumnIndex;
-                                if (tableColumnIndex < tableColumns.size()) { 
-                                    CTTableColumn ctTableColumn = tableColumns.get(tableColumnIndex);
-                                    if (ctTableColumn.getXmlColumnPr() != null) {
-                                        XSSFXmlColumnPr pointer = new XSSFXmlColumnPr(table, ctTableColumn,
-                                                ctTableColumn.getXmlColumnPr());
-                                        String localXPath = pointer.getLocalXPath();
-                                        Node currentNode = getNodeByXPath(localXPath,tableRootNode,doc,false);
-                                        mapCellOnNode(cell,currentNode);
-                                    }
+                                XSSFXmlColumnPr xmlColumnPr = tableColumn.getXmlColumnPr();
+                                if (xmlColumnPr != null) {
+                                    String localXPath = xmlColumnPr.getLocalXPath();
+                                    Node currentNode = getNodeByXPath(localXPath,tableRootNode,doc,false);
+                                    mapCellOnNode(cell, currentNode);
                                 }
                             }
                         }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFImportFromXML.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFImportFromXML.java?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFImportFromXML.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFImportFromXML.java Sun Feb 25 17:06:19 2018
@@ -47,6 +47,7 @@ import org.apache.poi.xssf.usermodel.XSS
 import org.apache.poi.xssf.usermodel.XSSFMap;
 import org.apache.poi.xssf.usermodel.XSSFRow;
 import org.apache.poi.xssf.usermodel.XSSFTable;
+import org.apache.poi.xssf.usermodel.XSSFTableColumn;
 import org.apache.poi.xssf.usermodel.helpers.XSSFSingleXmlCell;
 import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXmlDataType;
@@ -124,25 +125,32 @@ public class XSSFImportFromXML {
 
             String commonXPath = table.getCommonXpath();
             NodeList result = (NodeList) xpath.evaluate(commonXPath, doc, XPathConstants.NODESET);
-            int rowOffset = table.getStartCellReference().getRow() + 1;// the first row contains the table header
-            int columnOffset = table.getStartCellReference().getCol() - 1;
+            int rowOffset = table.getStartCellReference().getRow() + table.getHeaderRowCount();
+            int columnOffset = table.getStartCellReference().getCol();
+
+            table.setDataRowCount(result.getLength());
 
             for (int i = 0; i < result.getLength(); i++) {
 
                 // TODO: implement support for denormalized XMLs (see
                 // OpenOffice part 4: chapter 3.5.1.7)
 
-            	Node singleNode = result.item(i).cloneNode(true);
-                for (XSSFXmlColumnPr xmlColumnPr : table.getXmlColumnPrs()) {
+                Node singleNode = result.item(i).cloneNode(true);
+
+                for (XSSFTableColumn tableColum : table.getColumns()) {
+
+                    XSSFXmlColumnPr xmlColumnPr = tableColum.getXmlColumnPr();
+                    if(xmlColumnPr == null) {
+                        continue;
+                    }
 
-                    int localColumnId = (int) xmlColumnPr.getId();
                     int rowId = rowOffset + i;
-                    int columnId = columnOffset + localColumnId;
+                    int columnId = columnOffset + tableColum.getColumnIndex();
                     String localXPath = xmlColumnPr.getLocalXPath();
-                    localXPath = localXPath.substring(localXPath.substring(1).indexOf('/') + 2);
+                    localXPath = localXPath.substring(localXPath.indexOf('/', 1) + 1);
 
                     // TODO: convert the data to the cell format
-					String value = (String) xpath.evaluate(localXPath, singleNode, XPathConstants.STRING);
+                    String value = (String) xpath.evaluate(localXPath, singleNode, XPathConstants.STRING);
                     logger.log(POILogger.DEBUG, "Extracting with xpath " + localXPath + " : value is '" + value + "'");
                     XSSFRow row = table.getXSSFSheet().getRow(rowId);
                     if (row == null) {
@@ -161,6 +169,8 @@ public class XSSFImportFromXML {
         }
     }
 
+    
+
     private static enum DataType {
         BOOLEAN(STXmlDataType.BOOLEAN), //
         DOUBLE(STXmlDataType.DOUBLE), //

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java Sun Feb 25 17:06:19 2018
@@ -80,6 +80,7 @@ import org.apache.poi.util.Beta;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
+import org.apache.poi.util.Removal;
 import org.apache.poi.util.Units;
 import org.apache.poi.xssf.model.CommentsTable;
 import org.apache.poi.xssf.usermodel.XSSFPivotTable.PivotTableReferenceConfigurator;
@@ -4057,10 +4058,28 @@ public class XSSFSheet extends POIXMLDoc
     }
 
     /**
-     * Creates a new Table, and associates it with this Sheet
+     * Creates a new Table, and associates it with this Sheet. The table does
+     * not yet have an area defined and needs to be initialized by calling
+     * {@link XSSFTable#setArea(AreaReference)}.
+     * 
+     * @deprecated Use {@link #createTable(AreaReference))} instead
      */
+    @Deprecated
+    @Removal(version = "4.2.0")
     public XSSFTable createTable() {
-        if(! worksheet.isSetTableParts()) {
+        return createTable(null);
+    }
+    
+    /**
+     * Creates a new Table, and associates it with this Sheet.
+     *
+     * @param tableArea
+     *            the area that the table should cover, should not be {@null}
+     * @return the created table
+     * @since 4.0.0
+     */
+    public XSSFTable createTable(AreaReference tableArea) {
+        if (!worksheet.isSetTableParts()) {
             worksheet.addNewTableParts();
         }
 
@@ -4093,6 +4112,10 @@ public class XSSFSheet extends POIXMLDoc
 
         tables.put(tbl.getId(), table);
 
+        if(tableArea != null) {
+            table.setArea(tableArea);
+        }
+        
         return table;
     }
 

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java Sun Feb 25 17:06:19 2018
@@ -24,6 +24,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -32,12 +33,14 @@ import org.apache.poi.POIXMLDocumentPart
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.ss.SpreadsheetVersion;
 import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.ss.usermodel.DataFormatter;
 import org.apache.poi.ss.usermodel.Table;
 import org.apache.poi.ss.usermodel.TableStyleInfo;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.Internal;
+import org.apache.poi.util.Removal;
 import org.apache.poi.util.StringUtil;
 import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr;
 import org.apache.xmlbeans.XmlException;
@@ -48,12 +51,12 @@ import org.openxmlformats.schemas.spread
 
 /**
  * 
- * This class implements the Table Part (Open Office XML Part 4:
- * chapter 3.5.1)
+ * This class implements the Table Part (Open Office XML Part 4: chapter 3.5.1)
  * 
- * This implementation works under the assumption that a table contains mappings to a subtree of an XML.
- * The root element of this subtree an occur multiple times (one for each row of the table). The child nodes
- * of the root element can be only attributes or element with maxOccurs=1 property set
+ * Columns of this table may contains mappings to a subtree of an XML. The root
+ * element of this subtree can occur multiple times (one for each row of the
+ * table). The child nodes of the root element can be only attributes or
+ * elements with maxOccurs=1 property set.
  * 
  *
  * @author Roberto Manicardi
@@ -61,8 +64,8 @@ import org.openxmlformats.schemas.spread
 public class XSSFTable extends POIXMLDocumentPart implements Table {
 
     private CTTable ctTable;
-    private transient List<XSSFXmlColumnPr> xmlColumnPr;
-    private transient CTTableColumn[] ctColumns;
+    private transient List<XSSFXmlColumnPr> xmlColumnPrs;
+    private transient List<XSSFTableColumn> tableColumns;
     private transient HashMap<String, Integer> columnMap;
     private transient CellReference startCellReference;
     private transient CellReference endCellReference;    
@@ -155,18 +158,6 @@ public class XSSFTable extends POIXMLDoc
         
         return false;
     }
-
-    /**
-      * caches table columns for performance.
-      * Updated via updateHeaders
-      * @since 3.15 beta 2
-      */
-    private CTTableColumn[] getTableColumns() {
-        if (ctColumns == null) {
-            ctColumns = ctTable.getTableColumns().getTableColumnArray();
-        }
-        return ctColumns;
-    }
     
     /**
      * 
@@ -179,9 +170,9 @@ public class XSSFTable extends POIXMLDoc
     public String getCommonXpath() {
         if (commonXPath == null) {
             String[] commonTokens = {};
-            for (CTTableColumn column : getTableColumns()) {
+            for (XSSFTableColumn column : getColumns()) {
                 if (column.getXmlColumnPr()!=null) {
-                    String xpath = column.getXmlColumnPr().getXpath();
+                    String xpath = column.getXmlColumnPr().getXPath();
                     String[] tokens =  xpath.split("/");
                     if (commonTokens.length==0) {
                         commonTokens = tokens;
@@ -210,45 +201,166 @@ public class XSSFTable extends POIXMLDoc
         return commonXPath;
     }
 
+    /**
+     * Note this list is static - once read, it does not notice later changes to the underlying column structures
+     * To clear the cache, call {@link #updateHeaders}
+     * @return List of XSSFTableColumn
+     * @since 4.0.0
+     */
+    public List<XSSFTableColumn> getColumns() {
+        if (tableColumns == null) {
+           List<XSSFTableColumn> columns = new ArrayList<>();
+            CTTableColumns ctTableColumns = ctTable.getTableColumns();
+            if (ctTableColumns != null) {
+                for (CTTableColumn column : ctTableColumns.getTableColumnList()) {
+                    XSSFTableColumn tableColumn = new XSSFTableColumn(this, column);
+                    columns.add(tableColumn);
+                }
+            }
+            tableColumns = Collections.unmodifiableList(columns);
+        }
+        return tableColumns;
+    }
     
     /**
      * Note this list is static - once read, it does not notice later changes to the underlying column structures
      * To clear the cache, call {@link #updateHeaders}
+     * 
+     * @deprecated Use {@link XSSFTableColumn#getXmlColumnPr()} instead.
+     * 
      * @return List of XSSFXmlColumnPr
      */
+    @Deprecated
+    @Removal(version="4.2.0")
     public List<XSSFXmlColumnPr> getXmlColumnPrs() {
-        if (xmlColumnPr==null) {
-            xmlColumnPr = new ArrayList<>();
-            for (CTTableColumn column: getTableColumns()) {
-                if (column.getXmlColumnPr()!=null) {
-                    XSSFXmlColumnPr columnPr = new XSSFXmlColumnPr(this,column,column.getXmlColumnPr());
-                    xmlColumnPr.add(columnPr);
+        if (xmlColumnPrs == null) {
+            xmlColumnPrs = new ArrayList<>();
+            for (XSSFTableColumn column: getColumns()) {
+                XSSFXmlColumnPr xmlColumnPr = column.getXmlColumnPr();
+                if (xmlColumnPr != null) {
+                    xmlColumnPrs.add(xmlColumnPr);
                 }
             }
         }
-        return xmlColumnPr;
+        return xmlColumnPrs;
     }
     
     /**
-     * Adds another column to the table.
+     * Add a new column to the right end of the table.
      * 
-     * Warning - Return type likely to change!
+     * @param columnName
+     *            the unique name of the column, must not be {@code null}
+     * @return the created table column
+     * @since 4.0.0
      */
-    @Internal("Return type likely to change")
-    public void addColumn() {
+    public XSSFTableColumn createColumn(String columnName) {
+        return createColumn(columnName, getColumnCount());
+    }
+    
+    /**
+     * Adds a new column to the table.
+     * 
+     * @param columnName
+     *            the unique name of the column, or {@code null} for a generated name
+     * @param columnIndex
+     *            the 0-based position of the column in the table
+     * @return the created table column
+     * @throws IllegalArgumentException
+     *             if the column name is not unique or missing or if the column
+     *             can't be created at the given index
+     * @since 4.0.0
+     */
+    public XSSFTableColumn createColumn(String columnName, int columnIndex) {
+                
+        int columnCount = getColumnCount();
+        if(columnIndex < 0 || columnIndex > columnCount) {
+            throw new IllegalArgumentException("Column index out of bounds");
+        }
+        
         // Ensure we have Table Columns
         CTTableColumns columns = ctTable.getTableColumns();
         if (columns == null) {
             columns = ctTable.addNewTableColumns();
         }
         
-        // Add another Column, and give it a sensible ID
-        CTTableColumn column = columns.addNewTableColumn();
-        int num = columns.sizeOfTableColumnArray();
-        columns.setCount(num);
-        column.setId(num);
+        // check if name is unique and calculate unique column id 
+        long nextColumnId = 1; 
+        for (XSSFTableColumn tableColumn : getColumns()) {
+            if (columnName != null && columnName.equalsIgnoreCase(tableColumn.getName())) {
+                throw new IllegalArgumentException("Column '" + columnName
+                        + "' already exists. Column names must be unique per table.");
+            }
+            nextColumnId = Math.max(nextColumnId, tableColumn.getId());
+        }
+        
+        // Add the new Column
+        CTTableColumn column = columns.insertNewTableColumn(columnIndex);
+        columns.setCount(columns.sizeOfTableColumnArray());
+        
+        column.setId(nextColumnId);
+        if(columnName != null) {
+            column.setName(columnName); 
+        } else {
+            column.setName("Column " + nextColumnId);
+        }
+        
+        if (ctTable.getRef() != null) {
+            // calculate new area
+            int newColumnCount = columnCount + 1;
+            CellReference tableStart = getStartCellReference();
+            CellReference tableEnd = getEndCellReference();
+            SpreadsheetVersion version = getXSSFSheet().getWorkbook().getSpreadsheetVersion();
+            CellReference newTableEnd = new CellReference(tableEnd.getRow(),
+                    tableStart.getCol() + newColumnCount - 1);
+            AreaReference newTableArea = new AreaReference(tableStart, newTableEnd, version);
+
+            setCellRef(newTableArea);
+        }
+        
+        updateHeaders();
+        
+        return getColumns().get(columnIndex);
+    }
+    
+    /**
+     * Remove a column from the table.
+     *
+     * @param column
+     *            the column to remove
+     * @since 4.0.0
+     */
+    public void removeColumn(XSSFTableColumn column) {
+        int columnIndex = getColumns().indexOf(column);
+        if (columnIndex >= 0) {
+            ctTable.getTableColumns().removeTableColumn(columnIndex);
+            updateReferences();
+            updateHeaders();
+        }
+    }
+    
+    /**
+     * Remove a column from the table.
+     *
+     * @param columnIndex
+     *            the 0-based position of the column in the table
+     * @throws IllegalArgumentException
+     *             if no column at the index exists or if the table has only a
+     *             single column
+     * @since 4.0.0
+     */
+    public void removeColumn(int columnIndex) {
+        if (columnIndex < 0 || columnIndex > getColumnCount() - 1) {
+            throw new IllegalArgumentException("Column index out of bounds");
+        }
+        
+        if(getColumnCount() == 1) {
+            throw new IllegalArgumentException("Table must have at least one column");
+        }
         
-        // Have the Headers updated if possible
+        CTTableColumns tableColumns = ctTable.getTableColumns();
+        tableColumns.removeTableColumn(columnIndex);
+        tableColumns.setCount(tableColumns.getTableColumnList().size());
+        updateReferences();
         updateHeaders();
     }
     
@@ -323,20 +435,25 @@ public class XSSFTable extends POIXMLDoc
     }
 
     /**
+     * @deprecated Use {@link #getColumnCount()} instead.
+     * 
      * @return  the number of mapped table columns (see Open Office XML Part 4: chapter 3.5.1.4)
      */
+    @Deprecated
+    @Removal(version = "4.2.0")
     public long getNumberOfMappedColumns() {
         return ctTable.getTableColumns().getCount();
     }
 
     /**
-     * @return The reference for the cells of the table
-     * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref) 
+     * Get the area reference for the cells which this table covers. The area
+     * includes header rows and totals rows.
      *
-     * Does not track updates to underlying changes to CTTable
-     * To synchronize with changes to the underlying CTTable,
-     * call {@link #updateReferences()}.
+     * Does not track updates to underlying changes to CTTable To synchronize
+     * with changes to the underlying CTTable, call {@link #updateReferences()}.
      * 
+     * @return the area of the table
+     * @see "Open Office XML Part 4: chapter 3.5.1.2, attribute ref"
      * @since 3.17 beta 1
      */
     public AreaReference getCellReferences() {
@@ -346,16 +463,35 @@ public class XSSFTable extends POIXMLDoc
                 SpreadsheetVersion.EXCEL2007
         );
     }
+    
     /**
-     * Updates the reference for the cells of the table
-     * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref)
-     * and synchronizes any changes
-     * @param refs table range
+     * Set the area reference for the cells which this table covers. The area
+     * includes includes header rows and totals rows. Automatically synchronizes
+     * any changes by calling {@link #updateHeaders()}.
+     * 
+     * Note: The area's width should be identical to the amount of columns in
+     * the table or the table may be invalid. All header rows, totals rows and
+     * at least one data row must fit inside the area. Updating the area with
+     * this method does not create or remove any columns and does not change any
+     * cell values.
+     * 
+     * @deprecated Use {@link #setTableArea} instead, which will ensure that the
+     *             the amount of columns always matches table area always width.
      * 
+     * @see "Open Office XML Part 4: chapter 3.5.1.2, attribute ref"
      * @since 3.17 beta 1
      */
+    @Deprecated
+    @Removal(version="4.2.0")
     public void setCellReferences(AreaReference refs) {
-        // Strip the Sheet name
+        setCellRef(refs);
+    }
+    
+    @Internal
+    protected void setCellRef(AreaReference refs) {
+        
+        // Strip the sheet name,
+        // CTWorksheet.getTableParts defines in which sheet the table is
         String ref = refs.formatAsString();
         if (ref.indexOf('!') != -1) {
             ref = ref.substring(ref.indexOf('!')+1);
@@ -384,6 +520,87 @@ public class XSSFTable extends POIXMLDoc
     }
     
     /**
+     * Set the area reference for the cells which this table covers. The area
+     * includes includes header rows and totals rows.
+     * 
+     * Updating the area with this method will create new column as necessary to
+     * the right side of the table but will not modify any cell values.
+     * 
+     * @param refs
+     *            the new area of the table
+     * @throws IllegalArgumentException
+     *             if the area is {@code null} or not
+     * @since 4.0.0
+     */
+    public void setArea(AreaReference tableArea) {
+
+        if (tableArea == null) {
+            throw new IllegalArgumentException("AreaReference must not be null");
+        }
+        
+        String areaSheetName = tableArea.getFirstCell().getSheetName();
+        if (areaSheetName != null && !areaSheetName.equals(getXSSFSheet().getSheetName())) {
+            // TODO to move a table from one sheet to another
+            // CTWorksheet.getTableParts needs to be updated on both sheets
+            throw new IllegalArgumentException(
+                    "The AreaReference must not reference a different sheet");
+        }
+        
+        int rowCount = (tableArea.getLastCell().getRow() - tableArea.getFirstCell().getRow()) + 1;
+        int minimumRowCount = 1 + getHeaderRowCount() + getTotalsRowCount();
+        if (rowCount < minimumRowCount) {
+            throw new IllegalArgumentException("AreaReference needs at least " + minimumRowCount
+                    + " rows, to cover at least one data row and all header rows and totals rows");
+        }
+
+        // Strip the sheet name,
+        // CTWorksheet.getTableParts defines in which sheet the table is
+        String ref = tableArea.formatAsString();
+        if (ref.indexOf('!') != -1) {
+            ref = ref.substring(ref.indexOf('!') + 1);
+        }
+
+        // Update
+        ctTable.setRef(ref);
+        if (ctTable.isSetAutoFilter()) {
+            ctTable.getAutoFilter().setRef(ref);
+        }
+        updateReferences();
+
+        // add or remove columns on the right side of the table
+        int columnCount = getColumnCount();
+        int newColumnCount = (tableArea.getLastCell().getCol() - tableArea.getFirstCell().getCol()) + 1;
+        if (newColumnCount > columnCount) {
+            for (int i = columnCount; i < newColumnCount; i++) {
+                createColumn(null, i);
+            }
+        } else if (newColumnCount < columnCount) {
+            for (int i = columnCount; i > newColumnCount; i--) {
+                removeColumn(i -1);
+            }
+        }
+
+        updateHeaders();
+    }
+    
+    /**
+     * Get the area that this table covers.
+     *
+     * @return the table's area or {@code null} if the area has not been
+     *         initialized
+     * @since 4.0.0
+     */
+    public AreaReference getArea() {
+        String ref = ctTable.getRef();
+        if (ref != null) {
+            SpreadsheetVersion version = getXSSFSheet().getWorkbook().getSpreadsheetVersion();
+            return new AreaReference(ctTable.getRef(), version);
+        } else {
+            return null;
+        }
+    }
+    
+    /**
      * @return The reference for the cell in the top-left part of the table
      * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref) 
      *
@@ -445,12 +662,17 @@ public class XSSFTable extends POIXMLDoc
 
     
     /**
-     * @return the total number of rows in the selection. (Note: in this version autofiltering is ignored)
+     * Get the total number of rows in this table, including all
+     * {@linkplain #getHeaderRowCount() header rows} and all
+     * {@linkplain #getTotalsRowCount() totals rows}. (Note: in this version
+     * autofiltering is ignored)
+     * 
      * Returns <code>0</code> if the start or end cell references are not set.
      * 
-     * Does not track updates to underlying changes to CTTable
-     * To synchronize with changes to the underlying CTTable,
-     * call {@link #updateReferences()}.
+     * Does not track updates to underlying changes to CTTable To synchronize
+     * with changes to the underlying CTTable, call {@link #updateReferences()}.
+     * 
+     * @return the total number of rows
      */
     public int getRowCount() {
         CellReference from = getStartCellReference();
@@ -462,6 +684,117 @@ public class XSSFTable extends POIXMLDoc
         }
         return rowCount;
     }
+    
+    /**
+     * Get the number of data rows in this table. This does not include any
+     * header rows or totals rows.
+     * 
+     * Returns <code>0</code> if the start or end cell references are not set.
+     * 
+     * Does not track updates to underlying changes to CTTable To synchronize
+     * with changes to the underlying CTTable, call {@link #updateReferences()}.
+     * 
+     * @return the number of data rows
+     * @since 4.0.0
+     */
+    public int getDataRowCount() {
+        CellReference from = getStartCellReference();
+        CellReference to = getEndCellReference();
+
+        int rowCount = 0;
+        if (from != null && to != null) {
+            rowCount = (to.getRow() - from.getRow() + 1) - getHeaderRowCount()
+                    - getTotalsRowCount();
+        }
+        return rowCount;
+    }
+
+    /**
+     * Set the number of rows in the data area of the table. This does not
+     * affect any header rows or totals rows.
+     * 
+     * If the new row count is less than the current row count, superfluous rows
+     * will be cleared. If the new row count is greater than the current row
+     * count, cells below the table will be overwritten by the table.
+     * 
+     * To resize the table without overwriting cells, use
+     * {@link #setArea(AreaReference)} instead.
+     *
+     * @param newDataRowCount
+     *            new row count for the table
+     * @throws IllegalArgumentException
+     *             if the row count is less than 1
+     * @since 4.0.0
+     */
+    public void setDataRowCount(int newDataRowCount) {
+
+        if (newDataRowCount < 1) {
+            throw new IllegalArgumentException("Table must have at least one data row");
+        }
+
+        updateReferences();
+        int dataRowCount = getDataRowCount();
+        if (dataRowCount == newDataRowCount) {
+            return;
+        }
+
+        CellReference tableStart = getStartCellReference();
+        CellReference tableEnd = getEndCellReference();
+        SpreadsheetVersion version = getXSSFSheet().getWorkbook().getSpreadsheetVersion();
+
+        // calculate new area
+        int newTotalRowCount = getHeaderRowCount() + newDataRowCount + getTotalsRowCount();
+        CellReference newTableEnd = new CellReference(tableStart.getRow() + newTotalRowCount - 1,
+                tableEnd.getCol());
+        AreaReference newTableArea = new AreaReference(tableStart, newTableEnd, version);
+
+        // clear cells
+        CellReference clearAreaStart;
+        CellReference clearAreaEnd;
+        if (newDataRowCount < dataRowCount) {
+            // table size reduced -
+            // clear all table cells that are outside of the new area
+            clearAreaStart = new CellReference(newTableArea.getLastCell().getRow() + 1,
+                    newTableArea.getFirstCell().getCol());
+            clearAreaEnd = tableEnd;
+        } else {
+            // table size increased -
+            // clear all cells below the table that are inside the new area
+            clearAreaStart = new CellReference(tableEnd.getRow() + 1,
+                    newTableArea.getFirstCell().getCol());
+            clearAreaEnd = newTableEnd;
+        }
+        AreaReference areaToClear = new AreaReference(clearAreaStart, clearAreaEnd, version);
+        for (CellReference cellRef : areaToClear.getAllReferencedCells()) {
+            XSSFRow row = getXSSFSheet().getRow(cellRef.getRow());
+            if (row != null) {
+                XSSFCell cell = row.getCell(cellRef.getCol());
+                if (cell != null) {
+                    cell.setCellType(CellType.BLANK);
+                    cell.setCellStyle(null);
+                }
+            }
+        }
+
+        // update table area
+        setCellRef(newTableArea);
+    }
+
+    /**
+     * Get the total number of columns in this table.
+     *
+     * @return the column count
+     * @since 4.0.0
+     */
+    public int getColumnCount() {
+        CTTableColumns tableColumns = ctTable.getTableColumns();
+        if(tableColumns == null) {
+            return 0;
+        }
+        // Casting to int should be safe here - tables larger than the
+        // sheet (which holds the actual data of the table) can't exists.
+        return (int) tableColumns.getCount();
+    }
 
     /**
      * Synchronize table headers with cell values in the parent sheet.
@@ -479,7 +812,7 @@ public class XSSFTable extends POIXMLDoc
     public void updateHeaders() {
         XSSFSheet sheet = (XSSFSheet)getParent();
         CellReference ref = getStartCellReference();
-        if(ref == null) return;
+        if (ref == null) return;
 
         int headerRow = ref.getRow();
         int firstHeaderColumn = ref.getCol();
@@ -488,18 +821,21 @@ public class XSSFTable extends POIXMLDoc
 
         if (row != null && row.getCTRow().validate()) {
             int cellnum = firstHeaderColumn;
-            for (CTTableColumn col : getCTTable().getTableColumns().getTableColumnList()) {
-                XSSFCell cell = row.getCell(cellnum);
-                if (cell != null) {
-                    col.setName(formatter.formatCellValue(cell));
+            CTTableColumns ctTableColumns = getCTTable().getTableColumns();
+            if(ctTableColumns != null) {
+                for (CTTableColumn col : ctTableColumns.getTableColumnList()) {
+                    XSSFCell cell = row.getCell(cellnum);
+                    if (cell != null) {
+                        col.setName(formatter.formatCellValue(cell));
+                    }
+                    cellnum++;
                 }
-                cellnum++;
             }
-            ctColumns = null;
-            columnMap = null;
-            xmlColumnPr = null;
-            commonXPath = null;
         }
+        tableColumns = null;
+        columnMap = null;
+        xmlColumnPrs = null;
+        commonXPath = null;
     }
 
     private static String caseInsensitive(String s) {
@@ -522,11 +858,11 @@ public class XSSFTable extends POIXMLDoc
         if (columnHeader == null) return -1;
         if (columnMap == null) {
             // FIXME: replace with org.apache.commons.collections.map.CaseInsensitiveMap
-            final int count = getTableColumns().length;
+            final int count = getColumnCount();
             columnMap = new HashMap<>(count * 3 / 2);
             
             int i = 0;
-            for (CTTableColumn column : getTableColumns()) {
+            for (XSSFTableColumn column : getColumns()) {
                 String columnName = column.getName();
                 columnMap.put(caseInsensitive(columnName), i);
                 i++;

Added: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java?rev=1825315&view=auto
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java (added)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java Sun Feb 25 17:06:19 2018
@@ -0,0 +1,134 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import org.apache.poi.util.Internal;
+import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlColumnPr;
+
+/**
+ * A table column of an {@link XSSFTable}. Use {@link XSSFTable#createColumn} to
+ * create new table columns.
+ * 
+ * @author Leonard Kappe
+ * @since 4.0.0
+ */
+public class XSSFTableColumn {
+
+    private final XSSFTable table;
+    private final CTTableColumn ctTableColumn;
+    private XSSFXmlColumnPr xmlColumnPr;
+
+    /**
+     * Create a new table column.
+     *
+     * @param table
+     *            the table which contains the column
+     * @param ctTableColumn
+     *            the table column xmlbean to wrap
+     * @since 4.0.0
+     */
+    @Internal
+    protected XSSFTableColumn(XSSFTable table, CTTableColumn ctTableColumn) {
+        this.table = table;
+        this.ctTableColumn = ctTableColumn;
+    }
+
+    /**
+     * Get the table which contains this column
+     *
+     * @return the table containing this column
+     * @since 4.0.0
+     */
+    public XSSFTable getTable() {
+        return table;
+    }
+
+    /**
+     * Get the identifier of this column, which is is unique per table.
+     * 
+     * @return the column id
+     * @since 4.0.0
+     */
+    public long getId() {
+        return ctTableColumn.getId();
+    }
+
+    /**
+     * Set the identifier of this column, which must be unique per table.
+     * 
+     * It is up to the caller to enforce the uniqueness of the id.
+     * 
+     * @return the column id
+     * @since 4.0.0
+     */
+    public void setId(long columnId) {
+        ctTableColumn.setId(columnId);
+    }
+
+    /**
+     * Get the name of the column, which is is unique per table.
+     * 
+     * @return the column name
+     * @since 4.0.0
+     */
+    public String getName() {
+        return ctTableColumn.getName();
+    }
+
+    /**
+     * Get the name of the column, which is is unique per table.
+     * 
+     * @return the column name
+     * @since 4.0.0
+     */
+    public void setName(String columnName) {
+        ctTableColumn.setName(columnName);
+    }
+
+    /**
+     * Get the XmlColumnPr (XML column properties) if this column has an XML
+     * mapping.
+     *
+     * @return the XmlColumnPr or <code>null</code> if this column has no XML
+     *         mapping
+     * @since 4.0.0
+     */
+    public XSSFXmlColumnPr getXmlColumnPr() {
+        if (xmlColumnPr == null) {
+            CTXmlColumnPr ctXmlColumnPr = ctTableColumn.getXmlColumnPr();
+            if (ctXmlColumnPr != null) {
+                xmlColumnPr = new XSSFXmlColumnPr(this, ctXmlColumnPr);
+            }
+        }
+        return xmlColumnPr;
+    }
+
+    /**
+     * Get the column's position in its table, staring with zero from left to
+     * right.
+     *
+     * @return the column index
+     * @since 4.0.0
+     */
+    public int getColumnIndex() {
+        return table.findColumnIndex(getName());
+    }
+
+}

Propchange: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java Sun Feb 25 17:06:19 2018
@@ -17,12 +17,14 @@
 
 package org.apache.poi.xssf.usermodel.helpers;
 
+import org.apache.poi.util.Internal;
+import org.apache.poi.util.Removal;
 import org.apache.poi.xssf.usermodel.XSSFTable;
+import org.apache.poi.xssf.usermodel.XSSFTableColumn;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlColumnPr;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXmlDataType.Enum;
 
-
 /**
  * 
  * This class is a wrapper around the CTXmlColumnPr (Open Office XML Part 4:
@@ -32,56 +34,85 @@ import org.openxmlformats.schemas.spread
  * @author Roberto Manicardi
  */
 public class XSSFXmlColumnPr {
-	
-	private XSSFTable table;
-	private CTTableColumn ctTableColumn;
-	private CTXmlColumnPr ctXmlColumnPr;
-	
-	public XSSFXmlColumnPr(XSSFTable table ,CTTableColumn ctTableColum,CTXmlColumnPr ctXmlColumnPr){
-		this.table = table;
-		this.ctTableColumn = ctTableColum;
-		this.ctXmlColumnPr = ctXmlColumnPr;
-	}
-	
-	public long getMapId(){
-		return ctXmlColumnPr.getMapId();
-	}
-	
-	public String getXPath(){
-		return ctXmlColumnPr.getXpath();
-	}
-	/**
-	 * (see Open Office XML Part 4: chapter 3.5.1.3)
-	 * @return An integer representing the unique identifier of this column. 
-	 */
-	public long getId(){
-		return ctTableColumn.getId();
-	}
-	
-	
-	/**
-	 * If the XPath is, for example, /Node1/Node2/Node3 and /Node1/Node2 is the common XPath for the table, the local XPath is /Node3
-	 * 	
-	 * @return the local XPath 
-	 */
-	public String getLocalXPath(){
-		StringBuilder localXPath = new StringBuilder();
-		int numberOfCommonXPathAxis = table.getCommonXpath().split("/").length-1;
-		
-		String[] xPathTokens = ctXmlColumnPr.getXpath().split("/");
-		for(int i=numberOfCommonXPathAxis; i<xPathTokens.length;i++){
-			localXPath.append("/" +xPathTokens[i]);
-		}
-		return localXPath.toString();
-	}
-
-	public Enum getXmlDataType() {
-		
-		return ctXmlColumnPr.getXmlDataType();
-	}
-	
-	
-	
-	
+
+    private XSSFTable table;
+    private XSSFTableColumn tableColumn;
+    private CTXmlColumnPr ctXmlColumnPr;
+
+    /**
+     * Create a new XSSFXmlColumnPr (XML column properties) wrapper around a
+     * CTXmlColumnPr.
+     *
+     * @param tableColumn
+     *            table column for which the XML column properties are set
+     * @param ctXmlColumnPr
+     *            the XML column properties xmlbean to wrap
+     */
+    @Internal
+    public XSSFXmlColumnPr(XSSFTableColumn tableColumn, CTXmlColumnPr ctXmlColumnPr) {
+        this.table = tableColumn.getTable();
+        this.tableColumn = tableColumn;
+        this.ctXmlColumnPr = ctXmlColumnPr;
+    }
+
+    @Deprecated
+    @Removal(version="4.2")
+    public XSSFXmlColumnPr(XSSFTable table, CTTableColumn ctTableColum, CTXmlColumnPr ctXmlColumnPr) {
+        this.table = table;
+        this.tableColumn = table.getColumns().get(table.findColumnIndex(ctTableColum.getName()));
+        this.ctXmlColumnPr = ctXmlColumnPr;
+    }
+
+    /**
+     * Get the column for which these XML column properties are set.
+     *
+     * @return the table column
+     * @since 4.0.0
+     */
+    public XSSFTableColumn getTableColumn() {
+        return tableColumn;
+    }
+
+    public long getMapId() {
+        return ctXmlColumnPr.getMapId();
+    }
+
+    public String getXPath() {
+        return ctXmlColumnPr.getXpath();
+    }
+
+    /**
+     * (see Open Office XML Part 4: chapter 3.5.1.3)
+     * 
+     * @deprecated Use {@link XSSFTableColumn#getId()} instead.
+     * 
+     * @return An integer representing the unique identifier of this column.
+     */
+    @Deprecated
+    @Removal(version="4.2")
+    public long getId() {
+        return tableColumn.getId();
+    }
+
+    /**
+     * If the XPath is, for example, /Node1/Node2/Node3 and /Node1/Node2 is the common XPath for the table, the local XPath is /Node3
+     * 
+     * @return the local XPath
+     */
+    public String getLocalXPath() {
+        StringBuilder localXPath = new StringBuilder();
+        int numberOfCommonXPathAxis = table.getCommonXpath().split("/").length-1;
+
+        String[] xPathTokens = ctXmlColumnPr.getXpath().split("/");
+        for (int i = numberOfCommonXPathAxis; i < xPathTokens.length; i++) {
+            localXPath.append("/" + xPathTokens[i]);
+        }
+        return localXPath.toString();
+    }
+
+    public Enum getXmlDataType() {
+
+        return ctXmlColumnPr.getXmlDataType();
+    }
 
 }

Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFImportFromXML.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFImportFromXML.java?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFImportFromXML.java (original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFImportFromXML.java Sun Feb 25 17:06:19 2018
@@ -32,6 +32,7 @@ import java.util.Locale;
 
 import javax.xml.xpath.XPathExpressionException;
 
+import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.xssf.XSSFTestDataSamples;
 import org.apache.poi.xssf.usermodel.XSSFMap;
 import org.apache.poi.xssf.usermodel.XSSFRow;
@@ -41,188 +42,200 @@ import org.junit.Test;
 import org.xml.sax.SAXException;
 
 public class TestXSSFImportFromXML {
-	
-	@Test
-	public void testImportFromXML() throws IOException, XPathExpressionException, SAXException{
-		try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXMLMappings.xlsx")) {
-			String name = "name";
-			String teacher = "teacher";
-			String tutor = "tutor";
-			String cdl = "cdl";
-			String duration = "duration";
-			String topic = "topic";
-			String project = "project";
-			String credits = "credits";
-
-			String testXML = "<CORSO>" +
-					"<NOME>" + name + "</NOME>" +
-					"<DOCENTE>" + teacher + "</DOCENTE>" +
-					"<TUTOR>" + tutor + "</TUTOR>" +
-					"<CDL>" + cdl + "</CDL>" +
-					"<DURATA>" + duration + "</DURATA>" +
-					"<ARGOMENTO>" + topic + "</ARGOMENTO>" +
-					"<PROGETTO>" + project + "</PROGETTO>" +
-					"<CREDITI>" + credits + "</CREDITI>" +
-					"</CORSO>\u0000";
-
-			XSSFMap map = wb.getMapInfo().getXSSFMapByName("CORSO_mapping");
-			assertNotNull(map);
-			XSSFImportFromXML importer = new XSSFImportFromXML(map);
-
-			importer.importFromXML(testXML);
-
-			XSSFSheet sheet = wb.getSheetAt(0);
-
-			XSSFRow row = sheet.getRow(0);
-			assertTrue(row.getCell(0).getStringCellValue().equals(name));
-			assertTrue(row.getCell(1).getStringCellValue().equals(teacher));
-			assertTrue(row.getCell(2).getStringCellValue().equals(tutor));
-			assertTrue(row.getCell(3).getStringCellValue().equals(cdl));
-			assertTrue(row.getCell(4).getStringCellValue().equals(duration));
-			assertTrue(row.getCell(5).getStringCellValue().equals(topic));
-			assertTrue(row.getCell(6).getStringCellValue().equals(project));
-			assertTrue(row.getCell(7).getStringCellValue().equals(credits));
-		}
-	}
-	
-	@Test(timeout=60000)
-	public void testMultiTable() throws IOException, XPathExpressionException, SAXException{
-		try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXMLMappings-complex-type.xlsx")) {
-			String cellC6 = "c6";
-			String cellC7 = "c7";
-			String cellC8 = "c8";
-			String cellC9 = "c9";
-
-			StringBuilder testXML = new StringBuilder("<ns1:MapInfo xmlns:ns1=\"" + NS_SPREADSHEETML + "\" SelectionNamespaces=\"\">" +
-					"<ns1:Schema ID=\"" + cellC6 + "\" SchemaRef=\"a\" />" +
-					"<ns1:Schema ID=\"" + cellC7 + "\" SchemaRef=\"b\" />" +
-					"<ns1:Schema ID=\"" + cellC8 + "\" SchemaRef=\"c\" />" +
-					"<ns1:Schema ID=\"" + cellC9 + "\" SchemaRef=\"d\" />");
-
-			for (int i = 10; i < 10010; i++) {
-				testXML.append("<ns1:Schema ID=\"c").append(i).append("\" SchemaRef=\"d\" />");
-			}
-
-			testXML.append("<ns1:Map ID=\"1\" Name=\"\" RootElement=\"\" SchemaID=\"\" ShowImportExportValidationErrors=\"\" AutoFit=\"\" Append=\"\" PreserveSortAFLayout=\"\" PreserveFormat=\"\">" + "<ns1:DataBinding DataBindingLoadMode=\"\" />" + "</ns1:Map>" + "<ns1:Map ID=\"2\" Name=\"\" RootElement=\"\" SchemaID=\"\" ShowImportExportValidationErrors=\"\" AutoFit=\"\" Append=\"\" PreserveSortAFLayout=\"\" PreserveFormat=\"\">" + "<ns1:DataBinding DataBindingLoadMode=\"\" />" + "</ns1:Map>" + "<ns1:Map ID=\"3\" Name=\"\" RootElement=\"\" SchemaID=\"\" ShowImportExportValidationErrors=\"\" AutoFit=\"\" Append=\"\" PreserveSortAFLayout=\"\" PreserveFormat=\"\">" + "<ns1:DataBinding DataBindingLoadMode=\"\" />" + "</ns1:Map>" + "</ns1:MapInfo>\u0000");
-
-			XSSFMap map = wb.getMapInfo().getXSSFMapByName("MapInfo_mapping");
-			assertNotNull(map);
-			XSSFImportFromXML importer = new XSSFImportFromXML(map);
-
-			importer.importFromXML(testXML.toString());
-
-			//Check for Schema element
-			XSSFSheet sheet = wb.getSheetAt(1);
-
-			assertEquals(cellC6, sheet.getRow(5).getCell(2).getStringCellValue());
-			assertEquals(cellC7, sheet.getRow(6).getCell(2).getStringCellValue());
-			assertEquals(cellC8, sheet.getRow(7).getCell(2).getStringCellValue());
-			assertEquals(cellC9, sheet.getRow(8).getCell(2).getStringCellValue());
-			assertEquals("c5001", sheet.getRow(5000).getCell(2).getStringCellValue());
-		}
-	}
-
-	
-	@Test
-	public void testSingleAttributeCellWithNamespace() throws IOException, XPathExpressionException, SAXException{
-		try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXMLMapping-singleattributenamespace.xlsx")) {
-			int id = 1;
-			String displayName = "dispName";
-			String ref = "19";
-			int count = 21;
-
-			String testXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>" +
-					"<ns1:table xmlns:ns1=\"" + NS_SPREADSHEETML + "\" id=\"" + id + "\" displayName=\"" + displayName + "\" ref=\"" + ref + "\">" +
-					"<ns1:tableColumns count=\"" + count + "\" />" +
-					"</ns1:table>\u0000";
-			XSSFMap map = wb.getMapInfo().getXSSFMapByName("table_mapping");
-			assertNotNull(map);
-			XSSFImportFromXML importer = new XSSFImportFromXML(map);
-			importer.importFromXML(testXML);
-
-			//Check for Schema element
-			XSSFSheet sheet = wb.getSheetAt(0);
-
-			assertEquals(new Double(id), sheet.getRow(28).getCell(1).getNumericCellValue(), 0);
-			assertEquals(displayName, sheet.getRow(11).getCell(5).getStringCellValue());
-			assertEquals(ref, sheet.getRow(14).getCell(7).getStringCellValue());
-			assertEquals(new Double(count), sheet.getRow(18).getCell(3).getNumericCellValue(), 0);
-		}
-	}
-	
-	@Test
-	public void testOptionalFields_Bugzilla_55864() throws IOException, XPathExpressionException, SAXException {
-		try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("55864.xlsx")) {
-			String testXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
-					"<PersonInfoRoot>" +
-					"<PersonData>" +
-					"<FirstName>Albert</FirstName>" +
-					"<LastName>Einstein</LastName>" +
-					"<BirthDate>1879-03-14</BirthDate>" +
-					"</PersonData>" +
-					"</PersonInfoRoot>";
-
-			XSSFMap map = wb.getMapInfo().getXSSFMapByName("PersonInfoRoot_Map");
-			assertNotNull(map);
-			XSSFImportFromXML importer = new XSSFImportFromXML(map);
-
-			importer.importFromXML(testXML);
-
-			XSSFSheet sheet = wb.getSheetAt(0);
-
-			XSSFRow rowHeadings = sheet.getRow(0);
-			XSSFRow rowData = sheet.getRow(1);
-
-			assertEquals("FirstName", rowHeadings.getCell(0).getStringCellValue());
-			assertEquals("Albert", rowData.getCell(0).getStringCellValue());
-
-			assertEquals("LastName", rowHeadings.getCell(1).getStringCellValue());
-			assertEquals("Einstein", rowData.getCell(1).getStringCellValue());
-
-			assertEquals("BirthDate", rowHeadings.getCell(2).getStringCellValue());
-			assertEquals("1879-03-14", rowData.getCell(2).getStringCellValue());
-
-			// Value for OptionalRating is declared optional (minOccurs=0) in 55864.xlsx
-			assertEquals("OptionalRating", rowHeadings.getCell(3).getStringCellValue());
-			assertNull("", rowData.getCell(3));
-		}
-	}
-
-	@Test
-	public void testOptionalFields_Bugzilla_57890() throws IOException, ParseException, XPathExpressionException, SAXException {
-		XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("57890.xlsx");
-
-		String testXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + "<TestInfoRoot>"
-				+ "<TestData>" + "<Int>" + Integer.MIN_VALUE + "</Int>" + "<UnsignedInt>12345</UnsignedInt>"
-				+ "<double>1.0000123</double>" + "<Date>1991-03-14</Date>" + "</TestData>" + "</TestInfoRoot>";
-
-		XSSFMap map = wb.getMapInfo().getXSSFMapByName("TestInfoRoot_Map");
-		assertNotNull(map);
-		XSSFImportFromXML importer = new XSSFImportFromXML(map);
-
-		importer.importFromXML(testXML);
-
-		XSSFSheet sheet = wb.getSheetAt(0);
-
-		XSSFRow rowHeadings = sheet.getRow(0);
-		XSSFRow rowData = sheet.getRow(1);
-
-		assertEquals("Date", rowHeadings.getCell(0).getStringCellValue());
-		Date date = new SimpleDateFormat("yyyy-MM-dd", DateFormatSymbols.getInstance(Locale.ROOT)).parse("1991-3-14");
-		assertEquals(date, rowData.getCell(0).getDateCellValue());
-
-		assertEquals("Amount Int", rowHeadings.getCell(1).getStringCellValue());
-		assertEquals(new Double(Integer.MIN_VALUE), rowData.getCell(1).getNumericCellValue(), 0);
-
-		assertEquals("Amount Double", rowHeadings.getCell(2).getStringCellValue());
-		assertEquals(1.0000123, rowData.getCell(2).getNumericCellValue(), 0);
-
-		assertEquals("Amount UnsignedInt", rowHeadings.getCell(3).getStringCellValue());
-		assertEquals(new Double(12345), rowData.getCell(3).getNumericCellValue(), 0);
-		
-		wb.close();
-	}
-	
-	
-	
+
+    @Test
+    public void testImportFromXML() throws IOException, XPathExpressionException, SAXException{
+        try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXMLMappings.xlsx")) {
+            String name = "name";
+            String teacher = "teacher";
+            String tutor = "tutor";
+            String cdl = "cdl";
+            String duration = "duration";
+            String topic = "topic";
+            String project = "project";
+            String credits = "credits";
+
+            String testXML = "<CORSO>" +
+                    "<NOME>" + name + "</NOME>" +
+                    "<DOCENTE>" + teacher + "</DOCENTE>" +
+                    "<TUTOR>" + tutor + "</TUTOR>" +
+                    "<CDL>" + cdl + "</CDL>" +
+                    "<DURATA>" + duration + "</DURATA>" +
+                    "<ARGOMENTO>" + topic + "</ARGOMENTO>" +
+                    "<PROGETTO>" + project + "</PROGETTO>" +
+                    "<CREDITI>" + credits + "</CREDITI>" +
+                    "</CORSO>\u0000";
+
+            XSSFMap map = wb.getMapInfo().getXSSFMapByName("CORSO_mapping");
+            assertNotNull(map);
+            XSSFImportFromXML importer = new XSSFImportFromXML(map);
+
+            importer.importFromXML(testXML);
+
+            XSSFSheet sheet = wb.getSheetAt(0);
+
+            XSSFRow row = sheet.getRow(0);
+            assertTrue(row.getCell(0).getStringCellValue().equals(name));
+            assertTrue(row.getCell(1).getStringCellValue().equals(teacher));
+            assertTrue(row.getCell(2).getStringCellValue().equals(tutor));
+            assertTrue(row.getCell(3).getStringCellValue().equals(cdl));
+            assertTrue(row.getCell(4).getStringCellValue().equals(duration));
+            assertTrue(row.getCell(5).getStringCellValue().equals(topic));
+            assertTrue(row.getCell(6).getStringCellValue().equals(project));
+            assertTrue(row.getCell(7).getStringCellValue().equals(credits));
+        }
+    }
+
+    @Test(timeout=60000)
+    public void testMultiTable() throws IOException, XPathExpressionException, SAXException{
+        try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXMLMappings-complex-type.xlsx")) {
+            String cellC6 = "c6";
+            String cellC7 = "c7";
+            String cellC8 = "c8";
+            String cellC9 = "c9";
+
+            StringBuilder testXML = new StringBuilder("<ns1:MapInfo xmlns:ns1=\"" + NS_SPREADSHEETML + "\" SelectionNamespaces=\"\">" +
+                    "<ns1:Schema ID=\"" + cellC6 + "\" SchemaRef=\"a\" />" +
+                    "<ns1:Schema ID=\"" + cellC7 + "\" SchemaRef=\"b\" />" +
+                    "<ns1:Schema ID=\"" + cellC8 + "\" SchemaRef=\"c\" />" +
+                    "<ns1:Schema ID=\"" + cellC9 + "\" SchemaRef=\"d\" />");
+
+            int cellOffset = 10; // cell C10
+            for (int i = 0; i < 10000; i++) {
+                testXML.append("<ns1:Schema ID=\"c").append(i + cellOffset).append("\" SchemaRef=\"d\" />");
+            }
+
+            testXML.append("<ns1:Map ID=\"1\" Name=\"\" RootElement=\"\" SchemaID=\"\" ShowImportExportValidationErrors=\"\" AutoFit=\"\" Append=\"\" PreserveSortAFLayout=\"\" PreserveFormat=\"\">" + "<ns1:DataBinding DataBindingLoadMode=\"\" />" + "</ns1:Map>" + "<ns1:Map ID=\"2\" Name=\"\" RootElement=\"\" SchemaID=\"\" ShowImportExportValidationErrors=\"\" AutoFit=\"\" Append=\"\" PreserveSortAFLayout=\"\" PreserveFormat=\"\">" + "<ns1:DataBinding DataBindingLoadMode=\"\" />" + "</ns1:Map>" + "<ns1:Map ID=\"3\" Name=\"\" RootElement=\"\" SchemaID=\"\" ShowImportExportValidationErrors=\"\" AutoFit=\"\" Append=\"\" PreserveSortAFLayout=\"\" PreserveFormat=\"\">" + "<ns1:DataBinding DataBindingLoadMode=\"\" />" + "</ns1:Map>" + "</ns1:MapInfo>\u0000");
+
+            XSSFMap map = wb.getMapInfo().getXSSFMapByName("MapInfo_mapping");
+            assertNotNull(map);
+            XSSFImportFromXML importer = new XSSFImportFromXML(map);
+
+            importer.importFromXML(testXML.toString());
+
+            //Check for Schema element
+            XSSFSheet sheet = wb.getSheetAt(1);
+
+
+            // check table size (+1 for the header row)
+            assertEquals(3 + 1, wb.getTable("Tabella1").getRowCount());
+            assertEquals(10004 + 1, wb.getTable("Tabella2").getRowCount());
+
+            // table1 size was reduced, check that former table cells have been cleared
+            assertEquals(CellType.BLANK, wb.getSheetAt(0).getRow(8).getCell(5).getCellType());
+
+            // table2 size was increased, check that new table cells have been cleared
+            assertEquals(CellType.BLANK, sheet.getRow(10).getCell(3).getCellType());
+
+            assertEquals(cellC6, sheet.getRow(5).getCell(2).getStringCellValue());
+            assertEquals(cellC7, sheet.getRow(6).getCell(2).getStringCellValue());
+            assertEquals(cellC8, sheet.getRow(7).getCell(2).getStringCellValue());
+            assertEquals(cellC9, sheet.getRow(8).getCell(2).getStringCellValue());
+            assertEquals("c5001", sheet.getRow(5000).getCell(2).getStringCellValue());
+        }
+    }
+
+
+    @Test
+    public void testSingleAttributeCellWithNamespace() throws IOException, XPathExpressionException, SAXException{
+        try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXMLMapping-singleattributenamespace.xlsx")) {
+            int id = 1;
+            String displayName = "dispName";
+            String ref = "19";
+            int count = 21;
+
+            String testXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>" +
+                    "<ns1:table xmlns:ns1=\"" + NS_SPREADSHEETML + "\" id=\"" + id + "\" displayName=\"" + displayName + "\" ref=\"" + ref + "\">" +
+                    "<ns1:tableColumns count=\"" + count + "\" />" +
+                    "</ns1:table>\u0000";
+            XSSFMap map = wb.getMapInfo().getXSSFMapByName("table_mapping");
+            assertNotNull(map);
+            XSSFImportFromXML importer = new XSSFImportFromXML(map);
+            importer.importFromXML(testXML);
+
+            //Check for Schema element
+            XSSFSheet sheet = wb.getSheetAt(0);
+
+            assertEquals(new Double(id), sheet.getRow(28).getCell(1).getNumericCellValue(), 0);
+            assertEquals(displayName, sheet.getRow(11).getCell(5).getStringCellValue());
+            assertEquals(ref, sheet.getRow(14).getCell(7).getStringCellValue());
+            assertEquals(new Double(count), sheet.getRow(18).getCell(3).getNumericCellValue(), 0);
+        }
+    }
+
+    @Test
+    public void testOptionalFields_Bugzilla_55864() throws IOException, XPathExpressionException, SAXException {
+        try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("55864.xlsx")) {
+            String testXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
+                    "<PersonInfoRoot>" +
+                    "<PersonData>" +
+                    "<FirstName>Albert</FirstName>" +
+                    "<LastName>Einstein</LastName>" +
+                    "<BirthDate>1879-03-14</BirthDate>" +
+                    "</PersonData>" +
+                    "</PersonInfoRoot>";
+
+            XSSFMap map = wb.getMapInfo().getXSSFMapByName("PersonInfoRoot_Map");
+            assertNotNull(map);
+            XSSFImportFromXML importer = new XSSFImportFromXML(map);
+
+            importer.importFromXML(testXML);
+
+            XSSFSheet sheet = wb.getSheetAt(0);
+
+            XSSFRow rowHeadings = sheet.getRow(0);
+            XSSFRow rowData = sheet.getRow(1);
+
+            assertEquals("FirstName", rowHeadings.getCell(0).getStringCellValue());
+            assertEquals("Albert", rowData.getCell(0).getStringCellValue());
+
+            assertEquals("LastName", rowHeadings.getCell(1).getStringCellValue());
+            assertEquals("Einstein", rowData.getCell(1).getStringCellValue());
+
+            assertEquals("BirthDate", rowHeadings.getCell(2).getStringCellValue());
+            assertEquals("1879-03-14", rowData.getCell(2).getStringCellValue());
+
+            // Value for OptionalRating is declared optional (minOccurs=0) in 55864.xlsx
+            assertEquals("OptionalRating", rowHeadings.getCell(3).getStringCellValue());
+            assertNull("", rowData.getCell(3));
+        }
+    }
+
+    @Test
+    public void testOptionalFields_Bugzilla_57890() throws IOException, ParseException, XPathExpressionException, SAXException {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("57890.xlsx");
+
+        String testXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + "<TestInfoRoot>"
+                + "<TestData>" + "<Int>" + Integer.MIN_VALUE + "</Int>" + "<UnsignedInt>12345</UnsignedInt>"
+                + "<double>1.0000123</double>" + "<Date>1991-03-14</Date>" + "</TestData>" + "</TestInfoRoot>";
+
+        XSSFMap map = wb.getMapInfo().getXSSFMapByName("TestInfoRoot_Map");
+        assertNotNull(map);
+        XSSFImportFromXML importer = new XSSFImportFromXML(map);
+
+        importer.importFromXML(testXML);
+
+        XSSFSheet sheet = wb.getSheetAt(0);
+
+        XSSFRow rowHeadings = sheet.getRow(0);
+        XSSFRow rowData = sheet.getRow(1);
+
+        assertEquals("Date", rowHeadings.getCell(0).getStringCellValue());
+        Date date = new SimpleDateFormat("yyyy-MM-dd", DateFormatSymbols.getInstance(Locale.ROOT)).parse("1991-3-14");
+        assertEquals(date, rowData.getCell(0).getDateCellValue());
+
+        assertEquals("Amount Int", rowHeadings.getCell(1).getStringCellValue());
+        assertEquals(new Double(Integer.MIN_VALUE), rowData.getCell(1).getNumericCellValue(), 0);
+
+        assertEquals("Amount Double", rowHeadings.getCell(2).getStringCellValue());
+        assertEquals(1.0000123, rowData.getCell(2).getNumericCellValue(), 0);
+
+        assertEquals("Amount UnsignedInt", rowHeadings.getCell(3).getStringCellValue());
+        assertEquals(new Double(12345), rowData.getCell(3).getNumericCellValue(), 0);
+
+        wb.close();
+    }
+
+
+
 }

Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java (original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java Sun Feb 25 17:06:19 2018
@@ -31,6 +31,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.TempFile;
@@ -224,6 +225,14 @@ public final class TestXSSFTable {
     }
 
     @Test
+    public void getColumnCount() throws IOException {
+        XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("StructuredReferences.xlsx");
+        XSSFTable table = wb.getTable("\\_Prime.1");
+        assertEquals(3, table.getColumnCount());
+        wb.close(); 
+    }
+    
+    @Test
     public void getAndSetDisplayName() throws IOException {
         XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("StructuredReferences.xlsx");
         XSSFTable table = wb.getTable("\\_Prime.1");
@@ -291,7 +300,131 @@ public final class TestXSSFTable {
         
         IOUtils.closeQuietly(wb);
     }
+    
+    @Test
+    public void testGetDataRowCount() {
+        XSSFWorkbook wb = new XSSFWorkbook();
+        XSSFSheet sh = wb.createSheet();
+        AreaReference tableArea = new AreaReference("B2:B6", wb.getSpreadsheetVersion());
+        XSSFTable table = sh.createTable(tableArea);
+
+        assertEquals(5, table.getRowCount()); // includes column header
+        assertEquals(4, table.getDataRowCount());
+        
+        table.setArea(new AreaReference("B2:B7", wb.getSpreadsheetVersion()));
+        
+        assertEquals(6, table.getRowCount());
+        assertEquals(5, table.getDataRowCount());
+        
+        IOUtils.closeQuietly(wb);
+    }
+    
+    @Test
+    public void testSetDataRowCount() throws IOException {
+        XSSFWorkbook wb = new XSSFWorkbook();
+        XSSFSheet sh = wb.createSheet();
+        
+        // 1 header row + 1 data row 
+        AreaReference tableArea = new AreaReference("C10:C11", wb.getSpreadsheetVersion());
+        XSSFTable table = sh.createTable(tableArea); 
+            
+        assertEquals(2, table.getRowCount()); // includes all data and header/footer rows
+        
+        assertEquals(1, table.getHeaderRowCount());
+        assertEquals(1, table.getDataRowCount());
+        assertEquals(0, table.getTotalsRowCount());
+
+        table.setDataRowCount(5);
+        
+        assertEquals(6, table.getRowCount());
+        
+        assertEquals(1, table.getHeaderRowCount());
+        assertEquals(5, table.getDataRowCount());
+        assertEquals(0, table.getTotalsRowCount());
+        
+        assertEquals("C10:C15", table.getArea().formatAsString());
+        
+        
+        IOUtils.closeQuietly(wb);
+    }
+    
+    @Test
+    public void testSetArea() throws IOException {
+        XSSFWorkbook wb = new XSSFWorkbook();
+            XSSFSheet sh = wb.createSheet();
+            
+            AreaReference tableArea = new AreaReference("B10:D12", wb.getSpreadsheetVersion());
+            XSSFTable table = sh.createTable(tableArea);
+            
+            assertEquals(3, table.getColumnCount());
+            assertEquals(3, table.getRowCount());
+
+            // move table without resizing, shouldn't change row or column count
+            AreaReference tableArea2 = new AreaReference("B11:D13", wb.getSpreadsheetVersion());
+            table.setArea(tableArea2);
+
+            assertEquals(3, table.getColumnCount());
+            assertEquals(3, table.getRowCount());
+ 
+            // increase size by 1 row and 1 column
+            AreaReference tableArea3 = new AreaReference("B11:E14", wb.getSpreadsheetVersion());
+            table.setArea(tableArea3);
+            
+            assertEquals(4, table.getColumnCount());
+            assertEquals(4, table.getRowCount());
+
+            // reduce size by 2 rows and 2 columns
+            AreaReference tableArea4 = new AreaReference("C12:D13", wb.getSpreadsheetVersion());
+            table.setArea(tableArea4);
+
+            assertEquals(2, table.getColumnCount());
+            assertEquals(2, table.getRowCount());
+            
+            IOUtils.closeQuietly(wb);
+    }
+    
+    @Test
+    public void testCreateColumn() {
+        XSSFWorkbook wb = new XSSFWorkbook();
+        XSSFSheet sh = wb.createSheet();
+        
+        AreaReference tableArea = new AreaReference("A2:A3", wb.getSpreadsheetVersion());
+        XSSFTable table = sh.createTable(tableArea);
+
+        assertEquals(1, table.getColumnCount());
+        assertEquals(2, table.getRowCount());
+
+        // add columns
+        table.createColumn("Column B");
+        table.createColumn("Column D");
+        table.createColumn("Column C", 2); // add between B and D
+        table.updateReferences();
+        table.updateHeaders();
+
+        assertEquals(4, table.getColumnCount());
+        assertEquals(2, table.getRowCount());
+
+        assertEquals("Column 1", table.getColumns().get(0).getName()); // generated name
+        assertEquals("Column B", table.getColumns().get(1).getName());
+        assertEquals("Column C", table.getColumns().get(2).getName());
+        assertEquals("Column D", table.getColumns().get(3).getName());
 
+        IOUtils.closeQuietly(wb);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateColumnInvalidIndex() throws IOException {
+        try (XSSFWorkbook wb = new XSSFWorkbook();) {
+            XSSFSheet sh = wb.createSheet();
+            AreaReference tableArea = new AreaReference("D2:D3", wb.getSpreadsheetVersion());
+            XSSFTable table = sh.createTable(tableArea);
+
+            // add columns
+            table.createColumn("Column 2", 1);
+            table.createColumn("Column 3", 3); // out of bounds
+        }
+    }
+    
     @Test
     public void testDifferentHeaderTypes() throws IOException {
         XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("TablesWithDifferentHeaders.xlsx");
@@ -345,13 +478,13 @@ public final class TestXSSFTable {
         c5.setCellValue("CD");
         c6.setCellValue("EF");
 
-        // Setting up the CTTable
-        XSSFTable t = s.createTable();
+        // Setting up the table
+        XSSFTable t = s.createTable(new AreaReference("A1:C3", wb.getSpreadsheetVersion()));
         t.setName("TableTest");
         t.setDisplayName("CT_Table_Test");
-        t.addColumn();
-        t.addColumn();
-        t.addColumn();
+        t.createColumn("Column 1");
+        t.createColumn("Column 2");
+        t.createColumn("Column 3");
         t.setCellReferences(wb.getCreationHelper().createAreaReference(
                 new CellReference(c1), new CellReference(c6)
         ));

Added: poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTableColumn.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTableColumn.java?rev=1825315&view=auto
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTableColumn.java (added)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTableColumn.java Sun Feb 25 17:06:19 2018
@@ -0,0 +1,79 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.poi.xssf.XSSFTestDataSamples;
+import org.junit.Test;
+
+public final class TestXSSFTableColumn {
+
+    @Test
+    public void testGetColumnName() throws IOException {
+        try (XSSFWorkbook wb = XSSFTestDataSamples
+                .openSampleWorkbook("CustomXMLMappings-complex-type.xlsx")) {
+            XSSFTable table = wb.getTable("Tabella2");
+
+            List<XSSFTableColumn> tableColumns = table.getColumns();
+
+            assertEquals("ID", tableColumns.get(0).getName());
+            assertEquals("Unmapped Column", tableColumns.get(1).getName());
+            assertEquals("SchemaRef", tableColumns.get(2).getName());
+            assertEquals("Namespace", tableColumns.get(3).getName());
+
+        }
+    }
+
+    @Test
+    public void testGetColumnIndex() throws IOException {
+        try (XSSFWorkbook wb = XSSFTestDataSamples
+                .openSampleWorkbook("CustomXMLMappings-complex-type.xlsx")) {
+            XSSFTable table = wb.getTable("Tabella2");
+
+            List<XSSFTableColumn> tableColumns = table.getColumns();
+
+            assertEquals(0, tableColumns.get(0).getColumnIndex());
+            assertEquals(1, tableColumns.get(1).getColumnIndex());
+            assertEquals(2, tableColumns.get(2).getColumnIndex());
+            assertEquals(3, tableColumns.get(3).getColumnIndex());
+
+        }
+    }
+
+    @Test
+    public void testGetXmlColumnPrs() throws IOException {
+        try (XSSFWorkbook wb = XSSFTestDataSamples
+                .openSampleWorkbook("CustomXMLMappings-complex-type.xlsx")) {
+            XSSFTable table = wb.getTable("Tabella2");
+
+            List<XSSFTableColumn> tableColumns = table.getColumns();
+
+            assertNotNull(tableColumns.get(0).getXmlColumnPr());
+            assertNull(tableColumns.get(1).getXmlColumnPr()); // unmapped column
+            assertNotNull(tableColumns.get(2).getColumnIndex());
+            assertNotNull(tableColumns.get(3).getColumnIndex());
+
+        }
+    }
+}

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTableColumn.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/trunk/test-data/spreadsheet/CustomXMLMappings-complex-type.xlsx
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/CustomXMLMappings-complex-type.xlsx?rev=1825315&r1=1825314&r2=1825315&view=diff
==============================================================================
Binary files - no diff available.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org