I'm trying to edit charts in a docx file using docx4j. I can't seem to increase the number of rows (as in, the number of bars in a bar chart) in the chart. I can decrease the number of rows, that works fine. When I try to increase the number of rows, the values in the variables are changed correctly (ctNumvals and ctStrVals in the code). But when I open the edited doc, the chart only shows the original number of rows (before editing), with the last sets of data I entered.
Here is the code:
WordprocessingMLPackage template = WordprocessingMLPackage.load(new File(resultFile));
Chart chart = (Chart) template.getParts().get(new PartName(chartPartName));
List<Object> objects = chart.getJaxbElement().getChart().getPlotArea()
.getAreaChartOrArea3DChartOrLineChart();
//update chart values in doc
for (Object object : objects) {
if (object instanceof CTBarChart) {
List<CTBarSer> ctBarSers = ((CTBarChart) object).getSer();
for (CTBarSer ctBarSer : ctBarSers) {
List<CTNumVal> ctNumVals = ctBarSer.getVal().getNumRef().getNumCache().getPt();
List<CTStrVal> ctStrVals = ctBarSer.getCat().getStrRef().getStrCache().getPt();
while (data.size() < ctNumVals.size()) {
ctNumVals.remove(data.size());
}
while (data.size() < ctStrVals.size()) {
ctStrVals.remove(data.size());
}
while (data.size() > ctNumVals.size()) {
CTNumVal numVal = new CTNumVal();
ctNumVals.add(ctNumVals.size(), numVal);
}
while (data.size() > ctStrVals.size()) {
CTStrVal strVal = new CTStrVal();
ctStrVals.add(ctStrVals.size(), strVal);
}
ctBarSer.getVal().getNumRef().getNumCache().getPtCount().setVal(data.size());
ctBarSer.getCat().getStrRef().getStrCache().getPtCount().setVal(data.size());
for (CTNumVal ctNumVal : ctNumVals) {
ctNumVal.setV(valItr.next());
}
for (CTStrVal ctStrVal : ctStrVals) {
ctStrVal.setV(keyItr.next());
}
}
}
}
template.save(new File(resultFile));
The variable 'data' is a LinkedHashMap
I have found out what I am doing wrong.
When I create new bars,
while (data.size() > ctNumVals.size()) {
CTNumVal numVal = new CTNumVal();
ctNumVals.add(ctNumVals.size(), numVal);
}
while (data.size() > ctStrVals.size()) {
CTStrVal strVal = new CTStrVal();
ctStrVals.add(ctStrVals.size(), strVal);
}
the idx values of the new bar are set to 0 by default. This makes any bar you create the first bar of the chart (overwriting the actual first bar). Simply set the idx values to the appropriate values as below.
while (data.size() > ctNumVals.size()) {
CTNumVal numVal = new CTNumVal();
numVal.setIdx(ctNumVals.size());
ctNumVals.add(ctNumVals.size(), numVal);
}
while (data.size() > ctStrVals.size()) {
CTStrVal strVal = new CTStrVal();
strVal.setIdx(ctStrVals.size());
ctStrVals.add(ctStrVals.size(), strVal);
}