因为有需求 需要把折线图 表格数据导出到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("导出失败,请重试!");
}
}