提问人:raymax 提问时间:11/10/2023 更新时间:11/11/2023 访问量:30
添加更多标签时,Apache POI 图表位置垂直变化
Apache POI chart position vertically changed when more labels are added
问:
我正在编写一个代码,用于在 excel 文件中创建两个甜甜圈图。第一个图表有 10 个标签,第二个图表有 2 个标签。
我的问题是第二个图表。我想在锚点中同时将两个图表垂直对齐。但是由于标签和价值很少,它在锚地的地位发生了垂直变化。
从上面的图片可以看出。我把两个图表并排。但是第二个图表的位置垂直发生了变化,因为它只有两个标签。如何固定第二个图表位置与第一个图表位置对齐。
public String picChart9() throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet("doughnutChart");
sheet.setDisplayGridlines(false);
final int NUM_OF_ROWS = 2;
final int NUM_OF_COLUMNS = 10;
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor1 = drawing.createAnchor(0, 0, 0, 0, 1, 5, 4, 28);
// anchor1.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
XSSFClientAnchor anchor2 = drawing.createAnchor(0, 0, 0, 0, 4, 5, 7, 28);
// anchor2.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
XSSFChart chart1 = drawing.createChart(anchor1);
chart1.setTitleText("chart1");
chart1.setTitleOverlay(false);
//chart1.createValueAxis(AxisPosition.TOP);
XSSFChart chart2 = drawing.createChart(anchor2);
chart2.setTitleText("chart2");
chart2.setTitleOverlay(false);
//chart2.createValueAxis(AxisPosition.LEFT);
/**/
System.out.println("chart1.getCTChart() --:"+chart1.getCTChart());
System.out.println("chart1.getAxes() --:"+chart1.getAxes());
System.out.println("chart2.getAxes() --:"+chart2.getAxes());
/**/
XDDFChartLegend legend1 = chart1.getOrAddLegend();
legend1.setPosition(LegendPosition.BOTTOM);
XDDFChartLegend legend2 = chart2.getOrAddLegend();
legend2.setPosition(LegendPosition.BOTTOM);
String[] stringArray1 = new String[]{"one","two","three","four","five","six","seven","eight","nine","ten"};
XDDFDataSource<String> stringValue1 = XDDFDataSourcesFactory.fromArray(stringArray1);
Long[] longArray1 = new Long[]{ 11L,2L,3L,4L,5L,6L,7L,8L,9L,10L };
XDDFNumericalDataSource<Long> longValue1 = XDDFDataSourcesFactory.fromArray(longArray1);
String[] stringArray2 = new String[]{"one","two"};
XDDFDataSource<String> stringValue2 = XDDFDataSourcesFactory.fromArray(stringArray2);
Long[] longArray2 = new Long[]{ 60L,40L };
XDDFNumericalDataSource<Long> longValue2 = XDDFDataSourcesFactory.fromArray(longArray2);
XDDFDoughnutChartData data1 = new XDDFDoughnutChartData(chart1, chart1.getCTChart().getPlotArea().addNewDoughnutChart());
data1.setVaryColors(true);
data1.setHoleSize((short) 50);
data1.setFirstSliceAngle(10);
XDDFDoughnutChartData data2 = new XDDFDoughnutChartData(chart2, chart2.getCTChart().getPlotArea().addNewDoughnutChart());
data2.setVaryColors(true);
data2.setHoleSize((short) 50);
data2.setFirstSliceAngle(10);
XDDFChartData.Series series1 = data1.addSeries(stringValue1, longValue1);
XDDFChartData.Series series2 = data2.addSeries(stringValue2, longValue2);
// Remove the Anchore border line
(chart1).getCTChartSpace().addNewSpPr().addNewLn().addNewNoFill();
(chart2).getCTChartSpace().addNewSpPr().addNewLn().addNewNoFill();
// Data point colors; is necessary for showing data points in Calc
// Add data labels-Chart-1
if (!chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).isSetDLbls()) {
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).addNewDLbls();
}
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowVal().setVal(true);
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowSerName().setVal(false);
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowCatName().setVal(false);
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowPercent().setVal(false);
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowLegendKey().setVal(false);
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewNumFmt();
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().getNumFmt().setSourceLinked(false);
chart1.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().getNumFmt().setFormatCode("#,##0.00");
// Add data labels-Chart-2
if (!chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).isSetDLbls()) {
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).addNewDLbls();
}
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowVal().setVal(true);
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowSerName().setVal(false);
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowCatName().setVal(false);
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowPercent().setVal(false);
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewShowLegendKey().setVal(false);
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().addNewNumFmt();
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().getNumFmt().setSourceLinked(false);
chart2.getCTChart().getPlotArea().getDoughnutChartArray(0).getSerArray(0).getDLbls().getNumFmt().setFormatCode("#,##0.00");
//plot chart
chart1.plot(data1);
chart2.plot(data2);
// Write the output to a file
try (FileOutputStream fileOut = new FileOutputStream("picChart9.xlsx")) {
wb.write(fileOut);
}
}
return null;
}
我正在使用上面的代码。 谢谢。如果我的问题不清楚,请告诉我。
答:
1赞
Axel Richter
11/11/2023
#1
默认情况下,Excel 图表的绘图区域在标题和图例之间使用尽可能多的图表空间。如果不需要,则必须手动调整绘图区域的大小。
要了解如何操作,可以使用默认设置创建图表。之后,解压缩并查看 .它的 XML 如下所示:*.xlsx
/xl/charts/chart*.xml
...
<c:plotArea>
<c:layout/>
...
未定义打印区域的布局 - 默认值。
然后使用 Excel GUI 调整绘图区域的大小并保存。再次解压缩并查看 .然后,它的 XML 如下所示:*.xlsx
/xl/charts/chart*.xml
...
<c:plotArea>
<c:layout>
<c:manualLayout>
<c:layoutTarget val="inner"/>
<c:xMode val="edge"/>
<c:yMode val="edge"/>
<c:x val="0.1"/>
<c:y val="0.1"/>
<c:w val="0.8"/>
<c:h val="0.6"/>
</c:manualLayout>
</c:layout>
...
绘图区域的布局是针对图表空间内部空间的手动布局。它的 x 和 y 模式是边缘模式,意味着 x 和 y 坐标定向在周围空间的边缘。从周围空间左边缘开始的 x 位置为 0.1(周围空间宽度的 10%)。从周围空间的上边缘开始的 y 位置为 0.1(周围空间高度的 10%)。宽度(w)为0.8(周围空间宽度的80%)。高度(h)为0.6(周围空间高度的60%)。
使用 java 代码如下所示:
让它成为 ,那么:XSSFChart chart
// set plot area size
if (!chart.getCTChart().getPlotArea().isSetLayout()) {
chart.getCTChart().getPlotArea().addNewLayout();
}
if (chart.getCTChart().getPlotArea().getLayout().isSetManualLayout()) {
chart.getCTChart().getPlotArea().getLayout().unsetManualLayout();
}
chart.getCTChart().getPlotArea().getLayout().addNewManualLayout();
chart.getCTChart().getPlotArea().getLayout().getManualLayout().addNewLayoutTarget().setVal(
org.openxmlformats.schemas.drawingml.x2006.chart.STLayoutTarget.INNER);
chart.getCTChart().getPlotArea().getLayout().getManualLayout().addNewXMode().setVal(
org.openxmlformats.schemas.drawingml.x2006.chart.STLayoutMode.EDGE);
chart.getCTChart().getPlotArea().getLayout().getManualLayout().addNewYMode().setVal(
org.openxmlformats.schemas.drawingml.x2006.chart.STLayoutMode.EDGE);
chart.getCTChart().getPlotArea().getLayout().getManualLayout().addNewX().setVal(0.10); //10% from left
chart.getCTChart().getPlotArea().getLayout().getManualLayout().addNewY().setVal(0.10); //10% from top
chart.getCTChart().getPlotArea().getLayout().getManualLayout().addNewW().setVal(0.80); //80% width
chart.getCTChart().getPlotArea().getLayout().getManualLayout().addNewH().setVal(0.60); //60% height
评论