我开发了包括图表的Word函数。 在Word文件中编辑图表数据时,它将返回到表单中定义的数据。
以下是步骤:
库-ooxml-schemas-1.3,poi-4.0.0-SNAPSHOT
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String inFilePath = "../file/temp/TEMP_Chart_Simple.docx";
String outFilePath = "../file/out/NEW_Chart_" + System.currentTimeMillis() + ".docx";
Map<String, Map<String, String>> CHART_MAP_DATA = new LinkedHashMap<>();
Map<String, String> inData = new LinkedHashMap<>();
inData.put("1", "8.3");
inData.put("2", "7.3");
CHART_MAP_DATA.put("temp", inData);
Path path = Paths.get(inFilePath);
byte[] byteData = Files.readAllBytes(path);
// read as XWPFDocument from byte[]
XWPFDocument document = new XWPFDocument(new ByteArrayInputStream(byteData));
XWPFChart xChart = null;
CTChart ctChart = null;
XSSFWorkbook wb = null;
for (POIXMLDocumentPart part : document.getRelations()) {
if (part instanceof XWPFChart) {
xChart = (XWPFChart) part;
wb = xChart.getWorkbook();
ctChart = xChart.getCTChart();
if(getTitle(ctChart).equals("FIELD_CHART")) {
break;
}
}
}
CTPlotArea plotArea = ctChart.getPlotArea();
List<CTBarChart> arBarChart = plotArea.getBarChartList();
List<CTBarSer> arBarSer = arBarChart.get(0).getSerList();
if(CHART_MAP_DATA != null && !CHART_MAP_DATA.isEmpty()) {
Set<String> keys = CHART_MAP_DATA.keySet();
Iterator<String> itKeys = keys.iterator();
while(itKeys.hasNext()) {
String inKey = itKeys.next();
Map<String, String> barData = CHART_MAP_DATA.get(inKey);
setBarChartData(ctChart, serCnt, inKey, barData);
}
}
XSSFSheet sheet = wb.getSheetAt(0);
sheet.getRow(1).getCell(1).setCellValue(8.3);
sheet.getRow(2).getCell(1).setCellValue(7.3);
FileOutputStream fos = new FileOutputStream(new File(outFilePath));
document.write(fos);
fos.close();
document.close();
}
public static void setBarChartData(CTChart ctChart, int serIdx, String series, Map<String, String> data) {
CTPlotArea plotArea = ctChart.getPlotArea();
List<CTBarChart> arBarChart = plotArea.getBarChartList();
if(arBarChart.size() > 0) {
List<CTBarSer> arBarSer = arBarChart.get(0).getSerList();
CTBarSer barSer = arBarSer.get(serIdx);
CTSerTx serTx = barSer.getTx();
CTStrRef strRef = serTx.getStrRef();
CTStrData strData = strRef.getStrCache();
List<CTStrVal> arStrVal = strData.getPtList();
for(int b=0; b<arStrVal.size(); b++) {
arStrVal.get(b).setV(series);
}
CTAxDataSource dataSource = barSer.getCat();
CTStrRef dStrRef = dataSource.getStrRef();
boolean isCatDataTypeStr = true;
List<CTStrVal> arDStrVal = null;
List<CTNumVal> arDNumVal = null;
CTStrData dStrData = null;
CTNumData dNumData = null;
if(dStrRef != null) {
dStrData = dStrRef.getStrCache();
arDStrVal = dStrData.getPtList();
dStrData.getPtCount().setVal(data.size());
if(arDStrVal.size() > data.size()) {
for(int i=arDStrVal.size(); i>data.size(); i--) {
dStrData.removePt(i-1);
}
}
isCatDataTypeStr = true;
} else {
CTNumRef dNumRef = dataSource.getNumRef();
dNumData = dNumRef.getNumCache();
arDNumVal = dNumData.getPtList();
dNumData.getPtCount().setVal(data.size());
if(arDNumVal.size() > data.size()) {
for(int i=arDNumVal.size(); i>data.size(); i--) {
dNumData.removePt(i-1);
}
}
isCatDataTypeStr = false;
}
CTNumDataSource numDataSource = barSer.getVal();
CTNumRef numRef = numDataSource.getNumRef();
CTNumData numData = numRef.getNumCache();
List<CTNumVal> arNumVal = numData.getPtList();
numData.getPtCount().setVal(data.size());
if(arNumVal.size() > data.size()) {
for(int i=arNumVal.size(); i>data.size(); i--) {
numData.removePt(i-1);
}
}
Set<String> keys = data.keySet();
Iterator<String> itKeys = keys.iterator();
int valSize = 0;
if(isCatDataTypeStr) {
valSize = arDStrVal.size();
} else {
valSize = arDNumVal.size();
}
int idx = 0;
while(itKeys.hasNext()) {
String stKey = itKeys.next();
if(valSize > idx) {
if(isCatDataTypeStr) {
arDStrVal.get(idx).setV(stKey);
} else {
arDNumVal.get(idx).setV(stKey);
}
} else {
if(isCatDataTypeStr) {
CTStrVal val = dStrData.addNewPt();
val.setIdx(idx);
val.setV(stKey);
} else {
CTNumVal val = dNumData.addNewPt();
val.setIdx(idx);
val.setV(stKey);
}
}
if(arNumVal.size() > idx) {
arNumVal.get(idx).setV(data.get(stKey));
} else {
CTNumVal val = numData.addNewPt();
val.setIdx(idx);
val.setV(data.get(stKey));
}
idx++;
}
}
}
public static String getTitle(CTChart chart) {
CTTitle title = chart.getTitle();
if (title != null) {
CTTx tx = title.getTx();
CTTextBody tb = tx.getRich();
return tb.getPArray(0).getRArray(0).getT();
}
return "";
}
答案 0 :(得分:1)
使用apache poi 4.0.1
更改XDDFChart数据需要并行更新基础图表数据工作簿和图表本身中的所有更改。图表保存缓存的数据,而工作簿保存源数据。但是使用高级apache poi
类都可以实现。无需访问基础XML Bean。
示例
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();
}
}
结果: