java Apache POI / CTPlotArea / Num Cache -不加载图表上的最新数据版本

d5vmydt9  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(106)

我使用Apache POI 4.1.2从XLSx文件中加载图表数据,解析后用chartjs4java转换成ChartJS JSON格式,目的是在web应用中显示excel数据。
我的问题涉及从apache POI(扩展名为poi-ooxml-schema)加载数据。
如果计算机已升级数据(未打开Excel),则不会使用新值升级图表数据。
它似乎位于lib上的NumCache功能。
但是我不知道如何在没有这种缓存的情况下加载数据。

复制步骤

1.创建一个简单的xlsx文件example

1.使用外部工具打开并升级此文件**(不使用Excel**)。
例如,here就是一个例子,使用Apache POI库和Java代码。
3.尝试在单独的代码中从Apache POI获取图表数据。
这里是一个代码片段,我加载和浏览到我的图表数据。

public LineDataset getDataset(CTLineSer ctLineSer, CTPlotArea plot,  List<CTUnsignedInt> axIdList) {
    LineDataset dataset = new LineDataset();
    int count = 0;

    dataset = this.setLabelToDataset(dataset, ctLineSer);

    CTNumData ctStrVals = ctLineSer.getVal().getNumRef().getNumCache();
    for (int i = 0; i < Integer.parseInt(String.valueOf(ctStrVals.getPtCount().getVal())); i++) {
        // My code here to parse data
    }
}

1.最后,我将加载的数据以chartjs显示。
1.它仍然显示旧数据。
只有当我用Excel打开和关闭(保存但不做任何其他事情)文件时,才会加载正确的数据。

尝试

我做了以下尝试,没有任何成功的结果

  • 试用setForceFormulaRecalculation法进行力值计算

workbook.setForceFormulaRecalculation(true);

  • 我一直在寻找一种其他的方法来加载数据与CTPlotArea类在Apache POI文档没有任何结果
x4shl7ld

x4shl7ld1#

Apache POI既不呈现工作表,也不呈现图表,也不呈现表格,也不呈现数据透视表......它只能读取Excel文件,并能够在打开文件时更改Excel呈现的静态文件内容。
因此,如果您正在更新工作表数据,Apache POI将不会自动更新相关的图表数据。只有Exel会在下次打开更改的文件时进行渲染。幸运的是,Apache POI从版本4开始也可以使用XDDF更新图表数据。因此,在更新工作表数据后,您还可以使用XDDFChartData.Series.replaceDataXDDFChartData.Series.plot更新图表数据。
以下完整的示例显示了这一点。它使用您的simple.xlsx。两个System.out.println部分都显示图表数据值在updateChartData之后发生了更改。
免责声明:这是一个SSCCE。它不意味着是生产性代码。方法updateChartData仅限于类别数据和系列数据在列中的数据源。

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;

class ExcelUpdateChartData {

 static void updateChartData(XSSFChart chart, XSSFSheet dataSheet, 
  int firstDataRow, int lastDataRow, int categoryColumn, int[] seriesColumns) {

  for (XDDFChartData chartData : chart.getChartSeries()) {
   for (int s = 0; s < chartData.getSeriesCount() ; s++) {
    XDDFChartData.Series series = chartData.getSeries(s);
    if (seriesColumns.length > s) {
     XDDFCategoryDataSource category = XDDFDataSourcesFactory.fromStringCellRange(
      dataSheet, new CellRangeAddress(firstDataRow, lastDataRow, categoryColumn, categoryColumn));
     int seriesColumn = seriesColumns[s];
     XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(
      dataSheet, new CellRangeAddress(firstDataRow, lastDataRow, seriesColumn, seriesColumn));
     series.replaceData(category, values);  
     series.plot();
    }
   }
  }
 }

 public static void main(String[] args) throws Exception {

  String filePath = "./simple.xlsx";
  int firstDataRow = 1;
  int lastDataRow = 6;
  int categoryColumn = 0;
  int[] seriesColumns = new int[]{1};

  XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream(filePath));
  XSSFSheet sheet = workbook.getSheetAt(0);

  XSSFDrawing drawing = sheet.createDrawingPatriarch();
  XSSFChart chart = drawing.getCharts().get(0);

System.out.println("Chart values before data update:");
System.out.println(chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(0).getVal());

  double newValue = 5;
  //update sheet data
  sheet.getRow(firstDataRow+1).getCell(seriesColumns[0]).setCellValue(newValue); 
  sheet.getRow(lastDataRow).getCell(seriesColumns[0]).setCellValue(newValue); 
  //update chart data
  updateChartData(chart, sheet, firstDataRow, lastDataRow, categoryColumn, seriesColumns);

System.out.println("Chart values after data update:");
System.out.println(chart.getCTChart().getPlotArea().getBarChartArray(0).getSerArray(0).getVal());

  filePath = "./simpleChanged.xlsx";
  FileOutputStream out = new FileOutputStream(filePath);
  workbook.write(out);
  out.close();
  workbook.close();
 }

}

相关问题