Apache POI 生成折线图+柱状图设置双Y轴并导出word文档

实际项目中遇到的问题,相关信息实在较少,怕自己忘记,菜鸟记录一下

我设置的是双Y轴的组和图表。左侧为折线图Y轴,右侧为柱状图Y轴。

直接上代码。

// An highlighted block
public void hydrographAndRainfallFigureWordExport(HttpServletResponse response) {
        //创建文本对象
        XWPFDocument document = new XWPFDocument();
        CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
        CTPageMar pageMar = sectPr.addNewPgMar();
        pageMar.setLeft(BigInteger.valueOf(720L));
        pageMar.setTop(BigInteger.valueOf(1440L));
        pageMar.setRight(BigInteger.valueOf(720L));
        pageMar.setBottom(BigInteger.valueOf(1440L));
        try {
            //共用X轴数据
            List<String> DateList = new ArrayList<>();
            DateList.add("2022-01-01");
            DateList.add("2022-01-02");
            DateList.add("2022-01-03");
            DateList.add("2022-01-04");
            DateList.add("2022-01-05");
            DateList.add("2022-01-06");
            String[] categories = {"2022-01-01","2022-01-02","2022-01-03","2022-01-04","2022-01-05","2022-01-06"};
            //柱状图Y轴数据
            List<Double> HistogramDataList = new ArrayList<>();
            HistogramDataList.add(1.74);
            HistogramDataList.add(2.31);
            HistogramDataList.add(0.65);
            HistogramDataList.add(1.42);
            HistogramDataList.add(2.00);
            HistogramDataList.add(1.73);
            Double[] HistogramvaluesA  ={1.74,2.31,0.65,1.42,2.00,1.73};
            //折线图Y轴数据
            List<Double> LineDataList = new ArrayList<>();
            LineDataList.add(1.74);
            LineDataList.add(2.31);
            LineDataList.add(0.65);
            LineDataList.add(1.42);
            LineDataList.add(2.00);
            LineDataList.add(1.73);
            Double[] LinevaluesA = {1.74,2.31,0.65,1.42,2.00,1.73} ;
//-----------------------------------------柱状图-------------------------------------------------
            // 设置图表大小
            XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 5 * Units.EMU_PER_CENTIMETER);
            //创建相关数据
            int numOfPoints = categories.length;
            String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
            String valuesDataRangeA = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
            XDDFDataSource<String> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 1);
            XDDFNumericalDataSource<Double> valuesDataA = XDDFDataSourcesFactory.fromArray(HistogramvaluesA, valuesDataRangeA, 1);
            //创建X轴
            XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.TOP);
            // 左Y轴
            XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
            // 左Y轴和X轴交叉点在X轴0点位置,在这里我直接注释掉了。
//          leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
//          leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
            // 构建坐标轴
            leftAxis.crossAxis(bottomAxis);
            bottomAxis.crossAxis(leftAxis);
            //设置柱状图Y轴名称,方位和坐标轴大小
            leftAxis.setTitle("降雨量/mm");
            leftAxis.setCrosses(AxisCrosses.MAX);
            leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
            // create series
            bottomAxis.setMajorTickMark(AxisTickMark.NONE);//取消X轴的标刻度
            //获取X轴 图表的基本配置都在这个对象里面里面
            CTCatAx catAx = chart.getCTChart().getPlotArea().getCatAxArray(0);
            CTSkip ctSkip = CTSkip.Factory.newInstance();
            //设置显示间隔
            ctSkip.setVal((int) Math.ceil(1));
            catAx.setTickLblSkip(ctSkip);
            //设置标签位置为最下
            CTTickLblPos ctTickLblPos = CTTickLblPos.Factory.newInstance();
            ctTickLblPos.setVal(STTickLblPos.LOW);
            catAx.setTickLblPos(ctTickLblPos);
            //获取Y轴 图表的基本配置都在这个对象里面里面
            CTValAx catAy = chart.getCTChart().getPlotArea().getValAxArray(0);
            CTScaling ctScaling ;
            ctScaling = catAy.addNewScaling();
            //设置柱状图Y轴坐标最大值
            ctScaling.addNewMax().setVal(8);

            ctScaling.addNewOrientation().setVal(STOrientation.MAX_MIN);
            catAy.setScaling(ctScaling);
            // 设置图表背后的网格线
            CTLineProperties ctLine = catAy.addNewMajorGridlines().addNewSpPr().addNewLn();
            ctLine.addNewPrstDash().setVal(STPresetLineDashVal.DASH);

            //创建柱状图数据对象
            XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
            ((XDDFBarChartData) data).setBarDirection(BarDirection.COL);
			//柱状图图例标题
            XDDFChartData.Series series = data.addSeries(categoriesData, valuesDataA);
            series.setTitle("下雨量", setTitleInDataSheet(chart, "", 0));
            chart.plot(data);
