☰
我用华为云码道 CodeArts 做了个报表合并工具
2026/10/2 17:21:30 网站建设 项目流程

我用华为云码道 CodeArts 做了个报表合并工具

一键开通华为云码道 CodeArts 代码智能体:
https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwatomgit1&sourcead=dmzntgwatomgithd

在线体验:
https://excel-merge-tool-88500.app.workbuddy.host/

开源仓库(AtomGit):
https://atomgit.com/qq_40202349/excel-merge-tool

同一个订单,一份报表写 5800,另一份写 5850。月底汇总时,这两行该保留哪一行?删掉其中一行,差额的线索就没了;全部留着再求和,又可能把同一笔订单算两遍。

连把数据放到同一列都未必顺利。一份叫“金额”,另一份叫“销售额”,系统导出的 CSV 用的是amt。有的表还多了一列备注,按位置复制粘贴,很容易放错列。

这次我用华为云码道 CodeArts 做了一个报表合并工具,想先把这些麻烦摆到页面上:确认列名怎么对应,找出冲突和重复,再带着来源文件、行号回原表核对。文件的解析、合并和导出都在浏览器本地完成。

先看做出来的效果。从上传五份表到拿到合并报告,整个操作过程不到 20 秒:

图1:从上传报表到导出报告的操作演示。

用五份分公司销售报表做测试,四份 Excel 加一份 CSV,一共 21 行。里面埋了几个坑:各表列名不一样、一笔订单有两个金额、一条完全重复的记录,还有几个空着的日期。合并后勾选“只看异常行”,那笔对不上的订单就自己冒出来了:

图2:筛选出合并结果中的异常记录。

一、把五份表里的麻烦写进需求

先在 AtomGit 网页端通过 CodeArts Agent 创建excel-merge-tool仓库,再把需求交给它。技术栈选了 Vue 3、TypeScript 和 Vite,表格解析用 SheetJS,核心逻辑用 Vitest 测试。

“把几份表合成一份”还不够具体。列名不同怎么办?同一个订单出现两次,能不能直接删?这些都要提前交代。需求里要求先给出字段映射建议,让使用者选主键和去重策略;发生金额冲突时保留记录,导出时另附一张合并报告,写清输入、输出和跳过的行。

页面按上传、字段映射、合并预览、导出分成四步。解析和合并放进 Web Worker,核心函数单独放在core/,不引用 Vue 或 DOM。这样后面发现一条数据不对,就能直接给函数喂一个小样例,不用每次都从页面点起。

图3:码道检查主键、空值等边界情况。

执行中有个小细节:它修正了报告测试里的行号断言。数据下标是 1,加上表头,对应的却是 Excel 第 3 行。这个差别会影响使用者回原表找记录,不能只让程序内部的下标对得上。

图4:码道修正行号断言后,94 项测试通过。

到这里,四步界面、核心代码和测试都有了。接下来要检查的,是这些代码遇到实际文件以后会怎样。

二、日期少了一天,把问题发回码道

初版检查中发现了日期偏移:预期是2026-08-01,结果却成了2026-07-31。当时的实现把Date用toISOString().slice(0, 10)转成日期字符串。toISOString()输出 UTC 时间,东八区的本地午夜转过去,会落在前一天。

这次反馈写了出错位置、运行时区和预期结果,还要求补一个回归用例:让本地午夜的日期走完 Excel 写入、读取、解析,再核对输出。

图5:向码道反馈日期少一天的问题。

截图里的复现表达式写得不准确:new Date('2026-08-01')按 UTC 解析;构造本地午夜应使用new Date(2026, 7, 1),月份从 0 开始。历史截图保留原样,这里更正。

码道随后把格式化改成读取本地年月日,补了三个回归用例,并给出 97 项测试通过的修复报告。

图6:码道给出日期修复方案和 97 项测试通过的报告。

从 94 项到 97 项,新增的三项都有具体针对的问题。不过,这还是码道环境里的交付结果,拿到本地后需要再跑一次。

三、97 项测试拿到本地,仍有两项失败

后续独立复核在这台东八区 Windows 电脑上运行,结果是 95 项通过、2 项失败。失败的仍然是日期:本地午夜走完 Excel 写入、读取和解析,还是少了一天。

继续往前查,偏差发生在日期格式化之前。当时使用的 SheetJS 0.18.5,在这条写入再读回的链路中,读到的本地时间已经落在前一天午夜前。只改最后的字符串处理,修不到这一层。

核对 SheetJS 官方安装说明 后,复核阶段把依赖固定到官方 CDN 提供的 0.20.3。读取方式也做了调整:保留 Excel 的日期序列值和格式,直接输出日历日期,减少经过 JavaScript 时区转换的环节。

下面是src/core/parse.ts中的关键设置和日期转换片段,省略了遍历、日期类型判断及错误处理:

workbook=XLSX.read(data,{type:'array',cellDates:false,cellNF:true,raw:true,})cell.v=XLSX.SSF.format('yyyy-mm-dd',cell.v,{date1904:!!workbook.Workbook?.WBProps?.date1904,})cell.t='s'deletecell.wdeletecell.z

date1904也不能漏。工作簿使用的日期系统不同,同一个序列值对应的日历日期就不同。

这轮验证既保留了写入、读回的用例,也构造了固定序列值,覆盖 1900、1904 两种日期系统。相关解析和数据保全用例分别在 UTC、洛杉矶、UTC+14 下运行,检查换一个时区后日期是否仍然相同。

日期问题到这里才算经过本地复核。后面的页面和数据处理修正,同样属于独立复核阶段,并非码道那份 97 项测试报告中的内容。

四、再从上传走到预览,检查每一步的数据

