Есть ли способ установить две диаграммы рядом в текстовом документе с помощью Apache poi? Я создал две диаграммы, которые идут одна за другой в документ Word.
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 daf {
public static void main(String[] args) throws Exception {
// Create a new Word document
XWPFDocument doc = new XWPFDocument();
// Create a severitychart
XWPFChart severityChart = 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 chart data
XDDFPieChartData data = (XDDFPieChartData) severityChart.createData(ChartTypes.PIE, null, null);
severityChart.setTitleText("# of Vulnerabilites by Severity");
severityChart.setTitleOverlay(false);
XDDFChartData.Series series = data.addSeries(categoryDataSource, valueDataSource);
// Plot the chart
severityChart.plot(data);
severityChart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDLbls().addNewShowPercent().setVal(false);;
severityChart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowSerName().setVal(false);
severityChart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().setSeparator(" - ");
// Create a categorychart
XWPFChart categoryChart = doc.createChart(10 * Units.EMU_PER_CENTIMETER, 5 * Units.EMU_PER_CENTIMETER);
// Create chart data source
String[] categories1 = new String[]{"Critical", "High", "Medium","Low","Best Practice"};
Double[] values1 = new Double[]{(double) 1,(double) 2,(double) 3,(double) 4,(double) 5};
XDDFDataSource<String> categoryDataSource1 = XDDFDataSourcesFactory.fromArray(categories1);
XDDFNumericalDataSource<Double> valueDataSource1 = XDDFDataSourcesFactory.fromArray(values1);
// Create the category axis
XDDFCategoryAxis categoryAxis = categoryChart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis valueAxis = categoryChart.createValueAxis(AxisPosition.LEFT);
XDDFChartData data1 = categoryChart.createData(ChartTypes.BAR, categoryAxis, valueAxis);
XDDFChartData.Series series1 = data1.addSeries(categoryDataSource1, valueDataSource1);
series1.setTitle(null); //Title should be mandatory.
// Plot the chart
categoryChart.plot(data1);
// Save the document
FileOutputStream out = new FileOutputStream("chart_document.docx");
doc.write(out);
out.close();
doc.close();
System.out.println("chart created successfully!");
}
}
Этот код создает круговую диаграмму и гистограмму одну за другой. Можем ли мы изменить приведенный выше код, чтобы мы могли делать диаграммы рядом?




