leftso 215 0 2019-05-21 13:37:54

java通过freemarker导出word循环合并表格单元格


本文主要讲解通过freemarker模板引擎来导出word,并且在word中包含表格的合并部分需要循环生成。

一、Java需要通过模板导出的word
图一
如上图所示。物品的信息是循环部分。但是前面的表格是合并固定的。接下来我们将通过freemarker模板的方式来导出上述格式

二、创建freemarker模板

2.1首先将word的源文件另存为xml格式文件,如下
图2,Word存为xml

用文本工具打开xml文件。notepad++ 或者sublimetext都可以
图3
打开后如上图,看起来很乱。这时候需要进行xml格式化。欢迎使用本站xml格式化工具

格式化以后如下:
图4
格式化以后就好看多了。
首先我们需要去找到我们需要循环的表格
图5
物品信息就是我们要循环的开始部分。

在这之前需要科普下word的xml是如何实现单元格合并的

主要就是
<w:vMerge w:val="restart"/>
<w:vMerge/>
两个标签的组合。
首先了解下word的表格标签
<w:tr w:rsidR="00770B3E" w:rsidTr="00AB3846">
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                  <w:vMerge w:val="restart"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRPr="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                  <w:pPr>
                    <w:jc w:val="center"/>
                    <w:rPr>
                      <w:b/>
                    </w:rPr>
                  </w:pPr>
                  <w:r w:rsidRPr="00770B3E">
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                      <w:b/>
                    </w:rPr>
                    <w:t>物品信息</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>物品名称</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>刀</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>物品数量</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1660" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>2</w:t>
                  </w:r>
                </w:p>
              </w:tc>
            </w:tr>
上面是合并单元格的首行,所以你可以找到<w:vMerge w:val="restart"/>标签

标签说明:
<w:tr></w:tr>  ---行标签
<w:tc></w:tc>  ---单元格标签

我们继续看下面的一行xml
第二行表格xml:
<w:tr w:rsidR="00770B3E" w:rsidTr="00CC5D94">
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                  <w:vMerge/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333"/>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>物品说明</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="4978" w:type="dxa"/>
                  <w:gridSpan w:val="3"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:proofErr w:type="gramStart"/>
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>刀非常</w:t>
                  </w:r>
                  <w:proofErr w:type="gramEnd"/>
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>锋利</w:t>
                  </w:r>
                </w:p>
              </w:tc>
            </w:tr>
继续第三行:
            <w:tr w:rsidR="00770B3E" w:rsidTr="00AB3846">
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                  <w:vMerge/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333"/>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>上架时间</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>2</w:t>
                  </w:r>
                  <w:r>
                    <w:t>019</w:t>
                  </w:r>
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>-</w:t>
                  </w:r>
                  <w:r>
                    <w:t>08</w:t>
                  </w:r>
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>-</w:t>
                  </w:r>
                  <w:r>
                    <w:t>09</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>上架人</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1660" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>小左</w:t>
                  </w:r>
                </w:p>
              </w:tc>
            </w:tr>

从第二行,第三行可以找到<w:vMerge/>标签,标识这这列产生了合并
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                  <w:vMerge/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333"/>
              </w:tc>
并且<w:vMerge/>就在第一个单元格内。

那么模板就好改了。思路:
首先循环判断是否第一条数据
第一条数据那么就使用行1的格式。后面的都使用合并后的格式

提取需要做模板的几行进行组建,通过上面我们可以知道,其实我们就是要循环以下三行表格:
            <w:tr w:rsidR="00770B3E" w:rsidTr="00AB3846">
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                  <w:vMerge w:val="restart"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRPr="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                  <w:pPr>
                    <w:jc w:val="center"/>
                    <w:rPr>
                      <w:b/>
                    </w:rPr>
                  </w:pPr>
                  <w:r w:rsidRPr="00770B3E">
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                      <w:b/>
                    </w:rPr>
                    <w:t>物品信息</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>物品名称</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>刀</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>物品数量</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1660" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>2</w:t>
                  </w:r>
                </w:p>
              </w:tc>
            </w:tr>
            <w:tr w:rsidR="00770B3E" w:rsidTr="00CC5D94">
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                  <w:vMerge/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333"/>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>物品说明</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="4978" w:type="dxa"/>
                  <w:gridSpan w:val="3"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:proofErr w:type="gramStart"/>
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>刀非常</w:t>
                  </w:r>
                  <w:proofErr w:type="gramEnd"/>
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>锋利</w:t>
                  </w:r>
                </w:p>
              </w:tc>
            </w:tr>
            <w:tr w:rsidR="00770B3E" w:rsidTr="00AB3846">
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                  <w:vMerge/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333"/>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>上架时间</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>2</w:t>
                  </w:r>
                  <w:r>
                    <w:t>019</w:t>
                  </w:r>
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>-</w:t>
                  </w:r>
                  <w:r>
                    <w:t>08</w:t>
                  </w:r>
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>-</w:t>
                  </w:r>
                  <w:r>
                    <w:t>09</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1659" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>上架人</w:t>
                  </w:r>
                </w:p>
              </w:tc>
              <w:tc>
                <w:tcPr>
                  <w:tcW w:w="1660" w:type="dxa"/>
                </w:tcPr>
                <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                  <w:r>
                    <w:rPr>
                      <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t>小左</w:t>
                  </w:r>
                </w:p>
              </w:tc>