//-----------------------------------------折线图-------------------------------------------------
            // 右Y轴
            XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
            // 右Y轴和X轴交叉点在X轴最大值位置
            rightAxis.setCrosses(AxisCrosses.MIN);
            rightAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
            // 构建坐标轴
            rightAxis.crossAxis(bottomAxis);
            bottomAxis.crossAxis(rightAxis);
            //设置折线图Y轴名称
            rightAxis.setTitle("水位/m");
            XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(categories);
            //设置折线图Y轴坐标最大值
            rightAxis.setMaximum(8);
            //LINE:折线图,
            data = chart.createData(ChartTypes.LINE, bottomAxis, rightAxis);
            //加载折线图数据
            XDDFNumericalDataSource<Double> area = XDDFDataSourcesFactory.fromArray(LinevaluesA);
            //图表加载数据,折线1
            XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(countries, area);
            //折线图例标题
            series1.setTitle("水位", null);
            //直线
            series1.setSmooth(true);
            //设置标记大小
            series1.setMarkerSize((short) 2);
            //设置空数据显示间隙
            CTDispBlanksAs disp = CTDispBlanksAs.Factory.newInstance();
            disp.setVal(STDispBlanksAs.GAP);
            chart.getCTChart().setDispBlanksAs(disp);
            data.setVaryColors(false);
            //绘制
            chart.plot(data);
            //设置图表图例
            XDDFChartLegend legend = chart.getOrAddLegend();
            legend.setPosition(LegendPosition.TOP);
            //生成word文件,设置文件相关信息。
            response.setContentType("application/force-download");// 设置强制下载不打开
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("折线+柱状组合图.docx", "UTF-8"));
            OutputStream out = response.getOutputStream();
            document.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
//在WORD内生成柱状图所需方法
    static CellReference setTitleInDataSheet(XWPFChart chart, String title, int column) {
        try {
            XSSFWorkbook workbook = null;
            workbook = chart.getWorkbook();
            XSSFSheet sheet = workbook.getSheetAt(0);
            XSSFRow row = sheet.getRow(0);
            if (row == null)
                row = sheet.createRow(0);
            XSSFCell cell = row.getCell(column);
            if (cell == null)
                cell = row.createCell(column);
            cell.setCellValue(title);
            return new CellReference(sheet.getSheetName(), 0, column, true, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

生成的效果图如下:
在这里插入图片描述
实际项目中遇到的问题,相关信息较少,记录一下,防止以后自己忘记。

在Java中,使用Apache POI库可以创建操作Excel文件,包括绘制图表。如果你想要将折线图导出Word文档,虽然POI本身主要是针对Excel,但是你可以结合其他库如docx4j或XWPF,它们能帮助你在Word文档中插入图片,然后将Excel中的图表作为图片添加。 以下是一个简单的步骤概述: 1. **准备数据**:首先,你需要收集好折线图的数据,可以用`HSSFWorkbook`或`XSSFWorkbook`创建一个工作簿,使用`CreationHelper`构建数据系列。 2. **创建图表**:使用`ChartFactory`创建一个`PieChart`或其他适合折线图的图表类型,设置标题、标签等元素。 3. **保存图表为图像**:使用`ChartUtilities`将图表保存为`PNG`或`JPEG`等形式的图片文件。 4. **处理Word文档**:使用docx4j或XWPF创建一个Word文档。加载或创建一个新的`Document`对象。 5. **插入图片到Word**:通过获取Word文档的`Paragraph`,然后添加一个`ImagePart`,设置图片的路径和大小,将折线图图片插入到Word文档中。 6. **保存Word文档**:最后,保存整个Word文档。 ```java // 示例代码简化版 try (FileInputStream fis = new FileInputStream("chart.png"); OutputStream dos = new FileOutputStream("output.docx")) { // ... 创建和配置图表、保存为图片 ... Document document = ...; // 初始化或打开Word文档 // 插入图片 ImagePart imagePart = ImagePart.createImagePart(document, fis); Body body = document.getBody(); Paragraph paragraph = body.createParagraph(); Run run = paragraph.createRun(); run.addImage(imagePart); // 保存Word文档 document.write(dos); }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值