本文参考地址:https://blog.youkuaiyun.com/u014427811/article/details/100771314
在参考文章的基础上,增加了模板样例
模板样例地址 百度网盘
链接:https://pan.baidu.com/s/16qDvE2-V-tpX_bY8NNnepw
提取码:yhbd
这个必须引入poi4.0以上版本,以验证过
完整pom.xml内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.turing</groupId>
<artifactId>report</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>report</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
数据这块完全拷贝大哥的
package com.turing.report.controller;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author :MaWT
* @date :Created in 2020/2/21 11:40
* @description:
* @modified By:
* @version: $
*/
@RestController
public class ReportController {
@GetMapping("export")
public static void export() throws Exception {
final String returnurl = "C:\\Users\\wangcan\\Desktop\\data\\reportTemplate-word.docx"; // 结果文件
final String templateurl = "C:\\Users\\wangcan\\Desktop\\templates\\reportTemplate-word.docx"; // 模板文件
InputStream is = new FileInputStream(new File(templateurl));
XWPFDocument doc = new XWPFDocument(is);
// 替换word模板数据
replaceAll(doc);
// 保存结果文件
try {
File file = new File(returnurl);
if (file.exists()) {
file.delete();
}
FileOutputStream fos = new FileOutputStream(returnurl);
doc.write(fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @Description: 替换段落和表格中
*/
public static void replaceAll(XWPFDocument doc) throws InvalidFormatException, IOException {
doParagraphs(doc); // 处理段落文字数据,包括文字和表格、图片
doCharts(doc); // 处理图表数据,柱状图、折线图、饼图啊之类的
}
/**
* 处理段落文字
*
* @param doc
* @throws InvalidFormatException
* @throws FileNotFoundException
* @throws IOException
*/
public static void doParagraphs(XWPFDocument doc) throws InvalidFormatException, IOException {
// 文本数据
Map<String, String> textMap = new HashMap<String, String>();
textMap.put("var", "我是被替换的文本内容");
// 图片数据
Map<String, String> imgMap = new HashMap<String, String>();
imgMap.put("img", "E:\\idea\\timg.jpg");
/**----------------------------处理段落------------------------------------**/
List<XWPFParagraph> paragraphList = doc.getParagraphs();
if (paragraphList != null && paragraphList.size() > 0) {
for (XWPFParagraph paragraph : paragraphList) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
String text = run.getText(0);
if (text != null) {
// 替换文本信息
String tempText = text;
// String key = tempText.replaceAll("\\{\\{", "").replaceAll("}}", "");
if (!StringUtils.isEmpty(textMap.get(text))) {
run.setText(textMap.get(text), 0);
}
// 替换图片内容 参考:https://blog.youkuaiyun.com/a909301740/article/details/84984445
String tempImgText = text;
// String imgkey = tempImgText.replaceAll("\\{\\{@", "").replaceAll("}}", "");
if (!StringUtils.isEmpty(imgMap.get(text))) {
String imgPath = imgMap.get(text);
try {
run.setText("", 0);
run.addPicture(new FileInputStream(imgPath), Document.PICTURE_TYPE_PNG, "img.png", Units.toEMU(200), Units.toEMU(200));
} catch (Exception e) {
e.printStackTrace();
}
}
// 动态表格
if (text.contains("table")) {
run.setText("", 0);
XmlCursor cursor = paragraph.getCTP().newCursor();
XWPFTable tableOne = doc.insertNewTbl(cursor);// ---这个是关键
// 设置表格宽度,第一行宽度就可以了,这个值的单位,目前我也还不清楚,还没来得及研究
tableOne.setWidth(8500);
// 表格第一行,对于每个列,必须使用createCell(),而不是getCell(),因为第一行嘛,肯定是属于创建的,没有create哪里来的get呢
XWPFTableRow tableOneRowOne = tableOne.getRow(0);//行
PoiWordTools.setWordCellSelfStyle(tableOneRowOne.getCell(0), "微软雅黑", "9", 0, "left", "top", "#000000", "#B4C6E7", "10%", "序号");
PoiWordTools.setWordCellSelfStyle(tableOneRowOne.createCell(), "微软雅黑", "9", 0, "left", "top", "#000000", "#B4C6E7", "45%", "公司名称(英文)");
PoiWordTools.setWordCellSelfStyle(tableOneRowOne.createCell(), "微软雅黑", "9", 0, "left", "top", "#000000", "#B4C6E7", "45%", "公司名称(中文)");
// 表格第二行
XWPFTableRow tableOneRowTwo = tableOne.createRow();//行
PoiWordTools.setWordCellSelfStyle(tableOneRowTwo.getCell(0), "微软雅黑", "9", 0, "left", "top", "#000000", "#B4C6E7", "10%", "一行一列");
PoiWordTools.setWordCellSelfStyle(tableOneRowTwo.getCell(1), "微软雅黑", "9", 0, "left", "top", "#000000", "#B4C6E7", "45%", "一行一列");
PoiWordTools.setWordCellSelfStyle(tableOneRowTwo.getCell(2), "微软雅黑", "9", 0, "left", "top", "#000000", "#B4C6E7", "45%", "一行一列");
// ....... 可动态添加表格
}
}
}
}
}
}
/**
* 处理图表
*
* @param doc
* @throws FileNotFoundException
*/
public static void doCharts(XWPFDocument doc) throws FileNotFoundException {
/**----------------------------处理图表------------------------------------**/
// 数据准备
List<String> titleArr = new ArrayList<String>();// 标题
titleArr.add("title");
titleArr.add("金额");
List<String> fldNameArr = new ArrayList<String>();// 字段名
fldNameArr.add("item1");
fldNameArr.add("item2");
// 数据集合
List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();
// 第一行数据
Map<String, String> base1 = new HashMap<String, String>();
base1.put("item1", "材料费用");
base1.put("item2", "500");
// 第二行数据
Map<String, String> base2 = new HashMap<String, String>();
base2.put("item1", "出差费用");
base2.put("item2", "300");
// 第三行数据
Map<String, String> base3 = new HashMap<String, String>();
base3.put("item1", "住宿费用");
base3.put("item2", "300");
listItemsByType.add(base1);
listItemsByType.add(base2);
listItemsByType.add(base3);
// 获取word模板中的所有图表元素,用map存放
// 为什么不用list保存:查看doc.getRelations()的源码可知,源码中使用了hashMap读取文档图表元素,
// 对relations变量进行打印后发现,图表顺序和文档中的顺序不一致,也就是说relations的图表顺序不是文档中从上到下的顺序
Map<String, POIXMLDocumentPart> chartsMap = new HashMap<String, POIXMLDocumentPart>();
//动态刷新图表
List<POIXMLDocumentPart> relations = doc.getRelations();
for (POIXMLDocumentPart poixmlDocumentPart : relations) {
if (poixmlDocumentPart instanceof XWPFChart) { // 如果是图表元素
String str = poixmlDocumentPart.toString();
System.out.println("str:" + str);
String key = str.replaceAll("Name: ", "")
.replaceAll(" - Content Type: application/vnd\\.openxmlformats-officedocument\\.drawingml\\.chart\\+xml", "").trim();
System.out.println("key:" + key);
chartsMap.put(key, poixmlDocumentPart);
}
}
System.out.println("\n图表数量:" + chartsMap.size() + "\n");
// 第一个图表-条形图
POIXMLDocumentPart poixmlDocumentPart0 = chartsMap.get("/word/charts/chart1.xml");
PoiWordTools.replaceBarCharts(poixmlDocumentPart0, titleArr, fldNameArr, listItemsByType);
// 第二个-柱状图
POIXMLDocumentPart poixmlDocumentPart1 = chartsMap.get("/word/charts/chart2.xml");
PoiWordTools.replaceBarCharts(poixmlDocumentPart1, titleArr, fldNameArr, listItemsByType);
// 第三个图表-多列柱状图
doCharts3(chartsMap);
// 第四个图表-折线图
doCharts4(chartsMap);
// 第五个图表-饼图
POIXMLDocumentPart poixmlDocumentPart4 = chartsMap.get("/word/charts/chart5.xml");
PoiWordTools.replacePieCharts(poixmlDocumentPart4, titleArr, fldNameArr, listItemsByType);
doCharts6(chartsMap);
}
public static void doCharts3(Map<String, POIXMLDocumentPart> chartsMap) {
// 数据准备
List<String> titleArr = new ArrayList<String>();// 标题
titleArr.add("姓名");
titleArr.add("欠款");
titleArr.add("存款");
List<String> fldNameArr = new ArrayList<String>();// 字段名
fldNameArr.add("item1");
fldNameArr.add("item2");
fldNameArr.add("item3");
// 数据集合
List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();
// 第一行数据
Map<String, String> base1 = new HashMap<String, String>();
base1.put("item1", "老张");
base1.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base1.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第二行数据
Map<String, String> base2 = new HashMap<String, String>();
base2.put("item1", "老李");
base2.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base2.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第三行数据
Map<String, String> base3 = new HashMap<String, String>();
base3.put("item1", "老刘");
base3.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base3.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
listItemsByType.add(base1);
listItemsByType.add(base2);
listItemsByType.add(base3);
POIXMLDocumentPart poixmlDocumentPart2 = chartsMap.get("/word/charts/chart3.xml");
PoiWordTools.replaceBarCharts(poixmlDocumentPart2, titleArr, fldNameArr, listItemsByType);
}
public static void doCharts4(Map<String, POIXMLDocumentPart> chartsMap) {
// 数据准备
List<String> titleArr = new ArrayList<String>();// 标题
titleArr.add("title");
titleArr.add("占基金资产净值比例22222(%)");
titleArr.add("额外的(%)");
titleArr.add("额外的(%)");
List<String> fldNameArr = new ArrayList<String>();// 字段名
fldNameArr.add("item1");
fldNameArr.add("item2");
fldNameArr.add("item3");
fldNameArr.add("item4");
// 数据集合
List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();
// 第一行数据
Map<String, String> base1 = new HashMap<String, String>();
base1.put("item1", "材料费用");
base1.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base1.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base1.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第二行数据
Map<String, String> base2 = new HashMap<String, String>();
base2.put("item1", "出差费用");
base2.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base2.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base2.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第三行数据
Map<String, String> base3 = new HashMap<String, String>();
base3.put("item1", "住宿费用");
base3.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base3.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base3.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
listItemsByType.add(base1);
listItemsByType.add(base2);
listItemsByType.add(base3);
POIXMLDocumentPart poixmlDocumentPart2 = chartsMap.get("/word/charts/chart4.xml");
PoiWordTools.replaceLineCharts(poixmlDocumentPart2, titleArr, fldNameArr, listItemsByType);
}
/**
* 对应文档中的第6个图表(预处理—分公司情况)
*/
public static void doCharts6(Map<String, POIXMLDocumentPart> chartsMap) {
// 数据准备
List<String> titleArr = new ArrayList<String>();// 标题
titleArr.add("title");
titleArr.add("投诉受理量(次)");
titleArr.add("预处理拦截工单量(次)");
titleArr.add("拦截率");
List<String> fldNameArr = new ArrayList<String>();// 字段名
fldNameArr.add("item1");
fldNameArr.add("item2");
fldNameArr.add("item3");
fldNameArr.add("item4");
// 数据集合
List<Map<String, String>> listItemsByType = new ArrayList<Map<String, String>>();
// 第一行数据
Map<String, String> base1 = new HashMap<String, String>();
base1.put("item1", "通辽");
base1.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base1.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base1.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第二行数据
Map<String, String> base2 = new HashMap<String, String>();
base2.put("item1", "呼和浩特");
base2.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base2.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base2.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第三行数据
Map<String, String> base3 = new HashMap<String, String>();
base3.put("item1", "锡林郭勒");
base3.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base3.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base3.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第四行数据
Map<String, String> base4 = new HashMap<String, String>();
base4.put("item1", "阿拉善");
base4.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base4.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base4.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第五行数据
Map<String, String> base5 = new HashMap<String, String>();
base5.put("item1", "巴彦淖尔");
base5.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base5.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base5.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第六行数据
Map<String, String> base6 = new HashMap<String, String>();
base6.put("item1", "兴安");
base6.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base6.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base6.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第七行数据
Map<String, String> base7 = new HashMap<String, String>();
base7.put("item1", "乌兰察布");
base7.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base7.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base7.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第八行数据
Map<String, String> base8 = new HashMap<String, String>();
base8.put("item1", "乌海");
base8.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base8.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base8.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第九行数据
Map<String, String> base9 = new HashMap<String, String>();
base9.put("item1", "赤峰");
base9.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base9.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base9.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第十行数据
Map<String, String> base10 = new HashMap<String, String>();
base10.put("item1", "包头");
base10.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base10.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base10.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第十一行数据
Map<String, String> base11 = new HashMap<String, String>();
base11.put("item1", "呼伦贝尔");
base11.put("item2", (int)(int)(1 + Math.random() * (100 - 1 + 1)) + "");
base11.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base11.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
// 第十二行数据
Map<String, String> base12 = new HashMap<String, String>();
base12.put("item1", "鄂尔多斯");
base12.put("item2", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base12.put("item3", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
base12.put("item4", (int)(1 + Math.random() * (100 - 1 + 1)) + "");
listItemsByType.add(base1);
listItemsByType.add(base2);
listItemsByType.add(base3);
listItemsByType.add(base4);
listItemsByType.add(base5);
listItemsByType.add(base6);
listItemsByType.add(base7);
listItemsByType.add(base8);
listItemsByType.add(base9);
listItemsByType.add(base10);
listItemsByType.add(base11);
listItemsByType.add(base12);
// 下标0的图表-折线图
POIXMLDocumentPart poixmlDocumentPart5 = chartsMap.get("/word/charts/chart6.xml");
PoiWordTools.replaceCombinationCharts(poixmlDocumentPart5, titleArr, fldNameArr, listItemsByType);
}
}
工具类也是参考的加上游客的意见
package com.turing.report.controller;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFChart;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
/**
* poi生成word的工具类
*/
@Component
public class PoiWordTools {
private static final BigDecimal bd2 = new BigDecimal("2");
/**
* 调用替换柱状图数据
*/
public static void replaceBarCharts(POIXMLDocumentPart poixmlDocumentPart,
List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
XWPFChart chart = (XWPFChart) poixmlDocumentPart;
chart.getCTChart();
//根据属性第一列名称切换数据类型
CTChart ctChart = chart.getCTChart();
CTPlotArea plotArea = ctChart.getPlotArea();
CTBarChart barChart = plotArea.getBarChartArray(0);
List<CTBarSer> BarSerList = barChart.getSerList(); // 获取柱状图单位
//刷新内置excel数据
refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
//刷新页面显示数据
refreshBarStrGraphContent(barChart, BarSerList, listItemsByType, fldNameArr, 1);
}
/**
* 调用替换折线图数据
*/
public static void replaceLineCharts(POIXMLDocumentPart poixmlDocumentPart,
List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
XWPFChart chart = (XWPFChart) poixmlDocumentPart;
chart.getCTChart();
//根据属性第一列名称切换数据类型
CTChart ctChart = chart.getCTChart();
CTPlotArea plotArea = ctChart.getPlotArea();
CTLineChart lineChart = plotArea.getLineChartArray(0);
List<CTLineSer> lineSerList = lineChart.getSerList(); // 获取折线图单位
//刷新内置excel数据
refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
//刷新页面显示数据
refreshLineStrGraphContent(lineChart, lineSerList, listItemsByType, fldNameArr, 1);
}
/**
* 调用替换饼图数据
*/
public static void replacePieCharts(POIXMLDocumentPart poixmlDocumentPart,
List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
XWPFChart chart = (XWPFChart) poixmlDocumentPart;
chart.getCTChart();
//根据属性第一列名称切换数据类型
CTChart ctChart = chart.getCTChart();
CTPlotArea plotArea = ctChart.getPlotArea();
CTPieChart pieChart = plotArea.getPieChartArray(0);
List<CTPieSer> pieSerList = pieChart.getSerList(); // 获取饼图单位
//刷新内置excel数据
refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
//刷新页面显示数据
refreshPieStrGraphContent(pieChart, pieSerList, listItemsByType, fldNameArr, 1);
}
/**
* 调用替换柱状图、折线图组合数据
*/
public static void replaceCombinationCharts(POIXMLDocumentPart poixmlDocumentPart,
List<String> titleArr, List<String> fldNameArr, List<Map<String, String>> listItemsByType) {
XWPFChart chart = (XWPFChart) poixmlDocumentPart;
chart.getCTChart();
//根据属性第一列名称切换数据类型
CTChart ctChart = chart.getCTChart();
CTPlotArea plotArea = ctChart.getPlotArea();
CTBarChart barChart = plotArea.getBarChartArray(0);
List<CTBarSer> barSerList = barChart.getSerList(); // 获取柱状图单位
//刷新内置excel数据
refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
//刷新页面显示数据
refreshBarStrGraphContent(barChart, barSerList, listItemsByType, fldNameArr, 1);
CTBarChart barChart2 = plotArea.getBarChartArray(0);
List<CTBarSer> barSerList2 = barChart2.getSerList(); // 获取柱状图单位
//刷新内置excel数据
refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
//刷新页面显示数据
refreshBarStrGraphContent(barChart2, barSerList2, listItemsByType, fldNameArr, 1);
CTLineChart lineChart = plotArea.getLineChartArray(0);
List<CTLineSer> lineSerList = lineChart.getSerList(); // 获取折线图单位
//刷新内置excel数据
refreshExcel(chart, listItemsByType, fldNameArr, titleArr);
//刷新页面显示数据
refreshLineStrGraphContent(lineChart, lineSerList, listItemsByType, fldNameArr, 1);
}
/**
* 刷新折线图数据方法
*
* @param typeChart
* @param serList
* @param dataList
* @param fldNameArr
* @param position
* @return
*/
public static boolean refreshLineStrGraphContent(Object typeChart,
List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {
boolean result = true;
//更新数据区域
for (int i = 0; i < serList.size(); i++) {
//CTSerTx tx=null;
CTAxDataSource cat = null;
CTNumDataSource val = null;
CTLineSer ser = ((CTLineChart) typeChart).getSerArray(i);
//tx= ser.getTx();
// Category Axis Data
cat = ser.getCat();
// 获取图表的值
val = ser.getVal();
// strData.set
CTStrData strData = cat.getStrRef().getStrCache();
CTNumData numData = val.getNumRef().getNumCache();
strData.setPtArray((CTStrVal[]) null); // unset old axis text
numData.setPtArray((CTNumVal[]) null); // unset old values
// set model
long idx = 0;
for (int j = 0; j < dataList.size(); j++) {
//判断获取的值是否为空
String value = "0";
if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
}
if (!"0".equals(value)) {
CTNumVal numVal = numData.addNewPt();//序列值
numVal.setIdx(idx);
numVal.setV(value);
}
CTStrVal sVal = strData.addNewPt();//序列名称
sVal.setIdx(idx);
sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
idx++;
}
numData.getPtCount().setVal(idx);
strData.getPtCount().setVal(idx);
//赋值横坐标数据区域
String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
.formatAsString("Sheet1", false);
cat.getStrRef().setF(axisDataRange);
//数据区域
String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
.formatAsString("Sheet1", false);
val.getNumRef().setF(numDataRange);
// 设置系列生成方向
}
return result;
}
/**
* 刷新柱状图数据方法
*
* @param typeChart
* @param serList
* @param dataList
* @param fldNameArr
* @param position
* @return
*/
public static boolean refreshBarStrGraphContent(Object typeChart,
List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {
boolean result = true;
//更新数据区域
for (int i = 0; i < serList.size(); i++) {
//CTSerTx tx=null;
CTAxDataSource cat = null;
CTNumDataSource val = null;
CTBarSer ser = ((CTBarChart) typeChart).getSerArray(i);
//tx= ser.getTx();
// Category Axis Data
cat = ser.getCat();
// 获取图表的值
val = ser.getVal();
// strData.set
CTStrData strData = cat.getStrRef().getStrCache();
CTNumData numData = val.getNumRef().getNumCache();
strData.setPtArray((CTStrVal[]) null); // unset old axis text
numData.setPtArray((CTNumVal[]) null); // unset old values
// set model
long idx = 0;
for (int j = 0; j < dataList.size(); j++) {
//判断获取的值是否为空
String value = "0";
if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i+position))) != null) {
value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
}
if (!"0".equals(value)) {
CTNumVal numVal = numData.addNewPt();//序列值
numVal.setIdx(idx);
numVal.setV(value);
}
CTStrVal sVal = strData.addNewPt();//序列名称
sVal.setIdx(idx);
sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
idx++;
}
numData.getPtCount().setVal(idx);
strData.getPtCount().setVal(idx);
//赋值横坐标数据区域
String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
.formatAsString("Sheet1", true);
cat.getStrRef().setF(axisDataRange);
//数据区域
String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
.formatAsString("Sheet1", true);
val.getNumRef().setF(numDataRange);
}
return result;
}
/**
* 刷新饼图数据方法
*
* @param typeChart
* @param serList
* @param dataList
* @param fldNameArr
* @param position
* @return
*/
public static boolean refreshPieStrGraphContent(Object typeChart,
List<?> serList, List<Map<String, String>> dataList, List<String> fldNameArr, int position) {
boolean result = true;
//更新数据区域
for (int i = 0; i < serList.size(); i++) {
//CTSerTx tx=null;
CTAxDataSource cat = null;
CTNumDataSource val = null;
CTPieSer ser = ((CTPieChart) typeChart).getSerArray(i);
//tx= ser.getTx();
// Category Axis Data
cat = ser.getCat();
// 获取图表的值
val = ser.getVal();
// strData.set
CTStrData strData = cat.getStrRef().getStrCache();
CTNumData numData = val.getNumRef().getNumCache();
strData.setPtArray((CTStrVal[]) null); // unset old axis text
numData.setPtArray((CTNumVal[]) null); // unset old values
// set model
long idx = 0;
for (int j = 0; j < dataList.size(); j++) {
//判断获取的值是否为空
String value = "0";
if (new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))) != null) {
value = new BigDecimal(dataList.get(j).get(fldNameArr.get(i + position))).toString();
}
if (!"0".equals(value)) {
CTNumVal numVal = numData.addNewPt();//序列值
numVal.setIdx(idx);
numVal.setV(value);
}
CTStrVal sVal = strData.addNewPt();//序列名称
sVal.setIdx(idx);
sVal.setV(dataList.get(j).get(fldNameArr.get(0)));
idx++;
}
numData.getPtCount().setVal(idx);
strData.getPtCount().setVal(idx);
//赋值横坐标数据区域
String axisDataRange = new CellRangeAddress(1, dataList.size(), 0, 0)
.formatAsString("Sheet1", true);
cat.getStrRef().setF(axisDataRange);
//数据区域
String numDataRange = new CellRangeAddress(1, dataList.size(), i + position, i + position)
.formatAsString("Sheet1", true);
val.getNumRef().setF(numDataRange);
}
return result;
}
/**
* 刷新内置excel数据
*
* @param chart
* @param dataList
* @param fldNameArr
* @param titleArr
* @return
*/
public static boolean refreshExcel(XWPFChart chart,
List<Map<String, String>> dataList, List<String> fldNameArr, List<String> titleArr) {
boolean result = true;
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("Sheet1");
//根据数据创建excel第一行标题行
for (int i = 0; i < titleArr.size(); i++) {
if (sheet.getRow(0) == null) {
sheet.createRow(0).createCell(i).setCellValue(titleArr.get(i) == null ? "" : titleArr.get(i));
} else {
sheet.getRow(0).createCell(i).setCellValue(titleArr.get(i) == null ? "" : titleArr.get(i));
}
}
//遍历数据行
for (int i = 0; i < dataList.size(); i++) {
Map<String, String> baseFormMap = dataList.get(i);//数据行
//fldNameArr字段属性
for (int j = 0; j < fldNameArr.size(); j++) {
if (sheet.getRow(i + 1) == null) {
if (j == 0) {
try {
sheet.createRow(i + 1).createCell(j).setCellValue(baseFormMap.get(fldNameArr.get(j)) == null ? "" : baseFormMap.get(fldNameArr.get(j)));
} catch (Exception e) {
if (baseFormMap.get(fldNameArr.get(j)) == null) {
sheet.createRow(i + 1).createCell(j).setCellValue("");
} else {
sheet.createRow(i + 1).createCell(j).setCellValue(baseFormMap.get(fldNameArr.get(j)));
}
}
}
} else {
BigDecimal b = new BigDecimal(baseFormMap.get(fldNameArr.get(j)));
double value = 0d;
if (b != null) {
value = b.doubleValue();
}
if (value == 0) {
sheet.getRow(i + 1).createCell(j);
} else {
sheet.getRow(i + 1).createCell(j).setCellValue(b.doubleValue());
}
}
}
}
// 更新嵌入的workbook
List<POIXMLDocumentPart> pxdList = chart.getRelations();
if(pxdList!=null&&pxdList.size()>0){
for(int i = 0;i<pxdList.size();i++){
if(pxdList.get(i).toString().contains("sheet")){//判断为sheet再去进行更新表格数据
POIXMLDocumentPart xlsPart = pxdList.get(i);
OutputStream xlsOut = xlsPart.getPackagePart().getOutputStream();
try {
wb.write(xlsOut);
xlsOut.close();
} catch (IOException e) {
e.printStackTrace();
result = false;
} finally {
if (wb != null) {
try {
wb.close();
} catch (IOException e) {
e.printStackTrace();
result = false;
}
}
}
break;
}
}
}
return result;
}
/**
* 设置表格样式
*
* @param cell
* @param fontName
* @param fontSize
* @param fontBlod
* @param alignment
* @param vertical
* @param fontColor
* @param bgColor
* @param cellWidth
* @param content
*/
public static void setWordCellSelfStyle(XWPFTableCell cell, String fontName, String fontSize, int fontBlod,
String alignment, String vertical, String fontColor,
String bgColor, String cellWidth, String content) {
//poi对字体大小设置特殊,不支持小数,但对原word字体大小做了乘2处理
BigInteger bFontSize = new BigInteger("24");
if (fontSize != null && !fontSize.equals("")) {
//poi对字体大小设置特殊,不支持小数,但对原word字体大小做了乘2处理
BigDecimal fontSizeBD = new BigDecimal(fontSize);
fontSizeBD = bd2.multiply(fontSizeBD);
fontSizeBD = fontSizeBD.setScale(0, BigDecimal.ROUND_HALF_UP);//这里取整
bFontSize = new BigInteger(fontSizeBD.toString());// 字体大小
}
// 设置单元格宽度
cell.setWidth(cellWidth);
//=====获取单元格
CTTc tc = cell.getCTTc();
//====tcPr开始====》》》》
CTTcPr tcPr = tc.getTcPr();//获取单元格里的<w:tcPr>
if (tcPr == null) {//没有<w:tcPr>,创建
tcPr = tc.addNewTcPr();
}
// --vjc开始-->>
CTVerticalJc vjc = tcPr.getVAlign();//获取<w:tcPr> 的<w:vAlign w:val="center"/>
if (vjc == null) {//没有<w:w:vAlign/>,创建
vjc = tcPr.addNewVAlign();
}
//设置单元格对齐方式
vjc.setVal(vertical.equals("top") ? STVerticalJc.TOP : vertical.equals("bottom") ? STVerticalJc.BOTTOM : STVerticalJc.CENTER); //垂直对齐
CTShd shd = tcPr.getShd();//获取<w:tcPr>里的<w:shd w:val="clear" w:color="auto" w:fill="C00000"/>
if (shd == null) {//没有<w:shd>,创建
shd = tcPr.addNewShd();
}
// 设置背景颜色
shd.setFill(bgColor.substring(1));
//《《《《====tcPr结束====
//====p开始====》》》》
CTP p = tc.getPList().get(0);//获取单元格里的<w:p w:rsidR="00C36068" w:rsidRPr="00B705A0" w:rsidRDefault="00C36068" w:rsidP="00C36068">
//---ppr开始--->>>
CTPPr ppr = p.getPPr();//获取<w:p>里的<w:pPr>
if (ppr == null) {//没有<w:pPr>,创建
ppr = p.addNewPPr();
}
// --jc开始-->>
CTJc jc = ppr.getJc();//获取<w:pPr>里的<w:jc w:val="left"/>
if (jc == null) {//没有<w:jc/>,创建
jc = ppr.addNewJc();
}
//设置单元格对齐方式
jc.setVal(alignment.equals("left") ? STJc.LEFT : alignment.equals("right") ? STJc.RIGHT : STJc.CENTER); //水平对齐
// <<--jc结束--
// --pRpr开始-->>
CTParaRPr pRpr = ppr.getRPr(); //获取<w:pPr>里的<w:rPr>
if (pRpr == null) {//没有<w:rPr>,创建
pRpr = ppr.addNewRPr();
}
CTFonts pfont = pRpr.getRFonts();//获取<w:rPr>里的<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体"/>
if (pfont == null) {//没有<w:rPr>,创建
pfont = pRpr.addNewRFonts();
}
//设置字体
pfont.setAscii(fontName);
pfont.setEastAsia(fontName);
pfont.setHAnsi(fontName);
CTOnOff pb = pRpr.getB();//获取<w:rPr>里的<w:b/>
if (pb == null) {//没有<w:b/>,创建
pb = pRpr.addNewB();
}
//设置字体是否加粗
pb.setVal(fontBlod == 1 ? STOnOff.ON : STOnOff.OFF);
CTHpsMeasure psz = pRpr.getSz();//获取<w:rPr>里的<w:sz w:val="32"/>
if (psz == null) {//没有<w:sz w:val="32"/>,创建
psz = pRpr.addNewSz();
}
// 设置单元格字体大小
psz.setVal(bFontSize);
CTHpsMeasure pszCs = pRpr.getSzCs();//获取<w:rPr>里的<w:szCs w:val="32"/>
if (pszCs == null) {//没有<w:szCs w:val="32"/>,创建
pszCs = pRpr.addNewSzCs();
}
// 设置单元格字体大小
pszCs.setVal(bFontSize);
// <<--pRpr结束--
//<<<---ppr结束---
//---r开始--->>>
List<CTR> rlist = p.getRList(); //获取<w:p>里的<w:r w:rsidRPr="00B705A0">
CTR r = null;
if (rlist != null && rlist.size() > 0) {//获取第一个<w:r>
r = rlist.get(0);
} else {//没有<w:r>,创建
r = p.addNewR();
}
//--rpr开始-->>
CTRPr rpr = r.getRPr();//获取<w:r w:rsidRPr="00B705A0">里的<w:rPr>
if (rpr == null) {//没有<w:rPr>,创建
rpr = r.addNewRPr();
}
//->-
CTFonts font = rpr.getRFonts();//获取<w:rPr>里的<w:rFonts w:ascii="宋体" w:eastAsia="宋体" w:hAnsi="宋体" w:hint="eastAsia"/>
if (font == null) {//没有<w:rFonts>,创建
font = rpr.addNewRFonts();
}
//设置字体
font.setAscii(fontName);
font.setEastAsia(fontName);
font.setHAnsi(fontName);
CTOnOff b = rpr.getB();//获取<w:rPr>里的<w:b/>
if (b == null) {//没有<w:b/>,创建
b = rpr.addNewB();
}
//设置字体是否加粗
b.setVal(fontBlod == 1 ? STOnOff.ON : STOnOff.OFF);
CTColor color = rpr.getColor();//获取<w:rPr>里的<w:color w:val="FFFFFF" w:themeColor="background1"/>
if (color == null) {//没有<w:color>,创建
color = rpr.addNewColor();
}
// 设置字体颜色
if (content.contains("↓")) {
color.setVal("43CD80");
} else if (content.contains("↑")) {
color.setVal("943634");
} else {
color.setVal(fontColor.substring(1));
}
CTHpsMeasure sz = rpr.getSz();
if (sz == null) {
sz = rpr.addNewSz();
}
sz.setVal(bFontSize);
CTHpsMeasure szCs = rpr.getSzCs();
if (szCs == null) {
szCs = rpr.addNewSz();
}
szCs.setVal(bFontSize);
//-<-
//<<--rpr结束--
List<CTText> tlist = r.getTList();
CTText t = null;
if (tlist != null && tlist.size() > 0) {//获取第一个<w:r>
t = tlist.get(0);
} else {//没有<w:r>,创建
t = r.addNewT();
}
t.setStringValue(content);
//<<<---r结束---
}
}
模板需要按照楼主的模板来做