springboot使用freemarker进行复杂Excel导出(多sheet页)
下面是Excel部门sheet展示
上图中的配置率,挂职及培养锻炼后配置率,借用后配置率会根据规则进行表格颜色的填充
freemarker常用标签及语法了解
内容来自:freemarker常见语法大全
FTL模板编写
先在Excel中编写所需的设置和样式等等,如果有多个sheet页一次性编写完即可,然后点击文件–另存为(格式选择为XML)
上面表格中${xxx.xxx}是在生成Excel时取数据时的格式,数据要是前准备好了就可以直接写上去(在FTL文件中改比较麻烦…),然后在ftl文件中根据freemarker语法进行取值就可以了
另存为XML
代码示例
- 引入依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
- 修改配置文件
spring:
freemarker:
template-loader-path: classpath:/template
suffix: .ftl
- 将上述另存的xml文件保存在项目当中,记得后缀改为 .ftl。这里的文件路径要和配置中所写的保持一致
Freemarker工具类
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URLEncoder;
import java.util.Map;
public class FreeMarkerUtil {
/**
* @title: ExportExcel
* @description: 导出excel
* @author:
* @date: 2023/4/24
* @param: fileName
* @param: templateName
* @param: data
* @return: void
*/
public static void ExportExcel(String fileName, String templateName, Map<String,Object> data) throws IOException {
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
response.reset();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
OutputStreamWriter writer = null;
try {
Template template = FreeMarkerUtil.getTemplate(templateName);
writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
template.process(data, writer);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
writer.close();
}
}
}
private static Template getTemplate(String templateName) throws IOException {
Configuration configuration = new Configuration(Configuration.VERSION_2_3_26);
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(FreeMarkerUtil.class,"/template");
return configuration.getTemplate(templateName);
}
}
导出调用–具体的方法跟自己的情况来定
/**
*
* @param excelParamVO 这个参数用于判断是否需要导出相关的sheet以级对表格中表头是否展示进行控住
*/
public void exportExcel(ComplexExcelParamVO excelParamVO){
Map<String, Object> excelMap = new HashMap<>();
excelMap.put("excelParam",excelParamVO);
if (excelParamVO.isStatisticSheet()){
/*编制报表*/
Map<String, Object> map = queryStatisticSheet(excelParamVO.isStaffCell(),excelParamVO.isExpertCell());
excelMap.putAll(map);
}
if (excelParamVO.isStaffInfoSheet()){
/*员工*/
Map<String, Object> map = queryStaffInfoSheet();
excelMap.putAll(map);
}
if (excelParamVO.isThirdLevelStaffSheet()){
/*一二三级员工*/
}
if (excelParamVO.isOwnerDeptInfoSheet()){
/*本部及本部花名册*/
}
if (excelParamVO.isFiveLevelStaffSheet()){
/*四五级职员*/
}
if (excelParamVO.isSpecificRetireSheet()){
/*专责退休*/
}
if (excelParamVO.isHangAndFosterSheet()){
/*挂职和培养锻炼*/
}
if (excelParamVO.isBorrowStaffSheet()){
/*借用人员名册*/
}
try {
FreeMarkerUtil.ExportExcel("test","allData.ftl",excelMap);
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* 编制报表数据
* */
public Map<String, Object> queryStatisticSheet(boolean staffCell,boolean expertCell){
Map<String, Object> excelData = new HashMap<>();
Map<String, Object> unitConfigList = getUnitConfigList(new EmpBasicVo());
List<PrepareStatementVo> unitList = (List<PrepareStatementVo>) unitConfigList.get("unitList");
List<PrepareStatementVo> deptList = (List<PrepareStatementVo>) unitConfigList.get("deptList");
for (PrepareStatementVo prepareStatementVo : unitList) {
String id = prepareStatementVo.getId();
for (PrepareStatementVo statementVo : deptList) {
String pid = statementVo.getPid();
if (StringUtils.equals(id,pid)){
prepareStatementVo.getChildren().add(statementVo);
}
}
}
PrepareStatementVo totalcontData = (PrepareStatementVo) unitConfigList.get("totalcontData");
excelData.put("dataList",unitList);
excelData.put("totalcontData",totalcontData);
excelData.put("staff",staffCell);
excelData.put("expert",expertCell);
return excelData;
}
/*
* 员工数据组装
* */
public Map<String,Object> queryStaffInfoSheet(){
Map<String,Object> resultMap = new HashMap<>();
/*查询员工信息根据处室分组,人员信息必须带有岗位信息*/
List<StaffInfoSheetVo> staffInfoSheetVos = empBasicMapper.queryStaffInfoSheet();
Map<String, List<StaffInfoSheetVo>> collect = staffInfoSheetVos.stream().collect(Collectors.groupingBy(StaffInfoSheetVo::getDeptId));
Map<String, Object> map = queryStatisticSheet(false, false);
List<PrepareStatementVo> unitList = (List<PrepareStatementVo>) map.get("dataList");
for (PrepareStatementVo prepareStatementVo : unitList) {
String unitId = prepareStatementVo.getId();
List<StaffInfoSheetVo> unitStaffInfo = collect.get(unitId);
prepareStatementVo.setStaffList(unitStaffInfo);
List<PrepareStatementVo> children = prepareStatementVo.getChildren();
for (PrepareStatementVo child : children) {
/*部门id*/
String id = child.getId();
List<StaffInfoSheetVo> deptStaffInfo = collect.get(id);
if (isNotEmpty(deptStaffInfo)){
Map<String, List<StaffInfoSheetVo>> collect1 = deptStaffInfo.stream().collect(Collectors.groupingBy(StaffInfoSheetVo::getDeptId));
}
child.setStaffList(deptStaffInfo);
}
}
resultMap.put("staffInfoSheet",unitList);
return resultMap;
}
以下是一些相关的实体类 代码中未引入lombok 使用的是get和set方法此处进行了省略
import com.bms.project.govern.vo.excelVo.StaffInfoSheetVo;
import java.util.ArrayList;
import java.util.List;
/**
* 编制报表数据VO
*/
public class PrepareStatementVo {
/*部门id*/
private String id;
/*部门父id*/
private String pid;
/*部门名称*/
private String name;
/*公司简称-部门简称*/
private String deptName;
/*编制*/
private Integer count2;
/*实配*/
private Integer count3;
/*专责*/
private Integer count4;
/*一二三级职员*/
private Integer count5;
/*四级职员*/
private Integer count6;
/*五级职员*/
private Integer count7;
/*挂职和培养锻炼*/
private Integer count8;
/*借用*/
private Integer count9;
/*超缺*/
private Integer count10;
/*配置率颜色*/
private String rateColor;
/*挂职及培养锻炼后配置率颜色*/
private String hangrateColor;
/*借用后配置率颜色*/
private String borrowrateColor;
/*配置率*/
private String rate;
/*挂职及培养锻炼配置率*/
private String hangrate;
/*借用配置率*/
private String borrowrate;
private List<PrepareStatementVo> children = new ArrayList<>();
private List<StaffInfoSheetVo> staffList;
}
前端请求参数实体类(前端的实现是一个多选框,下面实体类中的staffCell和expertCell用于控制statisticSheet编制报表sheet中相关表头的动态显示)。字段值为TRUE则是需要导出的sheet页
/*
* 总表自定义导出请求参数VO
* */
public class ComplexExcelParamVO {
/*
* 编制报表sheet
* */
private boolean statisticSheet;
/*
* 四五级职员表格
* */
private boolean staffCell;
/*
* 四五级专家表格
* */
private boolean expertCell;
/*
* 员工sheet
* */
private boolean staffInfoSheet;
/*
* 一二三级员工
* */
private boolean thirdLevelStaffSheet;
/*
* 本部及本部花名册
* */
private boolean ownerDeptInfoSheet;
/*
* 四五级职员
* */
private boolean fiveLevelStaffSheet;
/*
* 专责退休
* */
private boolean specificRetireSheet;
/*
* 挂职和培养锻炼
* */
private boolean hangAndFosterSheet;
/*
* 借用人员名册
* */
private boolean borrowStaffSheet;
}
FTL文件部分展示
部门标签说明
<#--
ss:MergeDown="1" 向下合并一行
ss:MergeAcross="5" 向右合并5行 包括本单元格一共是6个单元格进行合并的
-->
<#if officeInfo.type?? && officeInfo.type == '1'>
<#-- officeInfo.type不为空且等于1 -->
<Data ss:Type="String"></Data>
<#else>
<#-- 否则 -->
<Data ss:Type="String">${officeInfo.officeName}</Data>
</#if>
<#-- 此处为判断是否需要次sheet文件 -->
<#if excelParam.thirdLevelStaffSheet >
<Worksheet ss:Name="sheetName" .....>
</#if>
<#-- 下面的<#if staff >为判断是否需要展示这些表头 -->
<#-- ss:StyleID="s208" 为对应的样式id -->
<Row ss:Height="24">
<#if staff >
<Cell ss:Index="13" ss:StyleID="s208">
<Data ss:Type="String">四级职员编制</Data>
</Cell>
<Cell ss:StyleID="s208">
<Data ss:Type="String">四级职员实配</Data>
</Cell>
<Cell ss:StyleID="s209">
<Data ss:Type="String">四级职员配置率</Data>
</Cell>
<Cell ss:StyleID="s209">
<Data ss:Type="String">五级职员编制</Data>
</Cell>
<Cell ss:StyleID="s209">
<Data ss:Type="String">五级职员实配</Data>
</Cell>
<Cell ss:StyleID="s211">
<Data ss:Type="String">五级职员配置率</Data>
</Cell>
</#if>
<#if expert >
<Cell ss:Index="20" ss:StyleID="s208">
<Data ss:Type="String">四级专家编制</Data>
</Cell>
<Cell ss:StyleID="s208">
<Data ss:Type="String">四级专家实配</Data>
</Cell>
<Cell ss:StyleID="s209">
<Data ss:Type="String">四级专家配置率</Data>
</Cell>
<Cell ss:StyleID="s209">
<Data ss:Type="String">五级专家编制</Data>
</Cell>
<Cell ss:StyleID="s209">
<Data ss:Type="String">五级专家实配</Data>
</Cell>
<Cell ss:StyleID="s211">
<Data ss:Type="String">五级专家配置率</Data>
</Cell>
</#if>
</Row>
循环赋值
<#-- dataList 就是调用工具类是传递的map中的key -->
<#-- <Cell ss:StyleID="${item.id}+'rate'"> 这样写是为了给单元格填充背景色 -->
<#list dataList as units>
<Row ss:Height="57">
<Cell ss:StyleID="s215" ss:MergeAcross="1">
<Data ss:Type="String">${units.name}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count2}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count3}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count4}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count10}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.rate}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count8}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.hangrate}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count9}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.borrowrate}</Data>
</Cell>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count5}</Data>
</Cell>
<#if staff >
<Cell ss:StyleID="s190"/>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count6}</Data>
</Cell>
<Cell ss:StyleID="s190"/>
<Cell ss:StyleID="s190"/>
<Cell ss:StyleID="s190">
<Data ss:Type="String">${units.count7}</Data>
</Cell>
<Cell ss:StyleID="s190"/>
</#if>
<Cell ss:StyleID="s190"/>
<#if expert >
<Cell ss:StyleID="s190"/>
<Cell ss:StyleID="s190"/>
<Cell ss:StyleID="s190"/>
<Cell ss:StyleID="s190"/>
<Cell ss:StyleID="s190"/>
<Cell ss:StyleID="s190"/>
</#if>
</Row>
<#list units.children as item>
<Row ss:Height="14.25">
<Cell ss:StyleID="s191">
<Data ss:Type="String">${item_index+1}</Data>
</Cell>
<Cell ss:StyleID="s191">
<Data ss:Type="String">${item.name}</Data>
</Cell>
<Cell ss:StyleID="s192">
<Data ss:Type="String">${item.count2}</Data>
</Cell>
<Cell ss:StyleID="s191">
<Data ss:Type="String">${item.count3}</Data>
</Cell>
<Cell ss:StyleID="s193">
<Data ss:Type="String">${item.count4}</Data>
</Cell>
<Cell ss:StyleID="s194">
<Data ss:Type="String">${item.count10}</Data>
</Cell>
<Cell ss:StyleID="${item.id}+'rate'">
<Data ss:Type="String">${item.rate}</Data>
</Cell>
<Cell ss:StyleID="s191">
<Data ss:Type="String">${item.count8}</Data>
</Cell>
<Cell ss:StyleID="${item.id}+'hangrate'">
<Data ss:Type="String">${item.hangrate}</Data>
</Cell>
<Cell ss:StyleID="s191">
<Data ss:Type="String">${item.count9}</Data>
</Cell>
<Cell ss:StyleID="${item.id}+'borrowrate'">
<Data ss:Type="String">${item.borrowrate}</Data>
</Cell>
<Cell ss:StyleID="s191">
<Data ss:Type="String">${item.count5}</Data>
</Cell>
<#if staff >
<Cell ss:StyleID="s191"/>
<Cell ss:StyleID="s191">
<Data ss:Type="String">${item.count6}</Data>
</Cell>
<Cell ss:StyleID="s191"/>
<Cell ss:StyleID="s191"/>
<Cell ss:StyleID="s191">
<Data ss:Type="String">${item.count7}</Data>
</Cell>
<Cell ss:StyleID="s191"/>
</#if>
<Cell ss:StyleID="s191"/>
<#if expert >
<Cell ss:StyleID="s191"/>
<Cell ss:StyleID="s191"/>
<Cell ss:StyleID="s191"/>
<Cell ss:StyleID="s191"/>
<Cell ss:StyleID="s191"/>
<Cell ss:StyleID="s191"/>
</#if>
</Row>
</#list>
</#list>
单元格样式控制
<#-- 我在组装数据是已经根据规则计算了相关单元格要展示的颜色,字段为xxColor 颜色的格式为:#ADD88D -->
<#list dataList as units>
<#list units.children as item>
<#if item.rateColor?? >
<Style ss:ID="${item.id}+'rate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="${item.rateColor}" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="${item.id}+'borrowrate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="#ADD88D" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="${item.id}+'hangrate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="#ADD88D" ss:Pattern="Solid"/>
</Style>
<#elseif item.borrowrateColor?? >
<Style ss:ID="${item.id}+'rate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="#ADD88D" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="${item.id}+'borrowrate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="${item.borrowrateColor}" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="${item.id}+'hangrate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="#ADD88D" ss:Pattern="Solid"/>
</Style>
<#else>
<Style ss:ID="${item.id}+'rate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="#ADD88D" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="${item.id}+'borrowrate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="#ADD88D" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="${item.id}+'hangrate'">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12" ss:Bold="1"/>
<Interior ss:Color="${item.hangrateColor}" ss:Pattern="Solid"/>
</Style>
</#if>
</#list>
</#list>
数据不是list则不需要循环直接赋值即可,ftl模板内容如下
<Row ss:Height="14.25">
<Cell ss:StyleID="s216" ss:MergeAcross="1">
<Data ss:Type="String">合计</Data>
</Cell>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.count2}</Data>
</Cell>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.count3}</Data>
</Cell>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.count4}</Data>
</Cell>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.count10}</Data>
</Cell>
<Cell ss:StyleID="s199">
<Data ss:Type="String">${totalcontData.rate}</Data>
</Cell>
<Cell ss:StyleID="s199">
<Data ss:Type="String">${totalcontData.count8}</Data>
</Cell>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.hangrate}</Data>
</Cell>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.count9}</Data>
</Cell>
<Cell ss:StyleID="s199">
<Data ss:Type="String">${totalcontData.borrowrate}</Data>
</Cell>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.count5}</Data>
</Cell>
<#if staff >
<Cell ss:StyleID="s198"/>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.count6}</Data>
</Cell>
<Cell ss:StyleID="s198"/>
<Cell ss:StyleID="s199"/>
<Cell ss:StyleID="s198">
<Data ss:Type="String">${totalcontData.count7}</Data>
</Cell>
<Cell ss:StyleID="s199"/>
</#if>
<Cell ss:StyleID="s198"/>
<#if expert >
<Cell ss:StyleID="s198"/>
<Cell ss:StyleID="s198"/>
<Cell ss:StyleID="s198"/>
<Cell ss:StyleID="s199"/>
<Cell ss:StyleID="s198"/>
<Cell ss:StyleID="s199"/>
</#if>
</Row>片
表头窗口冻结标签
....上面的内容省略 主要在WorksheetOptions中设置 这块是表头未冻结的
</Table>
<WorksheetOptions
xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header/>
<Footer/>
</PageSetup>
<Selected/>
<TopRowVisible>0</TopRowVisible>
<LeftColumnVisible>0</LeftColumnVisible>
<PageBreakZoom>100</PageBreakZoom>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>24</ActiveRow>
<ActiveCol>3</ActiveCol>
<RangeSelection>R25C4</RangeSelection>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
表头窗口冻结
...上面部分省略
</Table>
<WorksheetOptions
xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header/>
<Footer/>
</PageSetup>
<Selected/>
<TopRowVisible>0</TopRowVisible>
<LeftColumnVisible>0</LeftColumnVisible>
<PageBreakZoom>100</PageBreakZoom>
<FreezePanes/>
<FrozenNoSplit/>
<SplitHorizontal>3</SplitHorizontal>
<TopRowBottomPane>3</TopRowBottomPane>
<ActivePane>2</ActivePane>
<Panes>
<Pane>
<Number>3</Number>
</Pane>
<Pane>
<Number>2</Number>
<ActiveRow>24</ActiveRow>
<ActiveCol>3</ActiveCol>
<RangeSelection>R25C4</RangeSelection>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
这是修改添加的地方
<FreezePanes/>
<FrozenNoSplit/>
<SplitHorizontal>3</SplitHorizontal>
<TopRowBottomPane>3</TopRowBottomPane>
<ActivePane>2</ActivePane>
<Panes>
<Pane>
<Number>3</Number>
</Pane>
<Pane>
<Number>2</Number>
<ActiveRow>24</ActiveRow>
<ActiveCol>3</ActiveCol>
<RangeSelection>R25C4</RangeSelection>
</Pane>
</Panes>
下面是一些关键设置的解释:
在Excel的XML架构中,<FreezePanes/>和<FrozenNoSplit/>是与窗口冻结和分割相关的设置。
<FreezePanes/>:
这个元素用于指定是否冻结工作表中的某些行或列。当冻结窗格时,指定的行或列将保持可见,即使你滚动工作表的其他部分。这通常用于在查看大量数据时保持标题行或列始终可见。
<FrozenNoSplit/>:
这个元素与冻结窗格的功能相关,但它具体控制的是当冻结窗格时,是否允许分割窗口。如果设置为True,即使冻结了窗格,用户也不能分割窗口。如果设置为False或未设置,用户可以在冻结窗格的同时分割窗口。
简而言之,<FreezePanes/>用于控制是否冻结工作表中的行或列,而<FrozenNoSplit/>用于控制当窗格被冻结时,是否允许用户分割窗口。这两个设置通常一起使用,以提供对工作表视图和窗口行为的精细控制。
<PageSetup>:
<Header/> 和 <Footer/>:这两个元素定义了工作表打印时的页眉和页脚。在这个例子中,它们都是空的,意味着没有设置页眉和页脚。
<TopRowVisible>:
设置为0,表示第一行是可见的。如果设置为1,则表示第一行是隐藏的。
<LeftColumnVisible>:
设置为0,表示第一列是可见的。如果设置为1,则表示第一列是隐藏的。
<PageBreakZoom>:
设置为100,表示页面在打印预览或页面布局视图中的缩放比例为100%,即正常大小。
<SplitHorizontal>:
设置为3,表示工作表在水平方向上被分割,分割点位于第3行。这通常用于在Excel中同时查看工作表的不同部分。
<TopRowBottomPane>:
设置为3,表示在分割窗口的底部窗格中,第一行可见的行是第3行。
<ActivePane>:
设置为2,表示当前激活的窗格是第二个窗格。在Excel中,窗格是指分割后的视图区域。
<Panes>:
定义了工作表中存在的窗格及其属性。在这个例子中,有两个窗格,第二个窗格有特定的活动行、列和范围选择。
<ProtectObjects> 和 <ProtectScenarios>:
这两个都设置为False,表示工作表中的对象和方案都没有被保护。如果设置为True,则它们会被保护,无法编辑。
总的来说,这个XML片段定义了一个Excel工作表的打印和视图设置,包括页眉和页脚、行和列的可见性、缩放比例、窗口分割和窗格设置,以及对象和方案的保护状态。