接下来就针对这部分进行模板标签的编写
说明:Java代码后面给出,现在说明的是集合的key为 goodsList(物品集合)

循环片段代码格式缩进后如图
图6
上图其实就是判断了是否第一条记录,第一条记录和后面记录的区别就是第一行的第一个单元格,第一条记录的第一个单元格是写的”物品信息“后面的记录第一个单元格都是合并单元格的cell代码。

以下为循环片段代码:
          <#list goodsList! as goods>
            <#if goods_index == 0 >
              <w:tr w:rsidR="00770B3E" w:rsidTr="00AB3846">
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                    <w:vMerge w:val="restart"/>
                    <w:vAlign w:val="center"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRPr="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:pPr>
                      <w:jc w:val="center"/>
                      <w:rPr>
                        <w:b/>
                      </w:rPr>
                    </w:pPr>
                    <w:r w:rsidRPr="00770B3E">
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                        <w:b/>
                      </w:rPr>
                      <w:t>物品信息</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>物品名称</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.name}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>物品数量</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1660" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.number}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
              </w:tr>
              <w:tr w:rsidR="00770B3E" w:rsidTr="00CC5D94">
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                    <w:vMerge/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333"/>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>物品说明</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="4978" w:type="dxa"/>
                    <w:gridSpan w:val="3"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.description}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
              </w:tr>
              <w:tr w:rsidR="00770B3E" w:rsidTr="00AB3846">
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                    <w:vMerge/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333"/>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>上架时间</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.time}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>上架人</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1660" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="003A3333">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.user}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
              </w:tr>
            <#else>
              <w:tr w:rsidR="00770B3E" w:rsidTr="00AB3846">
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                    <w:vMerge/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E"/>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>物品名称</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.name}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>物品数量</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1660" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.number}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
              </w:tr>
              <w:tr w:rsidR="00770B3E" w:rsidTr="00644BE9">
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                    <w:vMerge/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E"/>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>物品说明</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="4978" w:type="dxa"/>
                    <w:gridSpan w:val="3"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.description}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
              </w:tr>
              <w:tr w:rsidR="00770B3E" w:rsidTr="00AB3846">
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                    <w:vMerge/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E"/>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>上架时间</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.time}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1659" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>上架人</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
                <w:tc>
                  <w:tcPr>
                    <w:tcW w:w="1660" w:type="dxa"/>
                  </w:tcPr>
                  <w:p w:rsidR="00770B3E" w:rsidRDefault="00770B3E" w:rsidP="00770B3E">
                    <w:r>
                      <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                      </w:rPr>
                      <w:t>${goods.user}</w:t>
                    </w:r>
                  </w:p>
                </w:tc>
              </w:tr>
            </#if>
          </#list>
将上面代码放入demo.xml文件中替换掉原来的两个假数据行。替换后如下:(由于数据多,这里就截图展示)
图7

将上诉的demo.xml保存并改为demo.ftl即完成freemarker的模板。
提示:这里说下为啥要if else ,因为第一次生成的行需要展示合并的单元格,后面的整个数据都是一个合并标签。当然简单化也可以在第一行的第一个单元格做if else不需要像我这样整个循环体做if else

三、编写freemarker模板导出复杂格式word代码

首先把上面制作的demo.ftl放入Java项目的classpath目录下

Java数据模型Goods
$title(Goods.java)
package demo;

public class Goods {
    public Goods(String name, Integer number, String description, String time, String user) {
        this.name = name;
        this.number = number;
        this.description = description;
        this.time = time;
        this.user = user;
    }

    String name;
    Integer number;
    String description;
    String time;
    String user;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getNumber() {
        return number;
    }

    public void setNumber(Integer number) {
        this.number = number;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }
}


导出代码:
$title(ComplexWordExport.java)
package demo;

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

public class ComplexWordExport {

    public static void main(String[] args) {
        try {
            // 创建模拟数据
            List<Goods> goodsList = new ArrayList<>();
            for (int i = 0; i < 4; i++) {
                goodsList.add(new Goods("刀" + i, i + 2, "到很好不错,数量多+" + i,
                        new SimpleDateFormat("HH:mm:ss:SSS").format(new Date()), "用户" + i));
            }
            Map<String ,Object> dataMap=new HashMap<>();
            dataMap.put("goodsList",goodsList);//注意这里的key与目标中的数据对应
            File wordFile = new File("d:/demo.doc");// 注意这里只能输出doc,不能直接输出docx


            Configuration configuration = new Configuration();
            configuration.setDefaultEncoding("UTF-8");
            configuration.setClassForTemplateLoading(WordTest.class, "/");
            // 模板来源
            // 1.创建一个word文件可以是doc或者docx的
            // 2.在需要使用变量的地方用占位符占位
            // 3.将word文档另存为xml文件
            // 4.打开xml文件将里面的占位符替换为freemarker的表达式
            // 5.重命名xml为ftl
            // 6.完成
            Template template = configuration.getTemplate("demo/demo.ftl", "UTF-8");//路径相对于项目的classpath

            try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(wordFile),"UTF-8"))) {
                template.process(dataMap, out);
                out.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

四、导出结果

Word导出结果


注意:导出文件必须是.doc因为docx会验证xml里面的一些数据导致文件打不开。

提示:项目源码下载