diff options
Diffstat (limited to 'src/ooxml/java/org/apache/poi/xssf/usermodel')
105 files changed, 0 insertions, 30789 deletions
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java deleted file mode 100644 index 79f003eb9c..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java +++ /dev/null @@ -1,449 +0,0 @@ -/* ==================================================================== - 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 java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import org.apache.poi.ss.SpreadsheetVersion; -import org.apache.poi.ss.formula.EvaluationName; -import org.apache.poi.ss.formula.EvaluationWorkbook; -import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaParsingWorkbook; -import org.apache.poi.ss.formula.FormulaRenderingWorkbook; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.formula.SheetIdentifier; -import org.apache.poi.ss.formula.functions.FreeRefFunction; -import org.apache.poi.ss.formula.ptg.Area3DPxg; -import org.apache.poi.ss.formula.ptg.NamePtg; -import org.apache.poi.ss.formula.ptg.NameXPtg; -import org.apache.poi.ss.formula.ptg.NameXPxg; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.formula.ptg.Ref3DPxg; -import org.apache.poi.ss.formula.udf.IndexedUDFFinder; -import org.apache.poi.ss.formula.udf.UDFFinder; -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.NotImplemented; -import org.apache.poi.util.Internal; -import org.apache.poi.xssf.model.ExternalLinksTable; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName; - -/** - * Internal POI use only - parent of XSSF and SXSSF evaluation workbooks - */ -@Internal -public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook { - protected final XSSFWorkbook _uBook; - - // lazily populated. This should only be accessed through getTableCache - // keys are lower-case to make this a quasi-case-insensitive map - private Map<String, XSSFTable> _tableCache; - - - protected BaseXSSFEvaluationWorkbook(XSSFWorkbook book) { - _uBook = book; - } - - /* (non-JavaDoc), inherit JavaDoc from EvaluationWorkbook - * @since POI 3.15 beta 3 - */ - @Override - public void clearAllCachedResultValues() { - _tableCache = null; - } - - private int convertFromExternalSheetIndex(int externSheetIndex) { - return externSheetIndex; - } - /** - * XSSF doesn't use external sheet indexes, so when asked treat - * it just as a local index - */ - @Override - public int convertFromExternSheetIndex(int externSheetIndex) { - return externSheetIndex; - } - /** - * @return the external sheet index of the sheet with the given internal - * index. Used by some of the more obscure formula and named range things. - * Fairly easy on XSSF (we think...) since the internal and external - * indices are the same - */ - private int convertToExternalSheetIndex(int sheetIndex) { - return sheetIndex; - } - - @Override - public int getExternalSheetIndex(String sheetName) { - int sheetIndex = _uBook.getSheetIndex(sheetName); - return convertToExternalSheetIndex(sheetIndex); - } - - private int resolveBookIndex(String bookName) { - // Strip the [] wrapper, if still present - if (bookName.startsWith("[") && bookName.endsWith("]")) { - bookName = bookName.substring(1, bookName.length()-2); - } - - // Is it already in numeric form? - try { - return Integer.parseInt(bookName); - } catch (NumberFormatException e) {} - - // Look up an External Link Table for this name - List<ExternalLinksTable> tables = _uBook.getExternalLinksTable(); - int index = findExternalLinkIndex(bookName, tables); - if (index != -1) return index; - - // Is it an absolute file reference? - if (bookName.startsWith("'file:///") && bookName.endsWith("'")) { - String relBookName = bookName.substring(bookName.lastIndexOf('/')+1); - relBookName = relBookName.substring(0, relBookName.length()-1); // Trailing ' - - // Try with this name - index = findExternalLinkIndex(relBookName, tables); - if (index != -1) return index; - - // If we get here, it's got no associated proper links yet - // So, add the missing reference and return - // Note - this is really rather nasty... - ExternalLinksTable fakeLinkTable = new FakeExternalLinksTable(relBookName); - tables.add(fakeLinkTable); - return tables.size(); // 1 based results, 0 = current workbook - } - - // Not properly referenced - throw new RuntimeException("Book not linked for filename " + bookName); - } - /* This is case-sensitive. Is that correct? */ - private int findExternalLinkIndex(String bookName, List<ExternalLinksTable> tables) { - int i = 0; - for (ExternalLinksTable table : tables) { - if (table.getLinkedFileName().equals(bookName)) { - return i+1; // 1 based results, 0 = current workbook - } - i++; - } - return -1; - } - private static class FakeExternalLinksTable extends ExternalLinksTable { - private final String fileName; - private FakeExternalLinksTable(String fileName) { - this.fileName = fileName; - } - @Override - public String getLinkedFileName() { - return fileName; - } - } - - /** - * Return EvaluationName wrapper around the matching XSSFName (named range) - * @param name case-aware but case-insensitive named range in workbook - * @param sheetIndex index of sheet if named range scope is limited to one sheet - * if named range scope is global to the workbook, sheetIndex is -1. - * @return If name is a named range in the workbook, returns - * EvaluationName corresponding to that named range - * Returns null if there is no named range with the same name and scope in the workbook - */ - @Override - public EvaluationName getName(String name, int sheetIndex) { - for (int i = 0; i < _uBook.getNumberOfNames(); i++) { - XSSFName nm = _uBook.getNameAt(i); - String nameText = nm.getNameName(); - int nameSheetindex = nm.getSheetIndex(); - if (name.equalsIgnoreCase(nameText) && - (nameSheetindex == -1 || nameSheetindex == sheetIndex)) { - return new Name(nm, i, this); - } - } - return sheetIndex == -1 ? null : getName(name, -1); - } - - @Override - public String getSheetName(int sheetIndex) { - return _uBook.getSheetName(sheetIndex); - } - - @Override - public ExternalName getExternalName(int externSheetIndex, int externNameIndex) { - throw new IllegalStateException("HSSF-style external references are not supported for XSSF"); - } - - @Override - public ExternalName getExternalName(String nameName, String sheetName, int externalWorkbookNumber) { - if (externalWorkbookNumber > 0) { - // External reference - reference is 1 based, link table is 0 based - int linkNumber = externalWorkbookNumber - 1; - ExternalLinksTable linkTable = _uBook.getExternalLinksTable().get(linkNumber); - - for (org.apache.poi.ss.usermodel.Name name : linkTable.getDefinedNames()) { - if (name.getNameName().equals(nameName)) { - // HSSF returns one sheet higher than normal, and various bits - // of the code assume that. So, make us match that behaviour! - int nameSheetIndex = name.getSheetIndex() + 1; - - // TODO Return a more specialised form of this, see bug #56752 - // Should include the cached values, for in case that book isn't available - // Should support XSSF stuff lookups - return new ExternalName(nameName, -1, nameSheetIndex); - } - } - throw new IllegalArgumentException("Name '"+nameName+"' not found in " + - "reference to " + linkTable.getLinkedFileName()); - } else { - // Internal reference - int nameIdx = _uBook.getNameIndex(nameName); - return new ExternalName(nameName, nameIdx, 0); // TODO Is this right? - } - - } - - /** - * Return an external name (named range, function, user-defined function) Pxg - */ - @Override - public NameXPxg getNameXPtg(String name, SheetIdentifier sheet) { - // First, try to find it as a User Defined Function - IndexedUDFFinder udfFinder = (IndexedUDFFinder)getUDFFinder(); - FreeRefFunction func = udfFinder.findFunction(name); - if (func != null) { - return new NameXPxg(null, name); - } - - // Otherwise, try it as a named range - if (sheet == null) { - if (!_uBook.getNames(name).isEmpty()) { - return new NameXPxg(null, name); - } - return null; - } - if (sheet.getSheetIdentifier() == null) { - // Workbook + Named Range only - int bookIndex = resolveBookIndex(sheet.getBookName()); - return new NameXPxg(bookIndex, null, name); - } - - // Use the sheetname and process - String sheetName = sheet.getSheetIdentifier().getName(); - - if (sheet.getBookName() != null) { - int bookIndex = resolveBookIndex(sheet.getBookName()); - return new NameXPxg(bookIndex, sheetName, name); - } else { - return new NameXPxg(sheetName, name); - } - } - @Override - public Ptg get3DReferencePtg(CellReference cell, SheetIdentifier sheet) { - if (sheet.getBookName() != null) { - int bookIndex = resolveBookIndex(sheet.getBookName()); - return new Ref3DPxg(bookIndex, sheet, cell); - } else { - return new Ref3DPxg(sheet, cell); - } - } - @Override - public Ptg get3DReferencePtg(AreaReference area, SheetIdentifier sheet) { - if (sheet.getBookName() != null) { - int bookIndex = resolveBookIndex(sheet.getBookName()); - return new Area3DPxg(bookIndex, sheet, area); - } else { - return new Area3DPxg(sheet, area); - } - } - - @Override - public String resolveNameXText(NameXPtg n) { - int idx = n.getNameIndex(); - String name = null; - - // First, try to find it as a User Defined Function - IndexedUDFFinder udfFinder = (IndexedUDFFinder)getUDFFinder(); - name = udfFinder.getFunctionName(idx); - if (name != null) return name; - - // Otherwise, try it as a named range - XSSFName xname = _uBook.getNameAt(idx); - if (xname != null) { - name = xname.getNameName(); - } - - return name; - } - - @Override - public ExternalSheet getExternalSheet(int externSheetIndex) { - throw new IllegalStateException("HSSF-style external references are not supported for XSSF"); - } - @Override - public ExternalSheet getExternalSheet(String firstSheetName, String lastSheetName, int externalWorkbookNumber) { - String workbookName; - if (externalWorkbookNumber > 0) { - // External reference - reference is 1 based, link table is 0 based - int linkNumber = externalWorkbookNumber - 1; - ExternalLinksTable linkTable = _uBook.getExternalLinksTable().get(linkNumber); - workbookName = linkTable.getLinkedFileName(); - } else { - // Internal reference - workbookName = null; - } - - if (lastSheetName == null || firstSheetName.equals(lastSheetName)) { - return new ExternalSheet(workbookName, firstSheetName); - } else { - return new ExternalSheetRange(workbookName, firstSheetName, lastSheetName); - } - } - - @NotImplemented - public int getExternalSheetIndex(String workbookName, String sheetName) { - throw new RuntimeException("not implemented yet"); - } - @Override - public int getSheetIndex(String sheetName) { - return _uBook.getSheetIndex(sheetName); - } - - @Override - public String getSheetFirstNameByExternSheet(int externSheetIndex) { - int sheetIndex = convertFromExternalSheetIndex(externSheetIndex); - return _uBook.getSheetName(sheetIndex); - } - @Override - public String getSheetLastNameByExternSheet(int externSheetIndex) { - // XSSF does multi-sheet references differently, so this is the same as the first - return getSheetFirstNameByExternSheet(externSheetIndex); - } - - @Override - public String getNameText(NamePtg namePtg) { - return _uBook.getNameAt(namePtg.getIndex()).getNameName(); - } - @Override - public EvaluationName getName(NamePtg namePtg) { - int ix = namePtg.getIndex(); - return new Name(_uBook.getNameAt(ix), ix, this); - } - @Override - public XSSFName createName() { - return _uBook.createName(); - } - - private static String caseInsensitive(String s) { - return s.toUpperCase(Locale.ROOT); - } - - /* - * TODO: data tables are stored at the workbook level in XSSF, but are bound to a single sheet. - * The current code structure has them hanging off XSSFSheet, but formulas reference them - * only by name (names are global, and case insensitive). - * This map stores names as lower case for case-insensitive lookups. - * - * FIXME: Caching tables by name here for fast formula lookup means the map is out of date if - * a table is renamed or added/removed to a sheet after the map is created. - * - * Perhaps tables can be managed similar to PivotTable references above? - */ - private Map<String, XSSFTable> getTableCache() { - if ( _tableCache != null ) { - return _tableCache; - } - // FIXME: use org.apache.commons.collections.map.CaseInsensitiveMap - _tableCache = new HashMap<>(); - - for (Sheet sheet : _uBook) { - for (XSSFTable tbl : ((XSSFSheet)sheet).getTables()) { - String lname = caseInsensitive(tbl.getName()); - _tableCache.put(lname, tbl); - } - } - return _tableCache; - } - - /** - * Returns the data table with the given name (case insensitive). - * Tables are cached for performance (formula evaluation looks them up by name repeatedly). - * After the first table lookup, adding or removing a table from the document structure will cause trouble. - * This is meant to be used on documents whose structure is essentially static at the point formulas are evaluated. - * - * @param name the data table name (case-insensitive) - * @return The Data table in the workbook named <tt>name</tt>, or <tt>null</tt> if no table is named <tt>name</tt>. - * @since 3.15 beta 2 - */ - @Override - public XSSFTable getTable(String name) { - if (name == null) return null; - String lname = caseInsensitive(name); - return getTableCache().get(lname); - } - - @Override - public UDFFinder getUDFFinder(){ - return _uBook.getUDFFinder(); - } - - @Override - public SpreadsheetVersion getSpreadsheetVersion(){ - return SpreadsheetVersion.EXCEL2007; - } - - private static final class Name implements EvaluationName { - - private final XSSFName _nameRecord; - private final int _index; - private final FormulaParsingWorkbook _fpBook; - - public Name(XSSFName name, int index, FormulaParsingWorkbook fpBook) { - _nameRecord = name; - _index = index; - _fpBook = fpBook; - } - - public Ptg[] getNameDefinition() { - - return FormulaParser.parse(_nameRecord.getRefersToFormula(), _fpBook, FormulaType.NAMEDRANGE, _nameRecord.getSheetIndex()); - } - - public String getNameText() { - return _nameRecord.getNameName(); - } - - public boolean hasFormula() { - // TODO - no idea if this is right - CTDefinedName ctn = _nameRecord.getCTName(); - String strVal = ctn.getStringValue(); - return !ctn.getFunction() && strVal != null && strVal.length() > 0; - } - - public boolean isFunctionName() { - return _nameRecord.isFunctionName(); - } - - public boolean isRange() { - return hasFormula(); // TODO - is this right? - } - public NamePtg createPtg() { - return new NamePtg(_index); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java deleted file mode 100644 index bbad20e518..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java +++ /dev/null @@ -1,86 +0,0 @@ -/* ==================================================================== - 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.ss.formula.BaseFormulaEvaluator; -import org.apache.poi.ss.formula.EvaluationCell; -import org.apache.poi.ss.formula.EvaluationWorkbook; -import org.apache.poi.ss.formula.WorkbookEvaluator; -import org.apache.poi.ss.formula.eval.BoolEval; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.eval.NumberEval; -import org.apache.poi.ss.formula.eval.StringEval; -import org.apache.poi.ss.formula.eval.ValueEval; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.CellValue; -import org.apache.poi.ss.usermodel.RichTextString; - -/** - * Internal POI use only - parent of XSSF and SXSSF formula evaluators - */ -public abstract class BaseXSSFFormulaEvaluator extends BaseFormulaEvaluator { - protected BaseXSSFFormulaEvaluator(WorkbookEvaluator bookEvaluator) { - super(bookEvaluator); - } - @Override - protected RichTextString createRichTextString(String str) { - return new XSSFRichTextString(str); - } - - /** - * Turns a XSSFCell / SXSSFCell into a XSSFEvaluationCell - */ - protected abstract EvaluationCell toEvaluationCell(Cell cell); - - /** - * Returns a CellValue wrapper around the supplied ValueEval instance. - */ - protected CellValue evaluateFormulaCellValue(Cell cell) { - EvaluationCell evalCell = toEvaluationCell(cell); - ValueEval eval = _bookEvaluator.evaluate(evalCell); - if (eval instanceof NumberEval) { - NumberEval ne = (NumberEval) eval; - return new CellValue(ne.getNumberValue()); - } - if (eval instanceof BoolEval) { - BoolEval be = (BoolEval) eval; - return CellValue.valueOf(be.getBooleanValue()); - } - if (eval instanceof StringEval) { - StringEval ne = (StringEval) eval; - return new CellValue(ne.getStringValue()); - } - if (eval instanceof ErrorEval) { - return CellValue.getError(((ErrorEval)eval).getErrorCode()); - } - throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")"); - } - - protected void setCellType(Cell cell, CellType cellType) { - if (cell instanceof XSSFCell) { - EvaluationWorkbook evaluationWorkbook = getEvaluationWorkbook(); - BaseXSSFEvaluationWorkbook xewb = BaseXSSFEvaluationWorkbook.class.isAssignableFrom(evaluationWorkbook.getClass()) ? (BaseXSSFEvaluationWorkbook) evaluationWorkbook : null; - - ((XSSFCell) cell).setCellType(cellType, xewb); - } else { - // could be an SXSSFCell - cell.setCellType(cellType); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/CustomIndexedColorMap.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/CustomIndexedColorMap.java deleted file mode 100644 index 05d442db75..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/CustomIndexedColorMap.java +++ /dev/null @@ -1,65 +0,0 @@ -/* ==================================================================== - 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 java.util.List; - -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColors; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRgbColor; - -/** - * custom index color map, i.e. from the styles.xml definition - */ -public class CustomIndexedColorMap implements IndexedColorMap { - - private final byte[][] colorIndex; - - /** - * @param colors array of RGB triplets indexed by color index - */ - private CustomIndexedColorMap(byte [][] colors) { - this.colorIndex = colors; - } - - public byte[] getRGB(int index) { - if (colorIndex == null || index < 0 || index >= colorIndex.length) return null; - return colorIndex[index]; - } - - /** - * OOXML spec says if this exists it must have all indexes. - * <p> - * From the OOXML Spec, Part 1, section 18.8.27: - * <p><i> - * This element contains a sequence of RGB color values that correspond to color indexes (zero-based). When - * using the default indexed color palette, the values are not written out, but instead are implied. When the color - * palette has been modified from default, then the entire color palette is written out. - * </i> - * @param colors CTColors from styles.xml possibly defining a custom color indexing scheme - * @return custom indexed color map or null if none defined in the document - */ - public static CustomIndexedColorMap fromColors(CTColors colors) { - if (colors == null || ! colors.isSetIndexedColors()) return null; - - List<CTRgbColor> rgbColorList = colors.getIndexedColors().getRgbColorList(); - byte[][] customColorIndex = new byte[rgbColorList.size()][3]; - for (int i=0; i < rgbColorList.size(); i++) { - customColorIndex[i] = rgbColorList.get(i).getRgb(); - } - return new CustomIndexedColorMap(customColorIndex); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/DefaultIndexedColorMap.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/DefaultIndexedColorMap.java deleted file mode 100644 index 0d2980b4b1..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/DefaultIndexedColorMap.java +++ /dev/null @@ -1,44 +0,0 @@ -/* ==================================================================== - 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.hssf.util.HSSFColor; - -/** - * Uses the legacy colors defined in HSSF for index lookups - */ -public class DefaultIndexedColorMap implements IndexedColorMap { - - /** - * @see org.apache.poi.xssf.usermodel.IndexedColorMap#getRGB(int) - */ - public byte[] getRGB(int index) { - return getDefaultRGB(index); - } - - /** - * @param index - * @return RGB bytes from HSSF default color by index - */ - public static byte[] getDefaultRGB(int index) { - HSSFColor hssfColor = HSSFColor.getIndexHash().get(index); - if (hssfColor == null) return null; - short[] rgbShort = hssfColor.getTriplet(); - return new byte[] {(byte) rgbShort[0], (byte) rgbShort[1], (byte) rgbShort[2]}; - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/IndexedColorMap.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/IndexedColorMap.java deleted file mode 100644 index eac3a037ed..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/IndexedColorMap.java +++ /dev/null @@ -1,31 +0,0 @@ -/* ==================================================================== - 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; - -/** - * Interface for color index to RGB mappings. - * May be either the default, built-in mappings - * or custom mappings defined in the document. - */ -public interface IndexedColorMap { - - /** - * @param index color index to look up - * @return the RGB array for the index, or null if the index is invalid/undefined - */ - byte[] getRGB(int index); -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/ListAutoNumber.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/ListAutoNumber.java deleted file mode 100644 index 5108813b28..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/ListAutoNumber.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ==================================================================== - * 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; - -/** - * Specifies type of automatic numbered bullet points that should be applied to a paragraph. - */ -public enum ListAutoNumber { - /** - * (a), (b), (c), ... - */ - ALPHA_LC_PARENT_BOTH, - /** - * (A), (B), (C), ... - */ - ALPHA_UC_PARENT_BOTH, - /** - * a), b), c), ... - */ - ALPHA_LC_PARENT_R, - /** - * A), B), C), ... - */ - ALPHA_UC_PARENT_R, - /** - * a., b., c., ... - */ - ALPHA_LC_PERIOD, - /** - * A., B., C., ... - */ - ALPHA_UC_PERIOD, - /** - * (1), (2), (3), ... - */ - ARABIC_PARENT_BOTH, - /** - * 1), 2), 3), ... - */ - ARABIC_PARENT_R, - - /** - * 1., 2., 3., ... - */ - ARABIC_PERIOD, - /** - * 1, 2, 3, ... - */ - ARABIC_PLAIN, - - /** - * (i), (ii), (iii), ... - */ - ROMAN_LC_PARENT_BOTH, - /** - * (I), (II), (III), ... - */ - ROMAN_UC_PARENT_BOTH, - /** - * i), ii), iii), ... - */ - ROMAN_LC_PARENT_R, - /** - * I), II), III), ... - */ - ROMAN_UC_PARENT_R, - /** - * i., ii., iii., ... - */ - ROMAN_LC_PERIOD , - /** - * I., II., III., ... - */ - ROMAN_UC_PERIOD, - /** - * Dbl-byte circle numbers - */ - CIRCLE_NUM_DB_PLAIN, - /** - * Wingdings black circle numbers - */ - CIRCLE_NUM_WD_BLACK_PLAIN, - /** - * Wingdings white circle numbers - */ - CIRCLE_NUM_WD_WHITE_PLAIN -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextAlign.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/TextAlign.java deleted file mode 100644 index b93a885c20..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextAlign.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * ==================================================================== - * 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; - -/** - * Specified a list of text alignment types - */ -public enum TextAlign { - /** - * Align text to the left margin. - */ - LEFT, - /** - * Align text in the center. - */ - CENTER, - - /** - * Align text to the right margin. - */ - RIGHT, - - /** - * Align text so that it is justified across the whole line. It - * is smart in the sense that it will not justify sentences - * which are short - */ - JUSTIFY, - JUSTIFY_LOW, - DIST, - THAI_DIST -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextAutofit.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/TextAutofit.java deleted file mode 100644 index 6e01b134fd..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextAutofit.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * ==================================================================== - * 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; - -/** - * Specifies a list of auto-fit types. - * <p> - * Autofit specifies that a shape should be auto-fit to fully contain the text described within it. - * Auto-fitting is when text within a shape is scaled in order to contain all the text inside - * </p> - */ -public enum TextAutofit { - /** - * Specifies that text within the text body should not be auto-fit to the bounding box. - * Auto-fitting is when text within a text box is scaled in order to remain inside - * the text box. - */ - NONE, - /** - * Specifies that text within the text body should be normally auto-fit to the bounding box. - * Autofitting is when text within a text box is scaled in order to remain inside the text box. - * - * <p> - * <em>Example:</em> Consider the situation where a user is building a diagram and needs - * to have the text for each shape that they are using stay within the bounds of the shape. - * An easy way this might be done is by using NORMAL autofit - * </p> - */ - NORMAL, - /** - * Specifies that a shape should be auto-fit to fully contain the text described within it. - * Auto-fitting is when text within a shape is scaled in order to contain all the text inside. - * - * <p> - * <em>Example:</em> Consider the situation where a user is building a diagram and needs to have - * the text for each shape that they are using stay within the bounds of the shape. - * An easy way this might be done is by using SHAPE autofit - * </p> - */ - SHAPE -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextCap.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/TextCap.java deleted file mode 100644 index 9202e92b42..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextCap.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * ==================================================================== - * 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; - -/** - * Text Capitalization that is to be applied to the text run. This is a render-only - * modification and does not affect the actual characters stored in the text run. - */ -public enum TextCap { - NONE, - SMALL, - ALL -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextDirection.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/TextDirection.java deleted file mode 100644 index f91fcca7a8..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextDirection.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * ==================================================================== - * 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; - -/** - * Vertical Text Types - */ -public enum TextDirection { - /** - * Horizontal text. This should be default. - */ - HORIZONTAL, - /** - * Vertical orientation. - * (each line is 90 degrees rotated clockwise, so it goes - * from top to bottom; each next line is to the left from - * the previous one). - */ - VERTICAL, - /** - * Vertical orientation. - * (each line is 270 degrees rotated clockwise, so it goes - * from bottom to top; each next line is to the right from - * the previous one). - */ - VERTICAL_270, - /** - * Determines if all of the text is vertical - * ("one letter on top of another"). - */ - STACKED -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextFontAlign.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/TextFontAlign.java deleted file mode 100644 index 96417980c4..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextFontAlign.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ==================================================================== - * 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; - -/** - * Specified a list of text font alignment types - */ -public enum TextFontAlign { - /** - * Automatic alignment - */ - AUTO, - /** - * Align text to the top. - */ - TOP, - /** - * Align text in the center. - */ - CENTER, - - /** - * Align text to the baseline. - */ - BASELINE, - - /** - * Align text to the bottom. - */ - BOTTOM -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextHorizontalOverflow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/TextHorizontalOverflow.java deleted file mode 100644 index b1fe0c18d3..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextHorizontalOverflow.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ==================================================================== - * 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; - -/** - * Text Horizontal Overflow - */ -public enum TextHorizontalOverflow { - /** - * When a big character does not fit into a line, allow a - * horizontal overflow. - */ - OVERFLOW, - - /** - * When a big character does not fit into a line, clip it at - * the proper horizontal overflow. - */ - CLIP -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextVerticalOverflow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/TextVerticalOverflow.java deleted file mode 100644 index 87d3e40189..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/TextVerticalOverflow.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * ==================================================================== - * 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; - -/** - * Text Vertical Overflow - */ -public enum TextVerticalOverflow { - /** - * Overflow the text and pay no attention to top and bottom barriers. - */ - OVERFLOW, - - /** - * Pay attention to top and bottom barriers. Use an - * ellipsis to denote that there is text which is not visible. - */ - ELLIPSIS, - - /** - * Pay attention to top and bottom barriers. Provide no - * indication that there is text which is not visible. - */ - CLIP -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java deleted file mode 100644 index de855787be..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java +++ /dev/null @@ -1,27 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.ChildAnchor; - -/** - * An anchor is what specifics the position of a shape within a client object - * or within another containing shape. - */ -public abstract class XSSFAnchor implements ChildAnchor { -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAutoFilter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAutoFilter.java deleted file mode 100644 index d363ab31ab..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAutoFilter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.AutoFilter; - -/** - * Represents autofiltering for the specified worksheet. - * - * @author Yegor Kozlov - */ -public final class XSSFAutoFilter implements AutoFilter { - private XSSFSheet _sheet; - - XSSFAutoFilter(XSSFSheet sheet){ - _sheet = sheet; - } - -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java deleted file mode 100644 index 4afbcb123e..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java +++ /dev/null @@ -1,346 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.BorderFormatting; -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.Color; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle; - -/** - * XSSF high level representation for Border Formatting component - * of Conditional Formatting settings - */ -public class XSSFBorderFormatting implements BorderFormatting { - IndexedColorMap _colorMap; - CTBorder _border; - - /*package*/ XSSFBorderFormatting(CTBorder border, IndexedColorMap colorMap) { - _border = border; - _colorMap = colorMap; - } - - @Override - public BorderStyle getBorderBottom() { - return getBorderStyle(_border.getBottom()); - } - - @Override - public BorderStyle getBorderDiagonal() { - return getBorderStyle(_border.getDiagonal()); - } - - @Override - public BorderStyle getBorderLeft() { - return getBorderStyle(_border.getLeft()); - } - - @Override - public BorderStyle getBorderRight() { - return getBorderStyle(_border.getRight()); - } - - @Override - public BorderStyle getBorderTop() { - return getBorderStyle(_border.getTop()); - } - - @Override - public XSSFColor getBottomBorderColorColor() { - return getColor(_border.getBottom()); - } - @Override - public short getBottomBorderColor() { - return getIndexedColor(getBottomBorderColorColor()); - } - - @Override - public XSSFColor getDiagonalBorderColorColor() { - return getColor(_border.getDiagonal()); - } - @Override - public short getDiagonalBorderColor() { - return getIndexedColor(getDiagonalBorderColorColor()); - } - - @Override - public XSSFColor getLeftBorderColorColor() { - return getColor(_border.getLeft()); - } - @Override - public short getLeftBorderColor() { - return getIndexedColor(getLeftBorderColorColor()); - } - - @Override - public XSSFColor getRightBorderColorColor() { - return getColor(_border.getRight()); - } - @Override - public short getRightBorderColor() { - return getIndexedColor(getRightBorderColorColor()); - } - - @Override - public XSSFColor getTopBorderColorColor() { - return getColor(_border.getTop()); - } - @Override - public short getTopBorderColor() { - return getIndexedColor(getTopBorderColorColor()); - } - - @Override - public void setBorderBottom(BorderStyle border) { - CTBorderPr pr = _border.isSetBottom() ? _border.getBottom() : _border.addNewBottom(); - if(border == BorderStyle.NONE) _border.unsetBottom(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - @Override - public void setBorderDiagonal(BorderStyle border) { - CTBorderPr pr = _border.isSetDiagonal() ? _border.getDiagonal() : _border.addNewDiagonal(); - if(border == BorderStyle.NONE) _border.unsetDiagonal(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - @Override - public void setBorderLeft(BorderStyle border) { - CTBorderPr pr = _border.isSetLeft() ? _border.getLeft() : _border.addNewLeft(); - if(border == BorderStyle.NONE) _border.unsetLeft(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - @Override - public void setBorderRight(BorderStyle border) { - CTBorderPr pr = _border.isSetRight() ? _border.getRight() : _border.addNewRight(); - if(border == BorderStyle.NONE) _border.unsetRight(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - @Override - public void setBorderTop(BorderStyle border) { - CTBorderPr pr = _border.isSetTop() ? _border.getTop() : _border.addNewTop(); - if(border == BorderStyle.NONE) _border.unsetTop(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - @Override - public void setBottomBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setBottomBorderColor((CTColor)null); - else setBottomBorderColor(xcolor.getCTColor()); - } - @Override - public void setBottomBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setBottomBorderColor(ctColor); - } - public void setBottomBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetBottom() ? _border.getBottom() : _border.addNewBottom(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public void setDiagonalBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setDiagonalBorderColor((CTColor)null); - else setDiagonalBorderColor(xcolor.getCTColor()); - } - @Override - public void setDiagonalBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setDiagonalBorderColor(ctColor); - } - public void setDiagonalBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetDiagonal() ? _border.getDiagonal() : _border.addNewDiagonal(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public void setLeftBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setLeftBorderColor((CTColor)null); - else setLeftBorderColor(xcolor.getCTColor()); - } - @Override - public void setLeftBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setLeftBorderColor(ctColor); - } - public void setLeftBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetLeft() ? _border.getLeft() : _border.addNewLeft(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public void setRightBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setRightBorderColor((CTColor)null); - else setRightBorderColor(xcolor.getCTColor()); - } - @Override - public void setRightBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setRightBorderColor(ctColor); - } - public void setRightBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetRight() ? _border.getRight() : _border.addNewRight(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public void setTopBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setTopBorderColor((CTColor)null); - else setTopBorderColor(xcolor.getCTColor()); - } - @Override - public void setTopBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setTopBorderColor(ctColor); - } - public void setTopBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetTop() ? _border.getTop() : _border.addNewTop(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - @Override - public BorderStyle getBorderVertical() { - return getBorderStyle(_border.getVertical()); - } - - @Override - public BorderStyle getBorderHorizontal() { - return getBorderStyle(_border.getHorizontal()); - } - - public short getVerticalBorderColor() { - return getIndexedColor(getVerticalBorderColorColor()); - } - - public XSSFColor getVerticalBorderColorColor() { - return getColor(_border.getVertical()); - } - - public short getHorizontalBorderColor() { - return getIndexedColor(getHorizontalBorderColorColor()); - } - - public XSSFColor getHorizontalBorderColorColor() { - return getColor(_border.getHorizontal()); - } - - public void setBorderHorizontal(BorderStyle border) { - CTBorderPr pr = _border.isSetHorizontal() ? _border.getHorizontal() : _border.addNewHorizontal(); - if(border == BorderStyle.NONE) _border.unsetHorizontal(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - public void setBorderVertical(BorderStyle border) { - CTBorderPr pr = _border.isSetVertical() ? _border.getVertical() : _border.addNewVertical(); - if(border == BorderStyle.NONE) _border.unsetVertical(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - } - - public void setHorizontalBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setHorizontalBorderColor(ctColor); - } - - public void setHorizontalBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setBottomBorderColor((CTColor)null); - else setHorizontalBorderColor(xcolor.getCTColor()); - } - - public void setHorizontalBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetHorizontal() ? _border.getHorizontal() : _border.addNewHorizontal(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - public void setVerticalBorderColor(short color) { - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - setVerticalBorderColor(ctColor); - } - - public void setVerticalBorderColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) setBottomBorderColor((CTColor)null); - else setVerticalBorderColor(xcolor.getCTColor()); - } - - public void setVerticalBorderColor(CTColor color) { - CTBorderPr pr = _border.isSetVertical() ? _border.getVertical() : _border.addNewVertical(); - if (color == null) { - pr.unsetColor(); - } else { - pr.setColor(color); - } - } - - /** - * @return BorderStyle from the given element's style, or NONE if border is null - */ - private BorderStyle getBorderStyle(CTBorderPr borderPr) { - if (borderPr == null) return BorderStyle.NONE; - STBorderStyle.Enum ptrn = borderPr.getStyle(); - return ptrn == null ? BorderStyle.NONE : BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - private short getIndexedColor(XSSFColor color) { - return color == null ? 0 : color.getIndexed(); - } - - private XSSFColor getColor(CTBorderPr pr) { - return pr == null ? null : XSSFColor.from(pr.getColor(), _colorMap); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBuiltinTableStyle.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBuiltinTableStyle.java deleted file mode 100644 index 2ba065b766..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBuiltinTableStyle.java +++ /dev/null @@ -1,487 +0,0 @@ -/* ==================================================================== - 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 java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; -import java.nio.charset.StandardCharsets; -import java.util.EnumMap; -import java.util.Map; - -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.apache.poi.ooxml.util.DocumentHelper; -import org.apache.poi.ss.usermodel.DifferentialStyleProvider; -import org.apache.poi.ss.usermodel.TableStyle; -import org.apache.poi.ss.usermodel.TableStyleType; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.XMLHelper; -import org.apache.poi.xssf.model.StylesTable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * Table style names defined in the OOXML spec. - * The actual styling is defined in presetTableStyles.xml - */ -public enum XSSFBuiltinTableStyle { - /***/ - TableStyleDark1, - /***/ - TableStyleDark2, - /***/ - TableStyleDark3, - /***/ - TableStyleDark4, - /***/ - TableStyleDark5, - /***/ - TableStyleDark6, - /***/ - TableStyleDark7, - /***/ - TableStyleDark8, - /***/ - TableStyleDark9, - /***/ - TableStyleDark10, - /***/ - TableStyleDark11, - /***/ - TableStyleLight1, - /***/ - TableStyleLight2, - /***/ - TableStyleLight3, - /***/ - TableStyleLight4, - /***/ - TableStyleLight5, - /***/ - TableStyleLight6, - /***/ - TableStyleLight7, - /***/ - TableStyleLight8, - /***/ - TableStyleLight9, - /***/ - TableStyleLight10, - /***/ - TableStyleLight11, - /***/ - TableStyleLight12, - /***/ - TableStyleLight13, - /***/ - TableStyleLight14, - /***/ - TableStyleLight15, - /***/ - TableStyleLight16, - /***/ - TableStyleLight17, - /***/ - TableStyleLight18, - /***/ - TableStyleLight19, - /***/ - TableStyleLight20, - /***/ - TableStyleLight21, - /***/ - TableStyleMedium1, - /***/ - TableStyleMedium2, - /***/ - TableStyleMedium3, - /***/ - TableStyleMedium4, - /***/ - TableStyleMedium5, - /***/ - TableStyleMedium6, - /***/ - TableStyleMedium7, - /***/ - TableStyleMedium8, - /***/ - TableStyleMedium9, - /***/ - TableStyleMedium10, - /***/ - TableStyleMedium11, - /***/ - TableStyleMedium12, - /***/ - TableStyleMedium13, - /***/ - TableStyleMedium14, - /***/ - TableStyleMedium15, - /***/ - TableStyleMedium16, - /***/ - TableStyleMedium17, - /***/ - TableStyleMedium18, - /***/ - TableStyleMedium19, - /***/ - TableStyleMedium20, - /***/ - TableStyleMedium21, - /***/ - TableStyleMedium22, - /***/ - TableStyleMedium23, - /***/ - TableStyleMedium24, - /***/ - TableStyleMedium25, - /***/ - TableStyleMedium26, - /***/ - TableStyleMedium27, - /***/ - TableStyleMedium28, - /***/ - PivotStyleMedium1, - /***/ - PivotStyleMedium2, - /***/ - PivotStyleMedium3, - /***/ - PivotStyleMedium4, - /***/ - PivotStyleMedium5, - /***/ - PivotStyleMedium6, - /***/ - PivotStyleMedium7, - /***/ - PivotStyleMedium8, - /***/ - PivotStyleMedium9, - /***/ - PivotStyleMedium10, - /***/ - PivotStyleMedium11, - /***/ - PivotStyleMedium12, - /***/ - PivotStyleMedium13, - /***/ - PivotStyleMedium14, - /***/ - PivotStyleMedium15, - /***/ - PivotStyleMedium16, - /***/ - PivotStyleMedium17, - /***/ - PivotStyleMedium18, - /***/ - PivotStyleMedium19, - /***/ - PivotStyleMedium20, - /***/ - PivotStyleMedium21, - /***/ - PivotStyleMedium22, - /***/ - PivotStyleMedium23, - /***/ - PivotStyleMedium24, - /***/ - PivotStyleMedium25, - /***/ - PivotStyleMedium26, - /***/ - PivotStyleMedium27, - /***/ - PivotStyleMedium28, - /***/ - PivotStyleLight1, - /***/ - PivotStyleLight2, - /***/ - PivotStyleLight3, - /***/ - PivotStyleLight4, - /***/ - PivotStyleLight5, - /***/ - PivotStyleLight6, - /***/ - PivotStyleLight7, - /***/ - PivotStyleLight8, - /***/ - PivotStyleLight9, - /***/ - PivotStyleLight10, - /***/ - PivotStyleLight11, - /***/ - PivotStyleLight12, - /***/ - PivotStyleLight13, - /***/ - PivotStyleLight14, - /***/ - PivotStyleLight15, - /***/ - PivotStyleLight16, - /***/ - PivotStyleLight17, - /***/ - PivotStyleLight18, - /***/ - PivotStyleLight19, - /***/ - PivotStyleLight20, - /***/ - PivotStyleLight21, - /***/ - PivotStyleLight22, - /***/ - PivotStyleLight23, - /***/ - PivotStyleLight24, - /***/ - PivotStyleLight25, - /***/ - PivotStyleLight26, - /***/ - PivotStyleLight27, - /***/ - PivotStyleLight28, - /***/ - PivotStyleDark1, - /***/ - PivotStyleDark2, - /***/ - PivotStyleDark3, - /***/ - PivotStyleDark4, - /***/ - PivotStyleDark5, - /***/ - PivotStyleDark6, - /***/ - PivotStyleDark7, - /***/ - PivotStyleDark8, - /***/ - PivotStyleDark9, - /***/ - PivotStyleDark10, - /***/ - PivotStyleDark11, - /***/ - PivotStyleDark12, - /***/ - PivotStyleDark13, - /***/ - PivotStyleDark14, - /***/ - PivotStyleDark15, - /***/ - PivotStyleDark16, - /***/ - PivotStyleDark17, - /***/ - PivotStyleDark18, - /***/ - PivotStyleDark19, - /***/ - PivotStyleDark20, - /***/ - PivotStyleDark21, - /***/ - PivotStyleDark22, - /***/ - PivotStyleDark23, - /***/ - PivotStyleDark24, - /***/ - PivotStyleDark25, - /***/ - PivotStyleDark26, - /***/ - PivotStyleDark27, - /***/ - PivotStyleDark28, - ; - - /** - * Interestingly, this is initialized after the enum instances, so using an {@link EnumMap} works. - */ - private static final Map<XSSFBuiltinTableStyle, TableStyle> styleMap = new EnumMap<>(XSSFBuiltinTableStyle.class); - - private XSSFBuiltinTableStyle() { - } - - /** - * @return built-in {@link TableStyle} definition - */ - public TableStyle getStyle() { - init(); - return styleMap.get(this); - } - - /** - * NOTE: only checks by name, not definition. - * - * @param style - * @return true if the style represents a built-in style, false if it is null or a custom style - */ - public static boolean isBuiltinStyle(TableStyle style) { - if (style == null) return false; - try { - XSSFBuiltinTableStyle.valueOf(style.getName()); - return true; - } catch (IllegalArgumentException e) { - return false; - } - } - - /** - * Only init once - thus the synchronized. Lazy, after creating instances, - * and only when a style is actually needed, to avoid overhead for uses - * that don't need the actual style definitions. - * <p> - * Public so clients can initialize the map on startup rather than lazily - * during evaluation if desired. - */ - public static synchronized void init() { - if (!styleMap.isEmpty()) return; - - /* - * initialize map. Every built-in has this format: - * <styleName> - * <dxfs> - * <dxf>...</dxf> - * ... - * </dxfs> - * <tableStyles count="1"> - * <tableStyle>...</tableStyle> - * </tableStyles> - * </styleName> - */ - try { - final InputStream is = XSSFBuiltinTableStyle.class.getResourceAsStream("presetTableStyles.xml"); - try { - final Document doc = DocumentHelper.readDocument(is); - - final NodeList styleNodes = doc.getDocumentElement().getChildNodes(); - for (int i = 0; i < styleNodes.getLength(); i++) { - final Node node = styleNodes.item(i); - if (node.getNodeType() != Node.ELEMENT_NODE) continue; // only care about elements - final Element tag = (Element) node; - String styleName = tag.getTagName(); - XSSFBuiltinTableStyle builtIn = XSSFBuiltinTableStyle.valueOf(styleName); - - Node dxfsNode = tag.getElementsByTagName("dxfs").item(0); - Node tableStyleNode = tag.getElementsByTagName("tableStyles").item(0); - - // hack because I can't figure out how to get XMLBeans to parse a sub-element in a standalone manner - // - build a fake styles.xml file with just this built-in - StylesTable styles = new StylesTable(); - styles.readFrom(new ByteArrayInputStream(styleXML(dxfsNode, tableStyleNode).getBytes(StandardCharsets.UTF_8))); - styleMap.put(builtIn, new XSSFBuiltinTypeStyleStyle(builtIn, styles.getExplicitTableStyle(styleName))); - } - } finally { - IOUtils.closeQuietly(is); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static String styleXML(Node dxfsNode, Node tableStyleNode) throws IOException, TransformerException { - // built-ins doc uses 1-based dxf indexing, Excel uses 0 based. - // add a dummy node to adjust properly. - dxfsNode.insertBefore(dxfsNode.getOwnerDocument().createElement("dxf"), dxfsNode.getFirstChild()); - - StringBuilder sb = new StringBuilder(); - sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n") - .append("<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" ") - .append("xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" ") - .append("xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" ") - .append("xmlns:x16r2=\"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main\" ") - .append("mc:Ignorable=\"x14ac x16r2\">\n"); - sb.append(writeToString(dxfsNode)); - sb.append(writeToString(tableStyleNode)); - sb.append("</styleSheet>"); - return sb.toString(); - } - - private static String writeToString(Node node) throws IOException, TransformerException { - try (StringWriter sw = new StringWriter()){ - Transformer transformer = XMLHelper.newTransformer(); - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - transformer.transform(new DOMSource(node), new StreamResult(sw)); - return sw.toString(); - } - } - - /** - * implementation for built-in styles - */ - protected static class XSSFBuiltinTypeStyleStyle implements TableStyle { - - private final XSSFBuiltinTableStyle builtIn; - private final TableStyle style; - - /** - * @param builtIn - * @param style - */ - protected XSSFBuiltinTypeStyleStyle(XSSFBuiltinTableStyle builtIn, TableStyle style) { - this.builtIn = builtIn; - this.style = style; - } - - public String getName() { - return style.getName(); - } - - public int getIndex() { - return builtIn.ordinal(); - } - - public boolean isBuiltin() { - return true; - } - - public DifferentialStyleProvider getStyle(TableStyleType type) { - return style.getStyle(type); - } - - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java deleted file mode 100644 index d2d135b3e2..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ /dev/null @@ -1,1263 +0,0 @@ -/* ==================================================================== - 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 java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.time.LocalDateTime; -import java.util.Calendar; -import java.util.Date; - -import org.apache.poi.ss.SpreadsheetVersion; -import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaRenderer; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.formula.SharedFormula; -import org.apache.poi.ss.formula.eval.ErrorEval; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellBase; -import org.apache.poi.ss.usermodel.CellCopyPolicy; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.Comment; -import org.apache.poi.ss.usermodel.DataFormatter; -import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.FormulaError; -import org.apache.poi.ss.usermodel.FormulaEvaluator; -import org.apache.poi.ss.usermodel.Hyperlink; -import org.apache.poi.ss.usermodel.RichTextString; -import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; -import org.apache.poi.ss.util.CellAddress; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.util.Beta; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LocaleUtil; -import org.apache.poi.util.Removal; -import org.apache.poi.xssf.model.SharedStringsTable; -import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.model.CalculationChain; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType; - -/** - * High level representation of a cell in a row of a spreadsheet. - * <p> - * Cells can be numeric, formula-based or string-based (text). The cell type - * specifies this. String cells cannot contain numbers and numeric cells cannot - * contain strings (at least according to our model). Client apps should do the - * conversions themselves. Formula cells have the formula string, as well as - * the formula result, which can be numeric or string. - * </p> - * <p> - * Cells should have their number (0 based) before being added to a row. Only - * cells that have values should be added. - * </p> - */ -public final class XSSFCell extends CellBase { - - private static final String FALSE_AS_STRING = "0"; - private static final String TRUE_AS_STRING = "1"; - private static final String FALSE = "FALSE"; - private static final String TRUE = "TRUE"; - - /** - * the xml bean containing information about the cell's location, value, - * data type, formatting, and formula - */ - private CTCell _cell; - - /** - * the XSSFRow this cell belongs to - */ - private final XSSFRow _row; - - /** - * 0-based column index - */ - private int _cellNum; - - /** - * Table of strings shared across this workbook. - * If two cells contain the same string, then the cell value is the same index into SharedStringsTable - */ - private SharedStringsTable _sharedStringSource; - - /** - * Table of cell styles shared across all cells in a workbook. - */ - private StylesTable _stylesSource; - - /** - * Construct a XSSFCell. - * - * @param row the parent row. - * @param cell the xml bean containing information about the cell. - */ - protected XSSFCell(XSSFRow row, CTCell cell) { - _cell = cell; - _row = row; - if (cell.getR() != null) { - _cellNum = new CellReference(cell.getR()).getCol(); - } else { - int prevNum = row.getLastCellNum(); - if(prevNum != -1){ - _cellNum = row.getCell(prevNum-1, MissingCellPolicy.RETURN_NULL_AND_BLANK).getColumnIndex() + 1; - } - } - _sharedStringSource = row.getSheet().getWorkbook().getSharedStringSource(); - _stylesSource = row.getSheet().getWorkbook().getStylesSource(); - } - - /** - * {@inheritDoc} - */ - @Override - protected SpreadsheetVersion getSpreadsheetVersion() { - return SpreadsheetVersion.EXCEL2007; - } - - /** - * Copy cell value, formula and style, from srcCell per cell copy policy - * If srcCell is null, clears the cell value and cell style per cell copy policy - * - * This does not shift references in formulas. Use {@link org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter} to shift references in formulas. - * - * @param srcCell The cell to take value, formula and style from - * @param policy The policy for copying the information, see {@link CellCopyPolicy} - * @throws IllegalArgumentException if copy cell style and srcCell is from a different workbook - */ - @Beta - @Internal - public void copyCellFrom(Cell srcCell, CellCopyPolicy policy) { - // Copy cell value (cell type is updated implicitly) - if (policy.isCopyCellValue()) { - if (srcCell != null) { - CellType copyCellType = srcCell.getCellType(); - if (copyCellType == CellType.FORMULA && !policy.isCopyCellFormula()) { - // Copy formula result as value - // FIXME: Cached value may be stale - copyCellType = srcCell.getCachedFormulaResultType(); - } - switch (copyCellType) { - case NUMERIC: - // DataFormat is not copied unless policy.isCopyCellStyle is true - if (DateUtil.isCellDateFormatted(srcCell)) { - setCellValue(srcCell.getDateCellValue()); - } - else { - setCellValue(srcCell.getNumericCellValue()); - } - break; - case STRING: - setCellValue(srcCell.getStringCellValue()); - break; - case FORMULA: - setCellFormula(srcCell.getCellFormula()); - break; - case BLANK: - setBlank(); - break; - case BOOLEAN: - setCellValue(srcCell.getBooleanCellValue()); - break; - case ERROR: - setCellErrorValue(srcCell.getErrorCellValue()); - break; - - default: - throw new IllegalArgumentException("Invalid cell type " + srcCell.getCellType()); - } - } else { //srcCell is null - setBlank(); - } - } - - // Copy CellStyle - if (policy.isCopyCellStyle()) { - setCellStyle(srcCell == null ? null : srcCell.getCellStyle()); - } - - final Hyperlink srcHyperlink = (srcCell == null) ? null : srcCell.getHyperlink(); - - if (policy.isMergeHyperlink()) { - // if srcCell doesn't have a hyperlink and destCell has a hyperlink, don't clear destCell's hyperlink - if (srcHyperlink != null) { - setHyperlink(new XSSFHyperlink(srcHyperlink)); - } - } else if (policy.isCopyHyperlink()) { - // overwrite the hyperlink at dest cell with srcCell's hyperlink - // if srcCell doesn't have a hyperlink, clear the hyperlink (if one exists) at destCell - setHyperlink(srcHyperlink == null ? null : new XSSFHyperlink(srcHyperlink)); - } - } - - /** - * @return table of strings shared across this workbook - */ - protected SharedStringsTable getSharedStringSource() { - return _sharedStringSource; - } - - /** - * @return table of cell styles shared across this workbook - */ - protected StylesTable getStylesSource() { - return _stylesSource; - } - - /** - * Returns the sheet this cell belongs to - * - * @return the sheet this cell belongs to - */ - @Override - public XSSFSheet getSheet() { - return getRow().getSheet(); - } - - /** - * Returns the row this cell belongs to - * - * @return the row this cell belongs to - */ - @Override - public XSSFRow getRow() { - return _row; - } - - /** - * Get the value of the cell as a boolean. - * <p> - * For strings, numbers, and errors, we throw an exception. For blank cells we return a false. - * </p> - * @return the value of the cell as a boolean - * @throws IllegalStateException if the cell type returned by {@link #getCellType()} - * is not {@link CellType#BOOLEAN}, {@link CellType#BLANK} or {@link CellType#FORMULA} - */ - @Override - public boolean getBooleanCellValue() { - CellType cellType = getCellType(); - switch(cellType) { - case BLANK: - return false; - case BOOLEAN: - return _cell.isSetV() && TRUE_AS_STRING.equals(_cell.getV()); - case FORMULA: - //YK: should throw an exception if requesting boolean value from a non-boolean formula - return _cell.isSetV() && TRUE_AS_STRING.equals(_cell.getV()); - default: - throw typeMismatch(CellType.BOOLEAN, cellType, false); - } - } - - /** - * Set a boolean value for the cell - * - * @param value the boolean value to set this cell to. For formulas we'll set the - * precalculated value, for booleans we'll set its value. For other types we - * will change the cell to a boolean cell and set its value. - */ - @Override - public void setCellValue(boolean value) { - _cell.setT(STCellType.B); - _cell.setV(value ? TRUE_AS_STRING : FALSE_AS_STRING); - } - - /** - * Get the value of the cell as a number. - * <p> - * For strings we throw an exception. For blank cells we return a 0. - * For formulas or error cells we return the precalculated value; - * </p> - * @return the value of the cell as a number - * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is {@link CellType#STRING} - * @exception NumberFormatException if the cell value isn't a parsable <code>double</code>. - * @see DataFormatter for turning this number into a string similar to that which Excel would render this number as. - */ - @Override - public double getNumericCellValue() { - CellType valueType = isFormulaCell() ? getCachedFormulaResultType() : getCellType(); - switch(valueType) { - case BLANK: - return 0.0; - case NUMERIC: - if(_cell.isSetV()) { - String v = _cell.getV(); - if (v.isEmpty()) { - return 0.0; - } - try { - return Double.parseDouble(v); - } catch(NumberFormatException e) { - throw typeMismatch(CellType.NUMERIC, CellType.STRING, false); - } - } else { - return 0.0; - } - case FORMULA: - throw new AssertionError(); - default: - throw typeMismatch(CellType.NUMERIC, valueType, false); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void setCellValueImpl(double value) { - _cell.setT(STCellType.N); - _cell.setV(String.valueOf(value)); - } - - /** - * Get the value of the cell as a string - * <p> - * For numeric cells we throw an exception. For blank cells we return an empty string. - * For formulaCells that are not string Formulas, we throw an exception - * </p> - * @return the value of the cell as a string - */ - @Override - public String getStringCellValue() { - return getRichStringCellValue().getString(); - } - - /** - * Get the value of the cell as a XSSFRichTextString - * <p> - * For numeric cells we throw an exception. For blank cells we return an empty string. - * For formula cells we return the pre-calculated value if a string, otherwise an exception - * </p> - * @return the value of the cell as a XSSFRichTextString - */ - @Override - public XSSFRichTextString getRichStringCellValue() { - CellType cellType = getCellType(); - XSSFRichTextString rt; - switch (cellType) { - case BLANK: - rt = new XSSFRichTextString(""); - break; - case STRING: - if (_cell.getT() == STCellType.INLINE_STR) { - if(_cell.isSetIs()) { - //string is expressed directly in the cell definition instead of implementing the shared string table. - rt = new XSSFRichTextString(_cell.getIs()); - } else if (_cell.isSetV()) { - //cached result of a formula - rt = new XSSFRichTextString(_cell.getV()); - } else { - rt = new XSSFRichTextString(""); - } - } else if (_cell.getT() == STCellType.STR) { - //cached formula value - rt = new XSSFRichTextString(_cell.isSetV() ? _cell.getV() : ""); - } else { - if (_cell.isSetV()) { - try { - int idx = Integer.parseInt(_cell.getV()); - rt = (XSSFRichTextString)_sharedStringSource.getItemAt(idx); - } catch(Throwable t) { - rt = new XSSFRichTextString(""); - } - } else { - rt = new XSSFRichTextString(""); - } - } - break; - case FORMULA: - checkFormulaCachedValueType(CellType.STRING, getBaseCellType(false)); - rt = new XSSFRichTextString(_cell.isSetV() ? _cell.getV() : ""); - break; - default: - throw typeMismatch(CellType.STRING, cellType, false); - } - rt.setStylesTableReference(_stylesSource); - return rt; - } - - private static void checkFormulaCachedValueType(CellType expectedTypeCode, CellType cachedValueType) { - if (cachedValueType != expectedTypeCode) { - throw typeMismatch(expectedTypeCode, cachedValueType, true); - } - } - - /** - * {@inheritDoc} - */ - @Override - protected void setCellValueImpl(String value) { - setCellValueImpl(new XSSFRichTextString(value)); - } - - /** - * {@inheritDoc} - */ - @Override - protected void setCellValueImpl(RichTextString str) { - CellType cellType = getCellType(); - if (cellType == CellType.FORMULA) { - _cell.setV(str.getString()); - _cell.setT(STCellType.STR); - } else { - if(_cell.getT() == STCellType.INLINE_STR) { - //set the 'pre-evaluated result - _cell.setV(str.getString()); - } else { - _cell.setT(STCellType.S); - XSSFRichTextString rt = (XSSFRichTextString)str; - rt.setStylesTableReference(_stylesSource); - int sRef = _sharedStringSource.addSharedStringItem(rt); - _cell.setV(Integer.toString(sRef)); - } - } - } - - /** - * Return a formula for the cell, for example, <code>SUM(C4:E4)</code> - * - * @return a formula for the cell - * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is not {@link CellType#FORMULA} - */ - @Override - public String getCellFormula() { - // existing behavior - create a new XSSFEvaluationWorkbook for every call - return getCellFormula(null); - } - - /** - * package/hierarchy use only - reuse an existing evaluation workbook if available for caching - * - * @param fpb evaluation workbook for reuse, if available, or null to create a new one as needed - * @return a formula for the cell - * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is not {@link CellType#FORMULA} - */ - protected String getCellFormula(BaseXSSFEvaluationWorkbook fpb) { - CellType cellType = getCellType(); - if(cellType != CellType.FORMULA) { - throw typeMismatch(CellType.FORMULA, cellType, false); - } - - CTCellFormula f = _cell.getF(); - if (isPartOfArrayFormulaGroup()) { - /* In an excel generated array formula, the formula property might be set, but the string is empty in related cells */ - if (f == null || f.getStringValue().isEmpty()) { - XSSFCell cell = getSheet().getFirstCellInArrayFormula(this); - return cell.getCellFormula(fpb); - } - } - if (f == null) { - return null; - } else if (f.getT() == STCellFormulaType.SHARED) { - return convertSharedFormula(Math.toIntExact(f.getSi()), - fpb == null ? XSSFEvaluationWorkbook.create(getSheet().getWorkbook()) : fpb); - } else { - return f.getStringValue(); - } - } - - /** - * Creates a non shared formula from the shared formula counterpart - * - * @param si Shared Group Index - * @return non shared formula created for the given shared formula and this cell - */ - private String convertSharedFormula(int si, BaseXSSFEvaluationWorkbook fpb){ - XSSFSheet sheet = getSheet(); - - CTCellFormula f = sheet.getSharedFormula(si); - if(f == null) { - throw new IllegalStateException( - "Master cell of a shared formula with sid="+si+" was not found"); - } - - String sharedFormula = f.getStringValue(); - //Range of cells which the shared formula applies to - String sharedFormulaRange = f.getRef(); - - CellRangeAddress ref = CellRangeAddress.valueOf(sharedFormulaRange); - - int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); - SharedFormula sf = new SharedFormula(SpreadsheetVersion.EXCEL2007); - - Ptg[] ptgs = FormulaParser.parse(sharedFormula, fpb, FormulaType.CELL, sheetIndex, getRowIndex()); - Ptg[] fmla = sf.convertSharedFormulas(ptgs, - getRowIndex() - ref.getFirstRow(), getColumnIndex() - ref.getFirstColumn()); - return FormulaRenderer.toFormulaString(fpb, fmla); - } - - /** - * Sets formula for this cell. - * <p> - * Note, this method only sets the formula string and does not calculate the formula value. - * To set the precalculated value use {@link #setCellValue(double)} or {@link #setCellValue(String)} - * </p> - * <p> - * Note, if there are any shared formulas, his will invalidate any - * {@link FormulaEvaluator} instances based on this workbook. - * </p> - * - * @param formula the formula to set, e.g. <code>"SUM(C4:E4)"</code>. - * If the argument is <code>null</code> then the current formula is removed. - * @throws org.apache.poi.ss.formula.FormulaParseException if the formula has incorrect syntax or is otherwise invalid - * @throws IllegalStateException if the operation is not allowed, for example, - * when the cell is a part of a multi-cell array formula - */ - @Override - protected void setCellFormulaImpl(String formula) { - assert formula != null; - setFormula(formula, FormulaType.CELL); - } - - /* package */ void setCellArrayFormula(String formula, CellRangeAddress range) { - setFormula(formula, FormulaType.ARRAY); - CTCellFormula cellFormula = _cell.getF(); - cellFormula.setT(STCellFormulaType.ARRAY); - cellFormula.setRef(range.formatAsString()); - } - - private void setFormula(String formula, FormulaType formulaType) { - XSSFWorkbook wb = _row.getSheet().getWorkbook(); - if (formulaType == FormulaType.ARRAY && formula == null) { - wb.onDeleteFormula(this); - if (_cell.isSetF()) { - _row.getSheet().onDeleteFormula(this, null); - _cell.unsetF(); - } - return; - } - - if (wb.getCellFormulaValidation()) { - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); - //validate through the FormulaParser - FormulaParser.parse(formula, fpb, formulaType, wb.getSheetIndex(getSheet()), getRowIndex()); - } - - CTCellFormula f; - if (_cell.isSetF()) { - f = _cell.getF(); - f.setStringValue(formula); - if(f.getT() == STCellFormulaType.SHARED){ - getRow().getSheet().onReadCell(this); - } - } else { - f = CTCellFormula.Factory.newInstance(); - f.setStringValue(formula); - _cell.setF(f); - } - } - - @Override - protected void removeFormulaImpl() { - _row.getSheet().getWorkbook().onDeleteFormula(this); - if (_cell.isSetF()) { - _row.getSheet().onDeleteFormula(this, null); - _cell.unsetF(); - } - } - - /** - * Returns column index of this cell - * - * @return zero-based column index of a column in a sheet. - */ - @Override - public int getColumnIndex() { - return this._cellNum; - } - - /** - * Returns row index of a row in the sheet that contains this cell - * - * @return zero-based row index of a row in the sheet that contains this cell - */ - @Override - public int getRowIndex() { - return _row.getRowNum(); - } - - /** - * Returns an A1 style reference to the location of this cell - * - * @return A1 style reference to the location of this cell - */ - public String getReference() { - String ref = _cell.getR(); - if(ref == null) { - return getAddress().formatAsString(); - } - return ref; - } - - /** - * Return the cell's style. - * - * @return the cell's style. - */ - @Override - public XSSFCellStyle getCellStyle() { - XSSFCellStyle style = null; - if(_stylesSource.getNumCellStyles() > 0){ - long idx = _cell.isSetS() ? _cell.getS() : 0; - style = _stylesSource.getStyleAt(Math.toIntExact(idx)); - } - return style; - } - - /** - * <p>Set the style for the cell. The style should be an XSSFCellStyle created/retreived from - * the XSSFWorkbook.</p> - * - * <p>To change the style of a cell without affecting other cells that use the same style, - * use {@link org.apache.poi.ss.util.CellUtil#setCellStyleProperties(Cell, java.util.Map)}</p> - * - * @param style reference contained in the workbook. - * If the value is null then the style information is removed causing the cell to used the default workbook style. - * @throws IllegalArgumentException if style belongs to a different styles source (most likely because style is from a different Workbook) - */ - @Override - public void setCellStyle(CellStyle style) { - if(style == null) { - if(_cell.isSetS()) { - _cell.unsetS(); - } - } else { - XSSFCellStyle xStyle = (XSSFCellStyle)style; - xStyle.verifyBelongsToStylesSource(_stylesSource); - - long idx = _stylesSource.putStyle(xStyle); - _cell.setS(idx); - } - } - - /** - * POI currently supports these formula types: - * <ul> - * <li> {@link STCellFormulaType#NORMAL} - * <li> {@link STCellFormulaType#SHARED} - * <li> {@link STCellFormulaType#ARRAY} - * </ul> - * POI does not support {@link STCellFormulaType#DATA_TABLE} formulas. - * @return true if the cell is of a formula type POI can handle - */ - private boolean isFormulaCell() { - if ( (_cell.isSetF() && _cell.getF().getT() != STCellFormulaType.DATA_TABLE ) || getSheet().isCellInArrayFormulaContext(this)) { - return true; - } - return false; - } - - /** - * Return the cell type. Tables in an array formula return - * {@link CellType#FORMULA} for all cells, even though the formula is only defined - * in the OOXML file for the top left cell of the array. - * <p> - * NOTE: POI does not support data table formulas. - * Cells in a data table appear to POI as plain cells typed from their cached value. - * - * @return the cell type - */ - @Override - public CellType getCellType() { - if (isFormulaCell()) { - return CellType.FORMULA; - } - - return getBaseCellType(true); - } - - /** - * Only valid for formula cells - * @return one of ({@link CellType#NUMERIC}, {@link CellType#STRING}, - * {@link CellType#BOOLEAN}, {@link CellType#ERROR}) depending - * on the cached value of the formula - */ - @Override - public CellType getCachedFormulaResultType() { - if (! isFormulaCell()) { - throw new IllegalStateException("Only formula cells have cached results"); - } - - return getBaseCellType(false); - } - - /** - * Detect cell type based on the "t" attribute of the CTCell bean - */ - private CellType getBaseCellType(boolean blankCells) { - switch (_cell.getT().intValue()) { - case STCellType.INT_B: - return CellType.BOOLEAN; - case STCellType.INT_N: - if (!_cell.isSetV() && blankCells) { - // ooxml does have a separate cell type of 'blank'. A blank cell gets encoded as - // (either not present or) a numeric cell with no value set. - // The formula evaluator (and perhaps other clients of this interface) needs to - // distinguish blank values which sometimes get translated into zero and sometimes - // empty string, depending on context - return CellType.BLANK; - } - return CellType.NUMERIC; - case STCellType.INT_E: - return CellType.ERROR; - case STCellType.INT_S: // String is in shared strings - case STCellType.INT_INLINE_STR: // String is inline in cell - case STCellType.INT_STR: - return CellType.STRING; - default: - throw new IllegalStateException("Illegal cell type: " + this._cell.getT()); - } - } - - /** - * Get the value of the cell as a date. - * <p> - * For strings we throw an exception. For blank cells we return a null. - * </p> - * @return the value of the cell as a date - * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is {@link CellType#STRING} - * @exception NumberFormatException if the cell value isn't a parsable <code>double</code>. - * @see DataFormatter for formatting this date into a string similar to how excel does. - */ - @Override - public Date getDateCellValue() { - if (getCellType() == CellType.BLANK) { - return null; - } - - double value = getNumericCellValue(); - boolean date1904 = getSheet().getWorkbook().isDate1904(); - return DateUtil.getJavaDate(value, date1904); - } - - /** - * Get the value of the cell as a LocalDateTime. - * <p> - * For strings we throw an exception. For blank cells we return a null. - * </p> - * @return the value of the cell as a LocalDateTime - * @throws IllegalStateException if the cell type returned by {@link #getCellType()} is {@link CellType#STRING} - * @exception NumberFormatException if the cell value isn't a parsable <code>double</code>. - * @see DataFormatter for formatting this date into a string similar to how excel does. - */ - @Override - public LocalDateTime getLocalDateTimeCellValue() { - if (getCellType() == CellType.BLANK) { - return null; - } - - double value = getNumericCellValue(); - boolean date1904 = getSheet().getWorkbook().isDate1904(); - return DateUtil.getLocalDateTime(value, date1904); - } - - /** - * {@inheritDoc} - */ - @Override - protected void setCellValueImpl(Date value) { - boolean date1904 = getSheet().getWorkbook().isDate1904(); - setCellValue(DateUtil.getExcelDate(value, date1904)); - } - - /** - * {@inheritDoc} - */ - @Override - protected void setCellValueImpl(LocalDateTime value) { - boolean date1904 = getSheet().getWorkbook().isDate1904(); - setCellValue(DateUtil.getExcelDate(value, date1904)); - } - - /** - * {@inheritDoc} - */ - @Override - protected void setCellValueImpl(Calendar value) { - boolean date1904 = getSheet().getWorkbook().isDate1904(); - setCellValue( DateUtil.getExcelDate(value, date1904 )); - } - - /** - * Returns the error message, such as #VALUE! - * - * @return the error message such as #VALUE! - * @throws IllegalStateException if the cell type returned by {@link #getCellType()} isn't {@link CellType#ERROR} - * @see FormulaError - */ - public String getErrorCellString() throws IllegalStateException { - CellType cellType = getBaseCellType(true); - if(cellType != CellType.ERROR) { - throw typeMismatch(CellType.ERROR, cellType, false); - } - - return _cell.getV(); - } - /** - * Get the value of the cell as an error code. - * <p> - * For strings, numbers, and booleans, we throw an exception. - * For blank cells we return a 0. - * </p> - * - * @return the value of the cell as an error code - * @throws IllegalStateException if the cell type returned by {@link #getCellType()} isn't {@link CellType #ERROR} - * @see FormulaError - */ - @Override - public byte getErrorCellValue() throws IllegalStateException { - String code = getErrorCellString(); - if (code == null) { - return 0; - } - try { - return FormulaError.forString(code).getCode(); - } catch (final IllegalArgumentException e) { - throw new IllegalStateException("Unexpected error code", e); - } - } - - /** - * Set a error value for the cell - * - * @param errorCode the error value to set this cell to. For formulas we'll set the - * precalculated value , for errors we'll set - * its value. For other types we will change the cell to an error - * cell and set its value. - * @see FormulaError - */ - @Override - public void setCellErrorValue(byte errorCode) { - FormulaError error = FormulaError.forInt(errorCode); - setCellErrorValue(error); - } - - /** - * Set a error value for the cell - * - * @param error the error value to set this cell to. For formulas we'll set the - * precalculated value , for errors we'll set - * its value. For other types we will change the cell to an error - * cell and set its value. - */ - public void setCellErrorValue(FormulaError error) { - _cell.setT(STCellType.E); - _cell.setV(error.getString()); - } - - /** - * {@inheritDoc} - */ - @Override - public void setAsActiveCell() { - getSheet().setActiveCell(getAddress()); - } - - /** - * Blanks this cell. Blank cells have no formula or value but may have styling. - * This method erases all the data previously associated with this cell. - */ - private void setBlankPrivate(){ - CTCell blank = CTCell.Factory.newInstance(); - blank.setR(_cell.getR()); - if(_cell.isSetS()) { - blank.setS(_cell.getS()); - } - _cell.set(blank); - } - - /** - * Sets column index of this cell - * - * @param num column index of this cell - */ - protected void setCellNum(int num) { - checkBounds(num); - _cellNum = num; - String ref = new CellReference(getRowIndex(), getColumnIndex()).formatAsString(); - _cell.setR(ref); - } - - @Override - protected void setCellTypeImpl(CellType cellType) { - setCellType(cellType, null); - } - - /** - * Needed by bug #62834, which points out getCellFormula() expects an evaluation context or creates a new one, - * so if there is one in use, it needs to be carried on through. - * @param cellType - * @param evalWb BaseXSSFEvaluationWorkbook already in use, or null if a new implicit one should be used - */ - protected void setCellType(CellType cellType, BaseXSSFEvaluationWorkbook evalWb) { - CellType prevType = getCellType(); - if(prevType == CellType.FORMULA && cellType != CellType.FORMULA) { - if (_cell.isSetF()) { - _row.getSheet().onDeleteFormula(this, evalWb); - } - getSheet().getWorkbook().onDeleteFormula(this); - } - - switch (cellType) { - case NUMERIC: - _cell.setT(STCellType.N); - break; - case STRING: - if(prevType != CellType.STRING){ - String str = convertCellValueToString(); - XSSFRichTextString rt = new XSSFRichTextString(str); - rt.setStylesTableReference(_stylesSource); - int sRef = _sharedStringSource.addSharedStringItem(rt); - _cell.setV(Integer.toString(sRef)); - } - _cell.setT(STCellType.S); - break; - case FORMULA: - if(!_cell.isSetF()){ - CTCellFormula f = CTCellFormula.Factory.newInstance(); - f.setStringValue("0"); - _cell.setF(f); - if(_cell.isSetT()) { - _cell.unsetT(); - } - } - break; - case BLANK: - setBlankPrivate(); - break; - case BOOLEAN: - String newVal = convertCellValueToBoolean() ? TRUE_AS_STRING : FALSE_AS_STRING; - _cell.setT(STCellType.B); - _cell.setV(newVal); - break; - - case ERROR: - _cell.setT(STCellType.E); - break; - - - default: - throw new IllegalArgumentException("Illegal cell type: " + cellType); - } - if (cellType != CellType.FORMULA && _cell.isSetF()) { - _cell.unsetF(); - } - } - - /** - * Returns a string representation of the cell - * <p> - * Formula cells return the formula string, rather than the formula result. - * Dates are displayed in dd-MMM-yyyy format - * Errors are displayed as #ERR<errIdx> - * </p> - */ - @Override - public String toString() { - switch (getCellType()) { - case NUMERIC: - if (DateUtil.isCellDateFormatted(this)) { - DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale()); - sdf.setTimeZone(LocaleUtil.getUserTimeZone()); - return sdf.format(getDateCellValue()); - } - return Double.toString(getNumericCellValue()); - case STRING: - return getRichStringCellValue().toString(); - case FORMULA: - return getCellFormula(); - case BLANK: - return ""; - case BOOLEAN: - return getBooleanCellValue() ? TRUE : FALSE; - case ERROR: - return ErrorEval.getText(getErrorCellValue()); - default: - return "Unknown Cell Type: " + getCellType(); - } - } - - /** - * Returns the raw, underlying ooxml value for the cell - * <p> - * If the cell contains a string, then this value is an index into - * the shared string table, pointing to the actual string value. Otherwise, - * the value of the cell is expressed directly in this element. Cells containing formulas express - * the last calculated result of the formula in this element. - * </p> - * - * @return the raw cell value as contained in the underlying CTCell bean, - * <code>null</code> for blank cells. - */ - public String getRawValue() { - return _cell.getV(); - } - - - /** - * Used to help format error messages - */ - private static RuntimeException typeMismatch(CellType expectedType, CellType actualType, boolean isFormulaCell) { - String msg = "Cannot get a " + expectedType + " value from a " + actualType+ " " + (isFormulaCell ? "formula " : "") + "cell"; - return new IllegalStateException(msg); - } - - /** - * @throws RuntimeException if the bounds are exceeded. - */ - private static void checkBounds(int cellIndex) { - SpreadsheetVersion v = SpreadsheetVersion.EXCEL2007; - int maxcol = SpreadsheetVersion.EXCEL2007.getLastColumnIndex(); - if (cellIndex < 0 || cellIndex > maxcol) { - throw new IllegalArgumentException("Invalid column index (" + cellIndex - + "). Allowable column range for " + v.name() + " is (0.." - + maxcol + ") or ('A'..'" + v.getLastColumnName() + "')"); - } - } - - /** - * Returns cell comment associated with this cell - * - * @return the cell comment associated with this cell or <code>null</code> - */ - @Override - public XSSFComment getCellComment() { - return getSheet().getCellComment(new CellAddress(this)); - } - - /** - * Assign a comment to this cell. If the supplied comment is null, - * the comment for this cell will be removed. - * - * @param comment the XSSFComment associated with this cell - */ - @Override - public void setCellComment(Comment comment) { - if(comment == null) { - removeCellComment(); - return; - } - - comment.setAddress(getRowIndex(), getColumnIndex()); - } - - /** - * Removes the comment for this cell, if there is one. - */ - @Override - public void removeCellComment() { - XSSFComment comment = getCellComment(); - if(comment != null){ - CellAddress ref = new CellAddress(getReference()); - XSSFSheet sh = getSheet(); - sh.getCommentsTable(false).removeComment(ref); - sh.getVMLDrawing(false).removeCommentShape(getRowIndex(), getColumnIndex()); - } - } - - /** - * Returns hyperlink associated with this cell - * - * @return hyperlink associated with this cell or <code>null</code> if not found - */ - @Override - public XSSFHyperlink getHyperlink() { - return getSheet().getHyperlink(_row.getRowNum(), _cellNum); - } - - /** - * Assign a hyperlink to this cell. If the supplied hyperlink is null, the - * hyperlink for this cell will be removed. - * - * @param hyperlink the hyperlink to associate with this cell - */ - @Override - public void setHyperlink(Hyperlink hyperlink) { - if (hyperlink == null) { - removeHyperlink(); - return; - } - - XSSFHyperlink link = (XSSFHyperlink)hyperlink; - - // Assign to us - link.setCellReference( new CellReference(_row.getRowNum(), _cellNum).formatAsString() ); - - // Add to the lists - getSheet().addHyperlink(link); - } - - /** - * Removes the hyperlink for this cell, if there is one. - */ - @Override - public void removeHyperlink() { - getSheet().removeHyperlink(_row.getRowNum(), _cellNum); - } - - /** - * Returns the xml bean containing information about the cell's location (reference), value, - * data type, formatting, and formula - * - * @return the xml bean containing information about this cell - */ - @Internal - public CTCell getCTCell(){ - return _cell; - } - - /** - * Set a new internal xml bean. This is only for internal use, do not call this from outside! - * - * This is necessary in some rare cases to work around XMLBeans specialties. - */ - @Internal - public void setCTCell(CTCell cell) { - _cell = cell; - } - - /** - * Chooses a new boolean value for the cell when its type is changing.<p> - * - * Usually the caller is calling setCellType() with the intention of calling - * setCellValue(boolean) straight afterwards. This method only exists to give - * the cell a somewhat reasonable value until the setCellValue() call (if at all). - * TODO - perhaps a method like setCellTypeAndValue(CellType, Object) should be introduced to avoid this - * - * @throws IllegalStateException if cell type cannot be converted to boolean - */ - private boolean convertCellValueToBoolean() { - CellType cellType = getCellType(); - - if (cellType == CellType.FORMULA) { - cellType = getBaseCellType(false); - } - - switch (cellType) { - case BOOLEAN: - return TRUE_AS_STRING.equals(_cell.getV()); - case STRING: - int sstIndex = Integer.parseInt(_cell.getV()); - RichTextString rt = _sharedStringSource.getItemAt(sstIndex); - String text = rt.getString(); - return Boolean.parseBoolean(text); - case NUMERIC: - return Double.parseDouble(_cell.getV()) != 0; - - case ERROR: - // fall-through - case BLANK: - return false; - - default: - throw new IllegalStateException("Unexpected cell type (" + cellType + ")"); - } - } - - private String convertCellValueToString() { - CellType cellType = getCellType(); - - switch (cellType) { - case BLANK: - return ""; - case BOOLEAN: - return TRUE_AS_STRING.equals(_cell.getV()) ? TRUE : FALSE; - case STRING: - try { - int sstIndex = Integer.parseInt(_cell.getV()); - RichTextString rt = _sharedStringSource.getItemAt(sstIndex); - return rt.getString(); - } catch (Throwable t) { - return ""; - } - case NUMERIC: - case ERROR: - return _cell.getV(); - case FORMULA: - // should really evaluate, but HSSFCell can't call HSSFFormulaEvaluator - // just use cached formula result instead - break; - default: - throw new IllegalStateException("Unexpected cell type (" + cellType + ")"); - } - cellType = getBaseCellType(false); - String textValue = _cell.getV(); - switch (cellType) { - case BOOLEAN: - if (TRUE_AS_STRING.equals(textValue)) { - return TRUE; - } - if (FALSE_AS_STRING.equals(textValue)) { - return FALSE; - } - throw new IllegalStateException("Unexpected boolean cached formula value '" - + textValue + "'."); - - case STRING: - // fall-through - case NUMERIC: - // fall-through - case ERROR: - return textValue; - - default: - throw new IllegalStateException("Unexpected formula result type (" + cellType + ")"); - } - - } - - @Override - public CellRangeAddress getArrayFormulaRange() { - XSSFCell cell = getSheet().getFirstCellInArrayFormula(this); - if (cell == null) { - throw new IllegalStateException("Cell " + new CellReference(this).formatAsString() - + " is not part of an array formula."); - } - String formulaRef = cell._cell.getF().getRef(); - return CellRangeAddress.valueOf(formulaRef); - } - - @Override - public boolean isPartOfArrayFormulaGroup() { - return getSheet().isCellInArrayFormulaContext(this); - } - - //Moved from XSSFRow.shift(). Not sure what is purpose. - public void updateCellReferencesForShifting(String msg){ - if(isPartOfArrayFormulaGroup()) { - tryToDeleteArrayFormula(msg); - } - - CalculationChain calcChain = getSheet().getWorkbook().getCalculationChain(); - int sheetId = Math.toIntExact(getSheet().sheet.getSheetId()); - - //remove the reference in the calculation chain - if(calcChain != null) calcChain.removeItem(sheetId, getReference()); - - CTCell ctCell = getCTCell(); - String r = new CellReference(getRowIndex(), getColumnIndex()).formatAsString(); - ctCell.setR(r); - } - -} - diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java deleted file mode 100644 index c7d1f85f32..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java +++ /dev/null @@ -1,1300 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import org.apache.poi.common.Duplicatable; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.FillPatternType; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.ReadingOrder; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.apache.poi.util.Internal; -import org.apache.poi.util.Removal; -import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.model.ThemesTable; -import org.apache.poi.xssf.usermodel.extensions.XSSFCellAlignment; -import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder; -import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder.BorderSide; -import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill; -import org.apache.xmlbeans.XmlException; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellAlignment; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPatternFill; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; - -/** - * - * High level representation of the the possible formatting information for the contents of the cells on a sheet in a - * SpreadsheetML document. - * - * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#createCellStyle() - * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getCellStyleAt(int) - * @see org.apache.poi.xssf.usermodel.XSSFCell#setCellStyle(org.apache.poi.ss.usermodel.CellStyle) - */ -public class XSSFCellStyle implements CellStyle, Duplicatable { - - private int _cellXfId; - private final StylesTable _stylesSource; - private CTXf _cellXf; - private final CTXf _cellStyleXf; - private XSSFFont _font; - private XSSFCellAlignment _cellAlignment; - private ThemesTable _theme; - - /** - * Creates a Cell Style from the supplied parts - * @param cellXfId The main XF for the cell. Must be a valid 0-based index into the XF table - * @param cellStyleXfId Optional, style xf. A value of <code>-1</code> means no xf. - * @param stylesSource Styles Source to work off - */ - public XSSFCellStyle(int cellXfId, int cellStyleXfId, StylesTable stylesSource, ThemesTable theme) { - _cellXfId = cellXfId; - _stylesSource = stylesSource; - _cellXf = stylesSource.getCellXfAt(this._cellXfId); - _cellStyleXf = cellStyleXfId == -1 ? null : stylesSource.getCellStyleXfAt(cellStyleXfId); - _theme = theme; - } - - /** - * Used so that StylesSource can figure out our location - */ - @Internal - public CTXf getCoreXf() { - return _cellXf; - } - - /** - * Used so that StylesSource can figure out our location - */ - @Internal - public CTXf getStyleXf() { - return _cellStyleXf; - } - - /** - * Creates an empty Cell Style - */ - public XSSFCellStyle(StylesTable stylesSource) { - _stylesSource = stylesSource; - // We need a new CTXf for the main styles - // TODO decide on a style ctxf - _cellXf = CTXf.Factory.newInstance(); - _cellStyleXf = null; - } - - /** - * Verifies that this style belongs to the supplied Workbook - * Styles Source. - * Will throw an exception if it belongs to a different one. - * This is normally called when trying to assign a style to a - * cell, to ensure the cell and the style are from the same - * workbook (if they're not, it won't work) - * @throws IllegalArgumentException if there's a workbook mis-match - */ - public void verifyBelongsToStylesSource(StylesTable src) { - if(this._stylesSource != src) { - throw new IllegalArgumentException("This Style does not belong to the supplied Workbook Styles Source. Are you trying to assign a style from one workbook to the cell of a different workbook?"); - } - } - - /** - * Clones all the style information from another - * XSSFCellStyle, onto this one. This - * XSSFCellStyle will then have all the same - * properties as the source, but the two may - * be edited independently. - * Any stylings on this XSSFCellStyle will be lost! - * - * The source XSSFCellStyle could be from another - * XSSFWorkbook if you like. This allows you to - * copy styles from one XSSFWorkbook to another. - */ - @Override - public void cloneStyleFrom(CellStyle source) { - if(source instanceof XSSFCellStyle) { - XSSFCellStyle src = (XSSFCellStyle)source; - - // Is it on our Workbook? - if(src._stylesSource == _stylesSource) { - // Nice and easy - _cellXf.set(src.getCoreXf()); - _cellStyleXf.set(src.getStyleXf()); - } else { - // Copy the style - try { - // Remove any children off the current style, to - // avoid orphaned nodes - if(_cellXf.isSetAlignment()) - _cellXf.unsetAlignment(); - if(_cellXf.isSetExtLst()) - _cellXf.unsetExtLst(); - - // Create a new Xf with the same contents - _cellXf = CTXf.Factory.parse( - src.getCoreXf().toString(), DEFAULT_XML_OPTIONS - ); - - // bug 56295: ensure that the fills is available and set correctly - CTFill fill = CTFill.Factory.parse( - src.getCTFill().toString(), DEFAULT_XML_OPTIONS - ); - addFill(fill); - - // bug 58084: set borders correctly - CTBorder border = CTBorder.Factory.parse( - src.getCTBorder().toString(), DEFAULT_XML_OPTIONS - ); - addBorder(border); - - // Swap it over - _stylesSource.replaceCellXfAt(_cellXfId, _cellXf); - } catch(XmlException e) { - throw new POIXMLException(e); - } - - // Copy the format - String fmt = src.getDataFormatString(); - setDataFormat( - (new XSSFDataFormat(_stylesSource)).getFormat(fmt) - ); - - // Copy the font - try { - CTFont ctFont = CTFont.Factory.parse( - src.getFont().getCTFont().toString(), DEFAULT_XML_OPTIONS - ); - XSSFFont font = new XSSFFont(ctFont); - font.registerTo(_stylesSource); - setFont(font); - } catch(XmlException e) { - throw new POIXMLException(e); - } - } - - // Clear out cached details - _font = null; - _cellAlignment = null; - } else { - throw new IllegalArgumentException("Can only clone from one XSSFCellStyle to another, not between HSSFCellStyle and XSSFCellStyle"); - } - } - - private void addFill(CTFill fill) { - int idx = _stylesSource.putFill(new XSSFCellFill(fill,_stylesSource.getIndexedColors())); - - _cellXf.setFillId(idx); - _cellXf.setApplyFill(true); - } - - private void addBorder(CTBorder border) { - int idx = _stylesSource.putBorder(new XSSFCellBorder(border, _theme,_stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - @Override - public HorizontalAlignment getAlignment() { - if(!_cellXf.getApplyAlignment()) return HorizontalAlignment.GENERAL; - - CTCellAlignment align = _cellXf.getAlignment(); - if(align != null && align.isSetHorizontal()) { - return HorizontalAlignment.forInt(align.getHorizontal().intValue()-1); - } - return HorizontalAlignment.GENERAL; - } - - @Override - public BorderStyle getBorderBottom() { - if(!_cellXf.getApplyBorder()) return BorderStyle.NONE; - - int idx = Math.toIntExact(_cellXf.getBorderId()); - CTBorder ct = _stylesSource.getBorderAt(idx).getCTBorder(); - STBorderStyle.Enum ptrn = ct.isSetBottom() ? ct.getBottom().getStyle() : null; - if (ptrn == null) { - return BorderStyle.NONE; - } - return BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - @Override - public BorderStyle getBorderLeft() { - if(!_cellXf.getApplyBorder()) return BorderStyle.NONE; - - int idx = Math.toIntExact(_cellXf.getBorderId()); - CTBorder ct = _stylesSource.getBorderAt(idx).getCTBorder(); - STBorderStyle.Enum ptrn = ct.isSetLeft() ? ct.getLeft().getStyle() : null; - if (ptrn == null) { - return BorderStyle.NONE; - } - return BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - @Override - public BorderStyle getBorderRight() { - if(!_cellXf.getApplyBorder()) return BorderStyle.NONE; - - int idx = Math.toIntExact(_cellXf.getBorderId()); - CTBorder ct = _stylesSource.getBorderAt(idx).getCTBorder(); - STBorderStyle.Enum ptrn = ct.isSetRight() ? ct.getRight().getStyle() : null; - if (ptrn == null) { - return BorderStyle.NONE; - } - return BorderStyle.valueOf((short)(ptrn.intValue() - 1)); - } - - @Override - public BorderStyle getBorderTop() { - if(!_cellXf.getApplyBorder()) return BorderStyle.NONE; - - int idx = Math.toIntExact(_cellXf.getBorderId()); - CTBorder ct = _stylesSource.getBorderAt(idx).getCTBorder(); - STBorderStyle.Enum ptrn = ct.isSetTop() ? ct.getTop().getStyle() : null; - if (ptrn == null) { - return BorderStyle.NONE; - } - return BorderStyle.valueOf((short) (ptrn.intValue() - 1)); - } - - /** - * Get the color to use for the bottom border - * <br> - * Color is optional. When missing, IndexedColors.AUTOMATIC is implied. - * @return the index of the color definition, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#AUTOMATIC} - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public short getBottomBorderColor() { - XSSFColor clr = getBottomBorderXSSFColor(); - return clr == null ? IndexedColors.BLACK.getIndex() : clr.getIndexed(); - } - - /** - * Get the color to use for the bottom border as a {@link XSSFColor} - * - * @return the used color or <code>null</code> if not set - */ - public XSSFColor getBottomBorderXSSFColor() { - if(!_cellXf.getApplyBorder()) return null; - - int idx = Math.toIntExact(_cellXf.getBorderId()); - XSSFCellBorder border = _stylesSource.getBorderAt(idx); - - return border.getBorderColor(BorderSide.BOTTOM); - } - - /** - * Get the index of the number format (numFmt) record used by this cell format. - * - * @return the index of the number format - */ - @Override - public short getDataFormat() { - return (short)_cellXf.getNumFmtId(); - } - - /** - * Get the contents of the format string, by looking up - * the StylesSource - * - * @return the number format string - */ - @Override - public String getDataFormatString() { - int idx = getDataFormat(); - return new XSSFDataFormat(_stylesSource).getFormat((short)idx); - } - - /** - * Get the background fill color. - * <p> - * Note - many cells are actually filled with a foreground - * fill, not a background fill - see {@link #getFillForegroundColor()} - * </p> - * @return fill color, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#AUTOMATIC} - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public short getFillBackgroundColor() { - XSSFColor clr = getFillBackgroundXSSFColor(); - return clr == null ? IndexedColors.AUTOMATIC.getIndex() : clr.getIndexed(); - } - - @Override - public XSSFColor getFillBackgroundColorColor() { - return getFillBackgroundXSSFColor(); - } - - /** - * Get the background fill color. - * <p> - * Note - many cells are actually filled with a foreground - * fill, not a background fill - see {@link #getFillForegroundColor()} - * </p> - * @see org.apache.poi.xssf.usermodel.XSSFColor#getRGB() - * @return XSSFColor - fill color or <code>null</code> if not set - */ - public XSSFColor getFillBackgroundXSSFColor() { - // bug 56295: handle missing applyFill attribute as "true" because Excel does as well - if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return null; - - int fillIndex = (int)_cellXf.getFillId(); - XSSFCellFill fg = _stylesSource.getFillAt(fillIndex); - - XSSFColor fillBackgroundColor = fg.getFillBackgroundColor(); - if (fillBackgroundColor != null && _theme != null) { - _theme.inheritFromThemeAsRequired(fillBackgroundColor); - } - return fillBackgroundColor; - } - - /** - * Get the foreground fill color. - * <p> - * Many cells are filled with this, instead of a - * background color ({@link #getFillBackgroundColor()}) - * </p> - * @see IndexedColors - * @return fill color, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#AUTOMATIC} - */ - @Override - public short getFillForegroundColor() { - XSSFColor clr = getFillForegroundXSSFColor(); - return clr == null ? IndexedColors.AUTOMATIC.getIndex() : clr.getIndexed(); - } - - @Override - public XSSFColor getFillForegroundColorColor() { - return getFillForegroundXSSFColor(); - } - - /** - * Get the foreground fill color. - * - * @return XSSFColor - fill color or <code>null</code> if not set - */ - public XSSFColor getFillForegroundXSSFColor() { - // bug 56295: handle missing applyFill attribute as "true" because Excel does as well - if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return null; - - int fillIndex = (int)_cellXf.getFillId(); - XSSFCellFill fg = _stylesSource.getFillAt(fillIndex); - - XSSFColor fillForegroundColor = fg.getFillForegroundColor(); - if (fillForegroundColor != null && _theme != null) { - _theme.inheritFromThemeAsRequired(fillForegroundColor); - } - return fillForegroundColor; - } - - @Override - public FillPatternType getFillPattern() { - // bug 56295: handle missing applyFill attribute as "true" because Excel does as well - if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return FillPatternType.NO_FILL; - - int fillIndex = (int)_cellXf.getFillId(); - XSSFCellFill fill = _stylesSource.getFillAt(fillIndex); - - STPatternType.Enum ptrn = fill.getPatternType(); - if(ptrn == null) return FillPatternType.NO_FILL; - return FillPatternType.forInt(ptrn.intValue() - 1); - } - - /** - * Gets the font for this style - * @return Font - font - */ - public XSSFFont getFont() { - if (_font == null) { - _font = _stylesSource.getFontAt(getFontId()); - } - return _font; - } - - /** - * Gets the index of the font for this style - * - * @return font index - * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getFontAt(int) - * @since 5.0.0 (used to return a short value) - */ - @Override - public int getFontIndex() { - return getFontId(); - } - - /** - * Gets the index of the font for this style - * - * @return font index - * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getFontAt(int) - * @deprecated use {@link #getFontIndex()} instead - * @since 4.0.0 - */ - @Deprecated - @Removal(version = "6.0.0") - @Override - public int getFontIndexAsInt() { - return getFontId(); - } - - /** - * Get whether the cell's using this style are to be hidden - * - * @return boolean - whether the cell using this style is hidden - */ - @Override - public boolean getHidden() { - return _cellXf.isSetProtection() && _cellXf.getProtection().isSetHidden() && _cellXf.getProtection().getHidden(); - } - - /** - * Get the number of spaces to indent the text in the cell - * - * @return indent - number of spaces - */ - @Override - public short getIndention() { - CTCellAlignment align = _cellXf.getAlignment(); - return (short)(align == null ? 0 : align.getIndent()); - } - - /** - * Get the index within the StylesTable (sequence within the collection of CTXf elements) - * - * @return unique index number of the underlying record this style represents, as a short (may wrap) - */ - @Override - public short getIndex() { - return (short)this._cellXfId; - } - - /** - * Workaround for places where we need to support more than 32767 cell styles, ideally - * the main getIndex() and others would return int, not short, but that would affect some - * public APIs - * - * @return unique index number of the underlying record this style represents, as an int (always positive) - */ - protected int getUIndex() { - return this._cellXfId; - } - - /** - * Get the color to use for the left border - * - * @return the index of the color definition, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#BLACK} - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public short getLeftBorderColor() { - XSSFColor clr = getLeftBorderXSSFColor(); - return clr == null ? IndexedColors.BLACK.getIndex() : clr.getIndexed(); - } - - /** - * Get the color to use for the left border - * - * @return the index of the color definition or <code>null</code> if not set - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - public XSSFColor getLeftBorderXSSFColor() { - if(!_cellXf.getApplyBorder()) return null; - - int idx = Math.toIntExact(_cellXf.getBorderId()); - XSSFCellBorder border = _stylesSource.getBorderAt(idx); - - return border.getBorderColor(BorderSide.LEFT); - } - - /** - * Get whether the cell's using this style are locked - * - * @return whether the cell using this style are locked - */ - @Override - public boolean getLocked() { - return !_cellXf.isSetProtection() || !_cellXf.getProtection().isSetLocked() || _cellXf.getProtection().getLocked(); - } - - /** - * Is "Quote Prefix" or "123 Prefix" enabled for the cell? - */ - @Override - public boolean getQuotePrefixed() { - return _cellXf.getQuotePrefix(); - } - - /** - * Get the color to use for the right border - * - * @return the index of the color definition, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#BLACK} - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public short getRightBorderColor() { - XSSFColor clr = getRightBorderXSSFColor(); - return clr == null ? IndexedColors.BLACK.getIndex() : clr.getIndexed(); - } - /** - * Get the color to use for the right border - * - * @return the used color or <code>null</code> if not set - */ - public XSSFColor getRightBorderXSSFColor() { - if(!_cellXf.getApplyBorder()) return null; - - int idx = Math.toIntExact(_cellXf.getBorderId()); - XSSFCellBorder border = _stylesSource.getBorderAt(idx); - - return border.getBorderColor(BorderSide.RIGHT); - } - - /** - * Get the degree of rotation for the text in the cell - * <p> - * Expressed in degrees. Values range from 0 to 180. The first letter of - * the text is considered the center-point of the arc. - * <br> - * For 0 - 90, the value represents degrees above horizon. For 91-180 the degrees below the - * horizon is calculated as: - * <br> - * <code>[degrees below horizon] = 90 - textRotation.</code> - * </p> - * - * @return rotation degrees (between 0 and 180 degrees) - */ - @Override - public short getRotation() { - CTCellAlignment align = _cellXf.getAlignment(); - return align == null || align.getTextRotation() == null ? 0 : align.getTextRotation().shortValue(); - } - - @Override - public boolean getShrinkToFit() { - CTCellAlignment align = _cellXf.getAlignment(); - return align != null && align.getShrinkToFit(); - } - - /** - * Get the color to use for the top border - * - * @return the index of the color definition, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#BLACK} - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public short getTopBorderColor() { - XSSFColor clr = getTopBorderXSSFColor(); - return clr == null ? IndexedColors.BLACK.getIndex() : clr.getIndexed(); - } - - /** - * Get the color to use for the top border - * - * @return the used color or <code>null</code> if not set - */ - public XSSFColor getTopBorderXSSFColor() { - if(!_cellXf.getApplyBorder()) return null; - - int idx = Math.toIntExact(_cellXf.getBorderId()); - XSSFCellBorder border = _stylesSource.getBorderAt(idx); - - return border.getBorderColor(BorderSide.TOP); - } - - @Override - public VerticalAlignment getVerticalAlignment() { - if(!_cellXf.getApplyAlignment()) return VerticalAlignment.BOTTOM; - - CTCellAlignment align = _cellXf.getAlignment(); - if(align != null && align.isSetVertical()) { - return VerticalAlignment.forInt(align.getVertical().intValue()-1); - } - return VerticalAlignment.BOTTOM; - } - - /** - * Whether the text should be wrapped - * - * @return a boolean value indicating if the text in a cell should be line-wrapped within the cell. - */ - @Override - public boolean getWrapText() { - CTCellAlignment align = _cellXf.getAlignment(); - return align != null && align.getWrapText(); - } - - /** - * Set the type of horizontal alignment for the cell - * - * @param align - the type of alignment - */ - @Override - public void setAlignment(HorizontalAlignment align) { - _cellXf.setApplyAlignment(true); - - getCellAlignment().setHorizontal(align); - } - - /** - * Set the type of border to use for the bottom border of the cell - * - * @param border - type of border to use - * @see org.apache.poi.ss.usermodel.BorderStyle - * @since POI 3.15 - */ - @Override - public void setBorderBottom(BorderStyle border) { - CTBorder ct = getCTBorder(); - CTBorderPr pr = ct.isSetBottom() ? ct.getBottom() : ct.addNewBottom(); - if(border == BorderStyle.NONE) ct.unsetBottom(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - - int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme, _stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - /** - * Set the type of border to use for the left border of the cell - * - * @param border the type of border to use - * @since POI 3.15 - */ - @Override - public void setBorderLeft(BorderStyle border) { - CTBorder ct = getCTBorder(); - CTBorderPr pr = ct.isSetLeft() ? ct.getLeft() : ct.addNewLeft(); - if(border == BorderStyle.NONE) ct.unsetLeft(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - - int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme, _stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - /** - * Set the type of border to use for the right border of the cell - * - * @param border the type of border to use - * @since POI 3.15 - */ - @Override - public void setBorderRight(BorderStyle border) { - CTBorder ct = getCTBorder(); - CTBorderPr pr = ct.isSetRight() ? ct.getRight() : ct.addNewRight(); - if(border == BorderStyle.NONE) ct.unsetRight(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - - int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - /** - * Set the type of border to use for the top border of the cell - * - * @param border the type of border to use - * @since POI 3.15 - */ - @Override - public void setBorderTop(BorderStyle border) { - CTBorder ct = getCTBorder(); - CTBorderPr pr = ct.isSetTop() ? ct.getTop() : ct.addNewTop(); - if(border == BorderStyle.NONE) ct.unsetTop(); - else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1)); - - int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - /** - * Set the color to use for the bottom border - * @param color the index of the color definition - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public void setBottomBorderColor(short color) { - XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors()); - clr.setIndexed(color); - setBottomBorderColor(clr); - } - - /** - * Set the color to use for the bottom border - * - * @param color the color to use, null means no color - */ - public void setBottomBorderColor(XSSFColor color) { - CTBorder ct = getCTBorder(); - if(color == null && !ct.isSetBottom()) return; - - CTBorderPr pr = ct.isSetBottom() ? ct.getBottom() : ct.addNewBottom(); - if(color != null) pr.setColor(color.getCTColor()); - else pr.unsetColor(); - - int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - /** - * Set the index of a data format - * - * @param fmt the index of a data format - */ - @Override - public void setDataFormat(short fmt) { - // XSSF supports >32,767 formats - setDataFormat(fmt&0xffff); - } - /** - * Set the index of a data format - * - * @param fmt the index of a data format - */ - public void setDataFormat(int fmt) { - _cellXf.setApplyNumberFormat(true); - _cellXf.setNumFmtId(fmt); - } - - /** - * Set the background fill color represented as a {@link XSSFColor} value. - * <p> - * For example: - * <pre> - * cs.setFillPattern(XSSFCellStyle.FINE_DOTS ); - * cs.setFillBackgroundXSSFColor(new XSSFColor(java.awt.Color.RED)); - * </pre> - * optionally a Foreground and background fill can be applied: - * <i>Note: Ensure Foreground color is set prior to background</i> - * <pre> - * cs.setFillPattern(XSSFCellStyle.FINE_DOTS ); - * cs.setFillForegroundColor(new XSSFColor(java.awt.Color.BLUE)); - * cs.setFillBackgroundColor(new XSSFColor(java.awt.Color.GREEN)); - * </pre> - * or, for the special case of SOLID_FILL: - * <pre> - * cs.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND ); - * cs.setFillForegroundColor(new XSSFColor(java.awt.Color.GREEN)); - * </pre> - * It is necessary to set the fill style in order - * for the color to be shown in the cell. - * - * @param color - the color to use - */ - public void setFillBackgroundColor(XSSFColor color) { - CTFill ct = getCTFill(); - CTPatternFill ptrn = ct.getPatternFill(); - if(color == null) { - if(ptrn != null && ptrn.isSetBgColor()) ptrn.unsetBgColor(); - } else { - if(ptrn == null) ptrn = ct.addNewPatternFill(); - ptrn.setBgColor(color.getCTColor()); - } - - addFill(ct); - } - - /** - * Set the background fill color represented as a indexed color value. - * <p> - * For example: - * <pre> - * cs.setFillPattern(XSSFCellStyle.FINE_DOTS ); - * cs.setFillBackgroundXSSFColor(IndexedColors.RED.getIndex()); - * </pre> - * optionally a Foreground and background fill can be applied: - * <i>Note: Ensure Foreground color is set prior to background</i> - * <pre> - * cs.setFillPattern(XSSFCellStyle.FINE_DOTS ); - * cs.setFillForegroundColor(IndexedColors.BLUE.getIndex()); - * cs.setFillBackgroundColor(IndexedColors.RED.getIndex()); - * </pre> - * or, for the special case of SOLID_FILL: - * <pre> - * cs.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND ); - * cs.setFillForegroundColor(IndexedColors.RED.getIndex()); - * </pre> - * It is necessary to set the fill style in order - * for the color to be shown in the cell. - * - * @param bg - the color to use - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public void setFillBackgroundColor(short bg) { - XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors()); - clr.setIndexed(bg); - setFillBackgroundColor(clr); - } - - /** - * Set the foreground fill color represented as a {@link XSSFColor} value. - * <br> - * <i>Note: Ensure Foreground color is set prior to background color.</i> - * @param color the color to use - * @see #setFillBackgroundColor(org.apache.poi.xssf.usermodel.XSSFColor) ) - */ - public void setFillForegroundColor(XSSFColor color) { - CTFill ct = getCTFill(); - - CTPatternFill ptrn = ct.getPatternFill(); - if(color == null) { - if(ptrn != null && ptrn.isSetFgColor()) ptrn.unsetFgColor(); - } else { - if(ptrn == null) ptrn = ct.addNewPatternFill(); - ptrn.setFgColor(color.getCTColor()); - } - - addFill(ct); - } - - /** - * Set the foreground fill color as a indexed color value - * <br> - * <i>Note: Ensure Foreground color is set prior to background color.</i> - * @param fg the color to use - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public void setFillForegroundColor(short fg) { - XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors()); - clr.setIndexed(fg); - setFillForegroundColor(clr); - } - - /** - * Get a <b>copy</b> of the currently used CTFill, if none is used, return a new instance. - */ - private CTFill getCTFill(){ - CTFill ct; - // bug 56295: handle missing applyFill attribute as "true" because Excel does as well - if(!_cellXf.isSetApplyFill() || _cellXf.getApplyFill()) { - int fillIndex = (int)_cellXf.getFillId(); - XSSFCellFill cf = _stylesSource.getFillAt(fillIndex); - - ct = (CTFill)cf.getCTFill().copy(); - } else { - ct = CTFill.Factory.newInstance(); - } - return ct; - } - - /** - * Set reading order for the cell - * - * @param order - the reading order - */ - public void setReadingOrder(ReadingOrder order) { - getCellAlignment().setReadingOrder(order); - } - - /** - * Get reading order of the cell - * - * @return ReadingOrder - the reading order - */ - public ReadingOrder getReadingOrder() { - return getCellAlignment().getReadingOrder(); - } - - /** - * Get a <b>copy</b> of the currently used CTBorder, if none is used, return a new instance. - */ - private CTBorder getCTBorder(){ - CTBorder ct; - if(_cellXf.getApplyBorder()) { - int idx = Math.toIntExact(_cellXf.getBorderId()); - XSSFCellBorder cf = _stylesSource.getBorderAt(idx); - - ct = (CTBorder)cf.getCTBorder().copy(); - } else { - ct = CTBorder.Factory.newInstance(); - } - return ct; - } - - /** - * This element is used to specify cell fill information for pattern and solid color cell fills. For solid cell fills (no pattern), - * foreground color is used is used. For cell fills with patterns specified, then the cell fill color is specified by the background color element. - * - * @param pattern the fill pattern to use - * @see #setFillBackgroundColor(XSSFColor) - * @see #setFillForegroundColor(XSSFColor) - * @see org.apache.poi.ss.usermodel.FillPatternType - */ - @Override - public void setFillPattern(FillPatternType pattern) { - CTFill ct = getCTFill(); - CTPatternFill ctptrn = ct.isSetPatternFill() ? ct.getPatternFill() : ct.addNewPatternFill(); - if (pattern == FillPatternType.NO_FILL && ctptrn.isSetPatternType()) { - ctptrn.unsetPatternType(); - } else { - ctptrn.setPatternType(STPatternType.Enum.forInt(pattern.getCode() + 1)); - } - - addFill(ct); - } - - /** - * Set the font for this style - * - * @param font a font object created or retrieved from the XSSFWorkbook object - * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#createFont() - * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getFontAt(int) - */ - @Override - public void setFont(Font font) { - if(font != null){ - long index = font.getIndex(); - this._cellXf.setFontId(index); - this._cellXf.setApplyFont(true); - } else { - this._cellXf.setApplyFont(false); - } - } - - /** - * Set the cell's using this style to be hidden - * - * @param hidden - whether the cell using this style should be hidden - */ - @Override - public void setHidden(boolean hidden) { - if (!_cellXf.isSetProtection()) { - _cellXf.addNewProtection(); - } - _cellXf.getProtection().setHidden(hidden); - } - - /** - * Set the number of spaces to indent the text in the cell - * - * @param indent - number of spaces - */ - @Override - public void setIndention(short indent) { - getCellAlignment().setIndent(indent); - } - - /** - * Set the color to use for the left border as a indexed color value - * - * @param color the index of the color definition - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public void setLeftBorderColor(short color) { - XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors()); - clr.setIndexed(color); - setLeftBorderColor(clr); - } - - /** - * Set the color to use for the left border as a {@link XSSFColor} value - * - * @param color the color to use - */ - public void setLeftBorderColor(XSSFColor color) { - CTBorder ct = getCTBorder(); - if(color == null && !ct.isSetLeft()) return; - - CTBorderPr pr = ct.isSetLeft() ? ct.getLeft() : ct.addNewLeft(); - if(color != null) pr.setColor(color.getCTColor()); - else pr.unsetColor(); - - int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - /** - * Set the cell's using this style to be locked - * - * @param locked - whether the cell using this style should be locked - */ - @Override - public void setLocked(boolean locked) { - if (!_cellXf.isSetProtection()) { - _cellXf.addNewProtection(); - } - _cellXf.getProtection().setLocked(locked); - } - - /** - * Turn on or off "Quote Prefix" or "123 Prefix" for the style, - * which is used to tell Excel that the thing which looks like - * a number or a formula shouldn't be treated as on. - */ - @Override - public void setQuotePrefixed(boolean quotePrefix) { - _cellXf.setQuotePrefix(quotePrefix); - } - - /** - * Set the color to use for the right border - * - * @param color the index of the color definition - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public void setRightBorderColor(short color) { - XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors()); - clr.setIndexed(color); - setRightBorderColor(clr); - } - - /** - * Set the color to use for the right border as a {@link XSSFColor} value - * - * @param color the color to use - */ - public void setRightBorderColor(XSSFColor color) { - CTBorder ct = getCTBorder(); - if(color == null && !ct.isSetRight()) return; - - CTBorderPr pr = ct.isSetRight() ? ct.getRight() : ct.addNewRight(); - if(color != null) pr.setColor(color.getCTColor()); - else pr.unsetColor(); - - int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - /** - * Set the degree of rotation for the text in the cell - * <p> - * Expressed in degrees. Values range from 0 to 180. The first letter of - * the text is considered the center-point of the arc. - * <br> - * For 0 - 90, the value represents degrees above horizon. For 91-180 the degrees below the - * horizon is calculated as: - * <br> - * <code>[degrees below horizon] = 90 - textRotation.</code> - * </p> - * - * Note: HSSF uses values from -90 to 90 degrees, whereas XSSF - * uses values from 0 to 180 degrees. The implementations of this method will map between these two value-ranges - * accordingly, however the corresponding getter is returning values in the range mandated by the current type - * of Excel file-format that this CellStyle is applied to. - * - * @param rotation - the rotation degrees (between 0 and 180 degrees) - */ - @Override - public void setRotation(short rotation) { - getCellAlignment().setTextRotation(rotation); - } - - - /** - * Set the color to use for the top border - * - * @param color the index of the color definition - * @see org.apache.poi.ss.usermodel.IndexedColors - */ - @Override - public void setTopBorderColor(short color) { - XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors()); - clr.setIndexed(color); - setTopBorderColor(clr); - } - - /** - * Set the color to use for the top border as a {@link XSSFColor} value - * - * @param color the color to use - */ - public void setTopBorderColor(XSSFColor color) { - CTBorder ct = getCTBorder(); - if(color == null && !ct.isSetTop()) return; - - CTBorderPr pr = ct.isSetTop() ? ct.getTop() : ct.addNewTop(); - if(color != null) pr.setColor(color.getCTColor()); - else pr.unsetColor(); - - int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors())); - - _cellXf.setBorderId(idx); - _cellXf.setApplyBorder(true); - } - - /** - * Set the type of vertical alignment for the cell - * - * @param align - the type of alignment - */ - public void setVerticalAlignment(VerticalAlignment align) { - _cellXf.setApplyAlignment(true); - - getCellAlignment().setVertical(align); - } - - /** - * Set whether the text should be wrapped. - * <p> - * Setting this flag to <code>true</code> make all content visible - * within a cell by displaying it on multiple lines - * </p> - * - * @param wrapped a boolean value indicating if the text in a cell should be line-wrapped within the cell. - */ - @Override - public void setWrapText(boolean wrapped) { - getCellAlignment().setWrapText(wrapped); - } - - /** - * Gets border color - * - * @param side the border side - * @return the used color - */ - public XSSFColor getBorderColor(BorderSide side) { - switch(side){ - case BOTTOM: - return getBottomBorderXSSFColor(); - case RIGHT: - return getRightBorderXSSFColor(); - case TOP: - return getTopBorderXSSFColor(); - case LEFT: - return getLeftBorderXSSFColor(); - default: - throw new IllegalArgumentException("Unknown border: " + side); - } - } - - /** - * Set the color to use for the selected border - * - * @param side - where to apply the color definition - * @param color - the color to use - */ - public void setBorderColor(BorderSide side, XSSFColor color) { - switch(side){ - case BOTTOM: - setBottomBorderColor(color); - break; - case RIGHT: - setRightBorderColor(color); - break; - case TOP: - setTopBorderColor(color); - break; - case LEFT: - setLeftBorderColor(color); - break; - } - } - - @Override - public void setShrinkToFit(boolean shrinkToFit) { - getCellAlignment().setShrinkToFit(shrinkToFit); - } - - private int getFontId() { - if (_cellXf.isSetFontId()) { - return (int) _cellXf.getFontId(); - } - return (int) _cellStyleXf.getFontId(); - } - - /** - * get the cellAlignment object to use for manage alignment - * @return XSSFCellAlignment - cell alignment - */ - protected XSSFCellAlignment getCellAlignment() { - if (this._cellAlignment == null) { - this._cellAlignment = new XSSFCellAlignment(getCTCellAlignment()); - } - return this._cellAlignment; - } - - /** - * Return the CTCellAlignment instance for alignment - * - * @return CTCellAlignment - */ - private CTCellAlignment getCTCellAlignment() { - if (_cellXf.getAlignment() == null) { - _cellXf.setAlignment(CTCellAlignment.Factory.newInstance()); - } - return _cellXf.getAlignment(); - } - - /** - * Returns a hash code value for the object. The hash is derived from the underlying CTXf bean. - * - * @return the hash code value for this style - */ - @Override - public int hashCode(){ - return _cellXf.toString().hashCode(); - } - - /** - * Checks is the supplied style is equal to this style - * - * @param o the style to check - * @return true if the supplied style is equal to this style - */ - @Override - public boolean equals(Object o){ - if(!(o instanceof XSSFCellStyle)) return false; - - XSSFCellStyle cf = (XSSFCellStyle)o; - return _cellXf.toString().equals(cf.getCoreXf().toString()); - } - - /** - * Make a copy of this style. The underlying CTXf bean is cloned, - * the references to fills and borders remain. - * - * @return a copy of this style - */ - @Override - public XSSFCellStyle copy(){ - CTXf xf = (CTXf)_cellXf.copy(); - - int xfSize = _stylesSource._getStyleXfsSize(); - int indexXf = _stylesSource.putCellXf(xf); - return new XSSFCellStyle(indexXf-1, xfSize-1, _stylesSource, _theme); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChart.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChart.java deleted file mode 100644 index e5646a41d6..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChart.java +++ /dev/null @@ -1,238 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLFactory; -import org.apache.poi.ooxml.POIXMLRelation; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.util.Removal; -import org.apache.poi.xddf.usermodel.chart.XDDFChart; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.drawingml.x2006.chart.*; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import javax.xml.namespace.QName; -import java.io.IOException; -import java.io.OutputStream; - -import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -/** - * Represents a SpreadsheetML Chart - */ -public final class XSSFChart extends XDDFChart { - - /** - * Parent graphic frame. - */ - private XSSFGraphicFrame frame; - - /** - * Create a new SpreadsheetML chart - */ - protected XSSFChart() { - super(); - createChart(); - } - - /** - * Construct a SpreadsheetML chart from a package part. - * - * @param part - * the package part holding the chart data, the content type must - * be - * <code>application/vnd.openxmlformats-officedocument.drawingml.chart+xml</code> - * - * @since POI 3.14-Beta1 - */ - protected XSSFChart(PackagePart part) throws IOException, XmlException { - super(part); - } - - @Override - protected POIXMLRelation getChartRelation() { - return null; - } - - @Override - protected POIXMLRelation getChartWorkbookRelation() { - return null; - } - - @Override - protected POIXMLFactory getChartFactory() { - return null; - } - - /** - * Construct a new CTChartSpace bean. By default, it's just an empty - * placeholder for chart objects. - */ - private void createChart() { - CTPlotArea plotArea = getCTPlotArea(); - - plotArea.addNewLayout(); - getCTChart().addNewPlotVisOnly().setVal(true); - - CTPrintSettings printSettings = chartSpace.addNewPrintSettings(); - printSettings.addNewHeaderFooter(); - - CTPageMargins pageMargins = printSettings.addNewPageMargins(); - pageMargins.setB(0.75); - pageMargins.setL(0.70); - pageMargins.setR(0.70); - pageMargins.setT(0.75); - pageMargins.setHeader(0.30); - pageMargins.setFooter(0.30); - printSettings.addNewPageSetup(); - } - - @Override - protected void commit() throws IOException { - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - - /* - * Saved chart space must have the following namespaces set: - * <c:chartSpace - * xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" - * xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" - * xmlns:r= - * "http://schemas.openxmlformats.org/officeDocument/2006/relationships"> - */ - xmlOptions.setSaveSyntheticDocumentElement( - new QName(CTChartSpace.type.getName().getNamespaceURI(), "chartSpace", "c")); - - PackagePart part = getPackagePart(); - try (OutputStream out = part.getOutputStream()) { - chartSpace.save(out, xmlOptions); - } - } - - /** - * Returns the parent graphic frame. - * - * @return the graphic frame this chart belongs to - */ - public XSSFGraphicFrame getGraphicFrame() { - return frame; - } - - /** - * Sets the parent graphic frame. - */ - protected void setGraphicFrame(XSSFGraphicFrame frame) { - this.frame = frame; - } - - /** - * Returns the title static text, or null if none is set. Note that a title - * formula may be set instead. Empty text result is for backward - * compatibility, and could mean the title text is empty or there is a - * formula instead. Check for a formula first, falling back on text for - * cleaner logic. - * - * @return static title text if set, null if there is no title, empty string - * if the title text is empty or the title uses a formula instead - */ - public XSSFRichTextString getTitleText() { - if (!getCTChart().isSetTitle()) { - return null; - } - - // TODO Do properly - CTTitle title = getCTChart().getTitle(); - - StringBuilder text = new StringBuilder(64); - XmlObject[] t = title.selectPath("declare namespace a='" + XSSFDrawing.NAMESPACE_A + "' .//a:t"); - for (XmlObject element : t) { - NodeList kids = element.getDomNode().getChildNodes(); - final int count = kids.getLength(); - for (int n = 0; n < count; n++) { - Node kid = kids.item(n); - if (kid instanceof Text) { - text.append(kid.getNodeValue()); - } - } - } - - return new XSSFRichTextString(text.toString()); - } - - /** - * Get the chart title formula expression if there is one - * - * @return formula expression or null - */ - public String getTitleFormula() { - if (!getCTChart().isSetTitle()) { - return null; - } - - CTTitle title = getCTChart().getTitle(); - - if (!title.isSetTx()) { - return null; - } - - CTTx tx = title.getTx(); - - if (!tx.isSetStrRef()) { - return null; - } - - return tx.getStrRef().getF(); - } - - /** - * Set the formula expression to use for the chart title - * - * @param formula - */ - public void setTitleFormula(String formula) { - CTTitle ctTitle; - if (getCTChart().isSetTitle()) { - ctTitle = getCTChart().getTitle(); - } else { - ctTitle = getCTChart().addNewTitle(); - } - - CTTx tx; - if (ctTitle.isSetTx()) { - tx = ctTitle.getTx(); - } else { - tx = ctTitle.addNewTx(); - } - - if (tx.isSetRich()) { - tx.unsetRich(); - } - - CTStrRef strRef; - if (tx.isSetStrRef()) { - strRef = tx.getStrRef(); - } else { - strRef = tx.addNewStrRef(); - } - - strRef.setF(formula); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChartSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChartSheet.java deleted file mode 100644 index 883e33a58e..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChartSheet.java +++ /dev/null @@ -1,108 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import javax.xml.namespace.QName; - -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTChartsheet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTLegacyDrawing; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.ChartsheetDocument; - -/** - * High level representation of Sheet Parts that are of type 'chartsheet'. - * <p> - * Chart sheet is a special kind of Sheet that contains only chart and no data. - * </p> - * - * @author Yegor Kozlov - */ -public class XSSFChartSheet extends XSSFSheet { - - private static final byte[] BLANK_WORKSHEET = blankWorksheet(); - - protected CTChartsheet chartsheet; - - /** - * @since POI 3.14-Beta1 - */ - protected XSSFChartSheet(PackagePart part) { - super(part); - } - - protected void read(InputStream is) throws IOException { - //initialize the supeclass with a blank worksheet - super.read(new ByteArrayInputStream(BLANK_WORKSHEET)); - - try { - chartsheet = ChartsheetDocument.Factory.parse(is, DEFAULT_XML_OPTIONS).getChartsheet(); - } catch (XmlException e){ - throw new POIXMLException(e); - } - } - - /** - * Provide access to the CTChartsheet bean holding this sheet's data - * - * @return the CTChartsheet bean holding this sheet's data - */ - public CTChartsheet getCTChartsheet() { - return chartsheet; - } - - @Override - protected CTDrawing getCTDrawing() { - return chartsheet.getDrawing(); - } - - @Override - protected CTLegacyDrawing getCTLegacyDrawing() { - return chartsheet.getLegacyDrawing(); - } - - @Override - protected void write(OutputStream out) throws IOException { - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement( - new QName(CTChartsheet.type.getName().getNamespaceURI(), "chartsheet")); - chartsheet.save(out, xmlOptions); - - } - - private static byte[] blankWorksheet(){ - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try { - new XSSFSheet().write(out); - } catch (IOException e){ - throw new RuntimeException(e); - } - return out.toByteArray(); - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java deleted file mode 100644 index ff727adb2a..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java +++ /dev/null @@ -1,84 +0,0 @@ -/* ==================================================================== - 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.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; - -/** - * @author Yegor Kozlov - */ -public final class XSSFChildAnchor extends XSSFAnchor { - private CTTransform2D t2d; - - public XSSFChildAnchor(int x, int y, int cx, int cy) { - t2d = CTTransform2D.Factory.newInstance(); - CTPoint2D off = t2d.addNewOff(); - CTPositiveSize2D ext = t2d.addNewExt(); - - off.setX(x); - off.setY(y); - ext.setCx(Math.abs(cx - x)); - ext.setCy(Math.abs(cy - y)); - if(x > cx) t2d.setFlipH(true); - if(y > cy) t2d.setFlipV(true); - } - - public XSSFChildAnchor(CTTransform2D t2d) { - this.t2d = t2d; - } - - @Internal - public CTTransform2D getCTTransform2D() { - return t2d; - } - - public int getDx1() { - return (int)t2d.getOff().getX(); - } - - public void setDx1(int dx1) { - t2d.getOff().setX(dx1); - } - - public int getDy1() { - return (int)t2d.getOff().getY(); - } - - public void setDy1(int dy1) { - t2d.getOff().setY(dy1); - } - - public int getDy2() { - return (int)(getDy1() + t2d.getExt().getCy()); - } - - public void setDy2(int dy2) { - t2d.getExt().setCy(dy2 - (long)getDy1()); - } - - public int getDx2() { - return (int)(getDx1() + t2d.getExt().getCx()); - } - - public void setDx2(int dx2) { - t2d.getExt().setCx(dx2 - (long)getDx1()); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java deleted file mode 100644 index 428a06ddf1..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java +++ /dev/null @@ -1,425 +0,0 @@ -/* ==================================================================== - 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.ooxml.util.POIXMLUnits; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.util.Internal; -import org.apache.poi.util.Units; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; - -/** - * A client anchor is attached to an excel worksheet. It anchors against: - * <ol> - * <li>A fixed position and fixed size - * <li>A position relative to a cell (top-left) and a fixed size - * <li>A position relative to a cell (top-left) and sized relative to another cell (bottom right) - * </ol> - * - * which method is used is determined by the {@link AnchorType}. - */ -public class XSSFClientAnchor extends XSSFAnchor implements ClientAnchor { - - /** - * placeholder for zeros when needed for dynamic position calculations - */ - private static final CTMarker EMPTY_MARKER = CTMarker.Factory.newInstance(); - - private AnchorType anchorType; - - /** - * Starting anchor point (top-left cell + relative offset) - * if left null recalculate as needed from point - */ - private CTMarker cell1; - - /** - * Ending anchor point (bottom-right cell + relative offset) - * if left null, re-calculate as needed from size and cell1 - */ - private CTMarker cell2; - - /** - * if present, fixed size of the object to use instead of cell2, which is inferred instead - */ - private CTPositiveSize2D size; - - /** - * if present, fixed top-left position to use instead of cell1, which is inferred instead - */ - private CTPoint2D position; - - /** - * sheet to base dynamic calculations on, if needed. Required if size and/or position or set. - * Not needed if cell1/2 are set explicitly (dynamic sizing and position relative to cells). - */ - private XSSFSheet sheet; - - /** - * Creates a new client anchor and defaults all the anchor positions to 0. - * Sets the type to {@link AnchorType#MOVE_AND_RESIZE} relative to cell range A1:A1. - */ - public XSSFClientAnchor() { - this(0,0,0,0,0,0,0,0); - } - - /** - * Creates a new client anchor and sets the top-left and bottom-right - * coordinates of the anchor by cell references and offsets. - * Sets the type to {@link AnchorType#MOVE_AND_RESIZE}. - * - * @param dx1 the x coordinate within the first cell. - * @param dy1 the y coordinate within the first cell. - * @param dx2 the x coordinate within the second cell. - * @param dy2 the y coordinate within the second cell. - * @param col1 the column (0 based) of the first cell. - * @param row1 the row (0 based) of the first cell. - * @param col2 the column (0 based) of the second cell. - * @param row2 the row (0 based) of the second cell. - */ - public XSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) { - anchorType = AnchorType.MOVE_AND_RESIZE; - cell1 = CTMarker.Factory.newInstance(); - cell1.setCol(col1); - cell1.setColOff(dx1); - cell1.setRow(row1); - cell1.setRowOff(dy1); - cell2 = CTMarker.Factory.newInstance(); - cell2.setCol(col2); - cell2.setColOff(dx2); - cell2.setRow(row2); - cell2.setRowOff(dy2); - } - - /** - * Create XSSFClientAnchor from existing xml beans, sized and positioned relative to a pair of cells. - * Sets the type to {@link AnchorType#MOVE_AND_RESIZE}. - * @param cell1 starting anchor point - * @param cell2 ending anchor point - */ - protected XSSFClientAnchor(CTMarker cell1, CTMarker cell2) { - anchorType = AnchorType.MOVE_AND_RESIZE; - this.cell1 = cell1; - this.cell2 = cell2; - } - - /** - * Create XSSFClientAnchor from existing xml beans, sized and positioned relative to a pair of cells. - * Sets the type to {@link AnchorType#MOVE_DONT_RESIZE}. - * - * @param sheet needed to calculate ending point based on column/row sizes - * @param cell1 starting anchor point - * @param size object size, to calculate ending anchor point - */ - protected XSSFClientAnchor(XSSFSheet sheet, CTMarker cell1, CTPositiveSize2D size) { - anchorType = AnchorType.MOVE_DONT_RESIZE; - this.sheet = sheet; - this.size = size; - this.cell1 = cell1; -// this.cell2 = calcCell(sheet, cell1, size.getCx(), size.getCy()); - } - - /** - * Create XSSFClientAnchor from existing xml beans, sized and positioned relative to a pair of cells. - * Sets the type to {@link AnchorType#DONT_MOVE_AND_RESIZE}. - * - * @param sheet needed to calculate starting and ending points based on column/row sizes - * @param position starting absolute position - * @param size object size, to calculate ending position - */ - protected XSSFClientAnchor(XSSFSheet sheet, CTPoint2D position, CTPositiveSize2D size) { - anchorType = AnchorType.DONT_MOVE_AND_RESIZE; - this.sheet = sheet; - this.position = position; - this.size = size; - // zeros for row/col/offsets -// this.cell1 = calcCell(sheet, EMPTY_MARKER, position.getCx(), position.getCy()); -// this.cell2 = calcCell(sheet, cell1, size.getCx(), size.getCy()); - } - - private CTMarker calcCell(CTMarker cell, long w, long h) { - CTMarker c2 = CTMarker.Factory.newInstance(); - - int r = cell.getRow(); - int c = cell.getCol(); - - int cw = Units.columnWidthToEMU(sheet.getColumnWidth(c)); - - // start with width - offset, then keep adding column widths until the next one puts us over w - long wPos = cw - POIXMLUnits.parseLength(cell.xgetColOff()); - - while (wPos < w) { - c++; - cw = Units.columnWidthToEMU(sheet.getColumnWidth(c)); - wPos += cw; - } - // now wPos >= w, so end column = c, now figure offset - c2.setCol(c); - c2.setColOff(cw - (wPos - w)); - - int rh = Units.toEMU(getRowHeight(sheet, r)); - // start with height - offset, then keep adding row heights until the next one puts us over h - long hPos = rh - POIXMLUnits.parseLength(cell.xgetRowOff()); - - while (hPos < h) { - r++; - rh = Units.toEMU(getRowHeight(sheet, r)); - hPos += rh; - } - // now hPos >= h, so end row = r, now figure offset - c2.setRow(r); - c2.setRowOff(rh - (hPos - h)); - - return c2; - } - - /** - * @param sheet - * @param row - * @return height in twips (1/20th of point) for row or default - */ - private static float getRowHeight(XSSFSheet sheet, int row) { - XSSFRow r = sheet.getRow(row); - return r == null ? sheet.getDefaultRowHeightInPoints() : r.getHeightInPoints(); - } - - private CTMarker getCell1() { - return cell1 != null ? cell1 : calcCell(EMPTY_MARKER, POIXMLUnits.parseLength(position.xgetX()), POIXMLUnits.parseLength(position.xgetY())); - } - - private CTMarker getCell2() { - return cell2 != null ? cell2 : calcCell(getCell1(), size.getCx(), size.getCy()); - } - - public short getCol1() { - return (short)getCell1().getCol(); - } - - /** - * @throws NullPointerException if cell1 is null (fixed position) - * @see org.apache.poi.ss.usermodel.ClientAnchor#setCol1(int) - */ - public void setCol1(int col1) { - cell1.setCol(col1); - } - - public short getCol2() { - return (short) getCell2().getCol(); - } - - /** - * @throws NullPointerException if cell2 is null (fixed size) - * @see org.apache.poi.ss.usermodel.ClientAnchor#setCol2(int) - */ - public void setCol2(int col2) { - cell2.setCol(col2); - } - - public int getRow1() { - return getCell1().getRow(); - } - - /** - * @throws NullPointerException if cell1 is null (fixed position) - * @see org.apache.poi.ss.usermodel.ClientAnchor#setRow1(int) - */ - public void setRow1(int row1) { - cell1.setRow(row1); - } - - public int getRow2() { - return getCell2().getRow(); - } - - /** - * @throws NullPointerException if cell2 is null (fixed size) - * @see org.apache.poi.ss.usermodel.ClientAnchor#setRow2(int) - */ - public void setRow2(int row2) { - cell2.setRow(row2); - } - - public int getDx1() { - return Math.toIntExact(POIXMLUnits.parseLength(getCell1().xgetColOff())); - } - - /** - * @throws NullPointerException if cell1 is null (fixed position) - * @see org.apache.poi.ss.usermodel.ChildAnchor#setDx1(int) - */ - public void setDx1(int dx1) { - cell1.setColOff(dx1); - } - - public int getDy1() { - return Math.toIntExact(POIXMLUnits.parseLength(getCell1().xgetRowOff())); - } - - /** - * @throws NullPointerException if cell1 is null (fixed position) - * @see org.apache.poi.ss.usermodel.ChildAnchor#setDy1(int) - */ - public void setDy1(int dy1) { - cell1.setRowOff(dy1); - } - - public int getDy2() { - return Math.toIntExact(POIXMLUnits.parseLength(getCell2().xgetRowOff())); - } - - /** - * @throws NullPointerException if cell2 is null (fixed size) - * @see org.apache.poi.ss.usermodel.ChildAnchor#setDy2(int) - */ - public void setDy2(int dy2) { - cell2.setRowOff(dy2); - } - - public int getDx2() { - return Math.toIntExact(POIXMLUnits.parseLength(getCell2().xgetColOff())); - } - - /** - * @throws NullPointerException if cell2 is null (fixed size) - * @see org.apache.poi.ss.usermodel.ChildAnchor#setDx2(int) - */ - public void setDx2(int dx2) { - cell2.setColOff(dx2); - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof XSSFClientAnchor)) return false; - - XSSFClientAnchor anchor = (XSSFClientAnchor) o; - return getDx1() == anchor.getDx1() && - getDx2() == anchor.getDx2() && - getDy1() == anchor.getDy1() && - getDy2() == anchor.getDy2() && - getCol1() == anchor.getCol1() && - getCol2() == anchor.getCol2() && - getRow1() == anchor.getRow1() && - getRow2() == anchor.getRow2() ; - - } - - @Override - public int hashCode() { - assert false : "hashCode not designed"; - return 42; // any arbitrary constant will do - } - - @Override - public String toString(){ - return "from : " + getCell1() + "; to: " + getCell2(); - } - - /** - * Return starting anchor point - * - * @return starting anchor point - */ - @Internal - public CTMarker getFrom(){ - return getCell1(); - } - - protected void setFrom(CTMarker from){ - cell1 = from; - } - - /** - * Return ending anchor point - * - * @return ending anchor point - */ - @Internal - public CTMarker getTo(){ - return getCell2(); - } - - protected void setTo(CTMarker to){ - cell2 = to; - } - - /** - * @return absolute top-left position, or null if position is determined from the "from" cell - * @since POI 3.17 beta 1 - */ - public CTPoint2D getPosition() { - return position; - } - - /** - * Sets the top-left absolute position of the object. To use this, "from" must be set to null. - * @param position - * @since POI 3.17 beta 1 - */ - public void setPosition(CTPoint2D position) { - this.position = position; - } - - /** - * - * @return size or null, if size is determined from the to and from cells - * @since POI 3.17 beta 1 - */ - public CTPositiveSize2D getSize() { - return size; - } - - /** - * Sets the size of the object. To use this, "to" must be set to null. - * @param size - * @since POI 3.17 beta 1 - */ - public void setSize(CTPositiveSize2D size) { - this.size = size; - } - - /** - * Sets the anchor type - * @param anchorType the anchor type to set - * @since POI 3.14 - */ - @Override - public void setAnchorType( AnchorType anchorType ) - { - this.anchorType = anchorType; - } - - /** - * Gets the anchor type - * Changed from returning an int to an enum in POI 3.14 beta 1. - * @return the anchor type - */ - @Override - public AnchorType getAnchorType() - { - return anchorType; - } - - public boolean isSet(){ - CTMarker c1 = getCell1(); - CTMarker c2 = getCell2(); - return !(c1.getCol() == 0 && c2.getCol() == 0 && - c1.getRow() == 0 && c2.getRow() == 0); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColor.java deleted file mode 100644 index a8507cd92e..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColor.java +++ /dev/null @@ -1,452 +0,0 @@ -/* ==================================================================== - 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 java.util.Arrays; - -import org.apache.poi.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.ExtendedColor; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.util.Internal; -import org.apache.poi.util.Removal; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; - -/** - * Represents a color in SpreadsheetML - */ -public class XSSFColor extends ExtendedColor { - private final CTColor ctColor; - private final IndexedColorMap indexedColorMap; - - /** - * @param color The ooxml color object to use - * @param map The IndexedColorMap to use instead of the default one - * @return null if color is null, new instance otherwise - */ - public static XSSFColor from(CTColor color, IndexedColorMap map) { - //noinspection deprecation - return color == null ? null : new XSSFColor(color, map); - } - - /** - * Create an instance of XSSFColor from the supplied XML bean, with default color indexes - * @param color The {@link CTColor} to use as color-value. - * @deprecated 3.17 beta 1 - pass the workbook styles indexed color map, if any - */ - @Deprecated - @Removal(version="4.2") - public XSSFColor(CTColor color) { - this(color, new DefaultIndexedColorMap()); - } - - /** - * Create an instance of XSSFColor from the supplied XML bean, with the given color indexes - * @param color The {@link CTColor} to use as color-value. - * @param map The IndexedColorMap to use instead of the default one - * @deprecated 4.0.0 - use the factory {@link #from(CTColor, IndexedColorMap)} method instead to check for null CTColor instances. Make private eventually - */ - @Deprecated - @Removal(version = "4.2") - public XSSFColor(CTColor color, IndexedColorMap map) { - this.ctColor = color; - this.indexedColorMap = map; - } - - /** - * Create an new instance of XSSFColor, without knowledge of any custom indexed colors. - * This is OK for just transiently setting indexes, etc. but is discouraged in read/get uses - * @deprecated as of 4.0.0, we want to have the indexed map, and all calling contexts have access to it. - * @see #XSSFColor(IndexedColorMap) - * @see #from(CTColor, IndexedColorMap) - */ - @Deprecated - @Removal(version="4.2") - public XSSFColor() { - this(CTColor.Factory.newInstance(), new DefaultIndexedColorMap()); - } - - /** - * new color with the given indexed color map - * @param colorMap The IndexedColorMap to use instead of the default one - */ - public XSSFColor(IndexedColorMap colorMap) { - //noinspection deprecation - this(CTColor.Factory.newInstance(), colorMap); - } - - /** - * Create an instance of XSSFColor from the awt Color - * @param clr awt Color - * @deprecated 3.17 beta 1 - pass the workbook styles indexed color map, if any - */ - @Deprecated - @Removal(version="4.2") - public XSSFColor(java.awt.Color clr) { - this(clr, new DefaultIndexedColorMap()); - } - - /** - * TEST ONLY - * @param clr awt Color - * @param map The IndexedColorMap to use instead of the default one - */ - public XSSFColor(java.awt.Color clr, IndexedColorMap map) { - this(map); - setColor(clr); - } - - /** - * - * @param rgb The RGB-byte-values for the Color - * @param colorMap The IndexedColorMap to use instead of the default one - */ - public XSSFColor(byte[] rgb, IndexedColorMap colorMap) { - //noinspection deprecation - this(CTColor.Factory.newInstance(), colorMap); - ctColor.setRgb(rgb); - } - - /** - * @param indexedColor color index (Enum named for default colors) - * @param colorMap The IndexedColorMap to use instead of the default one - */ - public XSSFColor(IndexedColors indexedColor, IndexedColorMap colorMap) { - //noinspection deprecation - this(CTColor.Factory.newInstance(), colorMap); - ctColor.setIndexed(indexedColor.index); - } - - /** - * A boolean value indicating the ctColor is automatic and system ctColor dependent. - */ - @Override - public boolean isAuto() { - return ctColor.getAuto(); - } - /** - * @param auto true if the ctColor is automatic and system ctColor dependent. - */ - public void setAuto(boolean auto) { - ctColor.setAuto(auto); - } - - /** - * A boolean value indicating the ctColor is Indexed - */ - @Override - public boolean isIndexed() { - return ctColor.isSetIndexed(); - } - - /** - * @return true if the ctColor is RGB or ARGB based - */ - @Override - public boolean isRGB() { - return ctColor.isSetRgb(); - } - - /** - * @return true if the ctColor is Theme based - */ - @Override - public boolean isThemed() { - return ctColor.isSetTheme(); - } - - /** - * @return true if the ctColor has a alpha - */ - public boolean hasAlpha() { - return ctColor.isSetRgb() && ctColor.getRgb().length == 4; - } - - /** - * @return true if the ctColor has a tint - */ - public boolean hasTint() { - return ctColor.isSetTint() && ctColor.getTint() != 0; - } - - /** - * Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors. - */ - @Override - public short getIndex() { - return (short)ctColor.getIndexed(); - } - /** - * @return Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors. - */ - public short getIndexed() { - return getIndex(); - } - - /** - * Indexed ctColor value. Only used for backwards compatibility. References a ctColor in indexedColors. - * @param indexed color index - */ - public void setIndexed(int indexed) { - ctColor.setIndexed(indexed); - } - - /** - * Standard Red Green Blue ctColor value (RGB). - * If there was an A (Alpha) value, it will be stripped. - */ - @Override - public byte[] getRGB() { - byte[] rgb = getRGBOrARGB(); - if(rgb == null) { - return null; - } - - // Need to trim off the alpha - return rgb.length == 4 ? Arrays.copyOfRange(rgb, 1, 4) : rgb; - } - - /** - * Standard Alpha Red Green Blue ctColor value (ARGB). - */ - @Override - public byte[] getARGB() { - byte[] rgb = getRGBOrARGB(); - if(rgb == null) { - return null; - } - - if(rgb.length == 3) { - // Pad with the default Alpha - byte[] tmp = new byte[4]; - tmp[0] = -1; - System.arraycopy(rgb, 0, tmp, 1, 3); - return tmp; - } else { - return rgb; - } - } - - @Override - protected byte[] getStoredRBG() { - return ctColor.getRgb(); - } - - protected byte[] getIndexedRGB() { - if (isIndexed()) { - if (indexedColorMap != null) return indexedColorMap.getRGB(getIndex()); - return DefaultIndexedColorMap.getDefaultRGB(getIndex()); - } - return null; - } - - /** - * Standard Alpha Red Green Blue ctColor value (ARGB). - */ - @Override - public void setRGB(byte[] rgb) { - ctColor.setRgb(rgb); - } - - /** - * Index into the <clrScheme> collection, referencing a particular <sysClr> or - * <srgbClr> value expressed in the Theme part. - */ - @Override - public int getTheme() { - return (int)ctColor.getTheme(); - } - - /** - * Index into the <clrScheme> collection, referencing a particular <sysClr> or - * <srgbClr> value expressed in the Theme part. - * @param theme index - */ - public void setTheme(int theme) { - ctColor.setTheme(theme); - } - - /** - * Specifies the tint value applied to the ctColor. - * - * <p> - * If tint is supplied, then it is applied to the RGB value of the ctColor to determine the final - * ctColor applied. - * </p> - * <p> - * The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken and - * 1.0 means 100% lighten. Also, 0.0 means no change. - * </p> - * <p> - * In loading the RGB value, it is converted to HLS where HLS values are (0..HLSMAX), where - * HLSMAX is currently 255. - * </p> - * Here are some examples of how to apply tint to ctColor: - * <blockquote> - * <pre> - * If (tint < 0) - * Lum' = Lum * (1.0 + tint) - * - * For example: Lum = 200; tint = -0.5; Darken 50% - * Lum' = 200 * (0.5) => 100 - * For example: Lum = 200; tint = -1.0; Darken 100% (make black) - * Lum' = 200 * (1.0-1.0) => 0 - * If (tint > 0) - * Lum' = Lum * (1.0-tint) + (HLSMAX - HLSMAX * (1.0-tint)) - * For example: Lum = 100; tint = 0.75; Lighten 75% - * - * Lum' = 100 * (1-.75) + (HLSMAX - HLSMAX*(1-.75)) - * = 100 * .25 + (255 - 255 * .25) - * = 25 + (255 - 63) = 25 + 192 = 217 - * For example: Lum = 100; tint = 1.0; Lighten 100% (make white) - * Lum' = 100 * (1-1) + (HLSMAX - HLSMAX*(1-1)) - * = 100 * 0 + (255 - 255 * 0) - * = 0 + (255 - 0) = 255 - * </pre> - * </blockquote> - * - * @return the tint value - */ - @Override - public double getTint() { - return ctColor.getTint(); - } - - /** - * Specifies the tint value applied to the ctColor. - * - * <p> - * If tint is supplied, then it is applied to the RGB value of the ctColor to determine the final - * ctColor applied. - * </p> - * <p> - * The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken and - * 1.0 means 100% lighten. Also, 0.0 means no change. - * </p> - * <p> - * In loading the RGB value, it is converted to HLS where HLS values are (0..HLSMAX), where - * HLSMAX is currently 255. - * </p> - * Here are some examples of how to apply tint to ctColor: - * <blockquote> - * <pre> - * If (tint < 0) - * Lum' = Lum * (1.0 + tint) - * - * For example: Lum = 200; tint = -0.5; Darken 50% - * Lum' = 200 * (0.5) => 100 - * For example: Lum = 200; tint = -1.0; Darken 100% (make black) - * Lum' = 200 * (1.0-1.0) => 0 - * If (tint > 0) - * Lum' = Lum * (1.0-tint) + (HLSMAX - HLSMAX * (1.0-tint)) - * For example: Lum = 100; tint = 0.75; Lighten 75% - * - * Lum' = 100 * (1-.75) + (HLSMAX - HLSMAX*(1-.75)) - * = 100 * .25 + (255 - 255 * .25) - * = 25 + (255 - 63) = 25 + 192 = 217 - * For example: Lum = 100; tint = 1.0; Lighten 100% (make white) - * Lum' = 100 * (1-1) + (HLSMAX - HLSMAX*(1-1)) - * = 100 * 0 + (255 - 255 * 0) - * = 0 + (255 - 0) = 255 - * </pre> - * </blockquote> - * - * @param tint the tint value - */ - @Override - public void setTint(double tint) { - ctColor.setTint(tint); - } - - /** - * Returns the underlying XML bean - * - * @return the underlying XML bean - */ - @Internal - public CTColor getCTColor(){ - return ctColor; - } - - /** - * Checked type cast <tt>color</tt> to an XSSFColor. - * - * @param color the color to type cast - * @return the type casted color - * @throws IllegalArgumentException if color is null or is not an instance of XSSFColor - */ - public static XSSFColor toXSSFColor(Color color) { - // FIXME: this method would be more useful if it could convert any Color to an XSSFColor - // Currently the only benefit of this method is to throw an IllegalArgumentException - // instead of a ClassCastException. - if (color != null && !(color instanceof XSSFColor)) { - throw new IllegalArgumentException("Only XSSFColor objects are supported, but had " + color.getClass()); - } - return (XSSFColor)color; - } - - @Override - public int hashCode(){ - return ctColor.toString().hashCode(); - } - - // Helper methods for {@link #equals(Object)} - private boolean sameIndexed(XSSFColor other) { - if (isIndexed() == other.isIndexed()) { - return !isIndexed() || getIndexed() == other.getIndexed(); - } - return false; - } - private boolean sameARGB(XSSFColor other) { - if (isRGB() == other.isRGB()) { - return !isRGB() || Arrays.equals(getARGB(), other.getARGB()); - } - return false; - } - private boolean sameTheme(XSSFColor other) { - if (isThemed() == other.isThemed()) { - return !isThemed() || getTheme() == other.getTheme(); - } - return false; - } - private boolean sameTint(XSSFColor other) { - if (hasTint() == other.hasTint()) { - return !hasTint() || getTint() == other.getTint(); - } - return false; - } - private boolean sameAuto(XSSFColor other) { - return isAuto() == other.isAuto(); - } - - @Override - public boolean equals(Object o){ - if(!(o instanceof XSSFColor)) { - return false; - } - - XSSFColor other = (XSSFColor)o; - - // Compare each field in ctColor. - // Cannot compare ctColor's XML string representation because equivalent - // colors may have different relation namespace URI's - return sameARGB(other) - && sameTheme(other) - && sameIndexed(other) - && sameTint(other) - && sameAuto(other); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColorScaleFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColorScaleFormatting.java deleted file mode 100644 index 31f5f28373..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColorScaleFormatting.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * ==================================================================== - * 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.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.ColorScaleFormatting; -import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColorScale; - -/** - * High level representation for Color Scale / Color Gradient Formatting - * component of Conditional Formatting settings - */ -public class XSSFColorScaleFormatting implements ColorScaleFormatting { - private CTColorScale _scale; - private IndexedColorMap _indexedColorMap; - - /*package*/ XSSFColorScaleFormatting(CTColorScale scale, IndexedColorMap colorMap){ - _scale = scale; - _indexedColorMap = colorMap; - } - - public int getNumControlPoints() { - return _scale.sizeOfCfvoArray(); - } - public void setNumControlPoints(int num) { - while (num < _scale.sizeOfCfvoArray()) { - _scale.removeCfvo(_scale.sizeOfCfvoArray()-1); - _scale.removeColor(_scale.sizeOfColorArray()-1); - } - while (num > _scale.sizeOfCfvoArray()) { - _scale.addNewCfvo(); - _scale.addNewColor(); - } - } - - public XSSFColor[] getColors() { - CTColor[] ctcols = _scale.getColorArray(); - XSSFColor[] c = new XSSFColor[ctcols.length]; - for (int i=0; i<ctcols.length; i++) { - c[i] = XSSFColor.from(ctcols[i], _indexedColorMap); - } - return c; - } - public void setColors(Color[] colors) { - CTColor[] ctcols = new CTColor[colors.length]; - for (int i=0; i<colors.length; i++) { - ctcols[i] = ((XSSFColor)colors[i]).getCTColor(); - } - _scale.setColorArray(ctcols); - } - - public XSSFConditionalFormattingThreshold[] getThresholds() { - CTCfvo[] cfvos = _scale.getCfvoArray(); - XSSFConditionalFormattingThreshold[] t = - new XSSFConditionalFormattingThreshold[cfvos.length]; - for (int i=0; i<cfvos.length; i++) { - t[i] = new XSSFConditionalFormattingThreshold(cfvos[i]); - } - return t; - } - public void setThresholds(ConditionalFormattingThreshold[] thresholds) { - CTCfvo[] cfvos = new CTCfvo[thresholds.length]; - for (int i=0; i<thresholds.length; i++) { - cfvos[i] = ((XSSFConditionalFormattingThreshold)thresholds[i]).getCTCfvo(); - } - _scale.setCfvoArray(cfvos); - } - - /** - * @return color from scale - */ - public XSSFColor createColor() { - return XSSFColor.from(_scale.addNewColor(), _indexedColorMap); - } - public XSSFConditionalFormattingThreshold createThreshold() { - return new XSSFConditionalFormattingThreshold(_scale.addNewCfvo()); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java deleted file mode 100644 index 441f242f4a..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java +++ /dev/null @@ -1,263 +0,0 @@ -/* ==================================================================== - 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.util.Units.EMU_PER_PIXEL; - -import java.math.BigInteger; - -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Comment; -import org.apache.poi.ss.usermodel.RichTextString; -import org.apache.poi.ss.util.CellAddress; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.model.CommentsTable; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; - -import com.microsoft.schemas.office.excel.CTClientData; -import com.microsoft.schemas.vml.CTShape; - -public class XSSFComment implements Comment { - - private final CTComment _comment; - private final CommentsTable _comments; - private final CTShape _vmlShape; - - /** - * cached reference to the string with the comment text - */ - private XSSFRichTextString _str; - - /** - * Creates a new XSSFComment, associated with a given - * low level comment object. - */ - public XSSFComment(CommentsTable comments, CTComment comment, CTShape vmlShape) { - _comment = comment; - _comments = comments; - _vmlShape = vmlShape; - - // we potentially need to adjust the column/row information in the shape - // the same way as we do in setRow()/setColumn() - if(comment != null && vmlShape != null && vmlShape.sizeOfClientDataArray() > 0) { - CellReference ref = new CellReference(comment.getRef()); - CTClientData clientData = vmlShape.getClientDataArray(0); - clientData.setRowArray(0, new BigInteger(String.valueOf(ref.getRow()))); - clientData.setColumnArray(0, new BigInteger(String.valueOf(ref.getCol()))); - - avoidXmlbeansCorruptPointer(vmlShape); - } - } - - /** - * - * @return Name of the original comment author. Default value is blank. - */ - @Override - public String getAuthor() { - return _comments.getAuthor(_comment.getAuthorId()); - } - - /** - * Name of the original comment author. Default value is blank. - * - * @param author the name of the original author of the comment - */ - @Override - public void setAuthor(String author) { - _comment.setAuthorId(_comments.findAuthor(author)); - } - - /** - * @return the 0-based column of the cell that the comment is associated with. - */ - @Override - public int getColumn() { - return getAddress().getColumn(); - } - - /** - * @return the 0-based row index of the cell that the comment is associated with. - */ - @Override - public int getRow() { - return getAddress().getRow(); - } - - /** - * Returns whether this comment is visible. - * - * @return <code>true</code> if the comment is visible, <code>false</code> otherwise - */ - @Override - public boolean isVisible() { - boolean visible = false; - if(_vmlShape != null) { - String style = _vmlShape.getStyle(); - visible = style != null && style.contains("visibility:visible"); - } - return visible; - } - - /** - * Sets whether this comment is visible. - * - * @param visible <code>true</code> if the comment is visible, <code>false</code> otherwise - */ - @Override - public void setVisible(boolean visible) { - if(_vmlShape != null){ - String style; - if(visible) style = "position:absolute;visibility:visible"; - else style = "position:absolute;visibility:hidden"; - _vmlShape.setStyle(style); - } - } - - @Override - public CellAddress getAddress() { - return new CellAddress(_comment.getRef()); - } - - @Override - public void setAddress(int row, int col) { - setAddress(new CellAddress(row, col)); - } - - @Override - public void setAddress(CellAddress address) { - CellAddress oldRef = new CellAddress(_comment.getRef()); - if (address.equals(oldRef)) { - // nothing to do - return; - } - - _comment.setRef(address.formatAsString()); - _comments.referenceUpdated(oldRef, _comment); - - if (_vmlShape != null) { - CTClientData clientData = _vmlShape.getClientDataArray(0); - clientData.setRowArray(0, new BigInteger(String.valueOf(address.getRow()))); - clientData.setColumnArray(0, new BigInteger(String.valueOf(address.getColumn()))); - - avoidXmlbeansCorruptPointer(_vmlShape); - } - } - - /** - * Set the column of the cell that contains the comment - * - * If changing both row and column, use {@link #setAddress}. - * - * @param col the 0-based column of the cell that contains the comment - */ - @Override - public void setColumn(int col) { - setAddress(getRow(), col); - } - - /** - * Set the row of the cell that contains the comment - * - * If changing both row and column, use {@link #setAddress}. - * - * @param row the 0-based row of the cell that contains the comment - */ - @Override - public void setRow(int row) { - setAddress(row, getColumn()); - } - - /** - * @return the rich text string of the comment - */ - @Override - public XSSFRichTextString getString() { - if(_str == null) { - CTRst rst = _comment.getText(); - if(rst != null) _str = new XSSFRichTextString(_comment.getText()); - } - return _str; - } - - /** - * Sets the rich text string used by this comment. - * - * @param string the XSSFRichTextString used by this object. - */ - @Override - public void setString(RichTextString string) { - if(!(string instanceof XSSFRichTextString)){ - throw new IllegalArgumentException("Only XSSFRichTextString argument is supported"); - } - _str = (XSSFRichTextString)string; - _comment.setText(_str.getCTRst()); - } - - public void setString(String string) { - setString(new XSSFRichTextString(string)); - } - - @Override - public ClientAnchor getClientAnchor() { - if(_vmlShape == null) { - return null; - } - String position = _vmlShape.getClientDataArray(0).getAnchorArray(0); - int[] pos = new int[8]; - int i = 0; - for (String s : position.split(",")) { - pos[i++] = Integer.parseInt(s.trim()); - } - return new XSSFClientAnchor(pos[1]*EMU_PER_PIXEL, pos[3]*EMU_PER_PIXEL, pos[5]*EMU_PER_PIXEL, pos[7]*EMU_PER_PIXEL, pos[0], pos[2], pos[4], pos[6]); - } - - /** - * @return the xml bean holding this comment's properties - */ - protected CTComment getCTComment(){ - return _comment; - } - - protected CTShape getCTShape(){ - return _vmlShape; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof XSSFComment)) { - return false; - } - XSSFComment other = (XSSFComment) obj; - return ((getCTComment() == other.getCTComment()) && - (getCTShape() == other.getCTShape())); - } - - @Override - public int hashCode() { - return ((getRow()*17) + getColumn())*31; - } - - private static void avoidXmlbeansCorruptPointer(CTShape vmlShape) { - // There is a very odd xmlbeans bug when changing the row - // arrays which can lead to corrupt pointer - // This call seems to fix them again... See bug #50795 - //noinspection ResultOfMethodCallIgnored - vmlShape.getClientDataList().toString(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionFilterData.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionFilterData.java deleted file mode 100644 index 59bfb94067..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionFilterData.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * ==================================================================== - * 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.ss.usermodel.ConditionFilterData; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule; - -public class XSSFConditionFilterData implements ConditionFilterData { - - private final CTCfRule _cfRule; - - /*package*/ XSSFConditionFilterData(CTCfRule cfRule) { - _cfRule = cfRule; - } - - public boolean getAboveAverage() { - return _cfRule.getAboveAverage(); - } - - public boolean getBottom() { - return _cfRule.getBottom(); - } - - public boolean getEqualAverage() { - return _cfRule.getEqualAverage(); - } - - public boolean getPercent() { - return _cfRule.getPercent(); - } - - public long getRank() { - return _cfRule.getRank(); - } - - public int getStdDev() { - return _cfRule.getStdDev(); - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormatting.java deleted file mode 100644 index eff8e375b4..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormatting.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * ==================================================================== - * 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.ss.usermodel.ConditionalFormatting; -import org.apache.poi.ss.usermodel.ConditionalFormattingRule; -import org.apache.poi.ss.util.CellRangeAddress; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTConditionalFormatting; - -import java.util.ArrayList; -import java.util.Collections; - -/** - * @author Yegor Kozlov - */ -public class XSSFConditionalFormatting implements ConditionalFormatting { - private final CTConditionalFormatting _cf; - private final XSSFSheet _sh; - - /*package*/ XSSFConditionalFormatting(XSSFSheet sh) { - _cf = CTConditionalFormatting.Factory.newInstance(); - _sh = sh; - } - - /*package*/ XSSFConditionalFormatting( - XSSFSheet sh, CTConditionalFormatting cf) { - _cf = cf; - _sh = sh; - } - - /*package*/ CTConditionalFormatting getCTConditionalFormatting() { - return _cf; - } - - /** - * @return array of <tt>CellRangeAddress</tt>s. Never <code>null</code> - */ - @Override - public CellRangeAddress[] getFormattingRanges() { - ArrayList<CellRangeAddress> lst = new ArrayList<>(); - for (Object stRef : _cf.getSqref()) { - String[] regions = stRef.toString().split(" "); - for (final String region : regions) { - lst.add(CellRangeAddress.valueOf(region)); - } - } - return lst.toArray(new CellRangeAddress[0]); - } - - @Override - public void setFormattingRanges(CellRangeAddress[] ranges) { - if (ranges == null) { - throw new IllegalArgumentException("cellRanges must not be null"); - } - final StringBuilder sb = new StringBuilder(); - boolean first = true; - for (CellRangeAddress range : ranges) { - if (!first) { - sb.append(" "); - } else { - first = false; - } - sb.append(range.formatAsString()); - } - _cf.setSqref(Collections.singletonList(sb.toString())); - } - - /** - * Replaces an existing Conditional Formatting rule at position idx. - * Excel allows to create up to 3 Conditional Formatting rules. - * This method can be useful to modify existing Conditional Formatting rules. - * - * @param idx position of the rule. Should be between 0 and 2. - * @param cfRule - Conditional Formatting rule - */ - @Override - public void setRule(int idx, ConditionalFormattingRule cfRule) { - XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule) cfRule; - _cf.getCfRuleArray(idx).set(xRule.getCTCfRule()); - } - - /** - * Add a Conditional Formatting rule. - * Excel allows to create up to 3 Conditional Formatting rules. - * - * @param cfRule - Conditional Formatting rule - */ - @Override - public void addRule(ConditionalFormattingRule cfRule) { - XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule) cfRule; - _cf.addNewCfRule().set(xRule.getCTCfRule()); - } - - /** - * @return the Conditional Formatting rule at position idx. - */ - @Override - public XSSFConditionalFormattingRule getRule(int idx) { - return new XSSFConditionalFormattingRule(_sh, _cf.getCfRuleArray(idx)); - } - - /** - * @return number of Conditional Formatting rules. - */ - @Override - public int getNumberOfRules() { - return _cf.sizeOfCfRuleArray(); - } - - @Override - public String toString() { - return _cf.toString(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java deleted file mode 100644 index 829acbbd30..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - * ==================================================================== - * 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 java.util.HashMap; -import java.util.Map; - -import org.apache.poi.ss.usermodel.ComparisonOperator; -import org.apache.poi.ss.usermodel.ConditionFilterData; -import org.apache.poi.ss.usermodel.ConditionFilterType; -import org.apache.poi.ss.usermodel.ConditionType; -import org.apache.poi.ss.usermodel.ConditionalFormattingRule; -import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; -import org.apache.poi.ss.usermodel.ExcelNumberFormat; -import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; -import org.apache.poi.xssf.model.StylesTable; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColorScale; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataBar; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxf; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIconSet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmt; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfvoType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STConditionalFormattingOperator; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STIconSetType; - -/** - * XSSF support for Conditional Formatting rules - */ -public class XSSFConditionalFormattingRule implements ConditionalFormattingRule { - private final CTCfRule _cfRule; - private XSSFSheet _sh; - - private static Map<STCfType.Enum, ConditionType> typeLookup = new HashMap<>(); - private static Map<STCfType.Enum, ConditionFilterType> filterTypeLookup = new HashMap<>(); - static { - typeLookup.put(STCfType.CELL_IS, ConditionType.CELL_VALUE_IS); - typeLookup.put(STCfType.EXPRESSION, ConditionType.FORMULA); - typeLookup.put(STCfType.COLOR_SCALE, ConditionType.COLOR_SCALE); - typeLookup.put(STCfType.DATA_BAR, ConditionType.DATA_BAR); - typeLookup.put(STCfType.ICON_SET, ConditionType.ICON_SET); - - // These are all subtypes of Filter, we think... - typeLookup.put(STCfType.TOP_10, ConditionType.FILTER); - typeLookup.put(STCfType.UNIQUE_VALUES, ConditionType.FILTER); - typeLookup.put(STCfType.DUPLICATE_VALUES, ConditionType.FILTER); - typeLookup.put(STCfType.CONTAINS_TEXT, ConditionType.FILTER); - typeLookup.put(STCfType.NOT_CONTAINS_TEXT, ConditionType.FILTER); - typeLookup.put(STCfType.BEGINS_WITH, ConditionType.FILTER); - typeLookup.put(STCfType.ENDS_WITH, ConditionType.FILTER); - typeLookup.put(STCfType.CONTAINS_BLANKS, ConditionType.FILTER); - typeLookup.put(STCfType.NOT_CONTAINS_BLANKS, ConditionType.FILTER); - typeLookup.put(STCfType.CONTAINS_ERRORS, ConditionType.FILTER); - typeLookup.put(STCfType.NOT_CONTAINS_ERRORS, ConditionType.FILTER); - typeLookup.put(STCfType.TIME_PERIOD, ConditionType.FILTER); - typeLookup.put(STCfType.ABOVE_AVERAGE, ConditionType.FILTER); - - filterTypeLookup.put(STCfType.TOP_10, ConditionFilterType.TOP_10); - filterTypeLookup.put(STCfType.UNIQUE_VALUES, ConditionFilterType.UNIQUE_VALUES); - filterTypeLookup.put(STCfType.DUPLICATE_VALUES, ConditionFilterType.DUPLICATE_VALUES); - filterTypeLookup.put(STCfType.CONTAINS_TEXT, ConditionFilterType.CONTAINS_TEXT); - filterTypeLookup.put(STCfType.NOT_CONTAINS_TEXT, ConditionFilterType.NOT_CONTAINS_TEXT); - filterTypeLookup.put(STCfType.BEGINS_WITH, ConditionFilterType.BEGINS_WITH); - filterTypeLookup.put(STCfType.ENDS_WITH, ConditionFilterType.ENDS_WITH); - filterTypeLookup.put(STCfType.CONTAINS_BLANKS, ConditionFilterType.CONTAINS_BLANKS); - filterTypeLookup.put(STCfType.NOT_CONTAINS_BLANKS, ConditionFilterType.NOT_CONTAINS_BLANKS); - filterTypeLookup.put(STCfType.CONTAINS_ERRORS, ConditionFilterType.CONTAINS_ERRORS); - filterTypeLookup.put(STCfType.NOT_CONTAINS_ERRORS, ConditionFilterType.NOT_CONTAINS_ERRORS); - filterTypeLookup.put(STCfType.TIME_PERIOD, ConditionFilterType.TIME_PERIOD); - filterTypeLookup.put(STCfType.ABOVE_AVERAGE, ConditionFilterType.ABOVE_AVERAGE); - - } - - /** - * NOTE: does not set priority, so this assumes the rule will not be added to the sheet yet - * @param sh - */ - /*package*/ XSSFConditionalFormattingRule(XSSFSheet sh){ - _cfRule = CTCfRule.Factory.newInstance(); - _sh = sh; - } - - /*package*/ XSSFConditionalFormattingRule(XSSFSheet sh, CTCfRule cfRule){ - _cfRule = cfRule; - _sh = sh; - } - - /*package*/ CTCfRule getCTCfRule(){ - return _cfRule; - } - - /*package*/ CTDxf getDxf(boolean create){ - StylesTable styles = _sh.getWorkbook().getStylesSource(); - CTDxf dxf = null; - if(styles._getDXfsSize() > 0 && _cfRule.isSetDxfId()){ - int dxfId = (int)_cfRule.getDxfId(); - dxf = styles.getDxfAt(dxfId); - } - if(create && dxf == null) { - dxf = CTDxf.Factory.newInstance(); - int dxfId = styles.putDxf(dxf); - _cfRule.setDxfId(dxfId - 1L); - } - return dxf; - } - - public int getPriority() { - final int priority = _cfRule.getPriority(); - // priorities start at 1, if it is less, it is undefined, use definition order in caller - return priority >=1 ? priority : 0; - } - - public boolean getStopIfTrue() { - return _cfRule.getStopIfTrue(); - } - - /** - * Create a new border formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - border formatting object, never returns <code>null</code>. - */ - public XSSFBorderFormatting createBorderFormatting(){ - CTDxf dxf = getDxf(true); - CTBorder border; - if(!dxf.isSetBorder()) { - border = dxf.addNewBorder(); - } else { - border = dxf.getBorder(); - } - - return new XSSFBorderFormatting(border, _sh.getWorkbook().getStylesSource().getIndexedColors()); - } - - /** - * @return - border formatting object if defined, <code>null</code> otherwise - */ - public XSSFBorderFormatting getBorderFormatting(){ - CTDxf dxf = getDxf(false); - if(dxf == null || !dxf.isSetBorder()) return null; - - return new XSSFBorderFormatting(dxf.getBorder(), _sh.getWorkbook().getStylesSource().getIndexedColors()); - } - - /** - * Create a new font formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - font formatting object, never returns <code>null</code>. - */ - public XSSFFontFormatting createFontFormatting(){ - CTDxf dxf = getDxf(true); - CTFont font; - if(!dxf.isSetFont()) { - font = dxf.addNewFont(); - } else { - font = dxf.getFont(); - } - - return new XSSFFontFormatting(font, _sh.getWorkbook().getStylesSource().getIndexedColors()); - } - - /** - * @return - font formatting object if defined, <code>null</code> otherwise - */ - public XSSFFontFormatting getFontFormatting(){ - CTDxf dxf = getDxf(false); - if(dxf == null || !dxf.isSetFont()) return null; - - return new XSSFFontFormatting(dxf.getFont(), _sh.getWorkbook().getStylesSource().getIndexedColors()); - } - - /** - * Create a new pattern formatting structure if it does not exist, - * otherwise just return existing object. - * - * @return - pattern formatting object, never returns <code>null</code>. - */ - public XSSFPatternFormatting createPatternFormatting(){ - CTDxf dxf = getDxf(true); - CTFill fill; - if(!dxf.isSetFill()) { - fill = dxf.addNewFill(); - } else { - fill = dxf.getFill(); - } - - return new XSSFPatternFormatting(fill, _sh.getWorkbook().getStylesSource().getIndexedColors()); - } - - /** - * @return - pattern formatting object if defined, <code>null</code> otherwise - */ - public XSSFPatternFormatting getPatternFormatting(){ - CTDxf dxf = getDxf(false); - if(dxf == null || !dxf.isSetFill()) return null; - - return new XSSFPatternFormatting(dxf.getFill(), _sh.getWorkbook().getStylesSource().getIndexedColors()); - } - - /** - * - * @param color - * @return data bar formatting - */ - public XSSFDataBarFormatting createDataBarFormatting(XSSFColor color) { - // Is it already there? - if (_cfRule.isSetDataBar() && _cfRule.getType() == STCfType.DATA_BAR) - return getDataBarFormatting(); - - // Mark it as being a Data Bar - _cfRule.setType(STCfType.DATA_BAR); - - // Ensure the right element - CTDataBar bar = null; - if (_cfRule.isSetDataBar()) { - bar = _cfRule.getDataBar(); - } else { - bar = _cfRule.addNewDataBar(); - } - // Set the color - bar.setColor(color.getCTColor()); - - // Add the default thresholds - CTCfvo min = bar.addNewCfvo(); - min.setType(STCfvoType.Enum.forString(RangeType.MIN.name)); - CTCfvo max = bar.addNewCfvo(); - max.setType(STCfvoType.Enum.forString(RangeType.MAX.name)); - - // Wrap and return - return new XSSFDataBarFormatting(bar, _sh.getWorkbook().getStylesSource().getIndexedColors()); - } - public XSSFDataBarFormatting getDataBarFormatting() { - if (_cfRule.isSetDataBar()) { - CTDataBar bar = _cfRule.getDataBar(); - return new XSSFDataBarFormatting(bar, _sh.getWorkbook().getStylesSource().getIndexedColors()); - } else { - return null; - } - } - - public XSSFIconMultiStateFormatting createMultiStateFormatting(IconSet iconSet) { - // Is it already there? - if (_cfRule.isSetIconSet() && _cfRule.getType() == STCfType.ICON_SET) - return getMultiStateFormatting(); - - // Mark it as being an Icon Set - _cfRule.setType(STCfType.ICON_SET); - - // Ensure the right element - CTIconSet icons = null; - if (_cfRule.isSetIconSet()) { - icons = _cfRule.getIconSet(); - } else { - icons = _cfRule.addNewIconSet(); - } - // Set the type of the icon set - if (iconSet.name != null) { - STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(iconSet.name); - icons.setIconSet(xIconSet); - } - - // Add a default set of thresholds - int jump = 100 / iconSet.num; - STCfvoType.Enum type = STCfvoType.Enum.forString(RangeType.PERCENT.name); - for (int i=0; i<iconSet.num; i++) { - CTCfvo cfvo = icons.addNewCfvo(); - cfvo.setType(type); - cfvo.setVal(Integer.toString(i*jump)); - } - - // Wrap and return - return new XSSFIconMultiStateFormatting(icons); - } - public XSSFIconMultiStateFormatting getMultiStateFormatting() { - if (_cfRule.isSetIconSet()) { - CTIconSet icons = _cfRule.getIconSet(); - return new XSSFIconMultiStateFormatting(icons); - } else { - return null; - } - } - - public XSSFColorScaleFormatting createColorScaleFormatting() { - // Is it already there? - if (_cfRule.isSetColorScale() && _cfRule.getType() == STCfType.COLOR_SCALE) - return getColorScaleFormatting(); - - // Mark it as being a Color Scale - _cfRule.setType(STCfType.COLOR_SCALE); - - // Ensure the right element - CTColorScale scale = null; - if (_cfRule.isSetColorScale()) { - scale = _cfRule.getColorScale(); - } else { - scale = _cfRule.addNewColorScale(); - } - - // Add a default set of thresholds and colors - if (scale.sizeOfCfvoArray() == 0) { - CTCfvo cfvo; - cfvo = scale.addNewCfvo(); - cfvo.setType(STCfvoType.Enum.forString(RangeType.MIN.name)); - cfvo = scale.addNewCfvo(); - cfvo.setType(STCfvoType.Enum.forString(RangeType.PERCENTILE.name)); - cfvo.setVal("50"); - cfvo = scale.addNewCfvo(); - cfvo.setType(STCfvoType.Enum.forString(RangeType.MAX.name)); - - for (int i=0; i<3; i++) { - scale.addNewColor(); - } - } - - // Wrap and return - return new XSSFColorScaleFormatting(scale, _sh.getWorkbook().getStylesSource().getIndexedColors()); - } - public XSSFColorScaleFormatting getColorScaleFormatting() { - if (_cfRule.isSetColorScale()) { - CTColorScale scale = _cfRule.getColorScale(); - return new XSSFColorScaleFormatting(scale, _sh.getWorkbook().getStylesSource().getIndexedColors()); - } else { - return null; - } - } - - /** - * Return the number format from the dxf style record if present, null if not - * @see org.apache.poi.ss.usermodel.ConditionalFormattingRule#getNumberFormat() - */ - public ExcelNumberFormat getNumberFormat() { - CTDxf dxf = getDxf(false); - if(dxf == null || !dxf.isSetNumFmt()) return null; - - CTNumFmt numFmt = dxf.getNumFmt(); - return new ExcelNumberFormat((int) numFmt.getNumFmtId(), numFmt.getFormatCode()); - } - - /** - * Type of conditional formatting rule. - */ - @Override - public ConditionType getConditionType() { - return typeLookup.get(_cfRule.getType()); - } - - /** - * Will return null if {@link #getConditionType()} != {@link ConditionType#FILTER} - * @see org.apache.poi.ss.usermodel.ConditionalFormattingRule#getConditionFilterType() - */ - public ConditionFilterType getConditionFilterType() { - return filterTypeLookup.get(_cfRule.getType()); - } - - public ConditionFilterData getFilterConfiguration() { - return new XSSFConditionFilterData(_cfRule); - } - - /** - * The comparison function used when the type of conditional formatting is set to - * {@link ConditionType#CELL_VALUE_IS} - * <p> - * MUST be a constant from {@link org.apache.poi.ss.usermodel.ComparisonOperator} - * </p> - * - * @return the conditional format operator - */ - @Override - public byte getComparisonOperation(){ - STConditionalFormattingOperator.Enum op = _cfRule.getOperator(); - if(op == null) return ComparisonOperator.NO_COMPARISON; - - switch(op.intValue()){ - case STConditionalFormattingOperator.INT_LESS_THAN: return ComparisonOperator.LT; - case STConditionalFormattingOperator.INT_LESS_THAN_OR_EQUAL: return ComparisonOperator.LE; - case STConditionalFormattingOperator.INT_GREATER_THAN: return ComparisonOperator.GT; - case STConditionalFormattingOperator.INT_GREATER_THAN_OR_EQUAL: return ComparisonOperator.GE; - case STConditionalFormattingOperator.INT_EQUAL: return ComparisonOperator.EQUAL; - case STConditionalFormattingOperator.INT_NOT_EQUAL: return ComparisonOperator.NOT_EQUAL; - case STConditionalFormattingOperator.INT_BETWEEN: return ComparisonOperator.BETWEEN; - case STConditionalFormattingOperator.INT_NOT_BETWEEN: return ComparisonOperator.NOT_BETWEEN; - } - return ComparisonOperator.NO_COMPARISON; - } - - /** - * The formula used to evaluate the first operand for the conditional formatting rule. - * <p> - * If the condition type is {@link ConditionType#CELL_VALUE_IS}, - * this field is the first operand of the comparison. - * If type is {@link ConditionType#FORMULA}, this formula is used - * to determine if the conditional formatting is applied. - * </p> - * <p> - * If comparison type is {@link ConditionType#FORMULA} the formula MUST be a Boolean function - * </p> - * - * @return the first formula - */ - public String getFormula1(){ - return _cfRule.sizeOfFormulaArray() > 0 ? _cfRule.getFormulaArray(0) : null; - } - - /** - * The formula used to evaluate the second operand of the comparison when - * comparison type is {@link ConditionType#CELL_VALUE_IS} and operator - * is either {@link org.apache.poi.ss.usermodel.ComparisonOperator#BETWEEN} or {@link org.apache.poi.ss.usermodel.ComparisonOperator#NOT_BETWEEN} - * - * @return the second formula - */ - public String getFormula2(){ - return _cfRule.sizeOfFormulaArray() == 2 ? _cfRule.getFormulaArray(1) : null; - } - - public String getText() { - return _cfRule.getText(); - } - - /** - * Conditional format rules don't define stripes, so always 0 - * @see org.apache.poi.ss.usermodel.DifferentialStyleProvider#getStripeSize() - */ - public int getStripeSize() { - return 0; - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java deleted file mode 100644 index f868f14a2b..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * ==================================================================== - * 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.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfvoType; - -/** - * High level representation for Icon / Multi-State / Databar / - * Colour Scale change thresholds - */ -public class XSSFConditionalFormattingThreshold implements org.apache.poi.ss.usermodel.ConditionalFormattingThreshold { - private CTCfvo cfvo; - - protected XSSFConditionalFormattingThreshold(CTCfvo cfvo) { - this.cfvo = cfvo; - } - - protected CTCfvo getCTCfvo() { - return cfvo; - } - - public RangeType getRangeType() { - return RangeType.byName(cfvo.getType().toString()); - } - public void setRangeType(RangeType type) { - STCfvoType.Enum xtype = STCfvoType.Enum.forString(type.name); - cfvo.setType(xtype); - } - - public String getFormula() { - if (cfvo.getType() == STCfvoType.FORMULA) { - return cfvo.getVal(); - } - return null; - } - public void setFormula(String formula) { - cfvo.setVal(formula); - } - - public Double getValue() { - if (cfvo.getType() == STCfvoType.FORMULA || - cfvo.getType() == STCfvoType.MIN || - cfvo.getType() == STCfvoType.MAX) { - return null; - } - if (cfvo.isSetVal()) { - return Double.parseDouble(cfvo.getVal()); - } else { - return null; - } - } - public void setValue(Double value) { - if (value == null) { - cfvo.unsetVal(); - } else { - cfvo.setVal(value.toString()); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java deleted file mode 100644 index 78d4e402e4..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java +++ /dev/null @@ -1,141 +0,0 @@ -/* ==================================================================== - 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.openxmlformats.schemas.drawingml.x2006.main.CTFontReference; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; -import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.main.STFontCollectionIndex; -import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTConnector; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTConnectorNonVisual; -import org.apache.poi.util.Internal; - -/** - * A connection shape drawing element. A connection shape is a line, etc. - * that connects two other shapes in this drawing. - * - * @author Yegor Kozlov - */ -public final class XSSFConnector extends XSSFShape { - - private static CTConnector prototype; - - private CTConnector ctShape; - - /** - * Construct a new XSSFConnector object. - * - * @param drawing the XSSFDrawing that owns this shape - * @param ctShape the shape bean that holds all the shape properties - */ - protected XSSFConnector(XSSFDrawing drawing, CTConnector ctShape) { - this.drawing = drawing; - this.ctShape = ctShape; - } - - /** - * Initialize default structure of a new auto-shape - * - */ - protected static CTConnector prototype() { - if(prototype == null) { - CTConnector shape = CTConnector.Factory.newInstance(); - CTConnectorNonVisual nv = shape.addNewNvCxnSpPr(); - CTNonVisualDrawingProps nvp = nv.addNewCNvPr(); - nvp.setId(1); - nvp.setName("Shape 1"); - nv.addNewCNvCxnSpPr(); - - CTShapeProperties sp = shape.addNewSpPr(); - CTTransform2D t2d = sp.addNewXfrm(); - CTPositiveSize2D p1 = t2d.addNewExt(); - p1.setCx(0); - p1.setCy(0); - CTPoint2D p2 = t2d.addNewOff(); - p2.setX(0); - p2.setY(0); - - CTPresetGeometry2D geom = sp.addNewPrstGeom(); - geom.setPrst(STShapeType.LINE); - geom.addNewAvLst(); - - CTShapeStyle style = shape.addNewStyle(); - CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr(); - scheme.setVal(STSchemeColorVal.ACCENT_1); - style.getLnRef().setIdx(1); - - CTStyleMatrixReference fillref = style.addNewFillRef(); - fillref.setIdx(0); - fillref.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); - - CTStyleMatrixReference effectRef = style.addNewEffectRef(); - effectRef.setIdx(0); - effectRef.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); - - CTFontReference fontRef = style.addNewFontRef(); - fontRef.setIdx(STFontCollectionIndex.MINOR); - fontRef.addNewSchemeClr().setVal(STSchemeColorVal.TX_1); - - prototype = shape; - } - return prototype; - } - - @Internal - public CTConnector getCTConnector(){ - return ctShape; - } - - /** - * Gets the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. - * - * @return the shape type - * @see org.apache.poi.ss.usermodel.ShapeTypes - */ - public int getShapeType() { - return ctShape.getSpPr().getPrstGeom().getPrst().intValue(); - } - - /** - * Sets the shape types. - * - * @param type the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. - * @see org.apache.poi.ss.usermodel.ShapeTypes - */ - public void setShapeType(int type) { - ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type)); - } - - protected CTShapeProperties getShapeProperties(){ - return ctShape.getSpPr(); - } - - @Override - public String getShapeName() { - return ctShape.getNvCxnSpPr().getCNvPr().getName(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java deleted file mode 100644 index fedbc8d3dd..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java +++ /dev/null @@ -1,107 +0,0 @@ -/* ==================================================================== - 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.common.usermodel.HyperlinkType; -import org.apache.poi.ss.usermodel.CreationHelper; -import org.apache.poi.ss.usermodel.Hyperlink; -import org.apache.poi.ss.util.AreaReference; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.util.Internal; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; - -public class XSSFCreationHelper implements CreationHelper { - private final XSSFWorkbook workbook; - - /** - * Should only be called by {@link XSSFWorkbook#getCreationHelper()} - * - * @param wb the workbook to create objects for - */ - @Internal - public XSSFCreationHelper(XSSFWorkbook wb) { - workbook = wb; - } - - /** - * Creates a new XSSFRichTextString for you. - */ - @Override - public XSSFRichTextString createRichTextString(String text) { - XSSFRichTextString rt = new XSSFRichTextString(text); - rt.setStylesTableReference(workbook.getStylesSource()); - return rt; - } - - @Override - public XSSFDataFormat createDataFormat() { - return workbook.createDataFormat(); - } - - @Override - public XSSFColor createExtendedColor() { - return XSSFColor.from(CTColor.Factory.newInstance(), workbook.getStylesSource().getIndexedColors()); - } - - /** - * Create a new XSSFHyperlink. - * - * @param type - the type of hyperlink to create, see {@link Hyperlink} - */ - @Override - public XSSFHyperlink createHyperlink(HyperlinkType type) { - return new XSSFHyperlink(type); - } - - /** - * Creates a XSSFFormulaEvaluator, the object that evaluates formula cells. - * - * @return a XSSFFormulaEvaluator instance - */ - @Override - public XSSFFormulaEvaluator createFormulaEvaluator() { - return new XSSFFormulaEvaluator(workbook); - } - - /** - * Creates a XSSFClientAnchor. Use this object to position drawing object in - * a sheet - * - * @return a XSSFClientAnchor instance - * @see org.apache.poi.ss.usermodel.Drawing - */ - @Override - public XSSFClientAnchor createClientAnchor() { - return new XSSFClientAnchor(); - } - - /** - * {@inheritDoc} - */ - @Override - public AreaReference createAreaReference(String reference) { - return new AreaReference(reference, workbook.getSpreadsheetVersion()); - } - - /** - * {@inheritDoc} - */ - @Override - public AreaReference createAreaReference(CellReference topLeft, CellReference bottomRight) { - return new AreaReference(topLeft, bottomRight, workbook.getSpreadsheetVersion()); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java deleted file mode 100644 index fecd4f0221..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * ==================================================================== - * 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.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.DataBarFormatting; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataBar; - -/** - * High level representation for DataBar / Data Bar Formatting - * component of Conditional Formatting settings - */ -public class XSSFDataBarFormatting implements DataBarFormatting { - IndexedColorMap _colorMap; - CTDataBar _databar; - - /*package*/ XSSFDataBarFormatting(CTDataBar databar, IndexedColorMap colorMap){ - _databar = databar; - _colorMap = colorMap; - } - - public boolean isIconOnly() { - if (_databar.isSetShowValue()) - return !_databar.getShowValue(); - return false; - } - public void setIconOnly(boolean only) { - _databar.setShowValue(!only); - } - - public boolean isLeftToRight() { - return true; - } - public void setLeftToRight(boolean ltr) { - // TODO How does XSSF encode this? - } - - public int getWidthMin() { - return 0; - } - public void setWidthMin(int width) { - // TODO How does XSSF encode this? - } - - public int getWidthMax() { - return 100; - } - public void setWidthMax(int width) { - // TODO How does XSSF encode this? - } - - public XSSFColor getColor() { - return XSSFColor.from(_databar.getColor(), _colorMap); - } - public void setColor(Color color) { - _databar.setColor( ((XSSFColor)color).getCTColor() ); - } - - public XSSFConditionalFormattingThreshold getMinThreshold() { - return new XSSFConditionalFormattingThreshold(_databar.getCfvoArray(0)); - } - public XSSFConditionalFormattingThreshold getMaxThreshold() { - return new XSSFConditionalFormattingThreshold(_databar.getCfvoArray(1)); - } - - public XSSFConditionalFormattingThreshold createThreshold() { - return new XSSFConditionalFormattingThreshold(_databar.addNewCfvo()); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataFormat.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataFormat.java deleted file mode 100644 index 8c867ab566..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataFormat.java +++ /dev/null @@ -1,86 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.BuiltinFormats; -import org.apache.poi.ss.usermodel.DataFormat; -import org.apache.poi.xssf.model.StylesTable; - -/** - * Handles data formats for XSSF. - * - * Per Microsoft Excel 2007+ format limitations: - * Workbooks support between 200 and 250 "number formats" - * (POI calls them "data formats") So short or even byte - * would be acceptable data types to use for referring to - * data format indices. - * https://support.office.com/en-us/article/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3 - * - */ -public class XSSFDataFormat implements DataFormat { - private final StylesTable stylesSource; - - protected XSSFDataFormat(StylesTable stylesSource) { - this.stylesSource = stylesSource; - } - - /** - * Get the format index that matches the given format - * string, creating a new format entry if required. - * Aliases text to the proper format as required. - * - * @param format string matching a built-in format - * @return index of format. - */ - @Override - public short getFormat(String format) { - int idx = BuiltinFormats.getBuiltinFormat(format); - if(idx == -1) idx = stylesSource.putNumberFormat(format); - return (short)idx; - } - - /** - * get the format string that matches the given format index - * @param index of a format - * @return string represented at index of format or <code>null</code> if there is not a format at that index - */ - @Override - public String getFormat(short index) { - // Indices used for built-in formats may be overridden with - // custom formats, such as locale-specific currency. - // See org.apache.poi.xssf.usermodel.TestXSSFDataFormat#test49928() - // or bug 49928 for an example. - // This is why we need to check stylesSource first and only fall back to - // BuiltinFormats if the format hasn't been overridden. - String fmt = stylesSource.getNumberFormatAt(index); - if(fmt == null) fmt = BuiltinFormats.getBuiltinFormat(index); - return fmt; - } - - /** - * Add a number format with a specific ID into the number format style table. - * If a format with the same ID already exists, overwrite the format code - * with <code>fmt</code> - * This may be used to override built-in number formats. - * - * @param index the number format ID - * @param format the number format code - */ - public void putFormat(short index, String format) { - stylesSource.putNumberFormat(index, format); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java deleted file mode 100644 index ca451a5d33..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidation.java +++ /dev/null @@ -1,294 +0,0 @@ -/* ==================================================================== - 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 java.util.HashMap; -import java.util.Map; - -import org.apache.commons.collections4.MapUtils; -import org.apache.poi.ss.usermodel.DataValidation; -import org.apache.poi.ss.usermodel.DataValidationConstraint; -import org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidation; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationErrorStyle; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationOperator; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationOperator.Enum; - -/** - * @author <a href="rjankiraman@emptoris.com">Radhakrishnan J</a> - * - */ -public class XSSFDataValidation implements DataValidation { - private static final int MAX_TEXT_LENGTH = 255; - - private CTDataValidation ctDataValidation; - private XSSFDataValidationConstraint validationConstraint; - private CellRangeAddressList regions; - - static Map<Integer, STDataValidationOperator.Enum> operatorTypeMappings = new HashMap<>(); - static Map<STDataValidationOperator.Enum, Integer> operatorTypeReverseMappings = new HashMap<>(); - static Map<Integer, STDataValidationType.Enum> validationTypeMappings = new HashMap<>(); - static Map<STDataValidationType.Enum, Integer> validationTypeReverseMappings = new HashMap<>(); - static Map<Integer, STDataValidationErrorStyle.Enum> errorStyleMappings = new HashMap<>(); - static Map<STDataValidationErrorStyle.Enum, Integer> reverseErrorStyleMappings; - - static { - errorStyleMappings.put(DataValidation.ErrorStyle.INFO, STDataValidationErrorStyle.INFORMATION); - errorStyleMappings.put(DataValidation.ErrorStyle.STOP, STDataValidationErrorStyle.STOP); - errorStyleMappings.put(DataValidation.ErrorStyle.WARNING, STDataValidationErrorStyle.WARNING); - - reverseErrorStyleMappings = MapUtils.invertMap(errorStyleMappings); - - operatorTypeMappings.put(DataValidationConstraint.OperatorType.BETWEEN,STDataValidationOperator.BETWEEN); - operatorTypeMappings.put(DataValidationConstraint.OperatorType.NOT_BETWEEN,STDataValidationOperator.NOT_BETWEEN); - operatorTypeMappings.put(DataValidationConstraint.OperatorType.EQUAL,STDataValidationOperator.EQUAL); - operatorTypeMappings.put(DataValidationConstraint.OperatorType.NOT_EQUAL,STDataValidationOperator.NOT_EQUAL); - operatorTypeMappings.put(DataValidationConstraint.OperatorType.GREATER_THAN,STDataValidationOperator.GREATER_THAN); - operatorTypeMappings.put(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL,STDataValidationOperator.GREATER_THAN_OR_EQUAL); - operatorTypeMappings.put(DataValidationConstraint.OperatorType.LESS_THAN,STDataValidationOperator.LESS_THAN); - operatorTypeMappings.put(DataValidationConstraint.OperatorType.LESS_OR_EQUAL,STDataValidationOperator.LESS_THAN_OR_EQUAL); - - for( Map.Entry<Integer,STDataValidationOperator.Enum> entry : operatorTypeMappings.entrySet() ) { - operatorTypeReverseMappings.put(entry.getValue(),entry.getKey()); - } - - validationTypeMappings.put(DataValidationConstraint.ValidationType.FORMULA,STDataValidationType.CUSTOM); - validationTypeMappings.put(DataValidationConstraint.ValidationType.DATE,STDataValidationType.DATE); - validationTypeMappings.put(DataValidationConstraint.ValidationType.DECIMAL,STDataValidationType.DECIMAL); - validationTypeMappings.put(DataValidationConstraint.ValidationType.LIST,STDataValidationType.LIST); - validationTypeMappings.put(DataValidationConstraint.ValidationType.ANY,STDataValidationType.NONE); - validationTypeMappings.put(DataValidationConstraint.ValidationType.TEXT_LENGTH,STDataValidationType.TEXT_LENGTH); - validationTypeMappings.put(DataValidationConstraint.ValidationType.TIME,STDataValidationType.TIME); - validationTypeMappings.put(DataValidationConstraint.ValidationType.INTEGER,STDataValidationType.WHOLE); - - for( Map.Entry<Integer,STDataValidationType.Enum> entry : validationTypeMappings.entrySet() ) { - validationTypeReverseMappings.put(entry.getValue(),entry.getKey()); - } - } - - XSSFDataValidation(CellRangeAddressList regions,CTDataValidation ctDataValidation) { - this(getConstraint(ctDataValidation), regions, ctDataValidation); - } - - public XSSFDataValidation(XSSFDataValidationConstraint constraint,CellRangeAddressList regions,CTDataValidation ctDataValidation) { - super(); - this.validationConstraint = constraint; - this.ctDataValidation = ctDataValidation; - this.regions = regions; - } - - CTDataValidation getCtDataValidation() { - return ctDataValidation; - } - - - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#createErrorBox(java.lang.String, java.lang.String) - */ - public void createErrorBox(String title, String text) { - // the spec does not specify a length-limit, however Excel reports files as "corrupt" if they exceed 255 bytes for these texts... - if(title != null && title.length() > MAX_TEXT_LENGTH) { - throw new IllegalStateException("Error-title cannot be longer than 32 characters, but had: " + title); - } - if(text != null && text.length() > MAX_TEXT_LENGTH) { - throw new IllegalStateException("Error-text cannot be longer than 255 characters, but had: " + text); - } - ctDataValidation.setErrorTitle(encodeUtf(title)); - ctDataValidation.setError(encodeUtf(text)); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#createPromptBox(java.lang.String, java.lang.String) - */ - public void createPromptBox(String title, String text) { - // the spec does not specify a length-limit, however Excel reports files as "corrupt" if they exceed 255 bytes for these texts... - if(title != null && title.length() > MAX_TEXT_LENGTH) { - throw new IllegalStateException("Error-title cannot be longer than 32 characters, but had: " + title); - } - if(text != null && text.length() > MAX_TEXT_LENGTH) { - throw new IllegalStateException("Error-text cannot be longer than 255 characters, but had: " + text); - } - ctDataValidation.setPromptTitle(encodeUtf(title)); - ctDataValidation.setPrompt(encodeUtf(text)); - } - - /** - * For all characters which cannot be represented in XML as defined by the XML 1.0 specification, - * the characters are escaped using the Unicode numerical character representation escape character - * format _xHHHH_, where H represents a hexadecimal character in the character's value. - * <p> - * Example: The Unicode character 0D is invalid in an XML 1.0 document, - * so it shall be escaped as <code>_x000D_</code>. - * </p> - * See section 3.18.9 in the OOXML spec. - * - * @param text the string to encode - * @return the encoded string - */ - private String encodeUtf(String text) { - if(text == null) { - return null; - } - - StringBuilder builder = new StringBuilder(); - for(char c : text.toCharArray()) { - // for now only encode characters below 32, we can add more here if needed - if(c < 32) { - builder.append("_x").append(c < 16 ? "000" : "00").append(Integer.toHexString(c)).append("_"); - } else { - builder.append(c); - } - } - - return builder.toString(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getEmptyCellAllowed() - */ - public boolean getEmptyCellAllowed() { - return ctDataValidation.getAllowBlank(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getErrorBoxText() - */ - public String getErrorBoxText() { - return ctDataValidation.getError(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getErrorBoxTitle() - */ - public String getErrorBoxTitle() { - return ctDataValidation.getErrorTitle(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getErrorStyle() - */ - public int getErrorStyle() { - return reverseErrorStyleMappings.get(ctDataValidation.getErrorStyle()); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getPromptBoxText() - */ - public String getPromptBoxText() { - return ctDataValidation.getPrompt(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getPromptBoxTitle() - */ - public String getPromptBoxTitle() { - return ctDataValidation.getPromptTitle(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getShowErrorBox() - */ - public boolean getShowErrorBox() { - return ctDataValidation.getShowErrorMessage(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getShowPromptBox() - */ - public boolean getShowPromptBox() { - return ctDataValidation.getShowInputMessage(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getSuppressDropDownArrow() - */ - public boolean getSuppressDropDownArrow() { - return !ctDataValidation.getShowDropDown(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#getValidationConstraint() - */ - public DataValidationConstraint getValidationConstraint() { - return validationConstraint; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#setEmptyCellAllowed(boolean) - */ - public void setEmptyCellAllowed(boolean allowed) { - ctDataValidation.setAllowBlank(allowed); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#setErrorStyle(int) - */ - public void setErrorStyle(int errorStyle) { - ctDataValidation.setErrorStyle(errorStyleMappings.get(errorStyle)); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#setShowErrorBox(boolean) - */ - public void setShowErrorBox(boolean show) { - ctDataValidation.setShowErrorMessage(show); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#setShowPromptBox(boolean) - */ - public void setShowPromptBox(boolean show) { - ctDataValidation.setShowInputMessage(show); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidation#setSuppressDropDownArrow(boolean) - */ - public void setSuppressDropDownArrow(boolean suppress) { - if (validationConstraint.getValidationType()==ValidationType.LIST) { - ctDataValidation.setShowDropDown(!suppress); - } - } - - public CellRangeAddressList getRegions() { - return regions; - } - - public String prettyPrint() { - StringBuilder builder = new StringBuilder(); - for(CellRangeAddress address : regions.getCellRangeAddresses()) { - builder.append(address.formatAsString()); - } - builder.append(" => "); - builder.append(this.validationConstraint.prettyPrint()); - return builder.toString(); - } - - private static XSSFDataValidationConstraint getConstraint(CTDataValidation ctDataValidation) { - String formula1 = ctDataValidation.getFormula1(); - String formula2 = ctDataValidation.getFormula2(); - Enum operator = ctDataValidation.getOperator(); - org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType.Enum type = ctDataValidation.getType(); - Integer validationType = XSSFDataValidation.validationTypeReverseMappings.get(type); - Integer operatorType = XSSFDataValidation.operatorTypeReverseMappings.get(operator); - return new XSSFDataValidationConstraint(validationType,operatorType, formula1,formula2); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidationConstraint.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidationConstraint.java deleted file mode 100644 index b62a38e0a5..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidationConstraint.java +++ /dev/null @@ -1,251 +0,0 @@ -/* ==================================================================== - 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 java.util.Arrays; -import java.util.regex.Pattern; - -import org.apache.poi.ss.usermodel.DataValidationConstraint; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationOperator.Enum; - -/** - * @author <a href="rjankiraman@emptoris.com">Radhakrishnan J</a> - * - */ -public class XSSFDataValidationConstraint implements DataValidationConstraint { - /** - * Excel validation constraints with static lists are delimited with optional whitespace and the Windows List Separator, - * which is typically comma, but can be changed by users. POI will just assume comma. - * In addition, Excel validation with static lists has a maximum size of 255 characters, including separators and excluding quotes. - */ - private static final String LIST_SEPARATOR = ","; - private static final Pattern LIST_SPLIT_REGEX = Pattern.compile("\\s*" + LIST_SEPARATOR + "\\s*"); - private static final String QUOTE = "\""; - private static final int MAX_EXPLICIT_LIST_LENGTH = 257; - - private String formula1; - private String formula2; - private int validationType = -1; - private int operator = -1; - private String[] explicitListOfValues; - - /** - * list literal constructor - */ - public XSSFDataValidationConstraint(String[] explicitListOfValues) { - if( explicitListOfValues==null || explicitListOfValues.length==0) { - throw new IllegalArgumentException("List validation with explicit values must specify at least one value"); - } - this.validationType = ValidationType.LIST; - setExplicitListValues(explicitListOfValues); - - validate(); - } - - public XSSFDataValidationConstraint(int validationType, String formula1) { - super(); - setFormula1(formula1); - this.validationType = validationType; - validate(); - } - - - - public XSSFDataValidationConstraint(int validationType, int operator, String formula1) { - super(); - setFormula1(formula1); - this.validationType = validationType; - this.operator = operator; - validate(); - } - - /** - * This is the constructor called using the OOXML raw data. Excel overloads formula1 to also encode explicit value lists, - * so this constructor has to check for and parse that syntax. - * @param validationType - * @param operator - * @param formula1 Overloaded: formula1 or list of explicit values - * @param formula2 (formula1 is a list of explicit values, this is ignored: use <code>null</code>) - */ - public XSSFDataValidationConstraint(int validationType, int operator, String formula1, String formula2) { - super(); - //removes leading equals sign if present - setFormula1(formula1); - setFormula2(formula2); - this.validationType = validationType; - this.operator = operator; - - validate(); - - //FIXME: Need to confirm if this is not a formula. - // empirical testing shows Excel saves explicit lists surrounded by double quotes, - // range formula expressions can't start with quotes (I think - anyone have a creative counter example?) - if ( ValidationType.LIST == validationType - && this.formula1 != null - && isQuoted(this.formula1) ) { - explicitListOfValues = LIST_SPLIT_REGEX.split(unquote(this.formula1)); - } - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#getExplicitListValues() - */ - public String[] getExplicitListValues() { - return explicitListOfValues; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#getFormula1() - */ - public String getFormula1() { - return formula1; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#getFormula2() - */ - public String getFormula2() { - return formula2; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#getOperator() - */ - public int getOperator() { - return operator; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#getValidationType() - */ - public int getValidationType() { - return validationType; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#setExplicitListValues(java.lang.String[]) - */ - public void setExplicitListValues(String[] explicitListValues) { - this.explicitListOfValues = explicitListValues; - - // for OOXML we need to set formula1 to the quoted csv list of values (doesn't appear documented, but that's where Excel puts its lists) - // further, Excel has no escaping for commas in explicit lists, so we don't need to worry about that. - if ( explicitListOfValues!=null && explicitListOfValues.length > 0 ) { - StringBuilder builder = new StringBuilder(QUOTE); - for (int i = 0; i < explicitListValues.length; i++) { - String string = explicitListValues[i]; - if (builder.length() > 1) { - builder.append(LIST_SEPARATOR); - } - builder.append(string); - } - builder.append(QUOTE); - setFormula1(builder.toString()); - } - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#setFormula1(java.lang.String) - */ - public void setFormula1(String formula1) { - this.formula1 = removeLeadingEquals(formula1); - } - - protected static String removeLeadingEquals(String formula1) { - return isFormulaEmpty(formula1) ? formula1 : formula1.charAt(0)=='=' ? formula1.substring(1) : formula1; - } - private static boolean isQuoted(String s) { - return s.startsWith(QUOTE) && s.endsWith(QUOTE); - } - private static String unquote(String s) { - // removes leading and trailing quotes from a quoted string - if (isQuoted(s)) { - return s.substring(1, s.length()-1); - } - return s; - } - protected static boolean isFormulaEmpty(String formula1) { - return formula1 == null || formula1.trim().length()==0; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#setFormula2(java.lang.String) - */ - public void setFormula2(String formula2) { - this.formula2 = removeLeadingEquals(formula2); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationConstraint#setOperator(int) - */ - public void setOperator(int operator) { - this.operator = operator; - } - - public void validate() { - if (validationType==ValidationType.ANY) { - return; - } - - if (validationType==ValidationType.LIST ) { - if (isFormulaEmpty(formula1)) { - throw new IllegalArgumentException("A valid formula or a list of values must be specified for list validation."); - } - if(formula1.length() > MAX_EXPLICIT_LIST_LENGTH) { - throw new IllegalArgumentException("A valid formula or a list of values must be less than or equal to 255 characters (including separators)."); - } - } else { - if( isFormulaEmpty(formula1) ) { - throw new IllegalArgumentException("Formula is not specified. Formula is required for all validation types except explicit list validation."); - } - - if( validationType!= ValidationType.FORMULA ) { - if (operator==-1) { - throw new IllegalArgumentException("This validation type requires an operator to be specified."); - } else if (( operator==OperatorType.BETWEEN || operator==OperatorType.NOT_BETWEEN) && isFormulaEmpty(formula2)) { - throw new IllegalArgumentException("Between and not between comparisons require two formulae to be specified."); - } - } - } - } - - - public String prettyPrint() { - StringBuilder builder = new StringBuilder(); - STDataValidationType.Enum vt = XSSFDataValidation.validationTypeMappings.get(validationType); - Enum ot = XSSFDataValidation.operatorTypeMappings.get(operator); - builder.append(vt); - builder.append(' '); - if (validationType!=ValidationType.ANY) { - if (validationType != ValidationType.LIST - && validationType != ValidationType.FORMULA) { - builder.append(LIST_SEPARATOR).append(ot).append(", "); - } - final String NOQUOTE = ""; - if (validationType == ValidationType.LIST && explicitListOfValues != null) { - builder.append(NOQUOTE).append(Arrays.asList(explicitListOfValues)).append(NOQUOTE).append(' '); - } else { - builder.append(NOQUOTE).append(formula1).append(NOQUOTE).append(' '); - } - if (formula2 != null) { - builder.append(NOQUOTE).append(formula2).append(NOQUOTE).append(' '); - } - } - return builder.toString(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidationHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidationHelper.java deleted file mode 100644 index 9e62aa07e7..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataValidationHelper.java +++ /dev/null @@ -1,177 +0,0 @@ -/* ==================================================================== - 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 java.util.ArrayList; -import java.util.List; - -import org.apache.poi.ss.usermodel.DataValidation; -import org.apache.poi.ss.usermodel.DataValidationConstraint; -import org.apache.poi.ss.usermodel.DataValidationHelper; -import org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidation; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationErrorStyle; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationOperator; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataValidationType; - -/** - * @author <a href="rjankiraman@emptoris.com">Radhakrishnan J</a> - * - */ -public class XSSFDataValidationHelper implements DataValidationHelper { - // Findbugs: URF_UNREAD_FIELD. Do not delete without understanding how this class works. - //private XSSFSheet xssfSheet; - - - public XSSFDataValidationHelper(XSSFSheet xssfSheet) { - super(); - // Findbugs: URF_UNREAD_FIELD. Do not delete without understanding how this class works. - //this.xssfSheet = xssfSheet; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationHelper#createDateConstraint(int, java.lang.String, java.lang.String, java.lang.String) - */ - public DataValidationConstraint createDateConstraint(int operatorType, String formula1, String formula2, String dateFormat) { - return new XSSFDataValidationConstraint(ValidationType.DATE, operatorType,formula1, formula2); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationHelper#createDecimalConstraint(int, java.lang.String, java.lang.String) - */ - public DataValidationConstraint createDecimalConstraint(int operatorType, String formula1, String formula2) { - return new XSSFDataValidationConstraint(ValidationType.DECIMAL, operatorType,formula1, formula2); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationHelper#createExplicitListConstraint(java.lang.String[]) - */ - public DataValidationConstraint createExplicitListConstraint(String[] listOfValues) { - return new XSSFDataValidationConstraint(listOfValues); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationHelper#createFormulaListConstraint(java.lang.String) - */ - public DataValidationConstraint createFormulaListConstraint(String listFormula) { - return new XSSFDataValidationConstraint(ValidationType.LIST, listFormula); - } - - - - public DataValidationConstraint createNumericConstraint(int validationType, int operatorType, String formula1, String formula2) { - if( validationType==ValidationType.INTEGER) { - return createIntegerConstraint(operatorType, formula1, formula2); - } else if ( validationType==ValidationType.DECIMAL) { - return createDecimalConstraint(operatorType, formula1, formula2); - } else if ( validationType==ValidationType.TEXT_LENGTH) { - return createTextLengthConstraint(operatorType, formula1, formula2); - } - return null; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationHelper#createIntegerConstraint(int, java.lang.String, java.lang.String) - */ - public DataValidationConstraint createIntegerConstraint(int operatorType, String formula1, String formula2) { - return new XSSFDataValidationConstraint(ValidationType.INTEGER, operatorType,formula1,formula2); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationHelper#createTextLengthConstraint(int, java.lang.String, java.lang.String) - */ - public DataValidationConstraint createTextLengthConstraint(int operatorType, String formula1, String formula2) { - return new XSSFDataValidationConstraint(ValidationType.TEXT_LENGTH, operatorType,formula1,formula2); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationHelper#createTimeConstraint(int, java.lang.String, java.lang.String, java.lang.String) - */ - public DataValidationConstraint createTimeConstraint(int operatorType, String formula1, String formula2) { - return new XSSFDataValidationConstraint(ValidationType.TIME, operatorType,formula1,formula2); - } - - public DataValidationConstraint createCustomConstraint(String formula) { - return new XSSFDataValidationConstraint(ValidationType.FORMULA, formula); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.usermodel.DataValidationHelper#createValidation(org.apache.poi.ss.usermodel.DataValidationConstraint, org.apache.poi.ss.util.CellRangeAddressList) - */ - public DataValidation createValidation(DataValidationConstraint constraint, CellRangeAddressList cellRangeAddressList) { - XSSFDataValidationConstraint dataValidationConstraint = (XSSFDataValidationConstraint)constraint; - CTDataValidation newDataValidation = CTDataValidation.Factory.newInstance(); - - int validationType = constraint.getValidationType(); - switch(validationType) { - case DataValidationConstraint.ValidationType.LIST: - newDataValidation.setType(STDataValidationType.LIST); - newDataValidation.setFormula1(constraint.getFormula1()); - break; - case DataValidationConstraint.ValidationType.ANY: - newDataValidation.setType(STDataValidationType.NONE); - break; - case DataValidationConstraint.ValidationType.TEXT_LENGTH: - newDataValidation.setType(STDataValidationType.TEXT_LENGTH); - break; - case DataValidationConstraint.ValidationType.DATE: - newDataValidation.setType(STDataValidationType.DATE); - break; - case DataValidationConstraint.ValidationType.INTEGER: - newDataValidation.setType(STDataValidationType.WHOLE); - break; - case DataValidationConstraint.ValidationType.DECIMAL: - newDataValidation.setType(STDataValidationType.DECIMAL); - break; - case DataValidationConstraint.ValidationType.TIME: - newDataValidation.setType(STDataValidationType.TIME); - break; - case DataValidationConstraint.ValidationType.FORMULA: - newDataValidation.setType(STDataValidationType.CUSTOM); - break; - default: - newDataValidation.setType(STDataValidationType.NONE); - } - - if (validationType!=ValidationType.ANY && validationType!=ValidationType.LIST) { - STDataValidationOperator.Enum op = XSSFDataValidation.operatorTypeMappings.get(constraint.getOperator()); - if(op != null) { - newDataValidation.setOperator(op); - } - if (constraint.getFormula1() != null) { - newDataValidation.setFormula1(constraint.getFormula1()); - } - if (constraint.getFormula2() != null) { - newDataValidation.setFormula2(constraint.getFormula2()); - } - } - - CellRangeAddress[] cellRangeAddresses = cellRangeAddressList.getCellRangeAddresses(); - List<String> sqref = new ArrayList<>(); - for (int i = 0; i < cellRangeAddresses.length; i++) { - CellRangeAddress cellRangeAddress = cellRangeAddresses[i]; - sqref.add(cellRangeAddress.formatAsString()); - } - newDataValidation.setSqref(sqref); - newDataValidation.setAllowBlank(true); - newDataValidation.setErrorStyle(STDataValidationErrorStyle.STOP); - - return new XSSFDataValidation(dataValidationConstraint,cellRangeAddressList,newDataValidation); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDialogsheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDialogsheet.java deleted file mode 100644 index bb81b5ff50..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDialogsheet.java +++ /dev/null @@ -1,108 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.Sheet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDialogsheet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageBreak; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPrintOptions; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetFormatPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetViews; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; - -//YK: TODO: this is only a prototype -@SuppressWarnings("unused") -public class XSSFDialogsheet extends XSSFSheet implements Sheet{ - protected CTDialogsheet dialogsheet; - - protected XSSFDialogsheet(XSSFSheet sheet) { - super(sheet.getPackagePart()); - this.dialogsheet = CTDialogsheet.Factory.newInstance(); - this.worksheet = CTWorksheet.Factory.newInstance(); - } - - public XSSFRow createRow(int rowNum) { - return null; - } - - protected CTHeaderFooter getDialogHeaderFooter() { - if (dialogsheet.getHeaderFooter() == null) { - dialogsheet.setHeaderFooter(CTHeaderFooter.Factory.newInstance()); - } - return dialogsheet.getHeaderFooter(); - } - - protected CTSheetPr getDialogSheetPr() { - if (dialogsheet.getSheetPr() == null) { - dialogsheet.setSheetPr(CTSheetPr.Factory.newInstance()); - } - return dialogsheet.getSheetPr(); - } - - protected CTPageBreak getDialogColumnBreaks() { - return null; - } - - protected CTSheetFormatPr getDialogSheetFormatPr() { - if (dialogsheet.getSheetFormatPr() == null) { - dialogsheet.setSheetFormatPr(CTSheetFormatPr.Factory.newInstance()); - } - return dialogsheet.getSheetFormatPr(); - } - - protected CTPageMargins getDialogPageMargins() { - if (dialogsheet.getPageMargins() == null) { - dialogsheet.setPageMargins(CTPageMargins.Factory.newInstance()); - } - return dialogsheet.getPageMargins(); - } - - protected CTPageBreak getDialogRowBreaks() { - return null; - } - - protected CTSheetViews getDialogSheetViews() { - if (dialogsheet.getSheetViews() == null) { - dialogsheet.setSheetViews(CTSheetViews.Factory.newInstance()); - dialogsheet.getSheetViews().addNewSheetView(); - } - return dialogsheet.getSheetViews(); - } - - protected CTPrintOptions getDialogPrintOptions() { - if (dialogsheet.getPrintOptions() == null) { - dialogsheet.setPrintOptions(CTPrintOptions.Factory.newInstance()); - } - return dialogsheet.getPrintOptions(); - } - - protected CTSheetProtection getDialogProtection() { - if (dialogsheet.getSheetProtection() == null) { - dialogsheet.setSheetProtection(CTSheetProtection.Factory.newInstance()); - } - return dialogsheet.getSheetProtection(); - } - - public boolean getDialog(){ - return true; - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java deleted file mode 100644 index c781ca7285..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java +++ /dev/null @@ -1,743 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.xml.namespace.QName; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.util.CellAddress; -import org.apache.poi.ss.util.ImageUtils; -import org.apache.poi.util.Internal; -import org.apache.poi.util.Units; -import org.apache.poi.xssf.model.CommentsTable; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; -import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl; -import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTAbsoluteAnchor; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTConnector; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTDrawing; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphicalObjectFrame; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGroupShape; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTOneCellAnchor; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTPicture; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.STEditAs; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOleObject; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOleObjects; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; - -/** - * Represents a SpreadsheetML drawing - */ -public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSSFShape> { - private static final Logger LOG = LogManager.getLogger(XSSFDrawing.class); - - /** - * Root element of the SpreadsheetML Drawing part - */ - private CTDrawing drawing; - private long numOfGraphicFrames; - - protected static final String NAMESPACE_A = XSSFRelation.NS_DRAWINGML; - protected static final String NAMESPACE_C = XSSFRelation.NS_CHART; - - /** - * Create a new SpreadsheetML drawing - * - * @see XSSFSheet#createDrawingPatriarch() - */ - protected XSSFDrawing() { - super(); - drawing = newDrawing(); - } - - /** - * Construct a SpreadsheetML drawing from a package part - * - * @param part - * the package part holding the drawing data, the content type - * must be - * <code>application/vnd.openxmlformats-officedocument.drawing+xml</code> - * - * @since POI 3.14-Beta1 - */ - public XSSFDrawing(PackagePart part) throws IOException, XmlException { - super(part); - XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); - // Removing root element - options.setLoadReplaceDocumentElement(null); - try (InputStream is = part.getInputStream()) { - drawing = CTDrawing.Factory.parse(is, options); - } - } - - /** - * Construct a new CTDrawing bean. By default, it's just an empty - * placeholder for drawing objects - * - * @return a new CTDrawing bean - */ - private static CTDrawing newDrawing() { - return CTDrawing.Factory.newInstance(); - } - - /** - * Return the underlying CTDrawing bean, the root element of the - * SpreadsheetML Drawing part. - * - * @return the underlying CTDrawing bean - */ - @Internal - public CTDrawing getCTDrawing() { - return drawing; - } - - @Override - protected void commit() throws IOException { - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - - /* - * Saved drawings must have the following namespaces set: <xdr:wsDr - * xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" - * xmlns:xdr= - * "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"> - */ - xmlOptions - .setSaveSyntheticDocumentElement(new QName(CTDrawing.type.getName().getNamespaceURI(), "wsDr", "xdr")); - - PackagePart part = getPackagePart(); - OutputStream out = part.getOutputStream(); - drawing.save(out, xmlOptions); - out.close(); - } - - @Override - public XSSFClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) { - return new XSSFClientAnchor(dx1, dy1, dx2, dy2, col1, row1, col2, row2); - } - - /** - * Constructs a textbox under the drawing. - * - * @param anchor - * the client anchor describes how this group is attached to the - * sheet. - * @return the newly created textbox. - */ - public XSSFTextBox createTextbox(XSSFClientAnchor anchor) { - long shapeId = newShapeId(); - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTShape ctShape = ctAnchor.addNewSp(); - ctShape.set(XSSFSimpleShape.prototype()); - ctShape.getNvSpPr().getCNvPr().setId(shapeId); - XSSFTextBox shape = new XSSFTextBox(this, ctShape); - shape.anchor = anchor; - return shape; - - } - - /** - * Creates a picture. - * - * @param anchor - * the client anchor describes how this picture is attached to - * the sheet. - * @param pictureIndex - * the index of the picture in the workbook collection of - * pictures, - * {@link XSSFWorkbook#getAllPictures()} - * . - * - * @return the newly created picture shape. - */ - public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) { - PackageRelationship rel = addPictureReference(pictureIndex); - - long shapeId = newShapeId(); - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTPicture ctShape = ctAnchor.addNewPic(); - ctShape.set(XSSFPicture.prototype()); - - ctShape.getNvPicPr().getCNvPr().setId(shapeId); - - XSSFPicture shape = new XSSFPicture(this, ctShape); - shape.anchor = anchor; - shape.setPictureReference(rel); - ctShape.getSpPr().setXfrm(createXfrm(anchor)); - - return shape; - } - - @Override - public XSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) { - return createPicture((XSSFClientAnchor) anchor, pictureIndex); - } - - /** - * Creates a chart. - * - * @param anchor - * the client anchor describes how this chart is attached to the - * sheet. - * @return the newly created chart - * @see XSSFDrawing#createChart(ClientAnchor) - */ - public XSSFChart createChart(XSSFClientAnchor anchor) { - RelationPart rp = createChartRelationPart(); - XSSFChart chart = rp.getDocumentPart(); - String chartRelId = rp.getRelationship().getId(); - - XSSFGraphicFrame frame = createGraphicFrame(anchor); - frame.setChart(chart, chartRelId); - frame.getCTGraphicalObjectFrame().setXfrm(createXfrm(anchor)); - - return chart; - } - - protected RelationPart createChartRelationPart() { - int chartNumber = getPackagePart().getPackage().getPartsByContentType(XSSFRelation.CHART.getContentType()) - .size() + 1; - - return createRelationship(XSSFRelation.CHART, XSSFFactory.getInstance(), chartNumber, false); - } - - /** - * Creates a chart. - * - * @param anchor - * the client anchor describes how this chart is attached to the - * sheet. - * @return the newly created chart - */ - - public XSSFChart createChart(ClientAnchor anchor) { - return createChart((XSSFClientAnchor) anchor); - } - - /** - * Imports the chart from the <code>srcChart</code> into this drawing. - * - * @param srcChart - * the source chart to be cloned into this drawing. - * @return the newly created chart. - * @since 4.0.0 - */ - public XSSFChart importChart(XSSFChart srcChart) { - CTTwoCellAnchor anchor = ((XSSFDrawing) srcChart.getParent()).getCTDrawing().getTwoCellAnchorArray(0); - CTMarker from = (CTMarker) anchor.getFrom().copy(); - CTMarker to = (CTMarker) anchor.getTo().copy(); - XSSFClientAnchor destAnchor = new XSSFClientAnchor(from, to); - destAnchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); - XSSFChart destChart = createChart(destAnchor); - destChart.getCTChartSpace().set(srcChart.getCTChartSpace().copy()); - return destChart; - } - - /** - * Add the indexed picture to this drawing relations - * - * @param pictureIndex the index of the picture in the workbook collection of pictures, - * {@link XSSFWorkbook#getAllPictures()} . - */ - protected PackageRelationship addPictureReference(int pictureIndex) { - XSSFWorkbook wb = (XSSFWorkbook) getParent().getParent(); - XSSFPictureData data = wb.getAllPictures().get(pictureIndex); - XSSFPictureData pic = new XSSFPictureData(data.getPackagePart()); - RelationPart rp = addRelation(null, XSSFRelation.IMAGES, pic); - return rp.getRelationship(); - } - - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor - * the client anchor describes how this group is attached to the - * sheet. - * @return the newly created shape. - */ - public XSSFSimpleShape createSimpleShape(XSSFClientAnchor anchor) { - long shapeId = newShapeId(); - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTShape ctShape = ctAnchor.addNewSp(); - ctShape.set(XSSFSimpleShape.prototype()); - ctShape.getNvSpPr().getCNvPr().setId(shapeId); - ctShape.getSpPr().setXfrm(createXfrm(anchor)); - XSSFSimpleShape shape = new XSSFSimpleShape(this, ctShape); - shape.anchor = anchor; - return shape; - } - - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor - * the client anchor describes how this group is attached to the - * sheet. - * @return the newly created shape. - */ - public XSSFConnector createConnector(XSSFClientAnchor anchor) { - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTConnector ctShape = ctAnchor.addNewCxnSp(); - ctShape.set(XSSFConnector.prototype()); - - XSSFConnector shape = new XSSFConnector(this, ctShape); - shape.anchor = anchor; - return shape; - } - - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor - * the client anchor describes how this group is attached to the - * sheet. - * @return the newly created shape. - */ - public XSSFShapeGroup createGroup(XSSFClientAnchor anchor) { - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTGroupShape ctGroup = ctAnchor.addNewGrpSp(); - ctGroup.set(XSSFShapeGroup.prototype()); - CTTransform2D xfrm = createXfrm(anchor); - CTGroupTransform2D grpXfrm = ctGroup.getGrpSpPr().getXfrm(); - grpXfrm.setOff(xfrm.getOff()); - grpXfrm.setExt(xfrm.getExt()); - grpXfrm.setChExt(xfrm.getExt()); - - XSSFShapeGroup shape = new XSSFShapeGroup(this, ctGroup); - shape.anchor = anchor; - return shape; - } - - /** - * Creates a comment. - * - * @param anchor - * the client anchor describes how this comment is attached to - * the sheet. - * @return the newly created comment. - */ - @Override - public XSSFComment createCellComment(ClientAnchor anchor) { - XSSFClientAnchor ca = (XSSFClientAnchor) anchor; - XSSFSheet sheet = getSheet(); - - // create comments and vmlDrawing parts if they don't exist - CommentsTable comments = sheet.getCommentsTable(true); - XSSFVMLDrawing vml = sheet.getVMLDrawing(true); - com.microsoft.schemas.vml.CTShape vmlShape = vml.newCommentShape(); - if (ca.isSet()) { - // convert offsets from emus to pixels since we get a - // DrawingML-anchor - // but create a VML Drawing - int dx1Pixels = ca.getDx1() / Units.EMU_PER_PIXEL; - int dy1Pixels = ca.getDy1() / Units.EMU_PER_PIXEL; - int dx2Pixels = ca.getDx2() / Units.EMU_PER_PIXEL; - int dy2Pixels = ca.getDy2() / Units.EMU_PER_PIXEL; - String position = ca.getCol1() + ", " + dx1Pixels + ", " + ca.getRow1() + ", " + dy1Pixels + ", " + ca - .getCol2() + ", " + dx2Pixels + ", " + ca.getRow2() + ", " + dy2Pixels; - vmlShape.getClientDataArray(0).setAnchorArray(0, position); - } - CellAddress ref = new CellAddress(ca.getRow1(), ca.getCol1()); - - if (comments.findCellComment(ref) != null) { - throw new IllegalArgumentException("Multiple cell comments in one cell are not allowed, cell: " + ref); - } - - return new XSSFComment(comments, comments.newComment(ref), vmlShape); - } - - /** - * Creates a new graphic frame. - * - * @param anchor - * the client anchor describes how this frame is attached to the - * sheet - * @return the newly created graphic frame - */ - private XSSFGraphicFrame createGraphicFrame(XSSFClientAnchor anchor) { - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTGraphicalObjectFrame ctGraphicFrame = ctAnchor.addNewGraphicFrame(); - ctGraphicFrame.set(XSSFGraphicFrame.prototype()); - ctGraphicFrame.setXfrm(createXfrm(anchor)); - - long frameId = numOfGraphicFrames++; - XSSFGraphicFrame graphicFrame = new XSSFGraphicFrame(this, ctGraphicFrame); - graphicFrame.setAnchor(anchor); - graphicFrame.setId(frameId); - graphicFrame.setName("Diagramm" + frameId); - return graphicFrame; - } - - @Override - public XSSFObjectData createObjectData(ClientAnchor anchor, int storageId, int pictureIndex) { - XSSFSheet sh = getSheet(); - PackagePart sheetPart = sh.getPackagePart(); - - /* - * The shape id of the ole object seems to be a legacy shape id. - * - * see 5.3.2.1 legacyDrawing (Legacy Drawing Object): Legacy Shape ID - * that is unique throughout the entire document. Legacy shape IDs - * should be assigned based on which portion of the document the drawing - * resides on. The assignment of these ids is broken down into clusters - * of 1024 values. The first cluster is 1-1024, the second 1025-2048 and - * so on. - * - * Ole shapes seem to start with 1025 on the first sheet ... and not - * sure, if the ids need to be reindexed when sheets are removed or more - * than 1024 shapes are on a given sheet (see #51332 for a similar - * issue) - */ - XSSFSheet sheet = getSheet(); - XSSFWorkbook wb = sheet.getWorkbook(); - int sheetIndex = wb.getSheetIndex(sheet); - long shapeId = (sheetIndex + 1L) * 1024 + newShapeId(); - - // add reference to OLE part - final XSSFRelation rel = XSSFRelation.OLEEMBEDDINGS; - PackagePartName olePN; - try { - olePN = PackagingURIHelper.createPartName(rel.getFileName(storageId)); - } catch (InvalidFormatException e) { - throw new POIXMLException(e); - } - PackageRelationship olePR = sheetPart.addRelationship(olePN, TargetMode.INTERNAL, rel.getRelation()); - - // add reference to image part - XSSFPictureData imgPD = sh.getWorkbook().getAllPictures().get(pictureIndex); - PackagePartName imgPN = imgPD.getPackagePart().getPartName(); - PackageRelationship imgSheetPR = sheetPart.addRelationship(imgPN, TargetMode.INTERNAL, - PackageRelationshipTypes.IMAGE_PART); - PackageRelationship imgDrawPR = getPackagePart().addRelationship(imgPN, TargetMode.INTERNAL, - PackageRelationshipTypes.IMAGE_PART); - - // add OLE part metadata to sheet - CTWorksheet cwb = sh.getCTWorksheet(); - CTOleObjects oo = cwb.isSetOleObjects() ? cwb.getOleObjects() : cwb.addNewOleObjects(); - - CTOleObject ole1 = oo.addNewOleObject(); - ole1.setProgId("Package"); - ole1.setShapeId(shapeId); - ole1.setId(olePR.getId()); - - XmlCursor cur1 = ole1.newCursor(); - cur1.toEndToken(); - cur1.beginElement("objectPr", XSSFRelation.NS_SPREADSHEETML); - cur1.insertAttributeWithValue("id", PackageRelationshipTypes.CORE_PROPERTIES_ECMA376_NS, imgSheetPR.getId()); - cur1.insertAttributeWithValue("defaultSize", "0"); - cur1.beginElement("anchor", XSSFRelation.NS_SPREADSHEETML); - cur1.insertAttributeWithValue("moveWithCells", "1"); - - CTTwoCellAnchor ctAnchor = createTwoCellAnchor((XSSFClientAnchor) anchor); - - XmlCursor cur2 = ctAnchor.newCursor(); - cur2.copyXmlContents(cur1); - cur2.dispose(); - - cur1.toParent(); - cur1.toFirstChild(); - cur1.setName(new QName(XSSFRelation.NS_SPREADSHEETML, "from")); - cur1.toNextSibling(); - cur1.setName(new QName(XSSFRelation.NS_SPREADSHEETML, "to")); - - cur1.dispose(); - - // add a new shape and link OLE & image part - CTShape ctShape = ctAnchor.addNewSp(); - ctShape.set(XSSFObjectData.prototype()); - ctShape.getSpPr().setXfrm(createXfrm((XSSFClientAnchor) anchor)); - - // workaround for not having the vmlDrawing filled - CTBlipFillProperties blipFill = ctShape.getSpPr().addNewBlipFill(); - blipFill.addNewBlip().setEmbed(imgDrawPR.getId()); - blipFill.addNewStretch().addNewFillRect(); - - CTNonVisualDrawingProps cNvPr = ctShape.getNvSpPr().getCNvPr(); - cNvPr.setId(shapeId); - cNvPr.setName("Object " + shapeId); - - XmlCursor extCur = cNvPr.getExtLst().getExtArray(0).newCursor(); - extCur.toFirstChild(); - extCur.setAttributeText(new QName("spid"), "_x0000_s" + shapeId); - extCur.dispose(); - - XSSFObjectData shape = new XSSFObjectData(this, ctShape); - shape.anchor = (XSSFClientAnchor) anchor; - - return shape; - } - - /** - * Returns all charts in this drawing. - */ - public List<XSSFChart> getCharts() { - List<XSSFChart> charts = new ArrayList<>(); - for (POIXMLDocumentPart part : getRelations()) { - if (part instanceof XSSFChart) { - charts.add((XSSFChart) part); - } - } - return charts; - } - - /** - * Create and initialize a CTTwoCellAnchor that anchors a shape against - * top-left and bottom-right cells. - * - * @return a new CTTwoCellAnchor - */ - private CTTwoCellAnchor createTwoCellAnchor(XSSFClientAnchor anchor) { - CTTwoCellAnchor ctAnchor = drawing.addNewTwoCellAnchor(); - ctAnchor.setFrom(anchor.getFrom()); - ctAnchor.setTo(anchor.getTo()); - ctAnchor.addNewClientData(); - anchor.setTo(ctAnchor.getTo()); - anchor.setFrom(ctAnchor.getFrom()); - STEditAs.Enum editAs; - switch (anchor.getAnchorType()) { - case DONT_MOVE_AND_RESIZE: - editAs = STEditAs.ABSOLUTE; - break; - case MOVE_AND_RESIZE: - editAs = STEditAs.TWO_CELL; - break; - case MOVE_DONT_RESIZE: - editAs = STEditAs.ONE_CELL; - break; - default: - editAs = STEditAs.ONE_CELL; - } - ctAnchor.setEditAs(editAs); - return ctAnchor; - } - - private CTTransform2D createXfrm(XSSFClientAnchor anchor) { - CTTransform2D xfrm = CTTransform2D.Factory.newInstance(); - CTPoint2D off = xfrm.addNewOff(); - off.setX(anchor.getDx1()); - off.setY(anchor.getDy1()); - XSSFSheet sheet = getSheet(); - double widthPx = 0; - for (int col = anchor.getCol1(); col < anchor.getCol2(); col++) { - widthPx += sheet.getColumnWidthInPixels(col); - } - double heightPx = 0; - for (int row = anchor.getRow1(); row < anchor.getRow2(); row++) { - heightPx += ImageUtils.getRowHeightInPixels(sheet, row); - } - long width = Units.pixelToEMU((int) widthPx); - long height = Units.pixelToEMU((int) heightPx); - CTPositiveSize2D ext = xfrm.addNewExt(); - ext.setCx(width - anchor.getDx1() + anchor.getDx2()); - ext.setCy(height - anchor.getDy1() + anchor.getDy2()); - - // TODO: handle vflip/hflip - return xfrm; - } - - private long newShapeId() { - return 1L + drawing.sizeOfAbsoluteAnchorArray() + drawing.sizeOfOneCellAnchorArray() + drawing - .sizeOfTwoCellAnchorArray(); - } - - /** - * @return list of shapes in this drawing - */ - public List<XSSFShape> getShapes() { - List<XSSFShape> lst = new ArrayList<>(); - XmlCursor cur = drawing.newCursor(); - try { - if (cur.toFirstChild()) { - addShapes(cur, lst); - } - } finally { - cur.dispose(); - } - return lst; - } - - /** - * @return list of shapes in this shape group - */ - public List<XSSFShape> getShapes(XSSFShapeGroup groupshape) { - List<XSSFShape> lst = new ArrayList<>(); - XmlCursor cur = groupshape.getCTGroupShape().newCursor(); - try { - addShapes(cur, lst); - } finally { - cur.dispose(); - } - return lst; - } - - private void addShapes(XmlCursor cur, List<XSSFShape> lst) { - try { - do { - cur.push(); - if (cur.toFirstChild()) { - do { - XmlObject obj = cur.getObject(); - - XSSFShape shape; - if (obj instanceof CTMarker) { - // ignore anchor elements - continue; - } else if (obj instanceof CTPicture) { - shape = new XSSFPicture(this, (CTPicture) obj); - } else if (obj instanceof CTConnector) { - shape = new XSSFConnector(this, (CTConnector) obj); - } else if (obj instanceof CTShape) { - shape = hasOleLink(obj) ? new XSSFObjectData(this, (CTShape) obj) - : new XSSFSimpleShape(this, (CTShape) obj); - } else if (obj instanceof CTGraphicalObjectFrame) { - shape = new XSSFGraphicFrame(this, (CTGraphicalObjectFrame) obj); - } else if (obj instanceof CTGroupShape) { - shape = new XSSFShapeGroup(this, (CTGroupShape) obj); - } else if (obj instanceof XmlAnyTypeImpl) { - LOG.atWarn().log("trying to parse AlternateContent, this unlinks the returned Shapes from the underlying xml content, so those shapes can't be used to modify the drawing, i.e. modifications will be ignored!"); - - // XmlAnyTypeImpl is returned for AlternateContent - // parts, which might contain a CTDrawing - cur.push(); - cur.toFirstChild(); - XmlCursor cur2 = null; - try { - // need to parse AlternateContent again, - // otherwise the child elements aren't typed, - // but also XmlAnyTypes - CTDrawing alterWS = CTDrawing.Factory.parse(cur.newXMLStreamReader()); - cur2 = alterWS.newCursor(); - if (cur2.toFirstChild()) { - addShapes(cur2, lst); - } - } catch (XmlException e) { - LOG.atWarn().withThrowable(e).log("unable to parse CTDrawing in alternate content."); - } finally { - if (cur2 != null) { - cur2.dispose(); - } - cur.pop(); - } - continue; - } else { - // ignore anything else - continue; - } - - assert (shape != null); - shape.anchor = getAnchorFromParent(obj); - lst.add(shape); - - } while (cur.toNextSibling()); - } - cur.pop(); - } while (cur.toNextSibling()); - } finally { - cur.dispose(); - } - } - - private boolean hasOleLink(XmlObject shape) { - QName uriName = new QName(null, "uri"); - String xquery = "declare namespace a='" + XSSFRelation.NS_DRAWINGML + "' .//a:extLst/a:ext"; - XmlCursor cur = shape.newCursor(); - cur.selectPath(xquery); - try { - while (cur.toNextSelection()) { - String uri = cur.getAttributeText(uriName); - if ("{63B3BB69-23CF-44E3-9099-C40C66FF867C}".equals(uri)) { - return true; - } - } - } finally { - cur.dispose(); - } - return false; - } - - private XSSFAnchor getAnchorFromParent(XmlObject obj) { - XSSFAnchor anchor = null; - - XmlObject parentXbean = null; - XmlCursor cursor = obj.newCursor(); - if (cursor.toParent()) { - parentXbean = cursor.getObject(); - } - cursor.dispose(); - if (parentXbean != null) { - if (parentXbean instanceof CTTwoCellAnchor) { - CTTwoCellAnchor ct = (CTTwoCellAnchor) parentXbean; - anchor = new XSSFClientAnchor(ct.getFrom(), ct.getTo()); - } else if (parentXbean instanceof CTOneCellAnchor) { - CTOneCellAnchor ct = (CTOneCellAnchor) parentXbean; - anchor = new XSSFClientAnchor(getSheet(), ct.getFrom(), ct.getExt()); - } else if (parentXbean instanceof CTAbsoluteAnchor) { - CTAbsoluteAnchor ct = (CTAbsoluteAnchor) parentXbean; - anchor = new XSSFClientAnchor(getSheet(), ct.getPos(), ct.getExt()); - } - } - return anchor; - } - - @Override - public Iterator<XSSFShape> iterator() { - return getShapes().iterator(); - } - - /** - * @return the sheet associated with the drawing - */ - public XSSFSheet getSheet() { - return (XSSFSheet) getParent(); - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDxfStyleProvider.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDxfStyleProvider.java deleted file mode 100644 index c68f16eb09..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDxfStyleProvider.java +++ /dev/null @@ -1,86 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.BorderFormatting; -import org.apache.poi.ss.usermodel.DifferentialStyleProvider; -import org.apache.poi.ss.usermodel.ExcelNumberFormat; -import org.apache.poi.ss.usermodel.FontFormatting; -import org.apache.poi.ss.usermodel.PatternFormatting; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxf; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmt; - -/** - * Style based on a dxf record - e.g. table style element or conditional formatting rule - */ -public class XSSFDxfStyleProvider implements DifferentialStyleProvider { - - private final IndexedColorMap colorMap; - private final BorderFormatting border; - private final FontFormatting font; - private final ExcelNumberFormat number; - private final PatternFormatting fill; - private final int stripeSize; - - /** - * @param dxf - * @param stripeSize 0 for non-stripe styles, > 1 for stripes - * @param colorMap - */ - public XSSFDxfStyleProvider(CTDxf dxf, int stripeSize, IndexedColorMap colorMap) { - this.stripeSize = stripeSize; - this.colorMap = colorMap; - if (dxf == null) { - border = null; - font = null; - number = null; - fill = null; - } else { - border = dxf.isSetBorder() ? new XSSFBorderFormatting(dxf.getBorder(), colorMap) : null; - font = dxf.isSetFont() ? new XSSFFontFormatting(dxf.getFont(), colorMap) : null; - if (dxf.isSetNumFmt()) { - CTNumFmt numFmt = dxf.getNumFmt(); - number = new ExcelNumberFormat((int) numFmt.getNumFmtId(), numFmt.getFormatCode()); - } else { - number = null; - } - fill = dxf.isSetFill() ? new XSSFPatternFormatting(dxf.getFill(), colorMap) : null; - } - } - - public BorderFormatting getBorderFormatting() { - return border; - } - - public FontFormatting getFontFormatting() { - return font; - } - - public ExcelNumberFormat getNumberFormat() { - return number; - } - - public PatternFormatting getPatternFormatting() { - return fill; - } - - public int getStripeSize() { - return stripeSize; - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationCell.java deleted file mode 100644 index 221154b331..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationCell.java +++ /dev/null @@ -1,105 +0,0 @@ -/* ==================================================================== - 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.ss.formula.EvaluationCell; -import org.apache.poi.ss.formula.EvaluationSheet; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.util.CellRangeAddress; - -/** - * XSSF wrapper for a cell under evaluation - */ -final class XSSFEvaluationCell implements EvaluationCell { - - private final EvaluationSheet _evalSheet; - private final XSSFCell _cell; - - public XSSFEvaluationCell(XSSFCell cell, XSSFEvaluationSheet evaluationSheet) { - _cell = cell; - _evalSheet = evaluationSheet; - } - - public XSSFEvaluationCell(XSSFCell cell) { - this(cell, new XSSFEvaluationSheet(cell.getSheet())); - } - - @Override - public Object getIdentityKey() { - // save memory by just using the cell itself as the identity key - // Note - this assumes XSSFCell has not overridden hashCode and equals - return _cell; - } - - public XSSFCell getXSSFCell() { - return _cell; - } - @Override - public boolean getBooleanCellValue() { - return _cell.getBooleanCellValue(); - } - /** - * @return cell type - */ - @Override - public CellType getCellType() { - return _cell.getCellType(); - } - @Override - public int getColumnIndex() { - return _cell.getColumnIndex(); - } - @Override - public int getErrorCellValue() { - return _cell.getErrorCellValue(); - } - @Override - public double getNumericCellValue() { - return _cell.getNumericCellValue(); - } - @Override - public int getRowIndex() { - return _cell.getRowIndex(); - } - @Override - public EvaluationSheet getSheet() { - return _evalSheet; - } - @Override - public String getStringCellValue() { - return _cell.getRichStringCellValue().getString(); - } - - @Override - public CellRangeAddress getArrayFormulaRange() { - return _cell.getArrayFormulaRange(); - } - - @Override - public boolean isPartOfArrayFormulaGroup() { - return _cell.isPartOfArrayFormulaGroup(); - } - - /** - * @return cell type of cached formula result - */ - @Override - public CellType getCachedFormulaResultType() { - return _cell.getCachedFormulaResultType(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationSheet.java deleted file mode 100644 index 18b663c2b3..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationSheet.java +++ /dev/null @@ -1,147 +0,0 @@ -/* ==================================================================== - 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 java.util.HashMap; -import java.util.Map; - -import org.apache.poi.ss.formula.EvaluationCell; -import org.apache.poi.ss.formula.EvaluationSheet; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.util.Internal; - -/** - * XSSF wrapper for a sheet under evaluation - */ -@Internal -final class XSSFEvaluationSheet implements EvaluationSheet { - - private final XSSFSheet _xs; - private Map<CellKey, EvaluationCell> _cellCache; - - public XSSFEvaluationSheet(XSSFSheet sheet) { - _xs = sheet; - } - - public XSSFSheet getXSSFSheet() { - return _xs; - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.formula.EvaluationSheet#getlastRowNum() - * @since POI 4.0.0 - */ - @Override - public int getLastRowNum() { - return _xs.getLastRowNum(); - } - - /* (non-Javadoc) - * @see org.apache.poi.ss.formula.EvaluationSheet#isRowHidden(int) - * @since POI 4.1.0 - */ - public boolean isRowHidden(int rowIndex) { - final XSSFRow row = _xs.getRow(rowIndex); - if (row == null) return false; - return row.getZeroHeight(); - } - - /* (non-JavaDoc), inherit JavaDoc from EvaluationWorkbook - * @since POI 3.15 beta 3 - */ - @Override - public void clearAllCachedResultValues() { - _cellCache = null; - } - - @Override - public EvaluationCell getCell(int rowIndex, int columnIndex) { - // shortcut evaluation if reference is outside the bounds of existing data - // see issue #61841 for impact on VLOOKUP in particular - if (rowIndex > getLastRowNum()) { - return null; - } - - // cache for performance: ~30% speedup due to caching - if (_cellCache == null) { - _cellCache = new HashMap<>(_xs.getLastRowNum() * 3); - for (final Row row : _xs) { - final int rowNum = row.getRowNum(); - for (final Cell cell : row) { - // cast is safe, the iterator is just defined using the interface - final CellKey key = new CellKey(rowNum, cell.getColumnIndex()); - final EvaluationCell evalcell = new XSSFEvaluationCell((XSSFCell) cell, this); - _cellCache.put(key, evalcell); - } - } - } - - final CellKey key = new CellKey(rowIndex, columnIndex); - EvaluationCell evalcell = _cellCache.get(key); - - // If cache is stale, update cache with this one cell - // This is a compromise between rebuilding the entire cache - // (which would quickly defeat the benefit of the cache) - // and not caching at all. - // See bug 59958: Add cells on the fly to the evaluation sheet cache on cache miss - if (evalcell == null) { - XSSFRow row = _xs.getRow(rowIndex); - if (row == null) { - return null; - } - XSSFCell cell = row.getCell(columnIndex); - if (cell == null) { - return null; - } - evalcell = new XSSFEvaluationCell(cell, this); - _cellCache.put(key, evalcell); - } - - return evalcell; - } - - private static class CellKey { - private final int _row; - private final int _col; - private int _hash = -1; //lazily computed - - protected CellKey(int row, int col) { - _row = row; - _col = col; - } - - @Override - public int hashCode() { - if ( _hash == -1 ) { - _hash = (17 * 37 + _row) * 37 + _col; - } - return _hash; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof CellKey)) { - return false; - } - // assumes other object is one of us, otherwise ClassCastException is thrown - final CellKey oKey = (CellKey) obj; - return _row == oKey._row && _col == oKey._col; - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java deleted file mode 100644 index 2c13f82668..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java +++ /dev/null @@ -1,87 +0,0 @@ -/* ==================================================================== - 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.ss.formula.EvaluationCell; -import org.apache.poi.ss.formula.EvaluationSheet; -import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.util.Internal; - -/** - * Internal POI use only - */ -@Internal -public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook { - private XSSFEvaluationSheet[] _sheetCache; - - public static XSSFEvaluationWorkbook create(XSSFWorkbook book) { - if (book == null) { - return null; - } - return new XSSFEvaluationWorkbook(book); - } - - private XSSFEvaluationWorkbook(XSSFWorkbook book) { - super(book); - } - - /* (non-JavaDoc), inherit JavaDoc from EvaluationSheet - * @since POI 3.15 beta 3 - */ - @Override - public void clearAllCachedResultValues() { - super.clearAllCachedResultValues(); - _sheetCache = null; - } - - @Override - public int getSheetIndex(EvaluationSheet evalSheet) { - XSSFSheet sheet = ((XSSFEvaluationSheet)evalSheet).getXSSFSheet(); - return _uBook.getSheetIndex(sheet); - } - - @Override - public EvaluationSheet getSheet(int sheetIndex) { - // Performance optimization: build sheet cache the first time this is called - // to avoid re-creating the XSSFEvaluationSheet each time a new cell is evaluated - // EvaluationWorkbooks make not guarantee to synchronize changes made to - // the underlying workbook after the EvaluationWorkbook is created. - if (_sheetCache == null) { - final int numberOfSheets = _uBook.getNumberOfSheets(); - _sheetCache = new XSSFEvaluationSheet[numberOfSheets]; - for (int i=0; i < numberOfSheets; i++) { - _sheetCache[i] = new XSSFEvaluationSheet(_uBook.getSheetAt(i)); - } - } - if (sheetIndex < 0 || sheetIndex >= _sheetCache.length) { - // do this to reuse the out-of-bounds logic and message from XSSFWorkbook - _uBook.getSheetAt(sheetIndex); - } - return _sheetCache[sheetIndex]; - } - - @Override - public Ptg[] getFormulaTokens(EvaluationCell evalCell) { - final XSSFCell cell = ((XSSFEvaluationCell)evalCell).getXSSFCell(); - final int sheetIndex = _uBook.getSheetIndex(cell.getSheet()); - final int rowIndex = cell.getRowIndex(); - return FormulaParser.parse(cell.getCellFormula(this), this, FormulaType.CELL, sheetIndex, rowIndex); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvenFooter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvenFooter.java deleted file mode 100644 index 8234793c3e..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvenFooter.java +++ /dev/null @@ -1,81 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.Footer; -import org.apache.poi.xssf.usermodel.extensions.XSSFHeaderFooter; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; - -/** - * <p> - * Even page footer value. Corresponds to even printed pages. - * Even page(s) in the sheet may not be printed, for example, if the print area is specified to be - * a range such that it falls outside an even page's scope. - * If no even footer is specified, then the odd footer's value is assumed for even page footers. - * </p><p> - * The even footer is activated by the "Different Even/Odd" Header/Footer property for the sheet. - * If this property is not set, the even footer is ignored, and the odd footer is used instead. - * </p><p> - * Creating an even header or footer sets this property by default, so all you need to do to - * get an even header or footer to display is to create one. Likewise, if both the even header - * and footer are usnset, then this property is unset, and the odd header and footer are used - * for even pages. - * </p> - */ -public class XSSFEvenFooter extends XSSFHeaderFooter implements Footer{ - - /** - * Create an instance of XSSFEvenFooter from the supplied XML bean - * @see XSSFSheet#getEvenFooter() - * @param headerFooter - */ - protected XSSFEvenFooter(CTHeaderFooter headerFooter) { - super(headerFooter); - headerFooter.setDifferentOddEven(true); - } - - /** - * Get the content text representing the footer - * @return text - */ - @Override - public String getText() { - return getHeaderFooter().getEvenFooter(); - } - - /** - * Set a text for the footer. If null, unset the value. If unsetting and there is no - * Even Header for this sheet, the "DifferentEvenOdd" property for this sheet is - * unset. - * - * @see XSSFHeaderFooter to see how to create a string with Header/Footer Formatting Syntax - * @param text - a string representing the footer. - */ - @Override - public void setText(String text) { - if(text == null) { - getHeaderFooter().unsetEvenFooter(); - if (!getHeaderFooter().isSetEvenHeader()) { - getHeaderFooter().unsetDifferentOddEven(); - } - } else { - getHeaderFooter().setEvenFooter(text); - } - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvenHeader.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvenHeader.java deleted file mode 100644 index dfd9d179b8..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvenHeader.java +++ /dev/null @@ -1,86 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.Header; -import org.apache.poi.xssf.usermodel.extensions.XSSFHeaderFooter; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; - -/** - * <p> - * Even page header value. Corresponds to even printed pages. Even page(s) in - * the sheet may not be printed, for example, if the print area is specified to - * be a range such that it falls outside an even page's scope. If no even header - * is specified, then odd header value is assumed for even page headers. - * </p><p> - * The even header is activated by the "Different Even/Odd" Header/Footer property for the sheet. - * If this property is not set, the even header is ignored, and the odd footer is used instead. - * </p><p> - * Creating an even header or footer sets this property by default, so all you need to do to - * get an even header or footer to display is to create it. Likewise, if both the even header - * and footer are usnset, then this property is unset, and the odd header and footer are used - * for even pages. - * </p> - */ -public class XSSFEvenHeader extends XSSFHeaderFooter implements Header { - - /** - * Create an instance of XSSFEvenHeader from the supplied XML bean. If an even - * header is created, The property "DifferentOddEven" is set for this sheet as well. - * - * @see XSSFSheet#getEvenHeader() - * @param headerFooter - */ - protected XSSFEvenHeader(CTHeaderFooter headerFooter) { - super(headerFooter); - headerFooter.setDifferentOddEven(true); - } - - /** - * Get the content text representing this header - * - * @return text - */ - @Override - public String getText() { - return getHeaderFooter().getEvenHeader(); - } - - /** - * Set a text for the header. If null, unset the value. If unsetting and there is no - * Even Footer for this sheet, the "DifferentEvenOdd" property for this sheet is - * unset. - * - * @see XSSFHeaderFooter to see how to create a string with Header/Footer - * Formatting Syntax - * @param text - * - a string representing the header. - */ - @Override - public void setText(String text) { - if (text == null) { - getHeaderFooter().unsetEvenHeader(); - if (!getHeaderFooter().isSetEvenFooter()) { - getHeaderFooter().unsetDifferentOddEven(); - } - } else { - getHeaderFooter().setEvenHeader(text); - } - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java deleted file mode 100644 index b931154d9a..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLFactory; -import org.apache.poi.ooxml.POIXMLRelation; - -/** - * Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type - */ -public class XSSFFactory extends POIXMLFactory { - private static final XSSFFactory inst = new XSSFFactory(); - - public static XSSFFactory getInstance(){ - return inst; - } - - protected XSSFFactory() {} - - /** - * @since POI 3.14-Beta1 - */ - @Override - protected POIXMLRelation getDescriptor(String relationshipType) { - return XSSFRelation.getInstance(relationshipType); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFirstFooter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFirstFooter.java deleted file mode 100644 index 4bccf9ef1e..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFirstFooter.java +++ /dev/null @@ -1,78 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.Footer; -import org.apache.poi.xssf.usermodel.extensions.XSSFHeaderFooter; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; - -/** - * <p> - * First page footer content. Corresponds to first printed page. - * The first logical page in the sheet may not be printed, for example, if the print area is specified to - * be a range such that it falls outside the first page's scope. - * </p><p> - * The first page footer is activated by the "Different First" Header/Footer property for the sheet. - * If this property is not set, the first page footer is ignored. - * </p><p> - * Creating a first page header or footer sets this property by default, so all you need to do to - * get an first page header or footer to display is to create one. Likewise, if both the first page - * header and footer are usnset, then this property is unset, and the first page header and footer - * are ignored. - * </p> - */ -public class XSSFFirstFooter extends XSSFHeaderFooter implements Footer{ - - /** - * Create an instance of XSSFFirstFooter from the supplied XML bean - * @see XSSFSheet#getFirstFooter() - * @param headerFooter - */ - protected XSSFFirstFooter(CTHeaderFooter headerFooter) { - super(headerFooter); - headerFooter.setDifferentFirst(true); - } - - /** - * Get the content text representing the footer - * @return text - */ - @Override - public String getText() { - return getHeaderFooter().getFirstFooter(); - } - - /** - * Set a text for the footer. If null unset the value. If unsetting this header results - * in no First Header, or footer for the sheet, the 'differentFirst' property is unset as well. - * - * @see XSSFHeaderFooter to see how to create a string with Header/Footer Formatting Syntax - * @param text - a string representing the footer. - */ - @Override - public void setText(String text) { - if(text == null) { - getHeaderFooter().unsetFirstFooter(); - if (!getHeaderFooter().isSetFirstHeader()) { - getHeaderFooter().unsetDifferentFirst(); - } - } else { - getHeaderFooter().setFirstFooter(text); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFirstHeader.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFirstHeader.java deleted file mode 100644 index 4cb2254d2f..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFirstHeader.java +++ /dev/null @@ -1,79 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.Header; -import org.apache.poi.xssf.usermodel.extensions.XSSFHeaderFooter; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; - -/** - * <p> - * First page header content. Corresponds to first printed page. - * The first logical page in the sheet may not be printed, for example, if the print area is specified to - * be a range such that it falls outside the first page's scope. - * </p><p> - * The first page header is activated by the "Different First" Header/Footer property for the sheet. - * If this property is not set, the first page header is ignored. - * </p><p> - * Creating a first page header or footer sets this property by default, so all you need to do to - * get an first page header or footer to display is to create one. Likewise, if both the first page - * header and footer are usnset, then this property is unset, and the first page header and footer - * are ignored. - * </p> - */ -public class XSSFFirstHeader extends XSSFHeaderFooter implements Header{ - - /** - * Create an instance of XSSFFirstHeader from the supplied XML bean - * @see XSSFSheet#getFirstHeader() - * @param headerFooter - */ - protected XSSFFirstHeader(CTHeaderFooter headerFooter) { - super(headerFooter); - headerFooter.setDifferentFirst(true); - } - - /** - * Get the content text representing this header - * @return text - */ - @Override - public String getText() { - return getHeaderFooter().getFirstHeader(); - } - - /** - * Set a text for the header. If null unset the value. If unsetting this header results - * in no First Header, or footer for the sheet, the 'differentFirst' property is unset as well. - * - * @see XSSFHeaderFooter to see how to create a string with Header/Footer Formatting Syntax - * @param text - a string representing the header. - */ - @Override - public void setText(String text) { - if(text == null) { - getHeaderFooter().unsetFirstHeader(); - if (!getHeaderFooter().isSetFirstFooter()) { - getHeaderFooter().unsetDifferentFirst(); - } - } else { - getHeaderFooter().setFirstHeader(text); - } - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFont.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFont.java deleted file mode 100644 index b6d4465ecc..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFont.java +++ /dev/null @@ -1,688 +0,0 @@ -/* ==================================================================== - 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 java.util.Objects; - -import org.apache.poi.common.usermodel.fonts.FontCharset; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.FontFamily; -import org.apache.poi.ss.usermodel.FontScheme; -import org.apache.poi.ss.usermodel.FontUnderline; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.util.Internal; -import org.apache.poi.util.Removal; -import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.model.ThemesTable; -import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STVerticalAlignRun; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBooleanProperty; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontFamily; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontName; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontScheme; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontSize; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIntProperty; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTUnderlineProperty; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTVerticalAlignFontProperty; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STFontScheme; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnderlineValues; - -/** - * Represents a font used in a workbook. - * - * @author Gisella Bronzetti - */ -public class XSSFFont implements Font { - - /** - * By default, Microsoft Office Excel 2007 uses the Calibri font in font size 11 - */ - public static final String DEFAULT_FONT_NAME = "Calibri"; - /** - * By default, Microsoft Office Excel 2007 uses the Calibri font in font size 11 - */ - public static final short DEFAULT_FONT_SIZE = 11; - /** - * Default font color is black - * @see org.apache.poi.ss.usermodel.IndexedColors#BLACK - */ - public static final short DEFAULT_FONT_COLOR = IndexedColors.BLACK.getIndex(); - - private IndexedColorMap _indexedColorMap; - private ThemesTable _themes; - private CTFont _ctFont; - private int _index; - - /** - * Create a new XSSFFont - * - * @param font the underlying CTFont bean - */ - @Internal - public XSSFFont(CTFont font) { - _ctFont = font; - _index = 0; - } - - /** - * Called from parsing styles.xml - * @param font CTFont - * @param index font index - * @param colorMap for default or custom indexed colors - */ - @Internal - public XSSFFont(CTFont font, int index, IndexedColorMap colorMap) { - _ctFont = font; - _index = (short)index; - _indexedColorMap = colorMap; - } - - /** - * Create a new XSSFont. This method is protected to be used only by XSSFWorkbook - */ - public XSSFFont() { - this._ctFont = CTFont.Factory.newInstance(); - setFontName(DEFAULT_FONT_NAME); - setFontHeight((double)DEFAULT_FONT_SIZE); - } - - /** - * get the underlying CTFont font - */ - @Internal - public CTFont getCTFont() { - return _ctFont; - } - - /** - * get a boolean value for the boldness to use. - * - * @return boolean - bold - */ - public boolean getBold() { - CTBooleanProperty bold = _ctFont.sizeOfBArray() == 0 ? null : _ctFont.getBArray(0); - return (bold != null && bold.getVal()); - } - - /** - * get character-set to use. - * - * @return int - character-set (0-255) - * @see FontCharset - */ - public int getCharSet() { - CTIntProperty charset = _ctFont.sizeOfCharsetArray() == 0 ? null : _ctFont.getCharsetArray(0); - return charset == null ? FontCharset.ANSI.getNativeId() : FontCharset.valueOf(charset.getVal()).getNativeId(); - } - - - /** - * get the indexed color value for the font - * References a color defined in IndexedColors. - * - * @return short - indexed color to use - * @see IndexedColors - */ - public short getColor() { - CTColor color = _ctFont.sizeOfColorArray() == 0 ? null : _ctFont.getColorArray(0); - if (color == null) return IndexedColors.BLACK.getIndex(); - - long index = color.getIndexed(); - if (index == XSSFFont.DEFAULT_FONT_COLOR) { - return IndexedColors.BLACK.getIndex(); - } else if (index == IndexedColors.RED.getIndex()) { - return IndexedColors.RED.getIndex(); - } else { - return (short)index; - } - } - - - /** - * get the color value for the font - * References a color defined as Standard Alpha Red Green Blue color value (ARGB). - * - * @return XSSFColor - rgb color to use - */ - public XSSFColor getXSSFColor() { - CTColor ctColor = _ctFont.sizeOfColorArray() == 0 ? null : _ctFont.getColorArray(0); - if(ctColor != null) { - XSSFColor color = XSSFColor.from(ctColor, _indexedColorMap); - if(_themes != null) { - _themes.inheritFromThemeAsRequired(color); - } - return color; - } else { - return null; - } - } - - - /** - * get the color value for the font - * References a color defined in theme. - * - * @return short - theme defined to use - */ - public short getThemeColor() { - CTColor color = _ctFont.sizeOfColorArray() == 0 ? null : _ctFont.getColorArray(0); - long index = color == null ? 0 : color.getTheme(); - return (short) index; - } - - /** - * Get the font height in unit's of 1/20th of a point. - * <p> - * For many users, the related {@link #getFontHeightInPoints()} - * will be more helpful, as that returns font heights in the - * more familiar points units, eg 10, 12, 14. - - * @return short - height in 1/20ths of a point - * @see #getFontHeightInPoints() - */ - public short getFontHeight() { - return (short)(getFontHeightRaw()*Font.TWIPS_PER_POINT); - } - - /** - * Get the font height in points. - * <p> - * This will return the same font height that is shown in Excel, - * such as 10 or 14 or 28. - * @return short - height in the familiar unit of measure - points - * @see #getFontHeight() - */ - public short getFontHeightInPoints() { - return (short)getFontHeightRaw(); - } - - /** - * Return the raw font height, in points, but also - * including fractions. - */ - private double getFontHeightRaw() { - CTFontSize size = _ctFont.sizeOfSzArray() == 0 ? null : _ctFont.getSzArray(0); - if (size != null) { - return size.getVal(); - } - return DEFAULT_FONT_SIZE; - } - - /** - * get the name of the font (i.e. Arial) - * - * @return String - a string representing the name of the font to use - */ - public String getFontName() { - CTFontName name = _ctFont.sizeOfNameArray() == 0 ? null : _ctFont.getNameArray(0); - return name == null ? DEFAULT_FONT_NAME : name.getVal(); - } - - /** - * get a boolean value that specify whether to use italics or not - * - * @return boolean - value for italic - */ - public boolean getItalic() { - CTBooleanProperty italic = _ctFont.sizeOfIArray() == 0 ? null : _ctFont.getIArray(0); - return italic != null && italic.getVal(); - } - - /** - * get a boolean value that specify whether to use a strikeout horizontal line through the text or not - * - * @return boolean - value for strikeout - */ - public boolean getStrikeout() { - CTBooleanProperty strike = _ctFont.sizeOfStrikeArray() == 0 ? null : _ctFont.getStrikeArray(0); - return strike != null && strike.getVal(); - } - - /** - * get normal,super or subscript. - * - * @return short - offset type to use (none,super,sub) - * @see Font#SS_NONE - * @see Font#SS_SUPER - * @see Font#SS_SUB - */ - public short getTypeOffset() { - CTVerticalAlignFontProperty vAlign = _ctFont.sizeOfVertAlignArray() == 0 ? null : _ctFont.getVertAlignArray(0); - if (vAlign == null) { - return Font.SS_NONE; - } - int val = vAlign.getVal().intValue(); - switch (val) { - case STVerticalAlignRun.INT_BASELINE: - return Font.SS_NONE; - case STVerticalAlignRun.INT_SUBSCRIPT: - return Font.SS_SUB; - case STVerticalAlignRun.INT_SUPERSCRIPT: - return Font.SS_SUPER; - default: - throw new POIXMLException("Wrong offset value " + val); - } - } - - /** - * get type of text underlining to use - * - * @return byte - underlining type - * @see org.apache.poi.ss.usermodel.FontUnderline - */ - public byte getUnderline() { - CTUnderlineProperty underline = _ctFont.sizeOfUArray() == 0 ? null : _ctFont.getUArray(0); - if (underline != null) { - FontUnderline val = FontUnderline.valueOf(underline.getVal().intValue()); - return val.getByteValue(); - } - return Font.U_NONE; - } - - /** - * set a boolean value for the boldness to use. If omitted, the default value is true. - * - * @param bold - boldness to use - */ - public void setBold(boolean bold) { - if(bold){ - CTBooleanProperty ctBold = _ctFont.sizeOfBArray() == 0 ? _ctFont.addNewB() : _ctFont.getBArray(0); - ctBold.setVal(true); - } else { - _ctFont.setBArray(null); - } - } - - /** - * set character-set to use. - * - * @param charset - charset - * @see FontCharset - */ - public void setCharSet(byte charset) { - int cs = charset & 0xff; - setCharSet(cs); - } - - /** - * set character-set to use. - * - * @param charset - charset - * @see FontCharset - */ - public void setCharSet(int charset) { - FontCharset fontCharset = FontCharset.valueOf(charset); - if(fontCharset != null) { - setCharSet(fontCharset); - } else { - throw new POIXMLException("Attention: an attempt to set a type of unknown charset and charset"); - } - } - - /** - * set character-set to use. - * - * @param charSet - * @deprecated use {@link #setCharSet(FontCharset)} instead - */ - @Deprecated - @Removal(version = "6.0.0") - public void setCharSet(org.apache.poi.ss.usermodel.FontCharset charSet) { - CTIntProperty charsetProperty; - if(_ctFont.sizeOfCharsetArray() == 0) { - charsetProperty = _ctFont.addNewCharset(); - } else { - charsetProperty = _ctFont.getCharsetArray(0); - } - // We know that FontCharset only has valid entries in it, - // so we can just set the int value from it - charsetProperty.setVal( charSet.getValue() ); - } - - /** - * set character-set to use. - * - * @param charSet - * @since 5.0.0 - */ - public void setCharSet(FontCharset charSet) { - CTIntProperty charsetProperty; - if(_ctFont.sizeOfCharsetArray() == 0) { - charsetProperty = _ctFont.addNewCharset(); - } else { - charsetProperty = _ctFont.getCharsetArray(0); - } - // We know that FontCharset only has valid entries in it, - // so we can just set the int value from it - charsetProperty.setVal( charSet.getNativeId() ); - } - - /** - * set the indexed color for the font - * - * @param color - color to use - * @see #DEFAULT_FONT_COLOR - Note: default font color - * @see IndexedColors - */ - public void setColor(short color) { - CTColor ctColor = _ctFont.sizeOfColorArray() == 0 ? _ctFont.addNewColor() : _ctFont.getColorArray(0); - switch (color) { - case Font.COLOR_NORMAL: { - ctColor.setIndexed(XSSFFont.DEFAULT_FONT_COLOR); - break; - } - case Font.COLOR_RED: { - ctColor.setIndexed(IndexedColors.RED.getIndex()); - break; - } - default: - ctColor.setIndexed(color); - } - } - - /** - * set the color for the font in Standard Alpha Red Green Blue color value - * - * @param color - color to use - */ - public void setColor(XSSFColor color) { - if(color == null) _ctFont.setColorArray(null); - else { - CTColor ctColor = _ctFont.sizeOfColorArray() == 0 ? _ctFont.addNewColor() : _ctFont.getColorArray(0); - if (ctColor.isSetIndexed()) { - ctColor.unsetIndexed(); - } - ctColor.setRgb(color.getRGB()); - } - } - - /** - * set the font height in points. - * - * @param height - height in points - */ - public void setFontHeight(short height) { - setFontHeight((double) height/Font.TWIPS_PER_POINT); - } - - /** - * set the font height in points. - * - * @param height - height in points - */ - public void setFontHeight(double height) { - CTFontSize fontSize = _ctFont.sizeOfSzArray() == 0 ? _ctFont.addNewSz() : _ctFont.getSzArray(0); - fontSize.setVal(height); - } - - /** - * set the font height in points. - * - * @see #setFontHeight - */ - public void setFontHeightInPoints(short height) { - setFontHeight((double)height); - } - - /** - * set the theme color for the font to use - * - * @param theme - theme color to use - */ - public void setThemeColor(short theme) { - CTColor ctColor = _ctFont.sizeOfColorArray() == 0 ? _ctFont.addNewColor() : _ctFont.getColorArray(0); - ctColor.setTheme(theme); - } - - /** - * set the name for the font (i.e. Arial). - * If the font doesn't exist (because it isn't installed on the system), - * or the charset is invalid for that font, then another font should - * be substituted. - * The string length for this attribute shall be 0 to 31 characters. - * Default font name is Calibri. - * - * @param name - value representing the name of the font to use - * @see #DEFAULT_FONT_NAME - */ - public void setFontName(String name) { - CTFontName fontName = _ctFont.sizeOfNameArray() == 0 ? _ctFont.addNewName() : _ctFont.getNameArray(0); - fontName.setVal(name == null ? DEFAULT_FONT_NAME : name); - } - - - /** - * set a boolean value for the property specifying whether to use italics or not - * If omitted, the default value is true. - * - * @param italic - value for italics or not - */ - public void setItalic(boolean italic) { - if(italic){ - CTBooleanProperty bool = _ctFont.sizeOfIArray() == 0 ? _ctFont.addNewI() : _ctFont.getIArray(0); - bool.setVal(true); - } else { - _ctFont.setIArray(null); - } - } - - - /** - * set a boolean value for the property specifying whether to use a strikeout horizontal line through the text or not - * If omitted, the default value is true. - * - * @param strikeout - value for strikeout or not - */ - public void setStrikeout(boolean strikeout) { - if(strikeout) { - CTBooleanProperty strike = _ctFont.sizeOfStrikeArray() == 0 ? _ctFont.addNewStrike() : _ctFont.getStrikeArray(0); - strike.setVal(true); - } else { - _ctFont.setStrikeArray(null); - } - } - - /** - * set normal,super or subscript, that representing the vertical-alignment setting. - * Setting this to either subscript or superscript shall make the font size smaller if a - * smaller font size is available. - * - * @param offset - offset type to use (none,super,sub) - * @see #SS_NONE - * @see #SS_SUPER - * @see #SS_SUB - */ - public void setTypeOffset(short offset) { - if(offset == Font.SS_NONE){ - _ctFont.setVertAlignArray(null); - } else { - CTVerticalAlignFontProperty offsetProperty = _ctFont.sizeOfVertAlignArray() == 0 ? _ctFont.addNewVertAlign() : _ctFont.getVertAlignArray(0); - switch (offset) { - case Font.SS_NONE: - offsetProperty.setVal(STVerticalAlignRun.BASELINE); - break; - case Font.SS_SUB: - offsetProperty.setVal(STVerticalAlignRun.SUBSCRIPT); - break; - case Font.SS_SUPER: - offsetProperty.setVal(STVerticalAlignRun.SUPERSCRIPT); - break; - default: - throw new IllegalStateException("Invalid type offset: " + offset); - } - } - } - - /** - * set the style of underlining that is used. - * The none style is equivalent to not using underlining at all. - * - * @param underline - underline type to use - * @see FontUnderline - */ - public void setUnderline(byte underline) { - setUnderline(FontUnderline.valueOf(underline)); - } - - /** - * set an enumeration representing the style of underlining that is used. - * The none style is equivalent to not using underlining at all. - * The possible values for this attribute are defined by the FontUnderline - * - * @param underline - FontUnderline enum value - */ - public void setUnderline(FontUnderline underline) { - if(underline == FontUnderline.NONE && _ctFont.sizeOfUArray() > 0){ - _ctFont.setUArray(null); - } else { - CTUnderlineProperty ctUnderline = _ctFont.sizeOfUArray() == 0 ? _ctFont.addNewU() : _ctFont.getUArray(0); - STUnderlineValues.Enum val = STUnderlineValues.Enum.forInt(underline.getValue()); - ctUnderline.setVal(val); - } - } - - - public String toString() { - return _ctFont.toString(); - } - - - /** - * Perform a registration of ourselves - * to the style table - */ - public long registerTo(StylesTable styles) { - return registerTo(styles, true); - } - - public long registerTo(StylesTable styles, boolean force) { - this._themes = styles.getTheme(); - this._index = styles.putFont(this, force); - return this._index; - } - - - /** - * Records the Themes Table that is associated with - * the current font, used when looking up theme - * based colours and properties. - */ - public void setThemesTable(ThemesTable themes) { - this._themes = themes; - } - - /** - * get the font scheme property. - * is used only in StylesTable to create the default instance of font - * - * @return FontScheme - * @see org.apache.poi.xssf.model.StylesTable#createDefaultFont() - */ - @SuppressWarnings("JavadocReference") - public FontScheme getScheme() { - CTFontScheme scheme = _ctFont.sizeOfSchemeArray() == 0 ? null : _ctFont.getSchemeArray(0); - return scheme == null ? FontScheme.NONE : FontScheme.valueOf(scheme.getVal().intValue()); - } - - /** - * set font scheme property - * - * @param scheme - FontScheme enum value - * @see FontScheme - */ - public void setScheme(FontScheme scheme) { - CTFontScheme ctFontScheme = _ctFont.sizeOfSchemeArray() == 0 ? _ctFont.addNewScheme() : _ctFont.getSchemeArray(0); - STFontScheme.Enum val = STFontScheme.Enum.forInt(scheme.getValue()); - ctFontScheme.setVal(val); - } - - /** - * get the font family to use. - * - * @return the font family to use - * @see org.apache.poi.ss.usermodel.FontFamily - */ - public int getFamily() { - CTFontFamily family = _ctFont.sizeOfFamilyArray() == 0 ? null : _ctFont.getFamilyArray(0); - return family == null ? FontFamily.NOT_APPLICABLE.getValue() : FontFamily.valueOf(family.getVal()).getValue(); - } - - /** - * Set the font family this font belongs to. - * A font family is a set of fonts having common stroke width and serif characteristics. - * The font name overrides when there are conflicting values. - * - * @param value - font family - * @see FontFamily - */ - public void setFamily(int value) { - CTFontFamily family = _ctFont.sizeOfFamilyArray() == 0 ? _ctFont.addNewFamily() : _ctFont.getFamilyArray(0); - family.setVal(value); - } - - /** - * set an enumeration representing the font family this font belongs to. - * A font family is a set of fonts having common stroke width and serif characteristics. - * - * @param family font family - * @see #setFamily(int value) - */ - public void setFamily(FontFamily family) { - setFamily(family.getValue()); - } - - @Override - public int getIndex() { - return _index; - } - - @Deprecated - @Removal(version = "6.0.0") - @Override - public int getIndexAsInt() - { - return _index; - } - - public int hashCode(){ - return _ctFont.toString().hashCode(); - } - - public boolean equals(Object o){ - if(!(o instanceof XSSFFont)) return false; - - XSSFFont cf = (XSSFFont)o; - - // BUG 60845 - return Objects.equals(this.getItalic(), cf.getItalic()) - && Objects.equals(this.getBold(), cf.getBold()) - && Objects.equals(this.getStrikeout(), cf.getStrikeout()) - && Objects.equals(this.getCharSet(), cf.getCharSet()) - && Objects.equals(this.getColor(), cf.getColor()) - && Objects.equals(this.getFamily(), cf.getFamily()) - && Objects.equals(this.getFontHeight(), cf.getFontHeight()) - && Objects.equals(this.getFontName(), cf.getFontName()) - && Objects.equals(this.getScheme(), cf.getScheme()) - && Objects.equals(this.getThemeColor(), cf.getThemeColor()) - && Objects.equals(this.getTypeOffset(), cf.getTypeOffset()) - && Objects.equals(this.getUnderline(), cf.getUnderline()) - && Objects.equals(this.getXSSFColor(), cf.getXSSFColor()); - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java deleted file mode 100644 index 6b359a2988..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * ==================================================================== - * 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.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.FontFormatting; -import org.apache.poi.ss.usermodel.FontUnderline; -import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STVerticalAlignRun; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontSize; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTUnderlineProperty; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTVerticalAlignFontProperty; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnderlineValues; - - -/** - * @author Yegor Kozlov - */ -public class XSSFFontFormatting implements FontFormatting { - private IndexedColorMap _colorMap; - private CTFont _font; - - /*package*/ XSSFFontFormatting(CTFont font, IndexedColorMap colorMap) { - _font = font; - _colorMap = colorMap; - } - - /** - * get the type of super or subscript for the font - * - * @return super or subscript option - * @see org.apache.poi.ss.usermodel.Font#SS_NONE - * @see org.apache.poi.ss.usermodel.Font#SS_SUPER - * @see org.apache.poi.ss.usermodel.Font#SS_SUB - */ - @Override - public short getEscapementType(){ - if(_font.sizeOfVertAlignArray() == 0) return org.apache.poi.ss.usermodel.Font.SS_NONE; - - CTVerticalAlignFontProperty prop = _font.getVertAlignArray(0); - return (short)(prop.getVal().intValue() - 1); - } - - /** - * set the escapement type for the font - * - * @param escapementType super or subscript option - * @see org.apache.poi.ss.usermodel.Font#SS_NONE - * @see org.apache.poi.ss.usermodel.Font#SS_SUPER - * @see org.apache.poi.ss.usermodel.Font#SS_SUB - */ - @Override - public void setEscapementType(short escapementType){ - _font.setVertAlignArray(null); - if(escapementType != org.apache.poi.ss.usermodel.Font.SS_NONE){ - _font.addNewVertAlign().setVal(STVerticalAlignRun.Enum.forInt(escapementType + 1)); - } - } - - /** - * XMLBeans and the XSD make this look like it can have multiple values, but it is maxOccurrs=1. - * Use get*Array(), it is much faster than get*List(). - * - * @see org.apache.poi.ss.usermodel.FontFormatting#isStruckout() - */ - @Override - public boolean isStruckout() { - return _font.sizeOfStrikeArray() > 0 && _font.getStrikeArray(0).getVal(); - } - - /** - * @return font color index - */ - @Override - public short getFontColorIndex(){ - if(_font.sizeOfColorArray() == 0) return -1; - - int idx = 0; - CTColor color = _font.getColorArray(0); - if(color.isSetIndexed()) idx = (int)color.getIndexed(); - return (short)idx; - } - - /** - * @param color font color index - */ - @Override - public void setFontColorIndex(short color){ - _font.setColorArray(null); - if(color != -1){ - _font.addNewColor().setIndexed(color); - } - } - - @Override - public XSSFColor getFontColor() { - if(_font.sizeOfColorArray() == 0) return null; - - return XSSFColor.from(_font.getColorArray(0), _colorMap); - } - - @Override - public void setFontColor(Color color) { - XSSFColor xcolor = XSSFColor.toXSSFColor(color); - if (xcolor == null) { - _font.getColorList().clear(); - } else if(_font.sizeOfColorArray() == 0) { - _font.addNewColor().setRgb(xcolor.getRGB()); - } else { - _font.setColorArray(0, xcolor.getCTColor()); - } - } - - /** - * gets the height of the font in 1/20th point units - * - * @return fontheight (in points/20); or -1 if not modified - */ - @Override - public int getFontHeight(){ - if(_font.sizeOfSzArray() == 0) return -1; - - CTFontSize sz = _font.getSzArray(0); - return (int)(20*sz.getVal()); - } - - /** - * Sets the height of the font in 1/20th point units - * - * @param height the height in twips (in points/20) - */ - @Override - public void setFontHeight(int height){ - _font.setSzArray(null); - if(height != -1){ - _font.addNewSz().setVal((double)height / 20); - } - } - - /** - * get the type of underlining for the font - * - * @return font underlining type - * - * @see Font#U_NONE - * @see Font#U_SINGLE - * @see Font#U_DOUBLE - * @see Font#U_SINGLE_ACCOUNTING - * @see Font#U_DOUBLE_ACCOUNTING - */ - @Override - public short getUnderlineType(){ - if(_font.sizeOfUArray() == 0) return Font.U_NONE; - CTUnderlineProperty u = _font.getUArray(0); - switch(u.getVal().intValue()){ - case STUnderlineValues.INT_SINGLE: return Font.U_SINGLE; - case STUnderlineValues.INT_DOUBLE: return Font.U_DOUBLE; - case STUnderlineValues.INT_SINGLE_ACCOUNTING: return Font.U_SINGLE_ACCOUNTING; - case STUnderlineValues.INT_DOUBLE_ACCOUNTING: return Font.U_DOUBLE_ACCOUNTING; - default: return Font.U_NONE; - } - } - - /** - * set the type of underlining type for the font - * - * @param underlineType super or subscript option - * - * @see Font#U_NONE - * @see Font#U_SINGLE - * @see Font#U_DOUBLE - * @see Font#U_SINGLE_ACCOUNTING - * @see Font#U_DOUBLE_ACCOUNTING - */ - @Override - public void setUnderlineType(short underlineType){ - _font.setUArray(null); - if(underlineType != Font.U_NONE){ - FontUnderline fenum = FontUnderline.valueOf(underlineType); - STUnderlineValues.Enum val = STUnderlineValues.Enum.forInt(fenum.getValue()); - _font.addNewU().setVal(val); - } - } - - /** - * get whether the font weight is set to bold or not - * - * @return bold - whether the font is bold or not - */ - @Override - public boolean isBold(){ - return _font.sizeOfBArray() == 1 && _font.getBArray(0).getVal(); - } - - /** - * @return true if font style was set to <i>italic</i> - */ - @Override - public boolean isItalic(){ - return _font.sizeOfIArray() == 1 && _font.getIArray(0).getVal(); - } - - /** - * set font style options. - * - * @param italic - if true, set posture style to italic, otherwise to normal - * @param bold if true, set font weight to bold, otherwise to normal - */ - @Override - public void setFontStyle(boolean italic, boolean bold){ - _font.setIArray(null); - _font.setBArray(null); - if(italic) _font.addNewI().setVal(true); - if(bold) _font.addNewB().setVal(true); - } - - /** - * set font style options to default values (non-italic, non-bold) - */ - @Override - public void resetFontStyle(){ - _font.set(CTFont.Factory.newInstance()); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java deleted file mode 100644 index ccd1799955..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFormulaEvaluator.java +++ /dev/null @@ -1,114 +0,0 @@ -/* ==================================================================== - 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.ss.formula.BaseFormulaEvaluator; -import org.apache.poi.ss.formula.EvaluationCell; -import org.apache.poi.ss.formula.IStabilityClassifier; -import org.apache.poi.ss.formula.WorkbookEvaluator; -import org.apache.poi.ss.formula.udf.UDFFinder; -import org.apache.poi.ss.usermodel.Cell; - -/** - * Evaluates formula cells.<p> - * - * For performance reasons, this class keeps a cache of all previously calculated intermediate - * cell values. Be sure to call {@link #clearAllCachedResultValues()} if any workbook cells are changed between - * calls to evaluate~ methods on this class. - */ -public final class XSSFFormulaEvaluator extends BaseXSSFFormulaEvaluator { - private final XSSFWorkbook _book; - - public XSSFFormulaEvaluator(XSSFWorkbook workbook) { - this(workbook, null, null); - } - private XSSFFormulaEvaluator(XSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) { - this(workbook, new WorkbookEvaluator(XSSFEvaluationWorkbook.create(workbook), stabilityClassifier, udfFinder)); - } - protected XSSFFormulaEvaluator(XSSFWorkbook workbook, WorkbookEvaluator bookEvaluator) { - super(bookEvaluator); - _book = workbook; - } - - /** - * @param stabilityClassifier used to optimise caching performance. Pass <code>null</code> - * for the (conservative) assumption that any cell may have its definition changed after - * evaluation begins. - * @param udfFinder pass <code>null</code> for default (AnalysisToolPak only) - */ - public static XSSFFormulaEvaluator create(XSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) { - return new XSSFFormulaEvaluator(workbook, stabilityClassifier, udfFinder); - } - - public void notifySetFormula(Cell cell) { - _bookEvaluator.notifyUpdateCell(new XSSFEvaluationCell((XSSFCell)cell)); - } - public void notifyDeleteCell(Cell cell) { - _bookEvaluator.notifyDeleteCell(new XSSFEvaluationCell((XSSFCell)cell)); - } - public void notifyUpdateCell(Cell cell) { - _bookEvaluator.notifyUpdateCell(new XSSFEvaluationCell((XSSFCell)cell)); - } - - /** - * Loops over all cells in all sheets of the supplied - * workbook. - * For cells that contain formulas, their formulas are - * evaluated, and the results are saved. These cells - * remain as formula cells. - * For cells that do not contain formulas, no changes - * are made. - * This is a helpful wrapper around looping over all - * cells, and calling evaluateFormulaCell on each one. - */ - public static void evaluateAllFormulaCells(XSSFWorkbook wb) { - BaseFormulaEvaluator.evaluateAllFormulaCells(wb); - } - - @Override - public XSSFCell evaluateInCell(Cell cell) { - return (XSSFCell) super.evaluateInCell(cell); - } - - /** - * Loops over all cells in all sheets of the supplied - * workbook. - * For cells that contain formulas, their formulas are - * evaluated, and the results are saved. These cells - * remain as formula cells. - * For cells that do not contain formulas, no changes - * are made. - * This is a helpful wrapper around looping over all - * cells, and calling evaluateFormulaCell on each one. - */ - public void evaluateAll() { - evaluateAllFormulaCells(_book, this); - } - - /** - * Turns a XSSFCell into a XSSFEvaluationCell - */ - protected EvaluationCell toEvaluationCell(Cell cell) { - if (!(cell instanceof XSSFCell)){ - throw new IllegalArgumentException("Unexpected type of cell: " + cell.getClass() + "." + - " Only XSSFCells can be evaluated."); - } - - return new XSSFEvaluationCell((XSSFCell)cell); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFGraphicFrame.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFGraphicFrame.java deleted file mode 100644 index 4a46f641a4..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFGraphicFrame.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * ==================================================================== - * 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 javax.xml.namespace.QName; - -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.util.Internal; -import org.apache.xmlbeans.XmlCursor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphicalObjectFrame; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGraphicalObjectFrameNonVisual; -import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * Represents DrawingML GraphicalObjectFrame. - * - * @author Roman Kashitsyn - */ -public final class XSSFGraphicFrame extends XSSFShape { - - private static CTGraphicalObjectFrame prototype; - - private CTGraphicalObjectFrame graphicFrame; - - /** - * Construct a new XSSFGraphicFrame object. - * - * @param drawing the XSSFDrawing that owns this frame - * @param ctGraphicFrame the XML bean that stores this frame content - */ - protected XSSFGraphicFrame(XSSFDrawing drawing, CTGraphicalObjectFrame ctGraphicFrame) { - this.drawing = drawing; // protected field on XSSFShape - this.graphicFrame = ctGraphicFrame; - // TODO: there may be a better way to delegate this - CTGraphicalObjectData graphicData = graphicFrame.getGraphic().getGraphicData(); - if (graphicData != null) { - NodeList nodes = graphicData.getDomNode().getChildNodes(); - for (int i = 0; i < nodes.getLength(); i++) { - final Node node = nodes.item(i); - // if the frame references a chart, associate the chart with this instance - if (node.getNodeName().equals("c:chart")) { - // this better succeed or the document is invalid - POIXMLDocumentPart relation = drawing.getRelationById(node.getAttributes().getNamedItem("r:id").getNodeValue()); - // Do XWPF charts need similar treatment? - if (relation instanceof XSSFChart) { - ((XSSFChart) relation).setGraphicFrame(this); - } - } - } - } - } - - @Internal - public CTGraphicalObjectFrame getCTGraphicalObjectFrame() { - return graphicFrame; - } - - /** - * Initialize default structure of a new graphic frame - */ - protected static CTGraphicalObjectFrame prototype() { - if (prototype == null) { - CTGraphicalObjectFrame graphicFrame = CTGraphicalObjectFrame.Factory.newInstance(); - - CTGraphicalObjectFrameNonVisual nvGraphic = graphicFrame.addNewNvGraphicFramePr(); - CTNonVisualDrawingProps props = nvGraphic.addNewCNvPr(); - props.setId(0); - props.setName("Diagramm 1"); - nvGraphic.addNewCNvGraphicFramePr(); - - CTTransform2D transform = graphicFrame.addNewXfrm(); - CTPositiveSize2D extPoint = transform.addNewExt(); - CTPoint2D offPoint = transform.addNewOff(); - - extPoint.setCx(0); - extPoint.setCy(0); - offPoint.setX(0); - offPoint.setY(0); - - /* CTGraphicalObject graphic = */ graphicFrame.addNewGraphic(); - - prototype = graphicFrame; - } - return prototype; - } - - /** - * Sets the frame macro. - */ - public void setMacro(String macro) { - graphicFrame.setMacro(macro); - } - - /** - * Sets the frame name. - */ - public void setName(String name) { - getNonVisualProperties().setName(name); - } - - /** - * Returns the frame name. - * @return name of the frame - */ - public String getName() { - return getNonVisualProperties().getName(); - } - - private CTNonVisualDrawingProps getNonVisualProperties() { - CTGraphicalObjectFrameNonVisual nvGraphic = graphicFrame.getNvGraphicFramePr(); - return nvGraphic.getCNvPr(); - } - - /** - * Attaches frame to an anchor. - */ - protected void setAnchor(XSSFClientAnchor anchor) { - this.anchor = anchor; - } - - /** - * Returns the frame anchor. - * @return the XSSFClientAnchor anchor this frame is attached to - */ - public XSSFClientAnchor getAnchor() { - return (XSSFClientAnchor) anchor; - } - - /** - * Assign a DrawingML chart to the graphic frame. - */ - protected void setChart(XSSFChart chart, String relId) { - CTGraphicalObjectData data = graphicFrame.getGraphic().addNewGraphicData(); - appendChartElement(data, relId); - chart.setGraphicFrame(this); - } - - /** - * Gets the frame id. - */ - public long getId() { - return graphicFrame.getNvGraphicFramePr().getCNvPr().getId(); - } - - /** - * Sets the frame id. - */ - protected void setId(long id) { - graphicFrame.getNvGraphicFramePr().getCNvPr().setId(id); - } - - /** - * The low level code to insert {@code <c:chart>} tag into - * {@code<a:graphicData>}. - * - * Here is the schema (ECMA-376): - * <pre> - * {@code - * <complexType name="CT_GraphicalObjectData"> - * <sequence> - * <any minOccurs="0" maxOccurs="unbounded" processContents="strict"/> - * </sequence> - * <attribute name="uri" type="xsd:token"/> - * </complexType> - * } - * </pre> - */ - private void appendChartElement(CTGraphicalObjectData data, String id) { - String r_namespaceUri = STRelationshipId.type.getName().getNamespaceURI(); - String c_namespaceUri = XSSFDrawing.NAMESPACE_C; - XmlCursor cursor = data.newCursor(); - cursor.toNextToken(); - cursor.beginElement(new QName(c_namespaceUri, "chart", "c")); - cursor.insertAttributeWithValue(new QName(r_namespaceUri, "id", "r"), id); - cursor.dispose(); - data.setUri(c_namespaceUri); - } - - @Override - protected CTShapeProperties getShapeProperties(){ - return null; - } - - @Override - public String getShapeName() { - return graphicFrame.getNvGraphicFramePr().getCNvPr().getName(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHeaderFooterProperties.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHeaderFooterProperties.java deleted file mode 100644 index af3f8c29fc..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHeaderFooterProperties.java +++ /dev/null @@ -1,144 +0,0 @@ -/* ==================================================================== - 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.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; - -/** - * <p> - * All Header/Footer properties for a sheet are scoped to the sheet. This includes Different First Page, - * and Different Even/Odd. These properties can be set or unset explicitly in this class. Note that while - * Scale With Document and Align With Margins default to unset, Different First, and Different Even/Odd - * are updated automatically as headers and footers are added and removed. - * </p> - */ -public class XSSFHeaderFooterProperties { - private CTHeaderFooter headerFooter; - - /** - * Create an instance of XSSFHeaderFooterProperties from the supplied XML bean - * - * @param headerFooter - */ - public XSSFHeaderFooterProperties(CTHeaderFooter headerFooter) { - this.headerFooter = headerFooter; - } - - /** - * Returns the underlying CTHeaderFooter xml bean - * - * @return the underlying CTHeaderFooter xml bean - */ - @Internal - public CTHeaderFooter getHeaderFooter() { - return this.headerFooter; - } - - /** - * returns alignWithMargins attribute - */ - public boolean getAlignWithMargins() { - return getHeaderFooter().isSetAlignWithMargins() ? getHeaderFooter().getAlignWithMargins() : false; - } - - /** - * returns differentFirst attribute - */ - public boolean getDifferentFirst() { - return getHeaderFooter().isSetDifferentFirst() ? getHeaderFooter().getDifferentFirst() : false; - } - - /** - * returns differentOddEven attribute - */ - public boolean getDifferentOddEven() { - return getHeaderFooter().isSetDifferentOddEven() ? getHeaderFooter().getDifferentOddEven() : false; - } - - /** - * returns scaleWithDoc attribute - */ - public boolean getScaleWithDoc() { - return getHeaderFooter().isSetScaleWithDoc() ? getHeaderFooter().getScaleWithDoc() : false; - } - - /** - * set alignWithMargins attribute - */ - public void setAlignWithMargins(boolean flag) { - getHeaderFooter().setAlignWithMargins(flag); - } - - /** - * set differentFirst attribute - */ - public void setDifferentFirst(boolean flag) { - getHeaderFooter().setDifferentFirst(flag); - } - - /** - * set differentOddEven attribute - */ - public void setDifferentOddEven(boolean flag) { - getHeaderFooter().setDifferentOddEven(flag); - } - - /** - * set scaleWithDoc attribute - */ - public void setScaleWithDoc(boolean flag) { - getHeaderFooter().setScaleWithDoc(flag); - } - - /** - * remove alignWithMargins attribute - */ - public void removeAlignWithMargins() { - if (getHeaderFooter().isSetAlignWithMargins()) { - getHeaderFooter().unsetAlignWithMargins(); - } - } - - /** - * remove differentFirst attribute - */ - public void removeDifferentFirst() { - if (getHeaderFooter().isSetDifferentFirst()) { - getHeaderFooter().unsetDifferentFirst(); - } - } - - /** - * remove differentOddEven attribute - */ - public void removeDifferentOddEven() { - if (getHeaderFooter().isSetDifferentOddEven()) { - getHeaderFooter().unsetDifferentOddEven(); - } - } - - /** - * remove scaleWithDoc attribute - */ - public void removeScaleWithDoc() { - if (getHeaderFooter().isSetScaleWithDoc()) { - getHeaderFooter().unsetScaleWithDoc(); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java deleted file mode 100644 index 1d13e688c5..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFHyperlink.java +++ /dev/null @@ -1,378 +0,0 @@ -/* ==================================================================== - 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 java.net.URI; -import java.net.URISyntaxException; - -import org.apache.poi.common.usermodel.HyperlinkType; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.ss.usermodel.Hyperlink; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.util.Internal; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink; - -/** - * XSSF Implementation of a Hyperlink. - * Note - unlike with HSSF, many kinds of hyperlink - * are largely stored as relations of the sheet - */ -public class XSSFHyperlink implements Hyperlink { - final private HyperlinkType _type; - final private PackageRelationship _externalRel; - final private CTHyperlink _ctHyperlink; //contains a reference to the cell where the hyperlink is anchored, getRef() - private String _location; //what the hyperlink refers to - - /** - * Create a new XSSFHyperlink. This method is protected to be used only by - * {@link XSSFCreationHelper#createHyperlink(HyperlinkType)}. - * - * @param type - the type of hyperlink to create - */ - protected XSSFHyperlink(HyperlinkType type) { - _type = type; - _ctHyperlink = CTHyperlink.Factory.newInstance(); - _externalRel = null; - } - - /** - * Create a XSSFHyperlink and initialize it from the supplied CTHyperlink bean and package relationship - * - * @param ctHyperlink the xml bean containing xml properties - * @param hyperlinkRel the relationship in the underlying OPC package which stores the actual link's address - */ - protected XSSFHyperlink(CTHyperlink ctHyperlink, PackageRelationship hyperlinkRel) { - _ctHyperlink = ctHyperlink; - _externalRel = hyperlinkRel; - - // Figure out the Hyperlink type and destination - - if (_externalRel == null) { - // If it has a location, it's internal - if (ctHyperlink.getLocation() != null) { - _type = HyperlinkType.DOCUMENT; - _location = ctHyperlink.getLocation(); - } else if (ctHyperlink.getId() != null) { - throw new IllegalStateException("The hyperlink for cell " - + ctHyperlink.getRef() + " references relation " - + ctHyperlink.getId() + ", but that didn't exist!"); - } else { - // hyperlink is internal and is not related to other parts - _type = HyperlinkType.DOCUMENT; - } - } else { - URI target = _externalRel.getTargetURI(); - _location = target.toString(); - if (ctHyperlink.getLocation() != null) { - // URI fragment - _location += "#" + ctHyperlink.getLocation(); - } - - // Try to figure out the type - if (_location.startsWith("http://") || _location.startsWith("https://") - || _location.startsWith("ftp://")) { - _type = HyperlinkType.URL; - } else if (_location.startsWith("mailto:")) { - _type = HyperlinkType.EMAIL; - } else { - _type = HyperlinkType.FILE; - } - } - - } - - /** - * Create a new XSSFHyperlink. This method is for Internal use only. - * XSSFHyperlinks can be created by {@link XSSFCreationHelper}. - * See the <a href="https://poi.apache.org/spreadsheet/quick-guide.html#Hyperlinks">spreadsheet quick-guide</a> - * for an example. - * - * @param other the hyperlink to copy - */ - @Internal //FIXME: change to protected if/when SXSSFHyperlink class is created - public XSSFHyperlink(Hyperlink other) { - if (other instanceof XSSFHyperlink) { - XSSFHyperlink xlink = (XSSFHyperlink) other; - _type = xlink.getType(); - _location = xlink._location; - _externalRel = xlink._externalRel; - _ctHyperlink = (CTHyperlink) xlink._ctHyperlink.copy(); - } - else { - _type = other.getType(); - _location = other.getAddress(); - _externalRel = null; - _ctHyperlink = CTHyperlink.Factory.newInstance(); - setCellReference(new CellReference(other.getFirstRow(), other.getFirstColumn())); - } - } - /** - * @return the underlying CTHyperlink object - */ - @Internal - public CTHyperlink getCTHyperlink() { - return _ctHyperlink; - } - - /** - * Do we need to a relation too, to represent - * this hyperlink? - */ - public boolean needsRelationToo() { - return (_type != HyperlinkType.DOCUMENT); - } - - /** - * Generates the relation if required - */ - protected void generateRelationIfNeeded(PackagePart sheetPart) { - if (_externalRel == null && needsRelationToo()) { - // Generate the relation - PackageRelationship rel = - sheetPart.addExternalRelationship(_location, XSSFRelation.SHEET_HYPERLINKS.getRelation()); - - // Update the r:id - _ctHyperlink.setId(rel.getId()); - } - } - - /** - * Return the type of this hyperlink - * - * @return the type of this hyperlink - */ - @Override - public HyperlinkType getType() { - return _type; - } - - /** - * Get the address of the cell this hyperlink applies to, e.g. A55 - */ - public String getCellRef() { - return _ctHyperlink.getRef(); - } - - /** - * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file. - * The is the hyperlink target. - * - * @return the address of this hyperlink - */ - @Override - public String getAddress() { - return _location; - } - - /** - * Return text label for this hyperlink - * - * @return text to display - */ - @Override - public String getLabel() { - return _ctHyperlink.getDisplay(); - } - - /** - * Location within target. If target is a workbook (or this workbook) this shall refer to a - * sheet and cell or a defined name. Can also be an HTML anchor if target is HTML file. - * - * @return location - */ - public String getLocation() { - return _ctHyperlink.getLocation(); - } - - /** - * Sets text label for this hyperlink - * - * @param label text label for this hyperlink - */ - @Override - public void setLabel(String label) { - _ctHyperlink.setDisplay(label); - } - - /** - * Location within target. If target is a workbook (or this workbook) this shall refer to a - * sheet and cell or a defined name. Can also be an HTML anchor if target is HTML file. - * - * @param location - string representing a location of this hyperlink - */ - public void setLocation(String location) { - _ctHyperlink.setLocation(location); - } - - /** - * Hyperlink address. Depending on the hyperlink type it can be URL, e-mail, path to a file - * This is the hyperlink target. - * - * @param address - the address of this hyperlink - */ - @Override - public void setAddress(String address) { - validate(address); - - _location = address; - //we must set location for internal hyperlinks - if (_type == HyperlinkType.DOCUMENT) { - setLocation(address); - } - } - - @SuppressWarnings("fall-through") - private void validate(String address) { - switch (_type) { - // email, path to file and url must be valid URIs - case EMAIL: - case FILE: - case URL: - try { - new URI(address); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Address of hyperlink must be a valid URI", e); - } - break; - case DOCUMENT: - // currently not evaluating anything. - break; - default: - throw new IllegalStateException("Invalid Hyperlink type: " + _type); - } - } - - /** - * Assigns this hyperlink to the given cell reference - */ - @Internal - public void setCellReference(String ref) { - _ctHyperlink.setRef(ref); - } - @Internal - public void setCellReference(CellReference ref) { - setCellReference(ref.formatAsString()); - } - - private CellReference buildCellReference() { - String ref = _ctHyperlink.getRef(); - if (ref == null) { - ref = "A1"; - } - return new CellReference(ref); - } - - - /** - * Return the column of the first cell that contains the hyperlink - * - * @return the 0-based column of the first cell that contains the hyperlink - */ - @Override - public int getFirstColumn() { - return buildCellReference().getCol(); - } - - - /** - * Return the column of the last cell that contains the hyperlink - * - * @return the 0-based column of the last cell that contains the hyperlink - */ - @Override - public int getLastColumn() { - return buildCellReference().getCol(); - } - - /** - * Return the row of the first cell that contains the hyperlink - * - * @return the 0-based row of the cell that contains the hyperlink - */ - @Override - public int getFirstRow() { - return buildCellReference().getRow(); - } - - - /** - * Return the row of the last cell that contains the hyperlink - * - * @return the 0-based row of the last cell that contains the hyperlink - */ - @Override - public int getLastRow() { - return buildCellReference().getRow(); - } - - /** - * Set the column of the first cell that contains the hyperlink - * - * @param col the 0-based column of the first cell that contains the hyperlink - */ - @Override - public void setFirstColumn(int col) { - setCellReference(new CellReference( getFirstRow(), col )); - } - - /** - * Set the column of the last cell that contains the hyperlink. - * For XSSF, a Hyperlink may only reference one cell - * - * @param col the 0-based column of the last cell that contains the hyperlink - */ - @Override - public void setLastColumn(int col) { - setFirstColumn(col); - } - - /** - * Set the row of the first cell that contains the hyperlink - * - * @param row the 0-based row of the first cell that contains the hyperlink - */ - @Override - public void setFirstRow(int row) { - setCellReference(new CellReference( row, getFirstColumn() )); - } - - /** - * Set the row of the last cell that contains the hyperlink. - * For XSSF, a Hyperlink may only reference one cell - * - * @param row the 0-based row of the last cell that contains the hyperlink - */ - @Override - public void setLastRow(int row) { - setFirstRow(row); - } - - /** - * @return additional text to help the user understand more about the hyperlink - */ - public String getTooltip() { - return _ctHyperlink.getTooltip(); - } - - /** - * @param text additional text to help the user understand more about the hyperlink - */ - public void setTooltip(String text) { - _ctHyperlink.setTooltip(text); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java deleted file mode 100644 index 29062ee06f..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * ==================================================================== - * 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.ss.usermodel.ConditionalFormattingThreshold; -import org.apache.poi.ss.usermodel.IconMultiStateFormatting; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIconSet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STIconSetType; - -/** - * High level representation for Icon / Multi-State Formatting - * component of Conditional Formatting settings - */ -public class XSSFIconMultiStateFormatting implements IconMultiStateFormatting { - CTIconSet _iconset; - - /*package*/ XSSFIconMultiStateFormatting(CTIconSet iconset){ - _iconset = iconset; - } - - public IconSet getIconSet() { - String set = _iconset.getIconSet().toString(); - return IconSet.byName(set); - } - public void setIconSet(IconSet set) { - STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(set.name); - _iconset.setIconSet(xIconSet); - } - - public boolean isIconOnly() { - if (_iconset.isSetShowValue()) - return !_iconset.getShowValue(); - return false; - } - public void setIconOnly(boolean only) { - _iconset.setShowValue(!only); - } - - public boolean isReversed() { - if (_iconset.isSetReverse()) - return _iconset.getReverse(); - return false; - } - public void setReversed(boolean reversed) { - _iconset.setReverse(reversed); - } - - public XSSFConditionalFormattingThreshold[] getThresholds() { - CTCfvo[] cfvos = _iconset.getCfvoArray(); - XSSFConditionalFormattingThreshold[] t = - new XSSFConditionalFormattingThreshold[cfvos.length]; - for (int i=0; i<cfvos.length; i++) { - t[i] = new XSSFConditionalFormattingThreshold(cfvos[i]); - } - return t; - } - public void setThresholds(ConditionalFormattingThreshold[] thresholds) { - CTCfvo[] cfvos = new CTCfvo[thresholds.length]; - for (int i=0; i<thresholds.length; i++) { - cfvos[i] = ((XSSFConditionalFormattingThreshold)thresholds[i]).getCTCfvo(); - } - _iconset.setCfvoArray(cfvos); - } - public XSSFConditionalFormattingThreshold createThreshold() { - return new XSSFConditionalFormattingThreshold(_iconset.addNewCfvo()); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFLineBreak.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFLineBreak.java deleted file mode 100644 index 99596992b9..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFLineBreak.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * ==================================================================== - * 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.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; - -class XSSFLineBreak extends XSSFTextRun { - private final CTTextCharacterProperties _brProps; - - XSSFLineBreak(CTRegularTextRun r, XSSFTextParagraph p, CTTextCharacterProperties brProps){ - super(r, p); - _brProps = brProps; - } - - @Override - protected CTTextCharacterProperties getRPr(){ - return _brProps; - } - - /** - * Always throws IllegalStateException. You cannot change text of a line break. - */ - public void setText(String text){ - throw new IllegalStateException("You cannot change text of a line break, it is always '\\n'"); - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFMap.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFMap.java deleted file mode 100644 index 17c12c195b..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFMap.java +++ /dev/null @@ -1,116 +0,0 @@ -/* ==================================================================== - 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 java.util.ArrayList; -import java.util.List; - -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.util.Internal; -import org.apache.poi.xssf.model.MapInfo; -import org.apache.poi.xssf.model.SingleXmlCells; -import org.apache.poi.xssf.usermodel.helpers.XSSFSingleXmlCell; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMap; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSchema; -import org.w3c.dom.Node; - -/** - * This class implements the Map element (Open Office XML Part 4: - * chapter 3.16.2) - * <p> - * This element contains all of the properties related to the XML map, - * and the behaviors expected during data refresh operations. - * - * @author Roberto Manicardi - */ - - -public class XSSFMap { - private CTMap ctMap; - private MapInfo mapInfo; - - public XSSFMap(CTMap ctMap, MapInfo mapInfo) { - this.ctMap = ctMap; - this.mapInfo = mapInfo; - } - - - @Internal - public CTMap getCtMap() { - return ctMap; - } - - @Internal - public CTSchema getCTSchema() { - String schemaId = ctMap.getSchemaID(); - return mapInfo.getCTSchemaById(schemaId); - } - - public Node getSchema() { - Node xmlSchema = null; - - CTSchema schema = getCTSchema(); - xmlSchema = schema.getDomNode().getFirstChild(); - - return xmlSchema; - } - - /** - * @return the list of Single Xml Cells that provide a map rule to this mapping. - */ - public List<XSSFSingleXmlCell> getRelatedSingleXMLCell() { - List<XSSFSingleXmlCell> relatedSimpleXmlCells = new ArrayList<>(); - - int sheetNumber = mapInfo.getWorkbook().getNumberOfSheets(); - for (int i = 0; i < sheetNumber; i++) { - XSSFSheet sheet = mapInfo.getWorkbook().getSheetAt(i); - for (POIXMLDocumentPart p : sheet.getRelations()) { - if (p instanceof SingleXmlCells) { - SingleXmlCells singleXMLCells = (SingleXmlCells) p; - for (XSSFSingleXmlCell cell : singleXMLCells.getAllSimpleXmlCell()) { - if (cell.getMapId() == ctMap.getID()) { - relatedSimpleXmlCells.add(cell); - } - } - } - } - } - return relatedSimpleXmlCells; - } - - /** - * @return the list of all Tables that provide a map rule to this mapping - */ - public List<XSSFTable> getRelatedTables() { - List<XSSFTable> tables = new ArrayList<>(); - for (Sheet sheet : mapInfo.getWorkbook()) { - for (RelationPart rp : ((XSSFSheet)sheet).getRelationParts()) { - if (rp.getRelationship().getRelationshipType().equals(XSSFRelation.TABLE.getRelation())) { - XSSFTable table = rp.getDocumentPart(); - if (table.mapsTo(ctMap.getID())) { - tables.add(table); - } - } - } - } - - return tables; - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java deleted file mode 100644 index 21300d47e3..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFName.java +++ /dev/null @@ -1,431 +0,0 @@ -/* ==================================================================== - 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.ss.SpreadsheetVersion; -import org.apache.poi.ss.formula.ptg.Ptg; - -import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.usermodel.Name; -import org.apache.poi.ss.util.AreaReference; -import org.apache.poi.ss.util.CellReference; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName; - -/** - * Represents a defined named range in a SpreadsheetML workbook. - * <p> - * Defined names are descriptive text that is used to represents a cell, range of cells, formula, or constant value. - * Use easy-to-understand names, such as Products, to refer to hard to understand ranges, such as <code>Sales!C20:C30</code>. - * </p> - * Example: - * <pre><blockquote> - * XSSFWorkbook wb = new XSSFWorkbook(); - * XSSFSheet sh = wb.createSheet("Sheet1"); - * - * //applies to the entire workbook - * XSSFName name1 = wb.createName(); - * name1.setNameName("FMLA"); - * name1.setRefersToFormula("Sheet1!$B$3"); - * - * //applies to Sheet1 - * XSSFName name2 = wb.createName(); - * name2.setNameName("SheetLevelName"); - * name2.setComment("This name is scoped to Sheet1"); - * name2.setLocalSheetId(0); - * name2.setRefersToFormula("Sheet1!$B$3"); - * - * </blockquote></pre> - * - * @author Nick Burch - * @author Yegor Kozlov - */ -public final class XSSFName implements Name { - - /** - * A built-in defined name that specifies the workbook's print area - */ - public static final String BUILTIN_PRINT_AREA = "_xlnm.Print_Area"; - - /** - * A built-in defined name that specifies the row(s) or column(s) to repeat - * at the top of each printed page. - */ - public static final String BUILTIN_PRINT_TITLE = "_xlnm.Print_Titles"; - - /** - * A built-in defined name that refers to a range containing the criteria values - * to be used in applying an advanced filter to a range of data - */ - public static final String BUILTIN_CRITERIA = "_xlnm.Criteria:"; - - - /** - * this defined name refers to the range containing the filtered - * output values resulting from applying an advanced filter criteria to a source - * range - */ - public static final String BUILTIN_EXTRACT = "_xlnm.Extract:"; - - /** - * ?an be one of the following - * <li> this defined name refers to a range to which an advanced filter has been - * applied. This represents the source data range, unfiltered. - * <li> This defined name refers to a range to which an AutoFilter has been - * applied - */ - public static final String BUILTIN_FILTER_DB = "_xlnm._FilterDatabase"; - - /** - * A built-in defined name that refers to a consolidation area - */ - public static final String BUILTIN_CONSOLIDATE_AREA = "_xlnm.Consolidate_Area"; - - /** - * A built-in defined name that specified that the range specified is from a database data source - */ - public static final String BUILTIN_DATABASE = "_xlnm.Database"; - - /** - * A built-in defined name that refers to a sheet title. - */ - public static final String BUILTIN_SHEET_TITLE = "_xlnm.Sheet_Title"; - - private XSSFWorkbook _workbook; - private CTDefinedName _ctName; - - /** - * Creates an XSSFName object - called internally by XSSFWorkbook. - * - * @param name - the xml bean that holds data represenring this defined name. - * @param workbook - the workbook object associated with the name - * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#createName() - */ - protected XSSFName(CTDefinedName name, XSSFWorkbook workbook) { - _workbook = workbook; - _ctName = name; - } - - /** - * Returns the underlying named range object - */ - protected CTDefinedName getCTName() { - return _ctName; - } - - /** - * Returns the name that will appear in the user interface for the defined name. - * - * @return text name of this defined name - */ - public String getNameName() { - return _ctName.getName(); - } - - /** - * Sets the name that will appear in the user interface for the defined name. - * Names must begin with a letter or underscore, not contain spaces and be unique across the workbook. - * - * <p> - * A name must always be unique within its scope. POI prevents you from defining a name that is not unique - * within its scope. However you can use the same name in different scopes. Example: - * <pre><blockquote> - * //by default names are workbook-global - * XSSFName name; - * name = workbook.createName(); - * name.setNameName("sales_08"); - * - * name = workbook.createName(); - * name.setNameName("sales_08"); //will throw an exception: "The workbook already contains this name (case-insensitive)" - * - * //create sheet-level name - * name = workbook.createName(); - * name.setSheetIndex(0); //the scope of the name is the first sheet - * name.setNameName("sales_08"); //ok - * - * name = workbook.createName(); - * name.setSheetIndex(0); - * name.setNameName("sales_08"); //will throw an exception: "The sheet already contains this name (case-insensitive)" - * - * </blockquote></pre> - * </p> - * @param name name of this defined name - * @throws IllegalArgumentException if the name is invalid or the workbook already contains this name (case-insensitive) - */ - public void setNameName(String name) { - validateName(name); - - String oldName = getNameName(); - int sheetIndex = getSheetIndex(); - //Check to ensure no other names have the same case-insensitive name at the same scope - for (XSSFName foundName : _workbook.getNames(name)) { - if (foundName.getSheetIndex() == sheetIndex && foundName != this) { - String msg = "The "+(sheetIndex == -1 ? "workbook" : "sheet")+" already contains this name: " + name; - throw new IllegalArgumentException(msg); - } - } - _ctName.setName(name); - //Need to update the name -> named ranges map - _workbook.updateName(this, oldName); - } - - public String getRefersToFormula() { - String result = _ctName.getStringValue(); - if (result == null || result.length() < 1) { - return null; - } - return result; - } - - public void setRefersToFormula(String formulaText) { - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(_workbook); - //validate through the FormulaParser - FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex(), -1); - - _ctName.setStringValue(formulaText); - } - - public boolean isDeleted(){ - String formulaText = getRefersToFormula(); - if (formulaText == null) { - return false; - } - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(_workbook); - Ptg[] ptgs = FormulaParser.parse(formulaText, fpb, FormulaType.NAMEDRANGE, getSheetIndex(), -1); - return Ptg.doesFormulaReferToDeletedCell(ptgs); - } - - /** - * Tell Excel that this name applies to the worksheet with the specified index instead of the entire workbook. - * - * @param index the sheet index this name applies to, -1 unsets this property making the name workbook-global - */ - public void setSheetIndex(int index) { - int lastSheetIx = _workbook.getNumberOfSheets() - 1; - if (index < -1 || index > lastSheetIx) { - throw new IllegalArgumentException("Sheet index (" + index +") is out of range" + - (lastSheetIx == -1 ? "" : (" (0.." + lastSheetIx + ")"))); - } - - if(index == -1) { - if(_ctName.isSetLocalSheetId()) _ctName.unsetLocalSheetId(); - } else { - _ctName.setLocalSheetId(index); - } - } - - /** - * Returns the sheet index this name applies to. - * - * @return the sheet index this name applies to, -1 if this name applies to the entire workbook - */ - public int getSheetIndex() { - return _ctName.isSetLocalSheetId() ? (int) _ctName.getLocalSheetId() : -1; - } - - /** - * Indicates that the defined name refers to a user-defined function. - * This attribute is used when there is an add-in or other code project associated with the file. - * - * @param value <code>true</code> indicates the name refers to a function. - */ - public void setFunction(boolean value) { - _ctName.setFunction(value); - } - - /** - * Indicates that the defined name refers to a user-defined function. - * This attribute is used when there is an add-in or other code project associated with the file. - * - * @return <code>true</code> indicates the name refers to a function. - */ - public boolean getFunction() { - return _ctName.getFunction(); - } - - /** - * Specifies the function group index if the defined name refers to a function. The function - * group defines the general category for the function. This attribute is used when there is - * an add-in or other code project associated with the file. - * - * @param functionGroupId the function group index that defines the general category for the function - */ - public void setFunctionGroupId(int functionGroupId) { - _ctName.setFunctionGroupId(functionGroupId); - } - - /** - * Returns the function group index if the defined name refers to a function. The function - * group defines the general category for the function. This attribute is used when there is - * an add-in or other code project associated with the file. - * - * @return the function group index that defines the general category for the function - */ - public int getFunctionGroupId() { - return (int) _ctName.getFunctionGroupId(); - } - - /** - * Get the sheets name which this named range is referenced to - * - * @return sheet name, which this named range referred to. - * Empty string if the referenced sheet name was not found. - */ - public String getSheetName() { - if (_ctName.isSetLocalSheetId()) { - // Given as explicit sheet id - int sheetId = (int)_ctName.getLocalSheetId(); - return _workbook.getSheetName(sheetId); - } - String ref = getRefersToFormula(); - AreaReference areaRef = new AreaReference(ref, SpreadsheetVersion.EXCEL2007); - return areaRef.getFirstCell().getSheetName(); - } - - /** - * Is the name refers to a user-defined function ? - * - * @return <code>true</code> if this name refers to a user-defined function - */ - public boolean isFunctionName() { - return getFunction(); - } - - /** - * Checks if this name is hidden, eg one of the built-in Excel - * internal names - * - * @return true if this name is a hidden one - */ - public boolean isHidden() { - return _ctName.getHidden(); - } - - /** - * Returns the comment the user provided when the name was created. - * - * @return the user comment for this named range - */ - public String getComment() { - return _ctName.getComment(); - } - - /** - * Specifies the comment the user provided when the name was created. - * - * @param comment the user comment for this named range - */ - public void setComment(String comment) { - _ctName.setComment(comment); - } - - @Override - public int hashCode() { - return _ctName.toString().hashCode(); - } - - /** - * Compares this name to the specified object. - * The result is <code>true</code> if the argument is XSSFName and the - * underlying CTDefinedName bean equals to the CTDefinedName representing this name - * - * @param o the object to compare this <code>XSSFName</code> against. - * @return <code>true</code> if the <code>XSSFName </code>are equal; - * <code>false</code> otherwise. - */ - @Override - public boolean equals(Object o) { - if(o == this) return true; - - if (!(o instanceof XSSFName)) return false; - - XSSFName cf = (XSSFName) o; - return _ctName.toString().equals(cf.getCTName().toString()); - } - - /** - * https://support.office.com/en-us/article/Define-and-use-names-in-formulas-4D0F13AC-53B7-422E-AFD2-ABD7FF379C64#bmsyntax_rules_for_names - * - * Valid characters: - * First character: { letter | underscore | backslash } - * Remaining characters: { letter | number | period | underscore } - * - * Cell shorthand: cannot be { "C" | "c" | "R" | "r" } - * - * Cell references disallowed: cannot be a cell reference $A$1 or R1C1 - * - * Spaces are not valid (follows from valid characters above) - * - * Name length: (XSSF-specific?) 255 characters maximum - * - * Case sensitivity: all names are case-insensitive - * - * Uniqueness: must be unique (for names with the same scope) - * - * @param name - */ - private static void validateName(String name) { - - if (name.length() == 0) { - throw new IllegalArgumentException("Name cannot be blank"); - } - if (name.length() > 255) { - throw new IllegalArgumentException("Invalid name: '"+name+"': cannot exceed 255 characters in length"); - } - if (name.equalsIgnoreCase("R") || name.equalsIgnoreCase("C")) { - throw new IllegalArgumentException("Invalid name: '"+name+"': cannot be special shorthand R or C"); - } - - // is first character valid? - char c = name.charAt(0); - String allowedSymbols = "_\\"; - boolean characterIsValid = (Character.isLetter(c) || allowedSymbols.indexOf(c) != -1); - if (!characterIsValid) { - throw new IllegalArgumentException("Invalid name: '"+name+"': first character must be underscore or a letter"); - } - - // are all other characters valid? - allowedSymbols = "_.\\"; //backslashes needed for unicode escape - for (final char ch : name.toCharArray()) { - characterIsValid = (Character.isLetterOrDigit(ch) || allowedSymbols.indexOf(ch) != -1); - if (!characterIsValid) { - throw new IllegalArgumentException("Invalid name: '"+name+"': name must be letter, digit, period, or underscore"); - } - } - - // Is the name a valid $A$1 cell reference - // Because $, :, and ! are disallowed characters, A1-style references become just a letter-number combination - if (name.matches("[A-Za-z]+\\d+")) { - String col = name.replaceAll("\\d", ""); - String row = name.replaceAll("[A-Za-z]", ""); - - try { - if (CellReference.cellReferenceIsWithinRange(col, row, SpreadsheetVersion.EXCEL2007)) { - throw new IllegalArgumentException("Invalid name: '"+name+"': cannot be $A$1-style cell reference"); - } - } catch (final NumberFormatException e) { - // row was not parseable as an Integer, such as a BigInt - // therefore name passes the not-a-cell-reference criteria - } - } - - // Is the name a valid R1C1 cell reference? - if (name.matches("[Rr]\\d+[Cc]\\d+")) { - throw new IllegalArgumentException("Invalid name: '"+name+"': cannot be R1C1-style cell reference"); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java deleted file mode 100644 index 16d04085f2..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFObjectData.java +++ /dev/null @@ -1,210 +0,0 @@ -/* ==================================================================== - 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 java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.xml.namespace.QName; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; -import org.apache.poi.poifs.filesystem.DirectoryEntry; -import org.apache.poi.poifs.filesystem.FileMagic; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.ss.usermodel.ObjectData; -import org.apache.poi.util.IOUtils; -import org.apache.xmlbeans.XmlCursor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtension; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtensionList; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOleObject; - -/** - * Represents binary object (i.e. OLE) data stored in the file. Eg. A GIF, JPEG etc... - */ -public class XSSFObjectData extends XSSFSimpleShape implements ObjectData { - private static final Logger LOG = LogManager.getLogger(XSSFObjectData.class); - - /** - * A default instance of CTShape used for creating new shapes. - */ - private static CTShape prototype; - - private CTOleObject oleObject; - - protected XSSFObjectData(XSSFDrawing drawing, CTShape ctShape) { - super(drawing, ctShape); - } - - /** - * Prototype with the default structure of a new auto-shape. - */ - /** - * Prototype with the default structure of a new auto-shape. - */ - protected static CTShape prototype() { - final String drawNS = "http://schemas.microsoft.com/office/drawing/2010/main"; - - if(prototype == null) { - CTShape shape = CTShape.Factory.newInstance(); - - CTShapeNonVisual nv = shape.addNewNvSpPr(); - CTNonVisualDrawingProps nvp = nv.addNewCNvPr(); - nvp.setId(1); - nvp.setName("Shape 1"); -// nvp.setHidden(true); - CTOfficeArtExtensionList extLst = nvp.addNewExtLst(); - // https://msdn.microsoft.com/en-us/library/dd911027(v=office.12).aspx - CTOfficeArtExtension ext = extLst.addNewExt(); - ext.setUri("{63B3BB69-23CF-44E3-9099-C40C66FF867C}"); - XmlCursor cur = ext.newCursor(); - cur.toEndToken(); - cur.beginElement(new QName(drawNS, "compatExt", "a14")); - cur.insertNamespace("a14", drawNS); - cur.insertAttributeWithValue("spid", "_x0000_s1"); - cur.dispose(); - - nv.addNewCNvSpPr(); - - CTShapeProperties sp = shape.addNewSpPr(); - CTTransform2D t2d = sp.addNewXfrm(); - CTPositiveSize2D p1 = t2d.addNewExt(); - p1.setCx(0); - p1.setCy(0); - CTPoint2D p2 = t2d.addNewOff(); - p2.setX(0); - p2.setY(0); - - CTPresetGeometry2D geom = sp.addNewPrstGeom(); - geom.setPrst(STShapeType.RECT); - geom.addNewAvLst(); - - prototype = shape; - } - return prototype; - } - - - - - @Override - public String getOLE2ClassName() { - return getOleObject().getProgId(); - } - - /** - * @return the CTOleObject associated with the shape - */ - public CTOleObject getOleObject() { - if (oleObject == null) { - long shapeId = getCTShape().getNvSpPr().getCNvPr().getId(); - oleObject = getSheet().readOleObject(shapeId); - if (oleObject == null) { - throw new POIXMLException("Ole object not found in sheet container - it's probably a control element"); - } - } - return oleObject; - } - - @Override - public byte[] getObjectData() throws IOException { - InputStream is = getObjectPart().getInputStream(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - IOUtils.copy(is, bos); - is.close(); - return bos.toByteArray(); - } - - /** - * @return the package part of the object data - */ - public PackagePart getObjectPart() { - if (!getOleObject().isSetId()) { - throw new POIXMLException("Invalid ole object found in sheet container"); - } - POIXMLDocumentPart pdp = getSheet().getRelationById(getOleObject().getId()); - return (pdp == null) ? null : pdp.getPackagePart(); - } - - @Override - public boolean hasDirectoryEntry() { - InputStream is = null; - try { - is = getObjectPart().getInputStream(); - is = FileMagic.prepareToCheckMagic(is); - return FileMagic.valueOf(is) == FileMagic.OLE2; - } catch (IOException e) { - LOG.atWarn().withThrowable(e).log("can't determine if directory entry exists"); - return false; - } finally { - IOUtils.closeQuietly(is); - } - } - - @Override - public DirectoryEntry getDirectory() throws IOException { - try (InputStream is = getObjectPart().getInputStream()) { - return new POIFSFileSystem(is).getRoot(); - } - } - - /** - * The filename of the embedded image - */ - @Override - public String getFileName() { - return getObjectPart().getPartName().getName(); - } - - protected XSSFSheet getSheet() { - return (XSSFSheet)getDrawing().getParent(); - } - - @Override - public XSSFPictureData getPictureData() { - XmlCursor cur = getOleObject().newCursor(); - try { - if (cur.toChild(XSSFRelation.NS_SPREADSHEETML, "objectPr")) { - String blipId = cur.getAttributeText(new QName(PackageRelationshipTypes.CORE_PROPERTIES_ECMA376_NS, "id")); - return (XSSFPictureData)getSheet().getRelationById(blipId); - } - return null; - } finally { - cur.dispose(); - } - } - - @Override - public String getContentType() { - return getObjectPart().getContentType(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFOddFooter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFOddFooter.java deleted file mode 100644 index 1e2239d8d3..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFOddFooter.java +++ /dev/null @@ -1,63 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.Footer; -import org.apache.poi.xssf.usermodel.extensions.XSSFHeaderFooter; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; - -/** - * Odd page footer value. Corresponds to odd printed pages. - * Odd page(s) in the sheet may not be printed, for example, if the print area is specified to be - * a range such that it falls outside an odd page's scope. - * - */ -public class XSSFOddFooter extends XSSFHeaderFooter implements Footer{ - - /** - * Create an instance of XSSFOddFooter from the supplied XML bean - * @see XSSFSheet#getOddFooter() - * @param headerFooter - */ - protected XSSFOddFooter(CTHeaderFooter headerFooter) { - super(headerFooter); - } - - /** - * Get the content text representing the footer - * @return text - */ - @Override - public String getText() { - return getHeaderFooter().getOddFooter(); - } - - /** - * Set a text for the footer. If null unset the value. - * @see XSSFHeaderFooter to see how to create a string with Header/Footer Formatting Syntax - * @param text - a string representing the footer. - */ - @Override - public void setText(String text) { - if(text == null) { - getHeaderFooter().unsetOddFooter(); - } else { - getHeaderFooter().setOddFooter(text); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFOddHeader.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFOddHeader.java deleted file mode 100644 index 1cce6e59be..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFOddHeader.java +++ /dev/null @@ -1,63 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.Header; -import org.apache.poi.xssf.usermodel.extensions.XSSFHeaderFooter; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; - -/** - * Odd page header value. Corresponds to odd printed pages. - * Odd page(s) in the sheet may not be printed, for example, if the print area is specified to be - * a range such that it falls outside an odd page's scope. - * - */ -public class XSSFOddHeader extends XSSFHeaderFooter implements Header{ - - /** - * Create an instance of XSSFOddHeader from the supplied XML bean - * @see XSSFSheet#getOddHeader() - * @param headerFooter - */ - protected XSSFOddHeader(CTHeaderFooter headerFooter) { - super(headerFooter); - } - - /** - * Get the content text representing this header - * @return text - */ - @Override - public String getText() { - return getHeaderFooter().getOddHeader(); - } - - /** - * Set a text for the header. If null unset the value - * @see XSSFHeaderFooter to see how to create a string with Header/Footer Formatting Syntax - * @param text - a string representing the header. - */ - @Override - public void setText(String text) { - if(text == null) { - getHeaderFooter().unsetOddHeader(); - } else { - getHeaderFooter().setOddHeader(text); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPatternFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPatternFormatting.java deleted file mode 100644 index 0f191c28f2..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPatternFormatting.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * ==================================================================== - * 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.ss.usermodel.Color; -import org.apache.poi.ss.usermodel.PatternFormatting; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPatternFill; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; - -/** - * @author Yegor Kozlov - */ -public class XSSFPatternFormatting implements PatternFormatting { - IndexedColorMap _colorMap; - CTFill _fill; - - XSSFPatternFormatting(CTFill fill, IndexedColorMap colorMap) { - _fill = fill; - _colorMap = colorMap; - } - - public XSSFColor getFillBackgroundColorColor() { - if(!_fill.isSetPatternFill()) return null; - return XSSFColor.from(_fill.getPatternFill().getBgColor(), _colorMap); - } - public XSSFColor getFillForegroundColorColor() { - if(!_fill.isSetPatternFill() || ! _fill.getPatternFill().isSetFgColor()) - return null; - return XSSFColor.from(_fill.getPatternFill().getFgColor(), _colorMap); - } - - public short getFillPattern() { - if(!_fill.isSetPatternFill() || !_fill.getPatternFill().isSetPatternType()) return NO_FILL; - - return (short)(_fill.getPatternFill().getPatternType().intValue() - 1); - } - - public short getFillBackgroundColor() { - XSSFColor color = getFillBackgroundColorColor(); - if (color == null) return 0; - return color.getIndexed(); - } - public short getFillForegroundColor() { - XSSFColor color = getFillForegroundColorColor(); - if (color == null) return 0; - return color.getIndexed(); - } - - public void setFillBackgroundColor(Color bg) { - XSSFColor xcolor = XSSFColor.toXSSFColor(bg); - if (xcolor == null) setFillBackgroundColor((CTColor)null); - else setFillBackgroundColor(xcolor.getCTColor()); - } - public void setFillBackgroundColor(short bg) { - CTColor bgColor = CTColor.Factory.newInstance(); - bgColor.setIndexed(bg); - setFillBackgroundColor(bgColor); - } - private void setFillBackgroundColor(CTColor color) { - CTPatternFill ptrn = _fill.isSetPatternFill() ? _fill.getPatternFill() : _fill.addNewPatternFill(); - if (color == null) { - ptrn.unsetBgColor(); - } else { - ptrn.setBgColor(color); - } - } - - public void setFillForegroundColor(Color fg) { - XSSFColor xcolor = XSSFColor.toXSSFColor(fg); - if (xcolor == null) setFillForegroundColor((CTColor)null); - else setFillForegroundColor(xcolor.getCTColor()); - } - public void setFillForegroundColor(short fg) { - CTColor fgColor = CTColor.Factory.newInstance(); - fgColor.setIndexed(fg); - setFillForegroundColor(fgColor); - } - private void setFillForegroundColor(CTColor color) { - CTPatternFill ptrn = _fill.isSetPatternFill() ? _fill.getPatternFill() : _fill.addNewPatternFill(); - if (color == null) { - ptrn.unsetFgColor(); - } else { - ptrn.setFgColor(color); - } - } - - public void setFillPattern(short fp){ - CTPatternFill ptrn = _fill.isSetPatternFill() ? _fill.getPatternFill() : _fill.addNewPatternFill(); - if(fp == NO_FILL) ptrn.unsetPatternType(); - else ptrn.setPatternType(STPatternType.Enum.forInt(fp + 1)); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java deleted file mode 100644 index 86f3bd917b..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java +++ /dev/null @@ -1,295 +0,0 @@ -/* ==================================================================== - 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 java.awt.Dimension; -import java.io.IOException; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.ss.usermodel.Picture; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.ImageUtils; -import org.apache.poi.util.Internal; -import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualPictureProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTPicture; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTPictureNonVisual; - -/** - * Represents a picture shape in a SpreadsheetML drawing. - * - * @author Yegor Kozlov - */ -public final class XSSFPicture extends XSSFShape implements Picture { - private static final Logger LOG = LogManager.getLogger(XSSFPicture.class); - - /** - * Column width measured as the number of characters of the maximum digit width of the - * numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin - * padding (two on each side), plus 1 pixel padding for the gridlines. - * - * This value is the same for default font in Office 2007 (Calibri) and Office 2003 and earlier (Arial) - */ - // private static float DEFAULT_COLUMN_WIDTH = 9.140625f; - - /** - * A default instance of CTShape used for creating new shapes. - */ - private static CTPicture prototype; - - /** - * This object specifies a picture object and all its properties - */ - private CTPicture ctPicture; - - /** - * Construct a new XSSFPicture object. This constructor is called from - * {@link XSSFDrawing#createPicture(XSSFClientAnchor, int)} - * - * @param drawing the XSSFDrawing that owns this picture - */ - protected XSSFPicture(XSSFDrawing drawing, CTPicture ctPicture){ - this.drawing = drawing; - this.ctPicture = ctPicture; - } - - /** - * Returns a prototype that is used to construct new shapes - * - * @return a prototype that is used to construct new shapes - */ - protected static CTPicture prototype(){ - if(prototype == null) { - CTPicture pic = CTPicture.Factory.newInstance(); - CTPictureNonVisual nvpr = pic.addNewNvPicPr(); - CTNonVisualDrawingProps nvProps = nvpr.addNewCNvPr(); - nvProps.setId(1); - nvProps.setName("Picture 1"); - nvProps.setDescr("Picture"); - CTNonVisualPictureProperties nvPicProps = nvpr.addNewCNvPicPr(); - nvPicProps.addNewPicLocks().setNoChangeAspect(true); - - CTBlipFillProperties blip = pic.addNewBlipFill(); - blip.addNewBlip().setEmbed(""); - blip.addNewStretch().addNewFillRect(); - - CTShapeProperties sppr = pic.addNewSpPr(); - CTTransform2D t2d = sppr.addNewXfrm(); - CTPositiveSize2D ext = t2d.addNewExt(); - //should be original picture width and height expressed in EMUs - ext.setCx(0); - ext.setCy(0); - - CTPoint2D off = t2d.addNewOff(); - off.setX(0); - off.setY(0); - - CTPresetGeometry2D prstGeom = sppr.addNewPrstGeom(); - prstGeom.setPrst(STShapeType.RECT); - prstGeom.addNewAvLst(); - - prototype = pic; - } - return prototype; - } - - /** - * Link this shape with the picture data - * - * @param rel relationship referring the picture data - */ - protected void setPictureReference(PackageRelationship rel){ - ctPicture.getBlipFill().getBlip().setEmbed(rel.getId()); - } - - /** - * Return the underlying CTPicture bean that holds all properties for this picture - * - * @return the underlying CTPicture bean - */ - @Internal - public CTPicture getCTPicture(){ - return ctPicture; - } - - /** - * Reset the image to the dimension of the embedded image - * - * @see #resize(double, double) - */ - public void resize(){ - resize(Double.MAX_VALUE); - } - - /** - * Resize the image proportionally. - * - * @see #resize(double, double) - */ - public void resize(double scale) { - resize(scale, scale); - } - - /** - * Resize the image relatively to its current size. - * <p> - * Please note, that this method works correctly only for workbooks - * with the default font size (Calibri 11pt for .xlsx). - * If the default font is changed the resized image can be streched vertically or horizontally. - * </p> - * <p> - * <code>resize(1.0,1.0)</code> keeps the original size,<br> - * <code>resize(0.5,0.5)</code> resize to 50% of the original,<br> - * <code>resize(2.0,2.0)</code> resizes to 200% of the original.<br> - * <code>resize({@link Double#MAX_VALUE},{@link Double#MAX_VALUE})</code> resizes to the dimension of the embedded image. - * </p> - * - * @param scaleX the amount by which the image width is multiplied relative to the original width, - * when set to {@link Double#MAX_VALUE} the width of the embedded image is used - * @param scaleY the amount by which the image height is multiplied relative to the original height, - * when set to {@link Double#MAX_VALUE} the height of the embedded image is used - */ - public void resize(double scaleX, double scaleY){ - XSSFClientAnchor anchor = getClientAnchor(); - XSSFClientAnchor pref = getPreferredSize(scaleX,scaleY); - if (anchor == null || pref == null) { - LOG.atWarn().log("picture is not anchored via client anchor - ignoring resize call"); - return; - } - - int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1()); - int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1()); - - anchor.setCol2(col2); - // anchor.setDx1(0); - anchor.setDx2(pref.getDx2()); - - anchor.setRow2(row2); - // anchor.setDy1(0); - anchor.setDy2(pref.getDy2()); - } - - /** - * Calculate the preferred size for this picture. - * - * @return XSSFClientAnchor with the preferred size for this image - */ - public XSSFClientAnchor getPreferredSize(){ - return getPreferredSize(1); - } - - /** - * Calculate the preferred size for this picture. - * - * @param scale the amount by which image dimensions are multiplied relative to the original size. - * @return XSSFClientAnchor with the preferred size for this image - */ - public XSSFClientAnchor getPreferredSize(double scale){ - return getPreferredSize(scale, scale); - } - - /** - * Calculate the preferred size for this picture. - * - * @param scaleX the amount by which image width is multiplied relative to the original width. - * @param scaleY the amount by which image height is multiplied relative to the original height. - * @return XSSFClientAnchor with the preferred size for this image - */ - public XSSFClientAnchor getPreferredSize(double scaleX, double scaleY){ - Dimension dim = ImageUtils.setPreferredSize(this, scaleX, scaleY); - CTPositiveSize2D size2d = ctPicture.getSpPr().getXfrm().getExt(); - size2d.setCx((int)dim.getWidth()); - size2d.setCy((int)dim.getHeight()); - return getClientAnchor(); - } - - /** - * Return the dimension of this image - * - * @param part the package part holding raw picture data - * @param type type of the picture: {@link Workbook#PICTURE_TYPE_JPEG}, - * {@link Workbook#PICTURE_TYPE_PNG} or {@link Workbook#PICTURE_TYPE_DIB} - * - * @return image dimension in pixels - */ - protected static Dimension getImageDimension(PackagePart part, int type){ - try { - return ImageUtils.getImageDimension(part.getInputStream(), type); - } catch (IOException e){ - //return a "singulariry" if ImageIO failed to read the image - LOG.atWarn().withThrowable(e).log("Failed to read image"); - return new Dimension(); - } - } - - /** - * Return the dimension of the embedded image in pixel - * - * @return image dimension in pixels - */ - public Dimension getImageDimension() { - XSSFPictureData picData = getPictureData(); - return getImageDimension(picData.getPackagePart(), picData.getPictureType()); - } - - /** - * Return picture data for this shape - * - * @return picture data for this shape - */ - public XSSFPictureData getPictureData() { - String blipId = ctPicture.getBlipFill().getBlip().getEmbed(); - return (XSSFPictureData)getDrawing().getRelationById(blipId); - } - - protected CTShapeProperties getShapeProperties(){ - return ctPicture.getSpPr(); - } - - /** - * @return the anchor that is used by this shape. - */ - @Override - public XSSFClientAnchor getClientAnchor() { - XSSFAnchor a = getAnchor(); - return (a instanceof XSSFClientAnchor) ? (XSSFClientAnchor)a : null; - } - - /** - * @return the sheet which contains the picture shape - */ - @Override - public XSSFSheet getSheet() { - return (XSSFSheet)getDrawing().getParent(); - } - - @Override - public String getShapeName() { - return ctPicture.getNvPicPr().getCNvPr().getName(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPictureData.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPictureData.java deleted file mode 100644 index ecdb1de04c..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPictureData.java +++ /dev/null @@ -1,140 +0,0 @@ -/* ==================================================================== - 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 java.io.IOException; - -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.ooxml.POIXMLRelation; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.ss.usermodel.PictureData; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.util.IOUtils; - -/** - * Raw picture data, normally attached to a SpreadsheetML Drawing. - * As a rule, pictures are stored in the /xl/media/ part of a SpreadsheetML package. - */ -public class XSSFPictureData extends POIXMLDocumentPart implements PictureData { - - /** - * Relationships for each known picture type - */ - protected static final POIXMLRelation[] RELATIONS; - static { - RELATIONS = new POIXMLRelation[13]; - RELATIONS[Workbook.PICTURE_TYPE_EMF] = XSSFRelation.IMAGE_EMF; - RELATIONS[Workbook.PICTURE_TYPE_WMF] = XSSFRelation.IMAGE_WMF; - RELATIONS[Workbook.PICTURE_TYPE_PICT] = XSSFRelation.IMAGE_PICT; - RELATIONS[Workbook.PICTURE_TYPE_JPEG] = XSSFRelation.IMAGE_JPEG; - RELATIONS[Workbook.PICTURE_TYPE_PNG] = XSSFRelation.IMAGE_PNG; - RELATIONS[Workbook.PICTURE_TYPE_DIB] = XSSFRelation.IMAGE_DIB; - RELATIONS[XSSFWorkbook.PICTURE_TYPE_GIF] = XSSFRelation.IMAGE_GIF; - RELATIONS[XSSFWorkbook.PICTURE_TYPE_TIFF] = XSSFRelation.IMAGE_TIFF; - RELATIONS[XSSFWorkbook.PICTURE_TYPE_EPS] = XSSFRelation.IMAGE_EPS; - RELATIONS[XSSFWorkbook.PICTURE_TYPE_BMP] = XSSFRelation.IMAGE_BMP; - RELATIONS[XSSFWorkbook.PICTURE_TYPE_WPG] = XSSFRelation.IMAGE_WPG; - } - - /** - * Create a new XSSFPictureData node - * - * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#addPicture(byte[], int) - */ - protected XSSFPictureData() { - super(); - } - - /** - * Construct XSSFPictureData from a package part - * - * @param part the package part holding the drawing data, - * - * @since POI 3.14-Beta1 - */ - protected XSSFPictureData(PackagePart part) { - super(part); - } - - /** - * Gets the picture data as a byte array. - * <p> - * Note, that this call might be expensive since all the picture data is copied into a temporary byte array. - * You can grab the picture data directly from the underlying package part as follows: - * <br> - * <code> - * InputStream is = getPackagePart().getInputStream(); - * </code> - * </p> - * - * @return the picture data. - */ - public byte[] getData() { - try { - return IOUtils.toByteArray(getPackagePart().getInputStream()); - } catch(IOException e) { - throw new POIXMLException(e); - } - } - - /** - * Suggests a file extension for this image. - * - * @return the file extension. - */ - public String suggestFileExtension() { - return getPackagePart().getPartName().getExtension(); - } - - /** - * Return an integer constant that specifies type of this picture - * - * @return an integer constant that specifies type of this picture - * @see org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_EMF - * @see org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_WMF - * @see org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_PICT - * @see org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_JPEG - * @see org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_PNG - * @see org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_DIB - */ - public int getPictureType(){ - String contentType = getPackagePart().getContentType(); - for (int i = 0; i < RELATIONS.length; i++) { - if(RELATIONS[i] == null) continue; - - if(RELATIONS[i].getContentType().equals(contentType)){ - return i; - } - } - return 0; - } - - public String getMimeType() { - return getPackagePart().getContentType(); - } - - /** - * *PictureData objects store the actual content in the part directly without keeping a - * copy like all others therefore we need to handle them differently. - */ - @Override - protected void prepareForCommit() { - // do not clear the part here - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCache.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCache.java deleted file mode 100644 index 2f5888976a..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCache.java +++ /dev/null @@ -1,77 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.util.Beta; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCache; - -public class XSSFPivotCache extends POIXMLDocumentPart { - - private CTPivotCache ctPivotCache; - - @Beta - public XSSFPivotCache(){ - super(); - ctPivotCache = CTPivotCache.Factory.newInstance(); - } - - @Beta - public XSSFPivotCache(CTPivotCache ctPivotCache) { - super(); - this.ctPivotCache = ctPivotCache; - } - - /** - * Creates n XSSFPivotCache 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 cache definition. - * - * @since POI 3.14-Beta1 - */ - @Beta - protected XSSFPivotCache(PackagePart part) throws IOException { - super(part); - readFrom(part.getInputStream()); - } - - @Beta - protected void readFrom(InputStream is) throws IOException { - try { - XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); - //Removing root element - options.setLoadReplaceDocumentElement(null); - ctPivotCache = CTPivotCache.Factory.parse(is, options); - } catch (XmlException e) { - throw new IOException(e.getLocalizedMessage()); - } - } - - @Beta - public CTPivotCache getCTPivotCache() { - return ctPivotCache; - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java deleted file mode 100644 index 540494c35f..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java +++ /dev/null @@ -1,186 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Date; - -import javax.xml.namespace.QName; - -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.ss.SpreadsheetVersion; -import org.apache.poi.ss.usermodel.Name; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -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.CTCacheField; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCacheFields; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCacheDefinition; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheetSource; - -public class XSSFPivotCacheDefinition extends POIXMLDocumentPart{ - - private CTPivotCacheDefinition ctPivotCacheDefinition; - - @Beta - public XSSFPivotCacheDefinition(){ - super(); - ctPivotCacheDefinition = CTPivotCacheDefinition.Factory.newInstance(); - createDefaultValues(); - } - - /** - * Creates an XSSFPivotCacheDefintion 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 cache definition. - * - * @since POI 3.14-Beta1 - */ - @Beta - protected XSSFPivotCacheDefinition(PackagePart part) throws IOException { - super(part); - readFrom(part.getInputStream()); - } - - @Beta - public void readFrom(InputStream is) throws IOException { - try { - XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); - //Removing root element - options.setLoadReplaceDocumentElement(null); - ctPivotCacheDefinition = CTPivotCacheDefinition.Factory.parse(is, options); - } catch (XmlException e) { - throw new IOException(e.getLocalizedMessage(), e); - } - } - - @Beta - @Internal - public CTPivotCacheDefinition getCTPivotCacheDefinition() { - return ctPivotCacheDefinition; - } - - @Beta - private void createDefaultValues() { - ctPivotCacheDefinition.setCreatedVersion(XSSFPivotTable.CREATED_VERSION); - ctPivotCacheDefinition.setMinRefreshableVersion(XSSFPivotTable.MIN_REFRESHABLE_VERSION); - ctPivotCacheDefinition.setRefreshedVersion(XSSFPivotTable.UPDATED_VERSION); - ctPivotCacheDefinition.setRefreshedBy("Apache POI"); - ctPivotCacheDefinition.setRefreshedDate(new Date().getTime()); - ctPivotCacheDefinition.setRefreshOnLoad(true); - } - - @Beta - @Override - protected void commit() throws IOException { - PackagePart part = getPackagePart(); - OutputStream out = part.getOutputStream(); - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - //Sets the pivotCacheDefinition tag - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTPivotCacheDefinition.type.getName(). - getNamespaceURI(), "pivotCacheDefinition")); - ctPivotCacheDefinition.save(out, xmlOptions); - out.close(); - } - - /** - * Find the 2D base data area for the pivot table, either from its direct reference or named table/range. - * @return AreaReference representing the current area defined by the pivot table - * @throws IllegalArgumentException if the ref attribute is not contiguous or the name attribute is not found. - */ - @Beta - public AreaReference getPivotArea(Workbook wb) throws IllegalArgumentException { - final CTWorksheetSource wsSource = ctPivotCacheDefinition.getCacheSource().getWorksheetSource(); - - final String ref = wsSource.getRef(); - final String name = wsSource.getName(); - - if (ref == null && name == null) { - throw new IllegalArgumentException("Pivot cache must reference an area, named range, or table."); - } - - // this is the XML format, so tell the reference that. - if (ref != null) { - return new AreaReference(ref, SpreadsheetVersion.EXCEL2007); - } - - assert (name != null); - - // named range or table? - final Name range = wb.getName(name); - if (range != null) { - return new AreaReference(range.getRefersToFormula(), SpreadsheetVersion.EXCEL2007); - } - - // not a named range, check for a table. - // do this second, as tables are sheet-specific, but named ranges are not, and may not have a sheet name given. - final XSSFSheet sheet = (XSSFSheet) wb.getSheet(wsSource.getSheet()); - for (XSSFTable table : sheet.getTables()) { - // TODO: case-sensitive? - if (name.equals(table.getName())) { - return new AreaReference(table.getStartCellReference(), table.getEndCellReference(), - SpreadsheetVersion.EXCEL2007); - } - } - - throw new IllegalArgumentException("Name '" + name + "' was not found."); - } - - /** - * Generates a cache field for each column in the reference area for the pivot table. - * @param sheet The sheet where the data i collected from - */ - @Beta - protected void createCacheFields(Sheet sheet) { - //Get values for start row, start and end column - AreaReference ar = getPivotArea(sheet.getWorkbook()); - CellReference firstCell = ar.getFirstCell(); - CellReference lastCell = ar.getLastCell(); - int columnStart = firstCell.getCol(); - int columnEnd = lastCell.getCol(); - Row row = sheet.getRow(firstCell.getRow()); - CTCacheFields cFields; - if(ctPivotCacheDefinition.getCacheFields() != null) { - cFields = ctPivotCacheDefinition.getCacheFields(); - } else { - cFields = ctPivotCacheDefinition.addNewCacheFields(); - } - //For each column, create a cache field and give it en empty sharedItems - for(int i=columnStart; i<=columnEnd; i++) { - CTCacheField cf = cFields.addNewCacheField(); - if(i==columnEnd){ - cFields.setCount(cFields.sizeOfCacheFieldArray()); - } - //General number format - cf.setNumFmtId(0); - cf.setName(row.getCell(i).getStringCellValue()); - cf.addNewSharedItems(); - } - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheRecords.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheRecords.java deleted file mode 100644 index d45f6c6a18..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheRecords.java +++ /dev/null @@ -1,88 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import javax.xml.namespace.QName; - -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.openxml4j.opc.PackagePart; -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.CTPivotCacheRecords; - -public class XSSFPivotCacheRecords extends POIXMLDocumentPart { - private CTPivotCacheRecords ctPivotCacheRecords; - - @Beta - public XSSFPivotCacheRecords() { - super(); - ctPivotCacheRecords = CTPivotCacheRecords.Factory.newInstance(); - } - - /** - * Creates an XSSFPivotCacheRecords 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 cache records. - * - * @since POI 3.14-Beta1 - */ - @Beta - protected XSSFPivotCacheRecords(PackagePart part) throws IOException { - super(part); - readFrom(part.getInputStream()); - } - - @Beta - protected void readFrom(InputStream is) throws IOException { - try { - XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); - //Removing root element - options.setLoadReplaceDocumentElement(null); - ctPivotCacheRecords = CTPivotCacheRecords.Factory.parse(is, options); - } catch (XmlException e) { - throw new IOException(e.getLocalizedMessage()); - } - } - - @Beta - @Internal - public CTPivotCacheRecords getCtPivotCacheRecords() { - return ctPivotCacheRecords; - } - - @Beta - @Override - protected void commit() throws IOException { - PackagePart part = getPackagePart(); - OutputStream out = part.getOutputStream(); - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - //Sets the pivotCacheDefinition tag - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTPivotCacheRecords.type.getName(). - getNamespaceURI(), "pivotCacheRecords")); - ctPivotCacheRecords.save(out, xmlOptions); - out.close(); - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java deleted file mode 100644 index 8ace06e95a..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java +++ /dev/null @@ -1,574 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import javax.xml.namespace.QName; -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 org.apache.poi.ooxml.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.DataConsolidateFunction; -import org.apache.poi.ss.usermodel.DataFormat; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -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.CTCacheSource; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColFields; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataField; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataFields; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTField; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTItems; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTLocation; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageField; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageFields; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCacheDefinition; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotField; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotFields; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotTableDefinition; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotTableStyle; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRowFields; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheetSource; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STAxis; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataConsolidateFunction; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STItemType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STSourceType; - -public class XSSFPivotTable extends POIXMLDocumentPart { - - protected static final short CREATED_VERSION = 3; - protected static final short MIN_REFRESHABLE_VERSION = 3; - protected static final 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()); - } - - @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() { - final Workbook wb = getDataSheet().getWorkbook(); - return getPivotCacheDefinition().getPivotArea(wb); - } - - /** - * 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<>(); - for (CTField f : pivotTableDefinition.getRowFields().getFieldArray()) { - columnIndexes.add(f.getX()); - } - return columnIndexes; - } else { - return Collections.emptyList(); - } - } - - /** - * Add a col 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. - * @param valueFormat format of column value (e.g. for date: "DD.MM.YYYY") - */ - @Beta - public void addColLabel(int columnIndex, String valueFormat) { - 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_COL); - pivotField.setShowAll(false); - if (valueFormat != null && !valueFormat.trim().isEmpty()) { - DataFormat df = parentSheet.getWorkbook().createDataFormat(); - pivotField.setNumFmtId(df.getFormat(valueFormat)); - } - for (int i = 0; i <= lastRowIndex; i++) { - items.addNewItem().setT(STItemType.DEFAULT); - } - items.setCount(items.sizeOfItemArray()); - pivotFields.setPivotFieldArray(columnIndex, pivotField); - - CTColFields colFields; - if(pivotTableDefinition.getColFields() != null) { - colFields = pivotTableDefinition.getColFields(); - } else { - colFields = pivotTableDefinition.addNewColFields(); - } - - colFields.addNewField().setX(columnIndex); - colFields.setCount(colFields.sizeOfFieldArray()); - } - - /** - * Add a col 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 addColLabel(int columnIndex) { - addColLabel(columnIndex, null); - } - - @Beta - public List<Integer> getColLabelColumns() { - if (pivotTableDefinition.getColFields() != null) { - List<Integer> columnIndexes = new ArrayList<>(); - for (CTField f : pivotTableDefinition.getColFields().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 - * @param valueFormat format of value field (e.g. "#,##0.00") - */ - @Beta - public void addColumnLabel(DataConsolidateFunction function, int columnIndex, String valueFieldName, String valueFormat) { - checkColumnIndex(columnIndex); - - addDataColumn(columnIndex, true); - addDataField(function, columnIndex, valueFieldName, valueFormat); - - // 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 - * @param valueFieldName the name of pivot table value field - */ - @Beta - public void addColumnLabel(DataConsolidateFunction function, int columnIndex, String valueFieldName) { - addColumnLabel(function, columnIndex, valueFieldName, null); - } - - /** - * 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(), null); - } - - /** - * 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, String valueFormat) { - checkColumnIndex(columnIndex); - - CTDataFields dataFields; - if(pivotTableDefinition.getDataFields() != null) { - dataFields = pivotTableDefinition.getDataFields(); - } else { - dataFields = pivotTableDefinition.addNewDataFields(); - } - CTDataField dataField = dataFields.addNewDataField(); - dataField.setSubtotal(STDataConsolidateFunction.Enum.forInt(function.getValue())); - dataField.setName(valueFieldName); - dataField.setFld(columnIndex); - if (valueFormat != null && !valueFormat.trim().isEmpty()) { - DataFormat df = parentSheet.getWorkbook().createDataFormat(); - dataField.setNumFmtId(df.getFormat(valueFormat)); - } - 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(); - // check and change row of location - CTLocation location = pivotTableDefinition.getLocation(); - AreaReference destination = new AreaReference(location.getRef(), SpreadsheetVersion.EXCEL2007); - if (destination.getFirstCell().getRow() < 2) { - AreaReference newDestination = new AreaReference(new CellReference(2, destination.getFirstCell().getCol()), new CellReference( - 3, destination.getFirstCell().getCol()+1), SpreadsheetVersion.EXCEL2007); - location.setRef(newDestination.formatAsString()); - } - - 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 position Position for pivot table in sheet - * @param sourceSheet Sheet where the source will be collected from - * @param refConfig an configurator that knows how to configure pivot table references - */ - @Beta - protected void createSourceReferences(CellReference position, Sheet sourceSheet, PivotTableReferenceConfigurator refConfig){ - - //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), SpreadsheetVersion.EXCEL2007); - - 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); - - refConfig.configureReference(worksheetSource); - if (worksheetSource.getName() == null && worksheetSource.getRef() == null) throw new IllegalArgumentException("Pivot table source area reference or name must be specified."); - } - - @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 = firstColumn; i<=lastColumn; i++) { - pivotField = pivotFields.addNewPivotField(); - pivotField.setDataField(false); - pivotField.setShowAll(false); - } - pivotFields.setCount(pivotFields.sizeOfPivotFieldArray()); - } - - protected static interface PivotTableReferenceConfigurator { - - /** - * Configure the name or area reference for the pivot table - * @param wsSource CTWorksheetSource that needs the pivot source reference assignment - */ - public void configureReference(CTWorksheetSource wsSource); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPrintSetup.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPrintSetup.java deleted file mode 100644 index e626790d88..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPrintSetup.java +++ /dev/null @@ -1,539 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLException; -import org.apache.poi.ss.usermodel.PageOrder; -import org.apache.poi.ss.usermodel.PaperSize; -import org.apache.poi.ss.usermodel.PrintCellComments; -import org.apache.poi.ss.usermodel.PrintOrientation; -import org.apache.poi.ss.usermodel.PrintSetup; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageSetup; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellComments; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STOrientation; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPageOrder; - - -/** - * Page setup and page margins settings for the worksheet. - */ -public class XSSFPrintSetup implements PrintSetup { - private CTWorksheet ctWorksheet; - private CTPageSetup pageSetup; - private CTPageMargins pageMargins; - - protected XSSFPrintSetup(CTWorksheet worksheet) { - this.ctWorksheet = worksheet; - - if(ctWorksheet.isSetPageSetup()) { - this.pageSetup = ctWorksheet.getPageSetup(); - } else { - this.pageSetup = ctWorksheet.addNewPageSetup(); - } - if(ctWorksheet.isSetPageMargins()) { - this.pageMargins = ctWorksheet.getPageMargins(); - } else { - this.pageMargins = ctWorksheet.addNewPageMargins(); - } - } - - /** - * Set the paper size. - * - * @param size the paper size. - */ - public void setPaperSize(short size) { - pageSetup.setPaperSize(size); - } - - /** - * Set the paper size as enum value. - * - * @param size value for the paper size. - */ - public void setPaperSize(PaperSize size) { - setPaperSize((short) (size.ordinal() + 1)); - } - - /** - * Set the scale. - * Valid values range from 10 to 400. - * This setting is overridden when fitToWidth and/or fitToHeight are in use - * - * @param scale the scale to use - */ - public void setScale(short scale) { - if (scale < 10 || scale > 400) throw new POIXMLException("Scale value not accepted: you must choose a value between 10 and 400."); - pageSetup.setScale(scale); - } - - /** - * Set the page numbering start. - * Page number for first printed page. If no value is specified, then 'automatic' is assumed. - * - * @param start the page numbering start - */ - public void setPageStart(short start) { - pageSetup.setFirstPageNumber(start); - } - - /** - * Set the number of pages wide to fit the sheet in - * - * @param width the number of pages - */ - public void setFitWidth(short width) { - pageSetup.setFitToWidth(width); - } - - /** - * Set the number of pages high to fit the sheet in - * - * @param height the number of pages - */ - public void setFitHeight(short height) { - pageSetup.setFitToHeight(height); - } - - /** - * Set whether to go left to right or top down in ordering - * - * @param leftToRight left to right - */ - public void setLeftToRight(boolean leftToRight) { - if (leftToRight) - setPageOrder(PageOrder.OVER_THEN_DOWN); - else - setPageOrder(PageOrder.DOWN_THEN_OVER); - } - - /** - * Set whether to print in landscape - * - * @param ls landscape - */ - public void setLandscape(boolean ls) { - if (ls) - setOrientation(PrintOrientation.LANDSCAPE); - else - setOrientation(PrintOrientation.PORTRAIT); - } - - /** - * Use the printer's defaults settings for page setup values and don't use the default values - * specified in the schema. For example, if dpi is not present or specified in the XML, the - * application shall not assume 600dpi as specified in the schema as a default and instead - * shall let the printer specify the default dpi. - * - * @param valid Valid - */ - public void setValidSettings(boolean valid) { - pageSetup.setUsePrinterDefaults(valid); - } - - /** - * Set whether it is black and white - * - * @param mono Black and white - */ - public void setNoColor(boolean mono) { - pageSetup.setBlackAndWhite(mono); - } - - /** - * Set whether it is in draft mode - * - * @param d draft - */ - public void setDraft(boolean d) { - pageSetup.setDraft(d); - } - - /** - * Print the include notes - * - * @param printNotes print the notes - */ - public void setNotes(boolean printNotes) { - if (printNotes){ - pageSetup.setCellComments(STCellComments.AS_DISPLAYED); - } - } - - /** - * Set no orientation. - * - * @param orientation Orientation. - */ - public void setNoOrientation(boolean orientation) { - if (orientation) { - setOrientation(PrintOrientation.DEFAULT); - } - } - - /** - * Set whether to use page start - * - * @param page Use page start - */ - public void setUsePage(boolean page) { - pageSetup.setUseFirstPageNumber(page); - } - - /** - * Sets the horizontal resolution. - * - * @param resolution horizontal resolution - */ - public void setHResolution(short resolution) { - pageSetup.setHorizontalDpi(resolution); - } - - /** - * Sets the vertical resolution. - * - * @param resolution vertical resolution - */ - public void setVResolution(short resolution) { - pageSetup.setVerticalDpi(resolution); - } - - /** - * Sets the header margin. - * - * @param headerMargin header margin - */ - public void setHeaderMargin(double headerMargin) { - pageMargins.setHeader(headerMargin); - } - - /** - * Sets the footer margin. - * - * @param footerMargin footer margin - */ - public void setFooterMargin(double footerMargin) { - pageMargins.setFooter(footerMargin); - } - - /** - * Sets the number of copies. - * - * @param copies number of copies - */ - public void setCopies(short copies) { - pageSetup.setCopies(copies); - } - - /** - * Orientation of the page: landscape - portrait. - * - * @param orientation - Orientation of the page - * @see PrintOrientation - */ - public void setOrientation(PrintOrientation orientation) { - STOrientation.Enum v = STOrientation.Enum.forInt(orientation.getValue()); - pageSetup.setOrientation(v); - } - - /** - * Orientation of the page: landscape - portrait. - * - * @return Orientation of the page - * @see PrintOrientation - */ - public PrintOrientation getOrientation() { - STOrientation.Enum val = pageSetup.getOrientation(); - return val == null ? PrintOrientation.DEFAULT : PrintOrientation.valueOf(val.intValue()); - } - - - public PrintCellComments getCellComment() { - STCellComments.Enum val = pageSetup.getCellComments(); - return val == null ? PrintCellComments.NONE : PrintCellComments.valueOf(val.intValue()); - } - - /** - * Set print page order. - * - * @param pageOrder An enum indicating the wanted ordering of printed pages - */ - public void setPageOrder(PageOrder pageOrder) { - STPageOrder.Enum v = STPageOrder.Enum.forInt(pageOrder.getValue()); - pageSetup.setPageOrder(v); - } - - /** - * get print page order. - * - * @return The currently set ordering of printed pages - */ - public PageOrder getPageOrder() { - return (pageSetup.getPageOrder() == null) ? null : PageOrder.valueOf(pageSetup.getPageOrder().intValue()); - } - - /** - * Returns the paper size. - * - * @return short - paper size - */ - public short getPaperSize() { - return (short) pageSetup.getPaperSize(); - } - - /** - * Returns the paper size as enum. - * - * @return PaperSize paper size - * @see PaperSize - */ - public PaperSize getPaperSizeEnum() { - return PaperSize.values()[getPaperSize() - 1]; - } - - /** - * Returns the scale. - * - * @return short - scale - */ - public short getScale() { - return (short) pageSetup.getScale(); - } - - /** - * Set the page numbering start. - * Page number for first printed page. If no value is specified, then 'automatic' is assumed. - * - * @return page number for first printed page - */ - public short getPageStart() { - return (short) pageSetup.getFirstPageNumber(); - } - - /** - * Returns the number of pages wide to fit sheet in. - * - * @return number of pages wide to fit sheet in - */ - public short getFitWidth() { - return (short) pageSetup.getFitToWidth(); - } - - /** - * Returns the number of pages high to fit the sheet in. - * - * @return number of pages high to fit the sheet in - */ - public short getFitHeight() { - return (short) pageSetup.getFitToHeight(); - } - - /** - * Returns the left to right print order. - * - * @return left to right print order - */ - public boolean getLeftToRight() { - return getPageOrder() == PageOrder.OVER_THEN_DOWN; - } - - /** - * Returns the landscape mode. - * - * @return landscape mode - */ - public boolean getLandscape() { - return getOrientation() == PrintOrientation.LANDSCAPE; - } - - /** - * Use the printer's defaults settings for page setup values and don't use the default values - * specified in the schema. For example, if dpi is not present or specified in the XML, the - * application shall not assume 600dpi as specified in the schema as a default and instead - * shall let the printer specify the default dpi. - * - * @return valid settings - */ - public boolean getValidSettings() { - return pageSetup.getUsePrinterDefaults(); - } - - /** - * Returns the black and white setting. - * - * @return black and white setting - */ - public boolean getNoColor() { - return pageSetup.getBlackAndWhite(); - } - - /** - * Returns the draft mode. - * - * @return draft mode - */ - public boolean getDraft() { - return pageSetup.getDraft(); - } - - /** - * Returns the print notes. - * - * @return print notes - */ - public boolean getNotes() { - return getCellComment() == PrintCellComments.AS_DISPLAYED; - } - - /** - * Returns the no orientation. - * - * @return no orientation - */ - public boolean getNoOrientation() { - return getOrientation() == PrintOrientation.DEFAULT; - } - - /** - * Returns the use page numbers. - * - * @return use page numbers - */ - public boolean getUsePage() { - return pageSetup.getUseFirstPageNumber(); - } - - /** - * Returns the horizontal resolution. - * - * @return horizontal resolution - */ - public short getHResolution() { - return (short) pageSetup.getHorizontalDpi(); - } - - /** - * Returns the vertical resolution. - * - * @return vertical resolution - */ - public short getVResolution() { - return (short) pageSetup.getVerticalDpi(); - } - - /** - * Returns the header margin. - * - * @return header margin - */ - public double getHeaderMargin() { - return pageMargins.getHeader(); - } - - /** - * Returns the footer margin. - * - * @return footer margin - */ - public double getFooterMargin() { - return pageMargins.getFooter(); - } - - /** - * Returns the number of copies. - * - * @return number of copies - */ - public short getCopies() { - return (short) pageSetup.getCopies(); - } - - /** - * Sets the top margin. - * - * @param topMargin top margin - */ - public void setTopMargin(double topMargin) { - pageMargins.setTop(topMargin); - } - - /** - * Returns the top margin. - * - * @return top margin - */ - public double getTopMargin() { - return pageMargins.getTop(); - } - - /** - * Sets the bottom margin. - * - * @param bottomMargin bottom margin - */ - public void setBottomMargin(double bottomMargin) { - pageMargins.setBottom(bottomMargin); - } - - /** - * Returns the bottom margin. - * - * @return bottom margin - */ - public double getBottomMargin() { - return pageMargins.getBottom(); - } - - /** - * Sets the left margin. - * - * @param leftMargin left margin - */ - public void setLeftMargin(double leftMargin) { - pageMargins.setLeft(leftMargin); - } - - /** - * Returns the left margin. - * - * @return left margin - */ - public double getLeftMargin() { - return pageMargins.getLeft(); - } - - /** - * Sets the right margin. - * - * @param rightMargin right margin - */ - public void setRightMargin(double rightMargin) { - pageMargins.setRight(rightMargin); - } - - /** - * Returns the right margin. - * - * @return right margin - */ - public double getRightMargin() { - return pageMargins.getRight(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRangeCopier.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRangeCopier.java deleted file mode 100644 index 50248fae81..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRangeCopier.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ==================================================================== - * 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.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaRenderer; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.RangeCopier; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.util.Beta; - -@Beta -public class XSSFRangeCopier extends RangeCopier { - - public XSSFRangeCopier(Sheet sourceSheet, Sheet destSheet) { - super(sourceSheet, destSheet); - } - - public XSSFRangeCopier(Sheet sheet) { - super(sheet); - } - - protected void adjustCellReferencesInsideFormula(Cell cell, Sheet destSheet, int deltaX, int deltaY){ - XSSFWorkbook hostWorkbook = (XSSFWorkbook) destSheet.getWorkbook(); - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(hostWorkbook); - Ptg[] ptgs = FormulaParser.parse(cell.getCellFormula(), fpb, FormulaType.CELL, 0); - int destSheetIndex = hostWorkbook.getSheetIndex(destSheet); - if(adjustInBothDirections(ptgs, destSheetIndex, deltaX, deltaY)) - cell.setCellFormula(FormulaRenderer.toFormulaString(fpb, ptgs)); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java deleted file mode 100644 index ee502b1b39..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java +++ /dev/null @@ -1,381 +0,0 @@ -/* ==================================================================== - 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 java.util.HashMap; -import java.util.Map; - -import org.apache.poi.ooxml.POIXMLDocument; -import org.apache.poi.ooxml.POIXMLRelation; -import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; -import org.apache.poi.xssf.model.CalculationChain; -import org.apache.poi.xssf.model.CommentsTable; -import org.apache.poi.xssf.model.ExternalLinksTable; -import org.apache.poi.xssf.model.MapInfo; -import org.apache.poi.xssf.model.SharedStringsTable; -import org.apache.poi.xssf.model.SingleXmlCells; -import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.model.ThemesTable; - -/** - * Defines namespaces, content types and normal file names / naming - * patterns, for the well-known XSSF format parts. - */ -public final class XSSFRelation extends POIXMLRelation { - - /** - * A map to lookup POIXMLRelation by its relation type - */ - private static final Map<String, XSSFRelation> _table = new HashMap<>(); - - - public static final XSSFRelation WORKBOOK = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/workbook", - "/xl/workbook.xml" - ); - - public static final XSSFRelation MACROS_WORKBOOK = new XSSFRelation( - "application/vnd.ms-excel.sheet.macroEnabled.main+xml", - PackageRelationshipTypes.CORE_DOCUMENT, - "/xl/workbook.xml" - ); - - public static final XSSFRelation TEMPLATE_WORKBOOK = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml", - PackageRelationshipTypes.CORE_DOCUMENT, - "/xl/workbook.xml" - ); - - public static final XSSFRelation MACRO_TEMPLATE_WORKBOOK = new XSSFRelation( - "application/vnd.ms-excel.template.macroEnabled.main+xml", - PackageRelationshipTypes.CORE_DOCUMENT, - "/xl/workbook.xml" - ); - - public static final XSSFRelation MACRO_ADDIN_WORKBOOK = new XSSFRelation( - "application/vnd.ms-excel.addin.macroEnabled.main+xml", - PackageRelationshipTypes.CORE_DOCUMENT, - "/xl/workbook.xml" - ); - - public static final XSSFRelation XLSB_BINARY_WORKBOOK = new XSSFRelation( - "application/vnd.ms-excel.sheet.binary.macroEnabled.main", - PackageRelationshipTypes.CORE_DOCUMENT, - "/xl/workbook.bin" - ); - - public static final XSSFRelation WORKSHEET = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", - "/xl/worksheets/sheet#.xml", - XSSFSheet::new, XSSFSheet::new - ); - - public static final XSSFRelation CHARTSHEET = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet", - "/xl/chartsheets/sheet#.xml", - null, XSSFChartSheet::new - ); - - public static final XSSFRelation SHARED_STRINGS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", - "/xl/sharedStrings.xml", - SharedStringsTable::new, SharedStringsTable::new - ); - - public static final XSSFRelation STYLES = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", - PackageRelationshipTypes.STYLE_PART, - "/xl/styles.xml", - StylesTable::new, StylesTable::new - ); - - public static final XSSFRelation DRAWINGS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.drawing+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing", - "/xl/drawings/drawing#.xml", - XSSFDrawing::new, XSSFDrawing::new - ); - - public static final XSSFRelation VML_DRAWINGS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.vmlDrawing", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing", - "/xl/drawings/vmlDrawing#.vml", - XSSFVMLDrawing::new, XSSFVMLDrawing::new - ); - - public static final XSSFRelation CHART = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.drawingml.chart+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", - "/xl/charts/chart#.xml", - XSSFChart::new, XSSFChart::new - ); - - public static final XSSFRelation CUSTOM_XML_MAPPINGS = new XSSFRelation( - "application/xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/xmlMaps", - "/xl/xmlMaps.xml", - MapInfo::new, MapInfo::new - ); - - public static final XSSFRelation SINGLE_XML_CELLS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/tableSingleCells", - "/xl/tables/tableSingleCells#.xml", - SingleXmlCells::new, SingleXmlCells::new - ); - - public static final XSSFRelation TABLE = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table", - "/xl/tables/table#.xml", - XSSFTable::new, XSSFTable::new - ); - - public static final XSSFRelation IMAGES = new XSSFRelation( - null, - PackageRelationshipTypes.IMAGE_PART, - null, - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_EMF = new XSSFRelation( - "image/x-emf", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.emf", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_WMF = new XSSFRelation( - "image/x-wmf", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.wmf", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_PICT = new XSSFRelation( - "image/pict", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.pict", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_JPEG = new XSSFRelation( - "image/jpeg", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.jpeg", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_PNG = new XSSFRelation( - "image/png", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.png", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_DIB = new XSSFRelation( - "image/dib", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.dib", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_GIF = new XSSFRelation( - "image/gif", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.gif", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_TIFF = new XSSFRelation( - "image/tiff", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.tiff", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_EPS = new XSSFRelation( - "image/x-eps", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.eps", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_BMP = new XSSFRelation( - "image/x-ms-bmp", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.bmp", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation IMAGE_WPG = new XSSFRelation( - "image/x-wpg", - PackageRelationshipTypes.IMAGE_PART, - "/xl/media/image#.wpg", - XSSFPictureData::new, XSSFPictureData::new - ); - - public static final XSSFRelation SHEET_COMMENTS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", - "/xl/comments#.xml", - CommentsTable::new, CommentsTable::new - ); - - public static final XSSFRelation SHEET_HYPERLINKS = new XSSFRelation( - null, - PackageRelationshipTypes.HYPERLINK_PART, - null - ); - - public static final XSSFRelation OLEEMBEDDINGS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.oleObject", - POIXMLDocument.OLE_OBJECT_REL_TYPE, - "/xl/embeddings/oleObject#.bin" - ); - - public static final XSSFRelation PACKEMBEDDINGS = new XSSFRelation( - null, - POIXMLDocument.PACK_OBJECT_REL_TYPE, - null - ); - - public static final XSSFRelation VBA_MACROS = new XSSFRelation( - "application/vnd.ms-office.vbaProject", - "http://schemas.microsoft.com/office/2006/relationships/vbaProject", - "/xl/vbaProject.bin", - XSSFVBAPart::new, XSSFVBAPart::new - ); - - public static final XSSFRelation ACTIVEX_CONTROLS = new XSSFRelation( - "application/vnd.ms-office.activeX+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/control", - "/xl/activeX/activeX#.xml" - ); - - public static final XSSFRelation ACTIVEX_BINS = new XSSFRelation( - "application/vnd.ms-office.activeX", - "http://schemas.microsoft.com/office/2006/relationships/activeXControlBinary", - "/xl/activeX/activeX#.bin" - ); - - public static final XSSFRelation MACRO_SHEET_BIN = new XSSFRelation( - null,//TODO: figure out what this should be? - "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet", - "/xl/macroSheets/sheet#.bin" - ); - - public static final XSSFRelation INTL_MACRO_SHEET_BIN = new XSSFRelation( - null,//TODO: figure out what this should be? - "http://schemas.microsoft.com/office/2006/relationships/xlIntlMacrosheet", - "/xl/macroSheets/sheet#.bin" - ); - - public static final XSSFRelation DIALOG_SHEET_BIN = new XSSFRelation( - null,//TODO: figure out what this should be? - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet", - "/xl/dialogSheets/sheet#.bin" - ); - - public static final XSSFRelation THEME = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.theme+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", - "/xl/theme/theme#.xml", - ThemesTable::new, ThemesTable::new - ); - - public static final XSSFRelation CALC_CHAIN = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain", - "/xl/calcChain.xml", - CalculationChain::new, CalculationChain::new - ); - - public static final XSSFRelation EXTERNAL_LINKS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink", - "/xl/externalLinks/externalLink#.xmll", - ExternalLinksTable::new, ExternalLinksTable::new - ); - - public static final XSSFRelation PRINTER_SETTINGS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings", - "/xl/printerSettings/printerSettings#.bin" - ); - public static final XSSFRelation PIVOT_TABLE = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable", - "/xl/pivotTables/pivotTable#.xml", - XSSFPivotTable::new, XSSFPivotTable::new - ); - public static final XSSFRelation PIVOT_CACHE_DEFINITION = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition", - "/xl/pivotCache/pivotCacheDefinition#.xml", - XSSFPivotCacheDefinition::new, XSSFPivotCacheDefinition::new - ); - public static final XSSFRelation PIVOT_CACHE_RECORDS = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords", - "/xl/pivotCache/pivotCacheRecords#.xml", - XSSFPivotCacheRecords::new, XSSFPivotCacheRecords::new - ); - - public static final XSSFRelation CTRL_PROP_RECORDS = new XSSFRelation( - null, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp", - "/xl/ctrlProps/ctrlProp#.xml" - ); - - public static final XSSFRelation CUSTOM_PROPERTIES = new XSSFRelation( - "application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customProperty", - "/xl/customProperty#.bin" - ); - - public static final String NS_SPREADSHEETML = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; - public static final String NS_DRAWINGML = "http://schemas.openxmlformats.org/drawingml/2006/main"; - public static final String NS_CHART = "http://schemas.openxmlformats.org/drawingml/2006/chart"; - - - private XSSFRelation(String type, String rel, String defaultName) { - this(type,rel, defaultName, null, null); - } - - private XSSFRelation(String type, String rel, String defaultName, - NoArgConstructor noArgConstructor, - PackagePartConstructor packagePartConstructor) { - super(type, rel, defaultName, noArgConstructor, packagePartConstructor, null); - _table.put(rel, this); - } - - /** - * Get POIXMLRelation by relation type - * - * @param rel relation type, for example, - * <code>http://schemas.openxmlformats.org/officeDocument/2006/relationships/image</code> - * @return registered POIXMLRelation or null if not found - */ - public static XSSFRelation getInstance(String rel) { - return _table.get(rel); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java deleted file mode 100644 index d71641b7de..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRichTextString.java +++ /dev/null @@ -1,642 +0,0 @@ -/* ==================================================================== - 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 java.util.Iterator; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.namespace.QName; - -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.RichTextString; -import org.apache.poi.util.Internal; -import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.model.ThemesTable; -import org.apache.xmlbeans.XmlCursor; -import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STXstring; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRElt; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRPrElt; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; - - -/** - * Rich text unicode string. These strings can have fonts applied to arbitary parts of the string. - * - * <p> - * Most strings in a workbook have formatting applied at the cell level, that is, the entire string in the cell has the - * same formatting applied. In these cases, the formatting for the cell is stored in the styles part, - * and the string for the cell can be shared across the workbook. The following code illustrates the example. - * </p> - * - * <blockquote> - * <pre> - * cell1.setCellValue(new XSSFRichTextString("Apache POI")); - * cell2.setCellValue(new XSSFRichTextString("Apache POI")); - * cell3.setCellValue(new XSSFRichTextString("Apache POI")); - * </pre> - * </blockquote> - * In the above example all three cells will use the same string cached on workbook level. - * - * <p> - * Some strings in the workbook may have formatting applied at a level that is more granular than the cell level. - * For instance, specific characters within the string may be bolded, have coloring, italicizing, etc. - * In these cases, the formatting is stored along with the text in the string table, and is treated as - * a unique entry in the workbook. The following xml and code snippet illustrate this. - * </p> - * - * <blockquote> - * <pre> - * XSSFRichTextString s1 = new XSSFRichTextString("Apache POI"); - * s1.applyFont(boldArial); - * cell1.setCellValue(s1); - * - * XSSFRichTextString s2 = new XSSFRichTextString("Apache POI"); - * s2.applyFont(italicCourier); - * cell2.setCellValue(s2); - * </pre> - * </blockquote> - */ -public class XSSFRichTextString implements RichTextString { - private static final Pattern utfPtrn = Pattern.compile("_x([0-9A-Fa-f]{4})_"); - - private CTRst st; - private StylesTable styles; - - /** - * Create a rich text string - */ - public XSSFRichTextString(String str) { - st = CTRst.Factory.newInstance(); - st.setT(str); - preserveSpaces(st.xgetT()); - } - - /** - * Create empty rich text string and initialize it with empty string - */ - public XSSFRichTextString() { - st = CTRst.Factory.newInstance(); - } - - /** - * Create a rich text string from the supplied XML bean - */ - @Internal - public XSSFRichTextString(CTRst st) { - this.st = st; - } - - /** - * Applies a font to the specified characters of a string. - * - * @param startIndex The start index to apply the font to (inclusive) - * @param endIndex The end index to apply the font to (exclusive) - * @param fontIndex The font to use. - */ - public void applyFont(int startIndex, int endIndex, short fontIndex) { - XSSFFont font; - if(styles == null) { - //style table is not set, remember fontIndex and set the run properties later, - //when setStylesTableReference is called - font = new XSSFFont(); - font.setFontName("#" + fontIndex); - } else { - font = styles.getFontAt(fontIndex); - } - applyFont(startIndex, endIndex, font); - } - - /** - * Applies a font to the specified characters of a string. - * - * @param startIndex The start index to apply the font to (inclusive) - * @param endIndex The end index to apply to font to (exclusive) - * @param font The index of the font to use. - */ - public void applyFont(int startIndex, int endIndex, Font font) { - if (startIndex > endIndex) - throw new IllegalArgumentException("Start index must be less than end index, but had " + startIndex + " and " + endIndex); - if (startIndex < 0 || endIndex > length()) - throw new IllegalArgumentException("Start and end index not in range, but had " + startIndex + " and " + endIndex); - - if (startIndex == endIndex) - return; - - if(st.sizeOfRArray() == 0 && st.isSetT()) { - //convert <t>string</t> into a text run: <r><t>string</t></r> - st.addNewR().setT(st.getT()); - st.unsetT(); - } - - String text = getString(); - XSSFFont xssfFont = (XSSFFont)font; - - TreeMap<Integer, CTRPrElt> formats = getFormatMap(st); - CTRPrElt fmt = CTRPrElt.Factory.newInstance(); - setRunAttributes(xssfFont.getCTFont(), fmt); - applyFont(formats, startIndex, endIndex, fmt); - - CTRst newSt = buildCTRst(text, formats); - st.set(newSt); - } - - /** - * Sets the font of the entire string. - * @param font The font to use. - */ - public void applyFont(Font font) { - String text = getString(); - applyFont(0, text.length(), font); - } - - /** - * Applies the specified font to the entire string. - * - * @param fontIndex the font to apply. - */ - public void applyFont(short fontIndex) { - XSSFFont font; - if(styles == null) { - font = new XSSFFont(); - font.setFontName("#" + fontIndex); - } else { - font = styles.getFontAt(fontIndex); - } - String text = getString(); - applyFont(0, text.length(), font); - } - - /** - * Append new text to this text run and apply the specify font to it - * - * @param text the text to append - * @param font the font to apply to the appended text or <code>null</code> if no formatting is required - */ - public void append(String text, XSSFFont font){ - if(st.sizeOfRArray() == 0 && st.isSetT()) { - //convert <t>string</t> into a text run: <r><t>string</t></r> - CTRElt lt = st.addNewR(); - lt.setT(st.getT()); - preserveSpaces(lt.xgetT()); - st.unsetT(); - } - CTRElt lt = st.addNewR(); - lt.setT(text); - preserveSpaces(lt.xgetT()); - - if (font != null) { - CTRPrElt pr = lt.addNewRPr(); - setRunAttributes(font.getCTFont(), pr); - } - } - - /** - * Append new text to this text run - * - * @param text the text to append - */ - public void append(String text){ - append(text, null); - } - - /** - * Copy font attributes from CTFont bean into CTRPrElt bean - */ - private void setRunAttributes(CTFont ctFont, CTRPrElt pr){ - if(ctFont.sizeOfBArray() > 0) pr.addNewB().setVal(ctFont.getBArray(0).getVal()); - if(ctFont.sizeOfUArray() > 0) pr.addNewU().setVal(ctFont.getUArray(0).getVal()); - if(ctFont.sizeOfIArray() > 0) pr.addNewI().setVal(ctFont.getIArray(0).getVal()); - if(ctFont.sizeOfColorArray() > 0) { - CTColor c1 = ctFont.getColorArray(0); - CTColor c2 = pr.addNewColor(); - if(c1.isSetAuto()) c2.setAuto(c1.getAuto()); - if(c1.isSetIndexed()) c2.setIndexed(c1.getIndexed()); - if(c1.isSetRgb()) c2.setRgb(c1.getRgb()); - if(c1.isSetTheme()) c2.setTheme(c1.getTheme()); - if(c1.isSetTint()) c2.setTint(c1.getTint()); - } - if(ctFont.sizeOfSzArray() > 0) pr.addNewSz().setVal(ctFont.getSzArray(0).getVal()); - if(ctFont.sizeOfNameArray() > 0) pr.addNewRFont().setVal(ctFont.getNameArray(0).getVal()); - if(ctFont.sizeOfFamilyArray() > 0) pr.addNewFamily().setVal(ctFont.getFamilyArray(0).getVal()); - if(ctFont.sizeOfSchemeArray() > 0) pr.addNewScheme().setVal(ctFont.getSchemeArray(0).getVal()); - if(ctFont.sizeOfCharsetArray() > 0) pr.addNewCharset().setVal(ctFont.getCharsetArray(0).getVal()); - if(ctFont.sizeOfCondenseArray() > 0) pr.addNewCondense().setVal(ctFont.getCondenseArray(0).getVal()); - if(ctFont.sizeOfExtendArray() > 0) pr.addNewExtend().setVal(ctFont.getExtendArray(0).getVal()); - if(ctFont.sizeOfVertAlignArray() > 0) pr.addNewVertAlign().setVal(ctFont.getVertAlignArray(0).getVal()); - if(ctFont.sizeOfOutlineArray() > 0) pr.addNewOutline().setVal(ctFont.getOutlineArray(0).getVal()); - if(ctFont.sizeOfShadowArray() > 0) pr.addNewShadow().setVal(ctFont.getShadowArray(0).getVal()); - if(ctFont.sizeOfStrikeArray() > 0) pr.addNewStrike().setVal(ctFont.getStrikeArray(0).getVal()); - } - - /** - * Does this string have any explicit formatting applied, or is - * it just text in the default style? - */ - public boolean hasFormatting() { - //noinspection deprecation - for performance reasons! - CTRElt[] rs = st.getRArray(); - if (rs == null || rs.length == 0) { - return false; - } - for (CTRElt r : rs) { - if (r.isSetRPr()) return true; - } - return false; - } - - /** - * Removes any formatting that may have been applied to the string. - */ - public void clearFormatting() { - String text = getString(); - st.setRArray(null); - st.setT(text); - } - - /** - * The index within the string to which the specified formatting run applies. - * - * @param index the index of the formatting run - * @return the index within the string. - */ - public int getIndexOfFormattingRun(int index) { - if(st.sizeOfRArray() == 0) return 0; - - int pos = 0; - for(int i = 0; i < st.sizeOfRArray(); i++){ - CTRElt r = st.getRArray(i); - if(i == index) return pos; - - pos += r.getT().length(); - } - return -1; - } - - /** - * Returns the number of characters this format run covers. - * - * @param index the index of the formatting run - * @return the number of characters this format run covers - */ - public int getLengthOfFormattingRun(int index) { - if(st.sizeOfRArray() == 0 || index >= st.sizeOfRArray()) { - return -1; - } - - CTRElt r = st.getRArray(index); - return r.getT().length(); - } - - /** - * Returns the plain string representation. - * - * @return The string representation of this RichText string, null if - * there is no data at all - */ - public String getString() { - if(st.sizeOfRArray() == 0) { - return utfDecode(st.getT()); - } - - StringBuilder buf = new StringBuilder(); - //noinspection deprecation - for performance reasons! - for(CTRElt r : st.getRArray()){ - buf.append(r.getT()); - } - return utfDecode(buf.toString()); - } - - /** - * Removes any formatting and sets new string value - * - * @param s new string value - */ - public void setString(String s) { - clearFormatting(); - st.setT(s); - preserveSpaces(st.xgetT()); - } - - /** - * Returns the plain string representation. - * - * @return The string representation of this RichText string, never null - */ - public String toString() { - String str = getString(); - if(str == null) { - return ""; - } - - return str; - } - - /** - * Returns the number of characters in this string. - */ - public int length() { - return getString().length(); - } - - /** - * @return The number of formatting runs used. - */ - public int numFormattingRuns() { - return st.sizeOfRArray(); - } - - /** - * Gets a copy of the font used in a particular formatting run. - * - * @param index the index of the formatting run - * @return A copy of the font used or null if no formatting is applied to the specified text run. - */ - public XSSFFont getFontOfFormattingRun(int index) { - if(st.sizeOfRArray() == 0 || index >= st.sizeOfRArray()) { - return null; - } - - CTRElt r = st.getRArray(index); - if(r.getRPr() != null) { - XSSFFont fnt = new XSSFFont(toCTFont(r.getRPr())); - fnt.setThemesTable(getThemesTable()); - return fnt; - } - - return null; - } - - /** - * Return a copy of the font in use at a particular index. - * - * @param index The index. - * @return A copy of the font that's currently being applied at that - * index or null if no font is being applied or the - * index is out of range. - */ - public XSSFFont getFontAtIndex( int index ) { - final ThemesTable themes = getThemesTable(); - int pos = 0; - //noinspection deprecation - for performance reasons! - for(CTRElt r : st.getRArray()){ - final int length = r.getT().length(); - if(index >= pos && index < pos + length) { - XSSFFont fnt = new XSSFFont(toCTFont(r.getRPr())); - fnt.setThemesTable(themes); - return fnt; - } - - pos += length; - } - return null; - - } - - /** - * Return the underlying xml bean - */ - @Internal - public CTRst getCTRst() { - return st; - } - - protected void setStylesTableReference(StylesTable tbl){ - styles = tbl; - if(st.sizeOfRArray() > 0) { - //noinspection deprecation - for performance reasons! - for (CTRElt r : st.getRArray()) { - CTRPrElt pr = r.getRPr(); - if(pr != null && pr.sizeOfRFontArray() > 0){ - String fontName = pr.getRFontArray(0).getVal(); - if(fontName.startsWith("#")){ - int idx = Integer.parseInt(fontName.substring(1)); - XSSFFont font = styles.getFontAt(idx); - pr.removeRFont(0); - setRunAttributes(font.getCTFont(), pr); - } - } - } - } - } - - /** - * - * CTRPrElt --> CTFont adapter - */ - protected static CTFont toCTFont(CTRPrElt pr){ - CTFont ctFont = CTFont.Factory.newInstance(); - - // Bug 58315: there are files where there is no pr-entry for a RichTextString - if(pr == null) { - return ctFont; - } - - if(pr.sizeOfBArray() > 0) ctFont.addNewB().setVal(pr.getBArray(0).getVal()); - if(pr.sizeOfUArray() > 0) ctFont.addNewU().setVal(pr.getUArray(0).getVal()); - if(pr.sizeOfIArray() > 0) ctFont.addNewI().setVal(pr.getIArray(0).getVal()); - if(pr.sizeOfColorArray() > 0) { - CTColor c1 = pr.getColorArray(0); - CTColor c2 = ctFont.addNewColor(); - if(c1.isSetAuto()) c2.setAuto(c1.getAuto()); - if(c1.isSetIndexed()) c2.setIndexed(c1.getIndexed()); - if(c1.isSetRgb()) c2.setRgb(c1.getRgb()); - if(c1.isSetTheme()) c2.setTheme(c1.getTheme()); - if(c1.isSetTint()) c2.setTint(c1.getTint()); - } - if(pr.sizeOfSzArray() > 0) ctFont.addNewSz().setVal(pr.getSzArray(0).getVal()); - if(pr.sizeOfRFontArray() > 0) ctFont.addNewName().setVal(pr.getRFontArray(0).getVal()); - if(pr.sizeOfFamilyArray() > 0) ctFont.addNewFamily().setVal(pr.getFamilyArray(0).getVal()); - if(pr.sizeOfSchemeArray() > 0) ctFont.addNewScheme().setVal(pr.getSchemeArray(0).getVal()); - if(pr.sizeOfCharsetArray() > 0) ctFont.addNewCharset().setVal(pr.getCharsetArray(0).getVal()); - if(pr.sizeOfCondenseArray() > 0) ctFont.addNewCondense().setVal(pr.getCondenseArray(0).getVal()); - if(pr.sizeOfExtendArray() > 0) ctFont.addNewExtend().setVal(pr.getExtendArray(0).getVal()); - if(pr.sizeOfVertAlignArray() > 0) ctFont.addNewVertAlign().setVal(pr.getVertAlignArray(0).getVal()); - if(pr.sizeOfOutlineArray() > 0) ctFont.addNewOutline().setVal(pr.getOutlineArray(0).getVal()); - if(pr.sizeOfShadowArray() > 0) ctFont.addNewShadow().setVal(pr.getShadowArray(0).getVal()); - if(pr.sizeOfStrikeArray() > 0) ctFont.addNewStrike().setVal(pr.getStrikeArray(0).getVal()); - - return ctFont; - } - - /** - * Add the xml:spaces="preserve" attribute if the string has leading or trailing spaces - * - * @param xs the string to check - */ - protected static void preserveSpaces(STXstring xs) { - String text = xs.getStringValue(); - if (text != null && text.length() > 0) { - char firstChar = text.charAt(0); - char lastChar = text.charAt(text.length() - 1); - if(Character.isWhitespace(firstChar) || Character.isWhitespace(lastChar)) { - XmlCursor c = xs.newCursor(); - c.toNextToken(); - c.insertAttributeWithValue(new QName("http://www.w3.org/XML/1998/namespace", "space"), "preserve"); - c.dispose(); - } - } - } - - /** - * Optimized counting of actual length of a string - * considering the replacement of _xHHHH_ that needs - * to be applied to rich-text strings. - * - * @param value The string - * @return The length of the string, 0 if the string is null. - */ - static int utfLength(String value) { - if(value == null) { - return 0; - } - if (!value.contains("_x")) { - return value.length(); - } - - Matcher matcher = utfPtrn.matcher(value); - int count = 0; - while (matcher.find()) { - count++; - } - - // Length of pattern is 7 (_xHHHH_), and we replace it with one character - return value.length() - (count * 6); - } - - /** - * For all characters which cannot be represented in XML as defined by the XML 1.0 specification, - * the characters are escaped using the Unicode numerical character representation escape character - * format _xHHHH_, where H represents a hexadecimal character in the character's value. - * <p> - * Example: The Unicode character 0D is invalid in an XML 1.0 document, - * so it shall be escaped as <code>_x000D_</code>. - * </p> - * See section 3.18.9 in the OOXML spec. - * - * @param value the string to decode - * @return the decoded string or null if the input string is null - */ - static String utfDecode(String value) { - if(value == null || !value.contains("_x")) { - return value; - } - - StringBuilder buf = new StringBuilder(); - Matcher m = utfPtrn.matcher(value); - int idx = 0; - while(m.find()) { - int pos = m.start(); - if( pos > idx) { - buf.append(value, idx, pos); - } - - String code = m.group(1); - int icode = Integer.decode("0x" + code); - buf.append((char)icode); - - idx = m.end(); - } - - // small optimization: don't go via StringBuilder if not necessary, - // the encodings are very rare, so we should almost always go via this shortcut. - if(idx == 0) { - return value; - } - - buf.append(value.substring(idx)); - return buf.toString(); - } - - void applyFont(TreeMap<Integer, CTRPrElt> formats, int startIndex, int endIndex, CTRPrElt fmt) { - // delete format runs that fit between startIndex and endIndex - // runs intersecting startIndex and endIndex remain - int runStartIdx = 0; - for (Iterator<Integer> it = formats.keySet().iterator(); it.hasNext();) { - int runEndIdx = it.next(); - if (runStartIdx >= startIndex && runEndIdx < endIndex) { - it.remove(); - } - runStartIdx = runEndIdx; - } - - if(startIndex > 0 && !formats.containsKey(startIndex)) { - // If there's a format that starts later in the string, make it start now - for(Map.Entry<Integer, CTRPrElt> entry : formats.entrySet()) { - if(entry.getKey() > startIndex) { - formats.put(startIndex, entry.getValue()); - break; - } - } - } - formats.put(endIndex, fmt); - - // assure that the range [startIndex, endIndex] consists if a single run - // there can be two or three runs depending whether startIndex or endIndex - // intersected existing format runs - SortedMap<Integer, CTRPrElt> sub = formats.subMap(startIndex, endIndex); - while(sub.size() > 1) sub.remove(sub.lastKey()); - } - - TreeMap<Integer, CTRPrElt> getFormatMap(CTRst entry){ - int length = 0; - TreeMap<Integer, CTRPrElt> formats = new TreeMap<>(); - //noinspection deprecation - for performance reasons! - for (CTRElt r : entry.getRArray()) { - String txt = r.getT(); - CTRPrElt fmt = r.getRPr(); - - length += utfLength(txt); - formats.put(length, fmt); - } - return formats; - } - - CTRst buildCTRst(String text, TreeMap<Integer, CTRPrElt> formats){ - if(text.length() != formats.lastKey()) { - throw new IllegalArgumentException("Text length was " + text.length() + - " but the last format index was " + formats.lastKey()); - } - CTRst stf = CTRst.Factory.newInstance(); - int runStartIdx = 0; - for (Map.Entry<Integer, CTRPrElt> me : formats.entrySet()) { - int runEndIdx = me.getKey(); - CTRElt run = stf.addNewR(); - String fragment = text.substring(runStartIdx, runEndIdx); - run.setT(fragment); - preserveSpaces(run.xgetT()); - - CTRPrElt fmt = me.getValue(); - if (fmt != null) { - run.setRPr(fmt); - } - runStartIdx = runEndIdx; - } - return stf; - } - - private ThemesTable getThemesTable() { - if(styles == null) return null; - return styles.getTheme(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java deleted file mode 100644 index 2e285dc747..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ /dev/null @@ -1,781 +0,0 @@ -/* ==================================================================== - 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 java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.Objects; -import java.util.Set; -import java.util.TreeMap; - -import org.apache.poi.ss.SpreadsheetVersion; -import org.apache.poi.ss.formula.FormulaShifter; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellCopyPolicy; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.FormulaError; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.helpers.RowShifter; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.util.Beta; -import org.apache.poi.util.Internal; -import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow; - -/** - * High level representation of a row of a spreadsheet. - */ -public class XSSFRow implements Row, Comparable<XSSFRow> { - /** - * the xml bean containing all cell definitions for this row - */ - private final CTRow _row; - - /** - * Cells of this row keyed by their column indexes. - * The TreeMap ensures that the cells are ordered by columnIndex in the ascending order. - */ - private final TreeMap<Integer, XSSFCell> _cells; - - /** - * the parent sheet - */ - private final XSSFSheet _sheet; - - /** - * Construct a XSSFRow. - * - * @param row the xml bean containing all cell definitions for this row. - * @param sheet the parent sheet. - */ - protected XSSFRow(CTRow row, XSSFSheet sheet) { - _row = row; - _sheet = sheet; - _cells = new TreeMap<>(); - for (CTCell c : row.getCArray()) { - XSSFCell cell = new XSSFCell(this, c); - // Performance optimization for bug 57840: explicit boxing is slightly faster than auto-unboxing, though may use more memory - final Integer colI = Integer.valueOf(cell.getColumnIndex()); // NOSONAR - _cells.put(colI, cell); - sheet.onReadCell(cell); - } - - if (! row.isSetR()) { - // Certain file format writers skip the row number - // Assume no gaps, and give this the next row number - int nextRowNum = sheet.getLastRowNum()+2; - if (nextRowNum == 2 && sheet.getPhysicalNumberOfRows() == 0) { - nextRowNum = 1; - } - row.setR(nextRowNum); - } - } - - /** - * Returns the XSSFSheet this row belongs to - * - * @return the XSSFSheet that owns this row - */ - @Override - public XSSFSheet getSheet() { - return this._sheet; - } - - /** - * Cell iterator over the physically defined cells: - * <blockquote><pre> - * for (Iterator<Cell> it = row.cellIterator(); it.hasNext(); ) { - * Cell cell = it.next(); - * ... - * } - * </pre></blockquote> - * - * @return an iterator over cells in this row. - */ - @Override - @SuppressWarnings("unchecked") - public Iterator<Cell> cellIterator() { - return (Iterator<Cell>)(Iterator<? extends Cell>)_cells.values().iterator(); - } - - /** - * Alias for {@link #cellIterator()} to allow foreach loops: - * <blockquote><pre> - * for(Cell cell : row){ - * ... - * } - * </pre></blockquote> - * - * @return an iterator over cells in this row. - */ - @Override - public Iterator<Cell> iterator() { - return cellIterator(); - } - - /** - * Compares two <code>XSSFRow</code> objects. Two rows are equal if they belong to the same worksheet and - * their row indexes are equal. - * - * @param other the <code>XSSFRow</code> to be compared. - * @return <ul> - * <li> - * the value <code>0</code> if the row number of this <code>XSSFRow</code> is - * equal to the row number of the argument <code>XSSFRow</code> - * </li> - * <li> - * a value less than <code>0</code> if the row number of this this <code>XSSFRow</code> is - * numerically less than the row number of the argument <code>XSSFRow</code> - * </li> - * <li> - * a value greater than <code>0</code> if the row number of this this <code>XSSFRow</code> is - * numerically greater than the row number of the argument <code>XSSFRow</code> - * </li> - * </ul> - * @throws IllegalArgumentException if the argument row belongs to a different worksheet - */ - @Override - public int compareTo(XSSFRow other) { - if (this.getSheet() != other.getSheet()) { - throw new IllegalArgumentException("The compared rows must belong to the same sheet"); - } - - int thisRow = this.getRowNum(); - int otherRow = other.getRowNum(); - return Integer.compare(thisRow, otherRow); - } - - @Override - public boolean equals(Object obj) - { - if (!(obj instanceof XSSFRow)) - { - return false; - } - XSSFRow other = (XSSFRow) obj; - - return (this.getRowNum() == other.getRowNum()) && - (this.getSheet() == other.getSheet()); - } - - @Override - public int hashCode() { - return _row.hashCode(); - } - - /** - * Use this to create new cells within the row and return it. - * <p> - * The cell that is returned is a {@link CellType#BLANK}. The type can be changed - * either through calling <code>setCellValue</code> or <code>setCellType</code>. - * </p> - * @param columnIndex - the column number this cell represents - * @return Cell a high level representation of the created cell. - * @throws IllegalArgumentException if columnIndex < 0 or greater than 16384, - * the maximum number of columns supported by the SpreadsheetML format (.xlsx) - */ - @Override - public XSSFCell createCell(int columnIndex) { - return createCell(columnIndex, CellType.BLANK); - } - - /** - * Use this to create new cells within the row and return it. - * - * @param columnIndex - the column number this cell represents - * @param type - the cell's data type - * @return XSSFCell a high level representation of the created cell. - * @throws IllegalArgumentException if the specified cell type is invalid, columnIndex < 0 - * or greater than 16384, the maximum number of columns supported by the SpreadsheetML format (.xlsx) - */ - @Override - public XSSFCell createCell(int columnIndex, CellType type) { - // Performance optimization for bug 57840: explicit boxing is slightly faster than auto-unboxing, though may use more memory - final Integer colI = Integer.valueOf(columnIndex); // NOSONAR - CTCell ctCell; - XSSFCell prev = _cells.get(colI); - if(prev != null){ - ctCell = prev.getCTCell(); - ctCell.set(CTCell.Factory.newInstance()); - } else { - ctCell = _row.addNewC(); - } - XSSFCell xcell = new XSSFCell(this, ctCell); - try { - xcell.setCellNum(columnIndex); - } catch (IllegalArgumentException e) { - // we need to undo adding the CTCell in _row if something fails here, e.g. - // cell-limits are exceeded - _row.removeC(_row.getCList().size()-1); - - throw e; - } - if (type != CellType.BLANK && type != CellType.FORMULA) { - setDefaultValue(xcell, type); - } - - _cells.put(colI, xcell); - return xcell; - } - - private static void setDefaultValue(XSSFCell cell, CellType type) { - switch (type) { - case NUMERIC: - cell.setCellValue(0); - break; - case STRING: - cell.setCellValue(""); - break; - case BOOLEAN: - cell.setCellValue(false); - break; - case ERROR: - cell.setCellErrorValue(FormulaError._NO_ERROR); - break; - default: - throw new AssertionError("Unknown cell-type specified: " + type); - } - } - - /** - * Returns the cell at the given (0 based) index, - * with the {@link org.apache.poi.ss.usermodel.Row.MissingCellPolicy} from the parent Workbook. - * - * @return the cell at the given (0 based) index - */ - @Override - public XSSFCell getCell(int cellnum) { - return getCell(cellnum, _sheet.getWorkbook().getMissingCellPolicy()); - } - - /** - * Returns the cell at the given (0 based) index, with the specified {@link org.apache.poi.ss.usermodel.Row.MissingCellPolicy} - * - * @return the cell at the given (0 based) index - * @throws IllegalArgumentException if cellnum < 0 or the specified MissingCellPolicy is invalid - */ - @Override - public XSSFCell getCell(int cellnum, MissingCellPolicy policy) { - if(cellnum < 0) { - throw new IllegalArgumentException("Cell index must be >= 0"); - } - - // Performance optimization for bug 57840: explicit boxing is slightly faster than auto-unboxing, though may use more memory - final Integer colI = Integer.valueOf(cellnum); // NOSONAR - XSSFCell cell = _cells.get(colI); - switch (policy) { - case RETURN_NULL_AND_BLANK: - return cell; - case RETURN_BLANK_AS_NULL: - boolean isBlank = (cell != null && cell.getCellType() == CellType.BLANK); - return (isBlank) ? null : cell; - case CREATE_NULL_AS_BLANK: - return (cell == null) ? createCell(cellnum, CellType.BLANK) : cell; - default: - throw new IllegalArgumentException("Illegal policy " + policy); - } - } - - /** - * Get the 0-based number of the first cell contained in this row. - * - * @return short representing the first logical cell in the row, - * or -1 if the row does not contain any cells. - */ - @Override - public short getFirstCellNum() { - return (short)(_cells.size() == 0 ? -1 : _cells.firstKey()); - } - - /** - * Gets the index of the last cell contained in this row <b>PLUS ONE</b>. The result also - * happens to be the 1-based column number of the last cell. This value can be used as a - * standard upper bound when iterating over cells: - * <pre> - * short minColIx = row.getFirstCellNum(); - * short maxColIx = row.getLastCellNum(); - * for(short colIx=minColIx; colIx<maxColIx; colIx++) { - * XSSFCell cell = row.getCell(colIx); - * if(cell == null) { - * continue; - * } - * //... do something with cell - * } - * </pre> - * - * @return short representing the last logical cell in the row <b>PLUS ONE</b>, - * or -1 if the row does not contain any cells. - */ - @Override - public short getLastCellNum() { - return (short)(_cells.size() == 0 ? -1 : (_cells.lastKey() + 1)); - } - - /** - * Get the row's height measured in twips (1/20th of a point). If the height is not set, the default worksheet value is returned, - * See {@link org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()} - * - * @return row height measured in twips (1/20th of a point) - */ - @Override - public short getHeight() { - return (short)(getHeightInPoints()*20); - } - - /** - * Returns row height measured in point size. If the height is not set, the default worksheet value is returned, - * See {@link org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()} - * - * @return row height measured in point size - * @see org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints() - */ - @Override - public float getHeightInPoints() { - if (this._row.isSetHt()) { - return (float) this._row.getHt(); - } - return _sheet.getDefaultRowHeightInPoints(); - } - - /** - * Set the height in "twips" or 1/20th of a point. - * - * @param height the height in "twips" or 1/20th of a point. <code>-1</code> resets to the default height - */ - @Override - public void setHeight(short height) { - if (height == -1) { - if (_row.isSetHt()) { - _row.unsetHt(); - } - if (_row.isSetCustomHeight()) { - _row.unsetCustomHeight(); - } - } else { - _row.setHt((double) height / 20); - _row.setCustomHeight(true); - - } - } - - /** - * Set the row's height in points. - * - * @param height the height in points. <code>-1</code> resets to the default height - */ - @Override - public void setHeightInPoints(float height) { - setHeight((short)(height == -1 ? -1 : (height*20))); - } - - /** - * Gets the number of defined cells (NOT number of cells in the actual row!). - * That is to say if only columns 0,4,5 have values then there would be 3. - * - * @return int representing the number of defined cells in the row. - */ - @Override - public int getPhysicalNumberOfCells() { - return _cells.size(); - } - - /** - * Get row number this row represents - * - * @return the row number (0 based) - */ - @Override - public int getRowNum() { - return Math.toIntExact(_row.getR() - 1); - } - - /** - * Set the row number of this row. - * - * @param rowIndex the row number (0-based) - * @throws IllegalArgumentException if rowNum < 0 or greater than 1048575 - */ - @Override - public void setRowNum(int rowIndex) { - int maxrow = SpreadsheetVersion.EXCEL2007.getLastRowIndex(); - if (rowIndex < 0 || rowIndex > maxrow) { - throw new IllegalArgumentException("Invalid row number (" + rowIndex - + ") outside allowable range (0.." + maxrow + ")"); - } - _row.setR(rowIndex + 1L); - } - - /** - * Get whether or not to display this row with 0 height - * - * @return - height is zero or not. - */ - @Override - public boolean getZeroHeight() { - return this._row.getHidden(); - } - - /** - * Set whether or not to display this row with 0 height - * - * @param height height is zero or not. - */ - @Override - public void setZeroHeight(boolean height) { - this._row.setHidden(height); - - } - - /** - * Is this row formatted? Most aren't, but some rows - * do have whole-row styles. For those that do, you - * can get the formatting from {@link #getRowStyle()} - */ - @Override - public boolean isFormatted() { - return _row.isSetS(); - } - /** - * Returns the whole-row cell style. Most rows won't - * have one of these, so will return null. Call - * {@link #isFormatted()} to check first. - */ - @Override - public XSSFCellStyle getRowStyle() { - if(!isFormatted()) { - return null; - } - - StylesTable stylesSource = getSheet().getWorkbook().getStylesSource(); - if(stylesSource.getNumCellStyles() > 0) { - return stylesSource.getStyleAt(Math.toIntExact(_row.getS())); - } else { - return null; - } - } - - /** - * Applies a whole-row cell styling to the row. - * If the value is null then the style information is removed, - * causing the cell to used the default workbook style. - */ - @Override - public void setRowStyle(CellStyle style) { - if(style == null) { - if(_row.isSetS()) { - _row.unsetS(); - _row.unsetCustomFormat(); - } - } else { - StylesTable styleSource = getSheet().getWorkbook().getStylesSource(); - - XSSFCellStyle xStyle = (XSSFCellStyle)style; - xStyle.verifyBelongsToStylesSource(styleSource); - - long idx = styleSource.putStyle(xStyle); - _row.setS(idx); - _row.setCustomFormat(true); - } - } - - /** - * Remove the Cell from this row. - * - * @param cell the cell to remove - */ - @Override - public void removeCell(Cell cell) { - if (cell.getRow() != this) { - throw new IllegalArgumentException("Specified cell does not belong to this row"); - } - //noinspection SuspiciousMethodCalls - if(!_cells.containsValue(cell)) { - throw new IllegalArgumentException("the row does not contain this cell"); - } - - XSSFCell xcell = (XSSFCell)cell; - if(xcell.isPartOfArrayFormulaGroup()) { - xcell.setCellFormula(null); // to remove the array formula - } - if(cell.getCellType() == CellType.FORMULA) { - _sheet.getWorkbook().onDeleteFormula(xcell); - } - // Performance optimization for bug 57840: explicit boxing is slightly faster than auto-unboxing, though may use more memory - final Integer colI = Integer.valueOf(cell.getColumnIndex()); // NOSONAR - XSSFCell removed = _cells.remove(colI); - - // also remove the corresponding CTCell from the _row.cArray, - // it may not be at the same position right now - // thus search for it - int i = 0; - for (CTCell ctCell : _row.getCArray()) { - if(ctCell == removed.getCTCell()) { - _row.removeC(i); - } - i++; - } - } - - /** - * Returns the underlying CTRow xml bean containing all cell definitions in this row - * - * @return the underlying CTRow xml bean - */ - @Internal - public CTRow getCTRow(){ - return _row; - } - - /** - * Fired when the document is written to an output stream. - * - * @see org.apache.poi.xssf.usermodel.XSSFSheet#write(java.io.OutputStream) () - */ - protected void onDocumentWrite() { - // _row.cArray and _cells.getCTCell might be out of sync after adding/removing cells, - // thus we need to re-order it here to make the resulting file correct - - // do a quick check if there is work to do to not incur the overhead if not necessary anyway - CTCell[] cArrayOrig = _row.getCArray(); - if(cArrayOrig.length == _cells.size()) { - boolean allEqual = true; - Iterator<XSSFCell> it = _cells.values().iterator(); - for (CTCell ctCell : cArrayOrig) { - XSSFCell cell = it.next(); - - // we want to compare on identity here on purpose - // as we want to ensure that both lists contain the - // same documents, not copies! - if (ctCell != cell.getCTCell()) { - allEqual = false; - break; - } - } - - // we did not find any difference, so we can skip the work - if(allEqual) { - return; - } - } - - fixupCTCells(cArrayOrig); - } - - private void fixupCTCells(CTCell[] cArrayOrig) { - // copy all values to 2nd array and a map for lookup of index - CTCell[] cArrayCopy = new CTCell[cArrayOrig.length]; - IdentityHashMap<CTCell, Integer> map = new IdentityHashMap<>(_cells.size()); - int i = 0; - for (CTCell ctCell : cArrayOrig) { - cArrayCopy[i] = (CTCell) ctCell.copy(); - map.put(ctCell, i); - i++; - } - - // populate _row.cArray correctly - i = 0; - for (XSSFCell cell : _cells.values()) { - // no need to change anything if position is correct - Integer correctPosition = map.get(cell.getCTCell()); - Objects.requireNonNull(correctPosition, "Should find CTCell in _row"); - if(correctPosition != i) { - // we need to re-populate this CTCell - _row.setCArray(i, cArrayCopy[correctPosition]); - cell.setCTCell(_row.getCArray(i)); - } - i++; - } - - // remove any remaining illegal references in _rows.cArray - while(cArrayOrig.length > _cells.size()) { - _row.removeC(_cells.size()); - } - } - - /** - * @return formatted xml representation of this row - */ - @Override - public String toString(){ - return _row.toString(); - } - - /** - * update cell references when shifting rows - * - * @param n the number of rows to move - */ - protected void shift(int n) { - int rownum = getRowNum() + n; - String msg = "Row[rownum=" + getRowNum() + "] contains cell(s) included in a multi-cell array formula. " + - "You cannot change part of an array."; - setRowNum(rownum); - for(Cell c : this){ - ((XSSFCell)c).updateCellReferencesForShifting(msg); - } - - } - - /** - * Copy the cells from srcRow to this row - * If this row is not a blank row, this will merge the two rows, overwriting - * the cells in this row with the cells in srcRow - * If srcRow is null, overwrite cells in destination row with blank values, styles, etc per cell copy policy - * srcRow may be from a different sheet in the same workbook - * @param srcRow the rows to copy from - * @param policy the policy to determine what gets copied - */ - @Beta - public void copyRowFrom(Row srcRow, CellCopyPolicy policy) { - if (srcRow == null) { - // srcRow is blank. Overwrite cells with blank values, blank styles, etc per cell copy policy - for (Cell destCell : this) { - final XSSFCell srcCell = null; - // FIXME: remove type casting when copyCellFrom(Cell, CellCopyPolicy) is added to Cell interface - ((XSSFCell)destCell).copyCellFrom(srcCell, policy); - } - - if (policy.isCopyMergedRegions()) { - // Remove MergedRegions in dest row - final int destRowNum = getRowNum(); - int index = 0; - final Set<Integer> indices = new HashSet<>(); - for (CellRangeAddress destRegion : getSheet().getMergedRegions()) { - if (destRowNum == destRegion.getFirstRow() && destRowNum == destRegion.getLastRow()) { - indices.add(index); - } - index++; - } - getSheet().removeMergedRegions(indices); - } - - if (policy.isCopyRowHeight()) { - // clear row height - setHeight((short)-1); - } - - } - else { - for (final Cell c : srcRow){ - final XSSFCell srcCell = (XSSFCell)c; - final XSSFCell destCell = createCell(srcCell.getColumnIndex()); - destCell.copyCellFrom(srcCell, policy); - } - - final int sheetIndex = _sheet.getWorkbook().getSheetIndex(_sheet); - final String sheetName = _sheet.getWorkbook().getSheetName(sheetIndex); - final int srcRowNum = srcRow.getRowNum(); - final int destRowNum = getRowNum(); - final int rowDifference = destRowNum - srcRowNum; - - final FormulaShifter formulaShifter = FormulaShifter.createForRowCopy(sheetIndex, sheetName, srcRowNum, srcRowNum, rowDifference, SpreadsheetVersion.EXCEL2007); - final XSSFRowShifter rowShifter = new XSSFRowShifter(_sheet); - rowShifter.updateRowFormulas(this, formulaShifter); - - // Copy merged regions that are fully contained on the row - // FIXME: is this something that rowShifter could be doing? - if (policy.isCopyMergedRegions()) { - for (CellRangeAddress srcRegion : srcRow.getSheet().getMergedRegions()) { - if (srcRowNum == srcRegion.getFirstRow() && srcRowNum == srcRegion.getLastRow()) { - CellRangeAddress destRegion = srcRegion.copy(); - destRegion.setFirstRow(destRowNum); - destRegion.setLastRow(destRowNum); - getSheet().addMergedRegion(destRegion); - } - } - } - - if (policy.isCopyRowHeight()) { - setHeight(srcRow.getHeight()); - } - } - } - - @Override - public int getOutlineLevel() { - return _row.getOutlineLevel(); - } - - /** - * Shifts column range [firstShiftColumnIndex-lastShiftColumnIndex] step places to the right. - * @param firstShiftColumnIndex the column to start shifting - * @param lastShiftColumnIndex the column to end shifting - * @param step length of the shifting step - */ - @Override - public void shiftCellsRight(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) { - RowShifter.validateShiftParameters(firstShiftColumnIndex, lastShiftColumnIndex, step); - - for (int columnIndex = lastShiftColumnIndex; columnIndex >= firstShiftColumnIndex; columnIndex--){ // process cells backwards, because of shifting - shiftCell(columnIndex, step); - } - for (int columnIndex = firstShiftColumnIndex; columnIndex <= firstShiftColumnIndex+step-1; columnIndex++) - { - _cells.remove(columnIndex); - XSSFCell targetCell = getCell(columnIndex); - if(targetCell != null) { - targetCell.getCTCell().set(CTCell.Factory.newInstance()); - } - } - } - - /** - * Shifts column range [firstShiftColumnIndex-lastShiftColumnIndex] step places to the left. - * @param firstShiftColumnIndex the column to start shifting - * @param lastShiftColumnIndex the column to end shifting - * @param step length of the shifting step - */ - @Override - public void shiftCellsLeft(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) { - RowShifter.validateShiftLeftParameters(firstShiftColumnIndex, lastShiftColumnIndex, step); - - for (int columnIndex = firstShiftColumnIndex; columnIndex <= lastShiftColumnIndex; columnIndex++){ - shiftCell(columnIndex, -step); - } - for (int columnIndex = lastShiftColumnIndex-step+1; columnIndex <= lastShiftColumnIndex; columnIndex++){ - _cells.remove(columnIndex); - XSSFCell targetCell = getCell(columnIndex); - if(targetCell != null) { - targetCell.getCTCell().set(CTCell.Factory.newInstance()); - } - } - } - - private void shiftCell(int columnIndex, int step/*pass negative value for left shift*/){ - if(columnIndex + step < 0) { - throw new IllegalStateException("Column index less than zero : " + (Integer.valueOf(columnIndex + step))); - } - - XSSFCell currentCell = getCell(columnIndex); - if(currentCell != null){ - currentCell.setCellNum(columnIndex+step); - _cells.put(columnIndex+step, currentCell); - } - else { - _cells.remove(columnIndex+step); - XSSFCell targetCell = getCell(columnIndex+step); - if(targetCell != null) { - targetCell.getCTCell().set(CTCell.Factory.newInstance()); - } - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java deleted file mode 100644 index 8f7489434c..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java +++ /dev/null @@ -1,139 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.Shape; -import org.apache.poi.util.Units; -import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNoFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; - -/** - * Represents a shape in a SpreadsheetML drawing. - */ -public abstract class XSSFShape implements Shape { - - /** - * Parent drawing - */ - protected XSSFDrawing drawing; - - /** - * The parent shape, always not-null for shapes in groups - */ - protected XSSFShapeGroup parent; - - /** - * anchor that is used by this shape - */ - protected XSSFAnchor anchor; - - /** - * Return the drawing that owns this shape - * - * @return the parent drawing that owns this shape - */ - public XSSFDrawing getDrawing(){ - return drawing; - } - - @Override - public XSSFShapeGroup getParent() - { - return parent; - } - - /** - * @return the anchor that is used by this shape. - */ - @Override - public XSSFAnchor getAnchor() - { - return anchor; - } - - /** - * Returns xml bean with shape properties. - * - * @return xml bean with shape properties. - */ - protected abstract CTShapeProperties getShapeProperties(); - - @Override - public boolean isNoFill() { - return getShapeProperties().isSetNoFill(); - } - - @Override - public void setNoFill(boolean noFill) { - CTShapeProperties props = getShapeProperties(); - //unset solid and pattern fills if they are set - if (props.isSetPattFill()) props.unsetPattFill(); - if (props.isSetSolidFill()) props.unsetSolidFill(); - - props.setNoFill(CTNoFillProperties.Factory.newInstance()); - } - - @Override - public void setFillColor(int red, int green, int blue) { - CTShapeProperties props = getShapeProperties(); - CTSolidColorFillProperties fill = props.isSetSolidFill() ? props.getSolidFill() : props.addNewSolidFill(); - CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); - rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue}); - fill.setSrgbClr(rgb); - } - - @Override - public void setLineStyleColor( int red, int green, int blue ) { - CTShapeProperties props = getShapeProperties(); - CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); - CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill(); - CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); - rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue}); - fill.setSrgbClr(rgb); - } - - /** - * Specifies the width to be used for the underline stroke. - * - * @param lineWidth width in points - */ - public void setLineWidth( double lineWidth ) { - CTShapeProperties props = getShapeProperties(); - CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); - ln.setW((int)(lineWidth*Units.EMU_PER_POINT)); - } - - /** - * Sets the line style. - * - * @param lineStyle - */ - public void setLineStyle( int lineStyle ) { - CTShapeProperties props = getShapeProperties(); - CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); - CTPresetLineDashProperties dashStyle = CTPresetLineDashProperties.Factory.newInstance(); - dashStyle.setVal(STPresetLineDashVal.Enum.forInt(lineStyle+1)); - ln.setPrstDash(dashStyle); - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java deleted file mode 100644 index 96c7c9bcd3..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java +++ /dev/null @@ -1,237 +0,0 @@ -/* ==================================================================== - 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 java.util.Iterator; - -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.ss.usermodel.ShapeContainer; -import org.apache.poi.util.Internal; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTConnector; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGroupShape; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTGroupShapeNonVisual; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTPicture; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; - -/** - * This object specifies a group shape that represents many shapes grouped together. This shape is to be treated - * just as if it were a regular shape but instead of being described by a single geometry it is made up of all the - * shape geometries encompassed within it. Within a group shape each of the shapes that make up the group are - * specified just as they normally would. - */ -public final class XSSFShapeGroup extends XSSFShape implements ShapeContainer<XSSFShape> { - private static CTGroupShape prototype; - - private CTGroupShape ctGroup; - - /** - * Construct a new XSSFSimpleShape object. - * - * @param drawing the XSSFDrawing that owns this shape - * @param ctGroup the XML bean that stores this group content - */ - protected XSSFShapeGroup(XSSFDrawing drawing, CTGroupShape ctGroup) { - this.drawing = drawing; - this.ctGroup = ctGroup; - } - - /** - * Initialize default structure of a new shape group - */ - protected static CTGroupShape prototype() { - if (prototype == null) { - CTGroupShape shape = CTGroupShape.Factory.newInstance(); - - CTGroupShapeNonVisual nv = shape.addNewNvGrpSpPr(); - CTNonVisualDrawingProps nvpr = nv.addNewCNvPr(); - nvpr.setId(0); - nvpr.setName("Group 0"); - nv.addNewCNvGrpSpPr(); - CTGroupShapeProperties sp = shape.addNewGrpSpPr(); - CTGroupTransform2D t2d = sp.addNewXfrm(); - CTPositiveSize2D p1 = t2d.addNewExt(); - p1.setCx(0); - p1.setCy(0); - CTPoint2D p2 = t2d.addNewOff(); - p2.setX(0); - p2.setY(0); - CTPositiveSize2D p3 = t2d.addNewChExt(); - p3.setCx(0); - p3.setCy(0); - CTPoint2D p4 = t2d.addNewChOff(); - p4.setX(0); - p4.setY(0); - - prototype = shape; - } - return prototype; - } - - /** - * Constructs a textbox. - * - * @param anchor the child anchor describes how this shape is attached - * to the group. - * @return the newly created textbox. - */ - public XSSFTextBox createTextbox(XSSFChildAnchor anchor){ - CTShape ctShape = ctGroup.addNewSp(); - ctShape.set(XSSFSimpleShape.prototype()); - - XSSFTextBox shape = new XSSFTextBox(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - shape.setXfrm(anchor.getCTTransform2D()); - return shape; - - } - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor the child anchor describes how this shape is attached - * to the group. - * @return the newly created shape. - */ - public XSSFSimpleShape createSimpleShape(XSSFChildAnchor anchor) { - CTShape ctShape = ctGroup.addNewSp(); - ctShape.set(XSSFSimpleShape.prototype()); - - XSSFSimpleShape shape = new XSSFSimpleShape(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - shape.setXfrm(anchor.getCTTransform2D()); - return shape; - } - - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor the child anchor describes how this shape is attached - * to the group. - * @return the newly created shape. - */ - public XSSFConnector createConnector(XSSFChildAnchor anchor) { - CTConnector ctShape = ctGroup.addNewCxnSp(); - ctShape.set(XSSFConnector.prototype()); - - XSSFConnector shape = new XSSFConnector(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - shape.getCTConnector().getSpPr().setXfrm(anchor.getCTTransform2D()); - return shape; - } - - /** - * Creates a picture. - * - * @param anchor the client anchor describes how this picture is attached to the sheet. - * @param pictureIndex the index of the picture in the workbook collection of pictures, - * {@link XSSFWorkbook#getAllPictures()} . - * @return the newly created picture shape. - */ - public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) { - PackageRelationship rel = getDrawing().addPictureReference(pictureIndex); - - CTPicture ctShape = ctGroup.addNewPic(); - ctShape.set(XSSFPicture.prototype()); - - XSSFPicture shape = new XSSFPicture(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - shape.setPictureReference(rel); - return shape; - } - - /** - * Creates a group shape. - * - * @param anchor the client anchor describes how this group is attached to the group. - * @return the newly created group shape. - */ - public XSSFShapeGroup createGroup(XSSFChildAnchor anchor) { - CTGroupShape ctShape = ctGroup.addNewGrpSp(); - ctShape.set(prototype()); - - XSSFShapeGroup shape = new XSSFShapeGroup(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - - // TODO: calculate bounding rectangle on anchor and set off/ext correctly - - CTGroupTransform2D xfrm = shape.getCTGroupShape().getGrpSpPr().getXfrm(); - CTTransform2D t2 = anchor.getCTTransform2D(); - xfrm.setOff(t2.getOff()); - xfrm.setExt(t2.getExt()); - // child offset is left to 0,0 - xfrm.setChExt(t2.getExt()); - xfrm.setFlipH(t2.getFlipH()); - xfrm.setFlipV(t2.getFlipV()); - - return shape; - } - - @Internal - public CTGroupShape getCTGroupShape() { - return ctGroup; - } - - /** - * Sets the coordinate space of this group. All children are constrained - * to these coordinates. - */ - public void setCoordinates(int x1, int y1, int x2, int y2) { - CTGroupTransform2D t2d = ctGroup.getGrpSpPr().getXfrm(); - CTPoint2D off = t2d.getOff(); - off.setX(x1); - off.setY(y1); - CTPositiveSize2D ext = t2d.getExt(); - ext.setCx(x2); - ext.setCy(y2); - - CTPoint2D chOff = t2d.getChOff(); - chOff.setX(x1); - chOff.setY(y1); - CTPositiveSize2D chExt = t2d.getChExt(); - chExt.setCx(x2); - chExt.setCy(y2); - } - - @Override - protected CTShapeProperties getShapeProperties() { - throw new IllegalStateException("Not supported for shape group"); - } - - @Override - public Iterator<XSSFShape> iterator() { - return getDrawing().getShapes(this).iterator(); - } - - @Override - public String getShapeName() { - return ctGroup.getNvGrpSpPr().getCNvPr().getName(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java deleted file mode 100644 index 571d4fb766..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ /dev/null @@ -1,4702 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; -import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.setPassword; -import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.validatePassword; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; - -import javax.xml.namespace.QName; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.PartAlreadyExistsException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.ss.SpreadsheetVersion; -import org.apache.poi.ss.formula.FormulaShifter; -import org.apache.poi.ss.formula.SheetNameFormatter; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellCopyPolicy; -import org.apache.poi.ss.usermodel.CellRange; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.DataValidation; -import org.apache.poi.ss.usermodel.DataValidationHelper; -import org.apache.poi.ss.usermodel.Font; -import org.apache.poi.ss.usermodel.Footer; -import org.apache.poi.ss.usermodel.FormulaEvaluator; -import org.apache.poi.ss.usermodel.Header; -import org.apache.poi.ss.usermodel.IgnoredErrorType; -import org.apache.poi.ss.usermodel.Name; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Table; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.AreaReference; -import org.apache.poi.ss.util.CellAddress; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.ss.util.PaneInformation; -import org.apache.poi.ss.util.SSCellRange; -import org.apache.poi.ss.util.SheetUtil; -import org.apache.poi.util.Beta; -import org.apache.poi.util.Internal; -import org.apache.poi.util.Units; -import org.apache.poi.xssf.model.CommentsTable; -import org.apache.poi.xssf.usermodel.XSSFPivotTable.PivotTableReferenceConfigurator; -import org.apache.poi.xssf.usermodel.helpers.ColumnHelper; -import org.apache.poi.xssf.usermodel.helpers.XSSFColumnShifter; -import org.apache.poi.xssf.usermodel.helpers.XSSFIgnoredErrorHelper; -import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; - -/** - * High level representation of a SpreadsheetML worksheet. - * - * <p> - * Sheets are the central structures within a workbook, and are where a user does most of his spreadsheet work. - * The most common type of sheet is the worksheet, which is represented as a grid of cells. Worksheet cells can - * contain text, numbers, dates, and formulas. Cells can also be formatted. - * </p> - */ -public class XSSFSheet extends POIXMLDocumentPart implements Sheet { - private static final Logger LOG = LogManager.getLogger(XSSFSheet.class); - - private static final double DEFAULT_ROW_HEIGHT = 15.0; - private static final double DEFAULT_MARGIN_HEADER = 0.3; - private static final double DEFAULT_MARGIN_FOOTER = 0.3; - private static final double DEFAULT_MARGIN_TOP = 0.75; - private static final double DEFAULT_MARGIN_BOTTOM = 0.75; - private static final double DEFAULT_MARGIN_LEFT = 0.7; - private static final double DEFAULT_MARGIN_RIGHT = 0.7; - - /** - * Kept for backwards-compatibility, use {@link Font#TWIPS_PER_POINT} instead. - * @deprecated POI 5.0.0 - */ - public static final int TWIPS_PER_POINT = Font.TWIPS_PER_POINT; - - //TODO make the two variable below private! - protected CTSheet sheet; - protected CTWorksheet worksheet; - - private final SortedMap<Integer, XSSFRow> _rows = new TreeMap<>(); - private List<XSSFHyperlink> hyperlinks; - private ColumnHelper columnHelper; - private CommentsTable sheetComments; - /** - * cache of master shared formulas in this sheet. - * Master shared formula is the first formula in a group of shared formulas is saved in the f element. - */ - private Map<Integer, CTCellFormula> sharedFormulas; - private SortedMap<String,XSSFTable> tables; - private List<CellRangeAddress> arrayFormulas; - private final XSSFDataValidationHelper dataValidationHelper; - - /** - * Creates new XSSFSheet - called by XSSFWorkbook to create a sheet from scratch. - * - * @see XSSFWorkbook#createSheet() - */ - protected XSSFSheet() { - super(); - dataValidationHelper = new XSSFDataValidationHelper(this); - onDocumentCreate(); - } - - /** - * Creates an XSSFSheet representing the given package part and relationship. - * Should only be called by XSSFWorkbook when reading in an existing file. - * - * @param part - The package part that holds xml data representing this sheet. - * - * @since POI 3.14-Beta1 - */ - protected XSSFSheet(PackagePart part) { - super(part); - dataValidationHelper = new XSSFDataValidationHelper(this); - } - - /** - * Returns the parent XSSFWorkbook - * - * @return the parent XSSFWorkbook - */ - @Override - public XSSFWorkbook getWorkbook() { - return (XSSFWorkbook)getParent(); - } - - /** - * Initialize worksheet data when reading in an exisiting file. - */ - @Override - protected void onDocumentRead() { - try { - read(getPackagePart().getInputStream()); - } catch (IOException e){ - throw new POIXMLException(e); - } - } - - protected void read(InputStream is) throws IOException { - try { - worksheet = WorksheetDocument.Factory.parse(is, DEFAULT_XML_OPTIONS).getWorksheet(); - } catch (XmlException e){ - throw new POIXMLException(e); - } - - initRows(worksheet); - columnHelper = new ColumnHelper(worksheet); - // Look for bits we're interested in - for(RelationPart rp : getRelationParts()){ - POIXMLDocumentPart p = rp.getDocumentPart(); - if(p instanceof CommentsTable) { - sheetComments = (CommentsTable)p; - } - if(p instanceof XSSFTable) { - tables.put( rp.getRelationship().getId(), (XSSFTable)p ); - } - if(p instanceof XSSFPivotTable) { - getWorkbook().getPivotTables().add((XSSFPivotTable) p); - } - } - - // Process external hyperlinks for the sheet, if there are any - initHyperlinks(); - } - - /** - * Initialize worksheet data when creating a new sheet. - */ - @Override - protected void onDocumentCreate(){ - worksheet = newSheet(); - initRows(worksheet); - columnHelper = new ColumnHelper(worksheet); - hyperlinks = new ArrayList<>(); - } - - private void initRows(CTWorksheet worksheetParam) { - _rows.clear(); - tables = new TreeMap<>(); - sharedFormulas = new HashMap<>(); - arrayFormulas = new ArrayList<>(); - for (CTRow row : worksheetParam.getSheetData().getRowArray()) { - XSSFRow r = new XSSFRow(row, this); - // Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory - //noinspection UnnecessaryBoxing - final Integer rownumI = Integer.valueOf(r.getRowNum()); // NOSONAR - _rows.put(rownumI, r); - } - } - - /** - * Read hyperlink relations, link them with CTHyperlink beans in this worksheet - * and initialize the internal array of XSSFHyperlink objects - */ - private void initHyperlinks() { - hyperlinks = new ArrayList<>(); - - if(!worksheet.isSetHyperlinks()) { - return; - } - - try { - PackageRelationshipCollection hyperRels = - getPackagePart().getRelationshipsByType(XSSFRelation.SHEET_HYPERLINKS.getRelation()); - - // Turn each one into a XSSFHyperlink - for(CTHyperlink hyperlink : worksheet.getHyperlinks().getHyperlinkArray()) { - PackageRelationship hyperRel = null; - if(hyperlink.getId() != null) { - hyperRel = hyperRels.getRelationshipByID(hyperlink.getId()); - } - - hyperlinks.add( new XSSFHyperlink(hyperlink, hyperRel) ); - } - } catch (InvalidFormatException e){ - throw new POIXMLException(e); - } - } - - /** - * Create a new CTWorksheet instance with all values set to defaults - * - * @return a new instance - */ - private static CTWorksheet newSheet(){ - CTWorksheet worksheet = CTWorksheet.Factory.newInstance(); - CTSheetFormatPr ctFormat = worksheet.addNewSheetFormatPr(); - ctFormat.setDefaultRowHeight(DEFAULT_ROW_HEIGHT); - - CTSheetView ctView = worksheet.addNewSheetViews().addNewSheetView(); - ctView.setWorkbookViewId(0); - - worksheet.addNewDimension().setRef("A1"); - - worksheet.addNewSheetData(); - - CTPageMargins ctMargins = worksheet.addNewPageMargins(); - ctMargins.setBottom(DEFAULT_MARGIN_BOTTOM); - ctMargins.setFooter(DEFAULT_MARGIN_FOOTER); - ctMargins.setHeader(DEFAULT_MARGIN_HEADER); - ctMargins.setLeft(DEFAULT_MARGIN_LEFT); - ctMargins.setRight(DEFAULT_MARGIN_RIGHT); - ctMargins.setTop(DEFAULT_MARGIN_TOP); - - return worksheet; - } - - /** - * Provide access to the CTWorksheet bean holding this sheet's data - * - * @return the CTWorksheet bean holding this sheet's data - */ - @Internal - public CTWorksheet getCTWorksheet() { - return this.worksheet; - } - - public ColumnHelper getColumnHelper() { - return columnHelper; - } - - /** - * Returns the name of this sheet - * - * @return the name of this sheet - */ - @Override - public String getSheetName() { - return sheet.getName(); - } - - /** - * Adds a merged region of cells on a sheet. - * - * @param region to merge - * @return index of this region - * @throws IllegalArgumentException if region contains fewer than 2 cells - * @throws IllegalStateException if region intersects with a multi-cell array formula - * @throws IllegalStateException if region intersects with an existing region on this sheet - */ - @Override - public int addMergedRegion(CellRangeAddress region) { - return addMergedRegion(region, true); - } - - /** - * Adds a merged region of cells (hence those cells form one). - * Skips validation. It is possible to create overlapping merged regions - * or create a merged region that intersects a multi-cell array formula - * with this formula, which may result in a corrupt workbook. - * - * To check for merged regions overlapping array formulas or other merged regions - * after addMergedRegionUnsafe has been called, call {@link #validateMergedRegions()}, which runs in O(n^2) time. - * - * @param region to merge - * @return index of this region - * @throws IllegalArgumentException if region contains fewer than 2 cells - */ - @Override - public int addMergedRegionUnsafe(CellRangeAddress region) { - return addMergedRegion(region, false); - } - - /** - * Adds a merged region of cells (hence those cells form one). - * If validate is true, check to make sure adding the merged region to the sheet doesn't create a corrupt workbook - * If validate is false, skips the expensive merged region checks, but may produce a corrupt workbook. - * - * @param region to merge - * @param validate whether to validate merged region - * @return 0-based index of this region - * @throws IllegalArgumentException if region contains fewer than 2 cells (this check is inexpensive and is performed regardless of <tt>validate</tt>) - * @throws IllegalStateException if region intersects with a multi-cell array formula - * @throws IllegalStateException if region intersects with an existing region on this sheet - */ - private int addMergedRegion(CellRangeAddress region, boolean validate) { - if (region.getNumberOfCells() < 2) { - throw new IllegalArgumentException("Merged region " + region.formatAsString() + " must contain 2 or more cells"); - } - region.validate(SpreadsheetVersion.EXCEL2007); - - if (validate) { - // throw IllegalStateException if the argument CellRangeAddress intersects with - // a multi-cell array formula defined in this sheet - validateArrayFormulas(region); - - // Throw IllegalStateException if the argument CellRangeAddress intersects with - // a merged region already in this sheet - validateMergedRegions(region); - } - - CTMergeCells ctMergeCells = worksheet.isSetMergeCells() ? worksheet.getMergeCells() : worksheet.addNewMergeCells(); - CTMergeCell ctMergeCell = ctMergeCells.addNewMergeCell(); - ctMergeCell.setRef(region.formatAsString()); - - long count = ctMergeCells.getCount(); - - if (count == 0) { - count=ctMergeCells.sizeOfMergeCellArray(); - } else { - count++; - } - - // also adjust the number of merged regions overall - ctMergeCells.setCount(count); - - return Math.toIntExact(count-1); - } - - /** - * Verify that the candidate region does not intersect with an existing multi-cell array formula in this sheet - * - * @param region a region that is validated. - * @throws IllegalStateException if candidate region intersects an existing array formula in this sheet - */ - private void validateArrayFormulas(CellRangeAddress region) { - // FIXME: this may be faster if it looped over array formulas directly rather than looping over each cell in - // the region and searching if that cell belongs to an array formula - int firstRow = region.getFirstRow(); - int firstColumn = region.getFirstColumn(); - int lastRow = region.getLastRow(); - int lastColumn = region.getLastColumn(); - // for each cell in sheet, if cell belongs to an array formula, check if merged region intersects array formula cells - for (int rowIn = firstRow; rowIn <= lastRow; rowIn++) { - XSSFRow row = getRow(rowIn); - if (row == null) { - continue; - } - - for (int colIn = firstColumn; colIn <= lastColumn; colIn++) { - XSSFCell cell = row.getCell(colIn); - if (cell == null) { - continue; - } - - if (cell.isPartOfArrayFormulaGroup()) { - CellRangeAddress arrayRange = cell.getArrayFormulaRange(); - if (arrayRange.getNumberOfCells() > 1 && region.intersects(arrayRange)) { - String msg = "The range " + region.formatAsString() + " intersects with a multi-cell array formula. " + - "You cannot merge cells of an array."; - throw new IllegalStateException(msg); - } - } - } - } - } - - /** - * Verify that none of the merged regions intersect a multi-cell array formula in this sheet - * - * @throws IllegalStateException if candidate region intersects an existing array formula in this sheet - */ - private void checkForMergedRegionsIntersectingArrayFormulas() { - for (CellRangeAddress region : getMergedRegions()) { - validateArrayFormulas(region); - } - } - - /** - * Verify that candidate region does not intersect with an existing merged region in this sheet - * - * @param candidateRegion the range of cells to verify - * @throws IllegalStateException if candidate region intersects an existing merged region in this sheet (or candidateRegion is already merged in this sheet) - */ - private void validateMergedRegions(CellRangeAddress candidateRegion) { - for (final CellRangeAddress existingRegion : getMergedRegions()) { - if (existingRegion.intersects(candidateRegion)) { - throw new IllegalStateException("Cannot add merged region " + candidateRegion.formatAsString() + - " to sheet because it overlaps with an existing merged region (" + existingRegion.formatAsString() + ")."); - } - } - } - - /** - * Verify that no merged regions intersect another merged region in this sheet. - * - * @throws IllegalStateException if at least one region intersects with another merged region in this sheet - */ - private void checkForIntersectingMergedRegions() { - final List<CellRangeAddress> regions = getMergedRegions(); - final int size = regions.size(); - for (int i=0; i < size; i++) { - final CellRangeAddress region = regions.get(i); - for (final CellRangeAddress other : regions.subList(i+1, regions.size())) { - if (region.intersects(other)) { - String msg = "The range " + region.formatAsString() + - " intersects with another merged region " + - other.formatAsString() + " in this sheet"; - throw new IllegalStateException(msg); - } - } - } - } - - /** - * Verify that merged regions do not intersect multi-cell array formulas and - * no merged regions intersect another merged region in this sheet. - * - * @throws IllegalStateException if region intersects with a multi-cell array formula - * @throws IllegalStateException if at least one region intersects with another merged region in this sheet - */ - @Override - public void validateMergedRegions() { - checkForMergedRegionsIntersectingArrayFormulas(); - checkForIntersectingMergedRegions(); - } - - /** - * Adjusts the column width to fit the contents. - * - * This process can be relatively slow on large sheets, so this should - * normally only be called once per column, at the end of your - * processing. - * - * @param column the column index - */ - @Override - public void autoSizeColumn(int column) { - autoSizeColumn(column, false); - } - - /** - * Adjusts the column width to fit the contents. - * <p> - * This process can be relatively slow on large sheets, so this should - * normally only be called once per column, at the end of your - * processing. - * </p> - * You can specify whether the content of merged cells should be considered or ignored. - * Default is to ignore merged cells. - * - * @param column the column index - * @param useMergedCells whether to use the contents of merged cells when calculating the width of the column - */ - @Override - public void autoSizeColumn(int column, boolean useMergedCells) { - double width = SheetUtil.getColumnWidth(this, column, useMergedCells); - - if (width != -1) { - width *= 256; - int maxColumnWidth = 255*256; // The maximum column width for an individual cell is 255 characters - if (width > maxColumnWidth) { - width = maxColumnWidth; - } - setColumnWidth(column, Math.toIntExact(Math.round(width))); - columnHelper.setColBestFit(column, true); - } - } - - /** - * Return the sheet's existing drawing, or null if there isn't yet one. - * - * Use {@link #createDrawingPatriarch()} to get or create - * - * @return a SpreadsheetML drawing - */ - @Override - public XSSFDrawing getDrawingPatriarch() { - CTDrawing ctDrawing = getCTDrawing(); - if (ctDrawing != null) { - // Search the referenced drawing in the list of the sheet's relations - for (RelationPart rp : getRelationParts()){ - POIXMLDocumentPart p = rp.getDocumentPart(); - if (p instanceof XSSFDrawing) { - XSSFDrawing dr = (XSSFDrawing)p; - String drId = rp.getRelationship().getId(); - if (drId.equals(ctDrawing.getId())){ - return dr; - } - break; - } - } - LOG.atError().log("Can't find drawing with id={} in the list of the sheet's relationships", ctDrawing.getId()); - } - return null; - } - - /** - * Create a new SpreadsheetML drawing. If this sheet already contains a drawing - return that. - * - * @return a SpreadsheetML drawing - */ - @Override - public XSSFDrawing createDrawingPatriarch() { - CTDrawing ctDrawing = getCTDrawing(); - if (ctDrawing != null) { - return getDrawingPatriarch(); - } - - // Default drawingNumber = #drawings.size() + 1 - int drawingNumber = getPackagePart().getPackage().getPartsByContentType(XSSFRelation.DRAWINGS.getContentType()).size() + 1; - drawingNumber = getNextPartNumber(XSSFRelation.DRAWINGS, drawingNumber); - RelationPart rp = createRelationship(XSSFRelation.DRAWINGS, XSSFFactory.getInstance(), drawingNumber, false); - XSSFDrawing drawing = rp.getDocumentPart(); - String relId = rp.getRelationship().getId(); - - //add CT_Drawing element which indicates that this sheet contains drawing components built on the drawingML platform. - //The relationship Id references the part containing the drawingML definitions. - ctDrawing = worksheet.addNewDrawing(); - ctDrawing.setId(relId); - - // Return the newly created drawing - return drawing; - } - - /** - * Get VML drawing for this sheet (aka 'legacy' drawig) - * - * @param autoCreate if true, then a new VML drawing part is created - * - * @return the VML drawing of <code>null</code> if the drawing was not found and autoCreate=false - */ - protected XSSFVMLDrawing getVMLDrawing(boolean autoCreate) { - XSSFVMLDrawing drawing = null; - CTLegacyDrawing ctDrawing = getCTLegacyDrawing(); - if(ctDrawing == null) { - if(autoCreate) { - int drawingNumber = getNextPartNumber(XSSFRelation.VML_DRAWINGS, - getPackagePart().getPackage().getPartsByContentType(XSSFRelation.VML_DRAWINGS.getContentType()).size()); - RelationPart rp = createRelationship(XSSFRelation.VML_DRAWINGS, XSSFFactory.getInstance(), drawingNumber, false); - drawing = rp.getDocumentPart(); - String relId = rp.getRelationship().getId(); - - //add CTLegacyDrawing element which indicates that this sheet contains drawing components built on the drawingML platform. - //The relationship Id references the part containing the drawing definitions. - ctDrawing = worksheet.addNewLegacyDrawing(); - ctDrawing.setId(relId); - } - } else { - //search the referenced drawing in the list of the sheet's relations - final String id = ctDrawing.getId(); - for (RelationPart rp : getRelationParts()){ - POIXMLDocumentPart p = rp.getDocumentPart(); - if(p instanceof XSSFVMLDrawing) { - XSSFVMLDrawing dr = (XSSFVMLDrawing)p; - String drId = rp.getRelationship().getId(); - if (drId.equals(id)) { - drawing = dr; - break; - } - // do not break here since drawing has not been found yet (see bug 52425) - } - } - if(drawing == null){ - LOG.atError().log("Can't find VML drawing with id={} in the list of the sheet's relationships", id); - } - } - return drawing; - } - - protected CTDrawing getCTDrawing() { - return worksheet.getDrawing(); - } - protected CTLegacyDrawing getCTLegacyDrawing() { - return worksheet.getLegacyDrawing(); - } - - /** - * Creates a split (freezepane). Any existing freezepane or split pane is overwritten. - * @param colSplit Horizontal position of split. - * @param rowSplit Vertical position of split. - */ - @Override - public void createFreezePane(int colSplit, int rowSplit) { - createFreezePane( colSplit, rowSplit, colSplit, rowSplit ); - } - - /** - * Creates a split (freezepane). Any existing freezepane or split pane is overwritten. - * - * <p> - * If both colSplit and rowSplit are zero then the existing freeze pane is removed - * </p> - * - * @param colSplit Horizontal position of split. - * @param rowSplit Vertical position of split. - * @param leftmostColumn Left column visible in right pane. - * @param topRow Top row visible in bottom pane - */ - @Override - public void createFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) { - final boolean removeSplit = colSplit == 0 && rowSplit == 0; - final CTSheetView ctView = getDefaultSheetView(!removeSplit); - - if (ctView != null) { - ctView.setSelectionArray(null); - } - - // If both colSplit and rowSplit are zero then the existing freeze pane is removed - if (removeSplit) { - if (ctView != null && ctView.isSetPane()) { - ctView.unsetPane(); - } - return; - } - - assert(ctView != null); - final CTPane pane = (ctView.isSetPane()) ? ctView.getPane() : ctView.addNewPane(); - assert(pane != null); - - if (colSplit > 0) { - pane.setXSplit(colSplit); - } else if (pane.isSetXSplit()) { - pane.unsetXSplit(); - } - if (rowSplit > 0) { - pane.setYSplit(rowSplit); - } else if(pane.isSetYSplit()) { - pane.unsetYSplit(); - } - - STPane.Enum activePane = STPane.BOTTOM_RIGHT; - int pRow = topRow, pCol = leftmostColumn; - if (rowSplit == 0) { - pRow = 0; - activePane = STPane.TOP_RIGHT; - } else if (colSplit == 0) { - pCol = 0; - activePane = STPane.BOTTOM_LEFT; - } - - pane.setState(STPaneState.FROZEN); - pane.setTopLeftCell(new CellReference(pRow, pCol).formatAsString()); - pane.setActivePane(activePane); - - ctView.addNewSelection().setPane(activePane); - } - - /** - * Create a new row within the sheet and return the high level representation - * - * Note: If a row already exists at this position, it is removed/overwritten and - * any existing cell is removed! - * - * @param rownum row number - * @return High level {@link XSSFRow} object representing a row in the sheet - * @see #removeRow(Row) - */ - @Override - public XSSFRow createRow(int rownum) { - // Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory - //noinspection UnnecessaryBoxing - final Integer rownumI = Integer.valueOf(rownum); // NOSONAR - CTRow ctRow; - XSSFRow prev = _rows.get(rownumI); - if(prev != null){ - // the Cells in an existing row are invalidated on-purpose, in order to clean up correctly, we - // need to call the remove, so things like ArrayFormulas and CalculationChain updates are done - // correctly. - // We remove the cell this way as the internal cell-list is changed by the remove call and - // thus would cause ConcurrentModificationException otherwise - while(prev.getFirstCellNum() != -1) { - prev.removeCell(prev.getCell(prev.getFirstCellNum())); - } - - ctRow = prev.getCTRow(); - ctRow.set(CTRow.Factory.newInstance()); - } else { - if(_rows.isEmpty() || rownum > _rows.lastKey()) { - // we can append the new row at the end - ctRow = worksheet.getSheetData().addNewRow(); - } else { - // get number of rows where row index < rownum - // --> this tells us where our row should go - int idx = _rows.headMap(rownumI).size(); - ctRow = worksheet.getSheetData().insertNewRow(idx); - } - } - XSSFRow r = new XSSFRow(ctRow, this); - r.setRowNum(rownum); - _rows.put(rownumI, r); - return r; - } - - /** - * Creates a split pane. Any existing freezepane or split pane is overwritten. - * @param xSplitPos Horizontal position of split (in 1/20th of a point). - * @param ySplitPos Vertical position of split (in 1/20th of a point). - * @param topRow Top row visible in bottom pane - * @param leftmostColumn Left column visible in right pane. - * @param activePane Active pane. One of: PANE_LOWER_RIGHT, - * PANE_UPPER_RIGHT, PANE_LOWER_LEFT, PANE_UPPER_LEFT - * @see Sheet#PANE_LOWER_LEFT - * @see Sheet#PANE_LOWER_RIGHT - * @see Sheet#PANE_UPPER_LEFT - * @see Sheet#PANE_UPPER_RIGHT - */ - @Override - public void createSplitPane(int xSplitPos, int ySplitPos, int leftmostColumn, int topRow, int activePane) { - createFreezePane(xSplitPos, ySplitPos, leftmostColumn, topRow); - if (xSplitPos > 0 || ySplitPos > 0) { - final CTPane pane = getPane(true); - pane.setState(STPaneState.SPLIT); - pane.setActivePane(STPane.Enum.forInt(activePane)); - } - } - - /** - * Return cell comment at row, column, if one exists. Otherwise returns null. - * - * @param address the location of the cell comment - * @return the cell comment, if one exists. Otherwise return null. - */ - @Override - public XSSFComment getCellComment(CellAddress address) { - if (sheetComments == null) { - return null; - } - - CTComment ctComment = sheetComments.getCTComment(address); - if(ctComment == null) { - return null; - } - - XSSFVMLDrawing vml = getVMLDrawing(false); - return new XSSFComment(sheetComments, ctComment, - vml == null ? null : vml.findCommentShape(address.getRow(), address.getColumn())); - } - - /** - * Returns all cell comments on this sheet. - * @return A map of each Comment in the sheet, keyed on the cell address where - * the comment is located. - */ - @Override - public Map<CellAddress, XSSFComment> getCellComments() { - if (sheetComments == null) { - return Collections.emptyMap(); - } - // the cell comments in sheetComments.getCellComments() do not have the client anchors set - Map<CellAddress, XSSFComment> map = new HashMap<>(); - for(Iterator<CellAddress> iter = sheetComments.getCellAddresses(); iter.hasNext(); ) { - CellAddress address = iter.next(); - map.put(address, getCellComment(address)); - } - return map; - } - - /** - * Get a Hyperlink in this sheet anchored at row, column - * - * @param row The row where the hyperlink is anchored - * @param column The column where the hyperlink is anchored - * @return hyperlink if there is a hyperlink anchored at row, column; otherwise returns null - */ - @Override - public XSSFHyperlink getHyperlink(int row, int column) { - return getHyperlink(new CellAddress(row, column)); - } - - /** - * Get a Hyperlink in this sheet located in a cell specified by {code addr} - * - * @param addr The address of the cell containing the hyperlink - * @return hyperlink if there is a hyperlink anchored at {@code addr}; otherwise returns {@code null} - * @since POI 3.15 beta 3 - */ - @Override - public XSSFHyperlink getHyperlink(CellAddress addr) { - String ref = addr.formatAsString(); - for(XSSFHyperlink hyperlink : hyperlinks) { - if(hyperlink.getCellRef().equals(ref)) { - return hyperlink; - } - } - return null; - } - - /** - * Get a list of Hyperlinks in this sheet - * - * @return Hyperlinks for the sheet - */ - @Override - public List<XSSFHyperlink> getHyperlinkList() { - return Collections.unmodifiableList(hyperlinks); - } - - private int[] getBreaks(CTPageBreak ctPageBreak) { - CTBreak[] brkArray = ctPageBreak.getBrkArray(); - int[] breaks = new int[brkArray.length]; - for (int i = 0 ; i < brkArray.length ; i++) { - breaks[i] = Math.toIntExact(brkArray[i].getId() - 1); - } - return breaks; - } - - private void removeBreak(int index, CTPageBreak ctPageBreak) { - int index1 = index + 1; - CTBreak[] brkArray = ctPageBreak.getBrkArray(); - for (int i = 0 ; i < brkArray.length ; i++) { - if (brkArray[i].getId() == index1) { - ctPageBreak.removeBrk(i); - // TODO: check if we can break here, i.e. if a page can have more than 1 break on the same id - } - } - } - - /** - * Vertical page break information used for print layout view, page layout view, drawing print breaks - * in normal view, and for printing the worksheet. - * - * @return column indexes of all the vertical page breaks, never <code>null</code> - */ - @Override - public int[] getColumnBreaks() { - return worksheet.isSetColBreaks() ? getBreaks(worksheet.getColBreaks()) : new int[0]; - } - - /** - * Get the actual column width (in units of 1/256th of a character width ) - * - * <p> - * Note, the returned value is always gerater that {@link #getDefaultColumnWidth()} because the latter does not include margins. - * Actual column width measured as the number of characters of the maximum digit width of the - * numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin - * padding (two on each side), plus 1 pixel padding for the gridlines. - * </p> - * - * @param columnIndex - the column to set (0-based) - * @return width - the width in units of 1/256th of a character width - */ - @Override - public int getColumnWidth(int columnIndex) { - CTCol col = columnHelper.getColumn(columnIndex, false); - double width = col == null || !col.isSetWidth() ? getDefaultColumnWidth() : col.getWidth(); - return Math.toIntExact(Math.round(width*256)); - } - - /** - * Get the actual column width in pixels - * - * <p> - * Please note, that this method works correctly only for workbooks - * with the default font size (Calibri 11pt for .xlsx). - * </p> - */ - @Override - public float getColumnWidthInPixels(int columnIndex) { - float widthIn256 = getColumnWidth(columnIndex); - return (float)(widthIn256/256.0*Units.DEFAULT_CHARACTER_WIDTH); - } - - /** - * Get the default column width for the sheet (if the columns do not define their own width) in - * characters. - * <p> - * Note, this value is different from {@link #getColumnWidth(int)}. The latter is always greater and includes - * 4 pixels of margin padding (two on each side), plus 1 pixel padding for the gridlines. - * </p> - * @return column width, default value is 8 - */ - @Override - public int getDefaultColumnWidth() { - CTSheetFormatPr pr = worksheet.getSheetFormatPr(); - return pr == null ? 8 : Math.toIntExact(pr.getBaseColWidth()); - } - - /** - * Get the default row height for the sheet (if the rows do not define their own height) in - * twips (1/20 of a point) - * - * @return default row height - */ - @Override - public short getDefaultRowHeight() { - return (short)(getDefaultRowHeightInPoints() * Font.TWIPS_PER_POINT); - } - - - /** - * Get the default row height for the sheet measued in point size (if the rows do not define their own height). - * - * @return default row height in points - */ - @Override - public float getDefaultRowHeightInPoints() { - CTSheetFormatPr pr = worksheet.getSheetFormatPr(); - return (float)(pr == null ? 0 : pr.getDefaultRowHeight()); - } - - private CTSheetFormatPr getSheetTypeSheetFormatPr() { - return worksheet.isSetSheetFormatPr() ? - worksheet.getSheetFormatPr() : - worksheet.addNewSheetFormatPr(); - } - - /** - * Returns the CellStyle that applies to the given - * (0 based) column, or null if no style has been - * set for that column - */ - @Override - public CellStyle getColumnStyle(int column) { - int idx = columnHelper.getColDefaultStyle(column); - return getWorkbook().getCellStyleAt((short)(idx == -1 ? 0 : idx)); - } - - /** - * Sets whether the worksheet is displayed from right to left instead of from left to right. - * - * @param value true for right to left, false otherwise. - */ - @Override - public void setRightToLeft(boolean value) { - final CTSheetView dsv = getDefaultSheetView(true); - assert(dsv != null); - dsv.setRightToLeft(value); - } - - /** - * Whether the text is displayed in right-to-left mode in the window - * - * @return whether the text is displayed in right-to-left mode in the window - */ - @Override - public boolean isRightToLeft() { - final CTSheetView dsv = getDefaultSheetView(false); - return (dsv != null && dsv.getRightToLeft()); - } - - /** - * Get whether to display the guts or not, - * default value is true - * - * @return boolean - guts or no guts - */ - @Override - public boolean getDisplayGuts() { - CTSheetPr sheetPr = getSheetTypeSheetPr(); - CTOutlinePr outlinePr = sheetPr.getOutlinePr() == null ? CTOutlinePr.Factory.newInstance() : sheetPr.getOutlinePr(); - return outlinePr.getShowOutlineSymbols(); - } - - /** - * Set whether to display the guts or not - * - * @param value - guts or no guts - */ - @Override - public void setDisplayGuts(boolean value) { - CTSheetPr sheetPr = getSheetTypeSheetPr(); - CTOutlinePr outlinePr = sheetPr.getOutlinePr() == null ? sheetPr.addNewOutlinePr() : sheetPr.getOutlinePr(); - outlinePr.setShowOutlineSymbols(value); - } - - /** - * Gets the flag indicating whether the window should show 0 (zero) in cells containing zero value. - * When false, cells with zero value appear blank instead of showing the number zero. - * - * @return whether all zero values on the worksheet are displayed (defaults to true) - */ - @Override - public boolean isDisplayZeros(){ - final CTSheetView dsv = getDefaultSheetView(false); - return (dsv == null) || dsv.getShowZeros(); - } - - /** - * Set whether the window should show 0 (zero) in cells containing zero value. - * When false, cells with zero value appear blank instead of showing the number zero. - * - * @param value whether to display or hide all zero values on the worksheet - */ - @Override - public void setDisplayZeros(boolean value){ - final CTSheetView view = getDefaultSheetView(true); - assert(view != null); - view.setShowZeros(value); - } - - /** - * Gets the first row on the sheet - * - * @return the number of the first logical row on the sheet, zero based - */ - @Override - public int getFirstRowNum() { - return _rows.isEmpty() ? -1 : _rows.firstKey(); - } - - /** - * Flag indicating whether the Fit to Page print option is enabled. - * - * @return <code>true</code> - */ - @Override - public boolean getFitToPage() { - CTSheetPr sheetPr = getSheetTypeSheetPr(); - CTPageSetUpPr psSetup = (sheetPr == null || !sheetPr.isSetPageSetUpPr()) ? - CTPageSetUpPr.Factory.newInstance() : sheetPr.getPageSetUpPr(); - return psSetup.getFitToPage(); - } - - private CTSheetPr getSheetTypeSheetPr() { - if (worksheet.getSheetPr() == null) { - worksheet.setSheetPr(CTSheetPr.Factory.newInstance()); - } - return worksheet.getSheetPr(); - } - - private CTHeaderFooter getSheetTypeHeaderFooter() { - if (worksheet.getHeaderFooter() == null) { - worksheet.setHeaderFooter(CTHeaderFooter.Factory.newInstance()); - } - return worksheet.getHeaderFooter(); - } - - - - /** - * Returns the default footer for the sheet, - * creating one as needed. - * You may also want to look at - * {@link #getFirstFooter()}, - * {@link #getOddFooter()} and - * {@link #getEvenFooter()} - */ - @Override - public Footer getFooter() { - // The default footer is an odd footer - return getOddFooter(); - } - - /** - * Returns the default header for the sheet, - * creating one as needed. - * You may also want to look at - * {@link #getFirstHeader()}, - * {@link #getOddHeader()} and - * {@link #getEvenHeader()} - */ - @Override - public Header getHeader() { - // The default header is an odd header - return getOddHeader(); - } - - /** - * Returns the odd footer. Used on all pages unless - * other footers also present, when used on only - * odd pages. - */ - public Footer getOddFooter() { - return new XSSFOddFooter(getSheetTypeHeaderFooter()); - } - /** - * Returns the even footer. Not there by default, but - * when set, used on even pages. - */ - public Footer getEvenFooter() { - return new XSSFEvenFooter(getSheetTypeHeaderFooter()); - } - /** - * Returns the first page footer. Not there by - * default, but when set, used on the first page. - */ - public Footer getFirstFooter() { - return new XSSFFirstFooter(getSheetTypeHeaderFooter()); - } - - /** - * Returns the odd header. Used on all pages unless - * other headers also present, when used on only - * odd pages. - */ - public Header getOddHeader() { - return new XSSFOddHeader(getSheetTypeHeaderFooter()); - } - /** - * Returns the even header. Not there by default, but - * when set, used on even pages. - */ - public Header getEvenHeader() { - return new XSSFEvenHeader(getSheetTypeHeaderFooter()); - } - /** - * Returns the first page header. Not there by - * default, but when set, used on the first page. - */ - public Header getFirstHeader() { - return new XSSFFirstHeader(getSheetTypeHeaderFooter()); - } - - - /** - * Determine whether printed output for this sheet will be horizontally centered. - */ - @Override - public boolean getHorizontallyCenter() { - CTPrintOptions opts = worksheet.getPrintOptions(); - return opts != null && opts.getHorizontalCentered(); - } - - @Override - public int getLastRowNum() { - // _rows.getLastKey() (O(logN)) or caching last row (O(1))? - // A test with 1_000_000 rows shows that querying getLastRowNum with lastKey() implementation takes ~40 ms, - // and ~1.2 ms with cached implementation. 40 ms is negligible compared to the time of evaluation a million - // cells, and the lastKey implementation is much more elegant and less error prone than caching. - return _rows.isEmpty() ? -1 : _rows.lastKey(); - } - - @Override - public short getLeftCol() { - String cellRef = worksheet.getSheetViews().getSheetViewArray(0).getTopLeftCell(); - if(cellRef == null) { - return 0; - } - CellReference cellReference = new CellReference(cellRef); - return cellReference.getCol(); - } - - /** - * Gets the size of the margin in inches. - * - * @param margin which margin to get - * @return the size of the margin - * @see Sheet#LeftMargin - * @see Sheet#RightMargin - * @see Sheet#TopMargin - * @see Sheet#BottomMargin - * @see Sheet#HeaderMargin - * @see Sheet#FooterMargin - */ - @Override - public double getMargin(short margin) { - if (!worksheet.isSetPageMargins()) { - return 0; - } - - CTPageMargins pageMargins = worksheet.getPageMargins(); - switch (margin) { - case LeftMargin: - return pageMargins.getLeft(); - case RightMargin: - return pageMargins.getRight(); - case TopMargin: - return pageMargins.getTop(); - case BottomMargin: - return pageMargins.getBottom(); - case HeaderMargin: - return pageMargins.getHeader(); - case FooterMargin: - return pageMargins.getFooter(); - default : - throw new IllegalArgumentException("Unknown margin constant: " + margin); - } - } - - /** - * Sets the size of the margin in inches. - * - * @param margin which margin to get - * @param size the size of the margin - * @see Sheet#LeftMargin - * @see Sheet#RightMargin - * @see Sheet#TopMargin - * @see Sheet#BottomMargin - * @see Sheet#HeaderMargin - * @see Sheet#FooterMargin - */ - @Override - public void setMargin(short margin, double size) { - CTPageMargins pageMargins = worksheet.isSetPageMargins() ? - worksheet.getPageMargins() : worksheet.addNewPageMargins(); - switch (margin) { - case LeftMargin: - pageMargins.setLeft(size); - break; - case RightMargin: - pageMargins.setRight(size); - break; - case TopMargin: - pageMargins.setTop(size); - break; - case BottomMargin: - pageMargins.setBottom(size); - break; - case HeaderMargin: - pageMargins.setHeader(size); - break; - case FooterMargin: - pageMargins.setFooter(size); - break; - default : - throw new IllegalArgumentException( "Unknown margin constant: " + margin ); - } - } - - /** - * Returns the merged region at the specified index. If you want multiple - * regions, it is faster to call {@link #getMergedRegions()} than to call - * this each time. - * - * @return the merged region at the specified index - */ - @Override - public CellRangeAddress getMergedRegion(int index) { - CTMergeCells ctMergeCells = worksheet.getMergeCells(); - if(ctMergeCells == null) { - throw new IllegalStateException("This worksheet does not contain merged regions"); - } - - CTMergeCell ctMergeCell = ctMergeCells.getMergeCellArray(index); - String ref = ctMergeCell.getRef(); - return CellRangeAddress.valueOf(ref); - } - - /** - * Returns the list of merged regions. If you want multiple regions, this is - * faster than calling {@link #getMergedRegion(int)} each time. - * - * @return the list of merged regions - */ - @Override - public List<CellRangeAddress> getMergedRegions() { - List<CellRangeAddress> addresses = new ArrayList<>(); - CTMergeCells ctMergeCells = worksheet.getMergeCells(); - if(ctMergeCells == null) { - return addresses; - } - - for(CTMergeCell ctMergeCell : ctMergeCells.getMergeCellArray()) { - String ref = ctMergeCell.getRef(); - addresses.add(CellRangeAddress.valueOf(ref)); - } - return addresses; - } - - /** - * Returns the number of merged regions defined in this worksheet - * - * @return number of merged regions in this worksheet - */ - @Override - public int getNumMergedRegions() { - CTMergeCells ctMergeCells = worksheet.getMergeCells(); - return ctMergeCells == null ? 0 : ctMergeCells.sizeOfMergeCellArray(); - } - - public int getNumHyperlinks() { - return hyperlinks.size(); - } - - /** - * Returns the information regarding the currently configured pane (split or freeze). - * - * @return null if no pane configured, or the pane information. - */ - @Override - public PaneInformation getPaneInformation() { - final CTPane pane = getPane(false); - // no pane configured - if(pane == null) { - return null; - } - - short row = 0, col = 0; - if (pane.isSetTopLeftCell()) { - final CellReference cellRef = new CellReference(pane.getTopLeftCell()); - row = (short)cellRef.getRow(); - col = cellRef.getCol(); - } - - final short x = (short)pane.getXSplit(); - final short y = (short)pane.getYSplit(); - final byte active = (byte)(pane.getActivePane().intValue() - 1); - final boolean frozen = pane.getState() == STPaneState.FROZEN; - - return new PaneInformation(x, y, row, col, active, frozen); - } - - /** - * Returns the number of physically defined rows (NOT the number of rows in the sheet) - * - * @return the number of physically defined rows - */ - @Override - public int getPhysicalNumberOfRows() { - return _rows.size(); - } - - /** - * Gets the print setup object. - * - * @return The user model for the print setup object. - */ - @Override - public XSSFPrintSetup getPrintSetup() { - return new XSSFPrintSetup(worksheet); - } - - /** - * Answer whether protection is enabled or disabled - * - * @return true => protection enabled; false => protection disabled - */ - @Override - public boolean getProtect() { - return isSheetLocked(); - } - - /** - * Enables sheet protection and sets the password for the sheet. - * Also sets some attributes on the {@link CTSheetProtection} that correspond to - * the default values used by Excel - * - * @param password to set for protection. Pass <code>null</code> to remove protection - */ - @Override - public void protectSheet(String password) { - if (password != null) { - CTSheetProtection sheetProtection = safeGetProtectionField(); - setSheetPassword(password, null); // defaults to xor password - sheetProtection.setSheet(true); - sheetProtection.setScenarios(true); - sheetProtection.setObjects(true); - } else { - worksheet.unsetSheetProtection(); - } - } - - /** - * Sets the sheet password. - * - * @param password if null, the password will be removed - * @param hashAlgo if null, the password will be set as XOR password (Excel 2010 and earlier) - * otherwise the given algorithm is used for calculating the hash password (Excel 2013) - */ - public void setSheetPassword(String password, HashAlgorithm hashAlgo) { - if (password == null && !isSheetProtectionEnabled()) { - return; - } - setPassword(safeGetProtectionField(), password, hashAlgo, null); - } - - /** - * Validate the password against the stored hash, the hashing method will be determined - * by the existing password attributes - * @return true, if the hashes match (... though original password may differ ...) - */ - public boolean validateSheetPassword(String password) { - if (!isSheetProtectionEnabled()) { - return (password == null); - } - return validatePassword(safeGetProtectionField(), password, null); - } - - /** - * Returns the logical row ( 0-based). If you ask for a row that is not - * defined you get a null. This is to say row 4 represents the fifth row on a sheet. - * - * @param rownum row to get - * @return <code>XSSFRow</code> representing the rownumber or <code>null</code> if its not defined on the sheet - */ - @Override - public XSSFRow getRow(int rownum) { - // Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory - //noinspection UnnecessaryBoxing - final Integer rownumI = Integer.valueOf(rownum); // NOSONAR - return _rows.get(rownumI); - } - - /** - * returns all rows between startRow and endRow, inclusive. - * Rows between startRow and endRow that haven't been created are not included - * in result unless createRowIfMissing is true - * - * @param startRowNum the first row number in this sheet to return - * @param endRowNum the last row number in this sheet to return - * @param createRowIfMissing If missing rows should be created. - * @return All rows between startRow and endRow, inclusive. If createRowIfMissing is false, - * only previously existing rows are returned, otherwise empty rows are added as necessary - * @throws IllegalArgumentException if startRowNum and endRowNum are not in ascending order - */ - private List<XSSFRow> getRows(int startRowNum, int endRowNum, boolean createRowIfMissing) { - if (startRowNum > endRowNum) { - throw new IllegalArgumentException("getRows: startRowNum must be less than or equal to endRowNum"); - } - final List<XSSFRow> rows = new ArrayList<>(); - if (createRowIfMissing) { - for (int i = startRowNum; i <= endRowNum; i++) { - XSSFRow row = getRow(i); - if (row == null) { - row = createRow(i); - } - rows.add(row); - } - } - else { - // Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory - //noinspection UnnecessaryBoxing - final Integer startI = Integer.valueOf(startRowNum); // NOSONAR - //noinspection UnnecessaryBoxing - final Integer endI = Integer.valueOf(endRowNum+1); // NOSONAR - final Collection<XSSFRow> inclusive = _rows.subMap(startI, endI).values(); - rows.addAll(inclusive); - } - return rows; - } - - /** - * Horizontal page break information used for print layout view, page layout view, drawing print breaks in normal - * view, and for printing the worksheet. - * - * @return row indexes of all the horizontal page breaks, never <code>null</code> - */ - @Override - public int[] getRowBreaks() { - return worksheet.isSetRowBreaks() ? getBreaks(worksheet.getRowBreaks()) : new int[0]; - - } - - /** - * Flag indicating whether summary rows appear below detail in an outline, when applying an outline. - * - * <p> - * When true a summary row is inserted below the detailed data being summarized and a - * new outline level is established on that row. - * </p> - * <p> - * When false a summary row is inserted above the detailed data being summarized and a new outline level - * is established on that row. - * </p> - * @return <code>true</code> if row summaries appear below detail in the outline - */ - @Override - public boolean getRowSumsBelow() { - CTSheetPr sheetPr = worksheet.getSheetPr(); - CTOutlinePr outlinePr = (sheetPr != null && sheetPr.isSetOutlinePr()) - ? sheetPr.getOutlinePr() : null; - return outlinePr == null || outlinePr.getSummaryBelow(); - } - - /** - * Flag indicating whether summary rows appear below detail in an outline, when applying an outline. - * - * <p> - * When true a summary row is inserted below the detailed data being summarized and a - * new outline level is established on that row. - * </p> - * <p> - * When false a summary row is inserted above the detailed data being summarized and a new outline level - * is established on that row. - * </p> - * @param value <code>true</code> if row summaries appear below detail in the outline - */ - @Override - public void setRowSumsBelow(boolean value) { - ensureOutlinePr().setSummaryBelow(value); - } - - /** - * Flag indicating whether summary columns appear to the right of detail in an outline, when applying an outline. - * - * <p> - * When true a summary column is inserted to the right of the detailed data being summarized - * and a new outline level is established on that column. - * </p> - * <p> - * When false a summary column is inserted to the left of the detailed data being - * summarized and a new outline level is established on that column. - * </p> - * @return <code>true</code> if col summaries appear right of the detail in the outline - */ - @Override - public boolean getRowSumsRight() { - CTSheetPr sheetPr = worksheet.getSheetPr(); - CTOutlinePr outlinePr = (sheetPr != null && sheetPr.isSetOutlinePr()) - ? sheetPr.getOutlinePr() : CTOutlinePr.Factory.newInstance(); - return outlinePr.getSummaryRight(); - } - - /** - * Flag indicating whether summary columns appear to the right of detail in an outline, when applying an outline. - * - * <p> - * When true a summary column is inserted to the right of the detailed data being summarized - * and a new outline level is established on that column. - * </p> - * <p> - * When false a summary column is inserted to the left of the detailed data being - * summarized and a new outline level is established on that column. - * </p> - * @param value <code>true</code> if col summaries appear right of the detail in the outline - */ - @Override - public void setRowSumsRight(boolean value) { - ensureOutlinePr().setSummaryRight(value); - } - - - /** - * Ensure CTWorksheet.CTSheetPr.CTOutlinePr - */ - private CTOutlinePr ensureOutlinePr(){ - CTSheetPr sheetPr = worksheet.isSetSheetPr() ? worksheet.getSheetPr() : worksheet.addNewSheetPr(); - return sheetPr.isSetOutlinePr() ? sheetPr.getOutlinePr() : sheetPr.addNewOutlinePr(); - } - - /** - * A flag indicating whether scenarios are locked when the sheet is protected. - * - * @return true => protection enabled; false => protection disabled - */ - @Override - public boolean getScenarioProtect() { - return worksheet.isSetSheetProtection() && worksheet.getSheetProtection().getScenarios(); - } - - /** - * The top row in the visible view when the sheet is - * first viewed after opening it in a viewer - * - * @return integer indicating the rownum (0 based) of the top row - */ - @Override - public short getTopRow() { - final CTSheetView dsv = getDefaultSheetView(false); - final String cellRef = (dsv == null) ? null : dsv.getTopLeftCell(); - if(cellRef == null) { - return 0; - } - return (short) new CellReference(cellRef).getRow(); - } - - /** - * Determine whether printed output for this sheet will be vertically centered. - * - * @return whether printed output for this sheet will be vertically centered. - */ - @Override - public boolean getVerticallyCenter() { - CTPrintOptions opts = worksheet.getPrintOptions(); - return opts != null && opts.getVerticalCentered(); - } - - /** - * Group between (0 based) columns - */ - @Override - public void groupColumn(int fromColumn, int toColumn) { - groupColumn1Based(fromColumn+1, toColumn+1); - } - private void groupColumn1Based(int fromColumn, int toColumn) { - CTCols ctCols=worksheet.getColsArray(0); - CTCol ctCol=CTCol.Factory.newInstance(); - - // copy attributes, as they might be removed by merging with the new column - // TODO: check if this fix is really necessary or if the sweeping algorithm - // in addCleanColIntoCols needs to be adapted ... - CTCol fixCol_before = this.columnHelper.getColumn1Based(toColumn, false); - if (fixCol_before != null) { - fixCol_before = (CTCol)fixCol_before.copy(); - } - - ctCol.setMin(fromColumn); - ctCol.setMax(toColumn); - this.columnHelper.addCleanColIntoCols(ctCols, ctCol); - - CTCol fixCol_after = this.columnHelper.getColumn1Based(toColumn, false); - if (fixCol_before != null && fixCol_after != null) { - this.columnHelper.setColumnAttributes(fixCol_before, fixCol_after); - } - - for(int index=fromColumn;index<=toColumn;index++){ - CTCol col=columnHelper.getColumn1Based(index, false); - //col must exist - short outlineLevel=col.getOutlineLevel(); - col.setOutlineLevel((short)(outlineLevel+1)); - index = Math.toIntExact(col.getMax()); - } - worksheet.setColsArray(0,ctCols); - setSheetFormatPrOutlineLevelCol(); - } - - /** - * Do not leave the width attribute undefined (see #52186). - */ - private void setColWidthAttribute(CTCols ctCols) { - for (CTCol col : ctCols.getColArray()) { - if (!col.isSetWidth()) { - col.setWidth(getDefaultColumnWidth()); - col.setCustomWidth(false); - } - } - } - - /** - * Tie a range of cell together so that they can be collapsed or expanded - * - * @param fromRow start row (0-based) - * @param toRow end row (0-based) - */ - @Override - public void groupRow(int fromRow, int toRow) { - for (int i = fromRow; i <= toRow; i++) { - XSSFRow xrow = getRow(i); - if (xrow == null) { - xrow = createRow(i); - } - CTRow ctrow = xrow.getCTRow(); - short outlineLevel = ctrow.getOutlineLevel(); - ctrow.setOutlineLevel((short) (outlineLevel + 1)); - } - setSheetFormatPrOutlineLevelRow(); - } - - private short getMaxOutlineLevelRows(){ - int outlineLevel = 0; - for (XSSFRow xrow : _rows.values()) { - outlineLevel = Math.max(outlineLevel, xrow.getCTRow().getOutlineLevel()); - } - return (short) outlineLevel; - } - - private short getMaxOutlineLevelCols() { - CTCols ctCols = worksheet.getColsArray(0); - int outlineLevel = 0; - for (CTCol col : ctCols.getColArray()) { - outlineLevel = Math.max(outlineLevel, col.getOutlineLevel()); - } - return (short) outlineLevel; - } - - /** - * Determines if there is a page break at the indicated column - */ - @Override - public boolean isColumnBroken(int column) { - for (int colBreak : getColumnBreaks()) { - if (colBreak == column) { - return true; - } - } - return false; - } - - /** - * Get the hidden state for a given column. - * - * @param columnIndex - the column to set (0-based) - * @return hidden - <code>false</code> if the column is visible - */ - @Override - public boolean isColumnHidden(int columnIndex) { - CTCol col = columnHelper.getColumn(columnIndex, false); - return col != null && col.getHidden(); - } - - /** - * Gets the flag indicating whether this sheet should display formulas. - * - * @return <code>true</code> if this sheet should display formulas. - */ - @Override - public boolean isDisplayFormulas() { - final CTSheetView dsv = getDefaultSheetView(false); - return dsv != null && dsv.getShowFormulas(); - } - - /** - * Gets the flag indicating whether this sheet displays the lines - * between rows and columns to make editing and reading easier. - * - * @return <code>true</code> (default) if this sheet displays gridlines. - * @see #isPrintGridlines() to check if printing of gridlines is turned on or off - */ - @Override - public boolean isDisplayGridlines() { - final CTSheetView dsv = getDefaultSheetView(false); - return (dsv == null) || dsv.getShowGridLines(); - } - - /** - * Sets the flag indicating whether this sheet should display the lines - * between rows and columns to make editing and reading easier. - * To turn printing of gridlines use {@link #setPrintGridlines(boolean)} - * - * - * @param show <code>true</code> if this sheet should display gridlines. - * @see #setPrintGridlines(boolean) - */ - @Override - public void setDisplayGridlines(boolean show) { - final CTSheetView dsv = getDefaultSheetView(true); - assert(dsv != null); - dsv.setShowGridLines(show); - } - - /** - * Gets the flag indicating whether this sheet should display row and column headings. - * <p> - * Row heading are the row numbers to the side of the sheet - * </p> - * <p> - * Column heading are the letters or numbers that appear above the columns of the sheet - * </p> - * - * @return <code>true</code> (default) if this sheet should display row and column headings. - */ - @Override - public boolean isDisplayRowColHeadings() { - final CTSheetView dsv = getDefaultSheetView(false); - return (dsv == null) || dsv.getShowRowColHeaders(); - } - - /** - * Sets the flag indicating whether this sheet should display row and column headings. - * <p> - * Row heading are the row numbers to the side of the sheet - * </p> - * <p> - * Column heading are the letters or numbers that appear above the columns of the sheet - * </p> - * - * @param show <code>true</code> if this sheet should display row and column headings. - */ - @Override - public void setDisplayRowColHeadings(boolean show) { - final CTSheetView dsv = getDefaultSheetView(true); - assert(dsv != null); - dsv.setShowRowColHeaders(show); - } - - /** - * Returns whether gridlines are printed. - * - * @return whether gridlines are printed - */ - @Override - public boolean isPrintGridlines() { - CTPrintOptions opts = worksheet.getPrintOptions(); - return opts != null && opts.getGridLines(); - } - - /** - * Turns on or off the printing of gridlines. - * - * @param value boolean to turn on or off the printing of gridlines - */ - @Override - public void setPrintGridlines(boolean value) { - CTPrintOptions opts = worksheet.isSetPrintOptions() ? - worksheet.getPrintOptions() : worksheet.addNewPrintOptions(); - opts.setGridLines(value); - } - - /** - * Returns whether row and column headings are printed. - * - * @return whether row and column headings are printed - */ - @Override - public boolean isPrintRowAndColumnHeadings() { - CTPrintOptions opts = worksheet.getPrintOptions(); - return opts != null && opts.getHeadings(); - } - - /** - * Turns on or off the printing of row and column headings. - * - * @param value boolean to turn on or off the printing of row and column headings - */ - @Override - public void setPrintRowAndColumnHeadings(boolean value) { - CTPrintOptions opts = worksheet.isSetPrintOptions() ? - worksheet.getPrintOptions() : worksheet.addNewPrintOptions(); - opts.setHeadings(value); - } - - /** - * Tests if there is a page break at the indicated row - * - * @param row index of the row to test - * @return <code>true</code> if there is a page break at the indicated row - */ - @Override - public boolean isRowBroken(int row) { - for (int rowBreak : getRowBreaks()) { - if (rowBreak == row) { - return true; - } - } - return false; - } - - private void setBreak(int id, CTPageBreak ctPgBreak, int lastIndex) { - CTBreak brk = ctPgBreak.addNewBrk(); - // this is id of the element which is 1-based: <row r="1" ... > - brk.setId(id + 1L); - brk.setMan(true); - // end column of the break - brk.setMax(lastIndex); - - int nPageBreaks = ctPgBreak.sizeOfBrkArray(); - ctPgBreak.setCount(nPageBreaks); - ctPgBreak.setManualBreakCount(nPageBreaks); - } - - /** - * Sets a page break at the indicated row - * Breaks occur above the specified row and left of the specified column inclusive. - * - * For example, <code>sheet.setColumnBreak(2);</code> breaks the sheet into two parts - * with columns A,B,C in the first and D,E,... in the second. Simuilar, <code>sheet.setRowBreak(2);</code> - * breaks the sheet into two parts with first three rows (rownum=1...3) in the first part - * and rows starting with rownum=4 in the second. - * - * @param row the row to break, inclusive - */ - @Override - public void setRowBreak(int row) { - if (!isRowBroken(row)) { - CTPageBreak pgBreak = worksheet.isSetRowBreaks() ? worksheet.getRowBreaks() : worksheet.addNewRowBreaks(); - setBreak(row, pgBreak, SpreadsheetVersion.EXCEL2007.getLastColumnIndex()); - } - } - - /** - * Removes a page break at the indicated column - */ - @Override - public void removeColumnBreak(int column) { - if (worksheet.isSetColBreaks()) { - removeBreak(column, worksheet.getColBreaks()); - } // else no breaks - } - - /** - * Removes a merged region of cells (hence letting them free) - * - * @param index of the region to unmerge - */ - @Override - public void removeMergedRegion(int index) { - if (!worksheet.isSetMergeCells()) { - return; - } - - CTMergeCells ctMergeCells = worksheet.getMergeCells(); - int size = ctMergeCells.sizeOfMergeCellArray(); - assert(0 <= index && index < size); - if (size > 1) { - ctMergeCells.removeMergeCell(index); - } else { - worksheet.unsetMergeCells(); - } - } - - /** - * Removes a number of merged regions of cells (hence letting them free) - * - * This method can be used to bulk-remove merged regions in a way - * much faster than calling removeMergedRegion() for every single - * merged region. - * - * @param indices A set of the regions to unmerge - */ - @Override - public void removeMergedRegions(Collection<Integer> indices) { - if (!worksheet.isSetMergeCells()) { - return; - } - - CTMergeCells ctMergeCells = worksheet.getMergeCells(); - List<CTMergeCell> newMergeCells = new ArrayList<>(ctMergeCells.sizeOfMergeCellArray()); - - int idx = 0; - for (CTMergeCell mc : ctMergeCells.getMergeCellArray()) { - if (!indices.contains(idx++)) { - newMergeCells.add(mc); - } - } - - if (newMergeCells.isEmpty()) { - worksheet.unsetMergeCells(); - } else { - CTMergeCell[] newMergeCellsArray = new CTMergeCell[newMergeCells.size()]; - ctMergeCells.setMergeCellArray(newMergeCells.toArray(newMergeCellsArray)); - } - } - - /** - * Remove a row from this sheet. All cells contained in the row are removed as well - * - * @param row the row to remove. - */ - @Override - public void removeRow(Row row) { - if (row.getSheet() != this) { - throw new IllegalArgumentException("Specified row does not belong to this sheet"); - } - // collect cells into a temporary array to avoid ConcurrentModificationException - ArrayList<XSSFCell> cellsToDelete = new ArrayList<>(); - for (Cell cell : row) { - cellsToDelete.add((XSSFCell)cell); - } - - for (XSSFCell cell : cellsToDelete) { - row.removeCell(cell); - } - - final int rowNum = row.getRowNum(); - // Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory - //noinspection UnnecessaryBoxing - final Integer rowNumI = Integer.valueOf(rowNum); // NOSONAR - // this is not the physical row number! - final int idx = _rows.headMap(rowNumI).size(); - _rows.remove(rowNumI); - worksheet.getSheetData().removeRow(idx); - - // also remove any comment located in that row - if(sheetComments != null) { - for (CellAddress ref : getCellComments().keySet()) { - if (ref.getRow() == rowNum) { - sheetComments.removeComment(ref); - } - } - } - } - - /** - * Removes the page break at the indicated row - */ - @Override - public void removeRowBreak(int row) { - if (worksheet.isSetRowBreaks()) { - removeBreak(row, worksheet.getRowBreaks()); - } // else no breaks - } - - /** - * Control if Excel should be asked to recalculate all formulas on this sheet - * when the workbook is opened. - * - * <p> - * Calculating the formula values with {@link FormulaEvaluator} is the - * recommended solution, but this may be used for certain cases where - * evaluation in POI is not possible. - * </p> - * - * <p> - * It is recommended to force recalcuation of formulas on workbook level using - * {@link Workbook#setForceFormulaRecalculation(boolean)} - * to ensure that all cross-worksheet formuals and external dependencies are updated. - * </p> - * @param value true if the application will perform a full recalculation of - * this worksheet values when the workbook is opened - * - * @see Workbook#setForceFormulaRecalculation(boolean) - */ - @Override - public void setForceFormulaRecalculation(boolean value) { - CTCalcPr calcPr = getWorkbook().getCTWorkbook().getCalcPr(); - - if(worksheet.isSetSheetCalcPr()) { - // Change the current setting - CTSheetCalcPr calc = worksheet.getSheetCalcPr(); - calc.setFullCalcOnLoad(value); - } - else if(value) { - // Add the Calc block and set it - CTSheetCalcPr calc = worksheet.addNewSheetCalcPr(); - calc.setFullCalcOnLoad(value); - } - if(value && calcPr != null && calcPr.getCalcMode() == STCalcMode.MANUAL) { - calcPr.setCalcMode(STCalcMode.AUTO); - } - - } - - /** - * Whether Excel will be asked to recalculate all formulas of this sheet - * when the workbook is opened. - * - * Note: This just returns if the sheet has the recalculate flag set and - * will still return false even if recalculation is enabled on workbook-level. - * - * @return true if the Sheet has the recalculate-flag set. - */ - @Override - public boolean getForceFormulaRecalculation() { - if(worksheet.isSetSheetCalcPr()) { - CTSheetCalcPr calc = worksheet.getSheetCalcPr(); - return calc.getFullCalcOnLoad(); - } - return false; - } - - /** - * @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not - * be the third row if say for instance the second row is undefined. - * Call getRowNum() on each row if you care which one it is. - */ - @Override - @SuppressWarnings("unchecked") - public Iterator<Row> rowIterator() { - return (Iterator<Row>)(Iterator<? extends Row>) _rows.values().iterator(); - } - - /** - * Alias for {@link #rowIterator()} to - * allow foreach loops - */ - @Override - public Iterator<Row> iterator() { - return rowIterator(); - } - - /** - * Flag indicating whether the sheet displays Automatic Page Breaks. - * - * @return <code>true</code> if the sheet displays Automatic Page Breaks. - */ - @Override - public boolean getAutobreaks() { - CTSheetPr sheetPr = getSheetTypeSheetPr(); - CTPageSetUpPr psSetup = (sheetPr == null || !sheetPr.isSetPageSetUpPr()) ? - CTPageSetUpPr.Factory.newInstance() : sheetPr.getPageSetUpPr(); - return psSetup.getAutoPageBreaks(); - } - - /** - * Flag indicating whether the sheet displays Automatic Page Breaks. - * - * @param value <code>true</code> if the sheet displays Automatic Page Breaks. - */ - @Override - public void setAutobreaks(boolean value) { - CTSheetPr sheetPr = getSheetTypeSheetPr(); - CTPageSetUpPr psSetup = sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr(); - psSetup.setAutoPageBreaks(value); - } - - /** - * Sets a page break at the indicated column. - * Breaks occur above the specified row and left of the specified column inclusive. - * - * For example, <code>sheet.setColumnBreak(2);</code> breaks the sheet into two parts - * with columns A,B,C in the first and D,E,... in the second. Simuilar, <code>sheet.setRowBreak(2);</code> - * breaks the sheet into two parts with first three rows (rownum=1...3) in the first part - * and rows starting with rownum=4 in the second. - * - * @param column the column to break, inclusive - */ - @Override - public void setColumnBreak(int column) { - if (!isColumnBroken(column)) { - CTPageBreak pgBreak = worksheet.isSetColBreaks() ? worksheet.getColBreaks() : worksheet.addNewColBreaks(); - setBreak(column, pgBreak, SpreadsheetVersion.EXCEL2007.getLastRowIndex()); - } - } - - @Override - public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) { - if (collapsed) { - collapseColumn(columnNumber); - } else { - expandColumn(columnNumber); - } - } - - private void collapseColumn(int columnNumber) { - CTCols cols = worksheet.getColsArray(0); - CTCol col = columnHelper.getColumn(columnNumber, false); - int colInfoIx = columnHelper.getIndexOfColumn(cols, col); - if (colInfoIx == -1) { - return; - } - // Find the start of the group. - int groupStartColInfoIx = findStartOfColumnOutlineGroup(colInfoIx); - - CTCol columnInfo = cols.getColArray(groupStartColInfoIx); - - // Hide all the columns until the end of the group - int lastColMax = setGroupHidden(groupStartColInfoIx, columnInfo - .getOutlineLevel(), true); - - // write collapse field - setColumn(lastColMax + 1, 0, null, null, Boolean.TRUE); - - } - - private void setColumn(int targetColumnIx, Integer style, - Integer level, Boolean hidden, Boolean collapsed) { - CTCols cols = worksheet.getColsArray(0); - CTCol ci = null; - for (CTCol tci : cols.getColArray()) { - long tciMin = tci.getMin(); - long tciMax = tci.getMax(); - if (tciMin >= targetColumnIx && tciMax <= targetColumnIx) { - ci = tci; - break; - } - if (tciMin > targetColumnIx) { - // call column infos after k are for later columns - break; // exit now so k will be the correct insert pos - } - } - - if (ci == null) { - // okay so there ISN'T a column info record that covers this column - // so lets create one! - CTCol nci = CTCol.Factory.newInstance(); - nci.setMin(targetColumnIx); - nci.setMax(targetColumnIx); - unsetCollapsed(collapsed, nci); - this.columnHelper.addCleanColIntoCols(cols, nci); - return; - } - - boolean styleChanged = style != null && ci.getStyle() != style; - boolean levelChanged = level != null && ci.getOutlineLevel() != level; - boolean hiddenChanged = hidden != null && ci.getHidden() != hidden; - boolean collapsedChanged = collapsed != null && ci.getCollapsed() != collapsed; - boolean columnChanged = levelChanged || hiddenChanged || collapsedChanged || styleChanged; - if (!columnChanged) { - // do nothing...nothing changed. - return; - } - - long ciMin = ci.getMin(); - long ciMax = ci.getMax(); - if (ciMin == targetColumnIx && ciMax == targetColumnIx) { - // ColumnInfo ci for a single column, the target column - unsetCollapsed(collapsed, ci); - return; - } - - if (ciMin == targetColumnIx || ciMax == targetColumnIx) { - // The target column is at either end of the multi-column ColumnInfo ci - // we'll just divide the info and create a new one - if (ciMin == targetColumnIx) { - ci.setMin(targetColumnIx + 1L); - } else { - ci.setMax(targetColumnIx - 1L); - } - CTCol nci = columnHelper.cloneCol(cols, ci); - nci.setMin(targetColumnIx); - unsetCollapsed(collapsed, nci); - this.columnHelper.addCleanColIntoCols(cols, nci); - - } else { - // split to 3 records - CTCol ciMid = columnHelper.cloneCol(cols, ci); - CTCol ciEnd = columnHelper.cloneCol(cols, ci); - int lastcolumn = Math.toIntExact(ciMax); - - ci.setMax(targetColumnIx - 1L); - - ciMid.setMin(targetColumnIx); - ciMid.setMax(targetColumnIx); - unsetCollapsed(collapsed, ciMid); - this.columnHelper.addCleanColIntoCols(cols, ciMid); - - ciEnd.setMin(targetColumnIx + 1L); - ciEnd.setMax(lastcolumn); - this.columnHelper.addCleanColIntoCols(cols, ciEnd); - } - } - - private void unsetCollapsed(Boolean collapsed, CTCol ci) { - if (collapsed != null && collapsed) { - ci.setCollapsed(true); - } else { - ci.unsetCollapsed(); - } - } - - /** - * Sets all adjacent columns of the same outline level to the specified - * hidden status. - * - * @param pIdx - * the col info index of the start of the outline group - * @return the column index of the last column in the outline group - */ - private int setGroupHidden(int pIdx, int level, boolean hidden) { - CTCols cols = worksheet.getColsArray(0); - int idx = pIdx; - CTCol[] colArray = cols.getColArray(); - CTCol columnInfo = colArray[idx]; - while (idx < colArray.length) { - columnInfo.setHidden(hidden); - if (idx + 1 < colArray.length) { - CTCol nextColumnInfo = colArray[idx + 1]; - - if (!isAdjacentBefore(columnInfo, nextColumnInfo)) { - break; - } - - if (nextColumnInfo.getOutlineLevel() < level) { - break; - } - columnInfo = nextColumnInfo; - } - idx++; - } - return Math.toIntExact(columnInfo.getMax()); - } - - private boolean isAdjacentBefore(CTCol col, CTCol otherCol) { - return col.getMax() == otherCol.getMin() - 1; - } - - private int findStartOfColumnOutlineGroup(int pIdx) { - // Find the start of the group. - CTCols cols = worksheet.getColsArray(0); - CTCol[] colArray = cols.getColArray(); - CTCol columnInfo = colArray[pIdx]; - int level = columnInfo.getOutlineLevel(); - int idx = pIdx; - while (idx != 0) { - CTCol prevColumnInfo = colArray[idx - 1]; - if (!isAdjacentBefore(prevColumnInfo, columnInfo)) { - break; - } - if (prevColumnInfo.getOutlineLevel() < level) { - break; - } - idx--; - columnInfo = prevColumnInfo; - } - return idx; - } - - private int findEndOfColumnOutlineGroup(int colInfoIndex) { - CTCols cols = worksheet.getColsArray(0); - // Find the end of the group. - CTCol[] colArray = cols.getColArray(); - CTCol columnInfo = colArray[colInfoIndex]; - int level = columnInfo.getOutlineLevel(); - int idx = colInfoIndex; - int lastIdx = colArray.length - 1; - while (idx < lastIdx) { - CTCol nextColumnInfo = colArray[idx + 1]; - if (!isAdjacentBefore(columnInfo, nextColumnInfo)) { - break; - } - if (nextColumnInfo.getOutlineLevel() < level) { - break; - } - idx++; - columnInfo = nextColumnInfo; - } - return idx; - } - - private void expandColumn(int columnIndex) { - CTCols cols = worksheet.getColsArray(0); - CTCol col = columnHelper.getColumn(columnIndex, false); - int colInfoIx = columnHelper.getIndexOfColumn(cols, col); - - int idx = findColInfoIdx(Math.toIntExact(col.getMax()), colInfoIx); - if (idx == -1) { - return; - } - - // If it is already expanded do nothing. - if (!isColumnGroupCollapsed(idx)) { - return; - } - - // Find the start/end of the group. - int startIdx = findStartOfColumnOutlineGroup(idx); - int endIdx = findEndOfColumnOutlineGroup(idx); - - // expand: - // colapsed bit must be unset - // hidden bit gets unset _if_ surrounding groups are expanded you can - // determine - // this by looking at the hidden bit of the enclosing group. You will - // have - // to look at the start and the end of the current group to determine - // which - // is the enclosing group - // hidden bit only is altered for this outline level. ie. don't - // uncollapse contained groups - CTCol[] colArray = cols.getColArray(); - CTCol columnInfo = colArray[endIdx]; - if (!isColumnGroupHiddenByParent(idx)) { - short outlineLevel = columnInfo.getOutlineLevel(); - boolean nestedGroup = false; - for (int i = startIdx; i <= endIdx; i++) { - CTCol ci = colArray[i]; - if (outlineLevel == ci.getOutlineLevel()) { - ci.unsetHidden(); - if (nestedGroup) { - nestedGroup = false; - ci.setCollapsed(true); - } - } else { - nestedGroup = true; - } - } - } - // Write collapse flag (stored in a single col info record after this - // outline group) - setColumn(Math.toIntExact(columnInfo.getMax() + 1), null, null, - Boolean.FALSE, Boolean.FALSE); - } - - private boolean isColumnGroupHiddenByParent(int idx) { - CTCols cols = worksheet.getColsArray(0); - // Look out outline details of end - int endLevel = 0; - boolean endHidden = false; - int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup(idx); - CTCol[] colArray = cols.getColArray(); - if (endOfOutlineGroupIdx < (colArray.length - 1)) { - CTCol nextInfo = colArray[endOfOutlineGroupIdx + 1]; - if (isAdjacentBefore(colArray[endOfOutlineGroupIdx], nextInfo)) { - endLevel = nextInfo.getOutlineLevel(); - endHidden = nextInfo.getHidden(); - } - } - // Look out outline details of start - int startLevel = 0; - boolean startHidden = false; - int startOfOutlineGroupIdx = findStartOfColumnOutlineGroup(idx); - if (startOfOutlineGroupIdx > 0) { - CTCol prevInfo = colArray[startOfOutlineGroupIdx - 1]; - - if (isAdjacentBefore(prevInfo, colArray[startOfOutlineGroupIdx])) { - startLevel = prevInfo.getOutlineLevel(); - startHidden = prevInfo.getHidden(); - } - - } - if (endLevel > startLevel) { - return endHidden; - } - return startHidden; - } - - private int findColInfoIdx(int columnValue, int fromColInfoIdx) { - CTCols cols = worksheet.getColsArray(0); - - if (columnValue < 0) { - throw new IllegalArgumentException( - "column parameter out of range: " + columnValue); - } - if (fromColInfoIdx < 0) { - throw new IllegalArgumentException( - "fromIdx parameter out of range: " + fromColInfoIdx); - } - - CTCol[] colArray = cols.getColArray(); - for (int k = fromColInfoIdx; k < colArray.length; k++) { - CTCol ci = colArray[k]; - - if (containsColumn(ci, columnValue)) { - return k; - } - - if (ci.getMin() > fromColInfoIdx) { - break; - } - - } - return -1; - } - - private boolean containsColumn(CTCol col, int columnIndex) { - return col.getMin() <= columnIndex && columnIndex <= col.getMax(); - } - - /** - * 'Collapsed' state is stored in a single column col info record - * immediately after the outline group - * - * @param idx The column-index to check - * @return a boolean represented if the column is collapsed - */ - private boolean isColumnGroupCollapsed(int idx) { - CTCols cols = worksheet.getColsArray(0); - CTCol[] colArray = cols.getColArray(); - int endOfOutlineGroupIdx = findEndOfColumnOutlineGroup(idx); - int nextColInfoIx = endOfOutlineGroupIdx + 1; - if (nextColInfoIx >= colArray.length) { - return false; - } - CTCol nextColInfo = colArray[nextColInfoIx]; - - CTCol col = colArray[endOfOutlineGroupIdx]; - if (!isAdjacentBefore(col, nextColInfo)) { - return false; - } - - return nextColInfo.getCollapsed(); - } - - /** - * Get the visibility state for a given column. - * - * @param columnIndex - the column to get (0-based) - * @param hidden - the visiblity state of the column - */ - @Override - public void setColumnHidden(int columnIndex, boolean hidden) { - columnHelper.setColHidden(columnIndex, hidden); - } - - /** - * Set the width (in units of 1/256th of a character width) - * - * <p> - * The maximum column width for an individual cell is 255 characters. - * This value represents the number of characters that can be displayed - * in a cell that is formatted with the standard font (first font in the workbook). - * </p> - * - * <p> - * Character width is defined as the maximum digit width - * of the numbers <code>0, 1, 2, ... 9</code> as rendered - * using the default font (first font in the workbook). - * <br> - * Unless you are using a very special font, the default character is '0' (zero), - * this is true for Arial (default font font in HSSF) and Calibri (default font in XSSF) - * </p> - * - * <p> - * Please note, that the width set by this method includes 4 pixels of margin padding (two on each side), - * plus 1 pixel padding for the gridlines (Section 3.3.1.12 of the OOXML spec). - * This results is a slightly less value of visible characters than passed to this method (approx. 1/2 of a character). - * </p> - * <p> - * To compute the actual number of visible characters, - * Excel uses the following formula (Section 3.3.1.12 of the OOXML spec): - * </p> - * <code> - * width = Truncate([{Number of Visible Characters} * - * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256)/256 - * </code> - * <p>Using the Calibri font as an example, the maximum digit width of 11 point font size is 7 pixels (at 96 dpi). - * If you set a column width to be eight characters wide, e.g. <code>setColumnWidth(columnIndex, 8*256)</code>, - * then the actual value of visible characters (the value shown in Excel) is derived from the following equation: - * <code> - Truncate([numChars*7+5]/7*256)/256 = 8; - * </code> - * - * which gives <code>7.29</code>. - * - * @param columnIndex - the column to set (0-based) - * @param width - the width in units of 1/256th of a character width - * @throws IllegalArgumentException if width > 255*256 (the maximum column width in Excel is 255 characters) - */ - @Override - public void setColumnWidth(int columnIndex, int width) { - if(width > 255*256) { - throw new IllegalArgumentException("The maximum column width for an individual cell is 255 characters."); - } - - columnHelper.setColWidth(columnIndex, (double)width/256); - columnHelper.setCustomWidth(columnIndex, true); - } - - @Override - public void setDefaultColumnStyle(int column, CellStyle style) { - columnHelper.setColDefaultStyle(column, style); - } - - /** - * Specifies the number of characters of the maximum digit width of the normal style's font. - * This value does not include margin padding or extra padding for gridlines. It is only the - * number of characters. - * - * @param width the number of characters. Default value is <code>8</code>. - */ - @Override - public void setDefaultColumnWidth(int width) { - getSheetTypeSheetFormatPr().setBaseColWidth(width); - } - - /** - * Set the default row height for the sheet (if the rows do not define their own height) in - * twips (1/20 of a point) - * - * @param height default row height in twips (1/20 of a point) - */ - @Override - public void setDefaultRowHeight(short height) { - setDefaultRowHeightInPoints((float)height / Font.TWIPS_PER_POINT); - } - - /** - * Sets default row height measured in point size. - * - * @param height default row height measured in point size. - */ - @Override - public void setDefaultRowHeightInPoints(float height) { - CTSheetFormatPr pr = getSheetTypeSheetFormatPr(); - pr.setDefaultRowHeight(height); - pr.setCustomHeight(true); - } - - /** - * Sets the flag indicating whether this sheet should display formulas. - * - * @param show <code>true</code> if this sheet should display formulas. - */ - @Override - public void setDisplayFormulas(boolean show) { - final CTSheetView dsv = getDefaultSheetView(true); - assert(dsv != null); - dsv.setShowFormulas(show); - } - - /** - * Flag indicating whether the Fit to Page print option is enabled. - * - * @param b <code>true</code> if the Fit to Page print option is enabled. - */ - @Override - public void setFitToPage(boolean b) { - getSheetTypePageSetUpPr().setFitToPage(b); - } - - /** - * Center on page horizontally when printing. - * - * @param value whether to center on page horizontally when printing. - */ - @Override - public void setHorizontallyCenter(boolean value) { - CTPrintOptions opts = worksheet.isSetPrintOptions() ? - worksheet.getPrintOptions() : worksheet.addNewPrintOptions(); - opts.setHorizontalCentered(value); - } - - /** - * Whether the output is vertically centered on the page. - * - * @param value true to vertically center, false otherwise. - */ - @Override - public void setVerticallyCenter(boolean value) { - CTPrintOptions opts = worksheet.isSetPrintOptions() ? - worksheet.getPrintOptions() : worksheet.addNewPrintOptions(); - opts.setVerticalCentered(value); - } - - /** - * group the row It is possible for collapsed to be false and yet still have - * the rows in question hidden. This can be achieved by having a lower - * outline level collapsed, thus hiding all the child rows. Note that in - * this case, if the lowest level were expanded, the middle level would - * remain collapsed. - * - * @param rowIndex - - * the row involved, 0 based - * @param collapse - - * boolean value for collapse - */ - @Override - public void setRowGroupCollapsed(int rowIndex, boolean collapse) { - if (collapse) { - collapseRow(rowIndex); - } else { - expandRow(rowIndex); - } - } - - /** - * @param rowIndex the zero based row index to collapse - */ - private void collapseRow(int rowIndex) { - XSSFRow row = getRow(rowIndex); - if (row != null) { - int startRow = findStartOfRowOutlineGroup(rowIndex); - - // Hide all the columns until the end of the group - int lastRow = writeHidden(row, startRow, true); - if (getRow(lastRow) != null) { - getRow(lastRow).getCTRow().setCollapsed(true); - } else { - XSSFRow newRow = createRow(lastRow); - newRow.getCTRow().setCollapsed(true); - } - } - } - - /** - * @param rowIndex the zero based row index to find from - */ - private int findStartOfRowOutlineGroup(int rowIndex) { - // Find the start of the group. - short level = getRow(rowIndex).getCTRow().getOutlineLevel(); - int currentRow = rowIndex; - while (getRow(currentRow) != null) { - if (getRow(currentRow).getCTRow().getOutlineLevel() < level) { - return currentRow + 1; - } - currentRow--; - } - return currentRow; - } - - private int writeHidden(XSSFRow xRow, int rowIndex, boolean hidden) { - short level = xRow.getCTRow().getOutlineLevel(); - for (Iterator<Row> it = rowIterator(); it.hasNext();) { - xRow = (XSSFRow) it.next(); - - // skip rows before the start of this group - if(xRow.getRowNum() < rowIndex) { - continue; - } - - if (xRow.getCTRow().getOutlineLevel() >= level) { - xRow.getCTRow().setHidden(hidden); - rowIndex++; - } - - } - return rowIndex; - } - - /** - * @param rowNumber the zero based row index to expand - */ - private void expandRow(int rowNumber) { - if (rowNumber == -1) { - return; - } - XSSFRow row = getRow(rowNumber); - // If it is already expanded do nothing. - if (!row.getCTRow().isSetHidden()) { - return; - } - - // Find the start of the group. - int startIdx = findStartOfRowOutlineGroup(rowNumber); - - // Find the end of the group. - int endIdx = findEndOfRowOutlineGroup(rowNumber); - - // expand: - // collapsed must be unset - // hidden bit gets unset _if_ surrounding groups are expanded you can - // determine - // this by looking at the hidden bit of the enclosing group. You will - // have - // to look at the start and the end of the current group to determine - // which - // is the enclosing group - // hidden bit only is altered for this outline level. ie. don't - // un-collapse contained groups - short level = row.getCTRow().getOutlineLevel(); - if (!isRowGroupHiddenByParent(rowNumber)) { - for (int i = startIdx; i < endIdx; i++) { - if (level == getRow(i).getCTRow().getOutlineLevel()) { - getRow(i).getCTRow().unsetHidden(); - } else if (!isRowGroupCollapsed(i)) { - getRow(i).getCTRow().unsetHidden(); - } - } - } - // Write collapse field - CTRow ctRow = getRow(endIdx).getCTRow(); - // This avoids an IndexOutOfBounds if multiple nested groups are collapsed/expanded - if(ctRow.getCollapsed()) { - ctRow.unsetCollapsed(); - } - } - - /** - * @param row the zero based row index to find from - */ - public int findEndOfRowOutlineGroup(int row) { - short level = getRow(row).getCTRow().getOutlineLevel(); - int currentRow; - final int lastRowNum = getLastRowNum(); - for (currentRow = row; currentRow < lastRowNum; currentRow++) { - if (getRow(currentRow) == null - || getRow(currentRow).getCTRow().getOutlineLevel() < level) { - break; - } - } - return currentRow; - } - - /** - * @param row the zero based row index to find from - */ - private boolean isRowGroupHiddenByParent(int row) { - // Look out outline details of end - int endLevel; - boolean endHidden; - int endOfOutlineGroupIdx = findEndOfRowOutlineGroup(row); - if (getRow(endOfOutlineGroupIdx) == null) { - endLevel = 0; - endHidden = false; - } else { - endLevel = getRow(endOfOutlineGroupIdx).getCTRow().getOutlineLevel(); - endHidden = getRow(endOfOutlineGroupIdx).getCTRow().getHidden(); - } - - // Look out outline details of start - int startLevel; - boolean startHidden; - int startOfOutlineGroupIdx = findStartOfRowOutlineGroup(row); - if (startOfOutlineGroupIdx < 0 - || getRow(startOfOutlineGroupIdx) == null) { - startLevel = 0; - startHidden = false; - } else { - startLevel = getRow(startOfOutlineGroupIdx).getCTRow() - .getOutlineLevel(); - startHidden = getRow(startOfOutlineGroupIdx).getCTRow() - .getHidden(); - } - if (endLevel > startLevel) { - return endHidden; - } - return startHidden; - } - - /** - * @param row the zero based row index to find from - */ - private boolean isRowGroupCollapsed(int row) { - int collapseRow = findEndOfRowOutlineGroup(row) + 1; - if (getRow(collapseRow) == null) { - return false; - } - return getRow(collapseRow).getCTRow().getCollapsed(); - } - - /** - * Window zoom magnification for current view representing percent values. - * Valid values range from 10 to 400. Horizontal & Vertical scale together. - * - * For example: - * <pre> - * 10 - 10% - * 20 - 20% - * ... - * 100 - 100% - * ... - * 400 - 400% - * </pre> - * - * Current view can be Normal, Page Layout, or Page Break Preview. - * - * @param scale window zoom magnification - * @throws IllegalArgumentException if scale is invalid - */ - @Override - public void setZoom(int scale) { - if (scale < 10 || scale > 400) { - throw new IllegalArgumentException("Valid scale values range from 10 to 400"); - } - final CTSheetView dsv = getDefaultSheetView(true); - assert(dsv != null); - dsv.setZoomScale(scale); - } - - - /** - * copyRows rows from srcRows to this sheet starting at destStartRow - * - * Additionally copies merged regions that are completely defined in these - * rows (ie. merged 2 cells on a row to be shifted). - * @param srcRows the rows to copy. Formulas will be offset by the difference - * in the row number of the first row in srcRows and destStartRow (even if srcRows - * are from a different sheet). - * @param destStartRow the row in this sheet to paste the first row of srcRows - * the remainder of srcRows will be pasted below destStartRow per the cell copy policy - * @param policy is the cell copy policy, which can be used to merge the source and destination - * when the source is blank, copy styles only, paste as value, etc - */ - @Beta - public void copyRows(List<? extends Row> srcRows, int destStartRow, CellCopyPolicy policy) { - if (srcRows == null || srcRows.size() == 0) { - throw new IllegalArgumentException("No rows to copy"); - } - final Row srcStartRow = srcRows.get(0); - final Row srcEndRow = srcRows.get(srcRows.size() - 1); - - if (srcStartRow == null) { - throw new IllegalArgumentException("copyRows: First row cannot be null"); - } - - final int srcStartRowNum = srcStartRow.getRowNum(); - final int srcEndRowNum = srcEndRow.getRowNum(); - - // check row numbers to make sure they are continuous and increasing (monotonic) - // and srcRows does not contain null rows - final int size = srcRows.size(); - for (int index=1; index < size; index++) { - final Row curRow = srcRows.get(index); - if (curRow == null) { - throw new IllegalArgumentException("srcRows may not contain null rows. Found null row at index " + index + "."); - //} else if (curRow.getRowNum() != prevRow.getRowNum() + 1) { - // throw new IllegalArgumentException("srcRows must contain continuously increasing row numbers. " + - // "Got srcRows[" + (index-1) + "]=Row " + prevRow.getRowNum() + ", srcRows[" + index + "]=Row " + curRow.getRowNum() + "."); - // FIXME: assumes row objects belong to non-null sheets and sheets belong to non-null workbooks. - } else if (srcStartRow.getSheet().getWorkbook() != curRow.getSheet().getWorkbook()) { - throw new IllegalArgumentException("All rows in srcRows must belong to the same sheet in the same workbook. " + - "Expected all rows from same workbook (" + srcStartRow.getSheet().getWorkbook() + "). " + - "Got srcRows[" + index + "] from different workbook (" + curRow.getSheet().getWorkbook() + ")."); - } else if (srcStartRow.getSheet() != curRow.getSheet()) { - throw new IllegalArgumentException("All rows in srcRows must belong to the same sheet. " + - "Expected all rows from " + srcStartRow.getSheet().getSheetName() + ". " + - "Got srcRows[" + index + "] from " + curRow.getSheet().getSheetName()); - } - } - - // FIXME: is special behavior needed if srcRows and destRows belong to the same sheets and the regions overlap? - - final CellCopyPolicy options = new CellCopyPolicy(policy); - // avoid O(N^2) performance scanning through all regions for each row - // merged regions will be copied after all the rows have been copied - options.setCopyMergedRegions(false); - - // FIXME: if srcRows contains gaps or null values, clear out those rows that will be overwritten - // how will this work with merging (copy just values, leave cell styles in place?) - - int r = destStartRow; - for (Row srcRow : srcRows) { - int destRowNum; - if (policy.isCondenseRows()) { - destRowNum = r++; - } else { - final int shift = (srcRow.getRowNum() - srcStartRowNum); - destRowNum = destStartRow + shift; - } - //removeRow(destRowNum); //this probably clears all external formula references to destRow, causing unwanted #REF! errors - final XSSFRow destRow = createRow(destRowNum); - destRow.copyRowFrom(srcRow, options); - } - - // ====================== - // Only do additional copy operations here that cannot be done with Row.copyFromRow(Row, options) - // reasons: operation needs to interact with multiple rows or sheets - - // Copy merged regions that are contained within the copy region - if (policy.isCopyMergedRegions()) { - // FIXME: is this something that rowShifter could be doing? - final int shift = destStartRow - srcStartRowNum; - for (CellRangeAddress srcRegion : srcStartRow.getSheet().getMergedRegions()) { - if (srcStartRowNum <= srcRegion.getFirstRow() && srcRegion.getLastRow() <= srcEndRowNum) { - // srcRegion is fully inside the copied rows - final CellRangeAddress destRegion = srcRegion.copy(); - destRegion.setFirstRow(destRegion.getFirstRow() + shift); - destRegion.setLastRow(destRegion.getLastRow() + shift); - addMergedRegion(destRegion); - } - } - } - } - - /** - * Copies rows between srcStartRow and srcEndRow to the same sheet, starting at destStartRow - * Convenience function for {@link #copyRows(List, int, CellCopyPolicy)} - * - * Equivalent to copyRows(getRows(srcStartRow, srcEndRow, false), destStartRow, cellCopyPolicy) - * - * @param srcStartRow the index of the first row to copy the cells from in this sheet - * @param srcEndRow the index of the last row to copy the cells from in this sheet - * @param destStartRow the index of the first row to copy the cells to in this sheet - * @param cellCopyPolicy the policy to use to determine how cells are copied - */ - @Beta - public void copyRows(int srcStartRow, int srcEndRow, int destStartRow, CellCopyPolicy cellCopyPolicy) { - final List<XSSFRow> srcRows = getRows(srcStartRow, srcEndRow, false); //FIXME: should be false, no need to create rows where src is only to copy them to dest - copyRows(srcRows, destStartRow, cellCopyPolicy); - } - - /** - * Shifts rows between startRow and endRow n number of rows. - * If you use a negative number, it will shift rows up. - * Code ensures that rows don't wrap around. - * - * Calls shiftRows(startRow, endRow, n, false, false); - * - * <p> - * Additionally shifts merged regions that are completely defined in these - * rows (ie. merged 2 cells on a row to be shifted). - * @param startRow the row to start shifting - * @param endRow the row to end shifting - * @param n the number of rows to shift - */ - @Override - public void shiftRows(int startRow, int endRow, int n) { - shiftRows(startRow, endRow, n, false, false); - } - - /** - * Shifts rows between startRow and endRow n number of rows. - * If you use a negative number, it will shift rows up. - * Code ensures that rows don't wrap around - * - * <p> - * Additionally shifts merged regions that are completely defined in these - * rows (ie. merged 2 cells on a row to be shifted). All merged regions that are - * completely overlaid by shifting will be deleted. - * <p> - * @param startRow the row to start shifting - * @param endRow the row to end shifting - * @param n the number of rows to shift - * @param copyRowHeight whether to copy the row height during the shift - * @param resetOriginalRowHeight whether to set the original row's height to the default - */ - @Override - public void shiftRows(int startRow, int endRow, final int n, boolean copyRowHeight, boolean resetOriginalRowHeight) { - XSSFVMLDrawing vml = getVMLDrawing(false); - - int sheetIndex = getWorkbook().getSheetIndex(this); - String sheetName = getWorkbook().getSheetName(sheetIndex); - FormulaShifter formulaShifter = FormulaShifter.createForRowShift( - sheetIndex, sheetName, startRow, endRow, n, SpreadsheetVersion.EXCEL2007); - removeOverwritten(vml, startRow, endRow, n); - shiftCommentsAndRows(vml, startRow, endRow, n); - - XSSFRowShifter rowShifter = new XSSFRowShifter(this); - rowShifter.shiftMergedRegions(startRow, endRow, n); - rowShifter.updateNamedRanges(formulaShifter); - rowShifter.updateFormulas(formulaShifter); - rowShifter.updateConditionalFormatting(formulaShifter); - rowShifter.updateHyperlinks(formulaShifter); - - rebuildRows(); - } - - /** - * Shifts columns between startColumn and endColumn n number of columns. - * If you use a negative number, it will shift columns left. - * Code ensures that columns don't wrap around - * - * @param startColumn the column to start shifting - * @param endColumn the column to end shifting - * @param n length of the shifting step - */ - @Override - public void shiftColumns(int startColumn, int endColumn, final int n) { - XSSFVMLDrawing vml = getVMLDrawing(false); - shiftCommentsForColumns(vml, startColumn, endColumn, n); - FormulaShifter formulaShifter = FormulaShifter.createForColumnShift(this.getWorkbook().getSheetIndex(this), this.getSheetName(), startColumn, endColumn, n, SpreadsheetVersion.EXCEL2007); - XSSFColumnShifter columnShifter = new XSSFColumnShifter(this); - columnShifter.shiftColumns(startColumn, endColumn, n); - columnShifter.shiftMergedRegions(startColumn, endColumn, n); - columnShifter.updateFormulas(formulaShifter); - columnShifter.updateConditionalFormatting(formulaShifter); - columnShifter.updateHyperlinks(formulaShifter); - columnShifter.updateNamedRanges(formulaShifter); - - rebuildRows(); - } - - private void rebuildRows() { - //rebuild the CTSheetData CTRow order - SortedMap<Long, CTRow> ctRows = new TreeMap<>(); - CTSheetData sheetData = getCTWorksheet().getSheetData(); - for (CTRow ctRow : sheetData.getRowList()) { - Long rownumL = ctRow.getR(); - ctRows.put(rownumL, ctRow); - } - List<CTRow> ctRowList = new ArrayList<>(ctRows.values()); - CTRow[] ctRowArray = new CTRow[ctRowList.size()]; - ctRowArray = ctRowList.toArray(ctRowArray); - sheetData.setRowArray(ctRowArray); - - //rebuild the _rows map - _rows.clear(); - for (CTRow ctRow : sheetData.getRowList()) { - XSSFRow row = new XSSFRow(ctRow, this); - Integer rownumI = Math.toIntExact(row.getRowNum()); - _rows.put(rownumI, row); - } - } - - // remove all rows which will be overwritten - private void removeOverwritten(XSSFVMLDrawing vml, int startRow, int endRow, final int n){ - for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) { - XSSFRow row = (XSSFRow)it.next(); - int rownum = row.getRowNum(); - - // check if we should remove this row as it will be overwritten by the data later - if (shouldRemoveRow(startRow, endRow, n, rownum)) { - // remove row from worksheet.getSheetData row array - // Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory - //noinspection UnnecessaryBoxing - final Integer rownumI = Integer.valueOf(row.getRowNum()); // NOSONAR - int idx = _rows.headMap(rownumI).size(); - worksheet.getSheetData().removeRow(idx); - - // remove row from _rows - it.remove(); - - // FIXME: (performance optimization) this should be moved outside the for-loop so that comments only needs to be iterated over once. - // also remove any comments associated with this row - if(sheetComments != null){ - CTCommentList lst = sheetComments.getCTComments().getCommentList(); - for (CTComment comment : lst.getCommentArray()) { - String strRef = comment.getRef(); - CellAddress ref = new CellAddress(strRef); - - // is this comment part of the current row? - if(ref.getRow() == rownum) { - sheetComments.removeComment(ref); - vml.removeCommentShape(ref.getRow(), ref.getColumn()); - } - } - } - // FIXME: (performance optimization) this should be moved outside the for-loop so that hyperlinks only needs to be iterated over once. - // also remove any hyperlinks associated with this row - if (hyperlinks != null) { - for (XSSFHyperlink link : new ArrayList<>(hyperlinks)) { - CellReference ref = new CellReference(link.getCellRef()); - if (ref.getRow() == rownum) { - hyperlinks.remove(link); - } - } - } - } - } - - } - - private void shiftCommentsAndRows(XSSFVMLDrawing vml, int startRow, int endRow, final int n){ - // then do the actual moving and also adjust comments/rowHeight - // we need to sort it in a way so the shifting does not mess up the structures, - // i.e. when shifting down, start from down and go up, when shifting up, vice-versa - SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>((o1, o2) -> { - int row1 = o1.getRow(); - int row2 = o2.getRow(); - - if (row1 == row2) { - // ordering is not important when row is equal, but don't return zero to still - // get multiple comments per row into the map - return o1.hashCode() - o2.hashCode(); - } - - // when shifting down, sort higher row-values first - if (n > 0) { - return row1 < row2 ? 1 : -1; - } else { - // sort lower-row values first when shifting up - return row1 > row2 ? 1 : -1; - } - }); - - - for (Iterator<Row> it = rowIterator() ; it.hasNext() ; ) { - XSSFRow row = (XSSFRow)it.next(); - int rownum = row.getRowNum(); - - if(sheetComments != null){ - // calculate the new rownum - int newrownum = shiftedRowNum(startRow, endRow, n, rownum); - - // is there a change necessary for the current row? - if(newrownum != rownum) { - CTCommentList lst = sheetComments.getCTComments().getCommentList(); - for (CTComment comment : lst.getCommentArray()) { - String oldRef = comment.getRef(); - CellReference ref = new CellReference(oldRef); - - // is this comment part of the current row? - if(ref.getRow() == rownum) { - XSSFComment xssfComment = new XSSFComment(sheetComments, comment, - vml == null ? null : vml.findCommentShape(rownum, ref.getCol())); - - // we should not perform the shifting right here as we would then find - // already shifted comments and would shift them again... - commentsToShift.put(xssfComment, newrownum); - } - } - } - } - - if(rownum < startRow || rownum > endRow) { - continue; - } - row.shift(n); - } - // adjust all the affected comment-structures now - // the Map is sorted and thus provides them in the order that we need here, - // i.e. from down to up if shifting down, vice-versa otherwise - for(Map.Entry<XSSFComment, Integer> entry : commentsToShift.entrySet()) { - entry.getKey().setRow(entry.getValue()); - } - - rebuildRows(); - } - - private int shiftedRowNum(int startRow, int endRow, int n, int rownum) { - // no change if before any affected row - if(rownum < startRow && (n > 0 || (startRow - rownum) > n)) { - return rownum; - } - - // no change if after any affected row - if(rownum > endRow && (n < 0 || (rownum - endRow) > n)) { - return rownum; - } - - // row before and things are moved up - if(rownum < startRow) { - // row is moved down by the shifting - return rownum + (endRow - startRow); - } - - // row is after and things are moved down - if(rownum > endRow) { - // row is moved up by the shifting - return rownum - (endRow - startRow); - } - - // row is part of the shifted block - return rownum + n; - } - - private void shiftCommentsForColumns(XSSFVMLDrawing vml, int startColumnIndex, int endColumnIndex, final int n){ - // then do the actual moving and also adjust comments/rowHeight - // we need to sort it in a way so the shifting does not mess up the structures, - // i.e. when shifting down, start from down and go up, when shifting up, vice-versa - SortedMap<XSSFComment, Integer> commentsToShift = new TreeMap<>((o1, o2) -> { - int column1 = o1.getColumn(); - int column2 = o2.getColumn(); - - if (column1 == column2) { - // ordering is not important when row is equal, but don't return zero to still - // get multiple comments per row into the map - return o1.hashCode() - o2.hashCode(); - } - - // when shifting down, sort higher row-values first - if (n > 0) { - return column1 < column2 ? 1 : -1; - } else { - // sort lower-row values first when shifting up - return column1 > column2 ? 1 : -1; - } - }); - - - if(sheetComments != null){ - CTCommentList lst = sheetComments.getCTComments().getCommentList(); - for (CTComment comment : lst.getCommentArray()) { - String oldRef = comment.getRef(); - CellReference ref = new CellReference(oldRef); - - int columnIndex =ref.getCol(); - int newColumnIndex = shiftedRowNum(startColumnIndex, endColumnIndex, n, columnIndex); - if(newColumnIndex != columnIndex){ - XSSFComment xssfComment = new XSSFComment(sheetComments, comment, - vml == null ? null : vml.findCommentShape(ref.getRow(), columnIndex)); - commentsToShift.put(xssfComment, newColumnIndex); - } - } - } - // adjust all the affected comment-structures now - // the Map is sorted and thus provides them in the order that we need here, - // i.e. from down to up if shifting down, vice-versa otherwise - for(Map.Entry<XSSFComment, Integer> entry : commentsToShift.entrySet()) { - entry.getKey().setColumn(entry.getValue()); - } - - rebuildRows(); - } - - /** - * Location of the top left visible cell Location of the top left visible cell in the bottom right - * pane (when in Left-to-Right mode). - * - * @param topRow the top row to show in desktop window pane - * @param leftCol the left column to show in desktop window pane - */ - @Override - public void showInPane(int topRow, int leftCol) { - final CellReference cellReference = new CellReference(topRow, leftCol); - final String cellRef = cellReference.formatAsString(); - final CTPane pane = getPane(true); - assert(pane != null); - pane.setTopLeftCell(cellRef); - } - - @Override - public void ungroupColumn(int fromColumn, int toColumn) { - CTCols cols = worksheet.getColsArray(0); - for (int index = fromColumn; index <= toColumn; index++) { - CTCol col = columnHelper.getColumn(index, false); - if (col != null) { - short outlineLevel = col.getOutlineLevel(); - col.setOutlineLevel((short) (outlineLevel - 1)); - index = Math.toIntExact(col.getMax()); - - if (col.getOutlineLevel() <= 0) { - int colIndex = columnHelper.getIndexOfColumn(cols, col); - worksheet.getColsArray(0).removeCol(colIndex); - } - } - } - worksheet.setColsArray(0, cols); - setSheetFormatPrOutlineLevelCol(); - } - - /** - * Ungroup a range of rows that were previously groupped - * - * @param fromRow start row (0-based) - * @param toRow end row (0-based) - */ - @Override - public void ungroupRow(int fromRow, int toRow) { - for (int i = fromRow; i <= toRow; i++) { - XSSFRow xrow = getRow(i); - if (xrow != null) { - CTRow ctRow = xrow.getCTRow(); - int outlineLevel = ctRow.getOutlineLevel(); - ctRow.setOutlineLevel((short) (outlineLevel - 1)); - //remove a row only if the row has no cell and if the outline level is 0 - if (outlineLevel == 1 && xrow.getFirstCellNum() == -1) { - removeRow(xrow); - } - } - } - setSheetFormatPrOutlineLevelRow(); - } - - private void setSheetFormatPrOutlineLevelRow(){ - short maxLevelRow=getMaxOutlineLevelRows(); - getSheetTypeSheetFormatPr().setOutlineLevelRow(maxLevelRow); - } - - private void setSheetFormatPrOutlineLevelCol(){ - short maxLevelCol=getMaxOutlineLevelCols(); - getSheetTypeSheetFormatPr().setOutlineLevelCol(maxLevelCol); - } - - protected CTSheetViews getSheetTypeSheetViews(final boolean create) { - final CTSheetViews views = (worksheet.isSetSheetViews() || !create) - ? worksheet.getSheetViews() : worksheet.addNewSheetViews(); - assert(views != null || !create); - if (views == null) { - return null; - } - if (views.sizeOfSheetViewArray() == 0 && create) { - views.addNewSheetView(); - } - return views; - } - - /** - * Returns a flag indicating whether this sheet is selected. - * <p> - * When only 1 sheet is selected and active, this value should be in synch with the activeTab value. - * In case of a conflict, the Start Part setting wins and sets the active sheet tab. - * </p> - * Note: multiple sheets can be selected, but only one sheet can be active at one time. - * - * @return <code>true</code> if this sheet is selected - */ - @Override - public boolean isSelected() { - final CTSheetView dsv = getDefaultSheetView(false); - return dsv != null && dsv.getTabSelected(); - } - - /** - * Sets a flag indicating whether this sheet is selected. - * - * <p> - * When only 1 sheet is selected and active, this value should be in synch with the activeTab value. - * In case of a conflict, the Start Part setting wins and sets the active sheet tab. - * </p> - * Note: multiple sheets can be selected, but only one sheet can be active at one time. - * - * @param value <code>true</code> if this sheet is selected - */ - @Override - public void setSelected(boolean value) { - final CTSheetViews views = getSheetTypeSheetViews(true); - assert(views != null); - for (CTSheetView view : views.getSheetViewArray()) { - view.setTabSelected(value); - } - } - - /** - * Register a hyperlink in the collection of hyperlinks on this sheet - * - * @param hyperlink the link to add - */ - @Internal - public void addHyperlink(XSSFHyperlink hyperlink) { - hyperlinks.add(hyperlink); - } - - /** - * Removes a hyperlink in the collection of hyperlinks on this sheet - * - * @param row row index - * @param column column index - */ - @Internal - public void removeHyperlink(int row, int column) { - // CTHyperlinks is regenerated from scratch when writing out the spreadsheet - // so don't worry about maintaining hyperlinks and CTHyperlinks in parallel. - // only maintain hyperlinks - String ref = new CellReference(row, column).formatAsString(); - for (Iterator<XSSFHyperlink> it = hyperlinks.iterator(); it.hasNext();) { - XSSFHyperlink hyperlink = it.next(); - if (hyperlink.getCellRef().equals(ref)) { - it.remove(); - return; - } - } - } - - /** - * Return location of the active cell, e.g. <code>A1</code>. - * - * @return the location of the active cell. - */ - @Override - public CellAddress getActiveCell() { - final CTSelection sts = getSheetTypeSelection(false); - final String address = (sts != null) ? sts.getActiveCell() : null; - return (address != null) ? new CellAddress(address) : null; - } - - /** - * {@inheritDoc} - */ - @Override - public void setActiveCell(CellAddress address) { - final CTSelection ctsel = getSheetTypeSelection(true); - assert(ctsel != null); - String ref = address.formatAsString(); - ctsel.setActiveCell(ref); - ctsel.setSqref(Collections.singletonList(ref)); - } - - /** - * Does this sheet have any comments on it? We need to know, - * so we can decide about writing it to disk or not - */ - public boolean hasComments() { - return sheetComments != null && sheetComments.getNumberOfComments() > 0; - } - - protected int getNumberOfComments() { - return sheetComments == null ? 0 : sheetComments.getNumberOfComments(); - } - - private CTSelection getSheetTypeSelection(final boolean create) { - final CTSheetView dsv = getDefaultSheetView(create); - assert(dsv != null || !create); - if (dsv == null) { - return null; - } - final int sz = dsv.sizeOfSelectionArray(); - if (sz == 0) { - return create ? dsv.addNewSelection() : null; - } - return dsv.getSelectionArray(sz - 1); - } - - /** - * Return the default sheet view. This is the last one if the sheet's views, according to sec. 3.3.1.83 - * of the OOXML spec: "A single sheet view definition. When more than 1 sheet view is defined in the file, - * it means that when opening the workbook, each sheet view corresponds to a separate window within the - * spreadsheet application, where each window is showing the particular sheet. containing the same - * workbookViewId value, the last sheetView definition is loaded, and the others are discarded. - * When multiple windows are viewing the same sheet, multiple sheetView elements (with corresponding - * workbookView entries) are saved." - */ - private CTSheetView getDefaultSheetView(final boolean create) { - final CTSheetViews views = getSheetTypeSheetViews(create); - assert(views != null || !create); - if (views == null) { - return null; - } - final int sz = views.sizeOfSheetViewArray(); - assert(sz > 0 || !create); - return (sz == 0) ? null : views.getSheetViewArray(sz - 1); - } - - /** - * Returns the sheet's comments object if there is one, - * or null if not - * - * @param create create a new comments table if it does not exist - */ - protected CommentsTable getCommentsTable(boolean create) { - if(sheetComments == null && create){ - // Try to create a comments table with the same number as - // the sheet has (i.e. sheet 1 -> comments 1) - try { - sheetComments = (CommentsTable)createRelationship( - XSSFRelation.SHEET_COMMENTS, XSSFFactory.getInstance(), Math.toIntExact(sheet.getSheetId())); - } catch(PartAlreadyExistsException e) { - // Technically a sheet doesn't need the same number as - // it's comments, and clearly someone has already pinched - // our number! Go for the next available one instead - sheetComments = (CommentsTable)createRelationship( - XSSFRelation.SHEET_COMMENTS, XSSFFactory.getInstance(), -1); - } - } - return sheetComments; - } - - private CTPageSetUpPr getSheetTypePageSetUpPr() { - CTSheetPr sheetPr = getSheetTypeSheetPr(); - return sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr(); - } - - private static boolean shouldRemoveRow(int startRow, int endRow, int n, int rownum) { - // is this row in the target-window where the moved rows will land? - if (rownum >= (startRow + n) && rownum <= (endRow + n)) { - // only remove it if the current row is not part of the data that is copied - if (n > 0 && rownum > endRow) { - return true; - } - else { - return n < 0 && rownum < startRow; - } - } - return false; - } - - private CTPane getPane(final boolean create) { - final CTSheetView dsv = getDefaultSheetView(create); - assert(dsv != null || !create); - if (dsv == null) { - return null; - } - return (dsv.isSetPane() || !create) ? dsv.getPane() : dsv.addNewPane(); - } - - /** - * Return a master shared formula by index - * - * @param sid shared group index - * @return a CTCellFormula bean holding shared formula or <code>null</code> if not found - */ - @Internal - public CTCellFormula getSharedFormula(int sid){ - return sharedFormulas.get(sid); - } - - void onReadCell(XSSFCell cell){ - //collect cells holding shared formulas - CTCell ct = cell.getCTCell(); - CTCellFormula f = ct.getF(); - if (f != null && f.getT() == STCellFormulaType.SHARED && f.isSetRef() && f.getStringValue() != null) { - // save a detached copy to avoid XmlValueDisconnectedException, - // this may happen when the master cell of a shared formula is changed - CTCellFormula sf = (CTCellFormula)f.copy(); - CellRangeAddress sfRef = CellRangeAddress.valueOf(sf.getRef()); - CellReference cellRef = new CellReference(cell); - // If the shared formula range precedes the master cell then the preceding part is discarded, e.g. - // if the cell is E60 and the shared formula range is C60:M85 then the effective range is E60:M85 - // see more details in https://issues.apache.org/bugzilla/show_bug.cgi?id=51710 - if(cellRef.getCol() > sfRef.getFirstColumn() || cellRef.getRow() > sfRef.getFirstRow()){ - String effectiveRef = new CellRangeAddress( - Math.max(cellRef.getRow(), sfRef.getFirstRow()), Math.max(cellRef.getRow(), sfRef.getLastRow()), - Math.max(cellRef.getCol(), sfRef.getFirstColumn()), Math.max(cellRef.getCol(), sfRef.getLastColumn())) - .formatAsString(); - sf.setRef(effectiveRef); - } - - sharedFormulas.put(Math.toIntExact(f.getSi()), sf); - } - if (f != null && f.getT() == STCellFormulaType.ARRAY && f.getRef() != null) { - arrayFormulas.add(CellRangeAddress.valueOf(f.getRef())); - } - } - - @Override - protected void commit() throws IOException { - PackagePart part = getPackagePart(); - OutputStream out = part.getOutputStream(); - write(out); - out.close(); - } - - protected void write(OutputStream out) throws IOException { - boolean setToNull = false; - if(worksheet.sizeOfColsArray() == 1) { - CTCols col = worksheet.getColsArray(0); - if(col.sizeOfColArray() == 0) { - setToNull = true; - // this is necessary so that we do not write an empty <cols/> item into the sheet-xml in the xlsx-file - // Excel complains about a corrupted file if this shows up there! - worksheet.setColsArray(null); - } else { - setColWidthAttribute(col); - } - } - - // Now re-generate our CTHyperlinks, if needed - if(hyperlinks.size() > 0) { - if(worksheet.getHyperlinks() == null) { - worksheet.addNewHyperlinks(); - } - CTHyperlink[] ctHls = new CTHyperlink[hyperlinks.size()]; - for(int i=0; i<ctHls.length; i++) { - // If our sheet has hyperlinks, have them add - // any relationships that they might need - XSSFHyperlink hyperlink = hyperlinks.get(i); - hyperlink.generateRelationIfNeeded(getPackagePart()); - // Now grab their underling object - ctHls[i] = hyperlink.getCTHyperlink(); - } - worksheet.getHyperlinks().setHyperlinkArray(ctHls); - } - else { - if (worksheet.getHyperlinks() != null) { - final int count = worksheet.getHyperlinks().sizeOfHyperlinkArray(); - for (int i=count-1; i>=0; i--) { - worksheet.getHyperlinks().removeHyperlink(i); - } - // For some reason, we have to remove the hyperlinks one by one from the CTHyperlinks array - // before unsetting the hyperlink array. - // Resetting the hyperlink array seems to break some XML nodes. - //worksheet.getHyperlinks().setHyperlinkArray(new CTHyperlink[0]); - worksheet.unsetHyperlinks(); - } /*else { - // nothing to do - }*/ - } - - int minCell = Integer.MAX_VALUE, maxCell = Integer.MIN_VALUE; - for(Map.Entry<Integer, XSSFRow> entry : _rows.entrySet()) { - XSSFRow row = entry.getValue(); - - // first perform the normal write actions for the row - row.onDocumentWrite(); - - // then calculate min/max cell-numbers for the worksheet-dimension - if(row.getFirstCellNum() != -1) { - minCell = Math.min(minCell, row.getFirstCellNum()); - } - if(row.getLastCellNum() != -1) { - maxCell = Math.max(maxCell, row.getLastCellNum()-1); - } - } - - // finally, if we had at least one cell we can populate the optional dimension-field - if(minCell != Integer.MAX_VALUE) { - String ref = new CellRangeAddress(getFirstRowNum(), getLastRowNum(), minCell, maxCell).formatAsString(); - if(worksheet.isSetDimension()) { - worksheet.getDimension().setRef(ref); - } else { - worksheet.addNewDimension().setRef(ref); - } - } - - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet")); - - worksheet.save(out, xmlOptions); - - // Bug 52233: Ensure that we have a col-array even if write() removed it - if(setToNull) { - worksheet.addNewCols(); - } - } - - /** - * @return true when Autofilters are locked and the sheet is protected. - */ - public boolean isAutoFilterLocked() { - return isSheetLocked() && safeGetProtectionField().getAutoFilter(); - } - - /** - * @return true when Deleting columns is locked and the sheet is protected. - */ - public boolean isDeleteColumnsLocked() { - return isSheetLocked() && safeGetProtectionField().getDeleteColumns(); - } - - /** - * @return true when Deleting rows is locked and the sheet is protected. - */ - public boolean isDeleteRowsLocked() { - return isSheetLocked() && safeGetProtectionField().getDeleteRows(); - } - - /** - * @return true when Formatting cells is locked and the sheet is protected. - */ - public boolean isFormatCellsLocked() { - return isSheetLocked() && safeGetProtectionField().getFormatCells(); - } - - /** - * @return true when Formatting columns is locked and the sheet is protected. - */ - public boolean isFormatColumnsLocked() { - return isSheetLocked() && safeGetProtectionField().getFormatColumns(); - } - - /** - * @return true when Formatting rows is locked and the sheet is protected. - */ - public boolean isFormatRowsLocked() { - return isSheetLocked() && safeGetProtectionField().getFormatRows(); - } - - /** - * @return true when Inserting columns is locked and the sheet is protected. - */ - public boolean isInsertColumnsLocked() { - return isSheetLocked() && safeGetProtectionField().getInsertColumns(); - } - - /** - * @return true when Inserting hyperlinks is locked and the sheet is protected. - */ - public boolean isInsertHyperlinksLocked() { - return isSheetLocked() && safeGetProtectionField().getInsertHyperlinks(); - } - - /** - * @return true when Inserting rows is locked and the sheet is protected. - */ - public boolean isInsertRowsLocked() { - return isSheetLocked() && safeGetProtectionField().getInsertRows(); - } - - /** - * @return true when Pivot tables are locked and the sheet is protected. - */ - public boolean isPivotTablesLocked() { - return isSheetLocked() && safeGetProtectionField().getPivotTables(); - } - - /** - * @return true when Sorting is locked and the sheet is protected. - */ - public boolean isSortLocked() { - return isSheetLocked() && safeGetProtectionField().getSort(); - } - - /** - * @return true when Objects are locked and the sheet is protected. - */ - public boolean isObjectsLocked() { - return isSheetLocked() && safeGetProtectionField().getObjects(); - } - - /** - * @return true when Scenarios are locked and the sheet is protected. - */ - public boolean isScenariosLocked() { - return isSheetLocked() && safeGetProtectionField().getScenarios(); - } - - /** - * @return true when Selection of locked cells is locked and the sheet is protected. - */ - public boolean isSelectLockedCellsLocked() { - return isSheetLocked() && safeGetProtectionField().getSelectLockedCells(); - } - - /** - * @return true when Selection of unlocked cells is locked and the sheet is protected. - */ - public boolean isSelectUnlockedCellsLocked() { - return isSheetLocked() && safeGetProtectionField().getSelectUnlockedCells(); - } - - /** - * @return true when Sheet is Protected. - */ - public boolean isSheetLocked() { - return worksheet.isSetSheetProtection() && safeGetProtectionField().getSheet(); - } - - /** - * Enable sheet protection - */ - public void enableLocking() { - safeGetProtectionField().setSheet(true); - } - - /** - * Disable sheet protection - */ - public void disableLocking() { - safeGetProtectionField().setSheet(false); - } - - /** - * Enable or disable Autofilters locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockAutoFilter(boolean enabled) { - safeGetProtectionField().setAutoFilter(enabled); - } - - /** - * Enable or disable Deleting columns locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockDeleteColumns(boolean enabled) { - safeGetProtectionField().setDeleteColumns(enabled); - } - - /** - * Enable or disable Deleting rows locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockDeleteRows(boolean enabled) { - safeGetProtectionField().setDeleteRows(enabled); - } - - /** - * Enable or disable Formatting cells locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockFormatCells(boolean enabled) { - safeGetProtectionField().setFormatCells(enabled); - } - - /** - * Enable or disable Formatting columns locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockFormatColumns(boolean enabled) { - safeGetProtectionField().setFormatColumns(enabled); - } - - /** - * Enable or disable Formatting rows locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockFormatRows(boolean enabled) { - safeGetProtectionField().setFormatRows(enabled); - } - - /** - * Enable or disable Inserting columns locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockInsertColumns(boolean enabled) { - safeGetProtectionField().setInsertColumns(enabled); - } - - /** - * Enable or disable Inserting hyperlinks locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockInsertHyperlinks(boolean enabled) { - safeGetProtectionField().setInsertHyperlinks(enabled); - } - - /** - * Enable or disable Inserting rows locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockInsertRows(boolean enabled) { - safeGetProtectionField().setInsertRows(enabled); - } - - /** - * Enable or disable Pivot Tables locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockPivotTables(boolean enabled) { - safeGetProtectionField().setPivotTables(enabled); - } - - /** - * Enable or disable Sort locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockSort(boolean enabled) { - safeGetProtectionField().setSort(enabled); - } - - /** - * Enable or disable Objects locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockObjects(boolean enabled) { - safeGetProtectionField().setObjects(enabled); - } - - /** - * Enable or disable Scenarios locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockScenarios(boolean enabled) { - safeGetProtectionField().setScenarios(enabled); - } - - /** - * Enable or disable Selection of locked cells locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockSelectLockedCells(boolean enabled) { - safeGetProtectionField().setSelectLockedCells(enabled); - } - - /** - * Enable or disable Selection of unlocked cells locking. - * This does not modify sheet protection status. - * To enforce this un-/locking, call {@link #disableLocking()} or {@link #enableLocking()} - */ - public void lockSelectUnlockedCells(boolean enabled) { - safeGetProtectionField().setSelectUnlockedCells(enabled); - } - - private CTSheetProtection safeGetProtectionField() { - if (!isSheetProtectionEnabled()) { - return worksheet.addNewSheetProtection(); - } - return worksheet.getSheetProtection(); - } - - /* package */ boolean isSheetProtectionEnabled() { - return (worksheet.isSetSheetProtection()); - } - - /* package */ boolean isCellInArrayFormulaContext(XSSFCell cell) { - for (CellRangeAddress range : arrayFormulas) { - if (range.isInRange(cell.getRowIndex(), cell.getColumnIndex())) { - return true; - } - } - return false; - } - - /* package */ XSSFCell getFirstCellInArrayFormula(XSSFCell cell) { - for (CellRangeAddress range : arrayFormulas) { - if (range.isInRange(cell.getRowIndex(), cell.getColumnIndex())) { - return getRow(range.getFirstRow()).getCell(range.getFirstColumn()); - } - } - return null; - } - - /** - * Also creates cells if they don't exist - */ - private CellRange<XSSFCell> getCellRange(CellRangeAddress range) { - int firstRow = range.getFirstRow(); - int firstColumn = range.getFirstColumn(); - int lastRow = range.getLastRow(); - int lastColumn = range.getLastColumn(); - int height = lastRow - firstRow + 1; - int width = lastColumn - firstColumn + 1; - List<XSSFCell> temp = new ArrayList<>(height * width); - for (int rowIn = firstRow; rowIn <= lastRow; rowIn++) { - for (int colIn = firstColumn; colIn <= lastColumn; colIn++) { - XSSFRow row = getRow(rowIn); - if (row == null) { - row = createRow(rowIn); - } - XSSFCell cell = row.getCell(colIn); - if (cell == null) { - cell = row.createCell(colIn); - } - temp.add(cell); - } - } - return SSCellRange.create(firstRow, firstColumn, height, width, temp, XSSFCell.class); - } - - @Override - public CellRange<XSSFCell> setArrayFormula(String formula, CellRangeAddress range) { - CellRange<XSSFCell> cr = getCellRange(range); - - XSSFCell mainArrayFormulaCell = cr.getTopLeftCell(); - mainArrayFormulaCell.setCellArrayFormula(formula, range); - arrayFormulas.add(range); - return cr; - } - - @Override - public CellRange<XSSFCell> removeArrayFormula(Cell cell) { - if (cell.getSheet() != this) { - throw new IllegalArgumentException("Specified cell does not belong to this sheet."); - } - for (CellRangeAddress range : arrayFormulas) { - if (range.isInRange(cell)) { - arrayFormulas.remove(range); - CellRange<XSSFCell> cr = getCellRange(range); - for (XSSFCell c : cr) { - c.setBlank(); - } - return cr; - } - } - String ref = new CellReference(cell).formatAsString(); - throw new IllegalArgumentException("Cell " + ref + " is not part of an array formula."); - } - - - @Override - public DataValidationHelper getDataValidationHelper() { - return dataValidationHelper; - } - - @Override - public List<XSSFDataValidation> getDataValidations() { - List<XSSFDataValidation> xssfValidations = new ArrayList<>(); - CTDataValidations dataValidations = this.worksheet.getDataValidations(); - if (dataValidations != null) { - for (CTDataValidation ctDataValidation : dataValidations.getDataValidationArray()) { - CellRangeAddressList addressList = new CellRangeAddressList(); - - @SuppressWarnings("unchecked") - List<String> sqref = ctDataValidation.getSqref(); - for (String stRef : sqref) { - String[] regions = stRef.split(" "); - for (String region : regions) { - String[] parts = region.split(":"); - CellReference begin = new CellReference(parts[0]); - CellReference end = parts.length > 1 ? new CellReference(parts[1]) : begin; - CellRangeAddress cellRangeAddress = new CellRangeAddress(begin.getRow(), end.getRow(), begin.getCol(), end.getCol()); - addressList.addCellRangeAddress(cellRangeAddress); - } - } - XSSFDataValidation xssfDataValidation = new XSSFDataValidation(addressList, ctDataValidation); - xssfValidations.add(xssfDataValidation); - } - } - - return xssfValidations; - } - - @Override - public void addValidationData(DataValidation dataValidation) { - XSSFDataValidation xssfDataValidation = (XSSFDataValidation)dataValidation; - CTDataValidations dataValidations = worksheet.getDataValidations(); - if( dataValidations==null ) { - dataValidations = worksheet.addNewDataValidations(); - } - int currentCount = dataValidations.sizeOfDataValidationArray(); - CTDataValidation newval = dataValidations.addNewDataValidation(); - newval.set(xssfDataValidation.getCtDataValidation()); - dataValidations.setCount(currentCount + 1L); - - } - - @Override - public XSSFAutoFilter setAutoFilter(CellRangeAddress range) { - CTAutoFilter af = worksheet.getAutoFilter(); - if(af == null) { - af = worksheet.addNewAutoFilter(); - } - - CellRangeAddress norm = new CellRangeAddress(range.getFirstRow(), range.getLastRow(), - range.getFirstColumn(), range.getLastColumn()); - String ref = norm.formatAsString(); - af.setRef(ref); - - XSSFWorkbook wb = getWorkbook(); - int sheetIndex = getWorkbook().getSheetIndex(this); - XSSFName name = wb.getBuiltInName(XSSFName.BUILTIN_FILTER_DB, sheetIndex); - if (name == null) { - name = wb.createBuiltInName(XSSFName.BUILTIN_FILTER_DB, sheetIndex); - } - - name.getCTName().setHidden(true); - CellReference r1 = new CellReference(getSheetName(), range.getFirstRow(), range.getFirstColumn(), true, true); - CellReference r2 = new CellReference(null, range.getLastRow(), range.getLastColumn(), true, true); - String fmla = r1.formatAsString() + ":" + r2.formatAsString(); - name.setRefersToFormula(fmla); - - return new XSSFAutoFilter(this); - } - - /** - * Creates a new Table, and associates it with this Sheet. - * <p> - * The table is assigned a default display name (since 4.1.1) which can be overridden - * by calling {@code setDisplayName}. The default display name is guaranteed to not conflict - * with the names of any {@code XSSFName} or {@code XSSFTable} in the workbook. - * - * @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(); - } - - CTTableParts tblParts = worksheet.getTableParts(); - CTTablePart tbl = tblParts.addNewTablePart(); - - // Table numbers need to be unique in the file, not just - // unique within the sheet. Find the next one - int tableNumber = getPackagePart().getPackage().getPartsByContentType(XSSFRelation.TABLE.getContentType()).size() + 1; - - // the id could already be taken after insertion/deletion of different tables - boolean loop = true; - while(loop) { - loop = false; - for (PackagePart packagePart : getPackagePart().getPackage().getPartsByContentType(XSSFRelation.TABLE.getContentType())) { - String fileName = XSSFRelation.TABLE.getFileName(tableNumber); - if(fileName.equals(packagePart.getPartName().getName())) { - // duplicate found, increase the number and start iterating again - tableNumber++; - loop = true; - } - } - } - - RelationPart rp = createRelationship(XSSFRelation.TABLE, XSSFFactory.getInstance(), tableNumber, false); - XSSFTable table = rp.getDocumentPart(); - tbl.setId(rp.getRelationship().getId()); - table.getCTTable().setId(tableNumber); - - tables.put(tbl.getId(), table); - - if(tableArea != null) { - table.setArea(tableArea); - } - - // Set the default name of the table. This must not conflict with any defined names. - while(tableNumber<Integer.MAX_VALUE) { - final String displayName="Table"+tableNumber; - if(getWorkbook().getTable(displayName) == null && - getWorkbook().getName(displayName) == null) { - table.setDisplayName(displayName); - table.setName(displayName); - break; - } - ++tableNumber; - } - - return table; - } - - /** - * Returns any tables associated with this Sheet - */ - public List<XSSFTable> getTables() { - return new ArrayList<>(tables.values()); - } - - /** - * Remove table references and relations - * @param t table to remove - */ - public void removeTable(XSSFTable t) { - long id = t.getCTTable().getId(); - Map.Entry<String, XSSFTable> toDelete = null; - - for (Map.Entry<String, XSSFTable> entry : tables.entrySet()) { - if (entry.getValue().getCTTable().getId() == id) toDelete = entry; - } - if (toDelete != null) { - removeRelation(getRelationById(toDelete.getKey()), true); - tables.remove(toDelete.getKey()); - toDelete.getValue().onTableDelete(); - } - } - - @Override - public XSSFSheetConditionalFormatting getSheetConditionalFormatting(){ - return new XSSFSheetConditionalFormatting(this); - } - - /** - * Get background color of the sheet tab. - * Returns <tt>null</tt> if no sheet tab color is set. - * - * @return the background color of the sheet tab - */ - public XSSFColor getTabColor() { - CTSheetPr pr = worksheet.getSheetPr(); - if(pr == null) { - pr = worksheet.addNewSheetPr(); - } - if (!pr.isSetTabColor()) { - return null; - } - return XSSFColor.from(pr.getTabColor(), getWorkbook().getStylesSource().getIndexedColors()); - } - - /** - * Set background color of the sheet tab - * - * @param color the color to set - */ - public void setTabColor(XSSFColor color) { - CTSheetPr pr = worksheet.getSheetPr(); - if(pr == null) { - pr = worksheet.addNewSheetPr(); - } - pr.setTabColor(color.getCTColor()); - } - - @Override - public CellRangeAddress getRepeatingRows() { - return getRepeatingRowsOrColums(true); - } - - - @Override - public CellRangeAddress getRepeatingColumns() { - return getRepeatingRowsOrColums(false); - } - - @Override - public void setRepeatingRows(CellRangeAddress rowRangeRef) { - CellRangeAddress columnRangeRef = getRepeatingColumns(); - setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef); - } - - - @Override - public void setRepeatingColumns(CellRangeAddress columnRangeRef) { - CellRangeAddress rowRangeRef = getRepeatingRows(); - setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef); - } - - - private void setRepeatingRowsAndColumns( - CellRangeAddress rowDef, CellRangeAddress colDef) { - int col1 = -1; - int col2 = -1; - int row1 = -1; - int row2 = -1; - - if (rowDef != null) { - row1 = rowDef.getFirstRow(); - row2 = rowDef.getLastRow(); - if ((row1 == -1 && row2 != -1) - || row1 < -1 || row2 < -1 || row1 > row2) { - throw new IllegalArgumentException("Invalid row range specification"); - } - } - if (colDef != null) { - col1 = colDef.getFirstColumn(); - col2 = colDef.getLastColumn(); - if ((col1 == -1 && col2 != -1) - || col1 < -1 || col2 < -1 || col1 > col2) { - throw new IllegalArgumentException( - "Invalid column range specification"); - } - } - - int sheetIndex = getWorkbook().getSheetIndex(this); - - boolean removeAll = rowDef == null && colDef == null; - - XSSFName name = getWorkbook().getBuiltInName( - XSSFName.BUILTIN_PRINT_TITLE, sheetIndex); - if (removeAll) { - if (name != null) { - getWorkbook().removeName(name); - } - return; - } - if (name == null) { - name = getWorkbook().createBuiltInName( - XSSFName.BUILTIN_PRINT_TITLE, sheetIndex); - } - - String reference = getReferenceBuiltInRecord( - name.getSheetName(), col1, col2, row1, row2); - name.setRefersToFormula(reference); - - // If the print setup isn't currently defined, then add it - // in but without printer defaults - // If it's already there, leave it as-is! - if (worksheet.isSetPageSetup() && worksheet.isSetPageMargins()) { - // Everything we need is already there - } else { - // Have initial ones put in place - getPrintSetup().setValidSettings(false); - } - } - - private static String getReferenceBuiltInRecord( - String sheetName, int startC, int endC, int startR, int endR) { - // Excel example for built-in title: - // 'second sheet'!$E:$F,'second sheet'!$2:$3 - - CellReference colRef = - new CellReference(sheetName, 0, startC, true, true); - CellReference colRef2 = - new CellReference(sheetName, 0, endC, true, true); - CellReference rowRef = - new CellReference(sheetName, startR, 0, true, true); - CellReference rowRef2 = - new CellReference(sheetName, endR, 0, true, true); - - String escapedName = SheetNameFormatter.format(sheetName); - - String c = ""; - String r = ""; - - if (startC != -1 || endC != -1) { - String col1 = colRef.getCellRefParts()[2]; - String col2 = colRef2.getCellRefParts()[2]; - c = escapedName + "!$" + col1 + ":$" + col2; - } - - if (startR != -1 || endR != -1) { - String row1 = rowRef.getCellRefParts()[1]; - String row2 = rowRef2.getCellRefParts()[1]; - if (!row1.equals("0") && !row2.equals("0")) { - r = escapedName + "!$" + row1 + ":$" + row2; - } - } - - StringBuilder rng = new StringBuilder(); - rng.append(c); - if(rng.length() > 0 && r.length() > 0) { - rng.append(','); - } - rng.append(r); - return rng.toString(); - } - - - private CellRangeAddress getRepeatingRowsOrColums(boolean rows) { - int sheetIndex = getWorkbook().getSheetIndex(this); - XSSFName name = getWorkbook().getBuiltInName( - XSSFName.BUILTIN_PRINT_TITLE, sheetIndex); - if (name == null ) { - return null; - } - String refStr = name.getRefersToFormula(); - if (refStr == null) { - return null; - } - String[] parts = refStr.split(","); - int maxRowIndex = SpreadsheetVersion.EXCEL2007.getLastRowIndex(); - int maxColIndex = SpreadsheetVersion.EXCEL2007.getLastColumnIndex(); - for (String part : parts) { - CellRangeAddress range = CellRangeAddress.valueOf(part); - if ((range.getFirstColumn() == 0 - && range.getLastColumn() == maxColIndex) - || (range.getFirstColumn() == -1 - && range.getLastColumn() == -1)) { - if (rows) { - return range; - } - } else if (range.getFirstRow() == 0 - && range.getLastRow() == maxRowIndex - || (range.getFirstRow() == -1 - && range.getLastRow() == -1)) { - if (!rows) { - return range; - } - } - } - return null; - } - - /** - * Creates an empty XSSFPivotTable and sets up all its relationships - * including: pivotCacheDefinition, pivotCacheRecords - * @return returns a pivotTable - */ - @Beta - private XSSFPivotTable createPivotTable() { - XSSFWorkbook wb = getWorkbook(); - List<XSSFPivotTable> pivotTables = wb.getPivotTables(); - int tableId = getWorkbook().getPivotTables().size()+1; - //Create relationship between pivotTable and the worksheet - XSSFPivotTable pivotTable = (XSSFPivotTable) createRelationship(XSSFRelation.PIVOT_TABLE, - XSSFFactory.getInstance(), tableId); - pivotTable.setParentSheet(this); - pivotTables.add(pivotTable); - XSSFWorkbook workbook = getWorkbook(); - - //Create relationship between the pivot cache defintion and the workbook - XSSFPivotCacheDefinition pivotCacheDefinition = (XSSFPivotCacheDefinition) workbook. - createRelationship(XSSFRelation.PIVOT_CACHE_DEFINITION, XSSFFactory.getInstance(), tableId); - String rId = workbook.getRelationId(pivotCacheDefinition); - //Create relationship between pivotTable and pivotCacheDefinition without creating a new instance - PackagePart pivotPackagePart = pivotTable.getPackagePart(); - pivotPackagePart.addRelationship(pivotCacheDefinition.getPackagePart().getPartName(), - TargetMode.INTERNAL, XSSFRelation.PIVOT_CACHE_DEFINITION.getRelation()); - - pivotTable.setPivotCacheDefinition(pivotCacheDefinition); - - //Create pivotCache and sets up it's relationship with the workbook - pivotTable.setPivotCache(new XSSFPivotCache(workbook.addPivotCache(rId))); - - //Create relationship between pivotcacherecord and pivotcachedefinition - XSSFPivotCacheRecords pivotCacheRecords = (XSSFPivotCacheRecords) pivotCacheDefinition. - createRelationship(XSSFRelation.PIVOT_CACHE_RECORDS, XSSFFactory.getInstance(), tableId); - - //Set relationships id for pivotCacheDefinition to pivotCacheRecords - pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().setId(pivotCacheDefinition.getRelationId(pivotCacheRecords)); - - wb.setPivotTables(pivotTables); - - return pivotTable; - } - - /** - * Create a pivot table using the AreaReference range on sourceSheet, at the given position. - * If the source reference contains a sheet name, it must match the sourceSheet - * @param source location of pivot data - * @param position A reference to the top left cell where the pivot table will start - * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name - * @throws IllegalArgumentException if source references a sheet different than sourceSheet - * @return The pivot table - */ - @Beta - public XSSFPivotTable createPivotTable(final AreaReference source, CellReference position, Sheet sourceSheet) { - final String sourceSheetName = source.getFirstCell().getSheetName(); - if(sourceSheetName != null && !sourceSheetName.equalsIgnoreCase(sourceSheet.getSheetName())) { - throw new IllegalArgumentException("The area is referenced in another sheet than the " - + "defined source sheet " + sourceSheet.getSheetName() + "."); - } - - return createPivotTable(position, sourceSheet, wsSource -> { - final String[] firstCell = source.getFirstCell().getCellRefParts(); - final String firstRow = firstCell[1]; - final String firstCol = firstCell[2]; - final String[] lastCell = source.getLastCell().getCellRefParts(); - final String lastRow = lastCell[1]; - final String lastCol = lastCell[2]; - final String ref = firstCol+firstRow+':'+lastCol+lastRow; //or just source.formatAsString() - wsSource.setRef(ref); - }); - } - - /** - * Create a pivot table using the AreaReference or named/table range on sourceSheet, at the given position. - * If the source reference contains a sheet name, it must match the sourceSheet. - * @param position A reference to the top left cell where the pivot table will start - * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name - * @param refConfig A reference to the pivot table configurator - * @throws IllegalArgumentException if source references a sheet different than sourceSheet - * @return The pivot table - */ - private XSSFPivotTable createPivotTable(CellReference position, Sheet sourceSheet, PivotTableReferenceConfigurator refConfig) { - - XSSFPivotTable pivotTable = createPivotTable(); - //Creates default settings for the pivot table - pivotTable.setDefaultPivotTableDefinition(); - - //Set sources and references - pivotTable.createSourceReferences(position, sourceSheet, refConfig); - - //Create cachefield/s and empty SharedItems - must be after creating references - pivotTable.getPivotCacheDefinition().createCacheFields(sourceSheet); - pivotTable.createDefaultDataColumns(); - - return pivotTable; - } - - /** - * Create a pivot table using the AreaReference range, at the given position. - * If the source reference contains a sheet name, that sheet is used, otherwise this sheet is assumed as the source sheet. - * @param source location of pivot data - * @param position A reference to the top left cell where the pivot table will start - * @return The pivot table - */ - @Beta - public XSSFPivotTable createPivotTable(AreaReference source, CellReference position){ - final String sourceSheetName = source.getFirstCell().getSheetName(); - if(sourceSheetName != null && !sourceSheetName.equalsIgnoreCase(this.getSheetName())) { - final XSSFSheet sourceSheet = getWorkbook().getSheet(sourceSheetName); - return createPivotTable(source, position, sourceSheet); - } - return createPivotTable(source, position, this); - } - - /** - * Create a pivot table using the Name range reference on sourceSheet, at the given position. - * If the source reference contains a sheet name, it must match the sourceSheet - * @param source location of pivot data - * @param position A reference to the top left cell where the pivot table will start - * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name - * @throws IllegalArgumentException if source references a sheet different than sourceSheet - * @return The pivot table - */ - @Beta - public XSSFPivotTable createPivotTable(final Name source, CellReference position, Sheet sourceSheet) { - if(source.getSheetName() != null && !source.getSheetName().equals(sourceSheet.getSheetName())) { - throw new IllegalArgumentException("The named range references another sheet than the " - + "defined source sheet " + sourceSheet.getSheetName() + "."); - } - - return createPivotTable(position, sourceSheet, wsSource -> wsSource.setName(source.getNameName())); - } - - /** - * Create a pivot table using the Name range, at the given position. - * If the source reference contains a sheet name, that sheet is used, otherwise this sheet is assumed as the source sheet. - * @param source location of pivot data - * @param position A reference to the top left cell where the pivot table will start - * @return The pivot table - */ - @Beta - public XSSFPivotTable createPivotTable(Name source, CellReference position) { - return createPivotTable(source, position, getWorkbook().getSheet(source.getSheetName())); - } - - /** - * Create a pivot table using the Table, at the given position. - * Tables are required to have a sheet reference, so no additional logic around reference sheet is needed. - * @param source location of pivot data - * @param position A reference to the top left cell where the pivot table will start - * @return The pivot table - */ - @Beta - public XSSFPivotTable createPivotTable(final Table source, CellReference position) { - return createPivotTable(position, getWorkbook().getSheet(source.getSheetName()), wsSource -> wsSource.setName(source.getName())); - } - - /** - * Returns all the pivot tables for this Sheet - */ - @Beta - public List<XSSFPivotTable> getPivotTables() { - List<XSSFPivotTable> tables = new ArrayList<>(); - for (XSSFPivotTable table : getWorkbook().getPivotTables()) { - if (table.getParent() == this) { - tables.add(table); - } - } - return tables; - } - - @Override - public int getColumnOutlineLevel(int columnIndex) { - CTCol col = columnHelper.getColumn(columnIndex, false); - if (col == null) { - return 0; - } - return col.getOutlineLevel(); - } - - /** - * Add ignored errors (usually to suppress them in the UI of a consuming - * application). - * - * @param cell Cell. - * @param ignoredErrorTypes Types of error to ignore there. - */ - public void addIgnoredErrors(CellReference cell, IgnoredErrorType... ignoredErrorTypes) { - addIgnoredErrors(cell.formatAsString(false), ignoredErrorTypes); - } - - /** - * Ignore errors across a range of cells. - * - * @param region Range of cells. - * @param ignoredErrorTypes Types of error to ignore there. - */ - public void addIgnoredErrors(CellRangeAddress region, IgnoredErrorType... ignoredErrorTypes) { - region.validate(SpreadsheetVersion.EXCEL2007); - addIgnoredErrors(region.formatAsString(), ignoredErrorTypes); - } - - /** - * Returns the errors currently being ignored and the ranges - * where they are ignored. - * - * @return Map of error type to the range(s) where they are ignored. - */ - public Map<IgnoredErrorType, Set<CellRangeAddress>> getIgnoredErrors() { - Map<IgnoredErrorType, Set<CellRangeAddress>> result = new LinkedHashMap<>(); - if (worksheet.isSetIgnoredErrors()) { - for (CTIgnoredError err : worksheet.getIgnoredErrors().getIgnoredErrorList()) { - for (IgnoredErrorType errType : XSSFIgnoredErrorHelper.getErrorTypes(err)) { - if (!result.containsKey(errType)) { - result.put(errType, new LinkedHashSet<>()); - } - for (Object ref : err.getSqref()) { - result.get(errType).add(CellRangeAddress.valueOf(ref.toString())); - } - } - } - } - return result; - } - - private void addIgnoredErrors(String ref, IgnoredErrorType... ignoredErrorTypes) { - CTIgnoredErrors ctIgnoredErrors = worksheet.isSetIgnoredErrors() ? worksheet.getIgnoredErrors() : worksheet.addNewIgnoredErrors(); - CTIgnoredError ctIgnoredError = ctIgnoredErrors.addNewIgnoredError(); - XSSFIgnoredErrorHelper.addIgnoredErrors(ctIgnoredError, ref, ignoredErrorTypes); - } - - /** - * called when a sheet is being deleted/removed from a workbook, to clean up relations and other document pieces tied to the sheet - */ - protected void onSheetDelete() { - for (RelationPart part : getRelationParts()) { - if (part.getDocumentPart() instanceof XSSFTable) { - // call table delete - removeTable(part.getDocumentPart()); - continue; - } - removeRelation(part.getDocumentPart(), true); - } - } - - /** - * when a cell with a 'master' shared formula is removed, the next cell in the range becomes the master - * @param cell The cell that is removed - * @param evalWb BaseXSSFEvaluationWorkbook in use, if one exists - */ - protected void onDeleteFormula(XSSFCell cell, BaseXSSFEvaluationWorkbook evalWb){ - - CTCellFormula f = cell.getCTCell().getF(); - if (f != null && f.getT() == STCellFormulaType.SHARED && f.isSetRef() && f.getStringValue() != null) { - - CellRangeAddress ref = CellRangeAddress.valueOf(f.getRef()); - if(ref.getNumberOfCells() > 1){ - DONE: - for(int i = cell.getRowIndex(); i <= ref.getLastRow(); i++){ - XSSFRow row = getRow(i); - if(row != null) for(int j = cell.getColumnIndex(); j <= ref.getLastColumn(); j++){ - XSSFCell nextCell = row.getCell(j); - if(nextCell != null && nextCell != cell && nextCell.getCellType() == CellType.FORMULA){ - CTCellFormula nextF = nextCell.getCTCell().getF(); - nextF.setStringValue(nextCell.getCellFormula(evalWb)); - CellRangeAddress nextRef = new CellRangeAddress( - nextCell.getRowIndex(), ref.getLastRow(), - nextCell.getColumnIndex(), ref.getLastColumn()); - nextF.setRef(nextRef.formatAsString()); - - sharedFormulas.put(Math.toIntExact(nextF.getSi()), nextF); - break DONE; - } - } - } - } - - } - } - - /** - * Determine the OleObject which links shapes with embedded resources - * - * @param shapeId the shape id - * @return the CTOleObject of the shape - */ - protected CTOleObject readOleObject(long shapeId) { - if (!getCTWorksheet().isSetOleObjects()) { - return null; - } - - // we use a XmlCursor here to handle oleObject with-/out AlternateContent wrappers - String xquery = "declare namespace p='"+XSSFRelation.NS_SPREADSHEETML+"' .//p:oleObject"; - XmlCursor cur = getCTWorksheet().getOleObjects().newCursor(); - try { - cur.selectPath(xquery); - CTOleObject coo = null; - while (cur.toNextSelection()) { - String sId = cur.getAttributeText(new QName(null, "shapeId")); - if (sId == null || Long.parseLong(sId) != shapeId) { - continue; - } - - XmlObject xObj = cur.getObject(); - if (xObj instanceof CTOleObject) { - // the unusual case ... - coo = (CTOleObject)xObj; - } else { - XMLStreamReader reader = cur.newXMLStreamReader(); - try { - CTOleObjects coos = CTOleObjects.Factory.parse(reader); - if (coos.sizeOfOleObjectArray() == 0) { - continue; - } - coo = coos.getOleObjectArray(0); - } catch (XmlException e) { - LOG.atInfo().withThrowable(e).log("can't parse CTOleObjects"); - } finally { - try { - reader.close(); - } catch (XMLStreamException e) { - LOG.atInfo().withThrowable(e).log("can't close reader"); - } - } - } - - // there are choice and fallback OleObject ... we prefer the one having the objectPr element, - // which is in the choice element - if (cur.toChild(XSSFRelation.NS_SPREADSHEETML, "objectPr")) { - break; - } - } - return coo; - } finally { - cur.dispose(); - } - } - - public XSSFHeaderFooterProperties getHeaderFooterProperties() { - return new XSSFHeaderFooterProperties(getSheetTypeHeaderFooter()); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheetConditionalFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheetConditionalFormatting.java deleted file mode 100644 index 9967a2cf79..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheetConditionalFormatting.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * ==================================================================== - * 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 java.util.ArrayList; -import java.util.List; - -import org.apache.poi.ss.SpreadsheetVersion; -import org.apache.poi.ss.usermodel.ComparisonOperator; -import org.apache.poi.ss.usermodel.ConditionalFormatting; -import org.apache.poi.ss.usermodel.ConditionalFormattingRule; -import org.apache.poi.ss.usermodel.ExtendedColor; -import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; -import org.apache.poi.ss.usermodel.SheetConditionalFormatting; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellRangeUtil; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTConditionalFormatting; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STConditionalFormattingOperator; - -/** - * XSSF Conditional Formattings - */ -public class XSSFSheetConditionalFormatting implements SheetConditionalFormatting { - /** Office 2010 Conditional Formatting extensions namespace */ - protected static final String CF_EXT_2009_NS_X14 = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"; - - private final XSSFSheet _sheet; - - /* package */ XSSFSheetConditionalFormatting(XSSFSheet sheet) { - _sheet = sheet; - } - - /** - * A factory method allowing to create a conditional formatting rule - * with a cell comparison operator<p> - * TODO - formulas containing cell references are currently not parsed properly - * - * @param comparisonOperation - a constant value from - * <tt>{@link org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator}</tt>: <p> - * <ul> - * <li>BETWEEN</li> - * <li>NOT_BETWEEN</li> - * <li>EQUAL</li> - * <li>NOT_EQUAL</li> - * <li>GT</li> - * <li>LT</li> - * <li>GE</li> - * <li>LE</li> - * </ul> - * </p> - * @param formula1 - formula for the valued, compared with the cell - * @param formula2 - second formula (only used with - * {@link org.apache.poi.ss.usermodel.ComparisonOperator#BETWEEN}) and - * {@link org.apache.poi.ss.usermodel.ComparisonOperator#NOT_BETWEEN} operations) - */ - public XSSFConditionalFormattingRule createConditionalFormattingRule( - byte comparisonOperation, - String formula1, - String formula2) { - - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - CTCfRule cfRule = rule.getCTCfRule(); - cfRule.addFormula(formula1); - if(formula2 != null) cfRule.addFormula(formula2); - cfRule.setType(STCfType.CELL_IS); - STConditionalFormattingOperator.Enum operator; - switch (comparisonOperation){ - case ComparisonOperator.BETWEEN: operator = STConditionalFormattingOperator.BETWEEN; break; - case ComparisonOperator.NOT_BETWEEN: operator = STConditionalFormattingOperator.NOT_BETWEEN; break; - case ComparisonOperator.LT: operator = STConditionalFormattingOperator.LESS_THAN; break; - case ComparisonOperator.LE: operator = STConditionalFormattingOperator.LESS_THAN_OR_EQUAL; break; - case ComparisonOperator.GT: operator = STConditionalFormattingOperator.GREATER_THAN; break; - case ComparisonOperator.GE: operator = STConditionalFormattingOperator.GREATER_THAN_OR_EQUAL; break; - case ComparisonOperator.EQUAL: operator = STConditionalFormattingOperator.EQUAL; break; - case ComparisonOperator.NOT_EQUAL: operator = STConditionalFormattingOperator.NOT_EQUAL; break; - default: throw new IllegalArgumentException("Unknown comparison operator: " + comparisonOperation); - } - cfRule.setOperator(operator); - - return rule; - } - - public XSSFConditionalFormattingRule createConditionalFormattingRule( - byte comparisonOperation, - String formula) { - - return createConditionalFormattingRule(comparisonOperation, formula, null); - } - - /** - * A factory method allowing to create a conditional formatting rule with a formula.<br> - * - * @param formula - formula for the valued, compared with the cell - */ - public XSSFConditionalFormattingRule createConditionalFormattingRule(String formula) { - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - CTCfRule cfRule = rule.getCTCfRule(); - cfRule.addFormula(formula); - cfRule.setType(STCfType.EXPRESSION); - return rule; - } - - /** - * Create a Databar conditional formatting rule. - * <p>The thresholds and colour for it will be created, but will be - * empty and require configuring with - * {@link XSSFConditionalFormattingRule#getDataBarFormatting()} - * then - * {@link XSSFDataBarFormatting#getMinThreshold()} - * and - * {@link XSSFDataBarFormatting#getMaxThreshold()} - */ - public XSSFConditionalFormattingRule createConditionalFormattingRule(XSSFColor color) { - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - - // Have it setup, with suitable defaults - rule.createDataBarFormatting(color); - - // All done! - return rule; - } - public XSSFConditionalFormattingRule createConditionalFormattingRule(ExtendedColor color) { - return createConditionalFormattingRule((XSSFColor)color); - } - - /** - * A factory method allowing the creation of conditional formatting - * rules using an Icon Set / Multi-State formatting. - * The thresholds for it will be created, but will be empty - * and require configuring with - * {@link XSSFConditionalFormattingRule#getMultiStateFormatting()} - * then - * {@link XSSFIconMultiStateFormatting#getThresholds()} - */ - public XSSFConditionalFormattingRule createConditionalFormattingRule(IconSet iconSet) { - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - - // Have it setup, with suitable defaults - rule.createMultiStateFormatting(iconSet); - - // All done! - return rule; - } - - /** - * Create a Color Scale / Color Gradient conditional formatting rule. - * <p>The thresholds and colours for it will be created, but will be - * empty and require configuring with - * {@link XSSFConditionalFormattingRule#getColorScaleFormatting()} - * then - * {@link XSSFColorScaleFormatting#getThresholds()} - * and - * {@link XSSFColorScaleFormatting#getColors()} - */ - public XSSFConditionalFormattingRule createConditionalFormattingColorScaleRule() { - XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); - - // Have it setup, with suitable defaults - rule.createColorScaleFormatting(); - - // All done! - return rule; - } - - public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) { - if (regions == null) { - throw new IllegalArgumentException("regions must not be null"); - } - for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL2007); - - if (cfRules == null) { - throw new IllegalArgumentException("cfRules must not be null"); - } - if (cfRules.length == 0) { - throw new IllegalArgumentException("cfRules must not be empty"); - } - - CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(regions); - CTConditionalFormatting cf = _sheet.getCTWorksheet().addNewConditionalFormatting(); - List<String> refs = new ArrayList<>(); - for(CellRangeAddress a : mergeCellRanges) refs.add(a.formatAsString()); - cf.setSqref(refs); - - int priority = 1; - for(CTConditionalFormatting c : _sheet.getCTWorksheet().getConditionalFormattingArray()){ - priority += c.sizeOfCfRuleArray(); - } - - for(ConditionalFormattingRule rule : cfRules){ - XSSFConditionalFormattingRule xRule = (XSSFConditionalFormattingRule)rule; - xRule.getCTCfRule().setPriority(priority++); - cf.addNewCfRule().set(xRule.getCTCfRule()); - } - return _sheet.getCTWorksheet().sizeOfConditionalFormattingArray() - 1; - } - - public int addConditionalFormatting(CellRangeAddress[] regions, - ConditionalFormattingRule rule1) - { - return addConditionalFormatting(regions, - rule1 == null ? null : new XSSFConditionalFormattingRule[] { - (XSSFConditionalFormattingRule)rule1 - }); - } - - public int addConditionalFormatting(CellRangeAddress[] regions, - ConditionalFormattingRule rule1, ConditionalFormattingRule rule2) - { - return addConditionalFormatting(regions, - rule1 == null ? null : new XSSFConditionalFormattingRule[] { - (XSSFConditionalFormattingRule)rule1, - (XSSFConditionalFormattingRule)rule2 - }); - } - - /** - * Adds a copy of HSSFConditionalFormatting object to the sheet - * <p>This method could be used to copy HSSFConditionalFormatting object - * from one sheet to another. For example: - * <pre> - * HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index); - * newSheet.addConditionalFormatting(cf); - * </pre> - * - * @param cf HSSFConditionalFormatting object - * @return index of the new Conditional Formatting object - */ - public int addConditionalFormatting( ConditionalFormatting cf ) { - XSSFConditionalFormatting xcf = (XSSFConditionalFormatting)cf; - CTWorksheet sh = _sheet.getCTWorksheet(); - sh.addNewConditionalFormatting().set(xcf.getCTConditionalFormatting().copy()); - return sh.sizeOfConditionalFormattingArray() - 1; - } - - /** - * gets Conditional Formatting object at a particular index - * - * @param index - * of the Conditional Formatting object to fetch - * @return Conditional Formatting object - */ - public XSSFConditionalFormatting getConditionalFormattingAt(int index) { - checkIndex(index); - CTConditionalFormatting cf = _sheet.getCTWorksheet().getConditionalFormattingArray(index); - return new XSSFConditionalFormatting(_sheet, cf); - } - - /** - * @return number of Conditional Formatting objects of the sheet - */ - public int getNumConditionalFormattings() { - return _sheet.getCTWorksheet().sizeOfConditionalFormattingArray(); - } - - /** - * removes a Conditional Formatting object by index - * @param index of a Conditional Formatting object to remove - */ - public void removeConditionalFormatting(int index) { - checkIndex(index); - _sheet.getCTWorksheet().removeConditionalFormatting(index); - } - - private void checkIndex(int index) { - int cnt = getNumConditionalFormattings(); - if (index < 0 || index >= cnt) { - throw new IllegalArgumentException("Specified CF index " + index - + " is outside the allowable range (0.." + (cnt - 1) + ")"); - } - } - -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSignatureLine.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSignatureLine.java deleted file mode 100644 index 478bca9626..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSignatureLine.java +++ /dev/null @@ -1,133 +0,0 @@ -/* ==================================================================== - 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 java.io.IOException; -import java.io.OutputStream; - -import javax.xml.namespace.QName; - -import com.microsoft.schemas.office.excel.CTClientData; -import com.microsoft.schemas.office.excel.STObjectType; -import com.microsoft.schemas.office.office.CTSignatureLine; -import com.microsoft.schemas.vml.CTImageData; -import com.microsoft.schemas.vml.CTShape; -import org.apache.poi.common.usermodel.PictureType; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.ooxml.POIXMLRelation; -import org.apache.poi.ooxml.util.XPathHelper; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.poifs.crypt.dsig.SignatureLine; -import org.apache.poi.schemas.vmldrawing.CTXML; -import org.apache.xmlbeans.XmlException; -import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STTrueFalseBlank; - -public class XSSFSignatureLine extends SignatureLine { - private static final String MS_VML_URN = "urn:schemas-microsoft-com:vml"; - - public void parse(XSSFSheet sheet) throws XmlException { - XSSFVMLDrawing vml = sheet.getVMLDrawing(false); - if (vml == null) { - return; - } - CTSignatureLine line = XPathHelper.selectProperty(vml.getDocument(), CTSignatureLine.class, null, - new QName[]{XSSFVMLDrawing.QNAME_VMLDRAWING}, - new QName[]{new QName(MS_VML_URN, "shape")}, - new QName[]{QNAME_SIGNATURE_LINE}); - - if (line != null) { - setSignatureShape(line); - parse(); - } - } - - public void add(XSSFSheet sheet, XSSFClientAnchor anchor) { - XSSFVMLDrawing vml = sheet.getVMLDrawing(true); - CTXML root = vml.getDocument().getXml(); - add(root, (image, type) -> addPicture(image,type,sheet)); - CTShape shape = getSignatureShape(); - CTClientData clientData = shape.addNewClientData(); - // LeftColumn, LeftOffset, TopRow, TopOffset, RightColumn, RightOffset, BottomRow, BottomOffset - String anchorStr = - anchor.getCol1()+", "+ - anchor.getDx1()+", "+ - anchor.getRow1()+", "+ - anchor.getDy1()+", "+ - anchor.getCol2()+", "+ - anchor.getDx2()+", "+ - anchor.getRow2()+", "+ - anchor.getDy2(); -// anchorStr = "2, 0, 3, 0, 5, 136, 9, 32"; - clientData.addAnchor(anchorStr); - clientData.setObjectType(STObjectType.PICT); - clientData.addSizeWithCells(STTrueFalseBlank.X); - clientData.addCF("pict"); - clientData.addAutoPict(STTrueFalseBlank.X); - } - - @Override - protected void setRelationId(CTImageData imageData, String relId) { - imageData.setRelid(relId); - } - - private String addPicture(byte[] image, PictureType type, XSSFSheet sheet) throws InvalidFormatException { - XSSFWorkbook wb = sheet.getWorkbook(); - XSSFVMLDrawing vml = sheet.getVMLDrawing(false); - POIXMLRelation xtype = mapType(type); - int idx = wb.getNextPartNumber(xtype, -1); - POIXMLDocumentPart.RelationPart rp = vml.createRelationship(xtype, XSSFFactory.getInstance(), idx, false); - POIXMLDocumentPart dp = rp.getDocumentPart(); - try (OutputStream out = dp.getPackagePart().getOutputStream()) { - out.write(image); - } catch (IOException e) { - throw new POIXMLException(e); - } - return rp.getRelationship().getId(); - } - - - private static POIXMLRelation mapType(PictureType type) throws InvalidFormatException { - switch (type) { - case BMP: - return XSSFRelation.IMAGE_BMP; - case DIB: - return XSSFRelation.IMAGE_DIB; - case EMF: - return XSSFRelation.IMAGE_EMF; - case EPS: - return XSSFRelation.IMAGE_EPS; - case GIF: - return XSSFRelation.IMAGE_GIF; - case JPEG: - return XSSFRelation.IMAGE_JPEG; - case PICT: - return XSSFRelation.IMAGE_PICT; - case PNG: - return XSSFRelation.IMAGE_PNG; - case TIFF: - return XSSFRelation.IMAGE_TIFF; - case WMF: - return XSSFRelation.IMAGE_WMF; - case WPG: - return XSSFRelation.IMAGE_WPG; - default: - throw new InvalidFormatException("Unsupported picture format "+type); - } - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java deleted file mode 100644 index dfc7a69466..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java +++ /dev/null @@ -1,1021 +0,0 @@ -/* ==================================================================== - 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 java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Optional; -import java.util.function.Function; -import java.util.function.Predicate; - -import org.apache.poi.hssf.util.HSSFColor; -import org.apache.poi.ss.usermodel.SimpleShape; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.apache.poi.util.Beta; -import org.apache.poi.util.Internal; -import org.apache.poi.xddf.usermodel.XDDFColor; -import org.apache.poi.xddf.usermodel.XDDFColorRgbBinary; -import org.apache.poi.xddf.usermodel.XDDFFillProperties; -import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties; -import org.apache.poi.xddf.usermodel.text.TextContainer; -import org.apache.poi.xddf.usermodel.text.XDDFRunProperties; -import org.apache.poi.xddf.usermodel.text.XDDFTextBody; -import org.apache.poi.xddf.usermodel.text.XDDFTextParagraph; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextHorzOverflowType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextVertOverflowType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRElt; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRPrElt; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnderlineValues; - -/** - * Represents a shape with a predefined geometry in a SpreadsheetML drawing. - * Possible shape types are defined in - * {@link org.apache.poi.ss.usermodel.ShapeTypes} - */ -public class XSSFSimpleShape extends XSSFShape implements Iterable<XSSFTextParagraph>, SimpleShape, TextContainer { - /** - * The text body containing the paragraphs for this shape. - */ - private final XDDFTextBody _textBody; - /** - * List of the paragraphs that make up the text in this shape - */ - private final List<XSSFTextParagraph> _paragraphs; - /** - * A default instance of CTShape used for creating new shapes. - */ - private static CTShape prototype; - - /** - * Xml bean that stores properties of this shape - */ - private CTShape ctShape; - - protected XSSFSimpleShape(XSSFDrawing drawing, CTShape ctShape) { - this.drawing = drawing; - this.ctShape = ctShape; - - _paragraphs = new ArrayList<>(); - - // initialize any existing paragraphs - this will be the default body - // paragraph in a new shape, - // or existing paragraphs that have been loaded from the file - CTTextBody body = ctShape.getTxBody(); - if (body == null) { - _textBody = null; - } else { - _textBody = new XDDFTextBody(this, body); - for (int i = 0; i < body.sizeOfPArray(); i++) { - _paragraphs.add(new XSSFTextParagraph(body.getPArray(i), ctShape)); - } - } - } - - /** - * Prototype with the default structure of a new auto-shape. - */ - protected static CTShape prototype() { - if (prototype == null) { - CTShape shape = CTShape.Factory.newInstance(); - - CTShapeNonVisual nv = shape.addNewNvSpPr(); - CTNonVisualDrawingProps nvp = nv.addNewCNvPr(); - nvp.setId(1); - nvp.setName("Shape 1"); - nv.addNewCNvSpPr(); - - CTShapeProperties sp = shape.addNewSpPr(); - CTTransform2D t2d = sp.addNewXfrm(); - CTPositiveSize2D p1 = t2d.addNewExt(); - p1.setCx(0); - p1.setCy(0); - CTPoint2D p2 = t2d.addNewOff(); - p2.setX(0); - p2.setY(0); - - CTPresetGeometry2D geom = sp.addNewPrstGeom(); - geom.setPrst(STShapeType.RECT); - geom.addNewAvLst(); - - XDDFTextBody body = new XDDFTextBody(null, shape.addNewTxBody()); - XDDFTextParagraph p = body.initialize(); - XDDFRunProperties rp = p.getAfterLastRunProperties(); - XDDFColor black = new XDDFColorRgbBinary(new byte[] { 0, 0, 0 }); - XDDFFillProperties fp = new XDDFSolidFillProperties(black); - rp.setFillProperties(fp); - - prototype = shape; - } - return prototype; - } - - @Internal - public CTShape getCTShape() { - return ctShape; - } - - @Beta - public XDDFTextBody getTextBody() { - return _textBody; - } - - protected void setXfrm(CTTransform2D t2d) { - ctShape.getSpPr().setXfrm(t2d); - } - - @Override - public Iterator<XSSFTextParagraph> iterator() { - return _paragraphs.iterator(); - } - - /** - * Returns the text from all paragraphs in the shape. Paragraphs are - * separated by new lines. - * - * @return text contained within this shape or empty string - */ - public String getText() { - final int MAX_LEVELS = 9; - StringBuilder out = new StringBuilder(); - List<Integer> levelCount = new ArrayList<>(MAX_LEVELS); // maximum 9 - // levels - // initialise the levelCount array - this maintains a record of the - // numbering to be used at each level - for (int k = 0; k < MAX_LEVELS; k++) { - levelCount.add(0); - } - - for (int i = 0; i < _paragraphs.size(); i++) { - if (out.length() > 0) { - out.append('\n'); - } - XSSFTextParagraph p = _paragraphs.get(i); - - if (p.isBullet() && p.getText().length() > 0) { - - int level = Math.min(p.getLevel(), MAX_LEVELS - 1); - - if (p.isBulletAutoNumber()) { - i = processAutoNumGroup(i, level, levelCount, out); - } else { - // indent appropriately for the level - for (int j = 0; j < level; j++) { - out.append('\t'); - } - String character = p.getBulletCharacter(); - out.append(character.length() > 0 ? character + " " : "- "); - out.append(p.getText()); - } - } else { - out.append(p.getText()); - - // this paragraph is not a bullet, so reset the count array - for (int k = 0; k < MAX_LEVELS; k++) { - levelCount.set(k, 0); - } - } - } - - return out.toString(); - } - - /** - * - */ - private int processAutoNumGroup(int index, int level, List<Integer> levelCount, StringBuilder out) { - XSSFTextParagraph p = _paragraphs.get(index); - - // The rules for generating the auto numbers are as follows. If the - // following paragraph is also - // an auto-number, has the same type/scheme (and startAt if defined on - // this paragraph) then they are - // considered part of the same group. An empty bullet paragraph is - // counted as part of the same - // group but does not increment the count for the group. A change of - // type, startAt or the paragraph - // not being a bullet resets the count for that level to 1. - - // first auto-number paragraph so initialise to 1 or the bullets startAt - // if present - int startAt = p.getBulletAutoNumberStart(); - ListAutoNumber scheme = p.getBulletAutoNumberScheme(); - if (levelCount.get(level) == 0) { - levelCount.set(level, startAt == 0 ? 1 : startAt); - } - // indent appropriately for the level - for (int j = 0; j < level; j++) { - out.append('\t'); - } - if (p.getText().length() > 0) { - out.append(getBulletPrefix(scheme, levelCount.get(level))); - out.append(p.getText()); - } - while (true) { - XSSFTextParagraph nextp = (index + 1) == _paragraphs.size() ? null : _paragraphs.get(index + 1); - if (nextp == null) { - break; // out of paragraphs - } - if (!(nextp.isBullet() && p.isBulletAutoNumber())) { - break; // not an auto-number bullet - } - if (nextp.getLevel() > level) { - // recurse into the new level group - if (out.length() > 0) { - out.append('\n'); - } - index = processAutoNumGroup(index + 1, nextp.getLevel(), levelCount, out); - continue; // restart the loop given the new index - } else if (nextp.getLevel() < level) { - break; // changed level - } - ListAutoNumber nextScheme = nextp.getBulletAutoNumberScheme(); - int nextStartAt = nextp.getBulletAutoNumberStart(); - - if (nextScheme == scheme && nextStartAt == startAt) { - // bullet is valid, so increment i - ++index; - if (out.length() > 0) { - out.append('\n'); - } - // indent for the level - for (int j = 0; j < level; j++) { - out.append('\t'); - } - // check for empty text - only output a bullet if there is text, - // but it is still part of the group - if (nextp.getText().length() > 0) { - // increment the count for this level - levelCount.set(level, levelCount.get(level) + 1); - out.append(getBulletPrefix(nextScheme, levelCount.get(level))); - out.append(nextp.getText()); - } - } else { - // something doesn't match so stop - break; - } - } - // end of the group so reset the count for this level - levelCount.set(level, 0); - - return index; - } - - /** - * Returns a string containing an appropriate prefix for an auto-numbering - * bullet - * - * @param scheme - * the auto-numbering scheme used by the bullet - * @param value - * the value of the bullet - * @return appropriate prefix for an auto-numbering bullet - */ - private String getBulletPrefix(ListAutoNumber scheme, int value) { - StringBuilder out = new StringBuilder(); - - switch (scheme) { - case ALPHA_LC_PARENT_BOTH: - case ALPHA_LC_PARENT_R: - if (scheme == ListAutoNumber.ALPHA_LC_PARENT_BOTH) { - out.append('('); - } - out.append(valueToAlpha(value).toLowerCase(Locale.ROOT)); - out.append(')'); - break; - case ALPHA_UC_PARENT_BOTH: - case ALPHA_UC_PARENT_R: - if (scheme == ListAutoNumber.ALPHA_UC_PARENT_BOTH) { - out.append('('); - } - out.append(valueToAlpha(value)); - out.append(')'); - break; - case ALPHA_LC_PERIOD: - out.append(valueToAlpha(value).toLowerCase(Locale.ROOT)); - out.append('.'); - break; - case ALPHA_UC_PERIOD: - out.append(valueToAlpha(value)); - out.append('.'); - break; - case ARABIC_PARENT_BOTH: - case ARABIC_PARENT_R: - if (scheme == ListAutoNumber.ARABIC_PARENT_BOTH) { - out.append('('); - } - out.append(value); - out.append(')'); - break; - case ARABIC_PERIOD: - out.append(value); - out.append('.'); - break; - case ARABIC_PLAIN: - out.append(value); - break; - case ROMAN_LC_PARENT_BOTH: - case ROMAN_LC_PARENT_R: - if (scheme == ListAutoNumber.ROMAN_LC_PARENT_BOTH) { - out.append('('); - } - out.append(valueToRoman(value).toLowerCase(Locale.ROOT)); - out.append(')'); - break; - case ROMAN_UC_PARENT_BOTH: - case ROMAN_UC_PARENT_R: - if (scheme == ListAutoNumber.ROMAN_UC_PARENT_BOTH) { - out.append('('); - } - out.append(valueToRoman(value)); - out.append(')'); - break; - case ROMAN_LC_PERIOD: - out.append(valueToRoman(value).toLowerCase(Locale.ROOT)); - out.append('.'); - break; - case ROMAN_UC_PERIOD: - out.append(valueToRoman(value)); - out.append('.'); - break; - default: - out.append('\u2022'); // can't set the font to wingdings so use the - // default bullet character - break; - } - out.append(" "); - return out.toString(); - } - - /** - * Convert an integer to its alpha equivalent e.g. 1 = A, 2 = B, 27 = AA etc - */ - private String valueToAlpha(int value) { - String alpha = ""; - int modulo; - while (value > 0) { - modulo = (value - 1) % 26; - alpha = (char) (65 + modulo) + alpha; - value = (value - modulo) / 26; - } - return alpha; - } - - private static String[] _romanChars = new String[] { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", - "IV", "I" }; - private static int[] _romanAlphaValues = new int[] { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }; - - /** - * Convert an integer to its roman equivalent e.g. 1 = I, 9 = IX etc - */ - private String valueToRoman(int value) { - StringBuilder out = new StringBuilder(); - for (int i = 0; value > 0 && i < _romanChars.length; i++) { - while (_romanAlphaValues[i] <= value) { - out.append(_romanChars[i]); - value -= _romanAlphaValues[i]; - } - } - return out.toString(); - } - - /** - * Clear all text from this shape - */ - public void clearText() { - _paragraphs.clear(); - CTTextBody txBody = ctShape.getTxBody(); - txBody.setPArray(null); // remove any existing paragraphs - } - - /** - * Set a single paragraph of text on the shape. Note this will replace all - * existing paragraphs created on the shape. - * - * @param text - * string representing the paragraph text - */ - public void setText(String text) { - clearText(); - - addNewTextParagraph().addNewTextRun().setText(text); - } - - /** - * Set a single paragraph of text on the shape. Note this will replace all - * existing paragraphs created on the shape. - * - * @param str - * rich text string representing the paragraph text - */ - public void setText(XSSFRichTextString str) { - - XSSFWorkbook wb = (XSSFWorkbook) getDrawing().getParent().getParent(); - str.setStylesTableReference(wb.getStylesSource()); - - CTTextParagraph p = CTTextParagraph.Factory.newInstance(); - if (str.numFormattingRuns() == 0) { - CTRegularTextRun r = p.addNewR(); - CTTextCharacterProperties rPr = r.addNewRPr(); - rPr.setLang("en-US"); - rPr.setSz(1100); - r.setT(str.getString()); - - } else { - for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) { - CTRElt lt = str.getCTRst().getRArray(i); - CTRPrElt ltPr = lt.getRPr(); - if (ltPr == null) { - ltPr = lt.addNewRPr(); - } - - CTRegularTextRun r = p.addNewR(); - CTTextCharacterProperties rPr = r.addNewRPr(); - rPr.setLang("en-US"); - - applyAttributes(ltPr, rPr); - - r.setT(lt.getT()); - } - } - - clearText(); - ctShape.getTxBody().setPArray(new CTTextParagraph[] { p }); - _paragraphs.add(new XSSFTextParagraph(ctShape.getTxBody().getPArray(0), ctShape)); - } - - /** - * Returns a collection of the XSSFTextParagraphs that are attached to this - * shape - * - * @return text paragraphs in this shape - */ - public List<XSSFTextParagraph> getTextParagraphs() { - return _paragraphs; - } - - /** - * Add a new paragraph run to this shape - * - * @return created paragraph run - */ - public XSSFTextParagraph addNewTextParagraph() { - CTTextBody txBody = ctShape.getTxBody(); - CTTextParagraph p = txBody.addNewP(); - XSSFTextParagraph paragraph = new XSSFTextParagraph(p, ctShape); - _paragraphs.add(paragraph); - return paragraph; - } - - /** - * Add a new paragraph run to this shape, set to the provided string - * - * @return created paragraph run - */ - public XSSFTextParagraph addNewTextParagraph(String text) { - XSSFTextParagraph paragraph = addNewTextParagraph(); - paragraph.addNewTextRun().setText(text); - return paragraph; - } - - /** - * Add a new paragraph run to this shape, set to the provided rich text - * string - * - * @return created paragraph run - */ - public XSSFTextParagraph addNewTextParagraph(XSSFRichTextString str) { - CTTextBody txBody = ctShape.getTxBody(); - CTTextParagraph p = txBody.addNewP(); - - if (str.numFormattingRuns() == 0) { - CTRegularTextRun r = p.addNewR(); - CTTextCharacterProperties rPr = r.addNewRPr(); - rPr.setLang("en-US"); - rPr.setSz(1100); - r.setT(str.getString()); - - } else { - for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) { - CTRElt lt = str.getCTRst().getRArray(i); - CTRPrElt ltPr = lt.getRPr(); - if (ltPr == null) { - ltPr = lt.addNewRPr(); - } - - CTRegularTextRun r = p.addNewR(); - CTTextCharacterProperties rPr = r.addNewRPr(); - rPr.setLang("en-US"); - - applyAttributes(ltPr, rPr); - - r.setT(lt.getT()); - } - } - - // Note: the XSSFTextParagraph constructor will create its required - // XSSFTextRuns from the provided CTTextParagraph - XSSFTextParagraph paragraph = new XSSFTextParagraph(p, ctShape); - _paragraphs.add(paragraph); - - return paragraph; - } - - /** - * Sets the type of horizontal overflow for the text. - * - * @param overflow - * - the type of horizontal overflow. A <code>null</code> values - * unsets this property. - */ - public void setTextHorizontalOverflow(TextHorizontalOverflow overflow) { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (overflow == null) { - if (bodyPr.isSetHorzOverflow()) { - bodyPr.unsetHorzOverflow(); - } - } else { - bodyPr.setHorzOverflow(STTextHorzOverflowType.Enum.forInt(overflow.ordinal() + 1)); - } - } - } - - /** - * Returns the type of horizontal overflow for the text. - * - * @return the type of horizontal overflow - */ - public TextHorizontalOverflow getTextHorizontalOverflow() { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (bodyPr.isSetHorzOverflow()) { - return TextHorizontalOverflow.values()[bodyPr.getHorzOverflow().intValue() - 1]; - } - } - return TextHorizontalOverflow.OVERFLOW; - } - - /** - * Sets the type of vertical overflow for the text. - * - * @param overflow - * - the type of vertical overflow. A <code>null</code> values - * unsets this property. - */ - public void setTextVerticalOverflow(TextVerticalOverflow overflow) { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (overflow == null) { - if (bodyPr.isSetVertOverflow()) { - bodyPr.unsetVertOverflow(); - } - } else { - bodyPr.setVertOverflow(STTextVertOverflowType.Enum.forInt(overflow.ordinal() + 1)); - } - } - } - - /** - * Returns the type of vertical overflow for the text. - * - * @return the type of vertical overflow - */ - public TextVerticalOverflow getTextVerticalOverflow() { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (bodyPr.isSetVertOverflow()) { - return TextVerticalOverflow.values()[bodyPr.getVertOverflow().intValue() - 1]; - } - } - return TextVerticalOverflow.OVERFLOW; - } - - /** - * Sets the type of vertical alignment for the text within the shape. - * - * @param anchor - * - the type of alignment. A <code>null</code> values unsets - * this property. - */ - public void setVerticalAlignment(VerticalAlignment anchor) { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (anchor == null) { - if (bodyPr.isSetAnchor()) { - bodyPr.unsetAnchor(); - } - } else { - bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1)); - } - } - } - - /** - * Returns the type of vertical alignment for the text within the shape. - * - * @return the type of vertical alignment - */ - public VerticalAlignment getVerticalAlignment() { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (bodyPr.isSetAnchor()) { - return VerticalAlignment.values()[bodyPr.getAnchor().intValue() - 1]; - } - } - return VerticalAlignment.TOP; - } - - /** - * Sets the vertical orientation of the text - * - * @param orientation - * vertical orientation of the text A <code>null</code> values - * unsets this property. - */ - public void setTextDirection(TextDirection orientation) { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (orientation == null) { - if (bodyPr.isSetVert()) { - bodyPr.unsetVert(); - } - } else { - bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1)); - } - } - } - - /** - * Gets the vertical orientation of the text - * - * @return vertical orientation of the text - */ - public TextDirection getTextDirection() { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - STTextVerticalType.Enum val = bodyPr.getVert(); - if (val != null) { - return TextDirection.values()[val.intValue() - 1]; - } - } - return TextDirection.HORIZONTAL; - } - - /** - * Returns the distance (in points) between the bottom of the text frame and - * the bottom of the inscribed rectangle of the shape that contains the - * text. - * - * @return the bottom inset in points - */ - public double getBottomInset() { - Double inset = _textBody.getBodyProperties().getBottomInset(); - if (inset == null) { - // If this attribute is omitted, then a value of 0.05 inches is - // implied - return 3.6; - } else { - return inset; - } - } - - /** - * Returns the distance (in points) between the left edge of the text frame - * and the left edge of the inscribed rectangle of the shape that contains - * the text. - * - * @return the left inset in points - */ - public double getLeftInset() { - Double inset = _textBody.getBodyProperties().getLeftInset(); - if (inset == null) { - // If this attribute is omitted, then a value of 0.05 inches is - // implied - return 3.6; - } else { - return inset; - } - } - - /** - * Returns the distance (in points) between the right edge of the text frame - * and the right edge of the inscribed rectangle of the shape that contains - * the text. - * - * @return the right inset in points - */ - public double getRightInset() { - Double inset = _textBody.getBodyProperties().getRightInset(); - if (inset == null) { - // If this attribute is omitted, then a value of 0.05 inches is - // implied - return 3.6; - } else { - return inset; - } - } - - /** - * Returns the distance (in points) between the top of the text frame and - * the top of the inscribed rectangle of the shape that contains the text. - * - * @return the top inset in points - */ - public double getTopInset() { - Double inset = _textBody.getBodyProperties().getTopInset(); - if (inset == null) { - // If this attribute is omitted, then a value of 0.05 inches is - // implied - return 3.6; - } else { - return inset; - } - } - - /** - * Sets the bottom inset. - * - * @see #getBottomInset() - * - * @param margin - * the bottom margin - */ - public void setBottomInset(double margin) { - if (margin == -1) { - _textBody.getBodyProperties().setBottomInset(null); - } else { - _textBody.getBodyProperties().setBottomInset(margin); - } - } - - /** - * Sets the left inset. - * - * @see #getLeftInset() - * - * @param margin - * the left margin - */ - public void setLeftInset(double margin) { - if (margin == -1) { - _textBody.getBodyProperties().setLeftInset(null); - } else { - _textBody.getBodyProperties().setLeftInset(margin); - } - } - - /** - * Sets the right inset. - * - * @see #getRightInset() - * - * @param margin - * the right margin - */ - public void setRightInset(double margin) { - if (margin == -1) { - _textBody.getBodyProperties().setRightInset(null); - } else { - _textBody.getBodyProperties().setRightInset(margin); - } - } - - /** - * Sets the top inset. - * - * @see #getTopInset() - * - * @param margin - * the top margin - */ - public void setTopInset(double margin) { - if (margin == -1) { - _textBody.getBodyProperties().setTopInset(null); - } else { - _textBody.getBodyProperties().setTopInset(margin); - } - } - - /** - * @return whether to wrap words within the bounding rectangle - */ - public boolean getWordWrap() { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (bodyPr.isSetWrap()) { - return bodyPr.getWrap() == STTextWrappingType.SQUARE; - } - } - return true; - } - - /** - * - * @param wrap - * whether to wrap words within the bounding rectangle - */ - public void setWordWrap(boolean wrap) { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - bodyPr.setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE); - } - } - - /** - * - * Specifies that a shape should be auto-fit to fully contain the text - * described within it. Auto-fitting is when text within a shape is scaled - * in order to contain all the text inside - * - * @param value - * type of autofit - */ - public void setTextAutofit(TextAutofit value) { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (bodyPr.isSetSpAutoFit()) { - bodyPr.unsetSpAutoFit(); - } - if (bodyPr.isSetNoAutofit()) { - bodyPr.unsetNoAutofit(); - } - if (bodyPr.isSetNormAutofit()) { - bodyPr.unsetNormAutofit(); - } - - switch (value) { - case NONE: - bodyPr.addNewNoAutofit(); - break; - case NORMAL: - bodyPr.addNewNormAutofit(); - break; - case SHAPE: - bodyPr.addNewSpAutoFit(); - break; - } - } - } - - /** - * - * @return type of autofit - */ - public TextAutofit getTextAutofit() { - CTTextBodyProperties bodyPr = ctShape.getTxBody().getBodyPr(); - if (bodyPr != null) { - if (bodyPr.isSetNoAutofit()) { - return TextAutofit.NONE; - } else if (bodyPr.isSetNormAutofit()) { - return TextAutofit.NORMAL; - } else if (bodyPr.isSetSpAutoFit()) { - return TextAutofit.SHAPE; - } - } - return TextAutofit.NORMAL; - } - - /** - * Gets the shape type, one of the constants defined in - * {@link org.apache.poi.ss.usermodel.ShapeTypes}. - * - * @return the shape type - * @see org.apache.poi.ss.usermodel.ShapeTypes - */ - public int getShapeType() { - return ctShape.getSpPr().getPrstGeom().getPrst().intValue(); - } - - /** - * Sets the shape types. - * - * @param type - * the shape type, one of the constants defined in - * {@link org.apache.poi.ss.usermodel.ShapeTypes}. - * @see org.apache.poi.ss.usermodel.ShapeTypes - */ - public void setShapeType(int type) { - ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type)); - } - - @Override - protected CTShapeProperties getShapeProperties() { - return ctShape.getSpPr(); - } - - /** - * org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRPrElt to - * org.openxmlformats.schemas.drawingml.x2006.main.CTFont adapter - */ - private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr) { - - if (pr.sizeOfBArray() > 0) { - rPr.setB(pr.getBArray(0).getVal()); - } - if (pr.sizeOfUArray() > 0) { - STUnderlineValues.Enum u1 = pr.getUArray(0).getVal(); - if (u1 == STUnderlineValues.SINGLE) { - rPr.setU(STTextUnderlineType.SNG); - } else if (u1 == STUnderlineValues.DOUBLE) { - rPr.setU(STTextUnderlineType.DBL); - } else if (u1 == STUnderlineValues.NONE) { - rPr.setU(STTextUnderlineType.NONE); - } - } - if (pr.sizeOfIArray() > 0) { - rPr.setI(pr.getIArray(0).getVal()); - } - - if (pr.sizeOfRFontArray() > 0) { - CTTextFont rFont = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin(); - rFont.setTypeface(pr.getRFontArray(0).getVal()); - } - - if (pr.sizeOfSzArray() > 0) { - int sz = (int) (pr.getSzArray(0).getVal() * 100); - rPr.setSz(sz); - } - - if (pr.sizeOfColorArray() > 0) { - CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill(); - org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor xlsColor = pr.getColorArray(0); - if (xlsColor.isSetRgb()) { - CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr(); - clr.setVal(xlsColor.getRgb()); - } else if (xlsColor.isSetIndexed()) { - HSSFColor indexed = HSSFColor.getIndexHash().get((int) xlsColor.getIndexed()); - if (indexed != null) { - byte[] rgb = new byte[3]; - rgb[0] = (byte) indexed.getTriplet()[0]; - rgb[1] = (byte) indexed.getTriplet()[1]; - rgb[2] = (byte) indexed.getTriplet()[2]; - CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr(); - clr.setVal(rgb); - } - } - } - } - - @Override - public String getShapeName() { - return ctShape.getNvSpPr().getCNvPr().getName(); - } - - @Override - public int getShapeId() { - return (int) ctShape.getNvSpPr().getCNvPr().getId(); - } - - @Override - public <R> Optional<R> findDefinedParagraphProperty(Predicate<CTTextParagraphProperties> isSet, - Function<CTTextParagraphProperties, R> getter) { - // TODO Auto-generated method stub - return Optional.empty(); - } - - @Override - public <R> Optional<R> findDefinedRunProperty(Predicate<CTTextCharacterProperties> isSet, - Function<CTTextCharacterProperties, R> getter) { - // TODO Auto-generated method stub - return Optional.empty(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java deleted file mode 100644 index 62f6158deb..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java +++ /dev/null @@ -1,957 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - -import java.io.IOException; -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; - -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.ss.SpreadsheetVersion; -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; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.TableDocument; - -/** - * - * This class implements the Table Part (Open Office XML Part 4: chapter 3.5.1) - * - * 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> xmlColumnPrs; - private transient List<XSSFTableColumn> tableColumns; - private transient HashMap<String, Integer> columnMap; - private transient CellReference startCellReference; - private transient CellReference endCellReference; - private transient String commonXPath; - private transient String name; - private transient String styleName; - - /** - * empty implementation, not attached to a workbook/worksheet yet - */ - public XSSFTable() { - super(); - ctTable = CTTable.Factory.newInstance(); - } - - /** - * @param part The part used to initialize the table - * @throws IOException If reading data from the part fails. - * @since POI 3.14-Beta1 - */ - public XSSFTable(PackagePart part) throws IOException { - super(part); - readFrom(part.getInputStream()); - } - - /** - * Read table XML from an {@link InputStream} - * @param is The stream which provides the XML data for the table. - * @throws IOException If reading from the stream fails - */ - public void readFrom(InputStream is) throws IOException { - try { - TableDocument doc = TableDocument.Factory.parse(is, DEFAULT_XML_OPTIONS); - ctTable = doc.getTable(); - } catch (XmlException e) { - throw new IOException(e.getLocalizedMessage()); - } - } - - /** - * @return owning sheet - */ - public XSSFSheet getXSSFSheet(){ - return (XSSFSheet) getParent(); - } - - /** - * write table XML to an {@link OutputStream} - * @param out The stream to write the XML data to - * @throws IOException If writing to the stream fails. - */ - public void writeTo(OutputStream out) throws IOException { - updateHeaders(); - - TableDocument doc = TableDocument.Factory.newInstance(); - doc.setTable(ctTable); - doc.save(out, DEFAULT_XML_OPTIONS); - } - - @Override - protected void commit() throws IOException { - PackagePart part = getPackagePart(); - OutputStream out = part.getOutputStream(); - writeTo(out); - out.close(); - } - - /** - * get the underlying CTTable XML bean - * @return underlying OOXML object - */ - @Internal(since="POI 3.15 beta 3") - public CTTable getCTTable() { - return ctTable; - } - - /** - * Checks if this Table element contains even a single mapping to the map identified by id - * @param id the XSSFMap ID - * @return true if the Table element contain mappings - */ - public boolean mapsTo(long id){ - List<XSSFXmlColumnPr> pointers = getXmlColumnPrs(); - - for (XSSFXmlColumnPr pointer: pointers) { - if (pointer.getMapId()==id) { - return true; - } - } - - return false; - } - - /** - * - * Calculates the xpath of the root element for the table. This will be the common part - * of all the mapping's xpaths - * Note: this function caches the result for performance. To flush the cache {@link #updateHeaders()} must be called. - * - * @return the xpath of the table's root element - */ - public String getCommonXpath() { - if (commonXPath == null) { - String[] commonTokens = {}; - for (XSSFTableColumn column : getColumns()) { - if (column.getXmlColumnPr()!=null) { - String xpath = column.getXmlColumnPr().getXPath(); - String[] tokens = xpath.split("/"); - if (commonTokens.length==0) { - commonTokens = tokens; - - } else { - final int maxLength = Math.min(commonTokens.length, tokens.length); - - for (int i =0; i<maxLength; i++) { - if (!commonTokens[i].equals(tokens[i])) { - List<String> subCommonTokens = Arrays.asList(commonTokens).subList(0, i); - - String[] container = {}; - - commonTokens = subCommonTokens.toArray(container); - break; - } - } - } - } - } - - commonTokens[0] = ""; - commonXPath = StringUtil.join(commonTokens, "/"); - } - - 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; - } - - /** - * Use {@link XSSFTableColumn#getXmlColumnPr()} instead. - */ - private List<XSSFXmlColumnPr> getXmlColumnPrs() { - if (xmlColumnPrs == null) { - xmlColumnPrs = new ArrayList<>(); - for (XSSFTableColumn column: getColumns()) { - XSSFXmlColumnPr xmlColumnPr = column.getXmlColumnPr(); - if (xmlColumnPr != null) { - xmlColumnPrs.add(xmlColumnPr); - } - } - } - return xmlColumnPrs; - } - - /** - * Add a new column to the right end of the table. - * - * @param columnName - * the unique name of the column, must not be {@code null} - * @return the created table column - * @since 4.0.0 - */ - 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(); - } - - // check if name is unique and calculate unique column id - long nextColumnId = 0; - 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()); - } - // Bug #62740, the logic was just re-using the existing max ID, not incrementing beyond it. - nextColumnId++; - - // 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"); - } - - CTTableColumns tableColumns = ctTable.getTableColumns(); - tableColumns.removeTableColumn(columnIndex); - tableColumns.setCount(tableColumns.getTableColumnList().size()); - updateReferences(); - updateHeaders(); - } - - /** - * @return the name of the Table, if set - */ - public String getName() { - if (name == null && ctTable.getName() != null) { - setName(ctTable.getName()); - } - return name; - } - - /** - * Changes the name of the Table - * @param newName The name of the table. - */ - public void setName(String newName) { - if (newName == null) { - ctTable.unsetName(); - name = null; - return; - } - ctTable.setName(newName); - name = newName; - } - - /** - * @return the table style name, if set - * @since 3.17 beta 1 - */ - public String getStyleName() { - if (styleName == null && ctTable.isSetTableStyleInfo()) { - setStyleName(ctTable.getTableStyleInfo().getName()); - } - return styleName; - } - - /** - * Changes the name of the Table - * @param newStyleName The name of the style. - * @since 3.17 beta 1 - */ - public void setStyleName(String newStyleName) { - if (newStyleName == null) { - if (ctTable.isSetTableStyleInfo()) { - ctTable.getTableStyleInfo().unsetName(); - } - styleName = null; - return; - } - if (! ctTable.isSetTableStyleInfo()) { - ctTable.addNewTableStyleInfo(); - } - ctTable.getTableStyleInfo().setName(newStyleName); - styleName = newStyleName; - } - - /** - * @return the display name of the Table, if set - */ - public String getDisplayName() { - return ctTable.getDisplayName(); - } - - /** - * Changes the display name of the Table - * @param name to use - */ - public void setDisplayName(String name) { - if (name == null || name.isEmpty()) { - throw new IllegalArgumentException("Display name must not be null or empty"); - } - ctTable.setDisplayName(name); - } - - /** - * 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()}. - * - * @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() { - return new AreaReference( - getStartCellReference(), - getEndCellReference(), - SpreadsheetVersion.EXCEL2007 - ); - } - - /** - * 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. - * - * @see "Open Office XML Part 4: chapter 3.5.1.2, attribute ref" - * @since 3.17 beta 1 - */ - public void setCellReferences(AreaReference refs) { - 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); - } - - // Update - ctTable.setRef(ref); - if (ctTable.isSetAutoFilter()) { - String filterRef; - int totalsRowCount = getTotalsRowCount(); - if (totalsRowCount == 0) { - filterRef = ref; - } else { - final CellReference start = new CellReference(refs.getFirstCell().getRow(), refs.getFirstCell().getCol()); - // account for footer row(s) in auto-filter range, which doesn't include footers - final CellReference end = new CellReference(refs.getLastCell().getRow() - totalsRowCount, refs.getLastCell().getCol()); - // this won't have sheet references because we built the cell references without them - filterRef = new AreaReference(start, end, SpreadsheetVersion.EXCEL2007).formatAsString(); - } - ctTable.getAutoFilter().setRef(filterRef); - } - - // Have everything recomputed - updateReferences(); - 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 tableArea - * 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) - * - * Does not track updates to underlying changes to CTTable - * To synchronize with changes to the underlying CTTable, - * call {@link #updateReferences()}. - */ - public CellReference getStartCellReference() { - if (startCellReference==null) { - setCellReferences(); - } - return startCellReference; - } - - /** - * @return The reference for the cell in the bottom-right part of the table - * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref) - * - * Does not track updates to underlying changes to CTTable - * To synchronize with changes to the underlying CTTable, - * call {@link #updateReferences()}. - */ - public CellReference getEndCellReference() { - if (endCellReference==null) { - setCellReferences(); - } - return endCellReference; - } - - /** - * @since POI 3.15 beta 3 - */ - private void setCellReferences() { - String ref = ctTable.getRef(); - if (ref != null) { - String[] boundaries = ref.split(":", 2); - String from = boundaries[0]; - String to = boundaries.length == 2 ? boundaries[1] : boundaries[0]; - startCellReference = new CellReference(from); - endCellReference = new CellReference(to); - } - } - - - /** - * Clears the cached values set by {@link #getStartCellReference()} - * and {@link #getEndCellReference()}. - * The next call to {@link #getStartCellReference()} and - * {@link #getEndCellReference()} will synchronize the - * cell references with the underlying <code>CTTable</code>. - * Thus this method is inexpensive. - * - * @since POI 3.15 beta 3 - */ - public void updateReferences() { - startCellReference = null; - endCellReference = null; - } - - - /** - * 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()}. - * - * @return the total number of rows - */ - public int getRowCount() { - CellReference from = getStartCellReference(); - CellReference to = getEndCellReference(); - - int rowCount = 0; - if (from!=null && to!=null) { - rowCount = to.getRow() - from.getRow() + 1; - } - 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.setBlank(); - 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. - * Headers <em>must</em> be in sync, otherwise Excel will display a - * "Found unreadable content" message on startup. - * - * If calling both {@link #updateReferences()} and - * this method, {@link #updateReferences()} - * should be called first. - * - * Note that a Table <em>must</em> have a header. To reproduce - * the equivalent of inserting a table in Excel without Headers, - * manually add cells with values of "Column1", "Column2" etc first. - */ - public void updateHeaders() { - XSSFSheet sheet = (XSSFSheet)getParent(); - CellReference ref = getStartCellReference(); - if (ref == null) return; - - int headerRow = ref.getRow(); - int firstHeaderColumn = ref.getCol(); - XSSFRow row = sheet.getRow(headerRow); - DataFormatter formatter = new DataFormatter(); - - if (row != null && row.getCTRow().validate()) { - int cellnum = firstHeaderColumn; - 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++; - } - } - } - tableColumns = null; - columnMap = null; - xmlColumnPrs = null; - commonXPath = null; - } - - private static String caseInsensitive(String s) { - return s.toUpperCase(Locale.ROOT); - } - - /** - * Gets the relative column index of a column in this table having the header name <code>column</code>. - * The column index is relative to the left-most column in the table, 0-indexed. - * Returns <code>-1</code> if <code>column</code> is not a header name in table. - * - * Column Header names are case-insensitive - * - * Note: this function caches column names for performance. To flush the cache (because columns - * have been moved or column headers have been changed), {@link #updateHeaders()} must be called. - * - * @since 3.15 beta 2 - */ - public int findColumnIndex(String columnHeader) { - if (columnHeader == null) return -1; - if (columnMap == null) { - // FIXME: replace with org.apache.commons.collections.map.CaseInsensitiveMap - final int count = getColumnCount(); - columnMap = new HashMap<>(count * 3 / 2); - - int i = 0; - for (XSSFTableColumn column : getColumns()) { - String columnName = column.getName(); - columnMap.put(caseInsensitive(columnName), i); - i++; - } - } - // Table column names with special characters need a single quote escape - // but the escape is not present in the column definition - Integer idx = columnMap.get(caseInsensitive(columnHeader.replace("'", ""))); - return idx == null ? -1 : idx.intValue(); - } - - /** - * @since 3.15 beta 2 - */ - public String getSheetName() { - return getXSSFSheet().getSheetName(); - } - - /** - * Note: This is misleading. The Spec indicates this is true if the totals row - * has <b><i>ever</i></b> been shown, not whether or not it is currently displayed. - * Use {@link #getTotalsRowCount()} > 0 to decide whether or not the totals row is visible. - * @since 3.15 beta 2 - * @see #getTotalsRowCount() - */ - public boolean isHasTotalsRow() { - return ctTable.getTotalsRowShown(); - } - - /** - * @return 0 for no totals rows, 1 for totals row shown. - * Values > 1 are not currently used by Excel up through 2016, and the OOXML spec - * doesn't define how they would be implemented. - * @since 3.17 beta 1 - */ - public int getTotalsRowCount() { - return (int) ctTable.getTotalsRowCount(); - } - - /** - * @return 0 for no header rows, 1 for table headers shown. - * Values > 1 might be used by Excel for pivot tables? - * @since 3.17 beta 1 - */ - public int getHeaderRowCount() { - return (int) ctTable.getHeaderRowCount(); - } - - /** - * @since 3.15 beta 2 - */ - public int getStartColIndex() { - return getStartCellReference().getCol(); - } - - /** - * @since 3.15 beta 2 - */ - public int getStartRowIndex() { - return getStartCellReference().getRow(); - } - - /** - * @since 3.15 beta 2 - */ - public int getEndColIndex() { - return getEndCellReference().getCol(); - } - - /** - * @since 3.15 beta 2 - */ - public int getEndRowIndex() { - return getEndCellReference().getRow(); - } - - /** - * @since 3.17 beta 1 - */ - public TableStyleInfo getStyle() { - if (! ctTable.isSetTableStyleInfo()) return null; - return new XSSFTableStyleInfo(((XSSFSheet) getParent()).getWorkbook().getStylesSource(), ctTable.getTableStyleInfo()); - } - - /** - * @see org.apache.poi.ss.usermodel.Table#contains(org.apache.poi.ss.usermodel.Cell) - * @since 3.17 beta 1 - */ - public boolean contains(CellReference cell) { - if (cell == null) return false; - // check if cell is on the same sheet as the table - if ( ! getSheetName().equals(cell.getSheetName())) return false; - // check if the cell is inside the table - if (cell.getRow() >= getStartRowIndex() - && cell.getRow() <= getEndRowIndex() - && cell.getCol() >= getStartColIndex() - && cell.getCol() <= getEndColIndex()) { - return true; - } - return false; - } - - /** - * Remove relations - */ - protected void onTableDelete() { - for (RelationPart part : getRelationParts()) { - removeRelation(part.getDocumentPart(), true); - } - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java deleted file mode 100644 index 7d1f4661cd..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableColumn.java +++ /dev/null @@ -1,134 +0,0 @@ -/* ==================================================================== - 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. - * - * @param columnId 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. - * - * @param columnName 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()); - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableStyle.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableStyle.java deleted file mode 100644 index 852f91c62d..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableStyle.java +++ /dev/null @@ -1,121 +0,0 @@ -/* ==================================================================== - 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 java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.ss.usermodel.DifferentialStyleProvider; -import org.apache.poi.ss.usermodel.TableStyle; -import org.apache.poi.ss.usermodel.TableStyleType; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxf; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxfs; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyle; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyleElement; - -/** - * {@link TableStyle} implementation for styles defined in the OOXML styles.xml. - * Also used for built-in styles via dummy XML generated from presetTableStyles.xml. - */ -public class XSSFTableStyle implements TableStyle { - private static final Logger LOG = LogManager.getLogger(XSSFTableStyle.class); - - private final String name; - private final int index; - private final Map<TableStyleType, DifferentialStyleProvider> elementMap = new EnumMap<>(TableStyleType.class); - - /** - * @param index style definition index or built-in ordinal depending on use - * @param dxfs - * @param tableStyle - * @param colorMap indexed color map - default or custom - * @see TableStyle#getIndex() - */ - public XSSFTableStyle(int index, CTDxfs dxfs, CTTableStyle tableStyle, IndexedColorMap colorMap) { - this.name = tableStyle.getName(); - this.index = index; - - List<CTDxf> dxfList = new ArrayList<>(); - - // CT* classes don't handle "mc:AlternateContent" elements, so get the Dxf instances manually - XmlCursor cur = dxfs.newCursor(); - // sometimes there are namespaces sometimes not. - String xquery = "declare namespace x='"+XSSFRelation.NS_SPREADSHEETML+"' .//x:dxf | .//dxf"; - cur.selectPath(xquery); - while (cur.toNextSelection()) { - XmlObject obj = cur.getObject(); - String parentName = obj.getDomNode().getParentNode().getNodeName(); - // ignore alternate content choices, we won't know anything about their namespaces - if (parentName.equals("mc:Fallback") || parentName.equals("x:dxfs") || parentName.contentEquals("dxfs")) { - CTDxf dxf; - try { - if (obj instanceof CTDxf) { - dxf = (CTDxf) obj; - } else { - dxf = CTDxf.Factory.parse(obj.newXMLStreamReader(), new XmlOptions().setDocumentType(CTDxf.type)); - } - if (dxf != null) dxfList.add(dxf); - } catch (XmlException e) { - LOG.atWarn().withThrowable(e).log("Error parsing XSSFTableStyle"); - } - } - } - - for (CTTableStyleElement element : tableStyle.getTableStyleElementList()) { - TableStyleType type = TableStyleType.valueOf(element.getType().toString()); - DifferentialStyleProvider dstyle = null; - if (element.isSetDxfId()) { - int idx = (int) element.getDxfId(); - CTDxf dxf; - dxf = dxfList.get(idx); - int stripeSize = 0; - if (element.isSetSize()) stripeSize = (int) element.getSize(); - if (dxf != null) dstyle = new XSSFDxfStyleProvider(dxf, stripeSize, colorMap); - } - elementMap.put(type, dstyle); - } - } - - public String getName() { - return name; - } - - public int getIndex() { - return index; - } - - /** - * Always false for these, these are user defined styles - */ - public boolean isBuiltin() { - return false; - } - - public DifferentialStyleProvider getStyle(TableStyleType type) { - return elementMap.get(type); - } - -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableStyleInfo.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableStyleInfo.java deleted file mode 100644 index fc515e6edb..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTableStyleInfo.java +++ /dev/null @@ -1,94 +0,0 @@ -/* ==================================================================== - 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.ss.usermodel.TableStyle; -import org.apache.poi.ss.usermodel.TableStyleInfo; -import org.apache.poi.xssf.model.StylesTable; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyleInfo; - -/** - * Wrapper for the CT class, to cache values and add style lookup - */ -public class XSSFTableStyleInfo implements TableStyleInfo { - private final CTTableStyleInfo styleInfo; - private final StylesTable stylesTable; - private TableStyle style; - private boolean columnStripes; - private boolean rowStripes; - private boolean firstColumn; - private boolean lastColumn; - - /** - * @param stylesTable - * @param tableStyleInfo - */ - public XSSFTableStyleInfo(StylesTable stylesTable, CTTableStyleInfo tableStyleInfo) { - this.columnStripes = tableStyleInfo.getShowColumnStripes(); - this.rowStripes = tableStyleInfo.getShowRowStripes(); - this.firstColumn = tableStyleInfo.getShowFirstColumn(); - this.lastColumn = tableStyleInfo.getShowLastColumn(); - this.style = stylesTable.getTableStyle(tableStyleInfo.getName()); - this.stylesTable = stylesTable; - this.styleInfo = tableStyleInfo; - } - - public boolean isShowColumnStripes() { - return columnStripes; - } - public void setShowColumnStripes(boolean show) { - this.columnStripes = show; - styleInfo.setShowColumnStripes(show); - } - - public boolean isShowRowStripes() { - return rowStripes; - } - public void setShowRowStripes(boolean show) { - this.rowStripes = show; - styleInfo.setShowRowStripes(show); - } - - public boolean isShowFirstColumn() { - return firstColumn; - } - public void setFirstColumn(boolean showFirstColumn) { - this.firstColumn = showFirstColumn; - styleInfo.setShowFirstColumn(showFirstColumn); - } - - public boolean isShowLastColumn() { - return lastColumn; - } - public void setLastColumn(boolean showLastColumn) { - this.lastColumn = showLastColumn; - styleInfo.setShowLastColumn(showLastColumn); - } - - public String getName() { - return style.getName(); - } - public void setName(String name) { - styleInfo.setName(name); - style = stylesTable.getTableStyle(name); - } - - public TableStyle getStyle() { - return style; - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java deleted file mode 100644 index 74c26b9306..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java +++ /dev/null @@ -1,32 +0,0 @@ -/* ==================================================================== - 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.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; - -/** - * Represents a text box in a SpreadsheetML drawing. - * - * @author Yegor Kozlov - */ -public final class XSSFTextBox extends XSSFSimpleShape { - - protected XSSFTextBox(XSSFDrawing drawing, CTShape ctShape) { - super(drawing, ctShape); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java deleted file mode 100644 index 0d33e0c4f6..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java +++ /dev/null @@ -1,870 +0,0 @@ -/* ==================================================================== - 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 java.awt.Color; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.ooxml.util.POIXMLUnits; -import org.apache.poi.util.Internal; -import org.apache.poi.util.Units; -import org.apache.poi.xssf.model.ParagraphPropertyFetcher; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.*; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; - -/** - * Represents a paragraph of text within the containing text body. - * The paragraph is the highest level text separation mechanism. - */ -public class XSSFTextParagraph implements Iterable<XSSFTextRun>{ - private final CTTextParagraph _p; - private final CTShape _shape; - private final List<XSSFTextRun> _runs; - - XSSFTextParagraph(CTTextParagraph p, CTShape ctShape){ - _p = p; - _shape = ctShape; - _runs = new ArrayList<>(); - - for(XmlObject ch : _p.selectPath("*")){ - if(ch instanceof CTRegularTextRun){ - CTRegularTextRun r = (CTRegularTextRun)ch; - _runs.add(new XSSFTextRun(r, this)); - } else if (ch instanceof CTTextLineBreak){ - CTTextLineBreak br = (CTTextLineBreak)ch; - CTRegularTextRun r = CTRegularTextRun.Factory.newInstance(); - r.setRPr(br.getRPr()); - r.setT("\n"); - _runs.add(new XSSFTextRun(r, this)); - } else if (ch instanceof CTTextField){ - CTTextField f = (CTTextField)ch; - CTRegularTextRun r = CTRegularTextRun.Factory.newInstance(); - r.setRPr(f.getRPr()); - r.setT(f.getT()); - _runs.add(new XSSFTextRun(r, this)); - } - } - } - - public String getText(){ - StringBuilder out = new StringBuilder(); - for (XSSFTextRun r : _runs) { - out.append(r.getText()); - } - return out.toString(); - } - - @Internal - public CTTextParagraph getXmlObject(){ - return _p; - } - - @Internal - public CTShape getParentShape(){ - return _shape; - } - - public List<XSSFTextRun> getTextRuns(){ - return _runs; - } - - public Iterator<XSSFTextRun> iterator(){ - return _runs.iterator(); - } - - /** - * Add a new run of text - * - * @return a new run of text - */ - public XSSFTextRun addNewTextRun(){ - CTRegularTextRun r = _p.addNewR(); - CTTextCharacterProperties rPr = r.addNewRPr(); - rPr.setLang("en-US"); - XSSFTextRun run = new XSSFTextRun(r, this); - _runs.add(run); - return run; - } - - /** - * Insert a line break - * - * @return text run representing this line break ('\n') - */ - public XSSFTextRun addLineBreak(){ - CTTextLineBreak br = _p.addNewBr(); - CTTextCharacterProperties brProps = br.addNewRPr(); - if(_runs.size() > 0){ - // by default line break has the font size of the last text run - CTTextCharacterProperties prevRun = _runs.get(_runs.size() - 1).getRPr(); - brProps.set(prevRun); - } - CTRegularTextRun r = CTRegularTextRun.Factory.newInstance(); - r.setRPr(brProps); - r.setT("\n"); - XSSFTextRun run = new XSSFLineBreak(r, this, brProps); - _runs.add(run); - return run; - } - - /** - * Returns the alignment that is applied to the paragraph. - * - * If this attribute is omitted, then a value of left is implied. - * @return alignment that is applied to the paragraph - */ - public TextAlign getTextAlign(){ - ParagraphPropertyFetcher<TextAlign> fetcher = new ParagraphPropertyFetcher<TextAlign>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetAlgn()){ - TextAlign val = TextAlign.values()[props.getAlgn().intValue() - 1]; - setValue(val); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? TextAlign.LEFT : fetcher.getValue(); - } - - /** - * Specifies the alignment that is to be applied to the paragraph. - * Possible values for this include left, right, centered, justified and distributed, - * see {@link org.apache.poi.xssf.usermodel.TextAlign}. - * - * @param align text align - */ - public void setTextAlign(TextAlign align){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(align == null) { - if(pr.isSetAlgn()) pr.unsetAlgn(); - } else { - pr.setAlgn(STTextAlignType.Enum.forInt(align.ordinal() + 1)); - } - } - - /** - * Returns where vertically on a line of text the actual words are positioned. This deals - * with vertical placement of the characters with respect to the baselines. - * - * If this attribute is omitted, then a value of baseline is implied. - * @return alignment that is applied to the paragraph - */ - public TextFontAlign getTextFontAlign(){ - ParagraphPropertyFetcher<TextFontAlign> fetcher = new ParagraphPropertyFetcher<TextFontAlign>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetFontAlgn()){ - TextFontAlign val = TextFontAlign.values()[props.getFontAlgn().intValue() - 1]; - setValue(val); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? TextFontAlign.BASELINE : fetcher.getValue(); - } - - /** - * Determines where vertically on a line of text the actual words are positioned. This deals - * with vertical placement of the characters with respect to the baselines. For instance - * having text anchored to the top baseline, anchored to the bottom baseline, centered in - * between, etc. - * - * @param align text font align - */ - public void setTextFontAlign(TextFontAlign align){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(align == null) { - if(pr.isSetFontAlgn()) pr.unsetFontAlgn(); - } else { - pr.setFontAlgn(STTextFontAlignType.Enum.forInt(align.ordinal() + 1)); - } - } - - /** - * @return the font to be used on bullet characters within a given paragraph - */ - public String getBulletFont(){ - ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuFont()){ - setValue(props.getBuFont().getTypeface()); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); - } - - public void setBulletFont(String typeface){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextFont font = pr.isSetBuFont() ? pr.getBuFont() : pr.addNewBuFont(); - font.setTypeface(typeface); - } - - /** - * @return the character to be used in place of the standard bullet point - */ - public String getBulletCharacter(){ - ParagraphPropertyFetcher<String> fetcher = new ParagraphPropertyFetcher<String>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuChar()){ - setValue(props.getBuChar().getChar()); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); - } - - public void setBulletCharacter(String str){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextCharBullet c = pr.isSetBuChar() ? pr.getBuChar() : pr.addNewBuChar(); - c.setChar(str); - } - - /** - * - * @return the color of bullet characters within a given paragraph. - * A <code>null</code> value means to use the text font color. - */ - public Color getBulletFontColor(){ - ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuClr()){ - if(props.getBuClr().isSetSrgbClr()){ - CTSRgbColor clr = props.getBuClr().getSrgbClr(); - byte[] rgb = clr.getVal(); - setValue(new Color(0xFF & rgb[0], 0xFF & rgb[1], 0xFF & rgb[2])); - return true; - } - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue(); - } - - /** - * Set the color to be used on bullet characters within a given paragraph. - * - * @param color the bullet color - */ - public void setBulletFontColor(Color color){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTColor c = pr.isSetBuClr() ? pr.getBuClr() : pr.addNewBuClr(); - CTSRgbColor clr = c.isSetSrgbClr() ? c.getSrgbClr() : c.addNewSrgbClr(); - clr.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()}); - } - - /** - * Returns the bullet size that is to be used within a paragraph. - * This may be specified in two different ways, percentage spacing and font point spacing: - * <p> - * If bulletSize >= 0, then bulletSize is a percentage of the font size. - * If bulletSize < 0, then it specifies the size in points - * </p> - * - * @return the bullet size - */ - public double getBulletFontSize(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuSzPct()){ - setValue(POIXMLUnits.parsePercent(props.getBuSzPct().xgetVal()) * 0.001); - return true; - } - if(props.isSetBuSzPts()){ - setValue( - props.getBuSzPts().getVal() * 0.01); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 100 : fetcher.getValue(); - } - - /** - * Sets the bullet size that is to be used within a paragraph. - * This may be specified in two different ways, percentage spacing and font point spacing: - * <p> - * If bulletSize >= 0, then bulletSize is a percentage of the font size. - * If bulletSize < 0, then it specifies the size in points - * </p> - */ - public void setBulletFontSize(double bulletSize){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - - if(bulletSize >= 0) { - // percentage - CTTextBulletSizePercent pt = pr.isSetBuSzPct() ? pr.getBuSzPct() : pr.addNewBuSzPct(); - pt.setVal(Integer.toString((int)(bulletSize*1000))); - // unset points if percentage is now set - if(pr.isSetBuSzPts()) pr.unsetBuSzPts(); - } else { - // points - CTTextBulletSizePoint pt = pr.isSetBuSzPts() ? pr.getBuSzPts() : pr.addNewBuSzPts(); - pt.setVal((int)(-bulletSize*100)); - // unset percentage if points is now set - if(pr.isSetBuSzPct()) pr.unsetBuSzPct(); - } - } - - /** - * Specifies the indent size that will be applied to the first line of text in the paragraph. - * - * @param value the indent in points, -1 to unset indent and use the default of 0. - */ - public void setIndent(double value){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(value == -1) { - if(pr.isSetIndent()) pr.unsetIndent(); - } else { - pr.setIndent(Units.toEMU(value)); - } - } - - /** - * - * @return the indent applied to the first line of text in the paragraph. - */ - public double getIndent(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetIndent()){ - setValue(Units.toPoints(props.getIndent())); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - - return fetcher.getValue() == null ? 0 : fetcher.getValue(); - } - - - - /** - * Specifies the left margin of the paragraph. This is specified in addition to the text body - * inset and applies only to this text paragraph. That is the text body inset and the LeftMargin - * attributes are additive with respect to the text position. - * - * @param value the left margin of the paragraph, -1 to clear the margin and use the default of 0. - */ - public void setLeftMargin(double value){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(value == -1) { - if(pr.isSetMarL()) pr.unsetMarL(); - } else { - pr.setMarL(Units.toEMU(value)); - } - - } - - /** - * - * @return the left margin of the paragraph - */ - public double getLeftMargin(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetMarL()){ - double val = Units.toPoints(props.getMarL()); - setValue(val); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - // if the marL attribute is omitted, then a value of 347663 is implied - return fetcher.getValue() == null ? 0 : fetcher.getValue(); - } - - /** - * Specifies the right margin of the paragraph. This is specified in addition to the text body - * inset and applies only to this text paragraph. That is the text body inset and the marR - * attributes are additive with respect to the text position. - * - * @param value the right margin of the paragraph, -1 to clear the margin and use the default of 0. - */ - public void setRightMargin(double value){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(value == -1) { - if(pr.isSetMarR()) pr.unsetMarR(); - } else { - pr.setMarR(Units.toEMU(value)); - } - - } - - /** - * - * @return the right margin of the paragraph - */ - public double getRightMargin(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetMarR()){ - double val = Units.toPoints(props.getMarR()); - setValue(val); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - // if the marL attribute is omitted, then a value of 347663 is implied - return fetcher.getValue() == null ? 0 : fetcher.getValue(); - } - - /** - * - * @return the default size for a tab character within this paragraph in points - */ - public double getDefaultTabSize(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetDefTabSz()){ - double val = Units.toPoints(POIXMLUnits.parseLength(props.xgetDefTabSz())); - setValue(val); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 0 : fetcher.getValue(); - } - - public double getTabStop(final int idx){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetTabLst()){ - CTTextTabStopList tabStops = props.getTabLst(); - if(idx < tabStops.sizeOfTabArray() ) { - CTTextTabStop ts = tabStops.getTabArray(idx); - double val = Units.toPoints(POIXMLUnits.parseLength(ts.xgetPos())); - setValue(val); - return true; - } - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 0. : fetcher.getValue(); - } - /** - * Add a single tab stop to be used on a line of text when there are one or more tab characters - * present within the text. - * - * @param value the position of the tab stop relative to the left margin - */ - public void addTabStop(double value){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextTabStopList tabStops = pr.isSetTabLst() ? pr.getTabLst() : pr.addNewTabLst(); - tabStops.addNewTab().setPos(Units.toEMU(value)); - } - - /** - * This element specifies the vertical line spacing that is to be used within a paragraph. - * This may be specified in two different ways, percentage spacing and font point spacing: - * <p> - * If linespacing >= 0, then linespacing is a percentage of normal line height - * If linespacing < 0, the absolute value of linespacing is the spacing in points - * </p> - * Examples: - * <pre><code> - * // spacing will be 120% of the size of the largest text on each line - * paragraph.setLineSpacing(120); - * - * // spacing will be 200% of the size of the largest text on each line - * paragraph.setLineSpacing(200); - * - * // spacing will be 48 points - * paragraph.setLineSpacing(-48.0); - * </code></pre> - * - * @param linespacing the vertical line spacing - */ - public void setLineSpacing(double linespacing){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); - if(linespacing >= 0) spc.addNewSpcPct().setVal((int)(linespacing*1000)); - else spc.addNewSpcPts().setVal((int)(-linespacing*100)); - pr.setLnSpc(spc); - } - - /** - * Returns the vertical line spacing that is to be used within a paragraph. - * This may be specified in two different ways, percentage spacing and font point spacing: - * <p> - * If linespacing >= 0, then linespacing is a percentage of normal line height. - * If linespacing < 0, the absolute value of linespacing is the spacing in points - * </p> - * - * @return the vertical line spacing. - */ - public double getLineSpacing(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetLnSpc()){ - CTTextSpacing spc = props.getLnSpc(); - - if(spc.isSetSpcPct()) setValue( POIXMLUnits.parsePercent(spc.getSpcPct().xgetVal())*0.001 ); - else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 ); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - - double lnSpc = fetcher.getValue() == null ? 100 : fetcher.getValue(); - if(lnSpc > 0) { - // check if the percentage value is scaled - CTTextNormalAutofit normAutofit = _shape.getTxBody().getBodyPr().getNormAutofit(); - if(normAutofit != null) { - double scale = 1 - (double)normAutofit.getLnSpcReduction() / 100000; - lnSpc *= scale; - } - } - - return lnSpc; - } - - /** - * Set the amount of vertical white space that will be present before the paragraph. - * This space is specified in either percentage or points: - * <p> - * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value of linespacing is the spacing in points - * </p> - * Examples: - * <pre><code> - * // The paragraph will be formatted to have a spacing before the paragraph text. - * // The spacing will be 200% of the size of the largest text on each line - * paragraph.setSpaceBefore(200); - * - * // The spacing will be a size of 48 points - * paragraph.setSpaceBefore(-48.0); - * </code></pre> - * - * @param spaceBefore the vertical white space before the paragraph. - */ - public void setSpaceBefore(double spaceBefore){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); - if(spaceBefore >= 0) spc.addNewSpcPct().setVal((int)(spaceBefore*1000)); - else spc.addNewSpcPts().setVal((int)(-spaceBefore*100)); - pr.setSpcBef(spc); - } - - /** - * The amount of vertical white space before the paragraph - * This may be specified in two different ways, percentage spacing and font point spacing: - * <p> - * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value of linespacing is the spacing in points - * </p> - * - * @return the vertical white space before the paragraph - */ - public double getSpaceBefore(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetSpcBef()){ - CTTextSpacing spc = props.getSpcBef(); - - if(spc.isSetSpcPct()) setValue( POIXMLUnits.parsePercent(spc.getSpcPct().xgetVal())*0.001 ); - else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 ); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - - return fetcher.getValue() == null ? 0 : fetcher.getValue(); - } - - /** - * Set the amount of vertical white space that will be present after the paragraph. - * This space is specified in either percentage or points: - * <p> - * If spaceAfter >= 0, then space is a percentage of normal line height. - * If spaceAfter < 0, the absolute value of linespacing is the spacing in points - * </p> - * Examples: - * <pre><code> - * // The paragraph will be formatted to have a spacing after the paragraph text. - * // The spacing will be 200% of the size of the largest text on each line - * paragraph.setSpaceAfter(200); - * - * // The spacing will be a size of 48 points - * paragraph.setSpaceAfter(-48.0); - * </code></pre> - * - * @param spaceAfter the vertical white space after the paragraph. - */ - public void setSpaceAfter(double spaceAfter){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextSpacing spc = CTTextSpacing.Factory.newInstance(); - if(spaceAfter >= 0) spc.addNewSpcPct().setVal((int)(spaceAfter*1000)); - else spc.addNewSpcPts().setVal((int)(-spaceAfter*100)); - pr.setSpcAft(spc); - } - - /** - * The amount of vertical white space after the paragraph - * This may be specified in two different ways, percentage spacing and font point spacing: - * <p> - * If spaceBefore >= 0, then space is a percentage of normal line height. - * If spaceBefore < 0, the absolute value of linespacing is the spacing in points - * </p> - * - * @return the vertical white space after the paragraph - */ - public double getSpaceAfter(){ - ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetSpcAft()){ - CTTextSpacing spc = props.getSpcAft(); - - if(spc.isSetSpcPct()) setValue( POIXMLUnits.parsePercent(spc.getSpcPct().xgetVal())*0.001 ); - else if (spc.isSetSpcPts()) setValue( -spc.getSpcPts().getVal()*0.01 ); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 0 : fetcher.getValue(); - } - - /** - * Specifies the particular level text properties that this paragraph will follow. - * The value for this attribute formats the text according to the corresponding level - * paragraph properties defined in the list of styles associated with the body of text - * that this paragraph belongs to (therefore in the parent shape). - * <p> - * Note that the closest properties object to the text is used, therefore if there is - * a conflict between the text paragraph properties and the list style properties for - * this level then the text paragraph properties will take precedence. - * </p> - * - * @param level the level (0 ... 4) - */ - public void setLevel(int level){ - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - - pr.setLvl(level); - } - - /** - * Returns the level of text properties that this paragraph will follow. - * - * @return the text level of this paragraph (0-based). Default is 0. - */ - public int getLevel(){ - CTTextParagraphProperties pr = _p.getPPr(); - if(pr == null) return 0; - - return pr.getLvl(); - } - - - /** - * Returns whether this paragraph has bullets - */ - public boolean isBullet() { - ParagraphPropertyFetcher<Boolean> fetcher = new ParagraphPropertyFetcher<Boolean>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if (props.isSetBuNone()) { - setValue(false); - return true; - } - if (props.isSetBuFont()) { - if (props.isSetBuChar() || props.isSetBuAutoNum()) { - setValue(true); - return true; - } /*else { - // Excel treats text with buFont but no char/autonum - // as not bulleted - // Possibly the font is just used if bullets turned on again? - }*/ - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); - } - - /** - * Set or unset this paragraph as a bullet point - * - * @param flag whether text in this paragraph has bullets - */ - public void setBullet(boolean flag) { - if(isBullet() == flag) return; - - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - if(!flag) { - pr.addNewBuNone(); - - if(pr.isSetBuAutoNum()) pr.unsetBuAutoNum(); - if(pr.isSetBuBlip()) pr.unsetBuBlip(); - if(pr.isSetBuChar()) pr.unsetBuChar(); - if(pr.isSetBuClr()) pr.unsetBuClr(); - if(pr.isSetBuClrTx()) pr.unsetBuClrTx(); - if(pr.isSetBuFont()) pr.unsetBuFont(); - if(pr.isSetBuFontTx()) pr.unsetBuFontTx(); - if(pr.isSetBuSzPct()) pr.unsetBuSzPct(); - if(pr.isSetBuSzPts()) pr.unsetBuSzPts(); - if(pr.isSetBuSzTx()) pr.unsetBuSzTx(); - } else { - if(pr.isSetBuNone()) pr.unsetBuNone(); - if(!pr.isSetBuFont()) pr.addNewBuFont().setTypeface("Arial"); - if(!pr.isSetBuAutoNum()) pr.addNewBuChar().setChar("\u2022"); - } - } - - /** - * Set this paragraph as an automatic numbered bullet point - * - * @param scheme type of auto-numbering - * @param startAt the number that will start number for a given sequence of automatically - * numbered bullets (1-based). - */ - public void setBullet(ListAutoNumber scheme, int startAt) { - if(startAt < 1) throw new IllegalArgumentException("Start Number must be greater or equal that 1") ; - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextAutonumberBullet lst = pr.isSetBuAutoNum() ? pr.getBuAutoNum() : pr.addNewBuAutoNum(); - lst.setType(STTextAutonumberScheme.Enum.forInt(scheme.ordinal() + 1)); - lst.setStartAt(startAt); - - if(!pr.isSetBuFont()) pr.addNewBuFont().setTypeface("Arial"); - if(pr.isSetBuNone()) pr.unsetBuNone(); - // remove these elements if present as it results in invalid content when opening in Excel. - if(pr.isSetBuBlip()) pr.unsetBuBlip(); - if(pr.isSetBuChar()) pr.unsetBuChar(); - } - - /** - * Set this paragraph as an automatic numbered bullet point - * - * @param scheme type of auto-numbering - */ - public void setBullet(ListAutoNumber scheme) { - CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); - CTTextAutonumberBullet lst = pr.isSetBuAutoNum() ? pr.getBuAutoNum() : pr.addNewBuAutoNum(); - lst.setType(STTextAutonumberScheme.Enum.forInt(scheme.ordinal() + 1)); - - if(!pr.isSetBuFont()) pr.addNewBuFont().setTypeface("Arial"); - if(pr.isSetBuNone()) pr.unsetBuNone(); - // remove these elements if present as it results in invalid content when opening in Excel. - if(pr.isSetBuBlip()) pr.unsetBuBlip(); - if(pr.isSetBuChar()) pr.unsetBuChar(); - } - - /** - * Returns whether this paragraph has automatic numbered bullets - */ - public boolean isBulletAutoNumber() { - ParagraphPropertyFetcher<Boolean> fetcher = new ParagraphPropertyFetcher<Boolean>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuAutoNum()) { - setValue(true); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? false : fetcher.getValue(); - } - - /** - * Returns the starting number if this paragraph has automatic numbered bullets, otherwise returns 0 - */ - public int getBulletAutoNumberStart() { - ParagraphPropertyFetcher<Integer> fetcher = new ParagraphPropertyFetcher<Integer>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuAutoNum() && props.getBuAutoNum().isSetStartAt()) { - setValue(props.getBuAutoNum().getStartAt()); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - return fetcher.getValue() == null ? 0 : fetcher.getValue(); - } - - /** - * Returns the auto number scheme if this paragraph has automatic numbered bullets, otherwise returns ListAutoNumber.ARABIC_PLAIN - */ - public ListAutoNumber getBulletAutoNumberScheme() { - ParagraphPropertyFetcher<ListAutoNumber> fetcher = new ParagraphPropertyFetcher<ListAutoNumber>(getLevel()){ - public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuAutoNum()) { - setValue(ListAutoNumber.values()[props.getBuAutoNum().getType().intValue() - 1]); - return true; - } - return false; - } - }; - fetchParagraphProperty(fetcher); - - // Note: documentation does not define a default, return ListAutoNumber.ARABIC_PLAIN (1,2,3...) - return fetcher.getValue() == null ? ListAutoNumber.ARABIC_PLAIN : fetcher.getValue(); - } - - - @SuppressWarnings("rawtypes") - private boolean fetchParagraphProperty(ParagraphPropertyFetcher visitor){ - boolean ok = false; - - if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr()); - - if(!ok) { - ok = visitor.fetch(_shape); - } - - return ok; - } - - @Override - public String toString(){ - return "[" + getClass() + "]" + getText(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextRun.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextRun.java deleted file mode 100644 index 1809e16cd5..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextRun.java +++ /dev/null @@ -1,358 +0,0 @@ -/* ==================================================================== - 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 java.awt.Color; - -import org.apache.poi.ooxml.util.POIXMLUnits; -import org.apache.poi.util.Units; -import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; - -/** - * Represents a run of text within the containing text body. The run element is the - * lowest level text separation mechanism within a text body. - */ -public class XSSFTextRun { - private final CTRegularTextRun _r; - private final XSSFTextParagraph _p; - - XSSFTextRun(CTRegularTextRun r, XSSFTextParagraph p){ - _r = r; - _p = p; - } - - XSSFTextParagraph getParentParagraph(){ - return _p; - } - - public String getText(){ - return _r.getT(); - } - - public void setText(String text){ - _r.setT(text); - } - - public CTRegularTextRun getXmlObject(){ - return _r; - } - - public void setFontColor(Color color){ - CTTextCharacterProperties rPr = getRPr(); - CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill(); - CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr(); - clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()}); - - if(fill.isSetHslClr()) fill.unsetHslClr(); - if(fill.isSetPrstClr()) fill.unsetPrstClr(); - if(fill.isSetSchemeClr()) fill.unsetSchemeClr(); - if(fill.isSetScrgbClr()) fill.unsetScrgbClr(); - if(fill.isSetSysClr()) fill.unsetSysClr(); - - } - - public Color getFontColor(){ - - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetSolidFill()){ - CTSolidColorFillProperties fill = rPr.getSolidFill(); - - if(fill.isSetSrgbClr()){ - CTSRgbColor clr = fill.getSrgbClr(); - byte[] rgb = clr.getVal(); - return new Color(0xFF & rgb[0], 0xFF & rgb[1], 0xFF & rgb[2]); - } - } - - return new Color(0, 0, 0); - } - - /** - * - * @param fontSize font size in points. - * The value of <code>-1</code> unsets the Sz attribute from the underlying xml bean - */ - public void setFontSize(double fontSize){ - CTTextCharacterProperties rPr = getRPr(); - if(fontSize == -1.0) { - if(rPr.isSetSz()) rPr.unsetSz(); - } else { - if(fontSize < 1.0) { - throw new IllegalArgumentException("Minimum font size is 1pt but was " + fontSize); - } - - rPr.setSz((int)(100*fontSize)); - } - } - - /** - * @return font size in points or -1 if font size is not set. - */ - public double getFontSize(){ - double scale = 1; - double size = XSSFFont.DEFAULT_FONT_SIZE; // default font size - CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTxBody().getBodyPr().getNormAutofit(); - if(afit != null) scale = (double)afit.getFontScale() / 100000; - - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetSz()){ - size = rPr.getSz()*0.01; - } - - return size * scale; - } - - /** - * - * @return the spacing between characters within a text run, - * If this attribute is omitted then a value of 0 or no adjustment is assumed. - */ - public double getCharacterSpacing(){ - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetSpc()){ - return Units.toPoints(POIXMLUnits.parseLength(rPr.xgetSpc())); - } - return 0; - } - - /** - * Set the spacing between characters within a text run. - * <p> - * The spacing is specified in points. Positive values will cause the text to expand, - * negative values to condense. - * </p> - * - * @param spc character spacing in points. - */ - public void setCharacterSpacing(double spc){ - CTTextCharacterProperties rPr = getRPr(); - if(spc == 0.0) { - if(rPr.isSetSpc()) rPr.unsetSpc(); - } else { - rPr.setSpc((int)(100*spc)); - } - } - - /** - * Specifies the typeface, or name of the font that is to be used for this text run. - * - * @param typeface the font to apply to this text run. - * The value of <code>null</code> unsets the Typeface attribute from the underlying xml. - */ - public void setFont(String typeface){ - setFontFamily(typeface, (byte)-1, (byte)-1, false); - } - - public void setFontFamily(String typeface, byte charset, byte pictAndFamily, boolean isSymbol){ - CTTextCharacterProperties rPr = getRPr(); - - if(typeface == null){ - if(rPr.isSetLatin()) rPr.unsetLatin(); - if(rPr.isSetCs()) rPr.unsetCs(); - if(rPr.isSetSym()) rPr.unsetSym(); - } else { - if(isSymbol){ - CTTextFont font = rPr.isSetSym() ? rPr.getSym() : rPr.addNewSym(); - font.setTypeface(typeface); - } else { - CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin(); - latin.setTypeface(typeface); - if(charset != -1) latin.setCharset(charset); - if(pictAndFamily != -1) latin.setPitchFamily(pictAndFamily); - } - } - } - - /** - * @return font family or null if not set - */ - public String getFontFamily(){ - CTTextCharacterProperties rPr = getRPr(); - CTTextFont font = rPr.getLatin(); - if(font != null){ - return font.getTypeface(); - } - return XSSFFont.DEFAULT_FONT_NAME; - } - - public byte getPitchAndFamily(){ - CTTextCharacterProperties rPr = getRPr(); - CTTextFont font = rPr.getLatin(); - if(font != null){ - return font.getPitchFamily(); - } - return 0; - } - - /** - * Specifies whether a run of text will be formatted as strikethrough text. - * - * @param strike whether a run of text will be formatted as strikethrough text. - */ - public void setStrikethrough(boolean strike) { - getRPr().setStrike(strike ? STTextStrikeType.SNG_STRIKE : STTextStrikeType.NO_STRIKE); - } - - /** - * @return whether a run of text will be formatted as strikethrough text. Default is false. - */ - public boolean isStrikethrough() { - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetStrike()){ - return rPr.getStrike() != STTextStrikeType.NO_STRIKE; - } - return false; - } - - /** - * @return whether a run of text will be formatted as a superscript text. Default is false. - */ - public boolean isSuperscript() { - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetBaseline()){ - return POIXMLUnits.parsePercent(rPr.xgetBaseline()) > 0; - } - return false; - } - - /** - * Set the baseline for both the superscript and subscript fonts. - * <p> - * The size is specified using a percentage. - * Positive values indicate superscript, negative values indicate subscript. - * </p> - * - * @param baselineOffset - */ - public void setBaselineOffset(double baselineOffset){ - getRPr().setBaseline((int) baselineOffset * 1000); - } - - /** - * Set whether the text in this run is formatted as superscript. - * Default base line offset is 30% - * - * @see #setBaselineOffset(double) - */ - public void setSuperscript(boolean flag){ - setBaselineOffset(flag ? 30. : 0.); - } - - /** - * Set whether the text in this run is formatted as subscript. - * Default base line offset is -25%. - * - * @see #setBaselineOffset(double) - */ - public void setSubscript(boolean flag){ - setBaselineOffset(flag ? -25.0 : 0.); - } - - /** - * @return whether a run of text will be formatted as a superscript text. Default is false. - */ - public boolean isSubscript() { - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetBaseline()){ - return POIXMLUnits.parsePercent(rPr.xgetBaseline()) < 0; - } - return false; - } - - /** - * @return whether a run of text will be formatted as a superscript text. Default is false. - */ - public TextCap getTextCap() { - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetCap()){ - return TextCap.values()[rPr.getCap().intValue() - 1]; - } - return TextCap.NONE; - } - - /** - * Specifies whether this run of text will be formatted as bold text - * - * @param bold whether this run of text will be formatted as bold text - */ - public void setBold(boolean bold){ - getRPr().setB(bold); - } - - /** - * @return whether this run of text is formatted as bold text - */ - public boolean isBold(){ - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetB()){ - return rPr.getB(); - } - return false; - } - - /** - * @param italic whether this run of text is formatted as italic text - */ - public void setItalic(boolean italic){ - getRPr().setI(italic); - } - - /** - * @return whether this run of text is formatted as italic text - */ - public boolean isItalic(){ - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetI()){ - return rPr.getI(); - } - return false; - } - - /** - * @param underline whether this run of text is formatted as underlined text - */ - public void setUnderline(boolean underline) { - getRPr().setU(underline ? STTextUnderlineType.SNG : STTextUnderlineType.NONE); - } - - /** - * @return whether this run of text is formatted as underlined text - */ - public boolean isUnderline(){ - CTTextCharacterProperties rPr = getRPr(); - if(rPr.isSetU()){ - return rPr.getU() != STTextUnderlineType.NONE; - } - return false; - } - - protected CTTextCharacterProperties getRPr(){ - return _r.isSetRPr() ? _r.getRPr() : _r.addNewRPr(); - } - - @Override - public String toString(){ - return "[" + getClass() + "]" + getText(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVBAPart.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVBAPart.java deleted file mode 100644 index b5efa0951a..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVBAPart.java +++ /dev/null @@ -1,52 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLDocumentPart; -import org.apache.poi.openxml4j.opc.PackagePart; - -public class XSSFVBAPart extends POIXMLDocumentPart { - - /** - * Create a new XSSFVBAPart node - */ - protected XSSFVBAPart() { - super(); - } - - /** - * Construct XSSFVBAPart from a package part - * - * @param part the package part holding the VBA data, - * - * @since POI 3.14-Beta1 - */ - protected XSSFVBAPart(PackagePart part) { - super(part); - } - - /** - * Like *PictureData, VBA objects store the actual content in the part - * directly without keeping a copy like all others therefore we need to - * handle them differently. - */ - protected void prepareForCommit() { - // do not clear the part here - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java deleted file mode 100644 index 59aa229853..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java +++ /dev/null @@ -1,323 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; -import static org.apache.poi.xssf.usermodel.XSSFRelation.NS_SPREADSHEETML; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.xml.namespace.QName; - -import com.microsoft.schemas.office.excel.CTClientData; -import com.microsoft.schemas.office.excel.STObjectType; -import com.microsoft.schemas.office.office.CTIdMap; -import com.microsoft.schemas.office.office.CTShapeLayout; -import com.microsoft.schemas.office.office.STConnectType; -import com.microsoft.schemas.office.office.STInsetMode; -import com.microsoft.schemas.office.office.ShapelayoutDocument; -import com.microsoft.schemas.vml.CTGroup; -import com.microsoft.schemas.vml.CTPath; -import com.microsoft.schemas.vml.CTShadow; -import com.microsoft.schemas.vml.CTShape; -import com.microsoft.schemas.vml.CTShapetype; -import com.microsoft.schemas.vml.STExt; -import com.microsoft.schemas.vml.STStrokeJoinStyle; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.schemas.vmldrawing.XmlDocument; -import org.apache.poi.util.ReplacingInputStream; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STTrueFalse; - -/** - * Represents a SpreadsheetML VML drawing. - * - * <p> - * In Excel 2007 VML drawings are used to describe properties of cell comments, - * although the spec says that VML is deprecated: - * </p> - * <p> - * The VML format is a legacy format originally introduced with Office 2000 and is included and fully defined - * in this Standard for backwards compatibility reasons. The DrawingML format is a newer and richer format - * created with the goal of eventually replacing any uses of VML in the Office Open XML formats. VML should be - * considered a deprecated format included in Office Open XML for legacy reasons only and new applications that - * need a file format for drawings are strongly encouraged to use preferentially DrawingML - * </p> - * - * <p> - * Warning - Excel is known to put invalid XML into these files! - * For example, >br< without being closed or escaped crops up. - * </p> - * - * See 6.4 VML - SpreadsheetML Drawing in Office Open XML Part 4 - Markup Language Reference.pdf - */ -public final class XSSFVMLDrawing extends POIXMLDocumentPart { - // this ID value seems to have significance to Excel >= 2010; - // see https://issues.apache.org/bugzilla/show_bug.cgi?id=55409 - private static final String COMMENT_SHAPE_TYPE_ID = "_x0000_t202"; - - /** - * to actually process the namespace-less vmldrawing, we've introduced a proxy namespace. - * this namespace is active in-memory, but will be removed on saving to the file - */ - public static final QName QNAME_VMLDRAWING = new QName("urn:schemas-poi-apache-org:vmldrawing", "xml"); - - /** - * regexp to parse shape ids, in VML they have weird form of id="_x0000_s1026" - */ - private static final Pattern ptrn_shapeId = Pattern.compile("_x0000_s(\\d+)"); - - private XmlDocument root; - private String _shapeTypeId; - private int _shapeId = 1024; - - /** - * Create a new SpreadsheetML drawing - * - * @see XSSFSheet#createDrawingPatriarch() - */ - protected XSSFVMLDrawing() { - super(); - newDrawing(); - } - - /** - * Construct a SpreadsheetML drawing from a package part - * - * @param part the package part holding the drawing data, - * the content type must be <code>application/vnd.openxmlformats-officedocument.drawing+xml</code> - * - * @since POI 3.14-Beta1 - */ - protected XSSFVMLDrawing(PackagePart part) throws IOException, XmlException { - super(part); - read(getPackagePart().getInputStream()); - } - - public XmlDocument getDocument() { - return root; - } - - - protected void read(InputStream is) throws IOException, XmlException { - XmlOptions xopt = new XmlOptions(DEFAULT_XML_OPTIONS); - xopt.setLoadSubstituteNamespaces(Collections.singletonMap("", QNAME_VMLDRAWING.getNamespaceURI())); - xopt.setDocumentType(XmlDocument.type); - - /* - * This is a seriously sick fix for the fact that some .xlsx files contain raw bits - * of HTML, without being escaped or properly turned into XML. - * The result is that they contain things like >br<, which breaks the XML parsing. - * This very sick InputStream wrapper attempts to spot these go past, and fix them. - * - * Furthermore some documents contain a default namespace of - * http://schemas.openxmlformats.org/spreadsheetml/2006/main for the namespace-less "xml" document type. - * this definition is wrong and removed. - */ - root = XmlDocument.Factory.parse( - new ReplacingInputStream( - new ReplacingInputStream(is, "<br>", "<br/>"), - " xmlns=\""+NS_SPREADSHEETML+"\"", "") - , xopt); - - XmlCursor cur = root.getXml().newCursor(); - - try { - for (boolean found = cur.toFirstChild(); found; found = cur.toNextSibling()) { - XmlObject xo = cur.getObject(); - if (xo instanceof CTShapetype) { - _shapeTypeId = ((CTShapetype)xo).getId(); - } else if (xo instanceof CTShape) { - CTShape shape = (CTShape)xo; - String id = shape.getId(); - if(id != null) { - Matcher m = ptrn_shapeId.matcher(id); - if(m.find()) { - _shapeId = Math.max(_shapeId, Integer.parseInt(m.group(1))); - } - } - } - } - } finally { - cur.dispose(); - } - } - - protected List<XmlObject> getItems(){ - List<XmlObject> items = new ArrayList<>(); - - XmlCursor cur = root.getXml().newCursor(); - try { - for (boolean found = cur.toFirstChild(); found; found = cur.toNextSibling()) { - items.add(cur.getObject()); - } - } finally { - cur.dispose(); - } - - return items; - } - - protected void write(OutputStream out) throws IOException { - XmlOptions xopt = new XmlOptions(DEFAULT_XML_OPTIONS); - xopt.setSaveImplicitNamespaces(Collections.singletonMap("", QNAME_VMLDRAWING.getNamespaceURI())); - root.save(out, xopt); - } - - @Override - protected void commit() throws IOException { - PackagePart part = getPackagePart(); - try (OutputStream out = part.getOutputStream()) { - write(out); - } - } - - /** - * Initialize a new Speadsheet VML drawing - */ - private void newDrawing(){ - root = XmlDocument.Factory.newInstance(); - XmlCursor xml = root.addNewXml().newCursor(); - - ShapelayoutDocument layDoc = ShapelayoutDocument.Factory.newInstance(); - CTShapeLayout layout = layDoc.addNewShapelayout(); - layout.setExt(STExt.EDIT); - CTIdMap idmap = layout.addNewIdmap(); - idmap.setExt(STExt.EDIT); - idmap.setData("1"); - - xml.toEndToken(); - XmlCursor layCur = layDoc.newCursor(); - layCur.copyXmlContents(xml); - layCur.dispose(); - - CTGroup grp = CTGroup.Factory.newInstance(); - CTShapetype shapetype = grp.addNewShapetype(); - _shapeTypeId = COMMENT_SHAPE_TYPE_ID; - shapetype.setId(_shapeTypeId); - shapetype.setCoordsize("21600,21600"); - shapetype.setSpt(202); - shapetype.setPath2("m,l,21600r21600,l21600,xe"); - shapetype.addNewStroke().setJoinstyle(STStrokeJoinStyle.MITER); - CTPath path = shapetype.addNewPath(); - path.setGradientshapeok(STTrueFalse.T); - path.setConnecttype(STConnectType.RECT); - - xml.toEndToken(); - XmlCursor grpCur = grp.newCursor(); - grpCur.copyXmlContents(xml); - grpCur.dispose(); - } - - protected CTShape newCommentShape(){ - CTGroup grp = CTGroup.Factory.newInstance(); - - CTShape shape = grp.addNewShape(); - shape.setId("_x0000_s" + (++_shapeId)); - shape.setType("#" + _shapeTypeId); - shape.setStyle("position:absolute; visibility:hidden"); - shape.setFillcolor("#ffffe1"); - shape.setInsetmode(STInsetMode.AUTO); - shape.addNewFill().setColor("#ffffe1"); - CTShadow shadow = shape.addNewShadow(); - shadow.setOn(STTrueFalse.T); - shadow.setColor("black"); - shadow.setObscured(STTrueFalse.T); - shape.addNewPath().setConnecttype(STConnectType.NONE); - shape.addNewTextbox().setStyle("mso-direction-alt:auto"); - CTClientData cldata = shape.addNewClientData(); - cldata.setObjectType(STObjectType.NOTE); - cldata.addNewMoveWithCells(); - cldata.addNewSizeWithCells(); - cldata.addNewAnchor().setStringValue("1, 15, 0, 2, 3, 15, 3, 16"); - cldata.addNewAutoFill().setStringValue("False"); - cldata.addNewRow().setBigIntegerValue(BigInteger.valueOf(0)); - cldata.addNewColumn().setBigIntegerValue(BigInteger.valueOf(0)); - - XmlCursor xml = root.getXml().newCursor(); - xml.toEndToken(); - XmlCursor grpCur = grp.newCursor(); - grpCur.copyXmlContents(xml); - xml.toPrevSibling(); - shape = (CTShape)xml.getObject(); - grpCur.dispose(); - xml.dispose(); - - return shape; - } - - /** - * Find a shape with ClientData of type "NOTE" and the specified row and column - * - * @return the comment shape or <code>null</code> - */ - public CTShape findCommentShape(int row, int col){ - XmlCursor cur = root.getXml().newCursor(); - for (boolean found = cur.toFirstChild(); found; found = cur.toNextSibling()) { - XmlObject itm = cur.getObject(); - if (matchCommentShape(itm, row, col)) { - return (CTShape)itm; - } - } - return null; - } - - private boolean matchCommentShape(XmlObject itm, int row, int col) { - if (!(itm instanceof CTShape)) { - return false; - } - - CTShape sh = (CTShape)itm; - if (sh.sizeOfClientDataArray() == 0) { - return false; - } - - CTClientData cldata = sh.getClientDataArray(0); - if(cldata.getObjectType() != STObjectType.NOTE) { - return false; - } - - int crow = cldata.getRowArray(0).intValue(); - int ccol = cldata.getColumnArray(0).intValue(); - return (crow == row && ccol == col); - } - - protected boolean removeCommentShape(int row, int col){ - XmlCursor cur = root.getXml().newCursor(); - for (boolean found = cur.toFirstChild(); found; found = cur.toNextSibling()) { - XmlObject itm = cur.getObject(); - if (matchCommentShape(itm, row, col)) { - cur.removeXml(); - return true; - } - } - return false; - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java deleted file mode 100644 index f64ed3c4cd..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ /dev/null @@ -1,2395 +0,0 @@ -/* ==================================================================== - 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.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; -import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.setPassword; -import static org.apache.poi.xssf.usermodel.helpers.XSSFPasswordHelper.validatePassword; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.regex.Pattern; - -import javax.xml.namespace.QName; - -import org.apache.commons.collections4.ListValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.hpsf.ClassIDPredefined; -import org.apache.poi.ooxml.POIXMLDocument; -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ooxml.POIXMLException; -import org.apache.poi.ooxml.POIXMLProperties; -import org.apache.poi.ooxml.util.PackageHelper; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackageAccess; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.Ole10Native; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.ss.SpreadsheetVersion; -import org.apache.poi.ss.formula.SheetNameFormatter; -import org.apache.poi.ss.formula.udf.AggregatingUDFFinder; -import org.apache.poi.ss.formula.udf.IndexedUDFFinder; -import org.apache.poi.ss.formula.udf.UDFFinder; -import org.apache.poi.ss.usermodel.DataFormat; -import org.apache.poi.ss.usermodel.Date1904Support; -import org.apache.poi.ss.usermodel.Name; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.SheetVisibility; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.ss.util.WorkbookUtil; -import org.apache.poi.util.Beta; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.Internal; -import org.apache.poi.util.NotImplemented; -import org.apache.poi.util.Removal; -import org.apache.poi.xssf.XLSBUnsupportedException; -import org.apache.poi.xssf.model.CalculationChain; -import org.apache.poi.xssf.model.ExternalLinksTable; -import org.apache.poi.xssf.model.MapInfo; -import org.apache.poi.xssf.model.SharedStringsTable; -import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.model.ThemesTable; -import org.apache.poi.xssf.usermodel.helpers.XSSFFormulaUtils; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookView; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookViews; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCalcPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedNames; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDialogsheet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTExternalReference; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCache; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCaches; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheets; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookProtection; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STSheetState; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument; - -/** - * High level representation of a SpreadsheetML workbook. This is the first object most users - * will construct whether they are reading or writing a workbook. It is also the - * top level object for creating new sheets/etc. - */ -public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Support { - private static final Pattern COMMA_PATTERN = Pattern.compile(","); - - /** - * Excel silently truncates long sheet names to 31 chars. - * This constant is used to ensure uniqueness in the first 31 chars - */ - private static final int MAX_SENSITIVE_SHEET_NAME_LEN = 31; - - /** - * Images formats supported by XSSF but not by HSSF - */ - public static final int PICTURE_TYPE_GIF = 8; - public static final int PICTURE_TYPE_TIFF = 9; - public static final int PICTURE_TYPE_EPS = 10; - public static final int PICTURE_TYPE_BMP = 11; - public static final int PICTURE_TYPE_WPG = 12; - - /** - * The underlying XML bean - */ - private CTWorkbook workbook; - - /** - * this holds the XSSFSheet objects attached to this workbook - */ - private List<XSSFSheet> sheets; - - /** - * this holds the XSSFName objects attached to this workbook, keyed by lower-case name - */ - private ListValuedMap<String, XSSFName> namedRangesByName; - - /** - * this holds the XSSFName objects attached to this workbook - */ - private List<XSSFName> namedRanges; - - /** - * shared string table - a cache of strings in this workbook - */ - private SharedStringsTable sharedStringSource; - - /** - * A collection of shared objects used for styling content, - * e.g. fonts, cell styles, colors, etc. - */ - private StylesTable stylesSource; - - /** - * The locator of user-defined functions. - * By default includes functions from the Excel Analysis Toolpack - */ - private final IndexedUDFFinder _udfFinder = new IndexedUDFFinder(AggregatingUDFFinder.DEFAULT); - - /** - * TODO - */ - private CalculationChain calcChain; - - /** - * External Links, for referencing names or cells in other workbooks. - */ - private List<ExternalLinksTable> externalLinks; - - /** - * A collection of custom XML mappings - */ - private MapInfo mapInfo; - - /** - * Used to keep track of the data formatter so that all - * createDataFormatter calls return the same one for a given - * book. This ensures that updates from one places is visible - * someplace else. - */ - private XSSFDataFormat formatter; - - /** - * The policy to apply in the event of missing or - * blank cells when fetching from a row. - * See {@link MissingCellPolicy} - */ - private MissingCellPolicy _missingCellPolicy = MissingCellPolicy.RETURN_NULL_AND_BLANK; - - /** - * Whether a call to {@link XSSFCell#setCellFormula(String)} will validate the formula or not. - */ - private boolean cellFormulaValidation = true; - - /** - * array of pictures for this workbook - */ - private List<XSSFPictureData> pictures; - - private static final Logger LOG = LogManager.getLogger(XSSFWorkbook.class); - - /** - * cached instance of XSSFCreationHelper for this workbook - * @see #getCreationHelper() - */ - private XSSFCreationHelper _creationHelper; - - /** - * List of all pivot tables in workbook - */ - private List<XSSFPivotTable> pivotTables; - private List<CTPivotCache> pivotCaches; - - private final XSSFFactory xssfFactory; - - /** - * Create a new SpreadsheetML workbook. - */ - public XSSFWorkbook() { - this(XSSFWorkbookType.XLSX); - } - - public XSSFWorkbook(XSSFFactory factory) { - this(XSSFWorkbookType.XLSX, factory); - } - - /** - * Create a new SpreadsheetML workbook. - * @param workbookType The type of workbook to make (.xlsx or .xlsm). - */ - public XSSFWorkbook(XSSFWorkbookType workbookType) { - this(workbookType, null); - } - - private XSSFWorkbook(XSSFWorkbookType workbookType, XSSFFactory factory) { - super(newPackage(workbookType)); - this.xssfFactory = (factory == null) ? XSSFFactory.getInstance() : factory; - onWorkbookCreate(); - } - - /** - * Constructs a XSSFWorkbook object given a OpenXML4J <code>Package</code> object, - * see <a href="https://poi.apache.org/oxml4j/">https://poi.apache.org/oxml4j/</a>. - * - * <p>Once you have finished working with the Workbook, you should close the package - * by calling either {@link #close()} or {@link OPCPackage#close()}, to avoid - * leaving file handles open. - * - * <p>Creating a XSSFWorkbook from a file-backed OPC Package has a lower memory - * footprint than an InputStream backed one. - * - * @param pkg the OpenXML4J <code>OPC Package</code> object. - */ - public XSSFWorkbook(OPCPackage pkg) throws IOException { - super(pkg); - this.xssfFactory = XSSFFactory.getInstance(); - - beforeDocumentRead(); - - // Build a tree of POIXMLDocumentParts, this workbook being the root - load(this.xssfFactory); - - // some broken Workbooks miss this... - setBookViewsIfMissing(); - } - - /** - * Constructs a XSSFWorkbook object, by buffering the whole stream into memory - * and then opening an {@link OPCPackage} object for it. - * - * <p>Using an {@link InputStream} requires more memory than using a File, so - * if a {@link File} is available then you should instead do something like - * <pre><code> - * OPCPackage pkg = OPCPackage.open(path); - * XSSFWorkbook wb = new XSSFWorkbook(pkg); - * // work with the wb object - * ...... - * pkg.close(); // gracefully closes the underlying zip file - * </code></pre> - */ - public XSSFWorkbook(InputStream is) throws IOException { - this(PackageHelper.open(is)); - } - - /** - * Constructs a XSSFWorkbook object from a given file. - * - * <p>Once you have finished working with the Workbook, you should close - * the package by calling {@link #close()}, to avoid leaving file - * handles open. - * - * <p>Opening a XSSFWorkbook from a file has a lower memory footprint - * than opening from an InputStream - * - * @param file the file to open - */ - public XSSFWorkbook(File file) throws IOException, InvalidFormatException { - this(OPCPackage.open(file)); - } - - /** - * Constructs a XSSFWorkbook object given a file name. - * - * - * <p>Once you have finished working with the Workbook, you should close - * the package by calling {@link #close()}, to avoid leaving file - * handles open. - * - * <p>Opening a XSSFWorkbook from a file has a lower memory footprint - * than opening from an InputStream - * - * @param path the file name. - */ - public XSSFWorkbook(String path) throws IOException { - this(openPackage(path)); - } - - /** - * Constructs a XSSFWorkbook object using Package Part. - * @param part package part - * @since POI 4.0.0 - */ - public XSSFWorkbook(PackagePart part) throws IOException { - this(part.getInputStream()); - } - - protected void beforeDocumentRead() { - // Ensure it isn't a XLSB file, which we don't support - if (getCorePart().getContentType().equals(XSSFRelation.XLSB_BINARY_WORKBOOK.getContentType())) { - throw new XLSBUnsupportedException(); - } - - // Create arrays for parts attached to the workbook itself - pivotTables = new ArrayList<>(); - pivotCaches = new ArrayList<>(); - } - - @Override - protected void onDocumentRead() throws IOException { - try { - WorkbookDocument doc = WorkbookDocument.Factory.parse(getPackagePart().getInputStream(), DEFAULT_XML_OPTIONS); - this.workbook = doc.getWorkbook(); - - ThemesTable theme = null; - Map<String, XSSFSheet> shIdMap = new HashMap<>(); - Map<String, ExternalLinksTable> elIdMap = new HashMap<>(); - for(RelationPart rp : getRelationParts()){ - POIXMLDocumentPart p = rp.getDocumentPart(); - if(p instanceof SharedStringsTable) { - sharedStringSource = (SharedStringsTable)p; - } else if(p instanceof StylesTable) { - stylesSource = (StylesTable)p; - } else if(p instanceof ThemesTable) { - theme = (ThemesTable)p; - } else if(p instanceof CalculationChain) { - calcChain = (CalculationChain)p; - } else if(p instanceof MapInfo) { - mapInfo = (MapInfo)p; - } else if (p instanceof XSSFSheet) { - shIdMap.put(rp.getRelationship().getId(), (XSSFSheet)p); - } else if (p instanceof ExternalLinksTable) { - elIdMap.put(rp.getRelationship().getId(), (ExternalLinksTable)p); - } - } - boolean packageReadOnly = (getPackage().getPackageAccess() == PackageAccess.READ); - - if (stylesSource == null) { - // Create Styles if it is missing - if (packageReadOnly) { - stylesSource = new StylesTable(); - } else { - stylesSource = (StylesTable)createRelationship(XSSFRelation.STYLES, this.xssfFactory); - } - } - stylesSource.setWorkbook(this); - stylesSource.setTheme(theme); - - if (sharedStringSource == null) { - // Create SST if it is missing - if (packageReadOnly) { - sharedStringSource = new SharedStringsTable(); - } else { - sharedStringSource = (SharedStringsTable)createRelationship(XSSFRelation.SHARED_STRINGS, this.xssfFactory); - } - } - - // Load individual sheets. The order of sheets is defined by the order - // of CTSheet elements in the workbook - sheets = new ArrayList<>(shIdMap.size()); - for (CTSheet ctSheet : this.workbook.getSheets().getSheetArray()) { - parseSheet(shIdMap, ctSheet); - } - - // Load the external links tables. Their order is defined by the order - // of CTExternalReference elements in the workbook - externalLinks = new ArrayList<>(elIdMap.size()); - if (this.workbook.isSetExternalReferences()) { - for (CTExternalReference er : this.workbook.getExternalReferences().getExternalReferenceArray()) { - ExternalLinksTable el = elIdMap.get(er.getId()); - if(el == null) { - LOG.atWarn().log("ExternalLinksTable with r:id {} was defined, but didn't exist in package, skipping", er.getId()); - continue; - } - externalLinks.add(el); - } - } - - // Process the named ranges - reprocessNamedRanges(); - } catch (XmlException e) { - throw new POIXMLException(e); - } - } - - /** - * Not normally to be called externally, but possibly to be overridden to avoid - * the DOM based parse of large sheets (see examples). - */ - public void parseSheet(Map<String, XSSFSheet> shIdMap, CTSheet ctSheet) { - XSSFSheet sh = shIdMap.get(ctSheet.getId()); - if(sh == null) { - LOG.atWarn().log("Sheet with name {} and r:id {} was defined, but didn't exist in package, skipping", ctSheet.getName(), ctSheet.getId()); - return; - } - sh.sheet = ctSheet; - sh.onDocumentRead(); - sheets.add(sh); - } - - /** - * Create a new CTWorkbook with all values set to default - */ - private void onWorkbookCreate() { - workbook = CTWorkbook.Factory.newInstance(); - - // don't EVER use the 1904 date system - CTWorkbookPr workbookPr = workbook.addNewWorkbookPr(); - workbookPr.setDate1904(false); - - setBookViewsIfMissing(); - workbook.addNewSheets(); - - POIXMLProperties.ExtendedProperties expProps = getProperties().getExtendedProperties(); - expProps.getUnderlyingProperties().setApplication(DOCUMENT_CREATOR); - - sharedStringSource = (SharedStringsTable)createRelationship(XSSFRelation.SHARED_STRINGS, this.xssfFactory); - stylesSource = (StylesTable)createRelationship(XSSFRelation.STYLES, this.xssfFactory); - stylesSource.setWorkbook(this); - - namedRanges = new ArrayList<>(); - namedRangesByName = new ArrayListValuedHashMap<>(); - sheets = new ArrayList<>(); - pivotTables = new ArrayList<>(); - } - - private void setBookViewsIfMissing() { - if(!workbook.isSetBookViews()) { - CTBookViews bvs = workbook.addNewBookViews(); - CTBookView bv = bvs.addNewWorkbookView(); - bv.setActiveTab(0); - } - } - - /** - * Create a new SpreadsheetML package and setup the default minimal content - */ - protected static OPCPackage newPackage(XSSFWorkbookType workbookType) { - OPCPackage pkg = null; - try { - pkg = OPCPackage.create(new ByteArrayOutputStream()); // NOSONAR - we do not want to close this here - // Main part - PackagePartName corePartName = PackagingURIHelper.createPartName(XSSFRelation.WORKBOOK.getDefaultFileName()); - // Create main part relationship - pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT); - // Create main document part - pkg.createPart(corePartName, workbookType.getContentType()); - - pkg.getPackageProperties().setCreatorProperty(DOCUMENT_CREATOR); - } catch (Exception e) { - IOUtils.closeQuietly(pkg); - throw new POIXMLException(e); - } - return pkg; - } - - /** - * Return the underlying XML bean - * - * @return the underlying CTWorkbook bean - */ - @Internal - public CTWorkbook getCTWorkbook() { - return this.workbook; - } - - /** - * Adds a picture to the workbook. - * - * @param pictureData The bytes of the picture - * @param format The format of the picture. - * - * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} . - * @see Workbook#PICTURE_TYPE_EMF - * @see Workbook#PICTURE_TYPE_WMF - * @see Workbook#PICTURE_TYPE_PICT - * @see Workbook#PICTURE_TYPE_JPEG - * @see Workbook#PICTURE_TYPE_PNG - * @see Workbook#PICTURE_TYPE_DIB - * @see #getAllPictures() - */ - @Override - public int addPicture(byte[] pictureData, int format) { - int imageNumber = getAllPictures().size() + 1; - XSSFPictureData img = createRelationship(XSSFPictureData.RELATIONS[format], this.xssfFactory, imageNumber, true).getDocumentPart(); - try (OutputStream out = img.getPackagePart().getOutputStream()) { - out.write(pictureData); - } catch (IOException e) { - throw new POIXMLException(e); - } - pictures.add(img); - return imageNumber - 1; - } - - /** - * Adds a picture to the workbook. - * - * @param is The sream to read image from - * @param format The format of the picture. - * - * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} . - * @see Workbook#PICTURE_TYPE_EMF - * @see Workbook#PICTURE_TYPE_WMF - * @see Workbook#PICTURE_TYPE_PICT - * @see Workbook#PICTURE_TYPE_JPEG - * @see Workbook#PICTURE_TYPE_PNG - * @see Workbook#PICTURE_TYPE_DIB - * @see #getAllPictures() - */ - public int addPicture(InputStream is, int format) throws IOException { - int imageNumber = getAllPictures().size() + 1; - XSSFPictureData img = createRelationship(XSSFPictureData.RELATIONS[format], this.xssfFactory, imageNumber, true).getDocumentPart(); - try (OutputStream out = img.getPackagePart().getOutputStream()) { - IOUtils.copy(is, out); - } - pictures.add(img); - return imageNumber - 1; - } - - /** - * Create an XSSFSheet from an existing sheet in the XSSFWorkbook. - * The cloned sheet is a deep copy of the original. - * - * @param sheetNum The index of the sheet to clone - * @return XSSFSheet representing the cloned sheet. - * @throws IllegalArgumentException if the sheet index in invalid - * @throws POIXMLException if there were errors when cloning - */ - @Override - public XSSFSheet cloneSheet(int sheetNum) { - return cloneSheet(sheetNum, null); - } - - @Override - public void close() throws IOException { - try { - super.close(); - } finally { - IOUtils.closeQuietly(sharedStringSource); - } - } - - /** - * Create an XSSFSheet from an existing sheet in the XSSFWorkbook. - * The cloned sheet is a deep copy of the original but with a new given - * name. - * - * @param sheetNum The index of the sheet to clone - * @param newName The name to set for the newly created sheet - * @return XSSFSheet representing the cloned sheet. - * @throws IllegalArgumentException if the sheet index or the sheet - * name is invalid - * @throws POIXMLException if there were errors when cloning - */ - public XSSFSheet cloneSheet(int sheetNum, String newName) { - validateSheetIndex(sheetNum); - XSSFSheet srcSheet = sheets.get(sheetNum); - - if (newName == null) { - String srcName = srcSheet.getSheetName(); - newName = getUniqueSheetName(srcName); - } else { - validateSheetName(newName); - } - - XSSFSheet clonedSheet = createSheet(newName); - - // copy sheet's relations - List<RelationPart> rels = srcSheet.getRelationParts(); - // if the sheet being cloned has a drawing then remember it and re-create it too - XSSFDrawing dg = null; - for(RelationPart rp : rels) { - POIXMLDocumentPart r = rp.getDocumentPart(); - // do not copy the drawing relationship, it will be re-created - if(r instanceof XSSFDrawing) { - dg = (XSSFDrawing)r; - continue; - } - - addRelation(rp, clonedSheet); - } - - try { - for(PackageRelationship pr : srcSheet.getPackagePart().getRelationships()) { - if (pr.getTargetMode() == TargetMode.EXTERNAL) { - clonedSheet.getPackagePart().addExternalRelationship - (pr.getTargetURI().toASCIIString(), pr.getRelationshipType(), pr.getId()); - } - } - } catch (InvalidFormatException e) { - throw new POIXMLException("Failed to clone sheet", e); - } - - - try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - srcSheet.write(out); - try (ByteArrayInputStream bis = new ByteArrayInputStream(out.toByteArray())) { - clonedSheet.read(bis); - } - } catch (IOException e){ - throw new POIXMLException("Failed to clone sheet", e); - } - CTWorksheet ct = clonedSheet.getCTWorksheet(); - if(ct.isSetLegacyDrawing()) { - LOG.atWarn().log("Cloning sheets with comments is not yet supported."); - ct.unsetLegacyDrawing(); - } - if (ct.isSetPageSetup()) { - LOG.atWarn().log("Cloning sheets with page setup is not yet supported."); - ct.unsetPageSetup(); - } - - clonedSheet.setSelected(false); - - // clone the sheet drawing along with its relationships - if (dg != null) { - if(ct.isSetDrawing()) { - // unset the existing reference to the drawing, - // so that subsequent call of clonedSheet.createDrawingPatriarch() will create a new one - ct.unsetDrawing(); - } - XSSFDrawing clonedDg = clonedSheet.createDrawingPatriarch(); - // copy drawing contents - clonedDg.getCTDrawing().set(dg.getCTDrawing().copy()); - - // Clone drawing relations - List<RelationPart> srcRels = srcSheet.getDrawingPatriarch().getRelationParts(); - for (RelationPart rp : srcRels) { - POIXMLDocumentPart r = rp.getDocumentPart(); - if (r instanceof XSSFChart) { - // Replace chart relation part with new relationship, cloning the chart's content - RelationPart chartPart = clonedDg.createChartRelationPart(); - XSSFChart chart = chartPart.getDocumentPart(); - chart.importContent((XSSFChart)r); - chart.replaceReferences(clonedSheet); - } else { - addRelation(rp, clonedDg); - } - } - } - return clonedSheet; - } - - /** - * @since 3.14-Beta1 - */ - private static void addRelation(RelationPart rp, POIXMLDocumentPart target) { - PackageRelationship rel = rp.getRelationship(); - if (rel.getTargetMode() == TargetMode.EXTERNAL) { - target.getPackagePart().addRelationship( - rel.getTargetURI(), rel.getTargetMode(), rel.getRelationshipType(), rel.getId()); - } else { - XSSFRelation xssfRel = XSSFRelation.getInstance(rel.getRelationshipType()); - if (xssfRel == null) { - // Don't copy all relations blindly, but only the ones we know about - throw new POIXMLException("Can't clone sheet - unknown relation type found: "+rel.getRelationshipType()); - } - target.addRelation(rel.getId(), xssfRel, rp.getDocumentPart()); - } - } - - /** - * Generate a valid sheet name based on the existing one. Used when cloning sheets. - * - * @param srcName the original sheet name to - * @return clone sheet name - */ - private String getUniqueSheetName(String srcName) { - int uniqueIndex = 2; - String baseName = srcName; - int bracketPos = srcName.lastIndexOf('('); - if (bracketPos > 0 && srcName.endsWith(")")) { - String suffix = srcName.substring(bracketPos + 1, srcName.length() - ")".length()); - try { - uniqueIndex = Integer.parseInt(suffix.trim()); - uniqueIndex++; - baseName = srcName.substring(0, bracketPos).trim(); - } catch (NumberFormatException e) { - // contents of brackets not numeric - } - } - while (true) { - // Try and find the next sheet name that is unique - String index = Integer.toString(uniqueIndex++); - String name; - if (baseName.length() + index.length() + 2 < 31) { - name = baseName + " (" + index + ")"; - } else { - name = baseName.substring(0, 31 - index.length() - 2) + "(" + index + ")"; - } - - //If the sheet name is unique, then set it otherwise move on to the next number. - if (getSheetIndex(name) == -1) { - return name; - } - } - } - - /** - * Create a new XSSFCellStyle and add it to the workbook's style table - * - * @return the new XSSFCellStyle object - */ - @Override - public XSSFCellStyle createCellStyle() { - return stylesSource.createCellStyle(); - } - - /** - * Returns the workbook's data format table (a factory for creating data format strings). - * - * @return the XSSFDataFormat object - * @see DataFormat - */ - @Override - public XSSFDataFormat createDataFormat() { - if (formatter == null) { - formatter = new XSSFDataFormat(stylesSource); - } - return formatter; - } - - /** - * Create a new Font and add it to the workbook's font table - * - * @return new font object - */ - @Override - public XSSFFont createFont() { - XSSFFont font = new XSSFFont(); - font.registerTo(stylesSource); - return font; - } - - @Override - public XSSFName createName() { - CTDefinedName ctName = CTDefinedName.Factory.newInstance(); - ctName.setName(""); - return createAndStoreName(ctName); - } - - private XSSFName createAndStoreName(CTDefinedName ctName) { - XSSFName name = new XSSFName(ctName, this); - namedRanges.add(name); - namedRangesByName.put(ctName.getName().toLowerCase(Locale.ENGLISH), name); - return name; - } - - /** - * Create an XSSFSheet for this workbook, adds it to the sheets and returns - * the high level representation. Use this to create new sheets. - * - * @return XSSFSheet representing the new sheet. - */ - @Override - public XSSFSheet createSheet() { - String sheetname = "Sheet" + (sheets.size()); - int idx = 0; - while(getSheet(sheetname) != null) { - sheetname = "Sheet" + idx; - idx++; - } - return createSheet(sheetname); - } - - /** - * Create a new sheet for this Workbook and return the high level representation. - * Use this to create new sheets. - * - * <p> - * Note that Excel allows sheet names up to 31 chars in length but other applications - * (such as OpenOffice) allow more. Some versions of Excel crash with names longer than 31 chars, - * others - truncate such names to 31 character. - * </p> - * <p> - * POI's SpreadsheetAPI silently truncates the input argument to 31 characters. - * Example: - * - * <pre><code> - * Sheet sheet = workbook.createSheet("My very long sheet name which is longer than 31 chars"); // will be truncated - * assert 31 == sheet.getSheetName().length(); - * assert "My very long sheet name which i" == sheet.getSheetName(); - * </code></pre> - * </p> - * - * Except the 31-character constraint, Excel applies some other rules: - * <p> - * Sheet name MUST be unique in the workbook and MUST NOT contain the any of the following characters: - * <ul> - * <li> 0x0000 </li> - * <li> 0x0003 </li> - * <li> colon (:) </li> - * <li> backslash (\) </li> - * <li> asterisk (*) </li> - * <li> question mark (?) </li> - * <li> forward slash (/) </li> - * <li> opening square bracket ([) </li> - * <li> closing square bracket (]) </li> - * </ul> - * The string MUST NOT begin or end with the single quote (') character. - * </p> - * - * <p> - * See {@link WorkbookUtil#createSafeSheetName(String nameProposal)} - * for a safe way to create valid names - * </p> - * @param sheetname sheetname to set for the sheet. - * @return Sheet representing the new sheet. - * @throws IllegalArgumentException if the name is null or invalid - * or workbook already contains a sheet with this name - * @see WorkbookUtil#createSafeSheetName(String nameProposal) - */ - @Override - public XSSFSheet createSheet(String sheetname) { - if (sheetname == null) { - throw new IllegalArgumentException("sheetName must not be null"); - } - - validateSheetName(sheetname); - - // YK: Mimic Excel and silently truncate sheet names longer than 31 characters - if(sheetname.length() > 31) { - sheetname = sheetname.substring(0, 31); - } - WorkbookUtil.validateSheetName(sheetname); - - CTSheet sheet = addSheet(sheetname); - - int sheetNumber = 1; - outerloop: - while(true) { - for(XSSFSheet sh : sheets) { - sheetNumber = (int)Math.max(sh.sheet.getSheetId() + 1, sheetNumber); - } - - // Bug 57165: We also need to check that the resulting file name is not already taken - // this can happen when moving/cloning sheets - String sheetName = XSSFRelation.WORKSHEET.getFileName(sheetNumber); - for(POIXMLDocumentPart relation : getRelations()) { - if(relation.getPackagePart() != null && - sheetName.equals(relation.getPackagePart().getPartName().getName())) { - // name is taken => try next one - sheetNumber++; - continue outerloop; - } - } - - // no duplicate found => use this one - break; - } - - RelationPart rp = createRelationship(XSSFRelation.WORKSHEET, this.xssfFactory, sheetNumber, false); - XSSFSheet wrapper = rp.getDocumentPart(); - wrapper.sheet = sheet; - sheet.setId(rp.getRelationship().getId()); - sheet.setSheetId(sheetNumber); - if (sheets.isEmpty()) { - wrapper.setSelected(true); - } - sheets.add(wrapper); - return wrapper; - } - - private void validateSheetName(final String sheetName) throws IllegalArgumentException { - if (containsSheet( sheetName, sheets.size() )) { - throw new IllegalArgumentException("The workbook already contains a sheet named '" + sheetName + "'"); - } - } - - protected XSSFDialogsheet createDialogsheet(String sheetname, CTDialogsheet dialogsheet) { - XSSFSheet sheet = createSheet(sheetname); - return new XSSFDialogsheet(sheet); - } - - private CTSheet addSheet(String sheetname) { - CTSheet sheet = workbook.getSheets().addNewSheet(); - sheet.setName(sheetname); - return sheet; - } - - /** - * Finds a font that matches the one with the supplied attributes - * - * @return the font with the matched attributes or <code>null</code> - */ - @Override - public XSSFFont findFont(boolean bold, short color, short fontHeight, String name, boolean italic, boolean strikeout, short typeOffset, byte underline) { - return stylesSource.findFont(bold, color, fontHeight, name, italic, strikeout, typeOffset, underline); - } - - /** - * Convenience method to get the active sheet. The active sheet is is the sheet - * which is currently displayed when the workbook is viewed in Excel. - * 'Selected' sheet(s) is a distinct concept. - */ - @Override - public int getActiveSheetIndex() { - //activeTab (Active Sheet Index) Specifies an unsignedInt - //that contains the index to the active sheet in this book view. - return (int)workbook.getBookViews().getWorkbookViewArray(0).getActiveTab(); - } - - /** - * Gets all pictures from the Workbook. - * - * @return the list of pictures (a list of {@link XSSFPictureData} objects.) - * @see #addPicture(byte[], int) - */ - @Override - public List<XSSFPictureData> getAllPictures() { - if(pictures == null){ - List<PackagePart> mediaParts = getPackage().getPartsByName(Pattern.compile("/xl/media/.*?")); - pictures = new ArrayList<>(mediaParts.size()); - for(PackagePart part : mediaParts){ - pictures.add(new XSSFPictureData(part)); - } - } - return pictures; //YK: should return Collections.unmodifiableList(pictures); - } - - /** - * Get the cell style object at the given index - * - * @param idx index within the set of styles - * @return XSSFCellStyle object at the index - */ - @Override - public XSSFCellStyle getCellStyleAt(int idx) { - return stylesSource.getStyleAt(idx); - } - - @Override - public XSSFFont getFontAt(int idx) { - return stylesSource.getFontAt(idx); - } - - /** - * Get the first named range with the given name. - * - * Note: names of named ranges are not unique as they are scoped by sheet. - * {@link #getNames(String name)} returns all named ranges with the given name. - * - * @param name named range name - * @return XSSFName with the given name. <code>null</code> is returned no named range could be found. - */ - @Override - public XSSFName getName(String name) { - Collection<XSSFName> list = getNames(name); - if (list.isEmpty()) { - return null; - } - return list.iterator().next(); - } - - /** - * Get the named ranges with the given name. - * <i>Note:</i>Excel named ranges are case-insensitive and - * this method performs a case-insensitive search. - * - * @param name named range name - * @return list of XSSFNames with the given name. An empty list if no named ranges could be found - */ - @Override - public List<XSSFName> getNames(String name) { - return Collections.unmodifiableList(namedRangesByName.get(name.toLowerCase(Locale.ENGLISH))); - } - - /** - * Get the named range at the given index. No longer public and only used in tests. - * - * @param nameIndex the index of the named range - * @return the XSSFName at the given index - */ - @Deprecated - XSSFName getNameAt(int nameIndex) { - int nNames = namedRanges.size(); - if (nNames < 1) { - throw new IllegalStateException("There are no defined names in this workbook"); - } - if (nameIndex < 0 || nameIndex > nNames) { - throw new IllegalArgumentException("Specified name index " + nameIndex - + " is outside the allowable range (0.." + (nNames-1) + ")."); - } - return namedRanges.get(nameIndex); - } - - /** - * Get a list of all the named ranges in the workbook. - * - * @return list of XSSFNames in the workbook - */ - @Override - public List<XSSFName> getAllNames() { - return Collections.unmodifiableList(namedRanges); - } - - /** - * Gets the named range index by name. No longer public and only used in tests. - * - * @param name named range name - * @return named range index. <code>-1</code> is returned if no named ranges could be found. - * - * @deprecated 3.16. New projects should avoid accessing named ranges by index. - * Use {@link #getName(String)} instead. - */ - @Deprecated - int getNameIndex(String name) { - XSSFName nm = getName(name); - if (nm != null) { - return namedRanges.indexOf(nm); - } - return -1; - } - - /** - * Get the number of styles the workbook contains - * - * @return count of cell styles - */ - @Override - public int getNumCellStyles() { - return stylesSource.getNumCellStyles(); - } - - @Override - public int getNumberOfFonts() { - return stylesSource.getFonts().size(); - } - - @Override - @Deprecated - @Removal(version = "6.0.0") - public int getNumberOfFontsAsInt() { - return getNumberOfFonts(); - } - - /** - * Get the number of named ranges in the this workbook - * - * @return number of named ranges - */ - @Override - public int getNumberOfNames() { - return namedRanges.size(); - } - - /** - * Get the number of worksheets in the this workbook - * - * @return number of worksheets - */ - @Override - public int getNumberOfSheets() { - return sheets.size(); - } - - /** - * Retrieves the reference for the printarea of the specified sheet, the sheet name is appended to the reference even if it was not specified. - * @param sheetIndex Zero-based sheet index (0 Represents the first sheet to keep consistent with java) - * @return String Null if no print area has been defined - */ - @Override - public String getPrintArea(int sheetIndex) { - XSSFName name = getBuiltInName(XSSFName.BUILTIN_PRINT_AREA, sheetIndex); - if (name == null) { - return null; - } - //adding one here because 0 indicates a global named region; doesnt make sense for print areas - return name.getRefersToFormula(); - - } - - /** - * Get sheet with the given name (case insensitive match) - * - * @param name of the sheet - * @return XSSFSheet with the name provided or <code>null</code> if it does not exist - */ - @Override - public XSSFSheet getSheet(String name) { - for (XSSFSheet sheet : sheets) { - if (name.equalsIgnoreCase(sheet.getSheetName())) { - return sheet; - } - } - return null; - } - - /** - * Get the XSSFSheet object at the given index. - * - * @param index of the sheet number (0-based physical & logical) - * @return XSSFSheet at the provided index - * @throws IllegalArgumentException if the index is out of range (index - * < 0 || index >= getNumberOfSheets()). - */ - @Override - public XSSFSheet getSheetAt(int index) { - validateSheetIndex(index); - return sheets.get(index); - } - - /** - * Returns the index of the sheet by his name (case insensitive match) - * - * @param name the sheet name - * @return index of the sheet (0 based) or <tt>-1</tt> if not found - */ - @Override - public int getSheetIndex(String name) { - int idx = 0; - for (XSSFSheet sh : sheets) { - if (name.equalsIgnoreCase(sh.getSheetName())) { - return idx; - } - idx++; - } - return -1; - } - - /** - * Returns the index of the given sheet - * - * @param sheet the sheet to look up - * @return index of the sheet (0 based). <tt>-1</tt> if not found - */ - @Override - public int getSheetIndex(Sheet sheet) { - int idx = 0; - for(XSSFSheet sh : sheets){ - if(sh == sheet) { - return idx; - } - idx++; - } - return -1; - } - - /** - * Get the sheet name - * - * @param sheetIx Number - * @return Sheet name - */ - @Override - public String getSheetName(int sheetIx) { - validateSheetIndex(sheetIx); - return sheets.get(sheetIx).getSheetName(); - } - - /** - * Returns an iterator of the sheets in the workbook - * in sheet order. Includes hidden and very hidden sheets. - * - * Note: remove() is not supported on this iterator. - * Use {@link #removeSheetAt(int)} to remove sheets instead. - * - * @return an iterator of the sheets. - */ - @Override - public Iterator<Sheet> sheetIterator() { - return new SheetIterator<>(); - } - - /** - * Alias for {@link #sheetIterator()} to allow - * foreach loops - * - * Note: remove() is not supported on this iterator. - * Use {@link #removeSheetAt(int)} to remove sheets instead. - * - * @return an iterator of the sheets. - */ - @Override - public Iterator<Sheet> iterator() { - return sheetIterator(); - } - - private final class SheetIterator<T extends Sheet> implements Iterator<T> { - final private Iterator<T> it; - @SuppressWarnings("unchecked") - public SheetIterator() { - it = (Iterator<T>) sheets.iterator(); - } - @Override - public boolean hasNext() { - return it.hasNext(); - } - @Override - public T next() throws NoSuchElementException { - return it.next(); - } - /** - * Unexpected behavior may occur if sheets are reordered after iterator - * has been created. Support for the remove method may be added in the future - * if someone can figure out a reliable implementation. - */ - @Override - public void remove() throws IllegalStateException { - throw new UnsupportedOperationException("remove method not supported on XSSFWorkbook.iterator(). "+ - "Use Sheet.removeSheetAt(int) instead."); - } - } - - /** - * Are we a normal workbook (.xlsx), or a - * macro enabled workbook (.xlsm)? - */ - public boolean isMacroEnabled() { - return getPackagePart().getContentType().equals(XSSFRelation.MACROS_WORKBOOK.getContentType()); - } - - /** - * @param name the name to remove. - * - * @throws IllegalArgumentException if the named range is not a part of this XSSFWorkbook - */ - @Override - public void removeName(Name name) { - if (!namedRangesByName.removeMapping(name.getNameName().toLowerCase(Locale.ENGLISH), name) - || !namedRanges.remove(name)) { - throw new IllegalArgumentException("Name was not found: " + name); - } - } - - void updateName(XSSFName name, String oldName) { - if (!namedRangesByName.removeMapping(oldName.toLowerCase(Locale.ENGLISH), name)) { - throw new IllegalArgumentException("Name was not found: " + name); - } - namedRangesByName.put(name.getNameName().toLowerCase(Locale.ENGLISH), name); - } - - - /** - * Delete the printarea for the sheet specified - * - * @param sheetIndex 0-based sheet index (0 = First Sheet) - */ - @Override - public void removePrintArea(int sheetIndex) { - XSSFName name = getBuiltInName(XSSFName.BUILTIN_PRINT_AREA, sheetIndex); - if (name != null) { - removeName(name); - } - } - - /** - * Removes sheet at the given index.<p> - * - * Care must be taken if the removed sheet is the currently active or only selected sheet in - * the workbook. There are a few situations when Excel must have a selection and/or active - * sheet. (For example when printing - see Bug 40414).<br> - * - * This method makes sure that if the removed sheet was active, another sheet will become - * active in its place. Furthermore, if the removed sheet was the only selected sheet, another - * sheet will become selected. The newly active/selected sheet will have the same index, or - * one less if the removed sheet was the last in the workbook. - * - * @param index of the sheet (0-based) - */ - @Override - public void removeSheetAt(int index) { - validateSheetIndex(index); - - onSheetDelete(index); - - XSSFSheet sheet = getSheetAt(index); - removeRelation(sheet); - sheets.remove(index); - - // only set new sheet if there are still some left - if(sheets.size() == 0) { - return; - } - - // the index of the closest remaining sheet to the one just deleted - int newSheetIndex = index; - if (newSheetIndex >= sheets.size()) { - newSheetIndex = sheets.size()-1; - } - - // adjust active sheet - int active = getActiveSheetIndex(); - if(active == index) { - // removed sheet was the active one, reset active sheet if there is still one left now - setActiveSheet(newSheetIndex); - } else if (active > index) { - // removed sheet was below the active one => active is one less now - setActiveSheet(active-1); - } - } - - /** - * Gracefully remove references to the sheet being deleted - * - * @param index the 0-based index of the sheet to delete - */ - private void onSheetDelete(int index) { - // remove all sheet relations - final XSSFSheet sheet = getSheetAt(index); - - sheet.onSheetDelete(); - - //delete the CTSheet reference from workbook.xml - workbook.getSheets().removeSheet(index); - - //calculation chain is auxiliary, remove it as it may contain orphan references to deleted cells - if(calcChain != null) { - removeRelation(calcChain); - calcChain = null; - } - - //adjust indices of names ranges - List<XSSFName> toRemove = new ArrayList<>(); - for (XSSFName nm : namedRanges) { - CTDefinedName ct = nm.getCTName(); - if(!ct.isSetLocalSheetId()) { - continue; - } - if (ct.getLocalSheetId() == index) { - toRemove.add(nm); - } else if (ct.getLocalSheetId() > index){ - // Bump down by one, so still points at the same sheet - ct.setLocalSheetId(ct.getLocalSheetId()-1); - } - } - for (XSSFName nm : toRemove) { - removeName(nm); - } - } - - /** - * Retrieves the current policy on what to do when - * getting missing or blank cells from a row. - * The default is to return blank and null cells. - * {@link MissingCellPolicy} - */ - @Override - public MissingCellPolicy getMissingCellPolicy() { - return _missingCellPolicy; - } - /** - * Sets the policy on what to do when - * getting missing or blank cells from a row. - * This will then apply to all calls to - * {@link Row#getCell(int)}}. See - * {@link MissingCellPolicy} - */ - @Override - public void setMissingCellPolicy(MissingCellPolicy missingCellPolicy) { - _missingCellPolicy = missingCellPolicy; - } - - /** - * Convenience method to set the active sheet. The active sheet is is the sheet - * which is currently displayed when the workbook is viewed in Excel. - * 'Selected' sheet(s) is a distinct concept. - */ - @Override - public void setActiveSheet(int index) { - - validateSheetIndex(index); - - for (CTBookView arrayBook : workbook.getBookViews().getWorkbookViewArray()) { - arrayBook.setActiveTab(index); - } - } - - /** - * Validate sheet index - * - * @param index the index to validate - * @throws IllegalArgumentException if the index is out of range (index - * < 0 || index >= getNumberOfSheets()). - */ - private void validateSheetIndex(int index) { - int lastSheetIx = sheets.size() - 1; - if (index < 0 || index > lastSheetIx) { - String range = "(0.." + lastSheetIx + ")"; - if (lastSheetIx == -1) { - range = "(no sheets)"; - } - throw new IllegalArgumentException("Sheet index (" - + index +") is out of range " + range); - } - } - - /** - * Gets the first tab that is displayed in the list of tabs in excel. - * - * @return integer that contains the index to the active sheet in this book view. - */ - @Override - public int getFirstVisibleTab() { - CTBookViews bookViews = workbook.getBookViews(); - CTBookView bookView = bookViews.getWorkbookViewArray(0); - return (short) bookView.getFirstSheet(); - } - - /** - * Sets the first tab that is displayed in the list of tabs in excel. - * - * @param index integer that contains the index to the active sheet in this book view. - */ - @Override - public void setFirstVisibleTab(int index) { - CTBookViews bookViews = workbook.getBookViews(); - CTBookView bookView= bookViews.getWorkbookViewArray(0); - bookView.setFirstSheet(index); - } - - /** - * Sets the printarea for the sheet provided - * <p> - * i.e. Reference = $A$1:$B$2 - * @param sheetIndex Zero-based sheet index (0 Represents the first sheet to keep consistent with java) - * @param reference Valid name Reference for the Print Area - */ - @Override - public void setPrintArea(int sheetIndex, String reference) { - XSSFName name = getBuiltInName(XSSFName.BUILTIN_PRINT_AREA, sheetIndex); - if (name == null) { - name = createBuiltInName(XSSFName.BUILTIN_PRINT_AREA, sheetIndex); - } - //short externSheetIndex = getWorkbook().checkExternSheet(sheetIndex); - //name.setExternSheetNumber(externSheetIndex); - String[] parts = COMMA_PATTERN.split(reference); - StringBuilder sb = new StringBuilder(32); - for (int i = 0; i < parts.length; i++) { - if(i>0) { - sb.append(','); - } - SheetNameFormatter.appendFormat(sb, getSheetName(sheetIndex)); - sb.append('!'); - sb.append(parts[i]); - } - name.setRefersToFormula(sb.toString()); - } - - /** - * For the Convenience of Java Programmers maintaining pointers. - * @see #setPrintArea(int, String) - * @param sheetIndex Zero-based sheet index (0 = First Sheet) - * @param startColumn Column to begin printarea - * @param endColumn Column to end the printarea - * @param startRow Row to begin the printarea - * @param endRow Row to end the printarea - */ - @Override - public void setPrintArea(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow) { - String reference=getReferencePrintArea(getSheetName(sheetIndex), startColumn, endColumn, startRow, endRow); - setPrintArea(sheetIndex, reference); - } - - private static String getReferencePrintArea(String sheetName, int startC, int endC, int startR, int endR) { - //windows excel example: Sheet1!$C$3:$E$4 - CellReference colRef = new CellReference(sheetName, startR, startC, true, true); - CellReference colRef2 = new CellReference(sheetName, endR, endC, true, true); - - return "$" + colRef.getCellRefParts()[2] + "$" + colRef.getCellRefParts()[1] + ":$" + colRef2.getCellRefParts()[2] + "$" + colRef2.getCellRefParts()[1]; - } - - XSSFName getBuiltInName(String builtInCode, int sheetNumber) { - for (XSSFName name : namedRangesByName.get(builtInCode.toLowerCase(Locale.ENGLISH))) { - if (name.getSheetIndex() == sheetNumber) { - return name; - } - } - return null; - } - - /** - * Generates a NameRecord to represent a built-in region - * - * @return a new NameRecord - * @throws IllegalArgumentException if sheetNumber is invalid - * @throws POIXMLException if such a name already exists in the workbook - */ - XSSFName createBuiltInName(String builtInName, int sheetNumber) { - validateSheetIndex(sheetNumber); - - CTDefinedNames names = workbook.getDefinedNames() == null ? workbook.addNewDefinedNames() : workbook.getDefinedNames(); - CTDefinedName nameRecord = names.addNewDefinedName(); - nameRecord.setName(builtInName); - nameRecord.setLocalSheetId(sheetNumber); - - if (getBuiltInName(builtInName, sheetNumber) != null) { - throw new POIXMLException("Builtin (" + builtInName - + ") already exists for sheet (" + sheetNumber + ")"); - } - - return createAndStoreName(nameRecord); - } - - /** - * We only set one sheet as selected for compatibility with HSSF. - */ - @Override - public void setSelectedTab(int index) { - int idx = 0; - for (XSSFSheet sh : sheets) { - sh.setSelected(idx == index); - idx++; - } - } - - /** - * Set the sheet name. - * - * @param sheetIndex sheet number (0 based) - * @param sheetname the new sheet name - * @throws IllegalArgumentException if the name is null or invalid - * or workbook already contains a sheet with this name - * @see #createSheet(String) - * @see WorkbookUtil#createSafeSheetName(String nameProposal) - */ - @Override - public void setSheetName(int sheetIndex, String sheetname) { - if (sheetname == null) { - throw new IllegalArgumentException( "sheetName must not be null" ); - } - - validateSheetIndex(sheetIndex); - String oldSheetName = getSheetName(sheetIndex); - - // YK: Mimic Excel and silently truncate sheet names longer than 31 characters - if(sheetname.length() > 31) { - sheetname = sheetname.substring(0, 31); - } - WorkbookUtil.validateSheetName(sheetname); - - // Do nothing if no change - if (sheetname.equals(oldSheetName)) { - return; - } - - // Check it isn't already taken - if (containsSheet(sheetname, sheetIndex )) { - throw new IllegalArgumentException( "The workbook already contains a sheet of this name" ); - } - - // Update references to the name - XSSFFormulaUtils utils = new XSSFFormulaUtils(this); - utils.updateSheetName(sheetIndex, oldSheetName, sheetname); - - workbook.getSheets().getSheetArray(sheetIndex).setName(sheetname); - } - - /** - * sets the order of appearance for a given sheet. - * - * @param sheetname the name of the sheet to reorder - * @param pos the position that we want to insert the sheet into (0 based) - */ - @Override - public void setSheetOrder(String sheetname, int pos) { - int idx = getSheetIndex(sheetname); - sheets.add(pos, sheets.remove(idx)); - - // Reorder CTSheets - CTSheets ct = workbook.getSheets(); - XmlObject cts = ct.getSheetArray(idx).copy(); - workbook.getSheets().removeSheet(idx); - CTSheet newcts = ct.insertNewSheet(pos); - newcts.set(cts); - - //notify sheets - CTSheet[] sheetArray = ct.getSheetArray(); - for(int i=0; i < sheetArray.length; i++) { - sheets.get(i).sheet = sheetArray[i]; - } - - updateNamedRangesAfterSheetReorder(idx, pos); - updateActiveSheetAfterSheetReorder(idx, pos); - } - - /** - * update sheet-scoped named ranges in this workbook after changing the sheet order - * of a sheet at oldIndex to newIndex. - * Sheets between these indices will move left or right by 1. - * - * @param oldIndex the original index of the re-ordered sheet - * @param newIndex the new index of the re-ordered sheet - */ - private void updateNamedRangesAfterSheetReorder(int oldIndex, int newIndex) { - // update sheet index of sheet-scoped named ranges - for (final XSSFName name : namedRanges) { - final int i = name.getSheetIndex(); - // name has sheet-level scope - if (i != -1) { - // name refers to this sheet - if (i == oldIndex) { - name.setSheetIndex(newIndex); - } - // if oldIndex > newIndex then this sheet moved left and sheets between newIndex and oldIndex moved right - else if (newIndex <= i && i < oldIndex) { - name.setSheetIndex(i+1); - } - // if oldIndex < newIndex then this sheet moved right and sheets between oldIndex and newIndex moved left - else if (oldIndex < i && i <= newIndex) { - name.setSheetIndex(i-1); - } - } - } - } - - private void updateActiveSheetAfterSheetReorder(int oldIndex, int newIndex) { - // adjust active sheet if necessary - int active = getActiveSheetIndex(); - if(active == oldIndex) { - // moved sheet was the active one - setActiveSheet(newIndex); - } else if ((active < oldIndex && active < newIndex) || - (active > oldIndex && active > newIndex)) { - // not affected - } else if (newIndex > oldIndex) { - // moved sheet was below before and is above now => active is one less - setActiveSheet(active-1); - } else { - // remaining case: moved sheet was higher than active before and is lower now => active is one more - setActiveSheet(active+1); - } - } - - /** - * marshal named ranges from the {@link #namedRanges} collection to the underlying CTWorkbook bean - */ - private void saveNamedRanges(){ - // Named ranges - if(namedRanges.size() > 0) { - CTDefinedNames names = CTDefinedNames.Factory.newInstance(); - CTDefinedName[] nr = new CTDefinedName[namedRanges.size()]; - int i = 0; - for(XSSFName name : namedRanges) { - nr[i] = name.getCTName(); - i++; - } - names.setDefinedNameArray(nr); - if(workbook.isSetDefinedNames()) { - workbook.unsetDefinedNames(); - } - workbook.setDefinedNames(names); - - // Re-process the named ranges - reprocessNamedRanges(); - } else { - if(workbook.isSetDefinedNames()) { - workbook.unsetDefinedNames(); - } - } - } - - private void reprocessNamedRanges() { - namedRangesByName = new ArrayListValuedHashMap<>(); - namedRanges = new ArrayList<>(); - if(workbook.isSetDefinedNames()) { - for(CTDefinedName ctName : workbook.getDefinedNames().getDefinedNameArray()) { - createAndStoreName(ctName); - } - } - } - - private void saveCalculationChain(){ - if(calcChain != null){ - int count = calcChain.getCTCalcChain().sizeOfCArray(); - if(count == 0){ - removeRelation(calcChain); - calcChain = null; - } - } - } - - @Override - protected void commit() throws IOException { - saveNamedRanges(); - saveCalculationChain(); - - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorkbook.type.getName().getNamespaceURI(), "workbook")); - - PackagePart part = getPackagePart(); - try (OutputStream out = part.getOutputStream()) { - workbook.save(out, xmlOptions); - } - } - - /** - * Returns SharedStringsTable - tha cache of string for this workbook - * - * @return the shared string table - */ - @Internal - public SharedStringsTable getSharedStringSource() { - return this.sharedStringSource; - } - - /** - * Return a object representing a collection of shared objects used for styling content, - * e.g. fonts, cell styles, colors, etc. - */ - public StylesTable getStylesSource() { - return this.stylesSource; - } - - /** - * Returns the Theme of current workbook. - */ - public ThemesTable getTheme() { - if (stylesSource == null) { - return null; - } - return stylesSource.getTheme(); - } - - /** - * Returns an object that handles instantiating concrete - * classes of the various instances for XSSF. - */ - @Override - public XSSFCreationHelper getCreationHelper() { - if(_creationHelper == null) { - _creationHelper = new XSSFCreationHelper(this); - } - return _creationHelper; - } - - /** - * Determines whether a workbook contains the provided sheet name. - * For the purpose of comparison, long names are truncated to 31 chars. - * - * @param name the name to test (case insensitive match) - * @param excludeSheetIdx the sheet to exclude from the check or -1 to include all sheets in the check. - * @return true if the sheet contains the name, false otherwise. - */ - private boolean containsSheet(String name, int excludeSheetIdx) { - CTSheet[] ctSheetArray = workbook.getSheets().getSheetArray(); - - if (name.length() > MAX_SENSITIVE_SHEET_NAME_LEN) { - name = name.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN); - } - - for (int i = 0; i < ctSheetArray.length; i++) { - String ctName = ctSheetArray[i].getName(); - if (ctName.length() > MAX_SENSITIVE_SHEET_NAME_LEN) { - ctName = ctName.substring(0, MAX_SENSITIVE_SHEET_NAME_LEN); - } - - if (excludeSheetIdx != i && name.equalsIgnoreCase(ctName)) { - return true; - } - } - return false; - } - - /** - * Gets a boolean value that indicates whether the date systems used in the workbook starts in 1904. - * <p> - * The default value is false, meaning that the workbook uses the 1900 date system, - * where 1/1/1900 is the first day in the system.. - * </p> - * @return true if the date systems used in the workbook starts in 1904 - */ - @Internal - @Override - public boolean isDate1904() { - CTWorkbookPr workbookPr = workbook.getWorkbookPr(); - return workbookPr != null && workbookPr.getDate1904(); - } - - /** - * Get the document's embedded files. - */ - @Override - public List<PackagePart> getAllEmbeddedParts() throws OpenXML4JException { - List<PackagePart> embedds = new LinkedList<>(); - - for(XSSFSheet sheet : sheets){ - // Get the embeddings for the workbook - for(PackageRelationship rel : sheet.getPackagePart().getRelationshipsByType(XSSFRelation.OLEEMBEDDINGS.getRelation())) { - embedds.add( sheet.getPackagePart().getRelatedPart(rel) ); - } - - for(PackageRelationship rel : sheet.getPackagePart().getRelationshipsByType(XSSFRelation.PACKEMBEDDINGS.getRelation())) { - embedds.add( sheet.getPackagePart().getRelatedPart(rel) ); - } - } - return embedds; - } - - @Override - @NotImplemented - public boolean isHidden() { - throw new RuntimeException("Not implemented yet"); - } - - @Override - @NotImplemented - public void setHidden(boolean hiddenFlag) { - throw new RuntimeException("Not implemented yet"); - } - - @Override - public boolean isSheetHidden(int sheetIx) { - validateSheetIndex(sheetIx); - CTSheet ctSheet = sheets.get(sheetIx).sheet; - return ctSheet.getState() == STSheetState.HIDDEN; - } - - @Override - public boolean isSheetVeryHidden(int sheetIx) { - validateSheetIndex(sheetIx); - CTSheet ctSheet = sheets.get(sheetIx).sheet; - return ctSheet.getState() == STSheetState.VERY_HIDDEN; - } - - @Override - public SheetVisibility getSheetVisibility(int sheetIx) { - validateSheetIndex(sheetIx); - final CTSheet ctSheet = sheets.get(sheetIx).sheet; - final STSheetState.Enum state = ctSheet.getState(); - if (state == STSheetState.VISIBLE) { - return SheetVisibility.VISIBLE; - } - if (state == STSheetState.HIDDEN) { - return SheetVisibility.HIDDEN; - } - if (state == STSheetState.VERY_HIDDEN) { - return SheetVisibility.VERY_HIDDEN; - } - throw new IllegalArgumentException("This should never happen"); - } - - @Override - public void setSheetHidden(int sheetIx, boolean hidden) { - setSheetVisibility(sheetIx, hidden ? SheetVisibility.HIDDEN : SheetVisibility.VISIBLE); - } - - @Override - public void setSheetVisibility(int sheetIx, SheetVisibility visibility) { - validateSheetIndex(sheetIx); - - final CTSheet ctSheet = sheets.get(sheetIx).sheet; - switch (visibility) { - case VISIBLE: - ctSheet.setState(STSheetState.VISIBLE); - break; - case HIDDEN: - ctSheet.setState(STSheetState.HIDDEN); - break; - case VERY_HIDDEN: - ctSheet.setState(STSheetState.VERY_HIDDEN); - break; - default: - throw new IllegalArgumentException("This should never happen"); - } - } - - - - - /** - * Fired when a formula is deleted from this workbook, - * for example when calling cell.setCellFormula(null) - * - * @see XSSFCell#setCellFormula(String) - */ - protected void onDeleteFormula(XSSFCell cell){ - if(calcChain != null) { - int sheetId = (int)cell.getSheet().sheet.getSheetId(); - calcChain.removeItem(sheetId, cell.getReference()); - } - } - - /** - * Return the {@link CalculationChain} object for this workbook - * <p> - * The calculation chain object specifies the order in which the cells in a workbook were last calculated - * </p> - * - * @return the <code>CalculationChain</code> object or <code>null</code> if not defined - */ - @Internal - public CalculationChain getCalculationChain() { - return calcChain; - } - - /** - * Returns the list of {@link ExternalLinksTable} object for this workbook - * - * <p>The external links table specifies details of named ranges etc - * that are referenced from other workbooks, along with the last seen - * values of what they point to.</p> - * - * <p>Note that Excel uses index 0 for the current workbook, so the first - * External Links in a formula would be '[1]Foo' which corresponds to - * entry 0 in this list.</p> - - * @return the <code>ExternalLinksTable</code> list, which may be empty - */ - @Internal - public List<ExternalLinksTable> getExternalLinksTable() { - return externalLinks; - } - - /** - * - * @return a collection of custom XML mappings defined in this workbook - */ - public Collection<XSSFMap> getCustomXMLMappings(){ - return mapInfo == null ? new ArrayList<>() : mapInfo.getAllXSSFMaps(); - } - - /** - * - * @return the helper class used to query the custom XML mapping defined in this workbook - */ - @Internal - public MapInfo getMapInfo(){ - return mapInfo; - } - - /** - * Adds the External Link Table part and relations required to allow formulas - * referencing the specified external workbook to be added to this one. Allows - * formulas such as "[MyOtherWorkbook.xlsx]Sheet3!$A$5" to be added to the - * file, for workbooks not already linked / referenced. - * - * Note: this is not implemented and thus currently throws an Exception stating this. - * - * @param name The name the workbook will be referenced as in formulas - * @param workbook The open workbook to fetch the link required information from - * - * @throws RuntimeException stating that this method is not implemented yet. - */ - @Override - @NotImplemented - public int linkExternalWorkbook(String name, Workbook workbook) { - throw new RuntimeException("Not Implemented - see bug #57184"); - } - - /** - * Specifies a boolean value that indicates whether structure of workbook is locked. <br> - * A value true indicates the structure of the workbook is locked. Worksheets in the workbook can't be moved, - * deleted, hidden, unhidden, or renamed, and new worksheets can't be inserted.<br> - * A value of false indicates the structure of the workbook is not locked.<br> - * - * @return true if structure of workbook is locked - */ - public boolean isStructureLocked() { - return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockStructure(); - } - - /** - * Specifies a boolean value that indicates whether the windows that comprise the workbook are locked. <br> - * A value of true indicates the workbook windows are locked. Windows are the same size and position each time the - * workbook is opened.<br> - * A value of false indicates the workbook windows are not locked. - * - * @return true if windows that comprise the workbook are locked - */ - public boolean isWindowsLocked() { - return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockWindows(); - } - - /** - * Specifies a boolean value that indicates whether the workbook is locked for revisions. - * - * @return true if the workbook is locked for revisions. - */ - public boolean isRevisionLocked() { - return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockRevision(); - } - - /** - * Locks the structure of workbook. - */ - public void lockStructure() { - safeGetWorkbookProtection().setLockStructure(true); - } - - /** - * Unlocks the structure of workbook. - */ - public void unLockStructure() { - safeGetWorkbookProtection().setLockStructure(false); - } - - /** - * Locks the windows that comprise the workbook. - */ - public void lockWindows() { - safeGetWorkbookProtection().setLockWindows(true); - } - - /** - * Unlocks the windows that comprise the workbook. - */ - public void unLockWindows() { - safeGetWorkbookProtection().setLockWindows(false); - } - - /** - * Locks the workbook for revisions. - */ - public void lockRevision() { - safeGetWorkbookProtection().setLockRevision(true); - } - - /** - * Unlocks the workbook for revisions. - */ - public void unLockRevision() { - safeGetWorkbookProtection().setLockRevision(false); - } - - /** - * Sets the workbook password. - * - * @param password if null, the password will be removed - * @param hashAlgo if null, the password will be set as XOR password (Excel 2010 and earlier) - * otherwise the given algorithm is used for calculating the hash password (Excel 2013) - */ - public void setWorkbookPassword(String password, HashAlgorithm hashAlgo) { - if (password == null && !workbookProtectionPresent()) { - return; - } - setPassword(safeGetWorkbookProtection(), password, hashAlgo, "workbook"); - } - - /** - * Validate the password against the stored hash, the hashing method will be determined - * by the existing password attributes - * @return true, if the hashes match (... though original password may differ ...) - */ - public boolean validateWorkbookPassword(String password) { - if (!workbookProtectionPresent()) { - return (password == null); - } - return validatePassword(safeGetWorkbookProtection(), password, "workbook"); - } - - /** - * Sets the revisions password. - * - * @param password if null, the password will be removed - * @param hashAlgo if null, the password will be set as XOR password (Excel 2010 and earlier) - * otherwise the given algorithm is used for calculating the hash password (Excel 2013) - */ - public void setRevisionsPassword(String password, HashAlgorithm hashAlgo) { - if (password == null && !workbookProtectionPresent()) { - return; - } - setPassword(safeGetWorkbookProtection(), password, hashAlgo, "revisions"); - } - - /** - * Validate the password against the stored hash, the hashing method will be determined - * by the existing password attributes - * @return true if the hashes match (... though original password may differ ...) - */ - public boolean validateRevisionsPassword(String password) { - if (!workbookProtectionPresent()) { - return (password == null); - } - return validatePassword(safeGetWorkbookProtection(), password, "revisions"); - } - - /** - * Removes the workbook protection settings - */ - public void unLock() { - if (workbookProtectionPresent()) { - workbook.unsetWorkbookProtection(); - } - } - - private boolean workbookProtectionPresent() { - return workbook.isSetWorkbookProtection(); - } - - private CTWorkbookProtection safeGetWorkbookProtection() { - if (!workbookProtectionPresent()){ - return workbook.addNewWorkbookProtection(); - } - return workbook.getWorkbookProtection(); - } - - /** - * - * Returns the locator of user-defined functions. - * <p> - * The default instance extends the built-in functions with the Excel Analysis Tool Pack. - * To set / evaluate custom functions you need to register them as follows: - * - * - * - * </p> - * @return wrapped instance of UDFFinder that allows seeking functions both by index and name - */ - /*package*/ UDFFinder getUDFFinder() { - return _udfFinder; - } - - /** - * Register a new toolpack in this workbook. - * - * @param toopack the toolpack to register - */ - @Override - public void addToolPack(UDFFinder toopack){ - _udfFinder.add(toopack); - } - - /** - * Whether the application shall perform a full recalculation when the workbook is opened. - * <p> - * Typically you want to force formula recalculation when you modify cell formulas or values - * of a workbook previously created by Excel. When set to true, this flag will tell Excel - * that it needs to recalculate all formulas in the workbook the next time the file is opened. - * </p> - * <p> - * Note, that recalculation updates cached formula results and, thus, modifies the workbook. - * Depending on the version, Excel may prompt you with "Do you want to save the changes in <em>filename</em>?" - * on close. - * </p> - * - * @param value true if the application will perform a full recalculation of - * workbook values when the workbook is opened - * @since 3.8 - */ - @Override - public void setForceFormulaRecalculation(boolean value){ - CTWorkbook ctWorkbook = getCTWorkbook(); - CTCalcPr calcPr = ctWorkbook.isSetCalcPr() ? ctWorkbook.getCalcPr() : ctWorkbook.addNewCalcPr(); - // when set to true, will tell Excel that it needs to recalculate all formulas - // in the workbook the next time the file is opened. - calcPr.setFullCalcOnLoad(value); - - if(value && calcPr.getCalcMode() == STCalcMode.MANUAL) { - calcPr.setCalcMode(STCalcMode.AUTO); - } - } - - /** - * Whether Excel will be asked to recalculate all formulas when the workbook is opened. - * - * @since 3.8 - */ - @Override - public boolean getForceFormulaRecalculation(){ - CTWorkbook ctWorkbook = getCTWorkbook(); - CTCalcPr calcPr = ctWorkbook.getCalcPr(); - return calcPr != null && calcPr.isSetFullCalcOnLoad() && calcPr.getFullCalcOnLoad(); - } - - - - /** - * Add pivotCache to the workbook - */ - @Beta - protected CTPivotCache addPivotCache(String rId) { - CTWorkbook ctWorkbook = getCTWorkbook(); - CTPivotCaches caches; - if (ctWorkbook.isSetPivotCaches()) { - caches = ctWorkbook.getPivotCaches(); - } else { - caches = ctWorkbook.addNewPivotCaches(); - } - CTPivotCache cache = caches.addNewPivotCache(); - - int tableId = getPivotTables().size()+1; - cache.setCacheId(tableId); - cache.setId(rId); - if(pivotCaches == null) { - pivotCaches = new ArrayList<>(); - } - pivotCaches.add(cache); - return cache; - } - - @Beta - public List<XSSFPivotTable> getPivotTables() { - return pivotTables; - } - - @Beta - protected void setPivotTables(List<XSSFPivotTable> pivotTables) { - this.pivotTables = pivotTables; - } - - public XSSFWorkbookType getWorkbookType() { - return isMacroEnabled() ? XSSFWorkbookType.XLSM : XSSFWorkbookType.XLSX; - } - - /** - * Sets whether the workbook will be an .xlsx or .xlsm (macro-enabled) file. - */ - public void setWorkbookType(XSSFWorkbookType type) { - try { - getPackagePart().setContentType(type.getContentType()); - } catch (InvalidFormatException e) { - throw new POIXMLException(e); - } - } - - /** - * Adds a vbaProject.bin file to the workbook. This will change the workbook - * type if necessary. - * - * @throws IOException If copying data from the stream fails. - */ - public void setVBAProject(InputStream vbaProjectStream) throws IOException { - if (!isMacroEnabled()) { - setWorkbookType(XSSFWorkbookType.XLSM); - } - - PackagePartName ppName; - try { - ppName = PackagingURIHelper.createPartName(XSSFRelation.VBA_MACROS.getDefaultFileName()); - } catch (InvalidFormatException e) { - throw new POIXMLException(e); - } - OPCPackage opc = getPackage(); - OutputStream outputStream; - if (!opc.containPart(ppName)) { - POIXMLDocumentPart relationship = createRelationship(XSSFRelation.VBA_MACROS, this.xssfFactory); - outputStream = relationship.getPackagePart().getOutputStream(); - } else { - PackagePart part = opc.getPart(ppName); - outputStream = part.getOutputStream(); - } - try { - IOUtils.copy(vbaProjectStream, outputStream); - } finally { - IOUtils.closeQuietly(outputStream); - } - } - - /** - * Adds a vbaProject.bin file taken from another, given workbook to this one. - * @throws IOException If copying the VBAProject stream fails. - * @throws InvalidFormatException If an error occurs while handling parts of the XSSF format - */ - public void setVBAProject(XSSFWorkbook macroWorkbook) throws IOException, InvalidFormatException { - if (!macroWorkbook.isMacroEnabled()) { - return; - } - InputStream vbaProjectStream = XSSFRelation.VBA_MACROS.getContents(macroWorkbook.getCorePart()); - if (vbaProjectStream != null) { - setVBAProject(vbaProjectStream); - } - } - - /** - * Returns the spreadsheet version (EXCLE2007) of this workbook - * - * @return EXCEL2007 SpreadsheetVersion enum - * @since 3.14 beta 2 - */ - @Override - public SpreadsheetVersion getSpreadsheetVersion() { - return SpreadsheetVersion.EXCEL2007; - } - - /** - * Returns the data table with the given name (case insensitive). - * - * @param name the data table name (case-insensitive) - * @return The Data table in the workbook named <tt>name</tt>, or <tt>null</tt> if no table is named <tt>name</tt>. - * @since 3.15 beta 2 - */ - public XSSFTable getTable(String name) { - if (name != null && sheets != null) { - for (XSSFSheet sheet : sheets) { - for (XSSFTable tbl : sheet.getTables()) { - if (name.equalsIgnoreCase(tbl.getName())) { - return tbl; - } - } - } - } - return null; - } - - @Override - public int addOlePackage(byte[] oleData, String label, String fileName, String command) - throws IOException { - final XSSFRelation rel = XSSFRelation.OLEEMBEDDINGS; - - // find an unused part name - OPCPackage opc = getPackage(); - PackagePartName pnOLE; - int oleId; - try { - oleId = opc.getUnusedPartIndex(rel.getDefaultFileName()); - pnOLE = PackagingURIHelper.createPartName(rel.getFileName(oleId)); - } catch (InvalidFormatException e) { - throw new IOException("ole object name not recognized", e); - } - - PackagePart pp = opc.createPart( pnOLE, rel.getContentType() ); - - Ole10Native ole10 = new Ole10Native(label, fileName, command, oleData); - - try (ByteArrayOutputStream bos = new ByteArrayOutputStream(oleData.length+500)) { - ole10.writeOut(bos); - - try (POIFSFileSystem poifs = new POIFSFileSystem()) { - DirectoryNode root = poifs.getRoot(); - root.createDocument(Ole10Native.OLE10_NATIVE, new ByteArrayInputStream(bos.toByteArray())); - root.setStorageClsid(ClassIDPredefined.OLE_V1_PACKAGE.getClassID()); - - // TODO: generate CombObj stream - - try (OutputStream os = pp.getOutputStream()) { - poifs.writeFilesystem(os); - } - } - } - - return oleId; - } - - /** - * Whether a call to {@link XSSFCell#setCellFormula(String)} will validate the formula or not. - * - * @param value true if the application will validate the formula is correct - * @since 3.17 - */ - public void setCellFormulaValidation(final boolean value) { - this.cellFormulaValidation = value; - } - - /** - * Whether a call to {@link XSSFCell#setCellFormula(String)} will validate the formula or not. - * - * @since 3.17 - */ - public boolean getCellFormulaValidation() { - return this.cellFormulaValidation; - } - - @Override - public XSSFEvaluationWorkbook createEvaluationWorkbook() { - return XSSFEvaluationWorkbook.create(this); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookFactory.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookFactory.java deleted file mode 100644 index 3ac689f372..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookFactory.java +++ /dev/null @@ -1,160 +0,0 @@ -/* ==================================================================== - 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 java.io.File; -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.EncryptedDocumentException; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.openxml4j.opc.PackageAccess; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; -import org.apache.poi.poifs.filesystem.FileMagic; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.WorkbookProvider; -import org.apache.poi.util.Internal; - -@Internal -public class XSSFWorkbookFactory implements WorkbookProvider { - - @Override - public boolean accepts(FileMagic fm) { - return fm == FileMagic.OOXML; - } - - /** - * Create a new empty Workbook - * - * @return The created workbook - */ - @Override - public XSSFWorkbook create() { - return new XSSFWorkbook(); - } - - @Override - public XSSFWorkbook create(DirectoryNode root, String password) throws IOException { - try (InputStream stream = DocumentFactoryHelper.getDecryptedStream(root, password)) { - return create(stream); - // don't close root.getFileSystem() otherwise the container filesystem becomes invalid - } - } - - @Override - public Workbook create(InputStream inp, String password) throws IOException { - InputStream bufInp = FileMagic.prepareToCheckMagic(inp); - FileMagic fm = FileMagic.valueOf(bufInp); - - if (fm == FileMagic.OLE2) { - try (POIFSFileSystem poifs = new POIFSFileSystem(bufInp); - InputStream stream = DocumentFactoryHelper.getDecryptedStream(poifs.getRoot(), password)) { - return create(stream); - } - } - - if (fm == FileMagic.OOXML) { - return create(bufInp); - } - - return null; - } - - /** - * Creates a XSSFWorkbook from the given InputStream - * - * <p>Note that in order to properly release resources the - * Workbook should be closed after use.</p> - * - * @param stream The {@link InputStream} to read data from. - * - * @return The created Workbook - * - * @throws IOException if an error occurs while reading the data - */ - @SuppressWarnings("resource") - @Override - public XSSFWorkbook create(InputStream stream) throws IOException { - try { - OPCPackage pkg = OPCPackage.open(stream); - return createWorkbook(pkg); - } catch (InvalidFormatException e) { - throw new IOException(e); - } - } - - /** - * Creates a XSSFWorkbook from the given OOXML Package - * - * <p>Note that in order to properly release resources the - * Workbook should be closed after use.</p> - * - * @param pkg The {@link OPCPackage} opened for reading data. - * - * @return The created Workbook - * - * @throws IOException if an error occurs while reading the data - */ - public static XSSFWorkbook createWorkbook(OPCPackage pkg) throws IOException { - try { - return new XSSFWorkbook(pkg); - } catch (RuntimeException ioe) { - // ensure that file handles are closed (use revert() to not re-write the file) - pkg.revert(); - //pkg.close(); - - // rethrow exception - throw ioe; - } - } - - /** - * Creates the XSSFWorkbook from the given File, which must exist and be readable. - * <p>Note that in order to properly release resources the Workbook should be closed after use. - * - * @param file The file to read data from. - * @param readOnly If the Workbook should be opened in read-only mode to avoid writing back - * changes when the document is closed. - * - * @return The created Workbook - * - * @throws IOException if an error occurs while reading the data - * @throws EncryptedDocumentException If the wrong password is given for a protected file - */ - @SuppressWarnings("resource") - public XSSFWorkbook create(File file, String password, boolean readOnly) throws IOException { - FileMagic fm = FileMagic.valueOf(file); - - if (fm == FileMagic.OLE2) { - try (POIFSFileSystem poifs = new POIFSFileSystem(file, true); - InputStream stream = DocumentFactoryHelper.getDecryptedStream(poifs.getRoot(), password)) { - return create(stream); - } - } - - try { - OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE); - return createWorkbook(pkg); - } catch (InvalidFormatException e) { - throw new IOException(e); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookType.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookType.java deleted file mode 100644 index 917d3d6daa..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookType.java +++ /dev/null @@ -1,45 +0,0 @@ -/* ==================================================================== - 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; - - -/** - * Represents the two different kinds of XML-based OOXML document. - */ -public enum XSSFWorkbookType { - - XLSX(XSSFRelation.WORKBOOK.getContentType(), "xlsx"), - XLSM(XSSFRelation.MACROS_WORKBOOK.getContentType(), "xlsm"); - - private final String _contentType; - private final String _extension; - - private XSSFWorkbookType(String contentType, String extension) { - _contentType = contentType; - _extension = extension; - } - - public String getContentType() { - return _contentType; - } - - public String getExtension() { - return _extension; - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellAlignment.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellAlignment.java deleted file mode 100644 index 15837ca575..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellAlignment.java +++ /dev/null @@ -1,209 +0,0 @@ -/* ==================================================================== - 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.extensions; - -import java.math.BigInteger; - -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.ReadingOrder; -import org.apache.poi.ss.usermodel.VerticalAlignment; -import org.apache.poi.util.Internal; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellAlignment; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STHorizontalAlignment; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STVerticalAlignment; - - -/** - * Cell settings available in the Format/Alignment tab - */ -public class XSSFCellAlignment { - private final CTCellAlignment cellAlignement; - - /** - * Creates a Cell Alignment from the supplied XML definition - * - * @param cellAlignment The low-level XML definition of the cell alignment - */ - public XSSFCellAlignment(CTCellAlignment cellAlignment) { - this.cellAlignement = cellAlignment; - } - - /** - * Get the type of vertical alignment for the cell - * - * @return the type of aligment - * @see VerticalAlignment - */ - public VerticalAlignment getVertical() { - STVerticalAlignment.Enum align = cellAlignement.getVertical(); - if (align == null) align = STVerticalAlignment.BOTTOM; - - return VerticalAlignment.values()[align.intValue() - 1]; - } - - /** - * Set the type of vertical alignment for the cell - * - * @param align - the type of alignment - * @see VerticalAlignment - */ - public void setVertical(VerticalAlignment align) { - cellAlignement.setVertical(STVerticalAlignment.Enum.forInt(align.ordinal() + 1)); - } - - /** - * Get the type of horizontal alignment for the cell - * - * @return the type of aligment - * @see HorizontalAlignment - */ - public HorizontalAlignment getHorizontal() { - STHorizontalAlignment.Enum align = cellAlignement.getHorizontal(); - if (align == null) align = STHorizontalAlignment.GENERAL; - - return HorizontalAlignment.values()[align.intValue() - 1]; - } - - /** - * Set the type of horizontal alignment for the cell - * - * @param align - the type of alignment - * @see HorizontalAlignment - */ - public void setHorizontal(HorizontalAlignment align) { - cellAlignement.setHorizontal(STHorizontalAlignment.Enum.forInt(align.ordinal() + 1)); - } - - /** - * Set the type of reading order for the cell - * - * @param order - the type of reading order - * @see ReadingOrder - */ - public void setReadingOrder(ReadingOrder order) { - cellAlignement.setReadingOrder(order.getCode()); - } - - /** - * Get the reading order for the cell - * - * @return the value of reading order - * @see ReadingOrder - */ - public ReadingOrder getReadingOrder() { - if(cellAlignement != null && cellAlignement.isSetReadingOrder()) { - return ReadingOrder.forLong(cellAlignement.getReadingOrder()); - } - return ReadingOrder.CONTEXT; - } - - /** - * Get the number of spaces to indent the text in the cell - * - * @return indent - number of spaces - */ - public long getIndent() { - return cellAlignement.getIndent(); - } - - /** - * Set the number of spaces to indent the text in the cell - * - * @param indent - number of spaces - */ - public void setIndent(long indent) { - cellAlignement.setIndent(indent); - } - - /** - * Get the degree of rotation for the text in the cell - * <p> - * Expressed in degrees. Values range from 0 to 180. The first letter of - * the text is considered the center-point of the arc. - * <br> - * For 0 - 90, the value represents degrees above horizon. For 91-180 the degrees below the - * horizon is calculated as: - * <br> - * <code>[degrees below horizon] = 90 - textRotation.</code> - * </p> - * - * @return rotation degrees (between 0 and 180 degrees) - */ - public long getTextRotation() { - return cellAlignement.isSetTextRotation() ? cellAlignement.getTextRotation().longValue() : 0; - } - - /** - * Set the degree of rotation for the text in the cell - * <p> - * Expressed in degrees. Values range from 0 to 180. The first letter of - * the text is considered the center-point of the arc. - * <br> - * For 0 - 90, the value represents degrees above horizon. For 91-180 the degrees below the - * horizon is calculated as: - * <br> - * <code>[degrees below horizon] = 90 - textRotation.</code> - * </p> - * - * Note: HSSF uses values from -90 to 90 degrees, whereas XSSF - * uses values from 0 to 180 degrees. The implementations of this method will map between these two value-ranges - * accordingly, however the corresponding getter is returning values in the range mandated by the current type - * of Excel file-format that this CellStyle is applied to. - * - * @param rotation - the rotation degrees (between 0 and 180 degrees) - */ - public void setTextRotation(long rotation) { - if(rotation < 0 && rotation >= -90) { - rotation = 90 + ((-1)*rotation); - } - cellAlignement.setTextRotation(BigInteger.valueOf(rotation)); - } - - /** - * Whether the text should be wrapped - * - * @return a boolean value indicating if the text in a cell should be line-wrapped within the cell. - */ - public boolean getWrapText() { - return cellAlignement.getWrapText(); - } - - /** - * Set whether the text should be wrapped - * - * @param wrapped a boolean value indicating if the text in a cell should be line-wrapped within the cell. - */ - public void setWrapText(boolean wrapped) { - cellAlignement.setWrapText(wrapped); - } - - public boolean getShrinkToFit() { - return cellAlignement.getShrinkToFit(); - } - - public void setShrinkToFit(boolean shrink) { - cellAlignement.setShrinkToFit(shrink); - } - - /** - * Access to low-level data - */ - @Internal - public CTCellAlignment getCTCellAlignment() { - return cellAlignement; - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellBorder.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellBorder.java deleted file mode 100644 index 31ed2a2203..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellBorder.java +++ /dev/null @@ -1,259 +0,0 @@ -/* ==================================================================== - 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.extensions; - - -import java.util.Objects; - -import org.apache.poi.ss.usermodel.BorderStyle; -import org.apache.poi.xssf.model.ThemesTable; -import org.apache.poi.xssf.usermodel.IndexedColorMap; -import org.apache.poi.xssf.usermodel.XSSFColor; -import org.apache.poi.util.Internal; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle; - -/** - * This element contains border formatting information, specifying border definition formats (left, right, top, bottom, diagonal) - * for cells in the workbook. - * Color is optional. - */ -public class XSSFCellBorder { - private final IndexedColorMap _indexedColorMap; - private ThemesTable _theme; - private final CTBorder border; - - /** - * Creates a Cell Border from the supplied XML definition - * @param border The ooxml object for the border - * @param theme The related themes - * @param colorMap The global map of colors - */ - public XSSFCellBorder(CTBorder border, ThemesTable theme, IndexedColorMap colorMap) { - this.border = border; - this._indexedColorMap = colorMap; - this._theme = theme; - } - - /** - * Creates a Cell Border from the supplied XML definition - * @param border The ooxml object for the border - */ - public XSSFCellBorder(CTBorder border) { - this(border, null, null); - } - - /** - * - * @param border The ooxml object for the border - * @param colorMap The global map of colors - */ - public XSSFCellBorder(CTBorder border, IndexedColorMap colorMap) { - this(border, null, colorMap); - } - - /** - * Creates a new, empty Cell Border. - * You need to attach this to the Styles Table - */ - public XSSFCellBorder() { - this(CTBorder.Factory.newInstance(), null, null); - } - - /** - * Records the Themes Table that is associated with - * the current font, used when looking up theme - * based colours and properties. - */ - public void setThemesTable(ThemesTable themes) { - this._theme = themes; - } - - /** - * The enumeration value indicating the side being used for a cell border. - */ - public enum BorderSide { - TOP, RIGHT, BOTTOM, LEFT, DIAGONAL, VERTICAL, HORIZONTAL - } - - /** - * Returns the underlying XML bean. - * - * @return CTBorder - */ - @Internal - public CTBorder getCTBorder() { - return border; - } - - /** - * Get the type of border to use for the selected border - * - * @param side - - where to apply the color definition - * @return borderstyle - the type of border to use. default value is NONE if border style is not set. - * @see BorderStyle - */ - public BorderStyle getBorderStyle(BorderSide side) { - CTBorderPr ctBorder = getBorder(side); - STBorderStyle.Enum border = ctBorder == null ? STBorderStyle.NONE : ctBorder.getStyle(); - return BorderStyle.values()[border.intValue() - 1]; - } - - /** - * Set the type of border to use for the selected border - * - * @param side - - where to apply the color definition - * @param style - border style - * @see BorderStyle - */ - public void setBorderStyle(BorderSide side, BorderStyle style) { - getBorder(side, true).setStyle(STBorderStyle.Enum.forInt(style.ordinal() + 1)); - } - - /** - * Get the color to use for the selected border - * - * @param side - where to apply the color definition - * @return color - color to use as XSSFColor. null if color is not set - */ - public XSSFColor getBorderColor(BorderSide side) { - CTBorderPr borderPr = getBorder(side); - - if(borderPr != null && borderPr.isSetColor()) { - XSSFColor clr = XSSFColor.from(borderPr.getColor(), _indexedColorMap); - if(_theme != null) { - _theme.inheritFromThemeAsRequired(clr); - } - return clr; - } else { - // No border set - return null; - } - } - - /** - * Set the color to use for the selected border - * - * @param side - where to apply the color definition - * @param color - the color to use - */ - public void setBorderColor(BorderSide side, XSSFColor color) { - CTBorderPr borderPr = getBorder(side, true); - if (color == null) borderPr.unsetColor(); - else - borderPr.setColor(color.getCTColor()); - } - - private CTBorderPr getBorder(BorderSide side) { - return getBorder(side, false); - } - - - private CTBorderPr getBorder(BorderSide side, boolean ensure) { - CTBorderPr borderPr; - switch (side) { - case TOP: - borderPr = border.getTop(); - if (ensure && borderPr == null) borderPr = border.addNewTop(); - break; - case RIGHT: - borderPr = border.getRight(); - if (ensure && borderPr == null) borderPr = border.addNewRight(); - break; - case BOTTOM: - borderPr = border.getBottom(); - if (ensure && borderPr == null) borderPr = border.addNewBottom(); - break; - case LEFT: - borderPr = border.getLeft(); - if (ensure && borderPr == null) borderPr = border.addNewLeft(); - break; - case DIAGONAL: - borderPr = border.getDiagonal(); - if (ensure && borderPr == null) borderPr = border.addNewDiagonal(); - break; - case VERTICAL: - borderPr = border.getVertical(); - if (ensure && borderPr == null) borderPr = border.addNewVertical(); - break; - case HORIZONTAL: - borderPr = border.getHorizontal(); - if (ensure && borderPr == null) borderPr = border.addNewHorizontal(); - break; - default: - throw new IllegalArgumentException("No suitable side specified for the border, had " + side); - } - return borderPr; - } - - - public int hashCode() { - return border.toString().hashCode(); - } - - public boolean equals(Object o) { - if (!(o instanceof XSSFCellBorder)) return false; - - XSSFCellBorder cf = (XSSFCellBorder) o; - - // bug 60845 - // Do not compare the representing strings but the properties - // Reason: - // The strings are different if the XMLObject is a fragment (e.g. the ones from cloneStyle) - // even if they are in fact representing the same style - boolean equal = true; - for(BorderSide side : BorderSide.values()){ - if(!Objects.equals(this.getBorderColor(side), cf.getBorderColor(side)) - || !Objects.equals(this.getBorderStyle(side), cf.getBorderStyle(side))){ - equal = false; - break; - } - } - if(!equal) { - return false; - } - - // we also need to compare some more boolean-values - - // first all booleans need to have the same state of "defined" or "undefined" - if(this.border.isSetDiagonalUp() != cf.border.isSetDiagonalUp() || - this.border.isSetDiagonalDown() != cf.border.isSetDiagonalDown() || - this.border.isSetOutline() != cf.border.isSetOutline()) { - return false; - } - - // then compare each value if necessary - if(this.border.isSetDiagonalUp() && - this.border.getDiagonalUp() != cf.border.getDiagonalUp()) { - return false; - } - - if(this.border.isSetDiagonalDown() && - this.border.getDiagonalDown() != cf.border.getDiagonalDown()) { - return false; - } - - //noinspection RedundantIfStatement - if(this.border.isSetOutline() && - this.border.getOutline() != cf.border.getOutline()) { - return false; - } - - return true; - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellFill.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellFill.java deleted file mode 100644 index dd9dca7d16..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellFill.java +++ /dev/null @@ -1,189 +0,0 @@ -/* ==================================================================== - 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.extensions; - -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPatternFill; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; -import org.apache.poi.xssf.usermodel.IndexedColorMap; -import org.apache.poi.xssf.usermodel.XSSFColor; - -import java.util.Objects; - -import org.apache.poi.util.Internal; - -/** - * This element specifies fill formatting. - * A cell fill consists of a background color, foreground color, and pattern to be applied across the cell. - */ -public final class XSSFCellFill { - - private IndexedColorMap _indexedColorMap; - private CTFill _fill; - - /** - * Creates a CellFill from the supplied parts - * - * @param fill - fill - */ - public XSSFCellFill(CTFill fill, IndexedColorMap colorMap) { - _fill = fill; - _indexedColorMap = colorMap; - } - - /** - * Creates an empty CellFill - */ - public XSSFCellFill() { - _fill = CTFill.Factory.newInstance(); - } - - /** - * Get the background fill color. - * - * @return fill color, null if color is not set - */ - public XSSFColor getFillBackgroundColor() { - CTPatternFill ptrn = _fill.getPatternFill(); - if (ptrn == null) return null; - - CTColor ctColor = ptrn.getBgColor(); - return XSSFColor.from(ctColor, _indexedColorMap); - } - - /** - * Set the background fill color represented as a indexed color value. - * - * @param index - the color to use - */ - public void setFillBackgroundColor(int index) { - CTPatternFill ptrn = ensureCTPatternFill(); - CTColor ctColor = ptrn.isSetBgColor() ? ptrn.getBgColor() : ptrn.addNewBgColor(); - ctColor.setIndexed(index); - } - - /** - * Set the background fill color represented as a {@link XSSFColor} value. - * - * @param color - background color. null if color should be unset - */ - public void setFillBackgroundColor(XSSFColor color) { - CTPatternFill ptrn = ensureCTPatternFill(); - if (color == null) { - ptrn.unsetBgColor(); - } else { - ptrn.setBgColor(color.getCTColor()); - } - } - - /** - * Get the foreground fill color. - * - * @return XSSFColor - foreground color. null if color is not set - */ - public XSSFColor getFillForegroundColor() { - CTPatternFill ptrn = _fill.getPatternFill(); - if (ptrn == null) return null; - - CTColor ctColor = ptrn.getFgColor(); - return XSSFColor.from(ctColor, _indexedColorMap); - } - - /** - * Set the foreground fill color as a indexed color value - * - * @param index - the color to use - */ - public void setFillForegroundColor(int index) { - CTPatternFill ptrn = ensureCTPatternFill(); - CTColor ctColor = ptrn.isSetFgColor() ? ptrn.getFgColor() : ptrn.addNewFgColor(); - ctColor.setIndexed(index); - } - - /** - * Set the foreground fill color represented as a {@link XSSFColor} value. - * - * @param color - the color to use - */ - public void setFillForegroundColor(XSSFColor color) { - CTPatternFill ptrn = ensureCTPatternFill(); - if (color == null) { - ptrn.unsetFgColor(); - } else { - ptrn.setFgColor(color.getCTColor()); - } - } - - /** - * get the fill pattern - * - * @return fill pattern type. null if fill pattern is not set - */ - public STPatternType.Enum getPatternType() { - CTPatternFill ptrn = _fill.getPatternFill(); - return ptrn == null ? null : ptrn.getPatternType(); - } - - /** - * set the fill pattern - * - * @param patternType fill pattern to use - */ - public void setPatternType(STPatternType.Enum patternType) { - CTPatternFill ptrn = ensureCTPatternFill(); - ptrn.setPatternType(patternType); - } - - private CTPatternFill ensureCTPatternFill() { - CTPatternFill patternFill = _fill.getPatternFill(); - if (patternFill == null) { - patternFill = _fill.addNewPatternFill(); - } - return patternFill; - } - - /** - * Returns the underlying XML bean. - * - * @return CTFill - */ - @Internal - public CTFill getCTFill() { - return _fill; - } - - - public int hashCode() { - return _fill.toString().hashCode(); - } - - public boolean equals(Object o) { - if (!(o instanceof XSSFCellFill)) return false; - - XSSFCellFill cf = (XSSFCellFill) o; - - // bug 60845 - // Do not compare the representing strings but the properties - // Reason: - // The strings are different if the XMLObject is a fragment (e.g. the ones from cloneStyle) - // even if they are in fact representing the same style - return Objects.equals(this.getFillBackgroundColor(), cf.getFillBackgroundColor()) - && Objects.equals(this.getFillForegroundColor(), cf.getFillForegroundColor()) - && Objects.equals(this.getPatternType(), cf.getPatternType()); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFHeaderFooter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFHeaderFooter.java deleted file mode 100644 index 2ab58f6fa0..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFHeaderFooter.java +++ /dev/null @@ -1,248 +0,0 @@ -/* ==================================================================== - 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.extensions; - -import org.apache.poi.ss.usermodel.HeaderFooter; -import org.apache.poi.xssf.usermodel.helpers.HeaderFooterHelper; -import org.apache.poi.util.Internal; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter; - -/** - * Parent class of all XSSF headers and footers. - * - * For a list of all the different fields that can be placed into a header or - * footer, such as page number, bold, underline etc, see the follow formatting - * syntax - * - *<b> Header/Footer Formatting Syntax</b> - *<p> - * There are a number of formatting codes that can be written inline with the - * actual header / footer text, which affect the formatting in the header or - * footer. - *</p> - * - * This example shows the text "Center Bold Header" on the first line (center - * section), and the date on the second line (center section). &CCenter - * &"-,Bold"Bold &"-,Regular"Header_x000A_&D - * - * <b>General Rules:</b> There is no required order in which these codes must - * appear. The first occurrence of the following codes turns the formatting ON, - * the second occurrence turns it OFF again: - * - * <dl> - * <dt>&L</dt> - * <dd>code for "left section" (there are three header / footer locations, - * "left", "center", and "right"). When two or more occurrences of this section - * marker exist, the contents from all markers are concatenated, in the order of - * appearance, and placed into the left section.</dd> - * <dt>&P</dt> - * <dd>code for "current page #"</dd> - * <dt>&N</dt> - * <dd>code for "total pages"</dd> - * <dt>&font size</dt> - * <dd>code for "text font size", where font size is a font size in points.</dd> - * <dt>&K</dt> - * <dd>code for "text font color" RGB Color is specified as RRGGBB Theme Color - * is specifed as TTSNN where TT is the theme color Id, S is either "+" or "-" - * of the tint/shade value, NN is the tint/shade value.</dd> - * <dt>&S</dt> - * <dd>code for "text strikethrough" on / off</dd> - * <dt>&X</dt> - * <dd>code for "text super script" on / off</dd> - * <dt>&Y</dt> - * <dd>code for "text subscript" on / off</dd> - * <dt>&C</dt> - * <dd>code for "center section". When two or more occurrences of this section - * marker exist, the contents from all markers are concatenated, in the order of - * appearance, and placed into the center section. SpreadsheetML Reference - * Material - Worksheets 1966</dd> - * <dt>&D</dt> - * <dd>code for "date"</dd> - * <dt>&T</dt> - * <dd>code for "time"</dd> - * <dt>&G</dt> - * <dd>code for "picture as background"</dd> - * <dt>&U</dt> - * <dd>code for "text single underline"</dd> - * <dt>&E</dt> - * <dd>code for "double underline"</dd> - * <dt>&R</dt> - * <dd>code for "right section". When two or more occurrences of this section - * marker exist, the contents from all markers are concatenated, in the order of - * appearance, and placed into the right section.</dd> - * <dt>&Z</dt> - * <dd>code for "this workbook's file path"</dd> - * <dt>&F</dt> - * <dd>code for "this workbook's file name"</dd> - * <dt>&A</dt> - * <dd>code for "sheet tab name"</dd> - * <dt>&+</dt> - * <dd>code for add to page #.</dd> - * <dt>&-</dt> - * <dd>code for subtract from page #.</dd> - * <dt>&"font name,font type" - code for "text font name" and "text font type", - * where font name and font type are strings specifying the name and type of the - * font, separated by a comma. When a hyphen appears in font name, it means - * "none specified". Both of font name and font type can be localized - * values.</dd> - * <dt>&"-,Bold"</dt> - * <dd>code for "bold font style"</dd> - * <dt>&B</dt> - * <dd>also means "bold font style"</dd> - * <dt>&"-,Regular"</dt> - * <dd>code for "regular font style"</dd> - * <dt>&"-,Italic"</dt> - * <dd>code for "italic font style"</dd> - * <dt>&I</dt> - * <dd>also means "italic font style"</dd> - * <dt>&"-,Bold Italic"</dt> - * <dd>code for "bold italic font style"</dd> - * <dt>&O</dt> - * <dd>code for "outline style"</dd> - * <dt>&H</dt> - * <dd>code for "shadow style"</dd> - * </dl> - * - * - */ -public abstract class XSSFHeaderFooter implements HeaderFooter { - private HeaderFooterHelper helper; - private CTHeaderFooter headerFooter; - - private boolean stripFields; - - /** - * Create an instance of XSSFAbstractHeaderFooter from the supplied XML bean - * - * @param headerFooter - */ - public XSSFHeaderFooter(CTHeaderFooter headerFooter) { - this.headerFooter = headerFooter; - this.helper = new HeaderFooterHelper(); - } - - /** - * Returns the underlying CTHeaderFooter xml bean - * - * @return the underlying CTHeaderFooter xml bean - */ - @Internal - public CTHeaderFooter getHeaderFooter() { - return this.headerFooter; - } - - /** - * Returns the value of the header or footer. - * - * @return the value of the header or footer. - */ - public String getValue() { - String value = getText(); - if (value == null) - return ""; - return value; - } - - /** - * Are fields currently being stripped from the text that this - * {@link XSSFHeaderFooter} returns? Default is false, but can be changed - */ - public boolean areFieldsStripped() { - return stripFields; - } - - /** - * Should fields (eg macros) be stripped from the text that this class - * returns? Default is not to strip. - * - * @param stripFields - */ - public void setAreFieldsStripped(boolean stripFields) { - this.stripFields = stripFields; - } - - /** - * Removes any fields (eg macros, page markers etc) from the string. - * Normally used to make some text suitable for showing to humans, and the - * resultant text should not normally be saved back into the document! - */ - public static String stripFields(String text) { - return org.apache.poi.hssf.usermodel.HeaderFooter.stripFields(text); - } - - public abstract String getText(); - - protected abstract void setText(String text); - - /** - * get the text representing the center part of this element - */ - @Override - public String getCenter() { - String text = helper.getCenterSection(getText()); - if (stripFields) - return stripFields(text); - return text; - } - - /** - * get the text representing the left part of this element - */ - @Override - public String getLeft() { - String text = helper.getLeftSection(getText()); - if (stripFields) - return stripFields(text); - return text; - } - - /** - * get the text representing the right part of this element - */ - @Override - public String getRight() { - String text = helper.getRightSection(getText()); - if (stripFields) - return stripFields(text); - return text; - } - - /** - * set a centered string value for this element - */ - @Override - public void setCenter(String newCenter) { - setText(helper.setCenterSection(getText(), newCenter)); - } - - /** - * set a left string value for this element - */ - @Override - public void setLeft(String newLeft) { - setText(helper.setLeftSection(getText(), newLeft)); - } - - /** - * set a right string value for this element - */ - @Override - public void setRight(String newRight) { - setText(helper.setRightSection(getText(), newRight)); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java deleted file mode 100644 index f65856ea69..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java +++ /dev/null @@ -1,331 +0,0 @@ -/* ==================================================================== - 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.helpers; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.NavigableSet; -import java.util.TreeSet; - -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.xssf.util.CTColComparator; -import org.apache.poi.xssf.util.NumericRanges; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; - -/** - * Helper class for dealing with the Column settings on - * a CTWorksheet (the data part of a sheet). - * Note - within POI, we use 0 based column indexes, but - * the column definitions in the XML are 1 based! - */ -public class ColumnHelper { - - private CTWorksheet worksheet; - - public ColumnHelper(CTWorksheet worksheet) { - super(); - this.worksheet = worksheet; - cleanColumns(); - } - - public void cleanColumns() { - TreeSet<CTCol> trackedCols = new TreeSet<>(CTColComparator.BY_MIN_MAX); - CTCols newCols = CTCols.Factory.newInstance(); - CTCols[] colsArray = worksheet.getColsArray(); - int i; - for (i = 0; i < colsArray.length; i++) { - CTCols cols = colsArray[i]; - for (CTCol col : cols.getColList()) { - addCleanColIntoCols(newCols, col, trackedCols); - } - } - for (int y = i - 1; y >= 0; y--) { - worksheet.removeCols(y); - } - - newCols.setColArray(trackedCols.toArray(new CTCol[0])); - worksheet.addNewCols(); - worksheet.setColsArray(0, newCols); - } - - public CTCols addCleanColIntoCols(CTCols cols, CTCol newCol) { - // Performance issue. If we encapsulated management of min/max in this - // class then we could keep trackedCols as state, - // making this log(N) rather than Nlog(N). We do this for the initial - // read above. - TreeSet<CTCol> trackedCols = new TreeSet<>( - CTColComparator.BY_MIN_MAX); - trackedCols.addAll(cols.getColList()); - addCleanColIntoCols(cols, newCol, trackedCols); - cols.setColArray(trackedCols.toArray(new CTCol[0])); - return cols; - } - - private void addCleanColIntoCols(final CTCols cols, final CTCol newCol, final TreeSet<CTCol> trackedCols) { - List<CTCol> overlapping = getOverlappingCols(newCol, trackedCols); - if (overlapping.isEmpty()) { - trackedCols.add(cloneCol(cols, newCol)); - return; - } - - trackedCols.removeAll(overlapping); - for (CTCol existing : overlapping) { - // We add up to three columns for each existing one: non-overlap - // before, overlap, non-overlap after. - long[] overlap = getOverlap(newCol, existing); - - CTCol overlapCol = cloneCol(cols, existing, overlap); - setColumnAttributes(newCol, overlapCol); - trackedCols.add(overlapCol); - - CTCol beforeCol = existing.getMin() < newCol.getMin() ? existing - : newCol; - long[] before = new long[] { - Math.min(existing.getMin(), newCol.getMin()), - overlap[0] - 1 }; - if (before[0] <= before[1]) { - trackedCols.add(cloneCol(cols, beforeCol, before)); - } - - CTCol afterCol = existing.getMax() > newCol.getMax() ? existing - : newCol; - long[] after = new long[] { overlap[1] + 1, - Math.max(existing.getMax(), newCol.getMax()) }; - if (after[0] <= after[1]) { - trackedCols.add(cloneCol(cols, afterCol, after)); - } - } - } - - private CTCol cloneCol(final CTCols cols, final CTCol col, final long[] newRange) { - CTCol cloneCol = cloneCol(cols, col); - cloneCol.setMin(newRange[0]); - cloneCol.setMax(newRange[1]); - return cloneCol; - } - - private long[] getOverlap(final CTCol col1, final CTCol col2) { - return getOverlappingRange(col1, col2); - } - - private List<CTCol> getOverlappingCols(final CTCol newCol, final TreeSet<CTCol> trackedCols) { - CTCol lower = trackedCols.lower(newCol); - NavigableSet<CTCol> potentiallyOverlapping = lower == null ? trackedCols : trackedCols.tailSet(lower, overlaps(lower, newCol)); - List<CTCol> overlapping = new ArrayList<>(); - for (CTCol existing : potentiallyOverlapping) { - if (overlaps(newCol, existing)) { - overlapping.add(existing); - } else { - break; - } - } - return overlapping; - } - - private boolean overlaps(final CTCol col1, final CTCol col2) { - return NumericRanges.getOverlappingType(toRange(col1), toRange(col2)) != NumericRanges.NO_OVERLAPS; - } - - private long[] getOverlappingRange(final CTCol col1, final CTCol col2) { - return NumericRanges.getOverlappingRange(toRange(col1), toRange(col2)); - } - - private long[] toRange(final CTCol col) { - return new long[] { col.getMin(), col.getMax() }; - } - - public static void sortColumns(CTCols newCols) { - CTCol[] colArray = newCols.getColArray(); - Arrays.sort(colArray, CTColComparator.BY_MIN_MAX); - newCols.setColArray(colArray); - } - - public CTCol cloneCol(CTCols cols, CTCol col) { - CTCol newCol = cols.addNewCol(); - newCol.setMin(col.getMin()); - newCol.setMax(col.getMax()); - setColumnAttributes(col, newCol); - return newCol; - } - - /** - * Returns the Column at the given 0 based index - */ - public CTCol getColumn(long index, boolean splitColumns) { - return getColumn1Based(index+1, splitColumns); - } - - /** - * Returns the Column at the given 1 based index. - * POI default is 0 based, but the file stores - * as 1 based. - */ - public CTCol getColumn1Based(long index1, boolean splitColumns) { - CTCols cols = worksheet.getColsArray(0); - - // Fetching the array is quicker than working on the new style - // list, assuming we need to read many of them (which we often do), - // and assuming we're not making many changes (which we're not) - CTCol[] colArray = cols.getColArray(); - - for (CTCol col : colArray) { - long colMin = col.getMin(); - long colMax = col.getMax(); - if (colMin <= index1 && colMax >= index1) { - if (splitColumns) { - if (colMin < index1) { - insertCol(cols, colMin, (index1 - 1), new CTCol[]{col}); - } - if (colMax > index1) { - insertCol(cols, (index1 + 1), colMax, new CTCol[]{col}); - } - col.setMin(index1); - col.setMax(index1); - } - return col; - } - } - return null; - } - - /* - * Insert a new CTCol at position 0 into cols, setting min=min, max=max and - * copying all the colsWithAttributes array cols attributes into newCol - */ - private CTCol insertCol(CTCols cols, long min, long max, CTCol[] colsWithAttributes) { - return insertCol(cols, min, max, colsWithAttributes, false, null); - } - - private CTCol insertCol(CTCols cols, long min, long max, - CTCol[] colsWithAttributes, boolean ignoreExistsCheck, CTCol overrideColumn) { - if(ignoreExistsCheck || !columnExists(cols,min,max)){ - CTCol newCol = cols.insertNewCol(0); - newCol.setMin(min); - newCol.setMax(max); - for (CTCol col : colsWithAttributes) { - setColumnAttributes(col, newCol); - } - if (overrideColumn != null) setColumnAttributes(overrideColumn, newCol); - return newCol; - } - return null; - } - - /** - * Does the column at the given 0 based index exist - * in the supplied list of column definitions? - */ - public boolean columnExists(CTCols cols, long index) { - return columnExists1Based(cols, index+1); - } - - private boolean columnExists1Based(CTCols cols, long index1) { - for (CTCol col : cols.getColArray()) { - if (col.getMin() == index1) { - return true; - } - } - return false; - } - - public void setColumnAttributes(CTCol fromCol, CTCol toCol) { - if(fromCol.isSetBestFit()) toCol.setBestFit(fromCol.getBestFit()); - if(fromCol.isSetCustomWidth()) toCol.setCustomWidth(fromCol.getCustomWidth()); - if(fromCol.isSetHidden()) toCol.setHidden(fromCol.getHidden()); - if(fromCol.isSetStyle()) toCol.setStyle(fromCol.getStyle()); - if(fromCol.isSetWidth()) toCol.setWidth(fromCol.getWidth()); - if(fromCol.isSetCollapsed()) toCol.setCollapsed(fromCol.getCollapsed()); - if(fromCol.isSetPhonetic()) toCol.setPhonetic(fromCol.getPhonetic()); - if(fromCol.isSetOutlineLevel()) toCol.setOutlineLevel(fromCol.getOutlineLevel()); - toCol.setCollapsed(fromCol.isSetCollapsed()); - } - - public void setColBestFit(long index, boolean bestFit) { - CTCol col = getOrCreateColumn1Based(index+1, false); - col.setBestFit(bestFit); - } - public void setCustomWidth(long index, boolean bestFit) { - CTCol col = getOrCreateColumn1Based(index+1, true); - col.setCustomWidth(bestFit); - } - - public void setColWidth(long index, double width) { - CTCol col = getOrCreateColumn1Based(index+1, true); - col.setWidth(width); - } - - public void setColHidden(long index, boolean hidden) { - CTCol col = getOrCreateColumn1Based(index+1, true); - col.setHidden(hidden); - } - - /** - * Return the CTCol at the given (0 based) column index, - * creating it if required. - */ - protected CTCol getOrCreateColumn1Based(long index1, boolean splitColumns) { - CTCol col = getColumn1Based(index1, splitColumns); - if (col == null) { - col = worksheet.getColsArray(0).addNewCol(); - col.setMin(index1); - col.setMax(index1); - } - return col; - } - - public void setColDefaultStyle(long index, CellStyle style) { - setColDefaultStyle(index, style.getIndex()); - } - - public void setColDefaultStyle(long index, int styleId) { - CTCol col = getOrCreateColumn1Based(index+1, true); - col.setStyle(styleId); - } - - // Returns -1 if no column is found for the given index - public int getColDefaultStyle(long index) { - if (getColumn(index, false) != null) { - return (int) getColumn(index, false).getStyle(); - } - return -1; - } - - private boolean columnExists(CTCols cols, long min, long max) { - for (CTCol col : cols.getColList()) { - if (col.getMin() == min && col.getMax() == max) { - return true; - } - } - return false; - } - - public int getIndexOfColumn(CTCols cols, CTCol searchCol) { - if (cols == null || searchCol == null) return -1; - int i = 0; - for (CTCol col : cols.getColList()) { - if (col.getMin() == searchCol.getMin() && col.getMax() == searchCol.getMax()) { - return i; - } - i++; - } - return -1; - } -}
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/HeaderFooterHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/HeaderFooterHelper.java deleted file mode 100644 index e4731dae11..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/HeaderFooterHelper.java +++ /dev/null @@ -1,119 +0,0 @@ -/* ==================================================================== - 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.helpers; - - -public class HeaderFooterHelper { - // Note - XmlBeans handles entity encoding for us, - // so these should be & forms, not the & ones! - private static final String HeaderFooterEntity_L = "&L"; - private static final String HeaderFooterEntity_C = "&C"; - private static final String HeaderFooterEntity_R = "&R"; - - // These are other entities that may be used in the - // left, center or right. Not exhaustive - public static final String HeaderFooterEntity_File = "&F"; - public static final String HeaderFooterEntity_Date = "&D"; - public static final String HeaderFooterEntity_Time = "&T"; - - public String getLeftSection(String string) { - return getParts(string)[0]; - } - public String getCenterSection(String string) { - return getParts(string)[1]; - } - public String getRightSection(String string) { - return getParts(string)[2]; - } - - public String setLeftSection(String string, String newLeft) { - String[] parts = getParts(string); - parts[0] = newLeft; - return joinParts(parts); - } - public String setCenterSection(String string, String newCenter) { - String[] parts = getParts(string); - parts[1] = newCenter; - return joinParts(parts); - } - public String setRightSection(String string, String newRight) { - String[] parts = getParts(string); - parts[2] = newRight; - return joinParts(parts); - } - - /** - * Split into left, center, right - */ - private String[] getParts(String string) { - String[] parts = new String[] { "", "", "" }; - if(string == null) - return parts; - - // They can come in any order, which is just nasty - // Work backwards from the end, picking the last - // on off each time as we go - int lAt = 0; - int cAt = 0; - int rAt = 0; - - while( - // Ensure all indicies get updated, then -1 tested - (lAt = string.indexOf(HeaderFooterEntity_L)) > -2 && - (cAt = string.indexOf(HeaderFooterEntity_C)) > -2 && - (rAt = string.indexOf(HeaderFooterEntity_R)) > -2 && - (lAt > -1 || cAt > -1 || rAt > -1) - ) { - // Pick off the last one - if(rAt > cAt && rAt > lAt) { - parts[2] = string.substring(rAt + HeaderFooterEntity_R.length()); - string = string.substring(0, rAt); - } else if(cAt > rAt && cAt > lAt) { - parts[1] = string.substring(cAt + HeaderFooterEntity_C.length()); - string = string.substring(0, cAt); - } else { - parts[0] = string.substring(lAt + HeaderFooterEntity_L.length()); - string = string.substring(0, lAt); - } - } - - return parts; - } - private String joinParts(String[] parts) { - return joinParts(parts[0], parts[1], parts[2]); - } - private String joinParts(String l, String c, String r) { - StringBuilder ret = new StringBuilder(64); - - // Join as c, l, r - if(c.length() > 0) { - ret.append(HeaderFooterEntity_C); - ret.append(c); - } - if(l.length() > 0) { - ret.append(HeaderFooterEntity_L); - ret.append(l); - } - if(r.length() > 0) { - ret.append(HeaderFooterEntity_R); - ret.append(r); - } - - return ret.toString(); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFColumnShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFColumnShifter.java deleted file mode 100644 index 2acc8955f1..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFColumnShifter.java +++ /dev/null @@ -1,61 +0,0 @@ -/* ==================================================================== - 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.helpers; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.ss.formula.FormulaShifter; -import org.apache.poi.ss.usermodel.helpers.ColumnShifter; -import org.apache.poi.util.Beta; -import org.apache.poi.xssf.usermodel.XSSFSheet; - -/** - * Helper for shifting columns up or down - * - * @since POI 4.0.0 - */ -// non-Javadoc: When possible, code should be implemented in the ColumnShifter abstract class to avoid duplication with -// {@link org.apache.poi.hssf.usermodel.helpers.HSSFColumnShifter} -@Beta -public final class XSSFColumnShifter extends ColumnShifter { - private static final Logger LOG = LogManager.getLogger(XSSFColumnShifter.class); - - public XSSFColumnShifter(XSSFSheet sh) { - super(sh); - } - - @Override - public void updateNamedRanges(FormulaShifter formulaShifter) { - XSSFRowColShifter.updateNamedRanges(sheet, formulaShifter); - } - - @Override - public void updateFormulas(FormulaShifter formulaShifter) { - XSSFRowColShifter.updateFormulas(sheet, formulaShifter); - } - - @Override - public void updateConditionalFormatting(FormulaShifter formulaShifter) { - XSSFRowColShifter.updateConditionalFormatting(sheet, formulaShifter); - } - - @Override - public void updateHyperlinks(FormulaShifter formulaShifter) { - XSSFRowColShifter.updateHyperlinks(sheet, formulaShifter); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java deleted file mode 100644 index 926e2a2d87..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * ==================================================================== - * 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.helpers; - -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.ooxml.POIXMLDocumentPart; -import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaRenderer; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.formula.ptg.Pxg; -import org.apache.poi.ss.formula.ptg.Pxg3D; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.xssf.usermodel.XSSFCell; -import org.apache.poi.xssf.usermodel.XSSFChart; -import org.apache.poi.xssf.usermodel.XSSFDrawing; -import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook; -import org.apache.poi.xssf.usermodel.XSSFName; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * Utility to update formulas and named ranges when a sheet name was changed - * - * @author Yegor Kozlov - */ -public final class XSSFFormulaUtils { - private final XSSFWorkbook _wb; - private final XSSFEvaluationWorkbook _fpwb; - - public XSSFFormulaUtils(XSSFWorkbook wb) { - _wb = wb; - _fpwb = XSSFEvaluationWorkbook.create(_wb); - } - - /** - * Update sheet name in all charts, formulas and named ranges. - * Called from {@link XSSFWorkbook#setSheetName(int, String)} - * <p> - * <p> - * The idea is to parse every formula and render it back to string - * with the updated sheet name. This is done by parsing into Ptgs, - * looking for ones with sheet references in them, and changing those - * </p> - * - * @param sheetIndex the 0-based index of the sheet being changed - * @param oldName the old sheet name - * @param newName the new sheet name - */ - public void updateSheetName(final int sheetIndex, final String oldName, final String newName) { - // update named ranges - for (XSSFName nm : _wb.getAllNames()) { - if (nm.getSheetIndex() == -1 || nm.getSheetIndex() == sheetIndex) { - updateName(nm, oldName, newName); - } - } - - // update formulas - for (Sheet sh : _wb) { - for (Row row : sh) { - for (Cell cell : row) { - if (cell.getCellType() == CellType.FORMULA) { - updateFormula((XSSFCell) cell, oldName, newName); - } - } - } - } - - // update charts - List<POIXMLDocumentPart> rels = _wb.getSheetAt(sheetIndex).getRelations(); - for (POIXMLDocumentPart r : rels) { - if (r instanceof XSSFDrawing) { - XSSFDrawing dg = (XSSFDrawing) r; - Iterator<XSSFChart> it = dg.getCharts().iterator(); - while (it.hasNext()) { - XSSFChart chart = it.next(); - Node dom = chart.getCTChartSpace().getDomNode(); - updateDomSheetReference(dom, oldName, newName); - } - } - } - } - - /** - * Parse cell formula and re-assemble it back using the new sheet name - * - * @param cell the cell to update - */ - private void updateFormula(XSSFCell cell, String oldName, String newName) { - CTCellFormula f = cell.getCTCell().getF(); - if (f != null) { - String formula = f.getStringValue(); - if (formula != null && formula.length() > 0) { - int sheetIndex = _wb.getSheetIndex(cell.getSheet()); - Ptg[] ptgs = FormulaParser.parse(formula, _fpwb, FormulaType.CELL, sheetIndex, cell.getRowIndex()); - for (Ptg ptg : ptgs) { - updatePtg(ptg, oldName, newName); - } - String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs); - if (!formula.equals(updatedFormula)) { - f.setStringValue(updatedFormula); - } - } - } - } - - /** - * Parse formula in the named range and re-assemble it back using the new sheet name. - * - * @param name the name to update - */ - private void updateName(XSSFName name, String oldName, String newName) { - String formula = name.getRefersToFormula(); - if (formula != null) { - int sheetIndex = name.getSheetIndex(); - int rowIndex = -1; //don't care - Ptg[] ptgs = FormulaParser.parse(formula, _fpwb, FormulaType.NAMEDRANGE, sheetIndex, rowIndex); - for (Ptg ptg : ptgs) { - updatePtg(ptg, oldName, newName); - } - String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs); - if (!formula.equals(updatedFormula)) { - name.setRefersToFormula(updatedFormula); - } - } - } - - private void updatePtg(Ptg ptg, String oldName, String newName) { - if (ptg instanceof Pxg) { - Pxg pxg = (Pxg)ptg; - if (pxg.getExternalWorkbookNumber() < 1) { - if (pxg.getSheetName() != null && - pxg.getSheetName().equals(oldName)) { - pxg.setSheetName(newName); - } - if (pxg instanceof Pxg3D) { - Pxg3D pxg3D = (Pxg3D)pxg; - if (pxg3D.getLastSheetName() != null && - pxg3D.getLastSheetName().equals(oldName)) { - pxg3D.setLastSheetName(newName); - } - } - } - } - } - - - /** - * Parse the DOM tree recursively searching for text containing reference to the old sheet name and replacing it. - * - * @param dom the XML node in which to perform the replacement. - * - * Code extracted from: <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=54470">Bug 54470</a> - */ - private void updateDomSheetReference(Node dom, final String oldName, final String newName) { - String value = dom.getNodeValue(); - if (value != null) { - // make sure the value contains the old sheet and not a similar sheet - // (ex: Valid: 'Sheet1'! or Sheet1! ; NotValid: 'Sheet1Test'! or Sheet1Test!) - if (value.contains(oldName+"!") || value.contains(oldName+"'!")) { - XSSFName temporary = _wb.createName(); - temporary.setRefersToFormula(value); - updateName(temporary, oldName, newName); - dom.setNodeValue(temporary.getRefersToFormula()); - _wb.removeName(temporary); - } - } - NodeList nl = dom.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - updateDomSheetReference(nl.item(i), oldName, newName); - } - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFIgnoredErrorHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFIgnoredErrorHelper.java deleted file mode 100644 index 2fd4218ca6..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFIgnoredErrorHelper.java +++ /dev/null @@ -1,106 +0,0 @@ -/* ==================================================================== - 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.helpers; - -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; - -import org.apache.poi.ss.usermodel.IgnoredErrorType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIgnoredError; - -/** - * XSSF-specific code for working with ignored errors - */ -public class XSSFIgnoredErrorHelper { - public static boolean isSet(IgnoredErrorType errorType, CTIgnoredError error) { - switch(errorType) { - case CALCULATED_COLUMN: - return error.isSetCalculatedColumn(); - case EMPTY_CELL_REFERENCE: - return error.isSetEmptyCellReference(); - case EVALUATION_ERROR: - return error.isSetEvalError(); - case FORMULA: - return error.isSetFormula(); - case FORMULA_RANGE: - return error.isSetFormulaRange(); - case LIST_DATA_VALIDATION: - return error.isSetListDataValidation(); - case NUMBER_STORED_AS_TEXT: - return error.isSetNumberStoredAsText(); - case TWO_DIGIT_TEXT_YEAR: - return error.isSetTwoDigitTextYear(); - case UNLOCKED_FORMULA: - return error.isSetUnlockedFormula(); - default: - throw new IllegalStateException(); - } - } - - public static void set(IgnoredErrorType errorType, CTIgnoredError error) { - switch(errorType) { - case CALCULATED_COLUMN: - error.setCalculatedColumn(true); - break; - case EMPTY_CELL_REFERENCE: - error.setEmptyCellReference(true); - break; - case EVALUATION_ERROR: - error.setEvalError(true); - break; - case FORMULA: - error.setFormula(true); - break; - case FORMULA_RANGE: - error.setFormulaRange(true); - break; - case LIST_DATA_VALIDATION: - error.setListDataValidation(true); - break; - case NUMBER_STORED_AS_TEXT: - error.setNumberStoredAsText(true); - break; - case TWO_DIGIT_TEXT_YEAR: - error.setTwoDigitTextYear(true); - break; - case UNLOCKED_FORMULA: - error.setUnlockedFormula(true); - break; - default: - throw new IllegalStateException(); - } - } - - public static void addIgnoredErrors(CTIgnoredError err, String ref, IgnoredErrorType... ignoredErrorTypes) { - err.setSqref(Collections.singletonList(ref)); - for (IgnoredErrorType errType : ignoredErrorTypes) { - XSSFIgnoredErrorHelper.set(errType, err); - } - } - - public static Set<IgnoredErrorType> getErrorTypes(CTIgnoredError err) { - Set<IgnoredErrorType> result = new LinkedHashSet<>(); - for (IgnoredErrorType errType : IgnoredErrorType.values()) { - if (XSSFIgnoredErrorHelper.isSet(errType, err)) { - result.add(errType); - } - } - return result; - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPasswordHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPasswordHelper.java deleted file mode 100644 index 167cee14ff..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFPasswordHelper.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * ==================================================================== - * 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.helpers; - -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.Base64; -import java.util.Locale; - -import javax.xml.namespace.QName; - -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.util.Internal; -import org.apache.poi.util.StringUtil; -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; - -@Internal(since="3.15 beta 3") -public final class XSSFPasswordHelper { - private XSSFPasswordHelper() { - // no instances of this static class - } - - /** - * Sets the XORed or hashed password - * - * @param xobj the xmlbeans object which contains the password attributes - * @param password the password, if null, the password attributes will be removed - * @param hashAlgo the hash algorithm, if null the password will be XORed - * @param prefix the prefix of the password attributes, may be null - */ - public static void setPassword(XmlObject xobj, String password, HashAlgorithm hashAlgo, String prefix) { - XmlCursor cur = xobj.newCursor(); - - if (password == null) { - cur.removeAttribute(getAttrName(prefix, "password")); - cur.removeAttribute(getAttrName(prefix, "algorithmName")); - cur.removeAttribute(getAttrName(prefix, "hashValue")); - cur.removeAttribute(getAttrName(prefix, "saltValue")); - cur.removeAttribute(getAttrName(prefix, "spinCount")); - return; - } - - cur.toFirstContentToken(); - if (hashAlgo == null) { - int hash = CryptoFunctions.createXorVerifier1(password); - cur.insertAttributeWithValue(getAttrName(prefix, "password"), - String.format(Locale.ROOT, "%04X", hash).toUpperCase(Locale.ROOT)); - } else { - SecureRandom random = new SecureRandom(); - byte[] salt = random.generateSeed(16); - - // Iterations specifies the number of times the hashing function shall be iteratively run (using each - // iteration's result as the input for the next iteration). - int spinCount = 100000; - - // Implementation Notes List: - // --> In this third stage, the reversed byte order legacy hash from the second stage shall - // be converted to Unicode hex string representation - byte[] hash = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCount, false); - - Base64.Encoder enc64 = Base64.getEncoder(); - - cur.insertAttributeWithValue(getAttrName(prefix, "algorithmName"), hashAlgo.jceId); - cur.insertAttributeWithValue(getAttrName(prefix, "hashValue"), enc64.encodeToString(hash)); - cur.insertAttributeWithValue(getAttrName(prefix, "saltValue"), enc64.encodeToString(salt)); - cur.insertAttributeWithValue(getAttrName(prefix, "spinCount"), ""+spinCount); - } - cur.dispose(); - } - - /** - * Validates the password, i.e. - * calculates the hash of the given password and compares it against the stored hash - * - * @param xobj the xmlbeans object which contains the password attributes - * @param password the password, if null the method will always return false, - * even if there's no password set - * @param prefix the prefix of the password attributes, may be null - * - * @return true, if the hashes match - */ - public static boolean validatePassword(XmlObject xobj, String password, String prefix) { - // TODO: is "velvetSweatshop" the default password? - if (password == null) return false; - - XmlCursor cur = xobj.newCursor(); - String xorHashVal = cur.getAttributeText(getAttrName(prefix, "password")); - String algoName = cur.getAttributeText(getAttrName(prefix, "algorithmName")); - String hashVal = cur.getAttributeText(getAttrName(prefix, "hashValue")); - String saltVal = cur.getAttributeText(getAttrName(prefix, "saltValue")); - String spinCount = cur.getAttributeText(getAttrName(prefix, "spinCount")); - cur.dispose(); - - if (xorHashVal != null) { - int hash1 = Integer.parseInt(xorHashVal, 16); - int hash2 = CryptoFunctions.createXorVerifier1(password); - return hash1 == hash2; - } else { - if (hashVal == null || algoName == null || saltVal == null || spinCount == null) { - return false; - } - - Base64.Decoder dec64 = Base64.getDecoder(); - - byte[] hash1 = dec64.decode(hashVal); - HashAlgorithm hashAlgo = HashAlgorithm.fromString(algoName); - byte[] salt = dec64.decode(saltVal); - int spinCnt = Integer.parseInt(spinCount); - byte[] hash2 = CryptoFunctions.hashPassword(password, hashAlgo, salt, spinCnt, false); - return Arrays.equals(hash1, hash2); - } - } - - - private static QName getAttrName(String prefix, String name) { - if (prefix == null || prefix.isEmpty()) { - return new QName(name); - } else { - return new QName(prefix + StringUtil.toUpperCase(name.charAt(0)) + name.substring(1)); - } - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowColShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowColShifter.java deleted file mode 100644 index 298fa3f48f..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowColShifter.java +++ /dev/null @@ -1,252 +0,0 @@ -/* ==================================================================== - 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.helpers; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.ss.formula.FormulaShifter; -import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.formula.FormulaRenderer; -import org.apache.poi.ss.formula.FormulaParseException; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.ss.usermodel.helpers.BaseRowColShifter; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.util.Internal; -import org.apache.poi.xssf.usermodel.*; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; - -import java.util.ArrayList; -import java.util.List; - -import static org.apache.logging.log4j.util.Unbox.box; - -/** - * Class for code common to {@link XSSFRowShifter} and {@link XSSFColumnShifter} - * - * @since POI 4.0.0 - */ -@Internal -/*private*/ final class XSSFRowColShifter { - private static final Logger LOG = LogManager.getLogger(XSSFRowColShifter.class); - - private XSSFRowColShifter() { /*no instances for static classes*/} - - /** - * Updated named ranges - */ - /*package*/ - static void updateNamedRanges(Sheet sheet, FormulaShifter formulaShifter) { - Workbook wb = sheet.getWorkbook(); - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb); - for (Name name : wb.getAllNames()) { - String formula = name.getRefersToFormula(); - int sheetIndex = name.getSheetIndex(); - final int rowIndex = -1; //don't care, named ranges are not allowed to include structured references - - Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex, rowIndex); - if (formulaShifter.adjustFormula(ptgs, sheetIndex)) { - String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); - name.setRefersToFormula(shiftedFmla); - } - } - } - - /** - * Update formulas. - */ - /*package*/ static void updateFormulas(Sheet sheet, FormulaShifter formulaShifter) { - //update formulas on the parent sheet - updateSheetFormulas(sheet,formulaShifter); - - //update formulas on other sheets - Workbook wb = sheet.getWorkbook(); - for(Sheet sh : wb) - { - if (sheet == sh) continue; - updateSheetFormulas(sh, formulaShifter); - } - } - - /*package*/ static void updateSheetFormulas(Sheet sh, FormulaShifter formulashifter) { - for (Row r : sh) { - XSSFRow row = (XSSFRow) r; - updateRowFormulas(row, formulashifter); - } - } - - /** - * Update the formulas in specified row using the formula shifting policy specified by shifter - * - * @param row the row to update the formulas on - * @param formulaShifter the formula shifting policy - */ - /*package*/ static void updateRowFormulas(XSSFRow row, FormulaShifter formulaShifter) { - XSSFSheet sheet = row.getSheet(); - for (Cell c : row) { - XSSFCell cell = (XSSFCell) c; - - CTCell ctCell = cell.getCTCell(); - if (ctCell.isSetF()) { - CTCellFormula f = ctCell.getF(); - String formula = f.getStringValue(); - if (formula.length() > 0) { - String shiftedFormula = shiftFormula(row, formula, formulaShifter); - if (shiftedFormula != null) { - f.setStringValue(shiftedFormula); - if(f.getT() == STCellFormulaType.SHARED){ - int si = Math.toIntExact(f.getSi()); - CTCellFormula sf = sheet.getSharedFormula(si); - sf.setStringValue(shiftedFormula); - updateRefInCTCellFormula(row, formulaShifter, sf); - } - } - - } - - //Range of cells which the formula applies to. - updateRefInCTCellFormula(row, formulaShifter, f); - } - - } - } - - /** - * Shift a formula using the supplied FormulaShifter - * - * @param row the row of the cell this formula belongs to. Used to get a reference to the parent workbook. - * @param formula the formula to shift - * @param formulaShifter the FormulaShifter object that operates on the parsed formula tokens - * @return the shifted formula if the formula was changed, - * <code>null</code> if the formula wasn't modified - */ - /*package*/ - static String shiftFormula(Row row, String formula, FormulaShifter formulaShifter) { - Sheet sheet = row.getSheet(); - Workbook wb = sheet.getWorkbook(); - int sheetIndex = wb.getSheetIndex(sheet); - final int rowIndex = row.getRowNum(); - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb); - - try { - Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, rowIndex); - String shiftedFmla = null; - if (formulaShifter.adjustFormula(ptgs, sheetIndex)) { - shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); - } - return shiftedFmla; - } catch (FormulaParseException fpe) { - // Log, but don't change, rather than breaking - LOG.atWarn().withThrowable(fpe).log("Error shifting formula on row {}", box(row.getRowNum())); - return formula; - } - } - - /*package*/ - static void updateRefInCTCellFormula(Row row, FormulaShifter formulaShifter, CTCellFormula f) { - if (f.isSetRef()) { //Range of cells which the formula applies to. - String ref = f.getRef(); - String shiftedRef = shiftFormula(row, ref, formulaShifter); - if (shiftedRef != null) f.setRef(shiftedRef); - } - } - - - - /*package*/ static void updateConditionalFormatting(Sheet sheet, FormulaShifter formulaShifter) { - XSSFSheet xsheet = (XSSFSheet) sheet; - XSSFWorkbook wb = xsheet.getWorkbook(); - int sheetIndex = wb.getSheetIndex(sheet); - final int rowIndex = -1; //don't care, structured references not allowed in conditional formatting - - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); - CTWorksheet ctWorksheet = xsheet.getCTWorksheet(); - CTConditionalFormatting[] conditionalFormattingArray = ctWorksheet.getConditionalFormattingArray(); - // iterate backwards due to possible calls to ctWorksheet.removeConditionalFormatting(j) - for (int j = conditionalFormattingArray.length - 1; j >= 0; j--) { - CTConditionalFormatting cf = conditionalFormattingArray[j]; - - ArrayList<CellRangeAddress> cellRanges = new ArrayList<>(); - for (Object stRef : cf.getSqref()) { - String[] regions = stRef.toString().split(" "); - for (String region : regions) { - cellRanges.add(CellRangeAddress.valueOf(region)); - } - } - - boolean changed = false; - List<CellRangeAddress> temp = new ArrayList<>(); - for (CellRangeAddress craOld : cellRanges) { - CellRangeAddress craNew = BaseRowColShifter.shiftRange(formulaShifter, craOld, sheetIndex); - if (craNew == null) { - changed = true; - continue; - } - temp.add(craNew); - if (craNew != craOld) { - changed = true; - } - } - - if (changed) { - int nRanges = temp.size(); - if (nRanges == 0) { - ctWorksheet.removeConditionalFormatting(j); - continue; - } - List<String> refs = new ArrayList<>(); - for(CellRangeAddress a : temp) refs.add(a.formatAsString()); - cf.setSqref(refs); - } - - for(CTCfRule cfRule : cf.getCfRuleArray()){ - String[] formulaArray = cfRule.getFormulaArray(); - for (int i = 0; i < formulaArray.length; i++) { - String formula = formulaArray[i]; - Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, rowIndex); - if (formulaShifter.adjustFormula(ptgs, sheetIndex)) { - String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); - cfRule.setFormulaArray(i, shiftedFmla); - } - } - } - } - } - - - /*package*/ static void updateHyperlinks(Sheet sheet, FormulaShifter formulaShifter) { - int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); - List<? extends Hyperlink> hyperlinkList = sheet.getHyperlinkList(); - - for (Hyperlink hyperlink : hyperlinkList) { - XSSFHyperlink xhyperlink = (XSSFHyperlink) hyperlink; - String cellRef = xhyperlink.getCellRef(); - CellRangeAddress cra = CellRangeAddress.valueOf(cellRef); - CellRangeAddress shiftedRange = BaseRowColShifter.shiftRange(formulaShifter, cra, sheetIndex); - if (shiftedRange != null && shiftedRange != cra) { - // shiftedRange should not be null. If shiftedRange is null, that means - // that a hyperlink wasn't deleted at the beginning of shiftRows when - // identifying rows that should be removed because they will be overwritten - xhyperlink.setCellReference(shiftedRange.formatAsString()); - } - } - } - - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java deleted file mode 100644 index ffbc570796..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java +++ /dev/null @@ -1,69 +0,0 @@ -/* ==================================================================== - 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.helpers; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.poi.ss.formula.FormulaShifter; -import org.apache.poi.ss.usermodel.helpers.RowShifter; -import org.apache.poi.util.Internal; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; - -/** - * Helper for shifting rows up or down - */ -// non-Javadoc: When possible, code should be implemented in the RowShifter abstract class to avoid duplication with -// {@link org.apache.poi.hssf.usermodel.helpers.HSSFRowShifter} -public final class XSSFRowShifter extends RowShifter { - private static final Logger LOG = LogManager.getLogger(XSSFRowShifter.class); - - public XSSFRowShifter(XSSFSheet sh) { - super(sh); - } - @Override - public void updateNamedRanges(FormulaShifter formulaShifter) { - XSSFRowColShifter.updateNamedRanges(sheet, formulaShifter); - } - - @Override - public void updateFormulas(FormulaShifter formulaShifter) { - XSSFRowColShifter.updateFormulas(sheet, formulaShifter); - } - - /** - * Update the formulas in specified row using the formula shifting policy specified by shifter - * - * @param row the row to update the formulas on - * @param formulaShifter the formula shifting policy - */ - @Internal(since="3.15 beta 2") - public void updateRowFormulas(XSSFRow row, FormulaShifter formulaShifter) { - XSSFRowColShifter.updateRowFormulas(row, formulaShifter); - } - - @Override - public void updateConditionalFormatting(FormulaShifter formulaShifter) { - XSSFRowColShifter.updateConditionalFormatting(sheet, formulaShifter); - } - - @Override - public void updateHyperlinks(FormulaShifter formulaShifter) { - XSSFRowColShifter.updateHyperlinks(sheet, formulaShifter); - } -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFSingleXmlCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFSingleXmlCell.java deleted file mode 100644 index 79cc921a34..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFSingleXmlCell.java +++ /dev/null @@ -1,89 +0,0 @@ -/* ==================================================================== - 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.helpers; - -import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.model.SingleXmlCells; -import org.apache.poi.xssf.usermodel.XSSFCell; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSingleXmlCell; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlCellPr; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlPr; - -/** - * - * This class is a wrapper around the CTSingleXmlCell (Open Office XML Part 4: - * chapter 3.5.2.1) - * - - * - * @author Roberto Manicardi - * - */ -public class XSSFSingleXmlCell { - - private CTSingleXmlCell singleXmlCell; - private SingleXmlCells parent; - - - public XSSFSingleXmlCell(CTSingleXmlCell singleXmlCell, SingleXmlCells parent){ - this.singleXmlCell = singleXmlCell; - this.parent = parent; - } - - /** - * Gets the XSSFCell referenced by the R attribute or creates a new one if cell doesn't exists - * @return the referenced XSSFCell, null if the cell reference is invalid - */ - public XSSFCell getReferencedCell(){ - XSSFCell cell = null; - - - CellReference cellReference = new CellReference(singleXmlCell.getR()); - - XSSFRow row = parent.getXSSFSheet().getRow(cellReference.getRow()); - if(row==null){ - row = parent.getXSSFSheet().createRow(cellReference.getRow()); - } - - cell = row.getCell(cellReference.getCol()); - if(cell==null){ - cell = row.createCell(cellReference.getCol()); - } - - - return cell; - } - - public String getXpath(){ - CTXmlCellPr xmlCellPr = singleXmlCell.getXmlCellPr(); - CTXmlPr xmlPr = xmlCellPr.getXmlPr(); - return xmlPr.getXpath(); - } - - public long getMapId(){ - return singleXmlCell.getXmlCellPr().getXmlPr().getMapId(); - } - - public String getXmlDataType() { - CTXmlCellPr xmlCellPr = singleXmlCell.getXmlCellPr(); - CTXmlPr xmlPr = xmlCellPr.getXmlPr(); - return xmlPr.getXmlDataType(); - } - -} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java deleted file mode 100644 index 08e9ca05c1..0000000000 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFXmlColumnPr.java +++ /dev/null @@ -1,94 +0,0 @@ -/* ==================================================================== - 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.helpers; - -import org.apache.poi.util.Internal; -import org.apache.poi.xssf.usermodel.XSSFTable; -import org.apache.poi.xssf.usermodel.XSSFTableColumn; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlColumnPr; - -/** - * - * This class is a wrapper around the CTXmlColumnPr (Open Office XML Part 4: - * chapter 3.5.1.7) - * - * - * @author Roberto Manicardi - */ -public class XSSFXmlColumnPr { - - 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; - } - - /** - * 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(); - } - - /** - * 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 String getXmlDataType() { - - return ctXmlColumnPr.getXmlDataType(); - } - -} |