Bootstrap

java使用poi技术导出折线图、表格到word

因为有需求 需要把折线图 表格数据导出到word 自己不会写 网上查了很多资源 有些代码零零散散得 还有缺少 不知道他们是怎么放上去得 自己当时写这个时候踩了很多坑 再次记录一下 防止忘记

话不多说 开始上硬菜

1.导出所需maven依赖

        <!--        导出所需依赖-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.4</version>
        </dependency>
        <!--hutool工具包-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.2</version>
        </dependency>
    • java具体代码

1.1这是所有数据名称
linedata:
  rowdate: 日期
  rowtime: 时间
  windgroupCmdP: 风机指令(MW)
  windgroupRealP: 风机实发(MW)
  storageCmdP: 储能指令(MW)
  storageRealP: 储能实发(MW)
  agcDispatchcmdP: AGC调令(MW)
  pccP: 并网点有功(MW)
1.2 前端传回所需导出word的数据 因为是多条多种数据 是一个集合 使用集合接收 nam是因为前端好几个页面公用一个方法 name是判断是哪个页面 方便最后生成导出文件默认文件名

代码之中其实用到了重复代码 我没有精简 因为这样后期方便维护 所以多写了一样的判断

package com.llx.controller;

import cn.hutool.core.io.FileUtil;
import com.llx.entiry.LineData;
import com.llx.results.Results;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.web.bind.annotation.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import java.io.*;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/export")
public class ExportReport {

