使用 Apache poi 在堆叠条上方显示 SUM 值

2023-12-12

我目前正在研究功能,应该在 .pptx 文件内生成堆叠图表。

为此,我使用这里的代码:java 使用 APACHE POI 在 powerpoint 中创建图表

我做了一些修改。主要是我将分组设置为“堆叠”并将重叠设置为 100(因此子栏看起来像一个更大的栏)。

现在我需要在每个栏上方显示子栏值的总和。啊啊啊我的问题来了。如何使用 Apache Poi 和 openxmlformats.schemas.drawingml.x2006.chart 实现此目的(下面的第二个 pohoto)?

一个想法是在顶部创建另一个 SubBar,使其透明并将其标签设置为我想要的 SUM,但我找不到一种方法来设置标签(仅值,在这种情况下,我的透明 SubBar 占用了太多空间,它只是看起来很糟糕 - 如下图所示)。

enter image description here

This is what I need it to look like: enter image description here

除了 StackOverflow 上的一些线程之外,我找不到任何文档或任何内容。 你们对如何实现这一目标有什么想法吗?

EDIT 1

With help from Alex I was able to print SUM values above BARs. Now I just need to get rid of these 0 values: enter image description here

EDIT 2

Axel 提到了一个问题,导致显示零(来自编辑 1)。阿克塞尔在他的答案中编辑了代码,所以现在零消失了。


你会如何使用PowerPoint?我看到的唯一方法是使用堆积条形图与折线图的组合,其中折线图显示总和值并设置为不可见。因此只有折线图的数据标签可见。中描述的方式如何在Excel中向堆积柱形图添加总计标签?.

使用电流apache poi 4.1.2这可以使用新的来实现XDDF东西。为一个Excel图表,我已经表明如何使用 apache poi 4.0.1 和 java 生成可编辑的堆叠条形图?.

我将展示一个完整的例子PowerPoint还有图表:

import java.io.*;

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

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

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

import java.util.*;

public class CreatePowerPointStackedBarChartXDDFChart {

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

   XSLFSlide slide = slideShow.createSlide();

   // create the data
   String[] categories = new String[]{"KW1", "KW2", "KW3", "KW4", "KW5", "KW6"};
   int numOfPoints = categories.length;

   Double[][] values = new Double [][] {
    new Double[]{10d, 0d, 20d, 5d, 30d, 10d},
    new Double[]{15d, 35d, 25d, 15d, 10d, 8d},
    new Double[]{5d, 15d, 0d, 25d, 15d, 0d},
    new Double[]{10d, 5d, 30d, 30d, 20d, 12d}
   };
   Double[] sums = new Double[numOfPoints];
   for (int i = 0; i < sums.length; i++) {
    double sum = 0;
    for (Double[] valueRow : values) {
     sum += valueRow[i];
    }
    sums[i] = sum;
   }

   // create the chart
   XSLFChart chart = slideShow.createChart();

   // add chart to slide
   slide.addChart(chart, new java.awt.geom.Rectangle2D.Double(1d*Units.EMU_PER_CENTIMETER, 1d*Units.EMU_PER_CENTIMETER, 20d*Units.EMU_PER_CENTIMETER, 15d*Units.EMU_PER_CENTIMETER));

   // bar chart

