Embed the excel histogram into a word document as an ole object. The downloaded word document can freely edit the histogram data

@KeYee 很难重现这个问题,因为您提供的代码无法执行。你能提供DataCount类吗?

    @Data
    static class  DataCount{
        private int count;
        private String category;
    }

    public static void main(String[] args) {
        List<Tuple3<String, String, List<DataCount>>> results = new ArrayList<>();

        List<DataCount> list1 = new ArrayList<>();
        DataCount dataCount1 = new DataCount();
        dataCount1.setCount(15);
        dataCount1.setCategory("2024-10-01");
        list1.add(dataCount1);
        DataCount dataCount2 = new DataCount();
        dataCount2.setCount(10);
        dataCount2.setCategory("2024-10-02");
        list1.add(dataCount2);

        List<DataCount> list2 = new ArrayList<>();
        DataCount dataCount3 = new DataCount();
        dataCount3.setCount(15);
        dataCount3.setCategory("2024-11-01");
        list2.add(dataCount3);
        DataCount dataCount4 = new DataCount();
        dataCount4.setCount(10);
        dataCount4.setCategory("2024-11-02");
        list2.add(dataCount4);

        Tuple3<String, String, List<DataCount>> tuple10 = Tuples.of("10月新增会员", "会员数量", list1);

        Tuple3<String, String, List<DataCount>> tuple11 = Tuples.of("11月新增会员", "会员数量", list2);

        results.add(tuple10);
        results.add(tuple11);
    }

数据结构类似于这样

@KeYee 看来,Ole 的对象与一个段落有关,所以才被移到了下一页。 你可以这样更新代码,在插入新的 ole 对象之前添加新的段落:

int oleObjectCount = 0;
for (Tuple3<String, String, ArrayList<DataCount>> result : results) {
    Workbook workbook = new Workbook();
    Worksheet dataSheet =workbook.getWorksheets().get(0);
    dataSheet.setType(SheetType.WORKSHEET);
    dataSheet.setName(result._1);
    // 填充数据到 Excel 工作表
    dataSheet.getCells().get("A1").setValue(result._1);
    dataSheet.getCells().get("B1").setValue(result._2);

    // 将数据填充到 Excel 表格
    int rowIndex = 2;
    for (DataCount countData : result._3) {
        dataSheet.getCells().get("A" + rowIndex).setValue(countData.getCategory());
        dataSheet.getCells().get("B" + rowIndex).setValue(countData.getCount());
        rowIndex++;
    }

    int WorksheetIndex = workbook.getWorksheets().add(SheetType.CHART);
    Worksheet chartSheet = workbook.getWorksheets().get(WorksheetIndex);
    chartSheet.setName("CHART");
    chartSheet.setType(SheetType.CHART);
    int chartSheetIdx = chartSheet.getIndex();

    // 创建柱状图
    int chartIndex = chartSheet.getCharts().add(ChartType.COLUMN_STACKED, 0,20,0,20);
    Chart chart = chartSheet.getCharts().get(chartIndex);
    chartSheet.getCells().getStyle().getFont().setName("微软雅黑");

    // 设置数据范围
    chart.getNSeries().add(result._1 +"!B2:B" + (rowIndex - 1), true);
    // 设置类别标签范围
    chart.getNSeries().setCategoryData(result._1+"!A2:A" + (rowIndex - 1));
    // 设置柱状图描述
    chart.getNSeries().get(0).setName(result._2);
    chart.getTitle().setText(result._1);

    ImageOrPrintOptions opts= new ImageOrPrintOptions();
    opts.setSaveFormat(SaveFormat.PNG);
    // 设置图像分辨率为 300 DPI
    opts.setVerticalResolution(300);
    opts.setHorizontalResolution(300);

    ByteArrayOutputStream imageStream=new ByteArrayOutputStream();
    workbook.getWorksheets().get(chartSheetIdx).getCharts().get(0).toImage(imageStream, opts);

    // 保存 Excel 文件到内存流
    ByteArrayOutputStream excelStream = new ByteArrayOutputStream();

    workbook.save(excelStream, com.aspose.cells.SaveFormat.XLSX);

    if (oleObjectCount > 0)
        builder.insertParagraph();
    // 将excel图表作为ole对象插入word,实现动态编辑
    Shape oleObject = builder.insertOleObject(new ByteArrayInputStream(excelStream.toByteArray()), "Excel.Sheet.12",
            false, new ByteArrayInputStream(imageStream.toByteArray()));

    // 设置图表大小
    double pageWidth = pageSetup.getPageWidth() - pageSetup.getRightMargin() - pageSetup.getLeftMargin();
    oleObject.setWidth(pageWidth);
    // 锁定宽高比例
    oleObject.setAspectRatioLocked(true);
    oleObjectCount++;
}

我在输出中看不到任何乱码字符。这是:
output.docx (58.8 KB)

程序部署到linux服务器上,输出的柱状图这两块中文不显示。在我自己电脑上输出的文件是正常显示的。猜测应该是服务器上没有安装对应的中文字体

@KeYee
文本不能正常显示是因为没有找到对应的字体。请先在服务器安装文件中使用到的所有字体然后再进行测试。你也可以将字体放置在一个文件夹,然后设置自定义字体目录。请参考以下文档。

builder.getFont().setName("微软雅黑");
builder.writeln("1. 数据概览");

输出到word中的这部分中文正常显示,但是

     var chart = chartSheet.getCharts().get(chartIndex);

            // 设置数据范围
            chart.getNSeries().add(result.getT1()+"!B2:B" + (rowIndex - 1), true);
            // 设置类别标签范围
            chart.getNSeries().setCategoryData(result.getT1()+"!A2:A" + (rowIndex - 1));
            // 设置柱状图描述
            chart.getNSeries().get(0).setName(result.getT2());
            chart.getTitle().setText(result.getT1());

            ImageOrPrintOptions opts= new ImageOrPrintOptions();
            opts.setSaveFormat(SaveFormat.PNG);
            //设置图像分辨率为 300 DPI
            opts.setVerticalResolution(300);
            opts.setHorizontalResolution(300);
            // 设置字体为支持中文的字体
            opts.setDefaultFont("微软雅黑");

生成图片后插入word中的chart图片 title series中文名称没有正常显示。如果是没有找到对应的字体,为什么word段落里的中文能正常显示呢

@KeYee
如果直接将Chart保存成图片,生成的图片里的中文可以正常显示吗?

现在的情况是图片里的中文不能正常显示,但是打开excel后就能正常显示了。打开excel后正常显示可以理解,因为它使用的是当前电脑自带的excel打开

@KeYee
因为转换Chart到图片时无法找到对应的字体,所以中文不能正常显示。你可以选择在服务器安装Chart使用到的字体,或者将字体放置到一个文件夹,然后设置自定义字体目录。完成这些操作后,将Chart导出到图片时中文就能正常显示了。
关于如何设置自定义字体目录,请参考以下文档。

@KeYee 对于“Aspose.Words”,您需要在linux上安装缺失的字体。你可以在linux上阅读更多关于字体文件夹的信息这里这里.

在您回复前我已经按照相同的方法解决了我的问题,非常感谢这几天您给予的帮助:)

1 Like

@KeYee
感谢你的反馈。很高兴你的问题得到了解决。如果你有任何疑问,请随时联系我们。