让我头疼一下午的Excel合并单元格

Excel导出常见问题

excel导出其实不算什么难事

在网上copy下模板代码,填充自己的业务数据,提供一个http接口基本就可以得到你要导出的数据了。

但是,凡事都有例外,截止今天,excel导出我遇到的主要是两大类问题

1、大数据量的excel数据,比如几十万条甚至更多的数据导出

2、因为excel中内容的问题,导致导出后的excel不能直接打开,报错“由于一些内容不可取,Excel无法打开xxx.xlsx。是否要打开并修复此工作簿?”

针对第一种大数据量问题,我遇到的主要问题是excel存储的记录上限和导出超时等问题

解决方法是将导出格式为xls升级为xlsx,xls每个sheet最多支持65536条记录,xlsx最多支持1048576条记录;超时则可以采用前端直接返回,后端异步取数据并导出的方式避免超时。

这种情况不是今天要介绍的重点,今天要介绍的第二种情况的解决思路。

需求描述

1、层级关系最多为四级

2、对于相同层级,如果内容相同需要纵向合并单元格,空白行不需要合并

3、样例数据如下所示

一级目录1,二级目录1,三级目录1,四级目录2,

一级目录1,二级目录1,三级目录3,

一级目录1,二级目录1,三级目录5,

一级目录1,二级目录3,

一级目录1,二级目录5,三级目录5,

一级目录2,二级目录2,三级目录2,

一级目录2,二级目录2,三级目录3,

一级目录2,二级目录4,三级目录4,

一级目录2,二级目录7,

一级目录3,二级目录6,三级目录4,

一级目录3,二级目录6,三级目录10,

一级目录4,

一级目录5,二级目录8,三级目录6,

解决思路

将上面样例数据存入一个集合中,遍历每条记录并存放到相应的单元格。

如果不需要合并单元格,到这里,就可以提供导出的Excel了。

但是重点是合并单元格。

遇到的问题

初步排查

自认为代码已经就位,调用接口,Excel文件也成功下载了,结果打开的那一刻一个对话框让我头疼了一下午。

报错信息如下

第一反应是肯定数据错乱了,估计是单元格之间相互挤占,数据肯定也是不堪入目。

但是我按照智能的Excel提示,点击“打开并修复”后发现,数据没有我想的那么糟,甚至仔细看看,发现居然没有问题。

有点小激动的同时,心里还是有点不爽,总不能让别人每次导出的时候都使用这个智能的“打开并修复”功能才能看导出的数据吧。

但是光从这个报错信息来看确实没有什么线索,于是网上找了一通与“由于一些内容不可取,Excel无法打开xxx.xlsx。是否要打开并修复此工作簿?”有关的解决方法。虽然有不少人遇到过这样的问题,但是引起问题的原因不太一样,有些是因为sheet的命名包含特殊字符,有些是导出的Excel内容中有非法字符,还有说要在response的header中加入Content-length字段的。

进一步排查

搜了一通,没有什么进展,这时候想起来在刚刚点击“打开并修复”后,还弹出了一个对话框,于是点击对话框中的查看

得到线索如下

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><logFileName>修复结果到 xxx.xml</logFileName><summary>在文件“/Users/jackie/Downloads/xxx.xlsx”中检测到错误</summary><removedRecords summary="以下是已删除记录的列表:"><removedRecord>已删除的记录: /xl/worksheets/sheet1.xml 的 合并单元格</removedRecord></removedRecords></recoveryLog>

排除了前面提到的种种非法字符的原因,看到线索里的“合并单元格”,基本可以断定这是因为在合并单元格的过程中出了问题。

寻找问题根本原因

结合合并单元格导致Excel表格无法打开的症状在网上搜索一通

http://www.360doc.com/content/14/0107/11/14931240_343269914.shtml这篇文章给出了解决思路

我将下载的Excel表格的后缀从xlsx改为zip并打开

打开sheet1.xml文件,找到mergeCells标签,将其内容拷贝到XML在线格式化工具中查看

经过人眼搜索,终于发现了问题所在

    ...

    <mergeCell ref="B175:B189"/>

    <mergeCell ref="B176:B190"/>

    ...

