gpt4 book ai didi

java - 如何将 XDDF 图表添加到特定段落运行(即表格中的单元格)?兴趣点4.0.1

转载 作者:行者123 更新时间:2023-12-02 09:25:54 25 4
gpt4 key购买 nike

我想将图表添加到 XWPFDocument 中的特定表格单元格。我希望图表位于表格单元格中,以便确保与随后添加的其他元素保持一致。那么,

  • 如何创建 XWPF/XDDF 图表而不将其添加到文档中(例如,不使用 document.createChart())?

  • 如何获取该图表并将其添加到特定段落/运行(例如在表格单元格中创建的段落/运行)?

已经尝试过:

  1. 创建一个反射(reflect) XWPFDocument.createChart() 中代码的图表
  2. XWPFRun.addChart()与我使用的RelationPart.getRelationship.getId()结合使用
  3. 到达表格的特定位置后使用document.createChart()
  4. 尝试制作图表 -> XDDFDrawing 并将其添加到运行中 run.getCTR.addDrawing...我不认为事情会这样?

/代码示例

// Create a document with some initial text
XWPFDocument document = new XWPFDocument();
XWPFParagraph tmpParagraph = document.createParagraph();
XWPFRun tmpRun = tmpParagraph.createRun();
tmpRun.setText("text");
tmpRun.setFontSize(18);

// Try making the chart
// the same code as here, https://stackoverflow.com/questions/55192804/how-do-i-add-a-second-line-with-a-second-axis-to-an-xddfchart-in-poi-4-0-1
try{
String[] categories = new String[]{"1","2","3","4","5","6","7","8","9"};
Double[] values1 = new Double[]{1d,2d,3d,4d,5d,6d,7d,8d,9d};
Double[] values2 = new Double[]{200d,300d,400d,500d,600d,700d,800d,900d,1000d};

// create the chart
// XWPFChart chart = document.createChart(7* Units.EMU_PER_CENTIMETER, 7*Units.EMU_PER_CENTIMETER);

// Try to make a chart stand alone
// using the same code as here,
// https://svn.apache.org/viewvc/poi/tags/REL_4_0_1/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java?view=markup

int chartNumber = document.getCharts().size();
POIXMLDocumentPart.RelationPart rp = document.createRelationship(XWPFRelation.CHART, XWPFFactory.getInstance(), chartNumber, false);
XWPFChart chart = rp.getDocumentPart();
chart.setChartIndex(chartNumber);
chart.setChartBoundingBox(7* Units.EMU_PER_CENTIMETER, 7*Units.EMU_PER_CENTIMETER);
document.getCharts().add(chart);


// This stuff to make the chart is not part of the question
// create data sources
int numOfPoints = categories.length;
String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
String valuesDataRange1 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
XDDFNumericalDataSource<Double> valuesData1 = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange1, 1);
XDDFNumericalDataSource<Double> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);

// first line chart
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFChartData data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFChartData.Series series = data.addSeries(categoriesData, valuesData1);
chart.plot(data);

solidLineSeries(data, 0, PresetColor.BLUE);

// second line chart
// bottom axis must be there but must not be visible
bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setVisible(false);

XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
rightAxis.setCrosses(AxisCrosses.MAX);

// set correct cross axis
bottomAxis.crossAxis(rightAxis);
rightAxis.crossAxis(bottomAxis);

data = chart.createData(ChartTypes.LINE, bottomAxis, rightAxis);
series = data.addSeries(categoriesData, valuesData2);
chart.plot(data);

// correct the id and order, must not be 0 again because there is one line series already
chart.getCTChart().getPlotArea().getLineChartArray(1).getSerArray(0).getIdx().setVal(1);
chart.getCTChart().getPlotArea().getLineChartArray(1).getSerArray(0).getOrder().setVal(1);

solidLineSeries(data, 0, PresetColor.RED);


// End of extra stuff
// Back to question

// Add the chart by relation id
XWPFParagraph p2 = document.createParagraph();
XWPFRun r2 = p2.createRun();
r2.addChart(rp.getRelationship().getId());

// Add a new run to try to add a new drawing?
XWPFRun r3 = p2.createRun();
CTDrawing drawing = r3.getCTR().addNewDrawing();
????

}catch(Exception e){}

当我通过 r2.addChart() 添加图表时,没有显示任何内容?那么也许我没有正确创建图表?或者我没有正确地将其添加到运行中?

是否可以将图表转换为绘图?

This shows the XML I am trying to mimic (copied from the other image)

  1. 段落
  2. 运行
  3. 画画?
  4. 图表?

This is the expected output

最佳答案

