我使用apache poi绘制了一个3D堆叠条形图,但在处理左轴标题的字体大小和图表的图例时遇到了麻烦。我查看了ooxml文档,发现了here,但无法确定是哪个对象造成了这种情况。我已经添加了我的代码和结果图表的一部分,我感谢任何帮助指导我在正确的道路上。
XSSFSheet sheet = wb.getSheetAt(0);
// Bar chart coordinates
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 37, 16, 47);
XSSFChart chart = drawing.createChart(anchor);
// configure axis properties
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("Call Duration");
// font size for left axis labels (ticks)
leftAxis.getOrAddTextProperties().setFontSize(8d);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
XDDFChartData data = chart.createData(ChartTypes.BAR3D, bottomAxis, leftAxis);
// create legend
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.BOTTOM);
/*DATA ADDITION HERE*/
发布于 2021-08-25 11:41:15
我已经找到了哪个xml对象解决了条形图、轴和图例的字体样式。我基本上是通过比较我的java代码生成的底层xl/charts/chart1.xml
和我用ms excel手工绘制的另一个条形图来完成的。我之所以必须这样做,是因为对于值轴,apache poi的XDDFValueAxis
对象没有实现轴标题操作方法,需要org.openxmlformats.schemas.drawingml.x2006
应用程序接口。正如我在问题中提到的,文档可以在here中找到。文档的问题是不是每个对象的功能都很明显(至少对我来说是这样),因此,比较和分析xml对象可以深入了解某些对象实际上负责什么。这是我的代码片段,它有apache poi 4.1.2
和poi-ooxml-schemas-4.1.2
依赖项。希望它能对有类似问题的人有所帮助。
XSSFSheet sheet = wb.getSheetAt(0);
// Bar chart coordinates
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 38, 16, 47);
XSSFChart chart = drawing.createChart(anchor);
// configure axis properties
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.getOrAddTextProperties().setFontSize(6d);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("Call Duration");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
// font size for left axis labels (ticks)
leftAxis.getOrAddTextProperties().setFontSize(6d);
// create legend
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.BOTTOM);
// reflect the underlying the xml objects in order to access fields that are not implemented in apache poi
org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx ctValAx = null;
org.openxmlformats.schemas.drawingml.x2006.chart.CTLegend ctLegend = null;
java.lang.reflect.Field ctValRef;
java.lang.reflect.Field chartLegendRef;
try {
ctValRef = XDDFValueAxis.class.getDeclaredField("ctValAx");
ctValRef.setAccessible(true);
ctValAx = (org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx) ctValRef.get(leftAxis);
chartLegendRef = XDDFChartLegend.class.getDeclaredField("legend");
chartLegendRef.setAccessible(true);
ctLegend = (org.openxmlformats.schemas.drawingml.x2006.chart.CTLegend) chartLegendRef.get(legend);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
// set title properties for left axis
CTTitle ctTitle = ctValAx.getTitle();
ctTitle.getTx().getRich().getPArray(0).getRArray(0).getRPr().setSz(600);
// adjust the font size of the legend
ctLegend.addNewTxPr();
ctLegend.getTxPr().addNewBodyPr();
ctLegend.getTxPr().addNewLstStyle(); // font size in hundreds format (6*100)
ctLegend.getTxPr().addNewP().addNewPPr().addNewDefRPr().setSz(600);
/*DATA ADDITION HERE*/
发布于 2021-08-27 05:56:04
至少对于图例的字体大小设置,使用org.apache.poi.xddf.usermodel.text.XDDFTextBody
是可能的。这样做的好处是,这是一个可以进一步开发的高级apache poi
类。因此,如果你有XDDFChartLegend legend
,那么用它来构造一个XDDFTextBody
,并用它来设置字体。
示例:
...
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.BOTTOM);
XDDFTextBody legendTextBody = new XDDFTextBody(legend);
legendTextBody.getXmlObject().addNewBodyPr();
legendTextBody.addNewParagraph().addDefaultRunProperties().setFontSize(8d);
legend.setTextBody(legendTextBody);
...
对于轴字体设置,需要使用低级org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx
或org.openxmlformats.schemas.drawingml.x2006.chart.CTCatAx
。但也有org.apache.poi.xddf.usermodel.chart.XDDFTitle
,它是CTValAx
-title或CTCatAx
-title的高级包装器。所以我们应该使用它,而不是直接使用CT*
类。
示例:
使用XDDFTitle getOrSetAxisTitle
方法:
private static XDDFTitle getOrSetAxisTitle(XDDFValueAxis axis) {
try {
java.lang.reflect.Field _ctValAx = XDDFValueAxis.class.getDeclaredField("ctValAx");
_ctValAx.setAccessible(true);
org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx ctValAx =
(org.openxmlformats.schemas.drawingml.x2006.chart.CTValAx)_ctValAx.get(axis);
if (!ctValAx.isSetTitle()) {
ctValAx.addNewTitle();
}
XDDFTitle title = new XDDFTitle(null, ctValAx.getTitle());
return title;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
private static XDDFTitle getOrSetAxisTitle(XDDFCategoryAxis axis) {
try {
java.lang.reflect.Field _ctCatAx = XDDFCategoryAxis.class.getDeclaredField("ctCatAx");
_ctCatAx.setAccessible(true);
org.openxmlformats.schemas.drawingml.x2006.chart.CTCatAx ctCatAx =
(org.openxmlformats.schemas.drawingml.x2006.chart.CTCatAx)_ctCatAx.get(axis);
if (!ctCatAx.isSetTitle()) {
ctCatAx.addNewTitle();
}
XDDFTitle title = new XDDFTitle(null, ctCatAx.getTitle());
return title;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
然后按如下方式使用它们:
...
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
//bottomAxis.setTitle("...");
XDDFTitle title = getOrSetAxisTitle(bottomAxis);
title.setOverlay(false);
title.setText("...");
title.getBody().getParagraph(0).addDefaultRunProperties().setFontSize(8d);
bottomAxis.getOrAddTextProperties().setFontSize(8d);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
//leftAxis.setTitle("...");
title = getOrSetAxisTitle(leftAxis);
title.setOverlay(false);
title.setText("...");
title.getBody().getParagraph(0).addDefaultRunProperties().setFontSize(8d);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
leftAxis.getOrAddTextProperties().setFontSize(8d);
...
https://stackoverflow.com/questions/68893190
复制相似问题