I have successfully able to create a word document using the below code but i am unable to open the created word document. I am new to Apache poi, java and web development and any help would be appreciated.
import java.io.FileOutputStream;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xwpf.usermodel.*;
public class BarChart {
public static void main(String[] args) throws Exception {
XWPFDocument doc = new XWPFDocument();
// Create a paragraph
XWPFParagraph paragraph = doc.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("Bar Chart Example:");
// Create a severitychart
XWPFChart categoryChart = doc.createChart(10 * Units.EMU_PER_CENTIMETER, 5 *
Units.EMU_PER_CENTIMETER);
// Create chart data source
String[] categories = new String[]{"Critical", "High", "Medium","Low","Best Practice"};
Double[] values = new Double[]{(double) 1,(double) 2,(double) 3,(double) 4,(double) 5};
XDDFDataSource<String> categoryDataSource =
XDDFDataSourcesFactory.fromArray(categories);
XDDFNumericalDataSource<Double> valueDataSource =
XDDFDataSourcesFactory.fromArray(values);
// Create the category axis
XDDFCategoryAxis categoryAxis = categoryChart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis valueAxis = categoryChart.createValueAxis(AxisPosition.TOP);
XDDFChartData data = categoryChart.createData(ChartTypes.BAR, categoryAxis, valueAxis);
//categoryChart.setTitleText("Evoke");
XDDFChartData.Series series = data.addSeries(categoryDataSource, valueDataSource);
//series.setTitle("Fruit Sales", null);
// Plot the chart
categoryChart.plot(data);
// Save the document
FileOutputStream out = new FileOutputStream("bar_chart_document.docx");
doc.write(out);
out.close();
doc.close();
System.out.println("chart created successfully!");
}
}
Main issue is that series title of charts is not optional. Each series needs a title to prepare legends.
So if you uncomment:
...
//series.setTitle("Fruit Sales", null);
...
a series title will be set and you should be able to open the file in Microsoft Word.
But a few more hints:
Set how the axis cross - for example at zero point of value axis: valueAxis.setCrosses(AxisCrosses.AUTO_ZERO)
.
Set AxisCrossBetween
, so the value axis crosses the category axis between the categories. Else first and last category is exactly on cross points and the bars are only half visible: valueAxis.setCrossBetween(AxisCrossBetween.BETWEEN)
.
Set bar direction to either BarDirection.BAR
or BarDirection.COL
.
Set series fill color - necessary for LibreOffice as this will not use default colors.
Minimal complete example for a bar chart in Word:
import java.io.FileOutputStream;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xwpf.usermodel.*;
public class BarChartWordMinimal {
public static void main(String[] args) throws Exception {
XWPFDocument doc = new XWPFDocument();
// Create some normal XWPF content
XWPFParagraph paragraph = doc.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("Bar Chart Example:");
// Create the chart
XWPFChart categoryChart = doc.createChart(10 * Units.EMU_PER_CENTIMETER, 5 * Units.EMU_PER_CENTIMETER);
// Create chart data sources
String[] categories = new String[]{"Critical", "High", "Medium","Low","Best Practice"};
Double[] values = new Double[]{(double) 1,(double) 2,(double) 3,(double) 4,(double) 5};
XDDFDataSource<String> categoryDataSource = XDDFDataSourcesFactory.fromArray(categories);
XDDFNumericalDataSource<Double> valueDataSource = XDDFDataSourcesFactory.fromArray(values);
// Create the category axis
XDDFCategoryAxis categoryAxis = categoryChart.createCategoryAxis(AxisPosition.BOTTOM);
// Create the value axis - axis position top is illogical for value axis but will not lead to error
//XDDFValueAxis valueAxis = categoryChart.createValueAxis(AxisPosition.TOP);
XDDFValueAxis valueAxis = categoryChart.createValueAxis(AxisPosition.LEFT);
// Set how the axis cross - for example at zero point of value axis
valueAxis.setCrosses(AxisCrosses.AUTO_ZERO);
// Set AxisCrossBetween, so the value axis crosses the category axis between the categories.
// Else first and last category is exactly on cross points and the bars are only half visible.
valueAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
XDDFChartData data = categoryChart.createData(ChartTypes.BAR, categoryAxis, valueAxis);
// Set bar direction
//((XDDFBarChartData)data).setBarDirection(BarDirection.BAR);
((XDDFBarChartData)data).setBarDirection(BarDirection.COL);
// Set chart title - optinal
categoryChart.setTitleText("Evoke");
// Add series
XDDFChartData.Series series = data.addSeries(categoryDataSource, valueDataSource);
// Set series title - not optional
series.setTitle("Fruit Sales", null);
// Set series fill color - necessary for LibreOffice as this will not use default colors
solidFillSeries(series, PresetColor.BLUE);
// Plot the chart
categoryChart.plot(data);
// Save the document
FileOutputStream out = new FileOutputStream("bar_chart_document.docx");
doc.write(out);
out.close();
doc.close();
System.out.println("chart created successfully!");
}
private static void solidFillSeries(XDDFChartData.Series series, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setFillProperties(fill);
series.setShapeProperties(properties);
}
}