当前位置: 首页 > article >正文

java根据模板导出word,并在word中插入echarts相关统计图片以及表格

  • 引入依赖
  • 创建word模板
    • 创建ftl模板文件
    • 保存的ftl可能会出现占位符分割的问题,需要处理
    • 将ftl文件中的图片的Base64删除,并使用占位符代替
    • 插入表格,并指定表格的位置在图片下方
  • Echarts转图片
  • 根据模板生成word文档
    • DocUtil
    • 导出word文档
  • 生成的word统计图片示例
  • 生成的word表格示例

java根据word模板生成对应的word文档,并且要在word文档中插入Echarts的一些统计图表,例如柱状图、折线图、柱状混合图等。思路是根据Echatrs的option生成json文件,然后通过命令行调用phantomjs执行echarts-convert的js脚本生成Echarts对应图表的图片,然后将图片转为Base64的字符串,替换word文档中的图片占位符,实现往word文档中插入统计图表的需求。同时也可以在word中插入表格

引入依赖

<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.11</version>
        </dependency>

        <dependency>
            <groupId>com.github.abel533</groupId>
            <artifactId>ECharts</artifactId>
            <version>2.2.7</version>
        </dependency>
        <!-- freemarker engine -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>

对应的phantomjs、echarts-convert和ECharts-2.2.7.jar下载地址:phantomjs

创建word模板

创建ftl模板文件

首先使用word创建一个doc文件,其中的主要字段全部用${param}占位符替换,示例如下:
在这里插入图片描述
然后将doc模板另存为xml在这里插入图片描述
重命名为ftl文件。

保存的ftl可能会出现占位符分割的问题,需要处理

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileAppender;
import cn.hutool.core.io.file.FileReader;
import java.util.List;
 
/**
 * 将分离的占位符去除、变量值重新拼装
 */
public class formatXml {
    public static void main(String[] args) {
            //文件读取-FileReader
            //默认UTF-8编码,可以在构造中传入第二个参数作为编码 原始ftl文件
            FileReader fileReader = new FileReader("C:\\Users\\Desktop\\jijiaritemp11.ftl");
            //从文件中读取每一行数据
            List<String> strings = fileReader.readLines();
            //文件追加-FileAppender
            //destFile – 目标文件
            //capacity – 当行数积累多少条时刷入到文件
            //isNewLineMode – 追加内容是否为新行
            FileAppender appender = new FileAppender(FileUtil.newFile("C:\\Users\\Desktop\\jiejiaritemp.ftl"), 16, true);
            //遍历得到每一行数据
            for (String string : strings) {
                //判断每一行数据中不包含'$'的数据先添加进新文件
                if (!string.contains("$")) {
                    appender.append(string);
                    continue;
                }
                //如果一行数据中包含'$'变量符将替换为'#$'
                string = string.replaceAll("\\$", "#\\$");
                //然后以'#'切割成每一行(数组),这样一来'$'都将在每一行的开头
                String[] ss = string.split("#");
                // 同一行的数据写到同一行,文件追加自动换行了(最后的完整数据)
                StringBuilder sb = new StringBuilder();
                //遍历每一行(数组ss)
                for (int i = 0; i < ss.length; i++) {
                    //暂存数据
                    String s1 = ss[i];
                    //将不是以'$'开头的行数据放进StringBuilder
                    if (!s1.startsWith("$")) {
                        sb.append(s1);
                        continue;
                    }
                    //被分离的数据一般都是'${'这样被分开
                    //匹配以'$'开头的变量找到'}' 得到索引位置
                    int i1 = s1.lastIndexOf("}");
                    //先切割得到这个完整体
                    String substr = s1.substring(0, i1 + 1);
                    //把变量追加到StringBuilder
                    sb.append(substr.replaceAll("<[^>]+>", ""));
                    //再将标签数据追加到StringBuilder包裹变量
                    sb.append(s1.substring(i1 + 1));
                }
                appender.append(sb.toString());
            }
            appender.flush();
            appender.toString();
 
    }
}

将ftl文件中的图片的Base64删除,并使用占位符代替

搜索<w:binData标签,删除Base64字符串,使用占位符代替
在这里插入图片描述
注意图片的宽高是模板文件中图片的宽高,如果不修改,最终生成的图片大小会与原始模板中的图片大小保持一致。
在这里插入图片描述

这样,word模板文件ftl就创建好了,只需组装数据即可。

插入表格,并指定表格的位置在图片下方

在这个示例中:
图片通过 <v:shape> 标签插入,其中包含一个 <v:imagedata> 子标签用于指定图片的来源。src=“wordml://03000001.png” 指定了图片的路径或关系 ID。
表格通过 <w:tbl> 标签插入,位于图片的 <w:p> 元素之后。
请注意,src=“wordml://03000001.png” 中的 wordml:// 前缀通常用于指向 Word 文档中嵌入的图片。如果你的图片是作为二进制数据嵌入到 Word 文档中的,你需要确保图片的关系 ID (rId) 与文档中的关系类型 ( 部分) 中定义的 ID 相匹配。
确保图片和表格的 XML 结构按照你希望的顺序排列,这样它们就会按照这个顺序显示在文档中。如果你使用 FreeMarker 或其他模板引擎生成 Word 文档,确保在模板中正确地插入这些标签,并根据需要调整图片和表格的位置。
表格分为表头和数据行,<#list ttFiveWNumList as item>中ttFiveWNumList 为数据集合。

