一、背景
工作内容需要生成大量数据(含图片)、格式自定义的 Excel,网络上没有找到对应的解决方案,试着自己摸索了下。好在有一个基本的解决思路了。
10w 条数据,图片大约 2G,测试下来生成时间不到 2 分钟。
二、基本概念
1、excel 本质上是一个压缩包,右键打开压缩包可查看其对应结构。如下:
2、excel 另存为 xml ,表示用 xml 来描述该表格,但仅能保存文本类型的数据,图片类的资源会丢失。
xml 能够描述一类数据结构的组织关系。对于文本类型的数据,只需在 xml 标签里面直接填入文字即可,而对于图片或是其它资源,xml 无法直接表示,但可以与具体类型的文档约定转换规则。如:work 在另存为 xml 时,图片会直接转换成 base64,存放在标签里,打开时,可直接解析为图片。
excel 本质上是一种压缩包,图片是直接以文件的方式存放在压缩包的 root\xl\media\ 目录下,在另存为 xml 时,仅将文字描述信息保存,图片直接丢失了。这时不禁产生了一个思考,有没有什么办法可以将这种转换关系表达出来?
三、操作步骤
操作步骤分为大体分为三步:
1、将编辑好的模板转存为 xml 文件,其中,图片格式调整为嵌入式图片;此时,打开xml文件发现,原来图片所在单元格内出现了一个如下字符:
<Row ss:Height="31.35">
<Cell ss:Formula="=DISPIMG("ID_44FBDDF08CF34A229F9C95EDAB8D6D4E",1)">
<Data ss:Type="String">=DISPIMG("ID_44FBDDF08CF34A229F9C95EDAB8D6D4E",1)</Data>
</Cell>
</Row>
DISPIMG 是 excel 内置函数,表示在单元格内插入图片
2、将步骤 1 中的 xml 另存为 ftl,通过 freemarker 生成一份包含数据的 xml,其中,图片部分按照上述格式填入图片的标识
3、将步骤 2 中生成的 xml 转存为 xlsx (java)
4、将以下 4 个配置文件分别生成拷贝到 excel 压缩包对应目录中
(1)[Content_Types].xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="jpeg"
ContentType="image/jpeg"/>
<Default Extension="JPG"
ContentType="image/.jpg"/>
<Default Extension="rels"
ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml"
ContentType="application/xml"/>
<Override PartName="/docProps/app.xml"
ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
<Override PartName="/docProps/core.xml"
ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
<Override PartName="/docProps/custom.xml"
ContentType="application/vnd.openxmlformats-officedocument.custom-properties+xml"/>
<Override PartName="/xl/cellimages.xml"
ContentType="application/vnd.wps-officedocument.cellimage+xml"/>
<Override PartName="/xl/sharedStrings.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
<Override PartName="/xl/styles.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
<Override PartName="/xl/theme/theme1.xml"
ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
<Override PartName="/xl/workbook.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
<Override PartName="/xl/worksheets/sheet1.xml"
ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
</Types>
(2)cellimages.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<etc:cellImages xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:etc="http://www.wps.cn/officeDocument/2017/etCustomData">
<etc:cellImage>
<xdr:pic>
<xdr:nvPicPr>
<xdr:cNvPr id="3"
name="ID_F15EB208E8164494AD0AFF387A896542"
descr="D:\tmp\003833-1649695113a4a0.jpg003833-1649695113a4a0"/>
<xdr:cNvPicPr>
<a:picLocks noChangeAspect="1"/>
</xdr:cNvPicPr>
</xdr:nvPicPr>
<xdr:blipFill>
<a:blip r:embed="rId1"/>
<a:srcRect/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</xdr:blipFill>
<xdr:spPr>
<a:xfrm>
<a:off x="9671050"
y="2582545"/>
<a:ext cx="1203960"
cy="686435"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
</xdr:spPr>
</xdr:pic>
</etc:cellImage>
</etc:cellImages>
(3)cellimages.xml.rels
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
Target="media/image1.jpeg"/>
</Relationships>
(4)workbook.xml.rels
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId5"
Type="http://www.wps.cn/officeDocument/2020/cellImage"
Target="cellimages.xml"/>
<Relationship Id="rId4"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"
Target="sharedStrings.xml"/>
<Relationship Id="rId3"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"
Target="styles.xml"/>
<Relationship Id="rId2"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
Target="theme/theme1.xml"/>
<Relationship Id="rId1"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
Target="worksheets/sheet1.xml"/>
</Relationships>
上面的 4 个配置文件描述了资源的对应关系
时间有限,后续会继续补充!!!