java - Apache POI 图表轴 endarrow
问题描述
我试图从折线图女巫 apache Poi 中获得不同的结局。
这是我的代码。它创建了一个没有箭头的图表。我找不到轴“样式类”或类似的东西。
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
setRoundedCorners(chart, false);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
//XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.BOTTOM);
//bottomAxis.setMajorTickMark(AxisTickMark.CROSS);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
我在创建后添加了箭头。现在有谁可以在代码中创建箭头?
我将 Axis 类更改为 XDDFValueAxis 并找到了一些看起来像我的混乱功能的东西,但不幸的是,将行 'lineProperties.getHeadEnd()' 抛出一个空指针异常。
XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.BOTTOM);
XDDFShapeProperties shapeProperties = valueAxis.getOrAddShapeProperties();
XDDFLineProperties lineProperties = shapeProperties.getLineProperties();
XDDFLineEndProperties lineEndProperties = lineProperties.getHeadEnd();
lineEndProperties.setType(LineEndType.ARROW);
valueAxis.setTitle("x");
如何创建 XDDFLineEndProperties 构造函数受保护?
如果需要,这是完整的代码示例。
mport java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.PresetColor;
import org.apache.poi.xddf.usermodel.XDDFColor;
import org.apache.poi.xddf.usermodel.XDDFLineProperties;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
* Line chart example.
*/
public final class LineChart {
private LineChart() {}
public static void main(String[] args) throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet("linechart");
final int NUM_OF_ROWS = 3;
final int NUM_OF_COLUMNS = 10;
// Create a row and put some cells in it. Rows are 0 based.
Row row;
Cell cell;
for (int rowIndex = 0; rowIndex < NUM_OF_ROWS; rowIndex++) {
row = sheet.createRow((short) rowIndex);
for (int colIndex = 0; colIndex < NUM_OF_COLUMNS; colIndex++) {
cell = row.createCell((short) colIndex);
cell.setCellValue(colIndex * (rowIndex + 1.0) -5 );
}
}
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 15);
XSSFChart chart = drawing.createChart(anchor);
setRoundedCorners(chart, false);
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP_RIGHT);
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
//XDDFValueAxis valueAxis = chart.createValueAxis(AxisPosition.BOTTOM);
//bottomAxis.setMajorTickMark(AxisTickMark.CROSS);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("f(x)");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
XDDFDataSource<Double> xs = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 0, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(1, 1, 0, NUM_OF_COLUMNS - 1));
XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(2, 2, 0, NUM_OF_COLUMNS - 1));
XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs, ys1);
series1.setTitle("2x", null); // https://stackoverflow.com/questions/21855842
series1.setSmooth(false); // https://stackoverflow.com/questions/29014848
series1.setMarkerStyle(MarkerStyle.STAR); // https://stackoverflow.com/questions/39636138
XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs, ys2);
series2.setTitle("3x", null);
series2.setSmooth(true);
series2.setMarkerSize((short) 6);
series2.setMarkerStyle(MarkerStyle.TRIANGLE); // https://stackoverflow.com/questions/39636138
chart.plot(data);
// if your series have missing values like https://stackoverflow.com/questions/29014848
// chart.displayBlanksAs(DisplayBlanks.GAP);
// https://stackoverflow.com/questions/24676460
//solidLineSeries(data, 0, PresetColor.CHARTREUSE);
//solidLineSeries(data, 1, PresetColor.TURQUOISE);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("ooxml-line-chart.xlsx")) {
wb.write(fileOut);
}
}
}
private static void setRoundedCorners(XSSFChart chart, boolean setVal) {
if (chart.getCTChartSpace().getRoundedCorners() == null) chart.getCTChartSpace().addNewRoundedCorners();
chart.getCTChartSpace().getRoundedCorners().setVal(setVal);
}
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);
}
}
解决方案
您可以拥有一个扩展XDDFLineEndProperties
并提供不受保护的构造函数的公共类:
import org.apache.poi.xddf.usermodel.XDDFLineEndProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
public class MyXDDFLineEndProperties extends XDDFLineEndProperties {
public MyXDDFLineEndProperties() {
super(CTLineEndProperties.Factory.newInstance());
}
}
然后你可以像这样使用它:
...
// Use a category axis for the bottom axis.
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("x"); // https://stackoverflow.com/questions/32010765
XDDFShapeProperties shapeProperties = bottomAxis.getOrAddShapeProperties();
XDDFLineProperties lineProperties = new XDDFLineProperties();
MyXDDFLineEndProperties lineEndProperties = new MyXDDFLineEndProperties();
lineEndProperties.setType(LineEndType.ARROW);
lineProperties.setTailEnd(lineEndProperties);
shapeProperties.setLineProperties(lineProperties);
...
推荐阅读
- c# - 在 PDF 中添加多个签名字段时遇到问题
- node.js - 节点的实时服务器如何工作?
- powershell - 如何使用powershell提取图标 - 结果文件不是Windows图标文件
- javascript - 承诺不在异步对象条目firebase调用中等待
- java - 使用 maven [com/sun/tools/javac/tree/JCTree$JCCompilationUnit] 构建项目时出错
- python - BeautifulSoup 查找多个类别
- javascript - 在 IBM worklight 8.0 中的 JavaScript HTTP 适配器问题中找不到对象的默认值
- android - 以编程方式从自定义视图创建多个视图
- dialogflow-es - Can I set the intent/context for the next DialogFlow interaction (for push notifications)?
- c# - 将 Datatable 转换为通用 IEnumerable