1. 先搞清楚,合并单元格在数据层面到底“合并”了什么
1.1 合并单元格的真实存储形态
我在处理各种报表时,“合并单元格”这几个字真是又爱又恨。爱是因为它在展示层确实干净利落,恨是因为一旦把数据交给程序去读取,它就成了最大的坑。很多人第一直觉是“合并单元格不就是一个大格子吗”,但实际上在 Excel 文件内部,合并区域并不是一个真正的“大格子”,它由一组单元格组成,只是视觉上合并了,底层只有左上角第一个单元格拥有真实值,其余单元格的值全是空(None)。
举个例子,你在 A1:A5 做了纵向合并,填了“研发部”,打开文件后的数据结构是这样的:
| 单元格 | 值 |
|---|---|
| A1 | 研发部 |
| A2 | 空 |
| A3 | 空 |
| A4 | 空 |
| A5 | 空 |
也就是说,Excel 在保存合并区域时,只保留了起始单元格(Anchor Cell)的值,其他格子纯粹是视觉占位。这个特性在日常手工看表时完全无感,但一旦你写公式、做匹配、用 Pandas 读取、做数据透视,问题就会集中爆发:明明 A 列有“研发部”,VLOOKUP 却只能在第一行找到,后面四行全部匹配不到。
如果只是五行还不可怕,可怕的是实际业务表里经常出现几千行的部门合并、日期合并、分类合并。合并单元格越多,数据读取时出现的“空洞”就越多,整个表格的可用性就越差。
1.2 为什么它会让匹配和查询全线崩溃
合并单元格在生产环境中最典型的三类问题,我这些年基本上都踩遍了。
第一类是VLOOKUP/INDEX-MATCH 类匹配失效。比如你有两张表,一张是员工明细表,一张是部门负责人映射表,映射表里“部门”列用合并单元格表示了。你用“部门”作为 Key 去匹配负责人,结果只有每个部门合并区域的第一行能匹配上,后面几行全是空值或错误值。明明表面上数据都存在,实际能用的行只有一小部分。
第二类是数据透视表和分类汇总结果错乱。透视表在生成行标签时,默认只读取每个有值的单元格,合并单元格其余空白部分会被当成“空值”单独分组,于是透视表里会莫名其妙多出一项“(空白)”,统计口径直接出问题。
第三类是Excel 公式下拉填充结果异常。很多人喜欢在合并区域旁边写“=A2”这样的引用公式,但下拉之后会发现只有第一行正常,后面全是空引用,因为源单元格本身就是空的。这个问题的本质就是:合并单元格没有把值“广播”到整个区域,公式拿到的只是一个空壳。
从这些现象可以提炼出一个结论:我们在做数据匹配和查询时,真正需要的不是“看起来合并”的单元格,而是它背后每个格子都有一个真实值的“完整矩阵”。只有把值补全,才能顺利基于它去建立索引、做匹配、生成映射关系。
1.3 我们需要的稳定映射,到底长什么样
标题里提到了一个关键词:Key→Value 映射。我理解的“稳定”至少包含三层含义。
第一层是存储稳定:每一个 Key 对应的 Value 不会因为合并单元格的视觉结构而出现缺失或错位。比如“部门→负责人”这个映射,应该是每个部门名称都能稳定对应到一个负责人,而不是只有第一条有值。
第二层是查询稳定:基于这张映射表做匹配,无论从哪个方向查、查多少次,结果都是一致且确定的。同一个 Key 永远返回同一个 Value,不会因为读到的行是合并区域里的第几行就返回空。
第三层是结构稳定:映射表能够脱离 Excel 界面独立存在,比如导出成 JSON、字典、数据库表,这样它才能真正交给后端程序、数据仓库去复用的。
举一个我最常做的例子:线上商城运营每周会给我一份“类目销售汇总”,第一列是“一级类目”,里面大量使用合并单元格,一合并就是几十行。要把它转成“一级类目 → 子类目列表”的 JSON 给前端筛选用,如果直接解析原始表格,出来的 JSON 里至少一半子类目没有父级 Key。而通过合并单元格匹配工具做一层“填充 + 映射”转换后,每个子类目都稳稳定定挂在对应的一级类目下,后面不管做筛选、权限控制还是数据分析,都不会再出幺蛾子。
2. 手工方案为什么撑不住,自动化又是怎么绕开它的
2.1 手工处理合并单元格的三个致命伤
在一开始,很多人的第一反应是:既然合并单元格有坑,那我手工“取消合并 → 填充 → 重新合并”不就行了?这个方法确实能解决这一次的问题,但我在实际工作中试过很多次,它有三个致命伤。
第一个是效率极低且不可复用。一张报表里如果有上百个合并区域,手工一个个取消合并再一个个填充,不仅要来回拉动 Excel,还容易漏掉某些小区域。处理完这一张,下一张来了又要重新来一遍。尤其当处理的是“每月周报”“每周明细”这类周期性报表时,手工方案等于每月受一次刑。
第二个是破坏原始表格的展示样式。你取消合并后做反向填充,如果不小心把边框样式覆盖了,表格就会变得很丑。而且如果后面还需要恢复原来的合并结构,手工操作几乎等于重做一遍格式,工作量翻倍。
第三个是无法嵌入自动化流程。在真实业务中,数据往往不是从单一的 Excel 文件来的,它可能来自某个报表系统导出、某个邮件附件、或者某个前端表格组件的上传。如果所有环节都依赖手工处理,整个数据链路就断在中间环节,没法实现从“收到文件”到“进入数据库”的全自动衔接。
所以,做一个小工具,把“识别合并区域 → 提取左上角值 → 填充到整个区域 → 构建映射”这四步固化下来,才是更合理的路子。
2.2 自动化处理的核心思路:把“左上角值”广播到整个合并区域
关于自动化,先厘清一个关键概念:这个工具做的事,本质上是forward fill(前向填充)。也就是对于每一个合并区域,取左上角单元格的值,然后把该值复制到该合并区域覆盖的所有其他单元格。
你可以把它理解成“广播”:合并区域左上角是一个信号源,信号源发出的值会覆盖到整个合并区域内所有空白位置。比如“季度 → 月份”这种多级表头,横向合并了“Q1”,我们就把 Q1 填充到它合并覆盖的所有列上,这样每一列都能知道自己属于哪个季度。
这个思路虽然简单,但它背后隐含了一个判断规则:必须真正识别出哪些单元格属于合并区域,而不是简单地对所有空值做一次 ffill。因为一张表里还可能存在“本来就该空”的单元格,如果对所有空值一律填充,就会把应该留空的位置也填上错误的值。所以核心实现第一步,永远是遍历文件内部的合并区域元数据,第二步才是做值填充。
理解了这一点,后面写代码心里就有底了:我们要处理的对象,不是“所有空单元格”,而是“被合并区域覆盖的单元格”。
2.3 三个可选技术方案的取舍对比
既然要把工具落地,就会面临技术选型。围绕“合并单元格 → Key→Value 映射”这个目标,我从实际可操作性角度对比了三种我最常用的方案。
| 方案 | 运行环境 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| Python + openpyxl | 本地脚本 / 服务器 | 可直接定位合并区域,支持保留原始合并结构,精确控制填充逻辑 | 只支持 .xlsx,不支持老版 .xls | 需要保留原文件的格式与合并结构,逐行逐格处理 |
| Python + pandas | 数据分析链路 | 代码极短,后续分析方便,能直接生成 DataFrame 再转 JSON/DB | 读取时默认会丢弃合并区域信息,需要配合参数处理 | 只关心最终数据结果,不需要保留 Excel 原格式 |
| 前端 JS + XLSX 库 | 浏览器 / Node.js | 在线就能处理,适合做上传解析、跨平台工具 | 依赖第三方库,且要额外处理 SheetJS 的解析逻辑 | 实现 Web 上传解析、前端表格组件的数据预处理 |
从整体效率看,如果只是把 Excel 里的配置表清洗成可用的映射,我建议首选 Python + openpyxl,因为它对合并区域的识别最精准;如果目标是把数据导入数据库做分析,pandas 方案更省事;如果做的是纯前端项目,那就直接走 JS 方案。三种方案我都亲手跑过,下面把每种的完整代码和注意事项一次讲清楚。
3. 代码来了:三种方式实现合并单元格到 Key→Value 映射
3.1 准备工作:环境与依赖
在写代码之前,先把环境准备好。我用 Python 3 为主,需要安装两个库:openpyxl 和 pandas。openpyxl 负责操作 .xlsx 文件,pandas 负责快速读取和二次处理。
pip install openpyxl pandas前端 JS 方案的话,需要引入 SheetJS(xlsx 库),我一般用 npm 安装:
npm install xlsx安装完成后,就可以按下面的方式分别处理了。
3.2 方案A:openpyxl 精准定位合并区域并填充(推荐)
openpyxl 最强大的地方在于它直接暴露了合并区域的元数据接口merged_cells.ranges,我们可以精准拿到所有合并区的行列范围,然后逐格填充值。下面是我在实际项目中使用的核心函数:
from openpyxl import load_workbook def fill_merged_cells(input_path, output_path, sheet_name=None): wb = load_workbook(input_path) ws = wb[sheet_name] if sheet_name else wb.active # 1. 收集所有合并区域 merged_ranges = list(ws.merged_cells.ranges) if not merged_ranges: print("没有检测到合并单元格") return filled_count = 0 for merged_range in merged_ranges: # 左上角坐标是合并区域的起点 start_row = merged_range.min_row start_col = merged_range.min_col anchor_value = ws.cell(row=start_row, column=start_col).value # 把锚点值广播到整个合并区域 for row in range(merged_range.min_row, merged_range.max_row + 1): for col in range(merged_range.min_col, merged_range.max_col + 1): ws.cell(row=row, column=col).value = anchor_value # 如果希望保持原合并结构,可以不执行 unmerge;如果希望后续导出更干净,就取消合并 ws.unmerge_cells(str(merged_range)) filled_count += 1 wb.save(output_path) print(f"已处理 {filled_count} 个合并区域,结果保存至 {output_path}") if __name__ == "__main__": fill_merged_cells("input.xlsx", "output_filled.xlsx")这里有几个细节我要重点说明。
第一,为什么遍历的顺序不需要担心嵌套合并。Excel 的合并区域是不允许重叠的,所以merged_cells.ranges返回的是一个互不交叉的区域集合,直接遍历不存在重复赋值问题。
第二,unmerge_cells这一步是可选的。如果你只是想在原表格基础上得到“每个格子都有值”的效果,建议保留合并单元格,这样打开文件时外观不变,但每个格子里又都有值。但如果你需要把数据导出成数据库可识别的扁平结构,那就执行 unmerge,让结构变成普通单元格。
第三,锚点值可能为 None。现实中有一些“空合并单元格”,左上角本身就是空的,这种情况填充后区域里的格子依然是空,这是正常现象,不需要特别处理,但要注意它不代表“合并单元格变成了有值单元格”。
3.3 方案B:pandas 极简填充,一行代码搞定大部分场景
如果你不需要保留原始 Excel 样式,只想拿到一份“完整值”的二维表用于后续分析,pandas 方案更简洁。它的原理是:读取文件时保留所有原始数据,然后按行方向(或列方向)做前向填充。
读取 Excel 文件时,我习惯指定header=None,因为合并单元格往往出现在表头部分,如果让 pandas 自动把第一行设为表头,很容易丢掉首行信息。之后用 pandas 自带的 ffill 处理:
import pandas as pd df = pd.read_excel("input.xlsx", header=None) # 纵向填充:把上方有值的单元格向下填充到本列的空格 df_filled = df.ffill(axis=0) # 如果表头是横向合并的,还需要横向填充一次 df_filled = df_filled.ffill(axis=1) # 处理后,第一行表头、第二行表头都能被完整还原 print(df_filled.head()) # 构建 Key→Value 映射,假设第一列是 Key,第二列是 Value mapping = dict(zip(df_filled[0], df_filled[1])) print(mapping)pandas 方案之所以要同时做ffill(axis=0)和ffill(axis=1),是因为合并单元格在表中既有纵向合并(如下方单元格归属某个分类),也有横向合并(如表头中的季度标题跨列)。单做一次纵向填充只能解决“同列合并”,处理不了“跨列合并”。碰到既有纵向合并又有横向合并的复杂报表,两次填充都要做,顺序通常建议先纵向再横向,原因在于:纵向优先把主分类补齐,横向再处理跨列表头,这样逻辑更清晰,我在反复测试中没遇到过反顺序更合理的情形。
不过这里我要提个醒:pandas 用 ffill 无法区分“合并产生的空值”和“原本就是空值的单元格”。如果表格里存在真正常规的空白行或空白列,ffill 会把它也填上值,可能改变数据语义。所以这个方案适合对数据结构比较熟悉的场景,如果不确定,还是用方案A更稳妥。
3.4 方案C:前端 JS 处理 Element 表格的合并导出
需求里经常出现“Element 表格合并单元格导出”的场景。用户在页面上看到合并后的表格很整齐,但导出到 Excel 后,程序解析又遇到同样的问题。如果把处理逻辑放到前端,就能在上传或导出环节直接完成映射补全。
我用 SheetJS 实现同样功能时,核心是读取工作表中!merges属性,然后对每个合并区域做填充:
const XLSX = require('xlsx'); function fillMergedCells(workbook, sheetName) { const sheet = workbook.Sheets[sheetName]; const merges = sheet['!merges'] || []; for (const range of merges) { const anchor = XLSX.utils.encode_cell({ r: range.s.r, c: range.s.c }); const anchorValue = sheet[anchor] ? sheet[anchor].v : undefined; for (let r = range.s.r; r <= range.e.r; r++) { for (let c = range.s.c; c <= range.e.c; c++) { const cellRef = XLSX.utils.encode_cell({ r, c }); sheet[cellRef] = { v: anchorValue, t: typeof anchorValue === 'number' ? 'n' : 's' }; } } } return workbook; } // 读取一个文件并处理所有 sheet const wb = XLSX.readFile('input.xlsx'); Object.keys(wb.Sheets).forEach(name => fillMergedCells(wb, name)); XLSX.writeFile(wb, 'output_filled.xlsx');这段代码的核心同样是两级循环:外层遍历合并区域,内层遍历区域内所有单元格。需要注意 SheetJS 中坐标是 0-based 的,range.s是合并区域左上角,range.e是右下角,通过encode_cell可以生成单元格引用。
Element 表格的同学经常问“怎么让合并的单元格也一起高亮”,其实高亮和填充是同一类逻辑:你需要完整的数据矩阵才能正确处理行级样式。如果导出时span-method合并过的行只有首行有数据,前端渲染高亮就只能覆盖第一行。解决办法是在拿到表格数据后先做一次类似上面的“区域填充”,把合并跨度对应的数据补齐,再渲染状态、背景色、点击事件,整行操作就不会断层了。
3.5 从二维表到稳定的 Key→Value 映射结构
填充完成后,最后一个关键步骤是把它转换成真正可用的映射结构。这个步骤因人而异,但我提供两种最常用的存档方式。
第一种是构建 Python 字典。适合把“配置表”转成程序内部的映射数据。比如处理完一份“商品类目对照表”后,第一列是类目编码,第二列是类目名称,就可以这样构建映射:
mapping_dict = {} for _, row in df_filled.iterrows(): key = row[0] value = row[1] if key not in mapping_dict: mapping_dict[key] = value第二种是导出为 JSON 文件,方便交接给前端或其他系统。用 Python 实现非常方便:
import json result = df_filled.to_dict(orient="records") with open("mapping.json", "w", encoding="utf-8") as f: json.dump(result, f, ensure_ascii=False, indent=2)这里又有一个容易出现的问题:同一 Key 出现多次时,怎么取值。合并单元格填充后,同一个“部门”可能对应很多行“人员”,如果只希望保留“部门→负责人”,那就用dict()直接去重;如果想要“部门→人员列表”,就要改成聚合模式。我通常的做法是,先设定目标映射的“粒度”,再在填充后的表上做 groupby,而不是盲目用dict(zip(...))一把梭。
4. 三个真实场景的完整实操
4.1 场景一:横向合并的两级表头转竖表
有一份“年度销售汇总表”,第一行是季度,第二行是月份,两个层级都用了合并单元格。季度那一行“Q1”横向合并了三列,“Q2”横向合并了三列;月份那一行“1月”“2月”“3月”各自独立。这种表如果直接读取,会发现只有每个季度块的第一列有 Q1 的值,其他列是空。
我的处理流程是这样的:
- 用 openpyxl 读取原文件,获取所有合并区域信息。
- 按方案A填充整个表,此时第一行每个季度列都有对应值,第二行每个月列也有对应值。
- 用 pandas 读取填充后的结果,把“季度”“月份”“销售额”三列拼成一张扁平表。
- 生成 JSON,结构是
[{ "quarter": "Q1", "month": "1月", "sales": 12345 }, ...]。
经过这个流程,原本靠视觉才能看懂的二级表头,就变成了机器能直接消费的结构化数据。这个方案的通用性很强,凡是“季度合并、月份合并、年份合并”的多级表头报表,都可以照搬。
4.2 场景二:纵向合并的部门人员映射
另一类很常见的场景是“人员名单表”,如表所示:A 列是部门,B 列是姓名,C 列是岗位。A 列之间有很多纵向合并单元格,一个部门下面挂了十几个人。如果直接读原始表,只能得到“部门名 + 第一个员工”的对应关系,后面十几条记录都缺失“部门”字段。
我用这个工具处理后,A 列的部门名会被填充到该部门合并区域覆盖的所有行。这样每一条员工记录都带上了所属部门,后续无论做“部门→人员列表”还是“员工→部门”的映射,都只需要简单的表格操作:
# 填充完成后,按部门聚合出人员列表 grouped = df_filled.groupby(df_filled[0])[1].apply(list).to_dict()这样做出来的“部门→人员列表”映射,在权限管理里非常常用。比如做 OA 系统时,需要根据部门自动匹配审批人,这个映射就是最直接的配置数据源。
4.3 场景三:批量处理多 Sheet 的配置表
第三种是我实际工作里最头疼的场景:一份工作簿有几十个 Sheet,每个 Sheet 里都有数量不等的合并单元格,要统一清洗后导入数据库。手工打开每个 Sheet 去清理,一天就没了。所以我给工具加了一层多 Sheet 循环。
思路很简单:遍历wb.sheetnames,对每个 sheet 执行相同的填充逻辑,再统一汇总输出:
def fill_all_sheets(input_path): wb = load_workbook(input_path) for ws in wb.worksheets: merged_ranges = list(ws.merged_cells.ranges) for merged_range in merged_ranges: anchor = ws.cell(merged_range.min_row, merged_range.min_col).value for row in range(merged_range.min_row, merged_range.max_row + 1): for col in range(merged_range.min_col, merged_range.max_col + 1): ws.cell(row=row, column=col).value = anchor wb.save("output_all_sheets.xlsx")如果 Sheet 数量特别多,我建议加一个日志,把每个 sheet 处理了多少个合并区域打印出来,方便核对是否漏处理。批量处理时我遇到过有些 sheet 是模板、没有实际数据,合并区域为空,这时打印信息也能帮助判断哪个 sheet 出了问题。
让我把这些运行经验整理成一个表格,方便你对照选择:
| 场景 | 推荐方案 | 关键注意点 |
|---|---|---|
| 单文件保留格式填充 | openpyxl | 遍历 merged_cells.ranges,再逐格赋值 |
| 多级表头转扁平结构 | openpyxl + pandas 组合 | 先 openpyxl 填充,再 pandas 读成宽表 |
| 纯数据分析、导入数据库 | pandas | 用 ffill 要注意区分真实空值和合并空值 |
| 前端 Web 上传解析 | SheetJS | 读取 sheet['!merges'],手动填充后转换 |
| 多 Sheet 批量清洗 | openpyxl 循环 | 加日志统计每个 sheet 的合并区域数 |
5. 常见问题与排查技巧实录
5.1 合并区域识别为空,或边界识别不准
先讲一个我自己踩过的坑:用 pandas 读取 Excel 后,df.columns经常出现Unnamed: 1这类奇怪列名,这就是因为表头存在合并单元格,pandas 自动把空列名处理成了Unnamed。很多新手在这就开始慌了,以为数据丢了。实际上合并单元格并没有丢,只是 pandas 不会自动读取合并区域信息,它读到的就是一个个空单元格。
排查思路是这样的:如果想知道某个文件里到底有哪些合并区域,先用 openpyxl 去看一眼,不要用 pandas 猜。执行下面这段代码,把所有合并区域坐标打印出来:
from openpyxl import load_workbook wb = load_workbook("input.xlsx") ws = wb.active for mr in ws.merged_cells.ranges: print(mr, "=> 锚点值:", ws.cell(mr.min_row, mr.min_col).value)如果这个输出为空,说明文件里根本没有合并单元格,那你的“空值”问题就另有原因(比如本身数据就是缺的)。如果输出有内容,但锚点值是 None,说明这个合并区域只是视觉合并,没有任何实际数据,需要在后续处理时特别留意。
5.2 空单元格和合并单元格的“真假美猴王”
用 pandas 的ffill()处理时,一个风险是会把“原本该空”的单元格也填充了。比如一张考勤表,某员工某天本来就没有打卡记录,空值是有业务含义的,但 ffill 会把它填充成前一天的状态,直接污染数据。
怎么避免这个问题?我给出两条经验。
第一条,优先使用 openpyxl 方案,因为它是根据merged_cells.ranges精准识别合并区域,而不是凭“空值”猜。只有合并区域内的单元格才被填充,其他空格保持原样,语义不会变。
第二条,如果只能用 pandas,先单独清洗合并区域,再做整体填充。也就是说,先用 openpyxl 把合并区域的值填充好,再交给 pandas 做后续分析,而不是一上来就read_excel然后无脑 ffill。在我的实践中,这种组合方案比“纯 pandas 一把梭”更稳妥。
5.3 大数据量场景的性能优化
说个真实数据:我处理过一张十万行的明细表,其中有三万多行处于合并单元格区域。如果直接用 openpyxl 逐格遍历赋值,耗时接近几分钟,这个等待非常难受。针对这个问题,我把 openpyxl 处理改成“先读取、后写入”的思路,性能提升明显:
- 先用
ws.values把整个工作表读入内存,得到一个二维数组。 - 在内存中根据合并区域坐标,对二维数组做填充。
- 一次性把二维数组写回工作表。
这样做的好处是减少了对 Excel 单元格对象的频繁访问。openpyxl 每次ws.cell()都会触发底层 XML 节点解析,把单元格对象换成普通 Python 对象后,速度能快好几倍。
与此同时,处理大文件时建议关闭 Excel 的自动计算和公式缓存。openpyxl 加载文件时可以传入data_only=True,这样读到的就是缓存值而不是公式,能避免后续处理公式时触发额外计算。需要注意:如果一个单元格保存的是公式且从未被打开计算过,data_only=True读到的值可能是 None,这时要反查原始公式单元格再处理。
5.4 类型与格式:填充后数字变文本,日期变字符串
最后一个高频问题:合并单元格填充后,数字或日期类型的值可能变成无法计算的文本。原因在于合并区域内的部分单元格可能是“字符串格式”或“常规格式”,赋值后 Excel 按原格式显示,数字就变成了文本。
openpyxl 里直接ws.cell(row, col).value = value时,赋的值本身保留 Python 类型:数字赋 int/float,日期赋 datetime。如果最终发现类型不对,可以检查源单元格的number_format,在填充时把number_format一并复制到目标单元格:
anchor_cell = ws.cell(start_row, start_col) for row in range(merged_range.min_row, merged_range.max_row + 1): for col in range(merged_range.min_col, merged_range.max_col + 1): target_cell = ws.cell(row, col) target_cell.value = anchor_cell.value target_cell.number_format = anchor_cell.number_format还有一个我经常被问到的问题:合并单元格里是公式,怎么办?比如左上角是=VLOOKUP(...),填充后其他格子值是公式结果还是公式本身?默认情况下 openpyxl 会把公式字符串赋值到所有格子,这会造成大面积公式重复计算。我的建议是:先读取公式的结果值,再赋值结果。也就是说,用data_only=True加载一份缓存值版本,或者先让 Excel 格式化保存一次,再用脚本读取,避免把公式到处复制。
从这些经验来看,合并单元格匹配工具虽然代码不长,但要在真实环境里稳定运行,需要考虑的细节远比“填充”本身多。不管你是做数据分析、报表开发,还是前端表格的导入导出,这套“识别合并区域 → 提取锚点值 → 广播填充 → 构建映射”的思路都是通用的。
我在实际使用中最深的一点体会是:合并单元格是给眼睛看的,不是给程序看的。工具的价值就在于把“视觉合并”翻译成“数据完整”,帮你在展示层和计算层之间搭一座桥。目前这份代码我已经稳定跑在几个内部报表流程里,包括月度销售汇总、部门人员权限映射、类目配置表清洗,效果都还不错。如果你在运行中遇到什么奇怪的数据问题,尤其是同一个文件里有几十种合并格式的那种,欢迎交流,后续我可以再整理一期专门针对“前端表格组件导出 + 后端解析”的合并单元格处理方案。