【摘】给定一些单元格的坐标,如何判断它们是否能合并为一个单元格?

首先,用二维坐标来表示一个单元格,于是单元格的集合就类似于:(1,1) (2,3) (4,2) (3,5)…… 之类的;
然后判断是否在同一行(列),如果是,按横(纵)坐标排序,扫描这一行(列)看看有没有缺失的横(纵)坐标。
然后,如果不是只有一行和一列,就找到左上角和右下角的两个格的坐标,来个二重循环看看中间有没有丢失的单元格。

呵呵,写到这里忽然发现其实蛮简单的,而且第一种情况可以合并到第二种情况里面。
============================================================================
泡饭的意思是:
只有选中的单元格构成一个完整的矩形时才能合并?
按这个思路的话
有简便的判断方法的应该
因为被选中的单元格只会出现一次

第一次扫描
得到
行的范围 R_Min R_Max
列的范围 C_Min C_Max
这时可以简单判断下单元格数目是否等于(R_Max-R_Min+1)*(C_Max-C_Min+1)

第二次扫描
统计各行(或列)的单元格数目是否等于C_Max-C_Min+1(或R_Max-R_Min+1)

----------------------------------------------------------------------------
好方法!如果这样的话貌似只需要一次扫描就够了,为什么还要搞第二次扫描?
----------------------------------------------------------------------------
因为需要确定范围嘛
一遍也行,但是得有类似HASH表的东东
----------------------------------------------------------------------------
不用 Hash 吧?
1、找到左上角的坐标(x1, y1);
2、找到右下角的坐标(x2, y2);
3、看总数是否等于(x2-x1+1)(y2-y1+1);
问题解决。
----------------------------------------------------------------------------
那样的话,应该找4个点吧?
因为选中的不一定是矩形
最左,最右,最上,最下
然后计算点数是不是等于面积
============================================================================

定义一个列表,存放当前sheet的所有合并的单元格,合并单元格用Rect来描述就可以了。
----------------------------------------------------------------------------
我建议还是树形结构比较好,主要是树形结构扩展形要好的多。如果象headzg(head)   所说的那样做,数据量小的情况下还可以应付,如果数据量大一些,恐怕就应付不来了。而且如果用树形结构,每一个Cell的类型都不可以不同,也就是有图片的Cell,字符串的Cell,还有Ole的。
----------------------------------------------------------------------------
楼上2位错了。用树必须要保有一个根,难道用物理位置为(1,1)的节点作为根?
当前sheet的所有cell是平等的,为什么要使用存在隐含父子关系的树型结构。

我以前做合并单元格就是使用grid,用rect描述合并的单元格,在基本rect上使用DECORATOR(装饰)就可以快速扩展cell类型。
至于因此而产生的数据量的问题,用FLYWEIGHT(享元)的设计模式可以轻松搞定。
----------------------------------------------------------------------------
树的根应代表所有网格合并后的结果,如果(1,1)是一孤立的网格,则它只是树的一个叶.这和用四叉树来表示图像的原理类似,但不完全相同,后者不容许合并.`

----------------------------------------------------------------------------
HV链表,在十字链表基础上自己发明的。
专门用来对付象Excel这种数据结构。
一定要用链表,不然表格一旦大了会把内存耗光,当然小表格就不用了。
----------------------------------------------------------------------------
我的想法也是用链表
但是链表具体如何链接呢
比如说要合并下面的单元格
a   b   c
e   f   g
是让a指向c和e表明合并的大小
还是让b   c   e   f   g   都指向a表明要合并到此单元格?
----------------------------------------------------------------------------
若你使用链表,则不应更改任何abcefg的指针,而应该创建一个新的区域,覆盖这六个单元格。因为你如果更改了指针,拆分时将无法回退。
----------------------------------------------------------------------------
干嘛要用树结构,直接使用一个附加的链表不就OK了!
链表的每一个节点就是一个合并了的单元格的所有基本单元的集合(链表,数组均可)。

无论显示还是选中和编辑,都要搜索这个链表,以确定当前的基本单元格是否被合并过。

为了加快速度,可以把上面的链表改成数组或Map(可以按照键值快速访问的数据结构),然后新建一个Map,其Key为所有被合并过的基础单元格,其Value为合并后的单元格所存储的位置。
----------------------------------------------------------------------------
zzwu(未名)
考察以下的6*10矩阵:

      |     0   1   2   3   4   5   6   7   8   9
--------------------------
  0   |     .   .   .   .   e   e   e   .   .   .
  1   |     .   a   a   a   .   .   .   c   c   .
  2   |     .   a   a   a   b   b   .   c   c   .
  3   |     .   a   a   a   b   b   .   c   c   d
  4   |     .   .   .   b   b   b   .   .   d   d
  5   |     .   f   .   .   .   .   .   .   .   .

每个矩阵用左上角的坐标x,y及矩阵的宽度w和高度h四个参数(x,y,w,h)来表示,则有:
Ma=(1,1,3,3)
Mb=(3,2,3,3)
Mc=(7,2,2,3)
Md=(8,3,2,2)
Me=(4,0,3,1)
Mf=(1,5,1,1)

而树是:

Mabcsef   +---   Mab   +----   Ma   =(1,1,3,3)
                |                 |----   Mb   =(3,2,3,3)
                |
                |
                +---   Mcd   +----   Mc   =(7,2,2,3)
                |                 |----   Md   =(8,3,2,2)
                |
                +----   Me   =(4,0,3,1)
                |
                |----   Mf   =(1,5,1,1)
为了减少矩阵数目,在以上表示中,允许相邻矩阵有相交的元素,这时,相交部分的元素由前者来规定.
----------------------------------------------------------------------------
那么你考虑过2个以上矩形相交的情况么?
单元格合并后为不规则形状是否有必要呢?
----------------------------------------------------------------------------
合并单元格,还要让它不规则?
恐怕真实世界中还没有这个需求吧!

另外,请教未明兄:
用户点击时我得到了鼠标坐标,如果用树结构,
该如何确定选中的是哪一个单元格?

我把链表改成Map的原因就在于此,先确定当前选中的基础单元格,
(根据各列列宽和各行行高进行计算),
再从Map中找出是否合并,以及合并到了哪里,
于是将选中单元格亮显。
计算:
1、行高累计,
2、列宽累计,
3、Map查询
4、显示单元格。
----------------------------------------------------------------------------
wpltt(NullpointExcept)
不知道   zzwu(未名)   凭什么可以那样的划分树,就拿ab两个区域来说,你为什么认为a和b是同一个级别的呢?
另外,用你的树,不但增加了数据结构的复杂程度,而且遍历算法就一定比散列表快?
再另外,因为拆分时直接回复到原始状态,所以不需要a和b的单独存在,只要有ab的存在就够了,a、b的叶子结点毫无用处,知会增加无用对象的数量
因为单元格的合并不是被destroy,而是被covered,所以无论连表还是map都没有问题。
----------------------------------------------------------------------------
zzwu (未名)

2个以上矩形相交,则优先级为1,2,3...,也就是单元格(x,y)如属于矩阵1,就是矩阵1,否则才考虑是否属于矩阵2,...
这是受四叉树表示图像的原理的启发提出来的.没有任何其他根据.`
----------------------------------------------------------------------------
to wpltt(NullpointException)  
如果单元格要无限拆分下去呢?你的基础单元格能拆分吗?
----------------------------------------------------------------------------
bfbd(八风不动)
拆分基础单元格可以看做是插入新的航和列。
这个操作需要对Map进行重整,
比较费时。