   // create data sources
   String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
   XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);

   List<XDDFNumericalDataSource<Double>> valuesData = new ArrayList<XDDFNumericalDataSource<Double>>();
   int c = 1;
   for (Double[] valueRow : values) {
    String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, c, c));
    valuesData.add(XDDFDataSourcesFactory.fromArray(valueRow, valuesDataRange, c));
    c++;
   }

   // create axis
   XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
   XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
   leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
   // Set AxisCrossBetween, so the left 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.
   leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);

   // create chart data
   XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
   ((XDDFBarChartData)data).setBarDirection(BarDirection.COL);
   // stacked bar chart
   ((XDDFBarChartData)data).setBarGrouping(BarGrouping.STACKED);
   ((XDDFBarChartData)data).setOverlap((byte)100);

   // create series
   if (valuesData.size() == 1) {
    // if only one series do not vary colors for each bar
    ((XDDFBarChartData)data).setVaryColors(false);
   } else {
    // if more than one series do vary colors of the series
    ((XDDFBarChartData)data).setVaryColors(true);
   }

   for (int s = 0; s < valuesData.size(); s++) {
    XDDFChartData.Series series = data.addSeries(categoriesData, valuesData.get(s));
    series.setTitle("Series"+(s+1), chart.setSheetTitle("Series"+(s+1), s+1));
   }

   // plot chart data
   chart.plot(data);

   // add data labels
   for (int s = 0 ; s < valuesData.size(); s++) {
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).addNewDLbls();
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls()
     .addNewDLblPos().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos.CTR);

    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewNumFmt();
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getNumFmt()
     .setSourceLinked(false);
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().getNumFmt()
     .setFormatCode("0;-0;");

    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowVal().setVal(true);
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowLegendKey().setVal(false);
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowCatName().setVal(false);
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowSerName().setVal(false);
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowPercent().setVal(false);
    chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(s).getDLbls().addNewShowBubbleSize().setVal(false);
   }


   // line chart
   c = values.length + 1;
   // create data source
   String sumDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, c, c));
   XDDFNumericalDataSource<Double> sumData = XDDFDataSourcesFactory.fromArray(sums, sumDataRange, c);

   // axis must be there but must not be visible
   bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
   bottomAxis.setVisible(false);
   leftAxis = chart.createValueAxis(AxisPosition.LEFT);
   leftAxis.setVisible(false);

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

   data = chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
   XDDFChartData.Series series = data.addSeries(categoriesData, sumData);
   series.setTitle("sum", chart.setSheetTitle("sum", c));
   ((XDDFLineChartData.Series)series).setSmooth(false);
   ((XDDFLineChartData.Series)series).setMarkerStyle(MarkerStyle.NONE);
   // don't show the line
   XDDFShapeProperties shapeProperties = new XDDFShapeProperties();
   shapeProperties.setLineProperties(new XDDFLineProperties(new XDDFNoFillProperties()));
   series.setShapeProperties(shapeProperties);

   // plot chart data
   chart.plot(data);

   // correct the id and order, must not start 0 again because there are bar series already
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getIdx().setVal(c);
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getOrder().setVal(c);
            
   // add data labels
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).addNewDLbls();
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls()
    .addNewDLblPos().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos.T);

   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewNumFmt();
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().getNumFmt()
    .setSourceLinked(false);
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().getNumFmt()
    .setFormatCode("0;-0;");

   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowVal().setVal(true);
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowLegendKey().setVal(false);
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowCatName().setVal(false);
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowSerName().setVal(false);
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowPercent().setVal(false);
   chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(0).getDLbls().addNewShowBubbleSize().setVal(false);
 
   // Write the output to a file
   try (FileOutputStream fileOut = new FileOutputStream("CreatePowerPointStackedBarChartXDDFChart.pptx")) {
    slideShow.write(fileOut);
   }
  }
 }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Apache poi 在堆叠条上方显示 SUM 值 的相关文章

随机推荐

  • 单击 css 内容属性

    以下代码在标题标记之前添加图像 单击标题之前添加的图像时 如何添加 javascript 或 jquery 代码来处理某些任务 h1 before content url smiley gif Html 代码是 h1 Hi h1 您不能将事
  • 验证两个属性相等

    是否可以验证类型的两个对象属性string是平等的使用Joi I found Joi ref 但我想知道是否还有其他方法可以做到这一点 尤其是作为Joi ref 似乎不支持any error 是的 可以检查对象的两个属性是否相同 并使用Jo
  • C# 调暗屏幕、多个 Windows 窗体的最佳方法?

    因此 我编写了代码来从父级创建一个新的 Windows 窗体 该窗体为全屏 黑色且不透明度为 80 以创建变暗效果 然后上面会显示另一个表格以显示进度 代码目前如下所示 this Enabled false frmDimScreen Bac
  • 如何制作一个脚本在我的默认 sqlite3 数据库 django 中插入数据

    我已经在 Django 中定义了我的模型和所有内容 如果用户通过我的应用程序注册 则用户可以在数据库中注册 问题是我有一个包含大量用户的 JSON 文件 我想做一项工作 允许我读取此文件并将所有用户插入我的数据库中 最好的方法是什么 如何在
  • 无法找到管道“ ” Angular2 自定义管道

    我似乎无法修复这个错误 我有一个搜索栏和一个 ngFor 我正在尝试使用这样的自定义管道来过滤数组 import Pipe PipeTransform from angular core import User from user user
  • Java:运行JAR文件时如何获取文件的路径

    当我使用相对路径时 我可以从 Eclipse 运行我的 Java 程序 但是当我将它作为 JAR 文件运行时 该路径不再起作用 在我的 src components SettingsWindow java 中 我有 ObjectInputS
  • 如何在 pyqt 中使用 Qtableview /QAbstractTableModel 存储和检索自定义数据(使用 QtCore.Qt.UserRole?)?

    我对模型 视图框架的使用还很陌生 并且遇到了一些麻烦 我在小部件上使用 Qtableview 和 QAbstractTableModel 我试图使用 QAbstractTableModel 中的 data 方法在 QModelIndex 中
  • 实数、浮点数、货币

    为什么当我在 SQL Server 中将 40 54 的值保存到 Real 类型的列时 它返回给我的值更像是 40 53999878999 而不是 40 54 我已经见过几次这种情况 但一直不明白为什么会发生这种情况 有其他人遇到过这个问题
  • OpenCV。匹配时绘制矩形

    我使用 OpenCv 来查找与参考图像上的模板匹配的区域 当代码找到与模板匹配的区域时 在该区域周围绘制一个矩形 但我想要的是当代码找不到该区域时 代码不会绘制任何矩形 code IplImage res CvPoint minloc ma
  • R-markdown 自包含

    我正在使用 R markdown 来编写一些报告 我用独立的图形来做 因为我通过电子邮件发送它 这一直有效直到最近 但现在图像不再显示 方框中出现十字错误 可能是我更新了RStudio的版本 我在脚本的顶部使用了这个 title blabl
  • Fluent NHibernate Composite ID表问题

    我对 nhibernate 有点陌生 遇到了一个问题 我有以下表格 Table 1 我在使用复合 id 做事时遇到了很多问题 例如this 我建议做我所做的事情 即创建一个新类型 它只包含复合 id 用于 id 的内容 然后像这样映射它 C
  • Objective-C中如何将字节值转换为int

    请告诉我如何在 iPhone 编程中将 Objective C 中的字节转换为 NSInteger int 字节 是什么意思 如果要将表示整数值的单字节转换为 int 或 NSInteger 类型 只需使用 Byte b 123 NSInt
  • 全套组合组合 3 套

    我需要生成组合三个不同子集所获得的完整组合集 Set 1 从 13 个元素的向量中选择任意 4 个数字 Set 2 从 3 个元素的向量中选择任意 2 个数字 Set 3 从 9 个元素的向量中选择任意 2 个数字 示例 A 组的向量 4
  • 将 DataContractSurrogate 与 WCF REST 结合使用

    如何将 DataContractSurrogate 用于我的 WCF REST 服务 使用 WebServiceHostFactory 托管 我没有看到添加一个的方法 即使我添加自定义 IOperationBehavior WebServi
  • 如何用C语言为AVR-Studio编写自定义reset()函数?

    所以我被分配了为 AVR 编译编写自定义 Reset 函数的任务 我得到了这个信息 Atmega128 和 Pic24e 在程序地址 0x0 处有复位中断 编写一个函数 Reset 来复位程序 我还听说强制系统重新启动的一个简单方法是发送它
  • 从多个源文件构建内核模块,其中一个源文件与模块同名

    是否可以从多个源文件构建一个内核模块 其中一个源文件与该模块同名 例如 我想使用以下源文件构建 mymodule ko mymodule cmymodule func c 这个 makefile 不起作用 Makefile obj m my
  • UILabel + IRR、KRW 和 KHR 货币符号错误

    我在将韩元 柬埔寨瑞尔和伊朗里亚尔的十进制转换为货币并将结果显示到 UILabel 文本时遇到问题 转换本身顺利进行 我可以在调试器中看到正确的货币符号 甚至 NSLog 也能很好地打印该符号 如果我将此 NSString 实例分配给 UI
  • ListView项目背景地狱

    因为复选框不是我的项目的选项 所以我希望可选项在选中时有背景 从 2 3 开始支持 我还没有设法解决这个问题 选择是正确的 但我在屏幕上看到的不是 随机行的随机颜色 拳头我有这个
  • React Router 无法与 Github Pages 一起使用

    我以前的网站仅在单击主页选项卡时显示主页 然后如果您单击我的导航栏品牌 它会显示 404 该网站在带有 npm start 的 create react app 上运行 但在这里不起作用 也不起作用在构建上 我不知道该应用程序出了什么问题
  • 使用 Apache poi 在堆叠条上方显示 SUM 值

    我目前正在研究功能 应该在 pptx 文件内生成堆叠图表 为此 我使用这里的代码 java 使用 APACHE POI 在 powerpoint 中创建图表 我做了一些修改 主要是我将分组设置为 堆叠 并将重叠设置为 100 因此子栏看起来