    @PostMapping("/report")
    //lineDataList:集合数据 
    //name:因为前端好几个页面公用一个方法 name是判断是哪个页面 方便最后生成导出文件默认文件名
    public Results getExportReport(@RequestBody List<LineData> lineDataList, String name) throws Exception {
        // 1、创建word文档对象
        XWPFDocument document = new XWPFDocument();
        //纸张大小设置
        //CTSectPr ctSectPr = document.getDocument().getBody().addNewSectPr();
        //CTPageSz pgsz = ctSectPr.isSetPgSz() ? ctSectPr.getPgSz() : ctSectPr.addNewPgSz();
        //pgsz.setW(BigInteger.valueOf(11907));
        //pgsz.setH(BigInteger.valueOf(16840));

        //折线图部分
        //标头格式设置
        XWPFParagraph xwpfParagraph = document.createParagraph();
        xwpfParagraph.setSpacingBefore(0);
        XWPFRun xwpfRun = xwpfParagraph.createRun();
        xwpfRun.setText(name + "折线图展示");
        xwpfRun.setFontFamily("宋体");
        xwpfRun.setFontSize(16);
        xwpfRun.setTextPosition(10);
        xwpfRun.setBold(true);
        xwpfParagraph.setAlignment(ParagraphAlignment.CENTER);
        // 2、创建chart图表对象,抛出异常
        XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);
        // 3、图表相关设置
        // 图表标题
        //chart.setTitleText("风机数据图表展示");
        // 图例是否覆盖标题
        //chart.setTitleOverlay(true);
        // 4、图例设置
        XDDFChartLegend legend = chart.getOrAddLegend();
        // 图例位置:上下左右
        legend.setPosition(LegendPosition.TOP);
        // 5、X轴(分类轴)相关设置
        // 创建X轴,并且指定位置
        XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        //取消X轴的标刻度
        xAxis.setMajorTickMark(AxisTickMark.NONE);
        //获取X轴 图表的基本配置都在这个对象里面里面
        CTCatAx catAx = chart.getCTChart().getPlotArea().getCatAxArray(0);
        //设置标签位置为最下
        CTTickLblPos ctTickLblPos = CTTickLblPos.Factory.newInstance();
        ctTickLblPos.setVal(STTickLblPos.LOW);
        catAx.setTickLblPos(ctTickLblPos);
        // x轴标题
        //        xAxis.setPosition(AxisPosition.BOTTOM);
        //        xAxis.set
        //xAxis.setTitle("日期(年月)");
        List<String> strings = new ArrayList<>();
        for (LineData lineData : lineDataList) {
            strings.add(lineData.getRowdate().substring(5, 7) + "日" +
                    lineData.getRowtime().substring(0, 5));
        }
        String[] strings1 = strings.toArray(new String[0]);
        XDDFCategoryDataSource xAxisSource = XDDFDataSourcesFactory.fromArray(strings1);
        // 6、Y轴(值轴)相关设置
        // 创建Y轴,指定位置
        XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);
        //xAxis.crossAxis(yAxis);
        //yAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        //yAxis.setTitle("粉丝数(个)"); // Y轴标题
        // 设置图表背后的网格线
        CTValAx catAy = chart.getCTChart().getPlotArea().getValAxArray(0);
        CTLineProperties ctLine = catAy.addNewMajorGridlines().addNewSpPr().addNewLn();
        ctLine.addNewPrstDash().setVal(STPresetLineDashVal.DASH);
        List<Double> windgroupCmdPList = null;
        List<Double> windgroupRealPList = null;
        List<Double> storageCmdPList = null;
        List<Double> storageRealPList = null;
        List<Double> agcDispatchcmdPList = null;
        List<Double> pccPList = null;
        Double[] windgroupCmdPDoubles = null;
        Double[] windgroupRealPDoubles = null;
        Double[] storageCmdPDoubles = null;
        Double[] storageRealPDoubles = null;
        Double[] agcDispatchcmdPDoubles = null;
        Double[] pccPDoubles = null;
        // 7、创建折线图对象
        XDDFLineChartData lineChart = (XDDFLineChartData) chart.createData(ChartTypes.LINE, xAxis, yAxis);
        lineChart.setVaryColors(false);
        LineData lineDataNew = new LineData();
        for (LineData lineDatas : lineDataList) {
            lineDataNew = lineDatas;
            break;
        }
        if (lineDataNew.getWindgroupCmdP() != null) {
            windgroupCmdPList = new ArrayList<>();
            for (LineData lineData : lineDataList) {
                windgroupCmdPList.add(Double.valueOf(lineData.getWindgroupCmdP()));
            }
            windgroupCmdPDoubles = windgroupCmdPList.toArray(new Double[0]);
            // 设置Y轴 风机指令(MW) 数据
            XDDFNumericalDataSource<Double> yAxisSource = XDDFDataSourcesFactory.fromArray(windgroupCmdPDoubles);
            // 8、加载折线图数据集
            XDDFLineChartData.Series lineSeries = (XDDFLineChartData.Series) lineChart.addSeries(xAxisSource, yAxisSource);
            lineSeries.setTitle("风机指令(MW)", null); // 图例标题
            lineSeries.setSmooth(true); // 线条样式:true平滑曲线,false折线
            lineSeries.setMarkerSize((short) 2); // 标记点大小
            lineSeries.setMarkerStyle(MarkerStyle.CIRCLE); // 标记点样式
        }
        if (lineDataNew.getWindgroupRealP() != null) {
            windgroupRealPList = new ArrayList<>();
            for (LineData lineData : lineDataList) {
                windgroupRealPList.add(Double.valueOf(lineData.getWindgroupRealP()));
            }
            windgroupRealPDoubles = windgroupRealPList.toArray(new Double[0]);
            // 设置Y轴 风机实发(MW) 数据
            XDDFNumericalDataSource<Double> yAxisSource2 = XDDFDataSourcesFactory.fromArray(windgroupRealPDoubles);
            // 8、加载折线图数据集
            XDDFLineChartData.Series lineSeries2 = (XDDFLineChartData.Series) lineChart.addSeries(xAxisSource, yAxisSource2);
            lineSeries2.setTitle("风机实发(MW)", null); // 图例标题
            lineSeries2.setSmooth(true); // 线条样式:true平滑曲线,false折线
            lineSeries2.setMarkerSize((short) 2); // 标记点大小
            lineSeries2.setMarkerStyle(MarkerStyle.CIRCLE); // 标记点样式
        }
        if (lineDataNew.getStorageCmdP() != null) {
            storageCmdPList = new ArrayList<>();
            for (LineData lineData : lineDataList) {
                storageCmdPList.add(Double.valueOf(lineData.getStorageCmdP()));
            }
            storageCmdPDoubles = storageCmdPList.toArray(new Double[0]);
            // 设置Y轴 储能指令(MW) 数据
            XDDFNumericalDataSource<Double> yAxisSource3 = XDDFDataSourcesFactory.fromArray(storageCmdPDoubles);
            // 8、加载折线图数据集
            XDDFLineChartData.Series lineSeries3 = (XDDFLineChartData.Series) lineChart.addSeries(xAxisSource, yAxisSource3);
            lineSeries3.setTitle("储能指令(MW)", null); // 图例标题
            lineSeries3.setSmooth(true); // 线条样式:true平滑曲线,false折线
            lineSeries3.setMarkerSize((short) 2); // 标记点大小
            lineSeries3.setMarkerStyle(MarkerStyle.CIRCLE); // 标记点样式
        }
        if (lineDataNew.getStorageRealP() != null) {
            storageRealPList = new ArrayList<>();
            for (LineData lineData : lineDataList) {
                storageRealPList.add(Double.valueOf(lineData.getStorageRealP()));
            }
            storageRealPDoubles = storageRealPList.toArray(new Double[0]);
            // 设置Y轴 储能实发(MW) 数据
            XDDFNumericalDataSource<Double> yAxisSource4 = XDDFDataSourcesFactory.fromArray(storageRealPDoubles);
            // 8、加载折线图数据集
            XDDFLineChartData.Series lineSeries4 = (XDDFLineChartData.Series) lineChart.addSeries(xAxisSource, yAxisSource4);
            lineSeries4.setTitle("储能实发(MW)", null); // 图例标题
            lineSeries4.setSmooth(true); // 线条样式:true平滑曲线,false折线
            lineSeries4.setMarkerSize((short) 2); // 标记点大小
            lineSeries4.setMarkerStyle(MarkerStyle.CIRCLE); // 标记点样式
        }
        if (lineDataNew.getAgcDispatchcmdP() != null) {
            agcDispatchcmdPList = new ArrayList<>();
            for (LineData lineData : lineDataList) {
                agcDispatchcmdPList.add(Double.valueOf(lineData.getAgcDispatchcmdP()));
            }
            agcDispatchcmdPDoubles = agcDispatchcmdPList.toArray(new Double[0]);
            // 设置Y轴 AGC调令(MW) 数据
            XDDFNumericalDataSource<Double> yAxisSource5 = XDDFDataSourcesFactory.fromArray(agcDispatchcmdPDoubles);
            // 8、加载折线图数据集
            XDDFLineChartData.Series lineSeries5 = (XDDFLineChartData.Series) lineChart.addSeries(xAxisSource, yAxisSource5);
            lineSeries5.setTitle("AGC调令(MW)", null); // 图例标题
            lineSeries5.setSmooth(true); // 线条样式:true平滑曲线,false折线
            lineSeries5.setMarkerSize((short) 2); // 标记点大小
            lineSeries5.setMarkerStyle(MarkerStyle.CIRCLE); // 标记点样式
        }
        if (lineDataNew.getPccP() != null) {
            pccPList = new ArrayList<>();
            for (LineData lineData : lineDataList) {
                pccPList.add(Double.valueOf(lineData.getPccP()));
            }
            pccPDoubles = pccPList.toArray(new Double[0]);
            // 设置Y轴 并网点有功(MW) 数据
            XDDFNumericalDataSource<Double> yAxisSource6 = XDDFDataSourcesFactory.fromArray(pccPDoubles);
            // 8、加载折线图数据集
            XDDFLineChartData.Series lineSeries6 = (XDDFLineChartData.Series) lineChart.addSeries(xAxisSource, yAxisSource6);
            lineSeries6.setTitle("并网点有功(MW)", null); // 图例标题
            lineSeries6.setSmooth(true); // 线条样式:true平滑曲线,false折线
            lineSeries6.setMarkerSize((short) 2); // 标记点大小
            lineSeries6.setMarkerStyle(MarkerStyle.CIRCLE); // 标记点样式
        }
