Ваш код, использующий классы низкого уровня ooxml-schemas
, обновляет только справочные формулы серии. Он не обновляет кэшированные значения в диаграмме.
Поскольку текущий apache poi 4.1.1
предоставляет XDDFChartData.Series.replaceData для обновления данных диаграммы, мы должны использовать это вместо низкого уровня ooxml-schemas
классы.
Давайте разберем полный пример, чтобы показать, как это сделать.
Мы начинаем с ExcelWithChartMar.xlsx
, который выглядит примерно так:
Как вы видите, есть данные графика в A1:D4
за месяцы с января по март уже и график, показывающий эти данные.
Что нам нужно знать: Первое строка данных равна 1 (строка 0 является строкой заголовка), а текущая последняя строка данных равна 3. Последняя строка данных увеличится. Столбец категории равен 0 (A
), а столбцы серии - 1 (B
), 2 (C
) и 3 (D
). Обратите внимание, что все индексы основаны на 0.
Теперь мы можем запустить следующий код, используя apache poi 4.1.1
:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
class ExcelChangeChartData {
static void updateChartData(XSSFChart chart, XSSFSheet dataSheet,
int firstDataRow, int lastDataRow, int categoryColumn, int[] seriesColumns) {
for (XDDFChartData chartData : chart.getChartSeries()) {
for (int s = 0; s < chartData.getSeriesCount() ; s++) {
XDDFChartData.Series series = chartData.getSeries(s);
if (seriesColumns.length > s) {
XDDFCategoryDataSource category = XDDFDataSourcesFactory.fromStringCellRange(
dataSheet, new CellRangeAddress(firstDataRow, lastDataRow, categoryColumn, categoryColumn));
int seriesColumn = seriesColumns[s];
XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(
dataSheet, new CellRangeAddress(firstDataRow, lastDataRow, seriesColumn, seriesColumn));
series.replaceData(category, values);
series.plot();
}
}
}
}
public static void main(String[] args) throws Exception {
String[] months = new String[]{"Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int firstDataRow = 1;
int lastDataRow = 3;
int categoryColumn = 0;
int[] seriesColumns = new int[]{1,2,3};
for (int m = 0; m < months.length - 1; m++) {
String monthSource = months[m];
String monthResult = months[m+1];
String filePath = "./ExcelWithChart" + monthSource + ".xlsx";
java.util.Random random = new java.util.Random();
XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream(filePath));
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.createRow(lastDataRow + 1);
XSSFCell cell = row.createCell(categoryColumn);
cell.setCellValue(monthResult);
for (int i = 0; i < seriesColumns.length; i++) {
cell = row.createCell(seriesColumns[i]);
cell.setCellValue(random.nextDouble() / 10 + 0.02);
cell.setCellStyle(sheet.getRow(lastDataRow).getCell(seriesColumns[i]).getCellStyle());
}
lastDataRow++;
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFChart chart = drawing.getCharts().get(0);
updateChartData(chart, sheet, firstDataRow, lastDataRow, categoryColumn, seriesColumns);
filePath = "./ExcelWithChart" + monthResult + ".xlsx";
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close();
workbook.close();
}
}
}
. Это создаст 9 дополнительных Excel
файлов ExcelWithChartApr.xlsx
... ExcelWithChartDec.xlsx
, где к каждому добавляются данные нового месяца.
Метод updateChartData
обновляет данные диаграммы с использованием метода XDDFChartData.Series.replaceData
.