}
}
// 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(
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;
// 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);
}
}
}
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;
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) {
}
}
+
+
private static enum DataType {
BOOLEAN(STXmlDataType.BOOLEAN), //
DOUBLE(STXmlDataType.DOUBLE), //
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;
}
/**
- * 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();
}
tables.put(tbl.getId(), table);
+ if(tableArea != null) {
+ table.setArea(tableArea);
+ }
+
return table;
}
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;
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;
/**
*
- * 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
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;
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;
- }
/**
*
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;
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);
+ }
- // Have the Headers updated if possible
+ 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");
+ }
+
+ CTTableColumns tableColumns = ctTable.getTableColumns();
+ tableColumns.removeTableColumn(columnIndex);
+ tableColumns.setCount(tableColumns.getTableColumnList().size());
+ updateReferences();
updateHeaders();
}
}
/**
+ * @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() {
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);
updateHeaders();
}
+ /**
+ * 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)
/**
- * @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();
}
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.
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();
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) {
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++;
--- /dev/null
+/* ====================================================================
+ 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());
+ }
+
+}
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:
* @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();
+ }
}
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;
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();
+ }
+
+
+
}
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;
wb.close();
}
+ @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");
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");
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)
));
--- /dev/null
+/* ====================================================================
+ 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());
+
+ }
+ }
+}