云表格的技术(一)

WPS Office是老百姓喜闻乐见的免费产品,虽然广告多了点,但是免费就是killing point。

程序员们喜欢造轮子, 那么,假如要造一个WPS 表格的轮子,可能面临的问题有哪些呢?借着移动互联网的春风,不妨从mobile版本的WPS 表格入手。

View层:

显然,表格的view是一个formal的二维结构,iOS里,有个component叫UICollectionView;Android里,RecyclerView+GridLayoutManager就能搞定。

但是,真的就这么简单吗?且慢!首先,真的是一个formal的二维结构吗?并不是。我们没有考虑合并单元格。其次,即使是二维结构,现有的组件能够满足条件吗?单身程序员可以打发时间试一试,结果肯定会让你失望的。在屏幕里单元格个数增长后,scroll的性能无法接受,更不谈zoom的性能啦!

那么真正的解决方案该如何呢?大胆猜测,整个worksheet必定是个纯定制的组件,从最底层的绘制开始定制,每个单元格都是一笔一笔绘制出来的!乖乖的从iOS的UIView drawRect和Android View的onDraw开始造轮子吧!什么!你已经是定制组件的老司机啦!没关系!你知道表格可以冻结行列吗?老司机可以钻研一下在冻结行列的情况下,滚动行为是怎样!什么!老司机觉得这也是小case!没问题!scroll的行为和性能解决啦,可以尝试一下在手机上zoom操作,这个功能的难度比scroll只高不低啊!(注意注意,不要偷懒截张图再做图片缩放,怎么也得像百度地图一样的基于tiledView吧)!想到这些,WPS表格真是不简单!

另外题外话吐槽,iOS的Quartz2D渲染的硬件加速好像不给力。Android的2D渲染时有硬件加速的,效果不错!

Model层:

每个单元格的属性定义一下即可。如果为了节省存储空间,单元格可能共享的属性可以抽取出来,比如格式相关的属性。

感觉比较难处理的是单元格边框。一个单元格上下左右四个边框。各自有各自的属性。但是!但是!两个相邻的单元格的边框怎么处理?如果各自维护,那么如果CellA1的下边框的属性和CellA2的上边框的属性冲突怎么办?什么?你能保证不会出现这种inconsistent的情况?其实还挺难,改变一个单元格的边框属性,是不是要对相邻的单元格的边框属性一并修改?如果不幸你改变一个很大的合并后的单元格的属性,那么相邻的单元格可能很多哦!

回过头想,单元格的边框属性真的是单元格的属性吗?还是说,单元格和边框是两个平行的概念?这个问题我也不知道啊,可以向WPS的程序员请教!

编辑操作以及撤销Undo/恢复Redo:

这是个宏大的话题,君不见很多讲授使用Excel/WPS的书籍出版,教大家各种技巧。我们抽丝拨茧,把几个元操作提取出来。首先,是文件相关的操作(比如rename);其次是worksheet相关的操作(比如添加/删除一个worksheet);再其次是对worksheet结构数据的操作(比如插/删行/列);最后是单元格数据的操作(值操作,格式操作)。

如此看来,非常简单嘛!真的如此吗?我来提一个概念,就是区域(Cell Range).在WPS中,有很多功能是针对单元格区域的,最典型的就是合并单元格。合并单元格合并的是一个区域的单元格。其他的例子比如表格(Table)功能(对某个单元格区域新建表格), 条件格式功能(对某个单元格区域设定规则并突出显示)。从概念上讲,单元格是退化的区域。

编辑操作必须维护好区域。插/删行/列时,区域需要相应的更新,比如,对于A1:B2区域,如果在B列前做插列操作,则区域应更新为A1:C2。这是简单情形。再比如,对于A1:C3区域,如果想单独取消B2的区域属性,则该3x3区域被挖掉了中心单元格,需要相应更新。

如果将行,列,单元格数据操作称为主操作,那么主操作的执行会产生side effect(更新区域信息)。因为side-effect的存在,撤销/恢复将变得相对复杂,因为不仅需要撤销恢复主操作,还需要将side effect撤销/恢复。

举个例子,用户做删除列B的操作,并将区域B1:C1更新为C1, A2:B2区域更新为A2。之后,用户Undo。显然,UNDO操作是一个插列的操作,同时,该操作将涉及到更新列左区域和列右区域。但是需要注意,一个典型的主动插列操作,通常是只更新一个方向的区域(向左插列/向右插列)。

你可能感兴趣的:(云表格的技术(一))