extract valuable code from 54470 submitted patch
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1842548 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
11dee9b086
commit
72d02f0c1c
@ -23,4 +23,23 @@ import org.apache.poi.util.Beta;
|
|||||||
|
|
||||||
@Beta
|
@Beta
|
||||||
public interface XDDFCategoryDataSource extends XDDFDataSource<String> {
|
public interface XDDFCategoryDataSource extends XDDFDataSource<String> {
|
||||||
|
@Override
|
||||||
|
default int getColIndex() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean isNumeric() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean isReference() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default String getDataRangeReference() {
|
||||||
|
return getFormula();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,4 +34,6 @@ public interface XDDFDataSource<T> {
|
|||||||
int getColIndex();
|
int getColIndex();
|
||||||
|
|
||||||
String getDataRangeReference();
|
String getDataRangeReference();
|
||||||
|
|
||||||
|
String getFormula();
|
||||||
}
|
}
|
||||||
|
@ -41,17 +41,18 @@ public class XDDFDataSourcesFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static XDDFCategoryDataSource fromDataSource(final CTAxDataSource categoryDS) {
|
public static XDDFCategoryDataSource fromDataSource(final CTAxDataSource categoryDS) {
|
||||||
|
if (categoryDS.getStrRef() == null) {
|
||||||
return new XDDFCategoryDataSource() {
|
return new XDDFCategoryDataSource() {
|
||||||
private CTStrData category = (CTStrData) categoryDS.getStrRef().getStrCache().copy();
|
private CTNumData category = (CTNumData) categoryDS.getNumRef().getNumCache().copy();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isNumeric() {
|
public boolean isNumeric() {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isReference() {
|
public String getFormula() {
|
||||||
return true;
|
return categoryDS.getNumRef().getF();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -63,24 +64,39 @@ public class XDDFDataSourcesFactory {
|
|||||||
public String getPointAt(int index) {
|
public String getPointAt(int index) {
|
||||||
return category.getPtArray(index).getV();
|
return category.getPtArray(index).getV();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return new XDDFCategoryDataSource() {
|
||||||
|
private CTStrData category = (CTStrData) categoryDS.getStrRef().getStrCache().copy();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDataRangeReference() {
|
public String getFormula() {
|
||||||
return categoryDS.getStrRef().getF();
|
return categoryDS.getStrRef().getF();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getColIndex() {
|
public int getPointCount() {
|
||||||
return 0;
|
return (int) category.getPtCount().getVal();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPointAt(int index) {
|
||||||
|
return category.getPtArray(index).getV();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static XDDFNumericalDataSource<Double> fromDataSource(final CTNumDataSource valuesDS) {
|
public static XDDFNumericalDataSource<Double> fromDataSource(final CTNumDataSource valuesDS) {
|
||||||
return new XDDFNumericalDataSource<Double>() {
|
return new XDDFNumericalDataSource<Double>() {
|
||||||
private CTNumData values = (CTNumData) valuesDS.getNumRef().getNumCache().copy();
|
private CTNumData values = (CTNumData) valuesDS.getNumRef().getNumCache().copy();
|
||||||
private String formatCode = values.isSetFormatCode() ? values.getFormatCode() : null;
|
private String formatCode = values.isSetFormatCode() ? values.getFormatCode() : null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFormula() {
|
||||||
|
return valuesDS.getNumRef().getF();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFormatCode() {
|
public String getFormatCode() {
|
||||||
return formatCode;
|
return formatCode;
|
||||||
@ -124,7 +140,7 @@ public class XDDFDataSourcesFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange) {
|
public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange) {
|
||||||
return new NumericalArrayDataSource<T>(elements, dataRange);
|
return new NumericalArrayDataSource<>(elements, dataRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange) {
|
public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange) {
|
||||||
@ -132,7 +148,7 @@ public class XDDFDataSourcesFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange, int col) {
|
public static <T extends Number> XDDFNumericalDataSource<T> fromArray(T[] elements, String dataRange, int col) {
|
||||||
return new NumericalArrayDataSource<T>(elements, dataRange, col);
|
return new NumericalArrayDataSource<>(elements, dataRange, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange, int col) {
|
public static XDDFCategoryDataSource fromArray(String[] elements, String dataRange, int col) {
|
||||||
@ -212,6 +228,11 @@ public class XDDFDataSourcesFactory {
|
|||||||
super(elements, dataRange, col);
|
super(elements, dataRange, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFormula() {
|
||||||
|
return getDataRangeReference();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFormatCode() {
|
public String getFormatCode() {
|
||||||
return formatCode;
|
return formatCode;
|
||||||
@ -232,6 +253,11 @@ public class XDDFDataSourcesFactory {
|
|||||||
public StringArrayDataSource(String[] elements, String dataRange, int col) {
|
public StringArrayDataSource(String[] elements, String dataRange, int col) {
|
||||||
super(elements, dataRange, col);
|
super(elements, dataRange, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFormula() {
|
||||||
|
return getDataRangeReference();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract static class AbstractCellRangeDataSource<T> implements XDDFDataSource<T> {
|
private abstract static class AbstractCellRangeDataSource<T> implements XDDFDataSource<T> {
|
||||||
@ -290,6 +316,11 @@ public class XDDFDataSourcesFactory {
|
|||||||
super(sheet, cellRangeAddress);
|
super(sheet, cellRangeAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFormula() {
|
||||||
|
return getDataRangeReference();
|
||||||
|
}
|
||||||
|
|
||||||
private String formatCode;
|
private String formatCode;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -324,6 +355,11 @@ public class XDDFDataSourcesFactory {
|
|||||||
super(sheet, cellRangeAddress);
|
super(sheet, cellRangeAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFormula() {
|
||||||
|
return getDataRangeReference();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPointAt(int index) {
|
public String getPointAt(int index) {
|
||||||
CellValue cellValue = getCellValueAt(index);
|
CellValue cellValue = getCellValueAt(index);
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
package org.apache.poi.xssf.usermodel.helpers;
|
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.FormulaParser;
|
||||||
import org.apache.poi.ss.formula.FormulaRenderer;
|
import org.apache.poi.ss.formula.FormulaRenderer;
|
||||||
import org.apache.poi.ss.formula.FormulaType;
|
import org.apache.poi.ss.formula.FormulaType;
|
||||||
@ -30,10 +34,14 @@ import org.apache.poi.ss.usermodel.CellType;
|
|||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFCell;
|
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.XSSFEvaluationWorkbook;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFName;
|
import org.apache.poi.xssf.usermodel.XSSFName;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
|
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
|
* Utility to update formulas and named ranges when a sheet name was changed
|
||||||
@ -50,7 +58,7 @@ public final class XSSFFormulaUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update sheet name in all formulas and named ranges.
|
* Update sheet name in all charts, formulas and named ranges.
|
||||||
* Called from {@link XSSFWorkbook#setSheetName(int, String)}
|
* Called from {@link XSSFWorkbook#setSheetName(int, String)}
|
||||||
* <p>
|
* <p>
|
||||||
* <p>
|
* <p>
|
||||||
@ -81,6 +89,20 @@ public final class XSSFFormulaUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,7 +121,9 @@ public final class XSSFFormulaUtils {
|
|||||||
updatePtg(ptg, oldName, newName);
|
updatePtg(ptg, oldName, newName);
|
||||||
}
|
}
|
||||||
String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs);
|
String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs);
|
||||||
if (!formula.equals(updatedFormula)) f.setStringValue(updatedFormula);
|
if (!formula.equals(updatedFormula)) {
|
||||||
|
f.setStringValue(updatedFormula);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +143,9 @@ public final class XSSFFormulaUtils {
|
|||||||
updatePtg(ptg, oldName, newName);
|
updatePtg(ptg, oldName, newName);
|
||||||
}
|
}
|
||||||
String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs);
|
String updatedFormula = FormulaRenderer.toFormulaString(_fpwb, ptgs);
|
||||||
if (!formula.equals(updatedFormula)) name.setRefersToFormula(updatedFormula);
|
if (!formula.equals(updatedFormula)) {
|
||||||
|
name.setRefersToFormula(updatedFormula);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,4 +167,32 @@ public final class XSSFFormulaUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ import java.util.List;
|
|||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.ooxml.POIXMLProperties;
|
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
|
import org.apache.poi.ooxml.POIXMLProperties;
|
||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.apache.poi.openxml4j.opc.ContentTypes;
|
import org.apache.poi.openxml4j.opc.ContentTypes;
|
||||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
@ -67,6 +67,8 @@ import org.apache.poi.ss.util.CellReference;
|
|||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
import org.apache.poi.util.TempFile;
|
import org.apache.poi.util.TempFile;
|
||||||
|
import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
|
||||||
|
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
|
||||||
import org.apache.poi.xssf.XSSFITestDataProvider;
|
import org.apache.poi.xssf.XSSFITestDataProvider;
|
||||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
import org.apache.poi.xssf.model.StylesTable;
|
import org.apache.poi.xssf.model.StylesTable;
|
||||||
@ -553,7 +555,9 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
|
|||||||
Sheet sheet = wb.getSheetAt(0);
|
Sheet sheet = wb.getSheetAt(0);
|
||||||
sheet.shiftRows(2, sheet.getLastRowNum(), 1, true, false);
|
sheet.shiftRows(2, sheet.getLastRowNum(), 1, true, false);
|
||||||
Row newRow = sheet.getRow(2);
|
Row newRow = sheet.getRow(2);
|
||||||
if (newRow == null) newRow = sheet.createRow(2);
|
if (newRow == null) {
|
||||||
|
newRow = sheet.createRow(2);
|
||||||
|
}
|
||||||
newRow.createCell(0).setCellValue(" Another Header");
|
newRow.createCell(0).setCellValue(" Another Header");
|
||||||
wb.cloneSheet(0);
|
wb.cloneSheet(0);
|
||||||
|
|
||||||
@ -700,6 +704,24 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bug60509() throws Exception {
|
||||||
|
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("60509.xlsx");
|
||||||
|
assertSheetOrder(wb, "Sheet1", "Sheet2", "Sheet3");
|
||||||
|
int sheetIndex = wb.getSheetIndex("Sheet1");
|
||||||
|
wb.setSheetName(sheetIndex, "Sheet1-Renamed");
|
||||||
|
Workbook read = XSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||||
|
assertNotNull(read);
|
||||||
|
assertSheetOrder(read, "Sheet1-Renamed", "Sheet2", "Sheet3");
|
||||||
|
XSSFSheet sheet = (XSSFSheet) read.getSheet("Sheet1-Renamed");
|
||||||
|
XDDFChartData.Series series = sheet.getDrawingPatriarch().getCharts().get(0).getChartSeries().get(0).getSeries().get(0);
|
||||||
|
assertTrue("should be a bar chart data series", series instanceof XDDFBarChartData.Series);
|
||||||
|
String formula = ((XDDFBarChartData.Series) series).getCategoryData().getFormula();
|
||||||
|
assertTrue("should contain new sheet name", formula.startsWith("'Sheet1-Renamed'!"));
|
||||||
|
read.close();
|
||||||
|
wb.close();
|
||||||
|
}
|
||||||
|
|
||||||
private static final int INDEX_NOT_FOUND = -1;
|
private static final int INDEX_NOT_FOUND = -1;
|
||||||
|
|
||||||
private static boolean isEmpty(CharSequence cs) {
|
private static boolean isEmpty(CharSequence cs) {
|
||||||
|
BIN
test-data/spreadsheet/60509.xlsx
Executable file
BIN
test-data/spreadsheet/60509.xlsx
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user