浏览器走查先卡在了上传入口。选择文件后,列表没有出现文件:输入框的change事件又调用了打开选择器的方法,没有接上读取逻辑。页面还缺少进入字段映射的按钮。核心测试不加载 Vue 页面,这两处问题要实际点击才能发现。

修好入口,才能继续核对字段。华北表用“订单编号”“产品名称”“销量”“销售额”,目标表则用统一列名。当前版本通过本地同义词表给建议,例如把“销售额”和amt对应到“金额”,不在运行时调用大模型;建议不合适,可以在下拉框里改。

图7:将各份报表的列名映射到统一字段。

这里还补了一个拦截:如果同一份表同时有“金额”和“销售额”,不能让两列都写进同一个目标列,否则后一次赋值会覆盖前面的内容。遇到重复映射,现在会提示文件名,等使用者改好再合并。

到了合并步骤,又遇到 Vue 响应式对象不能直接传入 Worker 的问题。postMessage使用结构化克隆算法,无法直接克隆 Vue Proxy。当前合并协议只有数组、字符串和普通对象,因此发送前转成普通 JSON 数据;上传文件仍用ArrayBuffer,通过 transfer list 传递。如果以后扩展协议来传日期对象或其他类型,这部分也要跟着调整。

预览能显示以后,还要看标签有没有漏。选择“全部保留”时,两条重复记录都应该带标签,也都能被“只看异常行”筛出来。对于金额为 100、200、200 的三条冲突记录,也不能只标出一个 200,漏掉另一条。

去重依据同样需要检查。原实现把复合主键中的空值过滤掉,再用|拼接,可能把不同记录拼成同一个键。修正后,缺少部分主键就提示空值,不自动去重;完整的复合主键用结构化形式编码:

exportfunctioncreateRowKey(parts:string[]):string{if(parts.length===0||parts.some(v=>v===''))return''returnparts.length===1?parts[0]:JSON.stringify(parts)}

最后还要保住单元格本来的含义。CSV 编号00123按文本读取,备注里的“运费¥50”保持原文;金额比较时可以识别货币符号和千分位,导出时再把金额、数量、单价写成数值,方便继续求和。

五、下载 Excel,再把结果读回来

修正后的版本在 Edge 中跑了一遍生产构建,从选择文件、确认映射,一直走到下载。导出完成后,又重新读取真正下载下来的 Excel,核对“合并结果”和“合并报告”。

五份样例输入 21 行,默认“保留一条”输出 20 行。少掉的是一条重复记录;开头那笔 5800、5850 的冲突仍然保留,报告能指出被去重的是华北表第 4 行。

图8:合并报告列出处理结果和去重明细。

检查项本次结果
输入文件4 份.xlsx、1 份.csv,共 21 行
选择“保留一条”输出 20 行,跳过 1 行重复记录
选择“全部保留”输出 21 行,重复的两行均有标签
金额冲突保留 5800、5850,标记 2 个冲突单元格
重复与空值1 组重复;3 个空单元格,含 1 个日期、2 个备注
导出内容结果、报告两张工作表,金额列为数值
最终本地测试7 个测试文件,112 项通过
核心实现覆盖率行 98.88%,分支 90.63%

这里的冲突按单元格计,重复按组计;备注空值目前也会提示。覆盖率只统计解析、同义词、映射、校验、合并、导出六个实现文件,不包含 Vue 页面。

浏览器走查还覆盖了拖拽、清空重选、错误文件提示和 390px 小屏。页面加载并解析完文件后断网,仍可导出;本轮观察到的 HTTP 请求都是本地页面资源,没有发现报表内容外发。这个结论限于本次测试环境。

当前工具适合表头清楚的明细表:每个文件只处理第一个工作表,第一条非空行作为表头。它不会完整保留合并单元格、多级标题、复杂公式和原样式,日期只输出到天。超大文件和其他浏览器还没做专项测试,金额冲突最终采用哪条记录,也仍需人工核对。

六、实际使用感受

码道这次帮忙最多的,是把需求变成了一套可以继续检查的工程。四步界面、核心函数和首轮测试一起交付,日期反馈后又有具体的修改和回归用例,省去了从空白项目搭起的工作。

后续花时间的地方,往往比最初的需求细:重复的两行是不是都能筛出来,主键缺一部分会不会误删,编号导出后还剩几个零。这些问题靠现成样例和下载后的文件更容易说清楚。94、97、112 也分别属于首轮交付、码道日期修复、后续本地复核,不能混成一次验收结果。

如果再做同类工具,我会把这五份带问题的表随需求一起交出去,连预期保留哪些行、报告写什么都说明白。交付后再用同一批文件核对,反馈也更具体。

你合并报表时,最常遇到的是列名不一致,还是同一笔业务在不同文件里对不上?也欢迎在评论里说说其他难处理的表格结构。

想试试当前版本,可以直接打开在线体验版,也可以拉下代码在本地启动:

gitclone https://atomgit.com/qq_40202349/excel-merge-tool.gitcdexcel-merge-toolnpmcinpmrun dev

导入fixtures/review/里的五份样例(在线版可以从这个下载目录逐个下载),保留默认“订单号”主键和“保留一条”策略。合并后应有 20 行,勾选“只看异常行”,找到ORD-2026-0912,看看那两个不同金额的来源。

再点“上一步”,把策略改成“全部保留”,重新合并。结果会变成 21 行,重复记录也会留下并带有标签。最后导出 Excel,打开“合并报告”,对照这两次处理的差别。

测试和构建命令如下:

npmtestnpmtest----coveragenpmrun build

的来源。

再点“上一步”,把策略改成“全部保留”,重新合并。结果会变成 21 行,重复记录也会留下并带有标签。最后导出 Excel,打开“合并报告”,对照这两次处理的差别。

测试和构建命令如下:

npmtestnpmtest----coveragenpmrun build

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询