<w:p wsp:rsidR="00CE037D" wsp:rsidRDefault="00CE037D" wsp:rsidP="005E50E9">
                <w:pPr>
                    <w:widowControl/>
					<!-- 居中 -->
                    <w:jc w:val="center"/>
                    <w:rPr>
                        <w:noProof/>
                    </w:rPr>
                </w:pPr>
                <w:r>
                    <w:rPr>
                        <w:rFonts w:ascii="仿宋_GB2312" w:fareast="仿宋_GB2312" w:h-ansi="仿宋_GB2312" w:cs="仿宋_GB2312" w:hint="fareast"/>
                        <wx:font wx:val="仿宋_GB2312"/>
                        <w:sz w:val="32"/>
                        <w:sz-cs w:val="32"/>
                    </w:rPr>
                    <w:t>${holidayName}假期前${num}天五环外公园数据</w:t>
                </w:r>
            </w:p>
            <w:tbl>
                <w:tblPr>
                    <w:tblStyle w:val="TableGrid"/>
					<!-- w:type="auto" 使表格宽度自适应内容 -->
                    <w:tblW w:type="auto"/>
					<!-- w:jc w:val="center" 设置表格居中显示 -->
                    <w:jc w:val="center"/>
                    <w:tblBorders>
                        <!-- 添加表格框线 设置上边框 -->
                        <w:top w:val="single" w:sz="4" w:space="0" w:color="auto"/>
                        <!-- 设置下边框 -->
                        <w:bottom w:val="single" w:sz="4" w:space="0" w:color="auto"/>
                        <!-- 设置左边框 -->
                        <w:left w:val="single" w:sz="4" w:space="0" w:color="auto"/>
                        <!-- 设置右边框 -->
                        <w:right w:val="single" w:sz="4" w:space="0" w:color="auto"/>
                        <!-- 设置内部水平边框 -->
                        <w:insideH w:val="single" w:sz="4" w:space="0" w:color="auto"/>
                        <!-- 设置内部垂直边框 -->
                        <w:insideV w:val="single" w:sz="4" w:space="0" w:color="auto"/>
                    </w:tblBorders>
                </w:tblPr>
                <w:tr>
                    <w:trPr>
                        <w:trHeight w:val="0" w:hRule="auto"/>
                    </w:trPr>
                    <w:tc>
                        <w:tcPr>
						<!-- w:tcW w:type="dxa" w:w="1500" 1500为表格初始列宽,可以调整-->
                            <w:tcW w:type="dxa" w:w="1500"/>
                        </w:tcPr>
                        <w:p>
                            <w:pPr>
                                <w:jc w:val="center"/>
                            </w:pPr>
                            <w:r>
                                <w:rPr>
                                    <w:rFonts w:ascii="仿宋_GB2312" w:fareast="仿宋_GB2312" w:h-ansi="仿宋_GB2312" w:cs="仿宋_GB2312" w:hint="fareast"/>
                                    <w:b w:val="true"/>
                                    <w:sz w:val="24"/>
                                    <w:sz-cs w:val="24"/>
                                </w:rPr>
                                <w:t>天数</w:t>
                            </w:r>
                        </w:p>
                    </w:tc>
                    <w:tc>
                        <w:tcPr>
                            <w:tcW w:type="dxa" w:w="4000"/>
                        </w:tcPr>
                        <w:p>
                            <w:pPr>
								<!-- 段落内文本居中显示 每一列都需要设置-->
                                <w:jc w:val="center"/>
                            </w:pPr>
                            <w:r>
                                <w:rPr>
									<!-- 设置字体样式,大小-->
                                    <w:rFonts w:ascii="仿宋_GB2312" w:fareast="仿宋_GB2312" w:h-ansi="仿宋_GB2312" w:cs="仿宋_GB2312" w:hint="fareast"/>
									<!-- w:b w:val="true"  字体加粗-->
                                    <w:b w:val="true"/>
                                    <w:sz w:val="24"/>
                                    <w:sz-cs w:val="24"/>
                                </w:rPr>
                                <w:t>${lastYear}年游客量(单位:人次)</w:t>
                            </w:r>
                        </w:p>
                    </w:tc>
                    <w:tc>
                        <w:tcPr>
                            <w:tcW w:type="dxa" w:w="4000"/>
                        </w:tcPr>
                        <w:p>
                            <w:pPr>
                                <w:jc w:val="center"/>
                            </w:pPr>
                            <w:r>
                                <w:rPr>
                                    <w:rFonts w:ascii="仿宋_GB2312" w:fareast="仿宋_GB2312" w:h-ansi="仿宋_GB2312" w:cs="仿宋_GB2312" w:hint="fareast"/>
                                    <w:b w:val="true"/>
                                    <w:sz w:val="24"/>
                                    <w:sz-cs w:val="24"/>
                                </w:rPr>
                                <w:t>${currentYear}年游客量(单位:人次)</w:t>
                            </w:r>
                        </w:p>
                    </w:tc>
                </w:tr>
                <#list ttFiveWNumList as item>
                    <w:tr>
                        <w:tc>
                            <w:p>
                                <w:pPr>
                                    <w:jc w:val="center"/>
                                </w:pPr>
                                <w:r>
                                    <w:rPr>
                                        <w:rFonts w:ascii="仿宋_GB2312" w:fareast="仿宋_GB2312" w:h-ansi="仿宋_GB2312" w:cs="仿宋_GB2312" w:hint="fareast"/>
                                        <w:sz w:val="20"/>
                                        <w:sz-cs w:val="20"/>
                                    </w:rPr>
                                    <w:t>${item.dayNumber}</w:t>
                                </w:r>
                            </w:p>
                        </w:tc>
                        <w:tc>
                            <w:p>
                                <w:pPr>
                                    <w:jc w:val="center"/>
                                </w:pPr>
                                <w:r>
                                    <w:rPr>
                                        <w:rFonts w:ascii="仿宋_GB2312" w:fareast="仿宋_GB2312" w:h-ansi="仿宋_GB2312" w:cs="仿宋_GB2312" w:hint="fareast"/>
                                        <w:sz w:val="20"/>
                                        <w:sz-cs w:val="20"/>
                                    </w:rPr>
                                    <w:t>${item.totalLastVisitorNumber}</w:t>
                                </w:r>
                            </w:p>
                        </w:tc>
                        <w:tc>
                            <w:p>
                                <w:pPr>
                                    <w:jc w:val="center"/>
                                </w:pPr>
                                <w:r>
                                    <w:rPr>
                                        <w:rFonts w:ascii="仿宋_GB2312" w:fareast="仿宋_GB2312" w:h-ansi="仿宋_GB2312" w:cs="仿宋_GB2312" w:hint="fareast"/>
                                        <w:sz w:val="20"/>
                                        <w:sz-cs w:val="20"/>
                                    </w:rPr>
                                    <w:t>${item.totalVisitorNumber}</w:t>
                                </w:r>
                            </w:p>
                        </w:tc>
                    </w:tr>
                </#list>
            </w:tbl>

Echarts转图片


import java.io.*;
import java.math.BigDecimal;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import com.github.abel533.echarts.axis.CategoryAxis;
import com.github.abel533.echarts.axis.ValueAxis;
import com.github.abel533.echarts.code.Magic;
import com.github.abel533.echarts.code.Tool;
import com.github.abel533.echarts.code.Trigger;
import com.github.abel533.echarts.feature.MagicType;
import com.github.abel533.echarts.json.GsonOption;
import com.github.abel533.echarts.series.Bar;
import com.github.abel533.echarts.series.Line;
import com.github.abel533.echarts.style.ItemStyle;
import com.github.abel533.echarts.style.itemstyle.Normal;
import com.google.gson.Gson;
import com.hollysmart.admin.modules.project.VO.BusParkVisitorsVO;
import com.hollysmart.admin.modules.project.entity.BusParkVisitors;


/**
 * eachrts后台出图
 * @author lxd
 *
 */
public class EchartsToPicUtil {

	// echarts包的路径  后面截图有说明
	private static final String JSpath = "D:\\work\\tourist\\phantomjs\\echarts-convert\\echarts-convert1.js";
	private static final String ImgPath = "D:\\tourist\\";

	
	public static void main(String[] args) {
		 String optiona = "{\"title\":{\"left\":\"center\",\"text\":\"草地植被演替评估\",\"padding\":30,\"textStyle\":{\"fontSize\":18,\"fontWeight\":\"bolder\",\"color\":\"#333\"},\"subtext\":\"2019-03-05 00:00:00-2020-03-04 00:00:00 全部\",\"subtextStyle\":{\"fontSize\":14,\"fontWeight\":\"bold\"}},\"legend\":{\"data\":[\"大柴旦\",\"都兰\",\"兴海\",\"河南\",\"刚察\",\"甘德\",\"杂多\",\"民和\",\"囊谦\",\"五道梁\",\"湟源\",\"久治\",\"同德\",\"湟中\",\"沙珠玉\",\"玉树\",\"乐都\",\"循化\",\"德令哈\",\"乌兰\",\"共和\",\"祁连\",\"治多\",\"贵德\",\"海晏\",\"沱沱河\",\"青海湖151\",\"门源\",\"化隆\",\"泽库\",\"同仁\",\"班玛\",\"格尔木\",\"野牛沟\",\"玛沁\",\"玛多\",\"贵南\",\"大通\",\"茫崖\",\"互助\",\"曲麻莱\",\"小灶火\",\"诺木洪\",\"清水河\",\"西宁\",\"尖扎\",\"冷湖\",\"托勒\",\"达日\",\"天峻\",\"茶卡\",\"平安\"],\"type\":\"scroll\",\"bottom\":10},\"toolbox\":{\"show\":true,\"orient\":\"vertical\",\"y\":\"45%\",\"x\":\"95%\",\"itemSize\":30},\"xAxis\":{\"name\":\"年份\",\"nameLocation\":\"middle\",\"nameTextStyle\":{\"fontSize\":16,\"padding\":15},\"type\":\"category\",\"data\":[\"2019\",\"2020\"],\"splitLine\":{\"show\":false},\"axisLabel\":{\"show\":true,\"textStyle\":{\"fontSize\":14}},\"axisLine\":{\"show\":true,\"onZero\":true,\"lineStyle\":{\"width\":2}},\"axisTick\":{\"show\":\"true\",\"lineStyle\":{\"color\":\"black\",\"width\":2,\"type\":\"solid\"}}},\"yAxis\":[{\"name\":\"结果\",\"nameLocation\":\"middle\",\"nameTextStyle\":{\"fontSize\":16,\"padding\":15},\"type\":\"value\",\"splitLine\":{\"show\":false},\"axisLabel\":{\"fontSize\":14},\"axisLine\":{\"show\":true,\"onZero\":true,\"lineStyle\":{\"width\":2}},\"axisTick\":{\"show\":\"true\",\"lineStyle\":{\"color\":\"black\",\"width\":2,\"type\":\"solid\"}}}],\"grid\":{\"top\":\"10%\",\"bottom\":\"15%\",\"left\":\"10%\",\"right\":\"10%\",\"borderColor\":\"black\",\"borderWidth\":1},\"tooltip\":{\"trigger\":\"axis\",\"axisPointer\":{\"type\":\"none\"}},\"series\":[{\"name\":\"大柴旦\",\"data\":[2306.4,0],\"type\":\"line\"},{\"name\":\"都兰\",\"data\":[2156.8,0],\"type\":\"line\"},{\"name\":\"兴海\",\"data\":[1713.7,0],\"type\":\"line\"},{\"name\":\"河南\",\"data\":[1435.3,0],\"type\":\"line\"},{\"name\":\"刚察\",\"data\":[1523,0],\"type\":\"line\"},{\"name\":\"甘德\",\"data\":[1131.1,0],\"type\":\"line\"},{\"name\":\"杂多\",\"data\":[1524.6,0],\"type\":\"line\"},{\"name\":\"民和\",\"data\":[3595.1,0],\"type\":\"line\"},{\"name\":\"囊谦\",\"data\":[2331.7,0],\"type\":\"line\"},{\"name\":\"五道梁\",\"data\":[599.6,0],\"type\":\"line\"},{\"name\":\"湟源\",\"data\":[2328,0],\"type\":\"line\"},{\"name\":\"久治\",\"data\":[1583.5,0],\"type\":\"line\"},{\"name\":\"同德\",\"data\":[1990.1,0],\"type\":\"line\"},{\"name\":\"湟中\",\"data\":[2384.8,0],\"type\":\"line\"},{\"name\":\"沙珠玉\",\"data\":[2119.9,0],\"type\":\"line\"},{\"name\":\"玉树\",\"data\":[1862.3,0],\"type\":\"line\"},{\"name\":\"乐都\",\"data\":[3312.2,0],\"type\":\"line\"},{\"name\":\"循化\",\"data\":[3727.7,0],\"type\":\"line\"},{\"name\":\"德令哈\",\"data\":[2522.5,0],\"type\":\"line\"},{\"name\":\"乌兰\",\"data\":[2402.6,0],\"type\":\"line\"},{\"name\":\"共和\",\"data\":[2461.3,0],\"type\":\"line\"},{\"name\":\"祁连\",\"data\":[1993.3,0],\"type\":\"line\"},{\"name\":\"治多\",\"data\":[1258.9,0],\"type\":\"line\"},{\"name\":\"贵德\",\"data\":[3421.9,0],\"type\":\"line\"},{\"name\":\"海晏\",\"data\":[1770.8,0],\"type\":\"line\"},{\"name\":\"沱沱河\",\"data\":[922.2,0],\"type\":\"line\"},{\"name\":\"青海湖151\",\"data\":[1822.5,0],\"type\":\"line\"},{\"name\":\"门源\",\"data\":[1903,0],\"type\":\"line\"},{\"name\":\"化隆\",\"data\":[2041.8,0],\"type\":\"line\"},{\"name\":\"泽库\",\"data\":[1227.2,0],\"type\":\"line\"},{\"name\":\"同仁\",\"data\":[2892.2,0],\"type\":\"line\"},{\"name\":\"班玛\",\"data\":[1921.5,0],\"type\":\"line\"},{\"name\":\"格尔木\",\"data\":[2918.8,0],\"type\":\"line\"},{\"name\":\"野牛沟\",\"data\":[1197.6,0],\"type\":\"line\"},{\"name\":\"玛沁\",\"data\":[1407,0],\"type\":\"line\"},{\"name\":\"玛多\",\"data\":[893.3,0],\"type\":\"line\"},{\"name\":\"贵南\",\"data\":[1954.2,0],\"type\":\"line\"},{\"name\":\"大通\",\"data\":[2451.6,0],\"type\":\"line\"},{\"name\":\"茫崖\",\"data\":[2480.6,0],\"type\":\"line\"},{\"name\":\"互助\",\"data\":[2454.6,0],\"type\":\"line\"},{\"name\":\"曲麻莱\",\"data\":[1131.7,0],\"type\":\"line\"},{\"name\":\"小灶火\",\"data\":[2666.8,0],\"type\":\"line\"},{\"name\":\"诺木洪\",\"data\":[2876.4,0],\"type\":\"line\"},{\"name\":\"清水河\",\"data\":[805.9,0],\"type\":\"line\"},{\"name\":\"西宁\",\"data\":[2767.6,0],\"type\":\"line\"},{\"name\":\"尖扎\",\"data\":[3422.2,0],\"type\":\"line\"},{\"name\":\"冷湖\",\"data\":[2497,0],\"type\":\"line\"},{\"name\":\"托勒\",\"data\":[1366.5,0],\"type\":\"line\"},{\"name\":\"达日\",\"data\":[1329,0],\"type\":\"line\"},{\"name\":\"天峻\",\"data\":[1400.1,0],\"type\":\"line\"},{\"name\":\"茶卡\",\"data\":[2120.6,0],\"type\":\"line\"},{\"name\":\"平安\",\"data\":[3214.8,0],\"type\":\"line\"}]}";
		 //前端传的option数据
		// generateEChart(optiona, "D:/",JSpath);
		//后台构造的柱状图数据
//		 generateEChart(testBar(true), "D:/",JSpath);
		//后台构造的折线图数据
		 generateEChart(testLine(true), ImgPath,JSpath);
	 }

	 public static String echartsToBase64(String type){
		 String optiona = "{\"title\":{\"left\":\"center\",\"text\":\"草地植被演替评估\",\"padding\":30,\"textStyle\":{\"fontSize\":18,\"fontWeight\":\"bolder\",\"color\":\"#333\"},\"subtext\":\"2019-03-05 00:00:00-2020-03-04 00:00:00 全部\",\"subtextStyle\":{\"fontSize\":14,\"fontWeight\":\"bold\"}},\"legend\":{\"data\":[\"大柴旦\",\"都兰\",\"兴海\",\"河南\",\"刚察\",\"甘德\",\"杂多\",\"民和\",\"囊谦\",\"五道梁\",\"湟源\",\"久治\",\"同德\",\"湟中\",\"沙珠玉\",\"玉树\",\"乐都\",\"循化\",\"德令哈\",\"乌兰\",\"共和\",\"祁连\",\"治多\",\"贵德\",\"海晏\",\"沱沱河\",\"青海湖151\",\"门源\",\"化隆\",\"泽库\",\"同仁\",\"班玛\",\"格尔木\",\"野牛沟\",\"玛沁\",\"玛多\",\"贵南\",\"大通\",\"茫崖\",\"互助\",\"曲麻莱\",\"小灶火\",\"诺木洪\",\"清水河\",\"西宁\",\"尖扎\",\"冷湖\",\"托勒\",\"达日\",\"天峻\",\"茶卡\",\"平安\"],\"type\":\"scroll\",\"bottom\":10},\"toolbox\":{\"show\":true,\"orient\":\"vertical\",\"y\":\"45%\",\"x\":\"95%\",\"itemSize\":30},\"xAxis\":{\"name\":\"年份\",\"nameLocation\":\"middle\",\"nameTextStyle\":{\"fontSize\":16,\"padding\":15},\"type\":\"category\",\"data\":[\"2019\",\"2020\"],\"splitLine\":{\"show\":false},\"axisLabel\":{\"show\":true,\"textStyle\":{\"fontSize\":14}},\"axisLine\":{\"show\":true,\"onZero\":true,\"lineStyle\":{\"width\":2}},\"axisTick\":{\"show\":\"true\",\"lineStyle\":{\"color\":\"black\",\"width\":2,\"type\":\"solid\"}}},\"yAxis\":[{\"name\":\"结果\",\"nameLocation\":\"middle\",\"nameTextStyle\":{\"fontSize\":16,\"padding\":15},\"type\":\"value\",\"splitLine\":{\"show\":false},\"axisLabel\":{\"fontSize\":14},\"axisLine\":{\"show\":true,\"onZero\":true,\"lineStyle\":{\"width\":2}},\"axisTick\":{\"show\":\"true\",\"lineStyle\":{\"color\":\"black\",\"width\":2,\"type\":\"solid\"}}}],\"grid\":{\"top\":\"10%\",\"bottom\":\"15%\",\"left\":\"10%\",\"right\":\"10%\",\"borderColor\":\"black\",\"borderWidth\":1},\"tooltip\":{\"trigger\":\"axis\",\"axisPointer\":{\"type\":\"none\"}},\"series\":[{\"name\":\"大柴旦\",\"data\":[2306.4,0],\"type\":\"line\"},{\"name\":\"都兰\",\"data\":[2156.8,0],\"type\":\"line\"},{\"name\":\"兴海\",\"data\":[1713.7,0],\"type\":\"line\"},{\"name\":\"河南\",\"data\":[1435.3,0],\"type\":\"line\"},{\"name\":\"刚察\",\"data\":[1523,0],\"type\":\"line\"},{\"name\":\"甘德\",\"data\":[1131.1,0],\"type\":\"line\"},{\"name\":\"杂多\",\"data\":[1524.6,0],\"type\":\"line\"},{\"name\":\"民和\",\"data\":[3595.1,0],\"type\":\"line\"},{\"name\":\"囊谦\",\"data\":[2331.7,0],\"type\":\"line\"},{\"name\":\"五道梁\",\"data\":[599.6,0],\"type\":\"line\"},{\"name\":\"湟源\",\"data\":[2328,0],\"type\":\"line\"},{\"name\":\"久治\",\"data\":[1583.5,0],\"type\":\"line\"},{\"name\":\"同德\",\"data\":[1990.1,0],\"type\":\"line\"},{\"name\":\"湟中\",\"data\":[2384.8,0],\"type\":\"line\"},{\"name\":\"沙珠玉\",\"data\":[2119.9,0],\"type\":\"line\"},{\"name\":\"玉树\",\"data\":[1862.3,0],\"type\":\"line\"},{\"name\":\"乐都\",\"data\":[3312.2,0],\"type\":\"line\"},{\"name\":\"循化\",\"data\":[3727.7,0],\"type\":\"line\"},{\"name\":\"德令哈\",\"data\":[2522.5,0],\"type\":\"line\"},{\"name\":\"乌兰\",\"data\":[2402.6,0],\"type\":\"line\"},{\"name\":\"共和\",\"data\":[2461.3,0],\"type\":\"line\"},{\"name\":\"祁连\",\"data\":[1993.3,0],\"type\":\"line\"},{\"name\":\"治多\",\"data\":[1258.9,0],\"type\":\"line\"},{\"name\":\"贵德\",\"data\":[3421.9,0],\"type\":\"line\"},{\"name\":\"海晏\",\"data\":[1770.8,0],\"type\":\"line\"},{\"name\":\"沱沱河\",\"data\":[922.2,0],\"type\":\"line\"},{\"name\":\"青海湖151\",\"data\":[1822.5,0],\"type\":\"line\"},{\"name\":\"门源\",\"data\":[1903,0],\"type\":\"line\"},{\"name\":\"化隆\",\"data\":[2041.8,0],\"type\":\"line\"},{\"name\":\"泽库\",\"data\":[1227.2,0],\"type\":\"line\"},{\"name\":\"同仁\",\"data\":[2892.2,0],\"type\":\"line\"},{\"name\":\"班玛\",\"data\":[1921.5,0],\"type\":\"line\"},{\"name\":\"格尔木\",\"data\":[2918.8,0],\"type\":\"line\"},{\"name\":\"野牛沟\",\"data\":[1197.6,0],\"type\":\"line\"},{\"name\":\"玛沁\",\"data\":[1407,0],\"type\":\"line\"},{\"name\":\"玛多\",\"data\":[893.3,0],\"type\":\"line\"},{\"name\":\"贵南\",\"data\":[1954.2,0],\"type\":\"line\"},{\"name\":\"大通\",\"data\":[2451.6,0],\"type\":\"line\"},{\"name\":\"茫崖\",\"data\":[2480.6,0],\"type\":\"line\"},{\"name\":\"互助\",\"data\":[2454.6,0],\"type\":\"line\"},{\"name\":\"曲麻莱\",\"data\":[1131.7,0],\"type\":\"line\"},{\"name\":\"小灶火\",\"data\":[2666.8,0],\"type\":\"line\"},{\"name\":\"诺木洪\",\"data\":[2876.4,0],\"type\":\"line\"},{\"name\":\"清水河\",\"data\":[805.9,0],\"type\":\"line\"},{\"name\":\"西宁\",\"data\":[2767.6,0],\"type\":\"line\"},{\"name\":\"尖扎\",\"data\":[3422.2,0],\"type\":\"line\"},{\"name\":\"冷湖\",\"data\":[2497,0],\"type\":\"line\"},{\"name\":\"托勒\",\"data\":[1366.5,0],\"type\":\"line\"},{\"name\":\"达日\",\"data\":[1329,0],\"type\":\"line\"},{\"name\":\"天峻\",\"data\":[1400.1,0],\"type\":\"line\"},{\"name\":\"茶卡\",\"data\":[2120.6,0],\"type\":\"line\"},{\"name\":\"平安\",\"data\":[3214.8,0],\"type\":\"line\"}]}";
		 //前端传的option数据
		 // generateEChart(optiona, "D:/",JSpath);
		switch (type) {
			case "1":
				optiona = "{\n" +
						"  title: {\n" +
						"    text: '假期第2天全市公园游客量、收入额对比图',\n" +
						"    left: 'center' // 水平居中\n" +
						"  },\n" +
						"  tooltip: {\n" +
						"    trigger: 'axis'\n" +
						"  },\n" +
						"  legend: {\n" +
						"    data: ['游客量(万人)', '收入额(万元)'],\n" +
						"    top: '5%'\n" +
						"  },\n" +
						"  toolbox: {\n" +
						"    show: true,\n" +
						"    feature: {\n" +
						"      dataView: { show: true, readOnly: false },\n" +
						"      magicType: { show: true, type: ['line', 'bar'] },\n" +
						"      restore: { show: true },\n" +
						"      saveAsImage: { show: true }\n" +
						"    }\n" +
						"  },\n" +
						"  calculable: true,\n" +
						"  xAxis: [\n" +
						"    {\n" +
						"      type: 'category',\n" +
						"      // prettier-ignore\n" +
						"      data: ['2024年', '2025年']\n" +
						"    }\n" +
						"  ],\n" +
						"  yAxis: [\n" +
						"    {\n" +
						"      type: 'value'\n" +
						"    }\n" +
						"  ],\n" +
						"  series: [\n" +
						"    {\n" +
						"      name: '游客量(万人)',\n" +
						"      type: 'bar',\n" +
						"      data: [\n" +
						"        169.90, 159.29\n" +
						"      ],\n" +
						"      markPoint: {\n" +
						"        data: [\n" +
						"          { type: 'max', name: 'Max' },\n" +
						"          { type: 'min', name: 'Min' }\n" +
						"        ]\n" +
						"      }\n" +
						"    },\n" +
						"    {\n" +
						"      name: '收入额(万元)',\n" +
						"      type: 'bar',\n" +
						"      data: [\n" +
						"        2622.30, 2012.14\n" +
						"      ],\n" +
						"      markPoint: {\n" +
						"        data: [\n" +
						"          { type: 'max', name: 'Max' },\n" +
						"          { type: 'min', name: 'Min' }\n" +
						"        ]\n" +
						"      }\n" +
						"    }\n" +
						"  ]\n" +
						"}";
				return generateEChart(testBar(true), ImgPath,JSpath);
			case "2":
				return generateEChart(testLine(true), ImgPath,JSpath);
			case "3":
				return generateEChart(optiona, ImgPath,JSpath);
			default:
				return generateEChart(testBar(true), ImgPath,JSpath);
		}
	 }

	public static String generateFive(String num,String currentYear,String lastYear,List<BusParkVisitorsVO> visitors) {
		String optiona = "{\n" +
				"  title: {\n" +
				"    text: '假期前"+ num +"天全市五环外公园游客量对比图', // 设置标题文本\n" +
				"    left: 'center', // 水平居中\n" +
				"    top: 'top', // 可以根据需要调整标题的垂直位置,'top' 表示顶部\n" +
				"  },\n" +
				"  tooltip: {\n" +
				"    trigger: 'axis',\n" +
				"    axisPointer: {\n" +
				"      type: 'cross',\n" +
				"      crossStyle: {\n" +
				"        color: '#999'\n" +
				"      }\n" +
				"    }\n" +
				"  },\n" +
				"  toolbox: {\n" +
				"    feature: {\n" +
				"      dataView: { show: true, readOnly: false },\n" +
				"      magicType: { show: true, type: ['line', 'bar'] },\n" +
				"      restore: { show: true },\n" +
				"      saveAsImage: { show: true }\n" +
				"    }\n" +
				"  },\n" +
				"  legend: {\n" +
				"    data: ['"+lastYear+"年五环外公园游客量', '"+currentYear+"年五环外公园游客量', '日环比','同比'],\n" +
				"    top: '4%'\n" +
				"  },\n" +
				"  grid: {\n" +
				"    left: '7%',\n" +
				"    right: '2%',\n" +
				"    bottom: '2%',\n" +
				"    top: '15%',\n" +
				"    containLabel: true\n" +
				"  },\n" +
				"  xAxis: [\n" +
				"    {\n" +
				"      type: 'category',\n" +
				"      data: ["+visitors.stream().map(o -> "'" + o.getDayNumber() + "'").collect(Collectors.joining(","))+"],\n" +
				"      axisPointer: {\n" +
				"        type: 'shadow'\n" +
				"      }\n" +
				"    }\n" +
				"  ],\n" +
				"  yAxis: [\n" +
				"    {\n" +
				"      type: 'value',\n" +
				"      name: '五环外公园游客量(万人)',\n" +
				"      interval: 50,\n" +
				"      axisLabel: {\n" +
				"        formatter: '{value} '\n" +
				"      }\n" +
				"    },\n" +
				"    {\n" +
				"      type: 'value',\n" +
				"      name: '日环比(%)',\n" +
				"      interval: 10,\n" +
				"      axisLabel: {\n" +
				"        formatter: '{value} '\n" +
				"      }\n" +
				"    }\n" +
				"  ],\n" +
				"  series: [\n" +
				"    {\n" +
				"      name: '"+lastYear+"年五环外公园游客量',\n" +
				"      type: 'bar',\n" +
				"      tooltip: {\n" +
				"        valueFormatter: function (value) {\n" +
				"          return value + ' 游客量(万人)';\n" +
				"        }\n" +
				"      },\n" +
				"      data: ["+visitors.stream().map(o -> "'" + (o.getTotalLastVisitorNum()) + "'").collect(Collectors.joining(","))+"],\n" +
				"		itemStyle: {\n" +
				"        color: '#4E68B8' // 指定柱状图颜色\n" +
				"      },\n"+
				"      label: {\n" +
				"        show: true, // 显示标签\n" +
				"        position: 'top' // 标签位置在柱状图的顶部\n" +
				"        // formatter: '{value} 万人次' // 格式化标签内容\n" +
				"      }\n" +
				"    },\n" +
				"    {\n" +
				"      name: '"+currentYear+"年五环外公园游客量',\n" +
				"      type: 'bar',\n" +
				"      tooltip: {\n" +
				"        valueFormatter: function (value) {\n" +
				"          return value + ' 游客量(万人)';\n" +
				"        }\n" +
				"      },\n" +
				"      data: ["+visitors.stream().map(o -> "'" + o.getTotalVisitorNum() + "'").collect(Collectors.joining(","))+"],\n" +
				"		itemStyle: {\n" +
				"        color: '#91CC75' // 指定柱状图颜色\n" +
				"      },\n"+
				"      label: {\n" +
				"        show: true, // 显示标签\n" +
				"        position: 'top' // 标签位置在柱状图的顶部\n" +
				"        // formatter: '{value} 万人次' // 格式化标签内容\n" +
				"      }\n" +
				"    },\n" +
				"    {\n" +
				"      name: '日环比',\n" +
				"      type: 'line',\n" +
				"      yAxisIndex: 1,\n" +
				"      tooltip: {\n" +
				"        valueFormatter: function (value) {\n" +
				"          return value + ' %';\n" +
				"        }\n" +
				"      },\n" +
				"      data: ["+visitors.stream().map(o -> "'" + o.getChain() + "'").collect(Collectors.joining(","))+"],\n" +
				"		itemStyle: {\n" +
				"        color: '#D6C029' // 指定柱状图颜色\n" +
				"      },\n"+
				"      label: {\n" +
				"        show: true, // 显示标签\n" +
				"        position: 'top' // 标签位置在柱状图的顶部\n" +
				"        // formatter: '{value} 万人次' // 格式化标签内容\n" +
				"      }\n" +
				"    },\n" +
				"    {\n" +
				"      name: '同比',\n" +
				"      type: 'line',\n" +
				"      yAxisIndex: 1,\n" +
				"      tooltip: {\n" +
				"        valueFormatter: function (value) {\n" +
				"          return value + ' %';\n" +
				"        }\n" +
				"      },\n" +
				"      data: ["+visitors.stream().map(o -> "'" + o.getYearOnYear() + "'").collect(Collectors.joining(","))+"],\n" +
				"		itemStyle: {\n" +
				"        color: '#F81D43' // 指定柱状图颜色\n" +
				"      },\n"+
				"      label: {\n" +
				"        show: true, // 显示标签\n" +
				"        position: 'top' // 标签位置在柱状图的顶部\n" +
				"        // formatter: '{value} 万人次' // 格式化标签内容\n" +
				"      }\n" +
				"    }\n" +
				"  ]\n" +
				"}";
		return  generateEChart(optiona, ImgPath,JSpath);
	}
	
	public static String generateEChart(String options, String tmpPath,String echartJsPath) {
		String dataPath = writeFile(options,tmpPath);
		String fileName =  UUID.randomUUID().toString().substring(0, 8) + ".png";
		String path = tmpPath + fileName;
		String base64Str = "";
		try {
			File file = new File(path); // 文件路径(路径+文件名)
			if (!file.exists()) { // 文件不存在则创建文件,先创建目录
				File dir = new File(file.getParent());
				dir.mkdirs();
				file.createNewFile();
			}

			String cmd = "D:\\work\\tourist\\phantomjs\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe  " + echartJsPath + " -infile " + dataPath
					+ " -outfile " + path;
			// 使用
//			Process process = Runtime.getRuntime().exec(cmd);
			// 创建 ProcessBuilder 对象
			ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", cmd);
			builder.redirectErrorStream(true); // 将错误输出重定向到标准输出
			// 启动进程
			Process process = builder.start();
			BufferedReader input = new BufferedReader(new InputStreamReader(
					process.getInputStream()));
			String line = "";
			while ((line = input.readLine()) != null) {
				System.out.println(line);
			}
			input.close();
			base64Str = encodeFileToBase64Binary(path);
			File jsonFile=new File(path);
			if(jsonFile.exists()){
				jsonFile.delete();
			}
			File jsFile=new File(dataPath);
			if(jsFile.exists()){
				jsFile.delete();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			return base64Str;
		}
	}

	public static String writeFile(String options,String tmpPath) {
		String dataPath = tmpPath
				+ UUID.randomUUID().toString().substring(0, 8) + ".json";
		try {
			/* 写入Txt文件 使用UFT-8编码*/
			String encoding = "UTF-8";
			File writename = new File(dataPath); // 相对路径,如果没有则要建立一个新的output.txt文件
			if (!writename.exists()) { // 文件不存在则创建文件,先创建目录
				File dir = new File(writename.getParent());
				dir.mkdirs();
				writename.createNewFile(); // 创建新文件
			}
			FileOutputStream fos = new FileOutputStream(writename);
			OutputStreamWriter osw = new OutputStreamWriter(fos, encoding);
			osw.write(options);
			osw.flush();
			osw.close();
//			BufferedWriter out = new BufferedWriter(new FileWriter(writename));
//			out.write(options); // \r\n即为换行
//			out.flush(); // 把缓存区内容压入文件
//			out.close(); // 最后记得关闭文件
		} catch (IOException e) {
			e.printStackTrace();
		}
		return dataPath;
	}

	/**
	 * 折线图
	 * 
	 * @param isHorizontal
	 *            是否水平放置
	 */
	public static String testLine(boolean isHorizontal) {
		String[] types = { "邮件营销", "联盟广告", "视频广告" };
		int[][] datas = { { 120, 132, 101, 134, 90, 230, 210 },
				{ 220, 182, 191, 234, 290, 330, 310 },
				{ 150, 232, 201, 154, 190, 330, 410 } };
		String title = "广告数据";

		GsonOption option = new GsonOption();

		option.title().text(title).subtext("虚构").x("left");// 大标题、小标题、位置

		// 提示工具
		option.tooltip().trigger(Trigger.axis);// 在轴上触发提示数据
		// 工具栏
		option.toolbox().show(true).feature(Tool.saveAsImage);// 显示保存为图片

		option.legend(types);// 图例

		CategoryAxis category = new CategoryAxis();// 轴分类
		category.data("周一", "周二", "周三", "周四", "周五", "周六", "周日");
		category.boundaryGap(false);// 起始和结束两端空白策略

		// 循环数据
		for (int i = 0; i < types.length; i++) {
			Line line = new Line();// 三条线,三个对象
			String type = types[i];
			line.name(type).stack("总量");
			for (int j = 0; j < datas[i].length; j++)
				line.data(datas[i][j]);
			option.series(line);
		}

		if (isHorizontal) {// 横轴为类别、纵轴为值
			option.xAxis(category);// x轴
			option.yAxis(new ValueAxis());// y轴
		} else {// 横轴为值、纵轴为类别
			option.xAxis(new ValueAxis());// x轴
			option.yAxis(category);// y轴
		}

		return new Gson().toJson(option);
	}

	/**
	 * 柱状图
	 * 
	 * @param isHorizontal
	 *            是否水平放置
	 */
	public static String testBar(boolean isHorizontal) {
		String[] citis = { "广州", "深圳", "珠海", "汕头", "韶关", "佛山" };
		int[] datas = { 6030, 7800, 5200, 3444, 2666, 5708 };
		String[] colors = { "rgb(2,111,230)", "rgb(186,73,46)",
				"rgb(78,154,97)", "rgb(2,111,230)", "rgb(186,73,46)",
				"rgb(78,154,97)" };
		String title = "地市数据";

		GsonOption option = new GsonOption();

		option.title(title); // 标题
		// 工具栏
		option.toolbox().show(true).feature(Tool.mark, // 辅助线
				Tool.dataView, // 数据视图
				new MagicType(Magic.line, Magic.bar),// 线图、柱状图切换
				Tool.restore,// 还原
				Tool.saveAsImage);// 保存为图片

		option.tooltip().show(true).formatter("{a} <br/>{b} : {c}");// 显示工具提示,设置提示格式

		option.legend(title);// 图例

		Bar bar = new Bar(title);// 图类别(柱状图)
		CategoryAxis category = new CategoryAxis();// 轴分类
		category.data(citis);// 轴数据类别
		// 循环数据
		for (int i = 0; i < citis.length; i++) {
			int data = datas[i];
			String color = colors[i];
			// 类目对应的柱状图
			HashMap<String, Object> map = new HashMap<String, Object>(2);
			map.put("value", data);
			map.put("itemStyle",
					new ItemStyle().normal(new Normal().color(color)));
			bar.data(map);
		}

		if (isHorizontal) {// 横轴为类别、纵轴为值
			option.xAxis(category);// x轴
			option.yAxis(new ValueAxis());// y轴
		} else {// 横轴为值、纵轴为类别
			option.xAxis(new ValueAxis());// x轴
			option.yAxis(category);// y轴
		}

		option.series(bar);
		return new Gson().toJson(option);
	}

	public static String encodeFileToBase64Binary(String fileName) throws IOException {
		File file = new File(fileName);
		FileInputStream fileInputStreamReader = new FileInputStream(file);
		byte[] bytes = new byte[(int) file.length()];
		fileInputStreamReader.read(bytes);

		// 使用 Base64 编码器将字节数组编码为 Base64 字符串
		String encodedfile = Base64.getEncoder().encodeToString(bytes);
		fileInputStreamReader.close();
//		System.out.println("base64Image:" + encodedfile);
		return encodedfile;
	}

	public static String formatNum(Long num) {
		// 格式化数字,以万为单位,保留两位小数
		String formatNumStr = String.format("%.2f", num / 10000.0);
		return formatNumStr;
	}

	public static String formatNum(BigDecimal num) {
		// 格式化数字,以万为单位,保留两位小数
		String formatNumStr = String.format("%.2f", num.doubleValue() / 10000.0);
		return formatNumStr;
	}

}


这里需要替换JSpath为echarts-convert1.js的路径、phantomjs.exe的路径。
对于echarts的optiona,可以先在 echarts官网上找到对应的统计图表,然后调整好样式后复制到代码中,主要参数需要替换为真实数据。

根据模板生成word文档

DocUtil

import freemarker.template.*;

import java.io.*;
import java.util.*;


public class DocUtil {
    public Configuration configure=null;

    public DocUtil(){
        configure=new Configuration(Configuration.VERSION_2_3_22);
        configure.setDefaultEncoding("utf-8");
    }
    /**
     * 根据Doc模板生成word文件
     * @param dataMap 需要填入模板的数据
     * @param downloadType 文件名称
     * @param savePath 保存路径
     */
    public void createDoc(Map<String,Object> dataMap, String downloadType, String savePath){
        try {
            //加载需要装填的模板
            Template template=null;

            //设置模板装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载。
            //加载模板文件
            Configuration configuration = new Configuration();
            configuration.setDirectoryForTemplateLoading(FileUtils.getClassPathTemplatesFile("/excels/"));
            configuration.setObjectWrapper(new DefaultObjectWrapper());
            configuration.setDefaultEncoding("UTF-8"); //这个一定要设置,不然在生成的页面中 会乱码

//            configure.setClassForTemplateLoading(this.getClass(), "/excels/");
            //设置对象包装器
//            configure.setObjectWrapper(new DefaultObjectWrapper());
            //设置异常处理器
            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
            //定义Template对象,注意模板类型名字与downloadType要一致
//            template = configuration.getTemplate("/"+downloadType+".ftl");
            try {
                template = configuration.getTemplate("/"+downloadType+".ftl");
            } catch (IOException e) {
                throw new RuntimeException("模板文件不存在: " + downloadType + ".ftl", e);
            }
            File outFile=new File(savePath);
            // 文件已存在,删除原文件
            if(outFile.exists()){
                outFile.delete();
            }
            Writer out=null;
            out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
            template.process(dataMap, out);
            out.close();
        } catch (IOException  e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
    }

    public String getImageStr(String imgFile){
        InputStream in=null;
        byte[] data=null;
        try {
            in=new FileInputStream(imgFile);
            data=new byte[in.available()];
            in.read(data);
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
//        BASE64Encoder encoder=new BASE64Encoder();
//        return encoder.encode(data);
        String encodedString = Base64.getEncoder().encodeToString(data);
        return encodedString;
    }
}

导出word文档

/**
     * 导出统计word报告
     * @param firstDate 
     * @param LastFirstDate 
     * @return
     */
    @RequestMapping(value = "exportWord1", method = RequestMethod.GET)
    public ResponseResult exportWord1(@RequestParam("firstDate") String firstDate,@RequestParam("LastFirstDate") String LastFirstDate){
        DocUtil docUtil=new DocUtil();
        Map<String, Object> dataMap=new HashMap<String, Object>();
        String WordTemplate = "";
        try{
            WordTemplate = "jiejiaritemp";
            // 格式化今天的日期为MM月dd日
            LocalDate localDate = LocalDate.now();
            String currentDate = localDate.toString();
            String[] currentDateArr = currentDate.split("-");
            String currentDateStr = currentDateArr[1] + "月" + currentDateArr[2] + "日";
            String currentDateStr1 = currentDateArr[0] + "-" + currentDateArr[1] + "-" + currentDateArr[2];
            // 计算firstDate与currentDate的差值
            int days = DateUtils.daysBetween(DateUtils.parseDate(firstDate), DateUtils.parseDate(currentDate));
            int days1 = days + 1;
            // 循环生成每一天的数据
            dataMap.put("currentDate", currentDateStr);
            dataMap.put("holidayName", "春节");
            dataMap.put("num", days1);
            // 组装数据

            List<BusParkVisitorsVO> list3 = busParkVisitorsService.selectFiveTourists(firstDate,currentDateStr1,null,"五环外");
            List<BusParkVisitorsVO> list4 = busParkVisitorsService.selectFiveTourists(LastFirstDate,lastDate,null,"五环外");
            // 将list3转为map,key为dayNumber,value为VisitorsListVO
            Map<Integer, List<BusParkVisitorsVO>> map3 = list3.stream().collect(Collectors.groupingBy(BusParkVisitorsVO::getSort));
            Map<Integer, List<BusParkVisitorsVO>> map4 = list4.stream().collect(Collectors.groupingBy(BusParkVisitorsVO::getSort));
            List<BusParkVisitorsVO> list5 = new ArrayList<>();
            // 计算同比与日环比
            for (Integer sort : map3.keySet()) {
                List<BusParkVisitorsVO> visitorsListVOList3 = map3.get(sort);
                List<BusParkVisitorsVO> visitorsListVOList4 = map4.get(sort);
                BusParkVisitorsVO busParkVisitorsVO = visitorsListVOList3.get(0);
                if (visitorsListVOList3.size() == 0 || visitorsListVOList4.size() == 0) {
                    continue;
                }
                double dayNumberPc = calculatePercentageChange((long) visitorsListVOList3.get(0).getFdVisitorNumber(), (long) visitorsListVOList4.get(0).getFdVisitorNumber());
                double dayNumberR;
                if(sort==1){
                    dayNumberR = 0;
                }else{
                    dayNumberR = calculatePercentageChange((long) visitorsListVOList3.get(0).getFdVisitorNumber(), (long) map3.get(sort-1).get(0).getFdVisitorNumber());
                }
                busParkVisitorsVO.setTotalVisitorNum(formatNum((long) visitorsListVOList3.get(0).getFdVisitorNumber()));
                busParkVisitorsVO.setTotalLastVisitorNum(formatNum((long) visitorsListVOList4.get(0).getFdVisitorNumber()));
                busParkVisitorsVO.setYearOnYear(dayNumberPc);
                busParkVisitorsVO.setChain(dayNumberR);
                list5.add(busParkVisitorsVO);
            }
            String pic5Base64Img = EchartsToPicUtil.generateFive(String.valueOf(days1),currentDateArr[0],lastDate.split("-")[0],list5);
            dataMap.put("pic5", pic5Base64Img);
            dataMap.put("currentDateTime", currentDateArr[0] + "年" +currentDateArr[1] + "月" + currentDateArr[2] + "日");
            String savedDir = System.getProperty("resources"); //获取服务器指定文件存取路径
            String dir = savedDir + "/touristStatistics/";
            File file2 = new File(dir);    //创建文件夹 如果不存在
            if (!file2.exists()) {
                file2.mkdirs();
            }
            String fileName = currentDateArr[0] + "年" +currentDateArr[1] + "月" + currentDateArr[2] + "日" + "全市游人量统计报告.doc";
            docUtil.createDoc(dataMap, WordTemplate,  dir+"/"+fileName);
            fileName = "/touristStatistics/" + fileName;
            return ResponseResult.ok(fileName);
        }catch (Exception ex){
            ex.printStackTrace();
            return ResponseResult.build(500,"生成word失敗,"+ex.toString());
        }
    }

在这里插入图片描述

生成的word统计图片示例

在这里插入图片描述

生成的word表格示例

在这里插入图片描述


http://www.kler.cn/a/509235.html

相关文章:

  • Redis可视化工具--RedisDesktopManager的安装
  • springboot基于微信小程序的传统美食文化宣传平台小程序
  • 代码随想录算法训练营第三十五天-动态规划-01背包(二维)
  • Nginx三种不同类型的虚拟主机(基于域名、IP 和端口)
  • ComfyUI-PromptOptimizer:文生图提示优化节点
  • PCL 新增自定义点类型【2025最新版】
  • 爱德华EDWARDS EPX180EPX500 Vacuum Pumps instruction Manual
  • 基于 Java Spring Boot 开发的项目复盘与技术总结
  • Spring Boot应用关闭分析
  • Linux中的nc命令是网络工具中的一种,用于进行网络连接和数据传输。下面是nc命令的使用方法和实例:
  • 2.使用Spring BootSpring AI快速构建AI应用程序
  • PHP企业IM客服系统
  • 鸿蒙学习构建视图的基本语法(二)
  • Jenkins下载安装
  • 利用 LNMP 实现 WordPress 站点搭建
  • qt自定义加载字体库ttf
  • Android 项目依赖冲突问题:Duplicate class found in modules
  • 阿里云 Serverless 助力盟主直播:高并发下的稳定性和成本优化
  • 窥探QCC518x/308x系列与手机之间的蓝牙HCI记录与分析 - 手机篇
  • 深度学习原理与Pytorch实战
  • 2025最新版IntelliJ IDEA for Mac安装使用指南
  • YOLOv10改进,YOLOv10检测头融合RFAConv卷积,添加小目标检测层(四头检测)+CA注意机制,全网首发
  • docker 部署confluence
  • 使用 Ansys Motor-CAD 的自适应模板加速创新
  • 慧集通(DataLinkX)iPaaS集成平台-系统管理之用户及权限
  • Red Hat8:搭建DHCP服务器