В документе Microsoft Word в формате Office Open XML (*.docx) диаграммы встроены в тело документа. Так же, как изображения или другие фигуры, они либо находятся на закрепленных рисунках, либо встроены в текст. Пока что Apache POI поддерживает только диаграммы, встроенные в текст. Это текстовые прогоны (XWPFRun). Поэтому они размещаются там, где в документе размещается текстовый ряд.
Использование текущей версии Apache POI 5.2.3
есть три XWPFDocument.createChart метода создания XWPFChart. См. XWPFDocument.
Первый, без параметров, создает диаграмму в новом текстовом прогоне в новом абзаце с размером по умолчанию. Второй имеет параметры width и height и создает диаграмму в новом текстовом прогоне в новом абзаце с заданным размером. Третий имеет параметры run, width и height и создает диаграмму в заданном текстовом прогоне с заданным размером. Таким образом, используя третий, вы имеете полный контроль над тем, где диаграмма должна быть размещена в тексте.
В следующем полном примере создаются две диаграммы в одном абзаце в разных текстовых прогонах в этом абзаце. Таким образом, до тех пор, пока не произойдет автоматический разрыв строки, графики будут располагаться рядом.
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 CreateWordCharts {
private static void createBarChart(XWPFRun run, String[] categories, Double[] values, PresetColor color,
BarDirection direction, String chartTitleText, String seriesTitle,
int width, int height) throws Exception {
// Create the chart
XWPFDocument document = run.getParent().getDocument();
XWPFChart chart = document.createChart(run, width * Units.EMU_PER_CENTIMETER, height * Units.EMU_PER_CENTIMETER);
// Create chart data sources
XDDFDataSource<String> categoryDataSource = XDDFDataSourcesFactory.fromArray(categories);
XDDFNumericalDataSource<Double> valueDataSource = XDDFDataSourcesFactory.fromArray(values);
// Create the category axis
XDDFCategoryAxis categoryAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
// Create the value axis
XDDFValueAxis valueAxis = chart.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);
// Create chart data
XDDFChartData data = chart.createData(ChartTypes.BAR, categoryAxis, valueAxis);
// Set bar direction
((XDDFBarChartData)data).setBarDirection(direction);
// Set chart title - optinal
if (chartTitleText != null && !chartTitleText.isBlank())
chart.setTitleText(chartTitleText);
// Add series
XDDFChartData.Series series = data.addSeries(categoryDataSource, valueDataSource);
// Set series title - not optional
if (seriesTitle == null || seriesTitle.isBlank()) seriesTitle = "Series1";
series.setTitle(seriesTitle, null);
// Set series fill color - necessary for LibreOffice as this will not use default colors
solidFillSeries(series, color);
// Plot the chart
chart.plot(data);
}
private static void createPieChart(XWPFRun run, String[] categories, Double[] values, byte[][] colors,
String chartTitleText, String seriesTitle,
int width, int height) throws Exception {
// Create the chart
XWPFDocument document = run.getParent().getDocument();
XWPFChart chart = document.createChart(run, width * Units.EMU_PER_CENTIMETER, height * Units.EMU_PER_CENTIMETER);
// Create chart data sources
XDDFDataSource<String> categoryDataSource = XDDFDataSourcesFactory.fromArray(categories);
XDDFNumericalDataSource<Double> valueDataSource = XDDFDataSourcesFactory.fromArray(values);
// Create chart data
XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
// Set chart title - optinal
if (chartTitleText != null && !chartTitleText.isBlank())
chart.setTitleText(chartTitleText);
// Add series
XDDFChartData.Series series = data.addSeries(categoryDataSource, valueDataSource);
// Set series title - not optional
if (seriesTitle == null || seriesTitle.isBlank()) seriesTitle = "Series1";
series.setTitle(seriesTitle, null);
// data point colors; is necessary for showing data points in LibreOffice
int pointCount = series.getCategoryData().getPointCount();
for (int p = 0; p < pointCount; p++) {
chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDPt().addNewIdx().setVal(p);
chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDPtArray(p)
.addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(colors[p]);
}
// Plot the chart
chart.plot(data);
}
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);
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
// Create some normal XWPF content
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("Chart Examples");
// Create paragraph for the charts
paragraph = document.createParagraph();
// Create run for text
run = paragraph.createRun();
run.setText("Chart1: ");
// Create a run to place the first chart
run = paragraph.createRun();
String[] categories = new String[]{"Cat1", "Cat2", "Cat3", "Cat4", "Cat5"};
Double[] values = new Double[]{3d, 5d, 2d, 4d, 1d};
createBarChart(run, categories, values, PresetColor.BLUE, BarDirection.COL, "Bar Chart", "Series1", 5, 5);
// Create run for text
run = paragraph.createRun();
run.setText(" Chart2: ");
// Create a run to place the second chart
run = paragraph.createRun();
categories = new String[]{"Cat1", "Cat2", "Cat3", "Cat4"};
values = new Double[]{1d, 4d, 3d, 2d};
byte[][] colors = new byte[][]{
new byte[]{(byte)255,0,0},
new byte[]{0, (byte)255,0},
new byte[]{0,0,(byte)255},
new byte[]{(byte)255, (byte)255, 0},
};
createPieChart(run, categories, values, colors, "Pie Chart", null, 5, 5);
// Create paragraph below the charts
paragraph = document.createParagraph();
// Save the document
FileOutputStream out = new FileOutputStream("./WorddocumentWithCharts.docx");
document.write(out);
out.close();
document.close();
}
}
Результат:
@Bharath Naidu Yenumula: Ответ остается прежним. Я обновил свой пример. Теперь он создает гистограмму и круговую диаграмму.
То, как вы предоставили детали, а не только решение, похвально. Именно то, что я искал. Решил мои сомнения и спасибо.
Привет, @Axel Richter, просто из любопытства, есть ли способ сделать форму области диаграммы прямоугольной, а не вышеописанной. Большое спасибо.
Решил это из вашего ответа на stackoverflow.com/questions/44255527/…. Спасибо за подробную информацию. Это было очень полезно.
Привет, Аксель Рихтер. Спасибо за комментарий. Я создал круговую диаграмму и гистограмму с помощью apache poi, и эти диаграммы шли одна за другой. Отредактировал вопрос и добавил код. Не могли бы вы подсказать мне, как установить круговую диаграмму и гистограмму рядом? Еще раз спасибо за комментарий.