这里显然出现了覆盖合并的情况,进而导致打开Excel报错的情况(后面经过测试发现,重复合并单元格也会出现同样的报错信息)

顺着这个思路,排查代码,不断调试测试,考虑各种情况下的合并单元格场景,最终搞定了这个稍稍复杂的合并单元格的Excel导出功能。

一点思考

虽然知道是合并单元格导致的问题,但是在实际调整代码时花费了几乎一个下午,曾经一度头大到不想思考。

回头想想,在这个问题上有两大收获。

1、排查问题的思路很重要

问题的现象已经摆在眼前,排查了不是非法字符的原因,就应该寻找其他原因

利用一切可以利用的手头信息比如上面简短而关键的报错日志信息。

活用搜索引擎,这种问题肯定已经有前人踩过雷,去看下他们是怎么排雷的就好,不用自己再去研究排雷的具体方法了。

2、写代码之前先想好

现在想想这段合并单元格的代码是不是可以写的更加漂亮,我想应该是可以的,但是能不能从30行精简为10行甚至5行,我想这不太可能。

因为这个导出合并时会遇到各种情况,比如连续相同的单元格何时合并,空白行如何保证不合并,某空白行区域前和后又如何实现合并等问题。

所以,写这段代码前应该先梳理所有可能的场景包括一些特殊情况,尽其所能罗列所有的情况,这样才能保证在应对各种情形的数据时正常导出。

代码稍后我会放到项目rome里

项目地址:https://github.com/DMinerJackie/rome

对了,导出效果图呈上

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

游戏服务器之数据存档(应用数据引擎redis)

游戏服务器之数据存档:把逻辑服务器的角色数据存档到mysql和redis,分析的是较早前的一个游戏项目的存档处理。有些设计缺点,会提出优化方式。 设计上: 逻辑...

50270
来自专栏ChaMd5安全团队

iOS 11.1.2越狱尝鲜

最近盘古公开了一些漏洞细节,然后大家都在做各种越狱工具,在大佬解决Cydia前,我先分享下自己的吧。 常用的命令行工具基本都备齐...

34650
来自专栏企鹅号快讯

入门干货之用DVG打造你的项目主页-Docfx、Vs、Github

由于这三项技术涉及到的要点以及内容较多,希望大家有空能自己挖掘一下更多更深的用法。 0x01、介绍 VS,即VS2017以及以上版本,宇宙最好的IDE,集成了宇...

22660
来自专栏Python小屋

Python截屏扩展库pyscreenshot安装与使用

PIL是非常成熟的Python图像处理扩展库,但只支持Python 2.x,另一个同样功能的扩展库pillow完美支持Python 3.x。然而,这两个库的部分...

30130
来自专栏Jacklin攻城狮

为Next主题添加多说评论系统

几个月前,在好奇心的鼓动下,利用Github Pages和Hexo以及Next主题搭建一个属于自己的个人主站,由于时间伧俗,搭建成功后就没有好好完善一下,可以参...

19140
来自专栏卡少编程之旅

新主题博客诞生之路

35990
来自专栏Python自动化测试

selenium 3.0.1遇到问题的解决方案

迄今为止,我个人认为,selenium是最好使用的web应用程序的自动化测试框架,不仅仅因为它是开源的优势之一,更加重要的是它可以支持的语言比较多,像...

15520
来自专栏WeTest质量开放平台团队的专栏

面向Unity程序员的Android快速上手教程

随着Unity、cocos2dx等优秀跨平台游戏引擎的出现,开发者可以把自己从繁重的Android、iOS原生台开发中解放出来,把精力放在游戏的创作。原来做一款...

16830
来自专栏网站那些事

利用MailChimp发送邮件加调取API开发落地页分享

基于平时爱好关注各类技术社区及众多技术微信号,经常看到很多有用有意思的内容,朋友总是让分享出来,索性就抽空做了个邮件订阅页面

606140
来自专栏DeveWork

WordPress免插件仅代码实现文章浏览次数的方法(1)

在WordPress中为每一篇文章提供个“浏览次数”计数,一来可以间接地给访客一种文章有价值的暗示,二来方便自己获取相关数据(访客的内容偏好等等),三貌似想不到...

24550

扫码关注云+社区

领取腾讯云代金券