但我想实际应用中拆分的操作次数要
远远小于
搜索合并格和显示合并格的次数。

所以我们设计的数据结构应优先满足和优化使用最频繁的操作。
如果能照顾的多些更好,
如果不能,就只好先凑合了。
毕竟没有万能的解决方案。
----------------------------------------------------------------------------
wpltt(NullpointExcept)

to zzwu(未名):图像和单元格毕竟是不一样的东西。图像需要对每一个变动作记录,但单元格不用。不知道我说的对不对。

to sliant():我想单元格无限拆分是没有意义的。何况正如bfbd(得失毁誉称讥苦乐-八风不动!)   所说,拆分基础单元格可以看做是插入新的航和列。要知道作软件应该兼顾功能和效率,无限拆分是可能实现的,但是为这个不实用的功能付出代价也要看是否划算。再说了,最强大的表格应该还是excel,excel也没有为无限拆分提供支持。

----------------------------------------------------------------------------
pabulum
多谢各位参与

我现在使用vector存放单元格
然后使用list存放合并单元格的信息,结构为:
int   rowfrom
int   colfrom
int   rowto
int   colto

其实我要实现的功能远没有大家说得复杂
我只是做报表合并的

我要输出显示的时候,从第一个单元格开始,然后向右向下继续输出
如果发现是合并单元格的话,则从list中取信息


因为可能合并单元格会落在换页的位置,
所以这时合并单元格就会拆分成为多个合并单元格显示
所以我现在对于单元格的数据结构中加入一个是否合并的标志

如果合并的话,就从list中查找看落在哪个合并单元格上
然后得到它的合并信息

现在的问题就是查找会比较费时
如果只是(rowfrom,colfrom)首单元格的话,
我可以使用map来存放合并单元格信息,
对应的key就是行数*100+列数(假设列数不超过100),
这样就能极大的缩短查找时间
可是还要看不是处于(rowfrom,colfrom)的单元格属于哪个合并单元格,
那怎么办,
我现在只能用list存储,然后遍历查找了
----------------------------------------------------------------------------
zzwu(未名)
关于   bfbd所提的:
用户点击时我得到了鼠标坐标,如果用树结构,
该如何确定选中的是哪一个单元格

问题的回复:
当然选鼠标点击的单元.
如这个单元格位于不同的矩阵中,我们选择首先找到的矩阵中的单元格,
这正好像我们在平台上,点击相互重叠的窗口时,选择的总是位于顶层的那个窗口的元素一样.

----------------------------------------------------------------------------
wpltt(NullpointExcept)
解决楼主最后的问题:
1输出的时候不用先定位合并单元格,而是只输出基本单元格(当然要注意长宽变化)。
2基本输出完,输出合并单元格进行覆盖,就不用进行查找了。建议在合并单元格里保有被覆盖的基本格指针,这样保证不会有何遗漏。这个保有动作在进行合并的时候完成。

累了,不想再讨论这个问题,还是结了吧。但是无论如何我总觉得,楼上的方法有点复杂了。
因为有重叠时,我坚决认为只有一层的存在已经足够。
----------------------------------------------------------------------------

----------------------------------------------------------------------------

----------------------------------------------------------------------------

----------------------------------------------------------------------------

----------------------------------------------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值