由于对哪些方法是 protected 或私有(private)的做出了奇怪的决定,apache poi 常常使扩展其代码变得非常困难。在这种情况下,它在 XWPFDocument 中缺少方法 public XWPFChart createChart(int width, int height, XWPFRun run) ,因为现有方法总是将图表放入新创建的运行中文档正文中新创建的段落。但简单地扩展 XWPFDocument 几乎是不可能的,因为所需的方法是 protected 或私有(private)的。

我发现的最简单的方法是首先使用document.createChart()将图表放在文档的第一段中。然后删除第一段。图表部分保留(至少使用 apache poi 4.1.0)。然后在所需的文本运行处附加新的图表部分。但即使这样也并不那么容易,因为 XWPFChart.attach 也受到保护。因此需要使用java.lang.reflect

完整示例:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Units;

import org.apache.poi.xddf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;

public class CreateWordXDDFChartTwoLinesInTable {

public static void main(String[] args) throws Exception {
try (XWPFDocument document = new XWPFDocument()) {

// create the data
String[] categories = new String[]{"1","2","3","4","5","6","7","8","9"};
Double[] values1 = new Double[]{1d,2d,3d,4d,5d,6d,7d,8d,9d};
Double[] values2 = new Double[]{200d,300d,400d,500d,600d,700d,800d,900d,1000d};

// create the chart
// this also puts the chart into a run in a new created paragraph
XWPFChart chart = createChart(document, categories, values1, values2);
// remove the first paragraph since we need the chart being elsewhere
document.removeBodyElement(0);

XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("First paragraph having first text run.");

// create the table
XWPFTable table = document.createTable(1,2);
table.setWidth("100%");
// create first run in first table cell
paragraph = table.getRow(0).getCell(0).getParagraphArray(0);
run = paragraph.createRun();
// attach the chart here
java.lang.reflect.Method attach = XWPFChart.class.getDeclaredMethod("attach", String.class, XWPFRun.class);
attach.setAccessible(true);
attach.invoke(chart, document.getRelationId(chart), run);
chart.setChartBoundingBox(7*Units.EMU_PER_CENTIMETER, 7*Units.EMU_PER_CENTIMETER);

// set text in second table cell
paragraph = table.getRow(0).getCell(1).getParagraphArray(0);
run = paragraph.createRun();
run.setText("Other text goes in the 2");
run = paragraph.createRun();
run.setSubscript(VerticalAlign.SUPERSCRIPT);
run.setText("nd");
run = paragraph.createRun();
run.setText(" cell.");

paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Lorem ipsum...");

// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("CreateWordXDDFChartTwoLinesInTable.docx")) {
document.write(fileOut);
}
}
}

private static XWPFChart createChart(XWPFDocument document,
String[] categories, Double[] values1, Double[] values2) throws Exception {

// create the chart
XWPFChart chart = document.createChart();

// create data sources
int numOfPoints = categories.length;
String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
String valuesDataRange1 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
XDDFNumericalDataSource<Double> valuesData1 = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange1, 1);
XDDFNumericalDataSource<Double> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);

// first line chart
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFChartData data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFChartData.Series series = data.addSeries(categoriesData, valuesData1);
chart.plot(data);

solidLineSeries(data, 0, PresetColor.BLUE);

// second line chart
// bottom axis must be there but must not be visible
bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setVisible(false);

XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
rightAxis.setCrosses(AxisCrosses.MAX);

// set correct cross axis
bottomAxis.crossAxis(rightAxis);
rightAxis.crossAxis(bottomAxis);

data = chart.createData(ChartTypes.LINE, bottomAxis, rightAxis);
series = data.addSeries(categoriesData, valuesData2);
chart.plot(data);

// correct the id and order, must not be 0 again because there is one line series already
chart.getCTChart().getPlotArea().getLineChartArray(1).getSerArray(0).getIdx().setVal(1);
chart.getCTChart().getPlotArea().getLineChartArray(1).getSerArray(0).getOrder().setVal(1);

solidLineSeries(data, 0, PresetColor.RED);

return chart;
}

private static void solidLineSeries(XDDFChartData data, int index, PresetColor color) {
XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(color));
XDDFLineProperties line = new XDDFLineProperties();
line.setFillProperties(fill);
XDDFChartData.Series series = data.getSeries().get(index);
XDDFShapeProperties properties = series.getShapeProperties();
if (properties == null) {
properties = new XDDFShapeProperties();
}
properties.setLineProperties(line);
series.setShapeProperties(properties);
}
}

关于java - 如何将 XDDF 图表添加到特定段落运行(即表格中的单元格)?兴趣点4.0.1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58349162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com