本文是通過一步步的還原事件的發(fā)生并解決的一個(gè)過程記錄驻呐,如果想知道如何解決的可以直接跳轉(zhuǎn)文章末尾結(jié)論部分
提示一下打洼,關(guān)注一下
Table
標(biāo)簽中的ss:ExpandedRowCount
屬性
解決的問題
在項(xiàng)目中使用freemarker的xml模板導(dǎo)出xls格式的Excel文件時(shí),使用國產(chǎn)Office工具可以打開查看蛉威,使用Excel打開提示文件已損壞
關(guān)鍵詞
國產(chǎn)office,Excel,freemarker
環(huán)境信息
- Windows 11
- office 2019
- 永中office2022體驗(yàn)版
- JDK8
- springboot 2.6.13
- freemarker 2.6.13
事件還原
1妻怎、首先使用Excel創(chuàng)建一個(gè)空白excel文件,輸入我們要導(dǎo)出的表格模板泞歉,如下圖所示逼侦,我們創(chuàng)建一個(gè)表格,表格中導(dǎo)出姓名腰耙、年齡榛丢、電話、住址等信息的這樣一個(gè)表格挺庞,并且添加了一行示例數(shù)據(jù)
2晰赞、點(diǎn)擊另存為,選中xml格式導(dǎo)出
3选侨、打開xml文件掖鱼,修改添加數(shù)據(jù)的地方,使用freemarker語法遍歷輸出數(shù)據(jù)
修改前如下圖所示
修改后如下圖所示
其中的#list
為固定語法援制,resultList
為獲取輸入模板數(shù)據(jù)的key戏挡,該值是一個(gè)List,as item
是List*中的每一個(gè)對象以item
來遍歷
item.name
為獲取姓名隘谣,item.age
為獲取年齡增拥,item.phont
為獲取電話啄巧,item.address
為獲取住址
${item.name!''}
的完整意思就是輸出用戶名,為空時(shí)輸出為空
4掌栅、創(chuàng)建springboot
程序秩仆,并在resources
下創(chuàng)建freemarker
目錄,繼續(xù)創(chuàng)建test.xml
模板文件猾封,test.xml
文件內(nèi)容就是上一步我們修改完成之后的xml
文件澄耍,結(jié)構(gòu)如下
文件內(nèi)容如下(本內(nèi)容為Excel打開異常的,如需正常的晌缘,需跳轉(zhuǎn)文章末尾)
提示一下齐莲,關(guān)注一下
Table
標(biāo)簽中的ss:ExpandedRowCount
屬性
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>zuiyu</Author>
<LastAuthor>zuiyu</LastAuthor>
<Created>2023-07-26T02:16:31Z</Created>
<LastSaved>2023-07-26T02:18:00Z</LastSaved>
<Version>16.00</Version>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>5880</WindowHeight>
<WindowWidth>14400</WindowWidth>
<WindowTopX>32767</WindowTopX>
<WindowTopY>32767</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Center"/>
<Borders/>
<Font ss:FontName="等線" x:CharSet="134" ss:Size="11" ss:Color="#000000"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
</Styles>
<Worksheet ss:Name="Sheet1">
<Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="2" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="51" ss:DefaultRowHeight="13.875">
<Row>
<Cell><Data ss:Type="String">姓名</Data></Cell>
<Cell><Data ss:Type="String">年齡</Data></Cell>
<Cell><Data ss:Type="String">電話</Data></Cell>
<Cell><Data ss:Type="String">住址</Data></Cell>
</Row>
<#list resultList as item>
<Row>
<Cell><Data ss:Type="String">${item.name!''}</Data></Cell>
<Cell><Data ss:Type="Number">${item.age!''}</Data></Cell>
<Cell><Data ss:Type="Number">${item.phone!''}</Data></Cell>
<Cell><Data ss:Type="String">${item.address!''}</Data></Cell>
</Row>
</#list>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<Selected/>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>4</ActiveRow>
<ActiveCol>5</ActiveCol>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</Workbook>
5、編寫導(dǎo)出excel文件的代碼磷箕,都是測試數(shù)據(jù)选酗,看看就好,只是舉個(gè)例子
需要關(guān)注的點(diǎn)是岳枷,我們此處導(dǎo)出的用戶數(shù)據(jù)為100芒填,而上文中提示需要關(guān)注的參數(shù)
ss:ExpandedRowCount
參數(shù)值為2
,這就是后文要探討的關(guān)鍵所在
package com.example.exceldemo.demos.excel;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URLEncoder;
import java.util.*;
/**
* @Author zuiyu
* @Date 2023/7/26 10:26
*/
@RestController
@RequestMapping("/excel")
public class ExcelController {
@GetMapping("/export")
public void export(HttpServletResponse response) throws IOException, TemplateException {
Configuration configuration = new Configuration(Configuration.VERSION_2_3_26);
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(getClass(),"/freemarker");
Template template = configuration.getTemplate("test.xml");
List<Person> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
Person person1 = new Person();
person1.setName("測試用戶名:"+i);
person1.setAge((i+1)*2);
person1.setPhone(new Random().nextInt(100));
person1.setAddress("地址:"+i);
list.add(person1);
}
Map<String,Object> map = new HashMap<>();
map.put("resultList",list);
ServletOutputStream outputStream = response.getOutputStream();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("測試xml導(dǎo)出excel.xls", "UTF-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
template.process(map,bw);
bw.flush();
bw.close();
System.out.println("導(dǎo)出成功");
}
}
6空繁、下面執(zhí)行接口http://localhost:8080/excel/export
導(dǎo)出xls文件進(jìn)行查看文件內(nèi)容殿衰,我們的預(yù)期就是國產(chǎn)Office可以打開觀看,而Excel打開時(shí)提示文件已損壞盛泡。打開結(jié)果就不進(jìn)行展示了闷祥,感興趣的可以使用上面的代碼進(jìn)行一下測試
7、下面我們修改ss:ExpandedRowCount="2"
為ss:ExpandedRowCount="9999"
傲诵,這樣就可以容納我們的100條記錄凯砍。此時(shí)重啟程序進(jìn)行導(dǎo)出我們就可以發(fā)現(xiàn)不管是使用Excel查看還是國產(chǎn)Office查看都可以進(jìn)行正常的顯示了
8、下面是修改之后的完整的xml文件內(nèi)容
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>zuiyu</Author>
<LastAuthor>zuiyu</LastAuthor>
<Created>2023-07-26T02:16:31Z</Created>
<LastSaved>2023-07-26T02:18:00Z</LastSaved>
<Version>16.00</Version>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>5880</WindowHeight>
<WindowWidth>14400</WindowWidth>
<WindowTopX>32767</WindowTopX>
<WindowTopY>32767</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Center"/>
<Borders/>
<Font ss:FontName="等線" x:CharSet="134" ss:Size="11" ss:Color="#000000"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
</Styles>
<Worksheet ss:Name="Sheet1">
<Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="9999" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="51" ss:DefaultRowHeight="13.875">
<Row>
<Cell><Data ss:Type="String">姓名</Data></Cell>
<Cell><Data ss:Type="String">年齡</Data></Cell>
<Cell><Data ss:Type="String">電話</Data></Cell>
<Cell><Data ss:Type="String">住址</Data></Cell>
</Row>
<#list resultList as item>
<Row>
<Cell><Data ss:Type="String">${item.name!''}</Data></Cell>
<Cell><Data ss:Type="Number">${item.age!''}</Data></Cell>
<Cell><Data ss:Type="Number">${item.phone!''}</Data></Cell>
<Cell><Data ss:Type="String">${item.address!''}</Data></Cell>
</Row>
</#list>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<Selected/>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>4</ActiveRow>
<ActiveCol>5</ActiveCol>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</Workbook>
總結(jié)
通過這次實(shí)驗(yàn)可以得知掰吕,文件的打開失敗的根本原因就是數(shù)據(jù)行超過了設(shè)置的ExpandedRowCount
屬性值果覆。而我們要做的就是修改該值到能容納我們要導(dǎo)出的數(shù)據(jù)即可。甚至是可以改為變量讀取數(shù)據(jù)長度是否可行 殖熟。
如果感覺有用的話歡迎點(diǎn)贊局待、收藏、轉(zhuǎn)發(fā)菱属,號(hào)《醉魚Java》