123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- /* ====================================================================
- 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.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
-
- import javax.xml.namespace.QName;
-
- import org.apache.poi.POIXMLDocumentPart;
- import org.apache.poi.openxml4j.opc.PackagePart;
- import org.apache.poi.openxml4j.opc.PackageRelationship;
- 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.DataConsolidateFunction;
- import org.apache.poi.ss.usermodel.Sheet;
- import org.apache.poi.ss.util.AreaReference;
- import org.apache.poi.ss.util.CellReference;
- import org.apache.poi.util.Beta;
- import org.apache.poi.util.Internal;
- import org.apache.xmlbeans.XmlException;
- import org.apache.xmlbeans.XmlOptions;
- import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
-
- public class XSSFPivotTable extends POIXMLDocumentPart {
-
- protected final static short CREATED_VERSION = 3;
- protected final static short MIN_REFRESHABLE_VERSION = 3;
- protected final static short UPDATED_VERSION = 3;
-
- private CTPivotTableDefinition pivotTableDefinition;
- private XSSFPivotCacheDefinition pivotCacheDefinition;
- private XSSFPivotCache pivotCache;
- private XSSFPivotCacheRecords pivotCacheRecords;
- private Sheet parentSheet;
- private Sheet dataSheet;
-
- @Beta
- protected XSSFPivotTable() {
- super();
- pivotTableDefinition = CTPivotTableDefinition.Factory.newInstance();
- pivotCache = new XSSFPivotCache();
- pivotCacheDefinition = new XSSFPivotCacheDefinition();
- pivotCacheRecords = new XSSFPivotCacheRecords();
- }
-
- /**
- * Creates an XSSFPivotTable representing the given package part and relationship.
- * Should only be called when reading in an existing file.
- *
- * @param part - The package part that holds xml data representing this pivot table.
- *
- * @since POI 3.14-Beta1
- */
- @Beta
- protected XSSFPivotTable(PackagePart part) throws IOException {
- super(part);
- readFrom(part.getInputStream());
- }
-
- /**
- * @deprecated in POI 3.14, scheduled for removal in POI 3.16
- */
- @Deprecated
- protected XSSFPivotTable(PackagePart part, PackageRelationship rel) throws IOException {
- this(part);
- }
-
- @Beta
- public void readFrom(InputStream is) throws IOException {
- try {
- XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS);
- //Removing root element
- options.setLoadReplaceDocumentElement(null);
- pivotTableDefinition = CTPivotTableDefinition.Factory.parse(is, options);
- } catch (XmlException e) {
- throw new IOException(e.getLocalizedMessage());
- }
- }
-
- @Beta
- public void setPivotCache(XSSFPivotCache pivotCache) {
- this.pivotCache = pivotCache;
- }
-
- @Beta
- public XSSFPivotCache getPivotCache() {
- return pivotCache;
- }
-
- @Beta
- public Sheet getParentSheet() {
- return parentSheet;
- }
-
- @Beta
- public void setParentSheet(XSSFSheet parentSheet) {
- this.parentSheet = parentSheet;
- }
-
- @Beta
- @Internal
- public CTPivotTableDefinition getCTPivotTableDefinition() {
- return pivotTableDefinition;
- }
-
- @Beta
- @Internal
- public void setCTPivotTableDefinition(CTPivotTableDefinition pivotTableDefinition) {
- this.pivotTableDefinition = pivotTableDefinition;
- }
-
- @Beta
- public XSSFPivotCacheDefinition getPivotCacheDefinition() {
- return pivotCacheDefinition;
- }
-
- @Beta
- public void setPivotCacheDefinition(XSSFPivotCacheDefinition pivotCacheDefinition) {
- this.pivotCacheDefinition = pivotCacheDefinition;
- }
-
- @Beta
- public XSSFPivotCacheRecords getPivotCacheRecords() {
- return pivotCacheRecords;
- }
-
- @Beta
- public void setPivotCacheRecords(XSSFPivotCacheRecords pivotCacheRecords) {
- this.pivotCacheRecords = pivotCacheRecords;
- }
-
- @Beta
- public Sheet getDataSheet() {
- return dataSheet;
- }
-
- @Beta
- private void setDataSheet(Sheet dataSheet) {
- this.dataSheet = dataSheet;
- }
-
- @Beta
- @Override
- protected void commit() throws IOException {
- XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
- //Sets the pivotTableDefinition tag
- xmlOptions.setSaveSyntheticDocumentElement(new QName(CTPivotTableDefinition.type.getName().
- getNamespaceURI(), "pivotTableDefinition"));
- PackagePart part = getPackagePart();
- OutputStream out = part.getOutputStream();
- pivotTableDefinition.save(out, xmlOptions);
- out.close();
- }
-
- /**
- * Set default values for the table definition.
- */
- @Beta
- protected void setDefaultPivotTableDefinition() {
- //Not more than one until more created
- pivotTableDefinition.setMultipleFieldFilters(false);
- //Indentation increment for compact rows
- pivotTableDefinition.setIndent(0);
- //The pivot version which created the pivot cache set to default value
- pivotTableDefinition.setCreatedVersion(CREATED_VERSION);
- //Minimun version required to update the pivot cache
- pivotTableDefinition.setMinRefreshableVersion(MIN_REFRESHABLE_VERSION);
- //Version of the application which "updated the spreadsheet last"
- pivotTableDefinition.setUpdatedVersion(UPDATED_VERSION);
- //Titles shown at the top of each page when printed
- pivotTableDefinition.setItemPrintTitles(true);
- //Set autoformat properties
- pivotTableDefinition.setUseAutoFormatting(true);
- pivotTableDefinition.setApplyNumberFormats(false);
- pivotTableDefinition.setApplyWidthHeightFormats(true);
- pivotTableDefinition.setApplyAlignmentFormats(false);
- pivotTableDefinition.setApplyPatternFormats(false);
- pivotTableDefinition.setApplyFontFormats(false);
- pivotTableDefinition.setApplyBorderFormats(false);
- pivotTableDefinition.setCacheId(pivotCache.getCTPivotCache().getCacheId());
- pivotTableDefinition.setName("PivotTable"+pivotTableDefinition.getCacheId());
- pivotTableDefinition.setDataCaption("Values");
-
- //Set the default style for the pivot table
- CTPivotTableStyle style = pivotTableDefinition.addNewPivotTableStyleInfo();
- style.setName("PivotStyleLight16");
- style.setShowLastColumn(true);
- style.setShowColStripes(false);
- style.setShowRowStripes(false);
- style.setShowColHeaders(true);
- style.setShowRowHeaders(true);
- }
-
- protected AreaReference getPivotArea() {
- AreaReference pivotArea = new AreaReference(
- getPivotCacheDefinition()
- .getCTPivotCacheDefinition()
- .getCacheSource()
- .getWorksheetSource()
- .getRef(),
- SpreadsheetVersion.EXCEL2007);
- return pivotArea;
- }
-
- /**
- * Verify column index (relative to first column in pivot area) is within the
- * pivot area
- *
- * @param columnIndex
- * @throws IndexOutOfBoundsException
- */
- private void checkColumnIndex(int columnIndex) throws IndexOutOfBoundsException {
- AreaReference pivotArea = getPivotArea();
- int size = pivotArea.getLastCell().getCol() - pivotArea.getFirstCell().getCol() + 1;
-
- if (columnIndex < 0 || columnIndex >= size) {
- throw new IndexOutOfBoundsException("Column Index: " + columnIndex + ", Size: " + size);
- }
- }
-
- /**
- * Add a row label using data from the given column.
- * @param columnIndex the index of the source column to be used as row label.
- * {@code columnIndex} is 0-based indexed and relative to the first column in the source.
- */
- @Beta
- public void addRowLabel(int columnIndex) {
- checkColumnIndex(columnIndex);
-
- AreaReference pivotArea = getPivotArea();
- final int lastRowIndex = pivotArea.getLastCell().getRow() - pivotArea.getFirstCell().getRow();
- CTPivotFields pivotFields = pivotTableDefinition.getPivotFields();
-
- CTPivotField pivotField = CTPivotField.Factory.newInstance();
- CTItems items = pivotField.addNewItems();
-
- pivotField.setAxis(STAxis.AXIS_ROW);
- pivotField.setShowAll(false);
- for (int i = 0; i <= lastRowIndex; i++) {
- items.addNewItem().setT(STItemType.DEFAULT);
- }
- items.setCount(items.sizeOfItemArray());
- pivotFields.setPivotFieldArray(columnIndex, pivotField);
-
- CTRowFields rowFields;
- if(pivotTableDefinition.getRowFields() != null) {
- rowFields = pivotTableDefinition.getRowFields();
- } else {
- rowFields = pivotTableDefinition.addNewRowFields();
- }
-
- rowFields.addNewField().setX(columnIndex);
- rowFields.setCount(rowFields.sizeOfFieldArray());
- }
-
- @Beta
- public List<Integer> getRowLabelColumns() {
- if (pivotTableDefinition.getRowFields() != null) {
- List<Integer> columnIndexes = new ArrayList<Integer>();
- for (CTField f : pivotTableDefinition.getRowFields().getFieldArray()) {
- columnIndexes.add(f.getX());
- }
- return columnIndexes;
- } else {
- return Collections.emptyList();
- }
- }
-
- /**
- * Add a column label using data from the given column and specified function
- * @param columnIndex the index of the source column to be used as column label.
- * {@code columnIndex} is 0-based indexed and relative to the first column in the source.
- * @param function the function to be used on the data
- * The following functions exists:
- * Sum, Count, Average, Max, Min, Product, Count numbers, StdDev, StdDevp, Var, Varp
- * @param valueFieldName the name of pivot table value field
- */
- @Beta
- public void addColumnLabel(DataConsolidateFunction function, int columnIndex, String valueFieldName) {
- checkColumnIndex(columnIndex);
-
- addDataColumn(columnIndex, true);
- addDataField(function, columnIndex, valueFieldName);
-
- // colfield should be added for the second one.
- if (pivotTableDefinition.getDataFields().getCount() == 2) {
- CTColFields colFields;
- if(pivotTableDefinition.getColFields() != null) {
- colFields = pivotTableDefinition.getColFields();
- } else {
- colFields = pivotTableDefinition.addNewColFields();
- }
- colFields.addNewField().setX(-2);
- colFields.setCount(colFields.sizeOfFieldArray());
- }
- }
-
- /**
- * Add a column label using data from the given column and specified function
- * @param columnIndex the index of the source column to be used as column label
- * {@code columnIndex} is 0-based indexed and relative to the first column in the source..
- * @param function the function to be used on the data
- * The following functions exists:
- * Sum, Count, Average, Max, Min, Product, Count numbers, StdDev, StdDevp, Var, Varp
- */
- @Beta
- public void addColumnLabel(DataConsolidateFunction function, int columnIndex) {
- addColumnLabel(function, columnIndex, function.getName());
- }
-
- /**
- * Add data field with data from the given column and specified function.
- * @param function the function to be used on the data
- * The following functions exists:
- * Sum, Count, Average, Max, Min, Product, Count numbers, StdDev, StdDevp, Var, Varp
- * @param columnIndex the index of the column to be used as column label.
- * @param valueFieldName the name of pivot table value field
- */
- @Beta
- private void addDataField(DataConsolidateFunction function, int columnIndex, String valueFieldName) {
- checkColumnIndex(columnIndex);
-
- AreaReference pivotArea = getPivotArea();
-
- CTDataFields dataFields;
- if(pivotTableDefinition.getDataFields() != null) {
- dataFields = pivotTableDefinition.getDataFields();
- } else {
- dataFields = pivotTableDefinition.addNewDataFields();
- }
- CTDataField dataField = dataFields.addNewDataField();
- dataField.setSubtotal(STDataConsolidateFunction.Enum.forInt(function.getValue()));
- Cell cell = getDataSheet().getRow(pivotArea.getFirstCell().getRow())
- .getCell(pivotArea.getFirstCell().getCol() + columnIndex);
- cell.setCellType(CellType.STRING);
- dataField.setName(valueFieldName);
- dataField.setFld(columnIndex);
- dataFields.setCount(dataFields.sizeOfDataFieldArray());
- }
-
- /**
- * Add column containing data from the referenced area.
- * @param columnIndex the index of the column containing the data
- * @param isDataField true if the data should be displayed in the pivot table.
- */
- @Beta
- public void addDataColumn(int columnIndex, boolean isDataField) {
- checkColumnIndex(columnIndex);
-
- CTPivotFields pivotFields = pivotTableDefinition.getPivotFields();
- CTPivotField pivotField = CTPivotField.Factory.newInstance();
-
- pivotField.setDataField(isDataField);
- pivotField.setShowAll(false);
- pivotFields.setPivotFieldArray(columnIndex, pivotField);
- }
-
- /**
- * Add filter for the column with the corresponding index and cell value
- * @param columnIndex index of column to filter on
- */
- @Beta
- public void addReportFilter(int columnIndex) {
- checkColumnIndex(columnIndex);
-
- AreaReference pivotArea = getPivotArea();
- int lastRowIndex = pivotArea.getLastCell().getRow() - pivotArea.getFirstCell().getRow();
-
- CTPivotFields pivotFields = pivotTableDefinition.getPivotFields();
-
- CTPivotField pivotField = CTPivotField.Factory.newInstance();
- CTItems items = pivotField.addNewItems();
-
- pivotField.setAxis(STAxis.AXIS_PAGE);
- pivotField.setShowAll(false);
- for(int i = 0; i <= lastRowIndex; i++) {
- items.addNewItem().setT(STItemType.DEFAULT);
- }
- items.setCount(items.sizeOfItemArray());
- pivotFields.setPivotFieldArray(columnIndex, pivotField);
-
- CTPageFields pageFields;
- if (pivotTableDefinition.getPageFields()!= null) {
- pageFields = pivotTableDefinition.getPageFields();
- //Another filter has already been created
- pivotTableDefinition.setMultipleFieldFilters(true);
- } else {
- pageFields = pivotTableDefinition.addNewPageFields();
- }
- CTPageField pageField = pageFields.addNewPageField();
- pageField.setHier(-1);
- pageField.setFld(columnIndex);
-
- pageFields.setCount(pageFields.sizeOfPageFieldArray());
- pivotTableDefinition.getLocation().setColPageCount(pageFields.getCount());
- }
-
- /**
- * Creates cacheSource and workSheetSource for pivot table and sets the source reference as well assets the location of the pivot table
- * @param source Source for data for pivot table
- * @param position Position for pivot table in sheet
- * @param sourceSheet Sheet where the source will be collected from
- */
- @Beta
- protected void createSourceReferences(AreaReference source, CellReference position, Sheet sourceSheet){
- //Get cell one to the right and one down from position, add both to AreaReference and set pivot table location.
- AreaReference destination = new AreaReference(position, new CellReference(position.getRow()+1, position.getCol()+1));
-
- CTLocation location;
- if(pivotTableDefinition.getLocation() == null) {
- location = pivotTableDefinition.addNewLocation();
- location.setFirstDataCol(1);
- location.setFirstDataRow(1);
- location.setFirstHeaderRow(1);
- } else {
- location = pivotTableDefinition.getLocation();
- }
- location.setRef(destination.formatAsString());
- pivotTableDefinition.setLocation(location);
-
- //Set source for the pivot table
- CTPivotCacheDefinition cacheDef = getPivotCacheDefinition().getCTPivotCacheDefinition();
- CTCacheSource cacheSource = cacheDef.addNewCacheSource();
- cacheSource.setType(STSourceType.WORKSHEET);
- CTWorksheetSource worksheetSource = cacheSource.addNewWorksheetSource();
- worksheetSource.setSheet(sourceSheet.getSheetName());
- setDataSheet(sourceSheet);
-
- String[] firstCell = source.getFirstCell().getCellRefParts();
- String[] lastCell = source.getLastCell().getCellRefParts();
- worksheetSource.setRef(firstCell[2]+firstCell[1]+':'+lastCell[2]+lastCell[1]);
- }
-
- @Beta
- protected void createDefaultDataColumns() {
- CTPivotFields pivotFields;
- if (pivotTableDefinition.getPivotFields() != null) {
- pivotFields = pivotTableDefinition.getPivotFields();
- } else {
- pivotFields = pivotTableDefinition.addNewPivotFields();
- }
- AreaReference sourceArea = getPivotArea();
- int firstColumn = sourceArea.getFirstCell().getCol();
- int lastColumn = sourceArea.getLastCell().getCol();
- CTPivotField pivotField;
- for(int i = 0; i<=lastColumn-firstColumn; i++) {
- pivotField = pivotFields.addNewPivotField();
- pivotField.setDataField(false);
- pivotField.setShowAll(false);
- }
- pivotFields.setCount(pivotFields.sizeOfPivotFieldArray());
- }
- }
|