// 9、绘制折线图
        chart.plot(lineChart);
//表格部分
        XWPFParagraph xwpfParagraph2 = document.createParagraph();
        xwpfParagraph2.setSpacingBefore(1);
        XWPFRun xwpfRun2 = xwpfParagraph2.createRun();
        xwpfRun2.addBreak();
        xwpfRun2.setText(name + "表格展示");
        xwpfRun2.setFontFamily("宋体");
        xwpfRun2.setFontSize(16);
        xwpfRun2.setTextPosition(10);
        xwpfRun2.setBold(true);
        xwpfParagraph2.setAlignment(ParagraphAlignment.CENTER);
// 创建表格
        XWPFTable table = document.createTable();
        CTTblWidth comTableWidth = table.getCTTbl().addNewTblPr().addNewTblW();
        comTableWidth.setType(STTblWidth.DXA);
        //表格宽度
        comTableWidth.setW(BigInteger.valueOf(9072));
// 设置表头
        int n = 2;
        StringBuilder stringBuilder = new StringBuilder();
        XWPFTableRow rowOne = table.getRow(0);
        stringBuilder.append("日期");
        stringBuilder.append(",时间");
        if (lineDataNew.getWindgroupCmdP() != null) {
            stringBuilder.append(",风机指令(MW)");
            n += 1;
        }
        if (lineDataNew.getWindgroupRealP() != null) {
            stringBuilder.append(",风机实发(MW)");
            n += 1;
        }
        if (lineDataNew.getStorageCmdP() != null) {
            stringBuilder.append(",储能指令(MW)");
            n += 1;
        }
        if (lineDataNew.getStorageRealP() != null) {
            stringBuilder.append(",储能实发(MW)");
            n += 1;
        }
        if (lineDataNew.getAgcDispatchcmdP() != null) {
            stringBuilder.append(",AGC调令(MW)");
            n += 1;
        }
        if (lineDataNew.getPccP() != null) {
            stringBuilder.append(",并网点有功(MW)");
            n += 1;
        }
        String[] lineDatas = stringBuilder.toString().split(",");
        for (int i = 0; i < lineDatas.length; i++) {
            XWPFTableCell cell = rowOne.getCell(i);
            if (cell == null) {
                cell = rowOne.addNewTableCell();
            }
            cell.setText(lineDatas[i]);
        }
