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;
    }

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

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
要在Java中导出带有Y轴的多条折线图到Excel,你可以继续使用Apache POI库和JFreeChart库,并进行一些适当的修改。以下是一个示例代码: ```java import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.*; import org.jfree.chart.*; import org.jfree.chart.axis.*; import org.jfree.chart.plot.*; import org.jfree.data.xy.*; import java.io.*; public class ExcelLineChartExporter { public static void main(String[] args) throws IOException { // 创建Excel工作簿和工作表 XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("折线图"); // 创建折线图数据集 XYDataset dataset = createDataset(); // 创建折线图 JFreeChart chart = createLineChart(dataset); // 将折线图绘制到Excel工作表中 ByteArrayOutputStream chartImage = new ByteArrayOutputStream(); ChartUtils.writeChartAsPNG(chartImage, chart, 400, 300); int pictureIdx = workbook.addPicture(chartImage.toByteArray(), Workbook.PICTURE_TYPE_PNG); chartImage.close(); CreationHelper helper = workbook.getCreationHelper(); Drawing drawing = sheet.createDrawingPatriarch(); ClientAnchor anchor = helper.createClientAnchor(); anchor.setCol1(0); anchor.setRow1(0); Picture picture = drawing.createPicture(anchor, pictureIdx); picture.resize(); // 保存Excel文件 FileOutputStream fileOut = new FileOutputStream("折线图.xlsx"); workbook.write(fileOut); fileOut.close(); System.out.println("折线图导出成功!"); } private static XYDataset createDataset() { // 创建折线图数据集 XYSeriesCollection dataset = new XYSeriesCollection(); // 添加折线图数据 XYSeries series1 = new XYSeries("系列1"); series1.add(1, 5); series1.add(2, 3); series1.add(3, 6); dataset.addSeries(series1); XYSeries series2 = new XYSeries("系列2"); series2.add(1, 4); series2.add(2, 7); series2.add(3, 9); dataset.addSeries(series2); return dataset; } private static JFreeChart createLineChart(XYDataset dataset) { // 创建折线图 JFreeChart chart = ChartFactory.createXYLineChart( "多条折线图", // 标题 "X轴", // X轴标签 "Y轴", // Y轴标签 dataset, // 数据集 PlotOrientation.VERTICAL, // 图表方向 true, // 是否包含图例 true, // 是否包含工具提示 false // 是否包含URL链接 ); // 获取绘图区域对象 XYPlot plot = chart.getXYPlot(); // 创建第二个Y轴 NumberAxis yAxis2 = new NumberAxis("Y轴2"); yAxis2.setAutoRangeIncludesZero(false); plot.setRangeAxis(1, yAxis2); // 将第二个数据集与第二个Y轴关联 plot.setDataset(1, createDataset()); plot.mapDatasetToRangeAxis(1, 1); // 创建第二个渲染器 XYLineAndShapeRenderer renderer2 = new XYLineAndShapeRenderer(); renderer2.setSeriesPaint(0, ChartColor.BLUE); plot.setRenderer(1, renderer2); return chart; } } ``` 在上述代码中,我们添加了一个名为`createLineChart`的新方法,用于创建带有Y轴折线图。我们使用了`XYPlot`和`NumberAxis`来创建第二个Y轴,并将第二个数据集与之关联。然后,我们创建了第二个渲染器`XYLineAndShapeRenderer`来设置第二个数据集的样式。 请注意,为了演示目的,我在`createLineChart`方法中直接调用了`createDataset`方法来创建第二个数据集。你可以根据实际需求修改代码以适应更复杂的数据集和样式。 同样,请确保已在项目中引入了Apache POI和JFreeChart的相关依赖。运行示例代码后,将会生成一个包含多条折线图的Excel文件。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值