Использование apache poi 4.0.1
изменение XDDFChart данные требуют параллельного обновления всех изменений в базовой книге данных диаграммы и самой диаграмме.Диаграмма содержит кэшированные данные, а рабочая книга содержит исходные данные.Но и то и другое возможно с использованием классов высокого уровня apache poi
.Нет необходимости в доступе к базовым XML-компонентам.
Пример
Шаблон Word, в котором шаблонная таблица имеет 2 серии и 3 категории:
Код:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.CellRangeAddress;
public class WordChangeChartData {
public static void main(String[] args) throws Exception {
String filePath = "TEMP_Chart_Simple.docx"; // has template chart having 2 series, 3 categories
String filePathNew = "New_Chart_Simple.docx";
Object[][] data = new Object[][] { // 2 series, 3 categories
{"", "male", "female"}, // series titles
{"health", 123d, 234d}, // category 1
{"amount", 345d, 123d}, // category 2
{"size", 180d, 160d} // category 3
};
XWPFDocument document = new XWPFDocument(new FileInputStream(filePath));
XWPFChart chart = document.getCharts().get(0);
XSSFWorkbook chartDataWorkbook = chart.getWorkbook();
String sheetName = chartDataWorkbook.getSheetName(0);
XSSFSheet chartDataSheet = chartDataWorkbook.getSheet(sheetName);
if (chart.getChartSeries().size() == 1) { // only one chart data
XDDFChartData chartData = chart.getChartSeries().get(0);
if (chartData.getSeries().size() == 2) { // exact two series
int rMin = 1;
int rMax = 3;
// set new category data (both series)
XDDFCategoryDataSource category = null;
int c = 0;
for (int r = rMin; r < rMax+1; r++) {
chartDataSheet.getRow(r).getCell(c).setCellValue((String)data[r][c]); // in sheet
}
category = XDDFDataSourcesFactory.fromStringCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c)); // in chart
// series 1
XDDFChartData.Series series1 = chartData.getSeries().get(0);
c = 1;
// set new title
String series1Title = (String)data[0][c];
chartDataSheet.getRow(0).getCell(c).setCellValue(series1Title); // in sheet
series1.setTitle(series1Title, new CellReference(sheetName, 0, c, true, true)); // in chart
// set new values
XDDFNumericalDataSource<Double> values = null;
for (int r = rMin; r < rMax+1; r++) {
chartDataSheet.getRow(r).getCell(c).setCellValue((Double)data[r][c]); // in sheet
}
values = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c));
series1.replaceData(category, values);
series1.plot(); //in chart
// series 2
XDDFChartData.Series series2 = chartData.getSeries().get(1);
c = 2;
// set new title
String series2Title = (String)data[0][c];
chartDataSheet.getRow(0).getCell(c).setCellValue(series2Title); // in sheet
series2.setTitle(series2Title, new CellReference(sheetName, 0, c, true, true)); // in chart
// set new values
for (int r = rMin; r < rMax+1; r++) {
chartDataSheet.getRow(r).getCell(c).setCellValue((Double)data[r][c]); // in sheet
}
values = XDDFDataSourcesFactory.fromNumericCellRange(chartDataSheet, new CellRangeAddress(rMin,rMax,c,c));
series2.replaceData(category, values);
series2.plot(); // in chart
}
}
FileOutputStream out = new FileOutputStream(filePathNew);
document.write(out);
out.close();
document.close();
}
}
Результат: