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

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

引入依赖

xml 复制代码
<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可能会出现占位符分割的问题,需要处理

java 复制代码
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 为数据集合。

xml 复制代码
<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转图片

java 复制代码
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

java 复制代码
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文档

java 复制代码
/**
     * 导出统计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表格示例

相关推荐
细心的莽夫7 分钟前
SpringMVC复习笔记
java·spring boot·笔记·学习·spring
新知图书15 分钟前
Spring MVC数据绑定POJO类型
java·spring·mvc
青木川崎34 分钟前
java集合面试题
java·windows·面试
工业甲酰苯胺1 小时前
.NET8.0多线程编码结合异步编码示例
java·算法·.net
Java知识日历1 小时前
Springboot集成Easy Rules引擎,实现一个商品优惠券系统
java·spring boot·后端·spring
Java知识日历2 小时前
SpringBoot整合Grizzly,提高您网站的并发能力
java·spring boot·后端·spring
Allen Bright2 小时前
【JVM-7】JVM 命令行工具 jstack 的使用和具体应用案例
java·开发语言·jvm
东北赵四2 小时前
JVM之垃圾回收器ZGC概述以及垃圾回收器总结的详细解析
java·jvm·算法
Allen Bright2 小时前
【JVM-5】深入解析JVM垃圾回收器:分类与原理
java·jvm
阿七想学习2 小时前
数据结构《Map&Set&哈希表》
java·数据结构·算法