// 设置行高
        rowOne.setHeight(500);
// 设置明细数据
        for (int i = 0; i < lineDataList.size(); i++) {
            XWPFTableRow tableRow = table.createRow();
            for (int j = 0; j < n; j++) {
                tableRow.getCell(j).setText(lineDataList.get(i).getRowdate());
                j += 1;
                tableRow.getCell(j).setText(lineDataList.get(i).getRowtime());
                j += 1;
                if (lineDataNew.getWindgroupCmdP() != null) {
                    tableRow.getCell(j).setText(lineDataList.get(i).getWindgroupCmdP());
                    j += 1;
                }
                if (lineDataNew.getWindgroupRealP() != null) {
                    tableRow.getCell(j).setText(lineDataList.get(i).getWindgroupRealP());
                    j += 1;
                }
                if (lineDataNew.getStorageCmdP() != null) {
                    tableRow.getCell(j).setText(lineDataList.get(i).getStorageCmdP());
                    j += 1;
                }
                if (lineDataNew.getStorageRealP() != null) {
                    tableRow.getCell(j).setText(lineDataList.get(i).getStorageRealP());
                    j += 1;
                }
                if (lineDataNew.getAgcDispatchcmdP() != null) {
                    tableRow.getCell(j).setText(lineDataList.get(i).getAgcDispatchcmdP());
                    j += 1;
                }
                if (lineDataNew.getPccP() != null) {
                    tableRow.getCell(j).setText(lineDataList.get(i).getPccP());
                    j += 1;
                }
            }
            tableRow.setHeight(400);
        }
        //设置单元格居中
        List<XWPFTableRow> rows = table.getRows();
        for (XWPFTableRow xwpfTableRow : rows) {
            List<XWPFTableCell> tableCells = xwpfTableRow.getTableCells();
            for (XWPFTableCell tableCell : tableCells) {
                CTTc ctTc = tableCell.getCTTc();
                CTTcPr ctTcPr = ctTc.addNewTcPr();
                //垂直居中
                ctTcPr.addNewVAlign().setVal(STVerticalJc.CENTER);
                //水平居中
                ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
            }
        }
//输出部分
// 10、输出到word文档 C:\Users\CHINA\Desktop\测试.docx
        String dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        String date = dateFormat.replace(" ", "-").replace(":", "-");
        String fileName = name + "-" + date;
        FileOutputStream fos = null;
        File file = null;
        JFrame frame = new JFrame();
        frame.setAlwaysOnTop(true);// 设置顶置
        frame.setVisible(false);// 隐藏顶置窗口
        frame.setBounds(400, 200, 0, 0);
        FileSystemView fsv = FileSystemView.getFileSystemView();
        FileNameExtensionFilter fileFilter = new FileNameExtensionFilter("*.docx", "docx");
        JFileChooser jFileChooser = new JFileChooser(fsv.getHomeDirectory());
        jFileChooser.setFileFilter(fileFilter);
//jFileChooser.setDialogTitle("ss");
        jFileChooser.setSelectedFile(new File(fileName));
//去掉 “所有文件” 这四个字
        jFileChooser.removeChoosableFileFilter(jFileChooser.getAcceptAllFileFilter());
        int result = jFileChooser.showSaveDialog(frame);
        if (result == JFileChooser.APPROVE_OPTION) {
            file = jFileChooser.getSelectedFile();
            String pathName = file.getPath() + "-" + date + ".docx";
            fos = new FileOutputStream(pathName);
        } else {
            return Results.success("用户取消操作");
        }
        if (fos != null) {
//导出word
            document.write(fos);
//11、关闭流
            fos.close();
        }
        document.close();
        String path = file.getPath().substring(0, file.getPath().lastIndexOf("\\"));
        List<String> listFileNames = FileUtil.listFileNames(path);
        for (String listFileName : listFileNames) {
            if (listFileName.equals(file.getName() + "-" + date + ".docx")) {
                return Results.success("导出成功");
            }
        }
        return Results.error("导出失败,请重试!");
    }
}
;