• 四川郎酒股份有限公司获第十二届人民企业社会责任奖年度环保奖 2019-05-13
  • 银保监会新规剑指大企业多头融资和过度融资 2019-05-12
  • 韩国再提4国联合申办世界杯 中国网友无视:我们自己来 2019-05-11
  • 中国人为什么一定要买房? 2019-05-11
  • 十九大精神进校园:风正扬帆当有为 勇做时代弄潮儿 2019-05-10
  • 粽叶飘香幸福邻里——廊坊市举办“我们的节日·端午”主题活动 2019-05-09
  • 太原设禁鸣路段 设备在测试中 2019-05-09
  • 拜耳医药保健有限公司获第十二届人民企业社会责任奖年度企业奖 2019-05-08
  • “港独”没出路!“梁天琦们”该醒醒了 2019-05-07
  • 陈卫平:中国文化内涵包含三方面 文化复兴表现在其中 2019-05-06
  • 人民日报客户端辟谣:“合成军装照”产品请放心使用 2019-05-05
  • 【十九大·理论新视野】为什么要“建设现代化经济体系”?   2019-05-04
  • 聚焦2017年乌鲁木齐市老城区改造提升工程 2019-05-04
  • 【专家谈】上合组织——构建区域命运共同体的有力实践者 2019-05-03
  • 【华商侃车NO.192】 亲!楼市火爆,别忘了买车位啊! 2019-05-03
    • / 41
    • 下载费用:30 金币  

    重庆时时彩个位遗漏: 一种表格模型操作的方法.pdf

    关 键 词:
    一种 表格 模型 操作 方法
      专利查询网所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
    摘要
    申请专利号:

    CN201010115817.5

    申请日:

    2010.03.01

    公开号:

    CN102193782A

    公开日:

    2011.09.21

    当前法律状态:

    终止

    有效性:

    无权

    法律详情: 未缴年费专利权终止IPC(主分类):G06F 9/44申请日:20100301授权公告日:20140409终止日期:20160301|||授权|||实质审查的生效IPC(主分类):G06F 9/44申请日:20100301|||公开
    IPC分类号: G06F9/44; G06F17/24 主分类号: G06F9/44
    申请人: 北京中企开源信息技术有限公司
    发明人: 贾培宽; 杨文军
    地址: 100176 北京市经济技术开发区西环南路18号C座301室
    优先权:
    专利代理机构: 北京派特恩知识产权代理事务所(普通合伙) 11270 代理人: 张颖玲;王黎延
    PDF完整版下载: PDF下载
    法律状态
    申请(专利)号:

    CN201010115817.5

    授权公告号:

    |||102193782B||||||

    法律状态公告日:

    2017.04.19|||2014.04.09|||2011.11.23|||2011.09.21

    法律状态类型:

    专利权的终止|||授权|||实质审查的生效|||公开

    摘要

    本发明提供了一种表格模型操作方法,包括:a、视图层获得用户对表格模型所展现的表格的操作,及所述操作涉及的表格参数;b、由算法模型层根据所述操作调用所述操作对应的算法模型,对表格模型执行对应的算法操作,所述算法操作中使用步骤a所获得的表格参数;c、视图层将执行所述算法操作后的表格模型进行展现。通过本发明,可以实现对表格开发中对表格模型的操作。

    权利要求书

    1.一种表格模型操作方法,其特征在于,包括:a、视图层获得用户对表格模型所展现的表格的操作,及所述操作涉及的表格参数;b、由算法模型层根据所述操作调用所述操作对应的算法模型,对表格模型执行对应的算法操作,所述算法操作中使用步骤a所获得的表格参数;c、视图层将执行所述算法操作后的表格模型进行展现。2.根据权利要求1所述的方法,其特征在于,所述表格模型由下述定义:用于定义单元格数量的行数属性rowNum、列数属性columnNum;用于定义表格外观的属性constraint;用于存储单元格的单元格容器属性cells、用于存储行的行容器属性rows、用于存储列的列容器属性columns;用于设置是否显示行首的属性showRowHead、是否显示列首的属性showColumnHead;所述单元格由下述属性定义:所属表格的属性table、用于定义单元格外观的属性constraint、跨行数属性rowSpan、跨列数属性columnSpan、用于设置单元格显示状态的是否虚格的属性isPhantom、占据者属性holder。3.根据权利要求2所述的方法,其特征在于,步骤a所述操作包括:合并单元格;步骤a所述表格参数包括:表示选择的所有单元格列表参数selectedList;步骤b所述算法操作包括:ba1、判断所述选择的所有单元格列表的区域是否为一个矩形,确定是否允许合并;ba2、若允许合并,则进行合并操作,包括:将区域内左上角第一个单元格宽高放大到整个区域,跨行数设为区域纵向单元格数,跨列数为区域横向单元格数;其它单元格设为虚格;ba3、合并后,判断某行除行首之外其它单元格全部为虚格时,删除此行;判断某列除列首之外其它单元格全部为虚格时,删除此列。4.根据权利要求3所述的方法,其特征在于,判断所述所有单元格列表的区域是否为一个矩形的步骤包括:判断是否满足等式:selectedCellCount=(maxRowId-minRowId+1)×(maxColId-minColId+1);其中,selectedCellCount为所述区域内所有单元格数量,maxRowId为所选区域最大行号,minRowId为所选区域最小行号,maxColId为所选区域最大列号,minColId为所选区域最小列号。5.根据权利要求3所述的方法,其特征在于,步骤a所述操作包括:拆分单元格;步骤a所述表格参数包括:表示当前所选的指定要拆分的单元格参数currentCell;表示要拆分的行数n,表示要拆分的列数m;步骤b所述算法操作包括:bb1、对于所选单元格是表格构建时的原始单元格:将currentCell高度设为原高度值的1/n取整,宽度设为原宽度值的1/m取整,设置循环插入行、循环插入列;循环遍历新插入行,其间遍历每行的所有单元格,将列号不在当前列号至当前列号加m-1之间的单元格设为虚格,其holder属性按如下设置:判断在当前行范围内和其列号相等的单元格为实格时,holder属性设为此实格,否则设为此实格的占据者,判断hasChangedCells容器不含有此holder属性指向的单元格时,将此holder属性的单元格的跨行数应设为原跨行数+n-1;循环遍历新插入的列,其间遍历每列的所有单元格,将行号不在当前行号至当前行号加n-1之间的单元格均设为虚格,其holder属性按如下设置:判断在当前列范围内和其行号相等的单元格为实格时,则占据者设为此实格,否则设为此实格的占据者,判断hasChangedCells容器不含有此holder属性指向的单元格时,将此holder属性单元格的跨列数设为原跨列数+m-1;bb2、对于所选单元格是复合单元格:设临时变量:lastHeight=当前单元格高度-当前行行首高度,lastRowSpan=当前单元格跨行数-1,lastWidth=当前单元格宽度-当前列列首宽度,lastColSpan=当前单元格跨列数-1;当lastRowSpan或lastColumnSpan等于0时,按bb1步骤进行拆分行或列;当lastRowSpan和lastColumnSpan不等于0时,依次循环遍历当前单元格横向和纵向所跨所有单元格,对这些单元格执行以下操作:均设为实格,holder属性设为null;判断如果其所在行不是拆分后这些行的最后一行,高度设为相对应的行首高度,跨行数设为1,且,如果其所在列是当前列,则将lastHeight设为lastHeight减去此高度,将lastRowSpan设为lastRowSpan减去1;否则高度设为lastHeight,跨行数设为lastRowSpan;判断如果其所在列不是拆分后这些列的最后一列,宽度设为相对应的列首宽度,跨列数设为1,且,如果其所在行是当前行,则将lastWidth设为lastWidth减去相对应的列首宽度,将lastColSpan设为lastColSpan减去1;否则宽度设为lastWidth,跨行数设为lastColSpan。6.根据权利要求3所述的方法,其特征在于,步骤a所述操作包括:拖动单元格边线改变行高列宽;步骤a所述表格参数包括:所选单元格、所拖动线是单元格的上、下、左、右哪一条边线以及拖动偏移量;其中边线参数名定义为position,其值对应上、下、左、右分别为常量TOP=-1、BOTTOM=1、LEFT=-2、RIGHT=2;拖动偏移量参数名定义为delta,向下、向右拖动时,拖动delta为正数,向上、向左拖动时,delta为负数;步骤b所述算法操作包括:bc1、声明整型变量RowId、ColumnId,用于把所选单元格行号赋于RowId、列号赋于ColumnId;声明整型变量cellIndex,用于存储格子坐标值;声明整型变量lineIndex,用于存储所拖动线坐标值;声明整型变量span,用于存储单方向跨格子数;声明线性定位器lineLocalizer,用于指向所选单元格所在行或所在列;声明线性定位器toChangeLine,用于指向另一个需变化的行或列;bc2、当position的绝对值等于1时,根据所选单元格行号取得行模型,赋于lineLocalizer;当position的绝对值等于2时,根据所选单元格列号取得列模型,赋于lineLocalizer;bc3、判断position<0时,把lineLocalizer的previous(?)方法返回的线性定位器引用赋于toChangeLine;判断position>0时,把lineLocalizer的next(?)方法返回的线性定位器引用赋于to?ChangeLine;bc4、遍历lineLocalizer、toChangeLine的所有单元格,比较坐标判断哪些单元格外观有变化;遍历过程中对单元格的引用设为iCell;其包括:当position的绝对值等于1时:cellIndex=iCell.getRowId(),lineIndex=2×cellIndex+position,span=iCell.getRowSpan();当position的绝对值等于2时,cellIndex=iCell.getColumnId(),lineIndex=2×cellIndex+position/2,span=iCell.getColumnSpan();判断indexIndex==2×cellIndex-1成立或indexIndex==2×(cellIndex+span-1)+1成立,iCell大小会变化,按照下述步骤改变单元格外观:遍历lineLocalizer范围内所有单元格时,如果position绝对值等于1,改变单元格高度为原高度加delta×position,且如果position=-1,改变单元格左上角y值为原值加delta;如果position绝对值等于2,改变宽度为原宽度加delta×position/2,且如果position=-2改变单元格左上角x值为原值加delta;遍历toChangeLine范围内所有单元格时,如果position的绝对值=1,单元格高度为原高度减delta×position,且position=1如果改变单元格左上角y值为原值加delta;如果position的绝对值=2,单元格宽度为原宽度减delta×position,且如果position=2,改变单元格左上角x值为原值加delta。7.根据权利要求3所述的方法,其特征在于,步骤a所述操作包括:插入行/插入列;步骤a所述表格参数包括:表示当前所选的单元格参数currentCell;表示是否为插入行参数isInsertRow,值为true表示插入行,值为false表示插入列;表示决定在当前单元格之前还是之后插入的参数position,取值为1表示在当前单元格之后插入,为-1表示在当前单元格之前插入;步骤b所述算法操作包括:bd1、声明线性定位器:currentLine和newLine;声明单元格模型变量currentHolder,用来存放可能即将作为占据者的单元格;声明整型变量currentId,用来存放行号或列号;声明容器newCells,用于临时存放新创建的单元格;声明容器allCells,用于供删除过程中存放转移单元格,初始化为空容器;声明整型变量bandwidth,用于存放当前行首高度或当前列列首宽度;声明容器hasChangedCell,用来存放本操作已经改变的单元格,防止二次改变,初始化为空容器;bd2、当插入行时,isInsertRow为true,取当前行行号赋于currentId,根据currentId取得当前行赋于currentLine,创建新的空行赋于newLine;当插入列时,isInsertRow为false,取当前列列号赋于currentId,根据currentId取得当前列赋于currentLine,创建新的空列赋于newLine;bd3、遍历currentLine的各单元格,遍历过程中设各单元格为cellInLine,创建一个宽高与cellInLine相等,跨行数、跨列数均为1的新单元格newCell;bd4、newCell按如下步骤设置:当isInsertRow为true时:如果cellInLine为跨列不跨行的单元格,则将newCell跨列数设为与cellInLine跨列数相等,并将newCell赋于currentHolder;如果cellInLine为跨行复合单元格且hasChangedCells不包含cellInLine,则把cellInLine跨行数加1,高度为原高度加bandwidth,并把cellInLine追加到hasChangedCells;如果cellInLine为虚格,则把newCell同样设为虚格,如果其占据者属性所指单元格为跨行复合单元格,newCell占据者属性设为cellInLine占据者属性,且如果hasChangedCells不包含cellInLine,则把其占据者属性所指单元格跨行数加1,高度为原高度加bandwidth;如果其占据者属性所指单元格为非跨行复合单元格,newCell占据者属性设为currentHolder;当isInsertRow为false时:如果cellInLine为是跨行不跨列的单元格,则将newCell跨行数设为与cellInLine跨行数相等,并将newCell赋于currentHolder;如果cellInLine为跨列复合单元格且hasChangedCells不包含cellInLine,则把cellInLine跨列数加1,宽度为原宽度加bandwidth,并把cellInLine追加到hasChangedCells;如果cellInLine为虚格,则把newCell同样设为虚格,如果其占据者属性所指单元格为跨列复合单元格,newCell占据者属性设为cellInLine占据者属性,且如果hasChangedCells不包含cellInLine,则把其占据者属性所指单元格跨列数加1,宽度为原宽度加bandwidth;如果其占据者属性所指单元格为非跨列复合单元格,newCell占据者属性设为currentHolder;bd5、在循环中依次把newCell加入到newCells;bd6、按如下步骤把所有新创建的单元格加入表格的适当位置:声明容器allCells;声明整型变量n=0,o=0,a=0;改变行数或列数,并把新行或新列加入到行容器或列容器:如果isInsertRow为true,将表格rowNum属性设为rowNum+1,将newLine加入到表格rows属性的currentId+position位置,否则,将表格columnNum属性设为columnNum+1,将newLine加入到表格columns属性的currentId+position位置;新单元格加入表格cells属性,且用两层循环控制单元格的加入位置:外层循环控制行,用i作循环变量,初值为0,步长为1,终止条件为i<rowNum,内层循环控制行内单元格,对应各列中的单元格,用j作循环变量,初值为0,步长为1,终止条件为:j<columnNum;在内循环中:当isInsertRow为true时,如果i==currentId+position,则取得newCells第n个单元格,追加到allCells,并将n设为n+1,否则取得表格的cells属性容器中第o个单元格,追加到allCells,并将o设为o+1;当isInsertRow为false时,如果j==currentId+position,则取得newCells第n个单元格,追加到allCells,并将n设为n+1,否则取得表格的cells属性容器中第o个单元格,追加到allCells,并将o设为o+1;循环结束后把allCells容器赋于表格cells属性,完成把新增单元格加入到表格cells属性。8.根据权利要求3所述的方法,其特征在于,步骤a所述操作包括:删除行/删除列;步骤a所述表格参数包括:表示当前所选的单元格参数currentCell;表示是否为删除行参数isDeleteRow,值为true表示删除行,值为false表示删除列;步骤b所述算法操作包括:be1、声明线性定位器currentLine,用来指定要删除的行或列;声明整型变量currentRowId、currentColumnId,用来存放行号或列号;声明容器hasChangedCells,用来存放本操作已经改变的单元格,防止二次改变,初始化为空容器;声明整型变量bandwidth,用来存放当前行首高度或当前列列首宽度;声明容器allCells,用来删除过程中存放转移单元格,初始化为空容器;be2、当删除行时,isInsertRow为true,取当前行行号赋于currentRowId,当前列列号赋于currentColumnId,根据currentRowId取得当前行赋于currentLine;当删除列时,isInsertRow为false取当前行行号赋于currentRowId,当前列列号赋于currentColumnId,根据currentColumnId取得当前列赋于currentLine;be3、将bandwidth置为currentLine.getBandwidth();遍历currentLine的各单元格,遍历过程中设当前访问单元格为cellInLine;当isInsertRow为true时:如果cellInLine为跨行复合单元格,则取得行号为currentRowId+1,列号为currentColumnId的单元格,设此单元格为replaceCell,如果hasChangedCells不包含replaceCell,则将replaceCell做以下改变:isPhantom属性置为false,rowSpan置为cellInLine的rowSpan-1,高度置为cellInLine的高度减去bandwidth;columnSpan置为cellInLine的columnSpan,宽度置为cellInLine的宽度,并把realCell追加到hasChangedCells;循环遍历行号大于currentRowId,且小于currentRowId+replaceCell跨行数,列号大于等于currentColumnId且小于currentColumnId+replaceCell跨列数的所有单元格将它们的占据者属性置为replaceCell;如果cellInLine为虚格,取得其占据者属性指向的单元格,设为realCell,如果realCell为跨行复合单元格,且hasChangedCells不包含realCell,则把realCell跨行数置为原跨行数减1,高度置为原高度减bandwidth,并把realCell追加到hasChangedCells;当isInsertRow为false时:如果cellInLine为跨列复合单元格,则取得行号为currentRowId,列号为currentColumnId+1的单元格,设此单元格为replaceCell,如果hasChangedCells不包含replaceCell,则将replaceCell做以下改变:isPhantom属性置为false,rowSpan置为cellInLine的rowSpan,高度置为cellInLine的高度;columnSpan置为cellInLine的columnSpan-1,宽度置为cellInLine的宽度减去bandwidth,并把realCell追加到hasChangedCells;循环遍历行号大于等于currentRowId,且小于currentRowId+replaceCell跨行数,列号大于currentColumnId且小于currentColumnId+replaceCell跨列数的所有单元格将它们的占据者属性置为replaceCell;如果cellInLine为虚格,取得其占据者属性指向的单元格,设为realCell,如果realCell为跨列复合单元格,且hasChangedCells不包含realCell,则把realCell跨列数置为原跨列数减1,宽度置为原宽度减bandwidth,并把realCell追加到hasChangedCells;be4、循环遍历结束后,按照下面步骤把currentLine范围内的单元格删除:用两层循环控制单元格删除哪些单元格:外层循环控制行,用i作循环变量,初值为0,步长为1,终止条件为i<rowNum,内层循环控制行内单元格,对应各列中的单元格,用j作循环变量,初值为0,步长为1,终止条件为:j<columnNum;在内循环中:当isInsertRow为true时,如果i不等于currentRowId,则取得表格的cells属性容器中第i×columnNum+j个单元格,追加到allCells;当isInsertRow为false时,如果j不等于currentColumnId,则取得表格的cells属性容器中第i×columnNum+j个单元格,追加到allCells;循环结束后把allCells容器赋于表格cells属性,完成从表格cells属性删除currentLine范围内的单元格;改变行数或列数,并把当前行或当前列从行容器或列容器中删除:如果isInsertRow为true,将表格rowNum属性设为rowNum-1,将currentLine从表格rows属性中删除,否则,将表格columnNum属性设为columnNum-1,将currentLine从表格columns属性中删除。9.根据权利要求3所述的方法,其特征在于,步骤b所述算法操作还包括表格绘画算法模型,包括:表格初始化算法子模型:用两层循环控制行、列、单元格的初始化,外循环中生成行并加入行容器,循环变量范围:0<=外循环变量<表格行数;内循环中,判断如果是第一行则生成列并加入列容器,循环变量范围:0<=内循环变量<表格列数;单元格在内循环中生成,单元格左上角坐标x值=(单元格宽度+水平表格边线间距)×内循环变量+水平表格边线间距;单元格左上角坐标y值=(单元格高度+垂直表格边线间距)×外循环变量+垂直表格边线间距;表格高度=(单元格高度+垂直表格边线间距)×表格行数+重直表格边线间距;表格宽度=(单元格宽度+水平表格边线间距)×表格列数+水平表格边线间距;整个表格重画算法子模型:重画之前声明一个空容器toShowCells,用于存放需要显示的单元格即实格;先取得第一行,把它赋于row变量引用,设置循环遍历所有行,跳出循环条件为row.hasNext()为false,在循环中通过row.createIterator(),遍历行内所有单元格,设置单元格的大小和位置,如果单元格为实格则加入到toShowCells容器;当前行遍历结束,把row.next()赋于row来访问下一行的所有单元格,直到row.hasNext()为false结束编历;将toShowCells传递给视图层显示;部分表格元素重画算法子模型:接收两个参数:线性定位器lineLocalizer、一个移动偏移量delta;设置循环遍历lineLocalizer以后的所有线性定位器,用lineLocalizer.hasNext()作为终止循环条件,在循环中设置lineLocalizer=lineLocalizer.next(),用lineLocalizer.createrIterator()创建迭代器访问其范围内所有单元格,判断如果lineLocalizer.getDirection()等于0,则单元格左上角坐标y值设为原值加delta,否则单元格左上角坐标x值设为原值加delta;循环结束后,判断如果lineLocalizer.getDirection()等于0,则表格外观总高度设为原值加delta,否则表格外观总宽度设为原值加delta。

    说明书

    一种表格模型操作的方法

    技术领域

    本发明涉及表格设计技术,特别是指一种表格模型操作的方法。

    背景技术

    随着计算机技术的越来越快的发展,应用软件也取得了飞速发展。在数据和文本展示方面,表格的作用不言而喻,能清楚明了、直观地说明情况,省去很多文字说明。在表格应用越来越广泛的背景下,Dreamweaver,Excel,Word等商业软件都提供了很强的表格功能。对于这些软件中的表格,用户只能应用其功能,很难在软件开发中嵌入或定制其功能。

    不难理解,在各种软件的开发中,在视图层展现业务数据,表格工具是一个必不可少的模型组件(如:表单,报表中就离不开表格),因此某些领域的软件开发,不可避免要加入表格开发,根据业务需要开发和定制适用于相应领域的表格功能。

    但是目前公开的表格开发的解决方案极少,有的只是提到了一些浅显的设计,而有的也只是提出了一点想法,并没有真正的可以遵循的用来开发出一个表格工具的完整方案,就这一点来说,表格开发模型领域几乎属于空白。

    发明内容

    有鉴于此,本发明的主要目的在于提供一种表格模型操作方法,用于实现对表格开发中对表格模型的操作。

    为达到上述目的,本发明提供了一种表格模型操作方法,包括:

    a、视图层获得用户对表格模型所展现的表格的操作,及所述操作涉及的表格参数;

    b、由算法模型层根据所述操作调用所述操作对应的算法模型,对表格模型执行对应的算法操作,所述算法操作中使用步骤a所获得的表格参数;

    c、视图层将执行所述算法操作后的表格模型进行展现。

    其中,所述表格模型由下述定义:用于定义单元格数量的行数属性rowNum、列数属性columnNum;用于定义表格外观的属性constraint;用于存储单元格的单元格容器属性cells、用于存储行的行容器属性rows、用于存储列的列容器属性columns;用于设置是否显示行首的属性showRowHead、是否显示列首的属性showColumnHead;

    所述单元格由下述属性定义:所属表格的属性table、用于定义单元格外观的属性constraint、跨行数属性rowSpan、跨列数属性columnSpan、用于设置单元格显示状态的是否虚格的属性isPhantom、占据者属性holder。

    其中,步骤a所述操作包括:合并单元格;

    步骤a所述表格参数包括:表示选择的所有单元格列表参数selectedList;

    步骤b所述算法操作包括:

    ba1、判断所述选择的所有单元格列表的区域是否为一个矩形,确定是否允许合并;

    ba2、若允许合并,则进行合并操作,包括:将区域内左上角第一个单元格宽高放大到整个区域,跨行数设为区域纵向单元格数,跨列数为区域横向单元格数;其它单元格设为虚格;

    ba3、合并后,判断某行除行首之外其它单元格全部为虚格时,删除此行;判断某列除列首之外其它单元格全部为虚格时,删除此列。

    其中,判断所述所有单元格列表的区域是否为一个矩形的步骤包括:

    判断是否满足等式:selectedCellCount=(maxRowId-minRowId+1)×(maxColId-minColId+1);

    这里,selectedCellCount为所述区域内所有单元格数量,maxRowId为所选区域最大行号,minRowId为所选区域最小行号,maxColId为所选区域最大列号,minColId为所选区域最小列号。

    由上可以看出,本发明具有下述有益效果:

    表格元素管理和访问方式方便:传统表格概念中行包含的单元格与列包含的单元格是重叠的,不仅把单元格既存于行又存于列难以正确表达表格结构,且把单元格存于行,则对于列的操作需先取得每行,再取得其中位于该列位置的单元格来曲折访问,极不方便。而本发明表格模型中将所有单元格存储于表格的单元格属性容器中,所有行存储于行容器,所有列存储于列容器,单元格和行、列没有直接关系,行与列的作用是定位、选择、遍历指定范围内的单元格;单元格数量及排列位置是由数值型属性行数、列数确定。访问单元格极为方便。

    提高了行列操作代码重用度:基于表格元素管理方法和对行列操作的过程步骤一致性,本发明采用了线性定位器概念同化行、列操作过程,与分别处理行、列操作方法相比,提高了代码重用度,提高了开发效率。

    合并单元格操作的实现方法的高效性:合并单元格要求所有被选择的单元格,能组成一个完整的矩形且所有被选的单元格均在此矩形区域内才允许合并。现有技术要验证所选区域是不是矩形会遍历所选的所有单元格,逐个判断是否两两相邻组成矩形。本发明避免了复杂的遍历判断,提供一种高效简捷的实现方法。

    拖动单元格边线改变行高列宽操作的实现方法降低了问题复杂度:在拖动单元格边线改变行高列宽操作中,如果所有单元格均为原始单元格,则操作行为很简单,将涉及到的每个单元格做同样变化即可。但实际操作中要考虑多种情况,如涉及到的单元格是虚格,就要取得其占据者引用的复合单元格,要确定所拖动的边线与此复合单元格位置关系,才能决定这个复合单元格大小是否要改变。位置关系的确定,需要做许多判断和比较。本发明提供一种清淅明了的坐标模型算法。省去过多的中间判断,提高运行性能。降低问题复杂性。

    解决方案的开发语言、视层技术无关性:本发明表格模型的实现是与开发语言、视层技术关联不紧。理论上采用本发明的表格模型组织结构和表格操作实现方法,可以与任何支持表格的视图层技术配合使用。采用什么开发语言及视图技术实现,由表格开发者决定,只需根据开发语言、视图技术特点做少量调整即可开发出表格产品。目前本发明已经使用java语言,Eclipse平台GEF(Graphical?Editor?Framework)技术已经实现,并且获得较好的效果,使用上灵活方便,实用性强,从而论证了此种方案的可行性。

    解决方案的扩展性:本发明的着重点是表格展现与表格操作方法实现,而对表格元素的线条颜色和背景颜色、及表格单元格作为容器放置UI(用户界面)组件的功能都没有提及。但基于本发明的解决方案可以很自然地增加这些属性和功能。如用选择行首的方式选择行,对行内所有单元格的颜色作集体改变;或让单元格继承容器特征以添加嵌入UI组件的功能。

    附图说明

    图1为表格模型操作的流程图。

    图2为确定是否为矩形以确定是否可以进行合并的流程图。

    图3为执行合并操作的流程图。

    图4为拆分单元格算法模型的第一种算法操作流程。

    图5为拆分单元格算法模型的第二种算法操作流程。

    图6为示出的拖动单元格边线改变行高列宽算法模型的操作流程图。

    图7为判断单元格大小、位置是否发生变化的流程图。

    图8为插入行/插入列算法模型的操作流程图。

    图9为插入行单元格处理流程图。

    图10为插入列单元格处理流程图。

    图11为删除行/删除列算法模型的操作流程图。

    图12为删除行处理流程图。

    图13为删除列处理流程图。

    图14为表格绘画算法模型的操作流程图。

    具体实施方式

    本发明属表格设计类,通过模型与算法,提供一种应用抽象的数学模型来定位、操作表格中的元素的方法。是一种表格开发中表格的表示、操作、存储的实现方法。表示和存储即为模型,为日常应用中所指的表格元素的表示,如单元格、行、列、行数、列数等及内在辅助信息的表示。操作的实现即为算法,包括:插入/删除行、插入/删除列、合并单元格、拆分单元格、拖动单元格边线改变行高、列宽,以及原子化操作:选定、定位单元格;得到单元格所在行、所在列;得到单元格宽高、是否能被合并;得到单元格上下左右的相邻单元格;得到指定行/列的所有单元格等。通过本发明可以快速地开发出功能强大、高性能的表格设计器,用以设计表单、报表等。

    下面对本发明原理进行介绍:本发明提供了表格模型,通过该表格模型可以建立其对应的表格(模型外观),当用户操作表格时,相应的对表格模型的操作包括以下步骤:

    a、由视图层获得用户对表格的操作,及所述操作涉及的表格参数。具体来说,视图层用于获得用户对模型外观即表格的操作,并将操作及相应参数传给对应的算法模型层。

    b、由算法模型层根据所述操作调用所述操作对应的算法(或称为对应的业务逻辑模型)模型,对表格模型进行对应的算法操作,所述业务算法操作中使用步骤a所获得的表格参数。

    其中,后文将对各个算法模型、各个表格模型进行详细介绍。算法模型是为了简化复杂算法而设定的虚拟模型。表格模型包括与视图展现层存在一对一的映射关系的表观模型,如表格、单元格(包括行首、列首和普通单元格),以及不在视图层产生映射应用中又存在的辅助模型,如行、行内单元格迭代器、列、列内单元格迭代器,辅助模型用于理清各表观模型间的关系,及定位、选定线条范围内的单位元素。

    c、视图层根据操作后的表格模型,对表格模型的外观进行展现。

    本发明还相应的提供了一种表格模型操作系统,包括:

    视图层,用于获得用户对表格的操作,及所述操作涉及的表格参数;以及根据操作后的表格模型,对表格模型进行展现;

    算法模型层,用于根据所述操作调用所述操作对应的算法模型,对表格模型进行对应的算法操作,所述算法操作中使用步骤a所获得的表格参数。

    表格模型,提供了表格的数学描述,定义了表格的不同属性,后文将详细描述。

    算法模型,用于提供对表格模型操作的实现算法,后文将详细描述。

    下面对本发明的表格模型、算法模型及算法操作进行详细说明:

    首先对本发明所采用的表格模型(table)进行介绍:

    如下表1示出了表格模型的属性定义,通过该属性定义可确定表格的位置和大?。浩涫粜悦枋霭ㄐ惺?、列数、外观、单元格容器、行容器、列容器、显示行首、显示列首等,具体如下:

    表1

    由上,本发明表格模型中将所有单元格存储于cells(单元格)容器,所有行存储于rows容器,所有列存储于columns容器,单元格和行、列没有直接关系,行与列的作用是定位、选择、遍历指定范围内的单元格;单元格数量及排列位置是由数值型属性行数rowNum、列数columnNum确定。

    初始状态下同一行内的单元格高度相等,同一列单元格(单元格属性将在后文描述)的宽度相等,因此由单元格高度、宽度确定行高、列宽。在执行单元格合并、拆分操作(将在后文描述)后,所操作的单元格高度、宽度有变化,同一行的单元格高度有可能不相等,同一列的单元宽度也可能不相等。

    在本发明表格模型中加入了行首、列首模型概念:每行第一个单元格作为行首;每列每一个单元格作为列首。行首、列首不参与合并、拆分单元格。在设计表格时,有些情况需要有行首、列首,有些情况则不需要,它们的作用主要是作标题和标识行列的ID、位置、大小特征。行首、列首模型大大方便了取得不规则表格的行高、列宽的操作。比如某行中只有跨行复合单元格和虚格(复合单元格及虚格概念参考下文单元格模型描述)时,如果没有行首作参考,要取得计算和取得行高是很繁琐的。因此,模型中设定了行首、列首概念,对于表格设计时是否涉及到行首、列首,设置了显示行首、显示列首的布尔标识属性来控制行首、列首显示与否。

    如下表2为表格模型中的单元格模型:

    其属性定义包括:所属表格、外观(包含宽度、高度、左上角坐标点x值、左上角坐标点y值、边线宽度)、跨行数、跨列数、是否虚格、占据者,具体如下:

    ??columnSpan
    ??int
    ??跨列数



    ??isPhantom
    ??boolean
    ??是否虚格



    ??holder
    ??单元格模型
    ??占据者



    表2

    在合并和拆分单元格操作中,会改变单元格状态。为了便于对本发明的描述,将不同状态的单元格加以分类、命名。单元格按照单元格的显示状态分为实单元格和虚单元格;按单元格占据位置多少分为原始单元格和复合单元格。下面进行介绍:

    实单元格和虚单元格:

    在表格初始化状态,所有单元格均为实单元格,特征是isPhantom(是否虚格)属性为false,holder(占据者)属性为null;在合并单元格后,所选区域左上角第一个单元格放大到整个合并区域,它仍为实格,而被合并的其它单元格,变为不显示隐藏状态,它们即为虚格。虚格特征:isPhantom属性置为true,holder属性为所选区域左上角第一个单元格的引用。虚格不参与视图层显示,传递给视图层的表格元素忽略它们。在拆分复合单元格时,变为显示状态的单元格,就又变回了实格。

    设置holder属性的原因:在行列操作时,涉及到的对虚格的操作,因为虚格不显示,其外观的变化应表现为占据其位置的单元格外观的变化,设置holder属性,可以方便地取得该具有holder属性的单元格,避免复杂遍历查找占据其位置的单元格。

    行首、列首是一种特殊的单元格。它们是否为虚格,取决于表1中的showRowHead、showColumnHead属性的值。

    原始单元格和复合单元格:

    在表格初始化状态,所有单元格均为原始单元格,特征为单元格处于显示状态、跨行数和跨列数属性均为1,在合并单元格后,所选区域内左上角第一个单元格放大到整个合并区域,它即为复合单元格。特征为单元格处于显示状态,跨行数为合并时所选区域纵向单元格数,跨列数为合并时所选区域横向单元格数。当拆分复合单元格且单元格的跨行数与跨列数均变为1时,就又变回了原始单元格。

    通过上述表格模型和单元格模型,可以方便的取得单元格,或者指定行、列等,下面简要说明:

    对于表格模型:

    取得指定行指定列的单元格算法:根据行号、列号计算单元格位置序号,通过位置序号从容器中取得单元格:cells.get(rowId×columnNum+columned);

    取得指定行算法:rows.get(roId);

    取得指定列算法:columns.get(columnId)。

    对于单元格模型:

    取得单元格在表格中的位置序号算法:表格使用有序容器存储单元格可以使用得取指定元素位置的方法得到单元格序号:getCellId():table.getCells().indexOf(this);

    取得所在行行号算法:单元格序号除以表格列数取整即为行号:getRowId():getCellId()/table.columnNum;

    取得所在列列号算法:单元格序号除以表格列数取余即为列号:getColumnId():getCellId()/table.columnNum。

    下面对本发明涉及到的辅助模型进行介绍。该辅助模型为线性定位器模型,如下表3示出了该线性定位器模型的定义:

    ??方法名称
    ??描述
    ??作用
    ??getTable()

    ??取得线性定位器本身所属的表格模型

    ??在列操作中方便访问
    ??当前表格
    ??getDirection()

    ??返回方向整型常量:在实现模型中如果
    ??是行返回0;如果是列返回1;
    ??区别行与列

    ??createIterator()


    ??返回一个迭代器,行模型的此方法返回
    ??行迭代器,列模型的此方法返回列迭代
    ??器
    ??用于遍历访问当前定
    ??位器范围内的所有单
    ??元格
    ??next()


    ??返回下一个。行模型返回下一行,列模
    ??型返回下一列。

    ??用于设置循环逐次向
    ??下取得行或向右取得
    ??列
    ??hasNext()

    ??返回是否存在下一个,最后一行和最后
    ??一列返回false,其它行、列返回true
    ??用作结束循环条件

    ??previous()


    ??返回上一个。在实现模型中如果是行,
    ??则返回上一行,如果是列则返回上一列。

    ??用于设置循环逐次向
    ??上取得行或向左取得
    ??列
    ??hasPrevious()

    ??返回是否存在上一个,第一行和第一列
    ??返回false,其它行、列返回true
    ??用作结束循环条件

    ??getBandwidth()

    ??返回带宽,行模型返回行首高度,列模
    ??型返回列首宽度。
    ??用于取得行或列的条
    ??状宽度

    表3

    通过该模型,同化了行操作和列操作,实现行、列模型都实现共性的接口,统一操作行为过程,以提高代码重用度和开发效率。通过该模型,可以实现在插入行、删除行、插入列、删除列操作中,调用此模型可同时满足取得插入位置后面的单元格向下或向右的移动量。

    如下示出了基于上述模型构建的行模型和列模型。

    其中,行模型如下表4所示:

    ??方法名称
    ?描述
    ??getTable()
    ?返回当前表格模型引用
    ??getDirection()
    ?返回方向整型常量0;
    ??createIterator()
    ?返回行迭代器,用于遍历访问所有行内的单元格

    ??next()

    ?返回下一行:从表格行容器中取得序号为当前行号加1的
    ?行
    ??hasNext()

    ?返回是否存在下一行,当前行号加1与表格总行数比较判
    ?断是否为最后一行,最后一行返回false,其它行返回true。
    ??previous()

    ?返回上一行:从表格行容器中取得序号为当前行号减1的
    ?行
    ??hasPrevious()

    ?返回是否存在上一行,当前行号与表格起始行号比较判断
    ?是否为第一行,第一行返回false,其它行返回true。
    ??getBandwidth()
    ?返回行首高度

    表4

    相应的提供了用来实现迭代器接口的行迭代器模型,用来遍历当前表格访问指定行号内的所有单元格。其属性如下表5所示,包括:

    ??属性名称
    ??描述
    ??table
    ??当前表格模型引用
    ??rowed
    ??行号
    ??position
    ??遍历过程中当前单元格位置

    表5

    其方法如下表6所示,包括:

    ??方法名称
    ??描述
    ??构造器

    ??传入当前表格引用和行号,设置position初值为
    ??rowId×table.columnNum
    ??next()

    ??返回table.getCells().get(position),并在返回前把position置为
    ??position加1
    ??hasNext()

    ??如果position小于(rowId+1)×table.columnNum返回true,否则返回
    ??false;

    表6

    其中,列模型如下表7所示:

    ??方法名称
    ?描述
    ??getTable()
    ?返回当前表格模型引用
    ??getDirection()
    ?返回方向整型常量1;
    ??createIterator()
    ?返回列迭代器,用于遍历访问所有列内的单元格
    ??next()

    ?返回下一列:从表格列容器中取得序号为当前列号加1
    ?的列
    ??hasNext()


    ?返回是否存在下一列,当前列号加1与表格总列数比
    ?较判断是否为最后一列,最后一列返回false,其它列
    ?返回true,。
    ??previous()

    ?返回下一列:从表格列容器中取得序号为当前列号减1
    ?的列
    ??hasPrevious()

    ?返回是否存在上一列,当前列号与表格起始列号比较
    ?判断是否为第一列,第一列返回false,其它列返回true。
    ??getBandwidth()
    ?返回列首宽度。

    表7

    相应的提供了实现迭代器接口的列迭代器模型,用来遍历当前表格访问指定列号内的所有单元格。其属性如下表8所示,包括:

    ??属性名称
    ??描述
    ??table
    ??当前表格模型引用
    ??columnId
    ??列号
    ??position
    ??遍历过程中当前单元格位置

    表8

    其方法如下表9所示,包括:

    ??方法名称
    ??描述
    ??构造器
    ??传入当前表格引用和列号,设置position初值为columnId
    ??next()

    ??返回table.getCells().get(position),并在返回前把position置为
    ??position+table.columnNum

    ??hasNext()

    ??如果position小于(table.rowNum-1)×table.columnNum+columnId返
    ??回true,否则返回false;

    表9

    下面对本发明的算法模型及相应的算法操作进行描述,通过算法模型,可以实现对表格模型的操作。

    一、合并单元格算法模型:

    合并单元格指:选中多个单元格,合并为一个大的区域。通常要合并单元格,要求所有被选择的单元格能组成一个完整的矩形且所有被选的单元格均在此矩形区域内才允许合并,并且要考虑所选中的单元格中有可能含有已经执行合并操作的单元格,这里所说的合并是把所选区域内左上角的单元格放大到整个选中区域矩形的大小,其它单元格标识为占位符(隐藏状态)。当整行(整列)合并时,应将合并范围内除第一行(第一列)外的其余行(列)删除,合并范围内的第一行的跨行数(跨列数)设为1。

    该算法模型需要视图层传递过来的参数为:selectedList,表示选择的所有单元格列表。

    该算法模型包括的算法操作为下述步骤:

    判断所选区域是否为一个矩形,确定是否允许合并;

    若允许合并,则进行合并:将区域内左上角第一个单元格宽高放大到整个区域,跨行数设为区域纵向单元格数,跨列数为区域横向单元格数;其它单元格设为虚格;

    合并后,如果某行除行首(第一个单元格)之外,其它单元格全部为虚格,则删除此行;如果某列除列首(第一个单元格)之外,其它单元格全部为虚格,则删除此列。

    其中,上述判断所选单元格构成的区域是否为一个矩形可采用下述算法:

    若所选区域是一个矩形,根据矩形面积计算公式,应满足以下等式:selectedCellCount=(maxRowId-minRowId+1)×(maxColId-minColId+1);

    其中:selectedCellCount为所选区域内所有单元格数量,所选单元格是一个已知集合,因此selectedCellCount为可取得(将在后文描述取得方法),如果所选区域内含有以前合并过的单元格,则取合并前的单元格数,即最小单位的单元格。计算方法为合并前行数与合并前列数相乘之积。maxRowId为所选区域最大行号,minRowId为所选区域最小行号,maxColId为所选区域最大列号,minColId为所选区域最小列号。

    下面对采用上述公式判断是否为矩形的原理进行介绍:假设所选区域是一个矩形,以单元格做最小单位,maxRowId、minRowId、maxColId、minColId就确定了矩形的位置和边长,长为maxColId-minColId+1,宽为(maxRowId-minRowId+1),根据矩形面积计算公式可知,所选单元格数量则为(maxRowId-minRowId+1)×(maxColId-minColId+1)。

    结合上述计算面积公式的等式,则该算法模型的具体算法可描述为:

    判断所选区域是否为一个矩形,以确定是否可以进行合并操作,参见图2示出的确定是否为矩形确定是否可以进行合并的流程,主要包括:将selectedCellCount初值置0,遍历selectedList所有单元格,取得最大行号、最小行号、最大列号、最小列号,遍历过程中如果单元格是复合单元格,则取得合并之前的单元格数:跨行数乘以跨列数,与selectedCellCount累加,否则一定是原始单元格,则selectedCellCount加1,遍历结束得到的就是最终的selectedCellCount。最后进行等式的比较,若等式成立,即允许合并操作,否则不允许。

    其中,如图3示出了上述合并操作的流程图,主要包括:遍历最小行到最大行行首,累计其中每行行高,将左上角单元格行高设为此值。再遍历最小列到最大列列首,累计其中每列列宽,将左上角单元格列宽设为此值。并将左上角单元格跨行数设为:maxRowId-maxRowId+1;跨列数设为maxColId-minColId+1。其他单元格全设为虚格,并把占据者属性设为左上角第一个单元格;

    然后,合并操作导致行内单元格或列内单元格全为虚格的删除操作过程:遍历合并受影响的行,将除行首外其余单元格全为虚格的行模型,放入willDeleteRow容器,遍历合并受影响的列,将除列首外其余单元格全为虚格的列模型,放入willDeleteColumn容器,对willDeleteRow、willDeleteColumn容器中的对象分别执行行删除和列删除即可。其中没有把单元格全为虚格的行、列直接删除,而是放入容器,是因为要避免遍历过程中因删除导致访问越界。

    二.拆分单元格算法模型:

    拆分单元格指:选定一个单元格,将其拆分为一个以上的单元格;包括横向拆分和纵向拆分,即把所选单元格拆分为n行m列,其中(n、m均大于等于1);如果单元格为原始单元格(未执行过合并操作),则新增各行(列)及原始行(列)的行高(列宽)均设为1/n(1/m)取整,如果当前单元格为复合单元格,则n(m)的取值只能大于等于1,且小于等于当前单元格的跨行数(跨列值),各行的行高(列宽)取对应的行首行高(列首列宽)。若n(m)的值小于跨行数(跨列数),则拆分范围内的最后行(列分别)对应的所有单元格均设为复合单元格,其跨行数=当前单元格跨行数-n+1;其跨列数=当前单元格跨列数-m+1。

    该算法模型需要视图层传递过来的参数为:currentCell,表示当前所选的单元格,用来指定要拆分的单元格;n,表示要拆分的行数、m,表示要拆分的列数。

    假设该模型用来将单元格拆分为n行、m列,根据单元格是原始还是复合单元格,该算法模型包括的算法操作分为对应的两种情况:

    如图4示出了拆分单元格算法模型的第一种算法操作流程,主要包括:所选单元格是表格构建时的原始单元格,这种情况的拆分操作要在当前行(所选单元格所在行)下方插入n-1个新行,然后在当前列右侧插入m-1个新列。具体算法操作包括:

    将currentCell高度设为原值的1/n取整,宽度设为原值的1/m取整,设置循环插入行:循环变量初值为1、步长为1、终止条件为循环变量大于n-1,循环中调用插入行/插入列方法,参数依次为:currentCell、true、1。设置循环插入列:循环变量初值为1、步长为1、终止条件为循环变量大于m-1,循环中调用插入行/插入列算法模型(将在后文描述),参数依次为:currentCell、false、1;

    声明hasChangedCells容器,把只需改变一次的单元格存入其中,用来防止二次改变;

    循环遍历新插入行,其间遍历每行的所有单元格,遍历过程中这些单元格引用名设为celli,将列号不在当前列号至当前列号加m-1之间的单元格(行首除外,行首是否为虚格取决于表格显示行首属性的值)均设为虚格,其holder属性设置:在当前行(拆分操作时选定的行)范围内取得和celli列号相等的单元格,设为cellci,如果cellci为实格,则celli占据者设为cellci的引用,否则设为cellci的占据者引用的单元格。判断如果hasChangedCells容器不含有celli占据者指向的单元格,则将此占据者单元格的跨行数应设为原跨行数+n-1,且将此占据者单元格存入hasChangedCells容器(此值也是完成本操作的最终值,即占据者单元格的跨行数在拆分过程中只作一次这样的改变);

    清空hasChangedCells容器;

    循环遍历新插入的列,其间遍历每列的所有单元格,遍历过程中这些单元格引用名为celli,将行号不在当前行号至当前行号加n-1之间的单元格(列首除外,列首是否为虚格取决于表格显示列首属性的值)均设为虚格,它们的holder属性设置:在当前列(拆分操作时选定的列)范围内取得和celli行号相等的单元格,设为cellci,如果cellci为实格,则celli占据者设为cellci的引用,否则设cellci的占据者引用的单元格。判断如果hasChangedCells容器不含有celli占据者指向的单元格,则将此占据者单元格的跨列数设为原跨列数+m-1,且将此占据者单元格存入hasChangedCells容器(此值也是完成本操作的最终值,即占据者单元格的跨行数只作一次这样的改变)。

    如图5示出了拆分单元格算法模型的第二种算法操作流程,主要包括:所选单元格是复合单元格,设临时变量:lastHeight=当前单元格高度-当前行行首高度,lastRowSpan=当前单元格跨行数-1,lastWidth=当前单元格宽度-当前列列首宽度,lastColSpan=当前单元格跨列数-1;

    当lastRowSpan等于0时,按第一种情况操作拆分行,即在当前行(所选单元格所在行)下方插入n-1个新行,并对新插入行范围内单元格状态按第一种情况的操作做相应变化;即执行图4中br-bc之间的操作步骤;

    当lastColumnSpan等于0时,按第一种情况操作拆分列,即在当前列(所选单元格所在列)右方插入n-1个新列,并对新插入列范围内的单元格按第一种情况的操作做相应变化;即执行图4中bc之后的操作步骤;

    当lastRowSpan和lastColumnSpan不等于0时,依次循环遍历当前单元格横向和纵向所跨所有单元格,对这些单元格执行以下操作:

    均设为实格,占据者属性设为null;

    判断如果其所在行不是拆分后这些行的最后一行,高度设为相对应的行首高度,跨行数设为1,且如果其所在列是当前列,则将lastHeight设为lastHeight减去此高度,将lastRowSpan设为lastRowSpan减去1;否则高度设为lastHeight,跨行数设为lastRowSpan;

    判断如果其所在列不是拆分后这些列的最后一列,宽度设为相对应的列首宽度,跨列数设为1,且如果其所在行是当前行,则将lastWidth设为lastWidth减去相对应的列首宽度,将lastColSpan设为lastColSpan减去1;否则宽度设为lastWidth,跨行数设为lastColSpan。

    三、拖动单元格边线改变行高列宽算法模型:

    拖动单元格边线改变行高列宽指:当拖动第一行上边线、最后一行下边线、第一列左边线、最后一列右边线时,它们均处于表格的四条边,则将当前行行高改变为原行高(当前列列宽)加上拖动改变量,并将表格整个高度(宽高)改变为原值加拖动改变量。且如果为当前行为第一行(第一列),则应将其范围内的单元格左上角x值(y值)改变为原值加上拖动改变量,表格左上角点x值改变为原值加拖动改变量。当其他拖动其它水平(垂直)方向边线时,则应改变当前行(列)及与拖动线相邻行(列)的行高(列宽),即:当前行行高改变为原行高(当前列列宽)加上拖动改变量,与拖动线相邻行行高(相邻列列宽)改变为原行高(列列宽)减去拖动改变量;表格其它部分固定不变。当前行(当前列)的确定分两种情况:当所选单元格为复合单元格,且拖动线为复合单元格下边线(右边线)时,当前行是行号等于此复合单元格所在行+它的跨行数-1的列(当前列是列号等于此复合单元格所在列+它的跨列数-1的列)。其它情况均为所选单元格所在行(列)。

    该算法模型需要视图层传递过来的参数为:所选单元格、所拖动线是单元格的上、下、左、右哪一条边线以及拖动偏移量。为了方便描述,约定如下:把边线参数名定义为position,其值对应上、下、左、右分别为常量TOP=-1、BOTTOM=1、LEFT=-2、RIGHT=2。把拖动偏移量参数名定义为delta,向下、向右拖动时,拖动delta为正数,向上、向左拖动时,delta为负数。

    进而,可通过线性定位器同化行列操作,在这个操作中,行和列可以共用同一个行为过程,只需根据position参数绝对值区分取得行模型或列模型,并根据其它几个相关参数执行操作即可。

    首先介绍下该算法模型的算法原理,如下:

    在本算法中虚拟一个平面坐标来明确、清淅化它们的位置关系。虽然相邻的两个单元格都有独自的边线,坐标模型中把它们相邻的边线看成一条线。单元格和线独立开来,把它们都看成坐标中的点,水平方向上,以表格左上角单元格坐标值为0,其右侧线与水平方向第二个单元格左侧线共用一个坐标值为1,水平方向第二个单元格坐标值为2,水平方向第二个单元格右侧线与水平方向第三个单元格左侧线供用一个坐标值为3,第三个单元格坐标值为4……,以此类推,直到最后一个单元格。同理,垂直方向也如此理解。因此可用数学公式定位:

    第n列(0<=n<columnNum)的水平坐标值:2n;

    第n列左侧线坐标值:2n-1;

    第n列右侧线坐标值:2n+1;

    第m行(0<=n<rowNum)的垂直坐标值:2m;

    第m行上侧线坐标值:2m-1;

    第m行下侧线坐标值:2m+1。

    根据坐标模型判断拖动线与单元格位置关系,当拖动的是水平线时,受影响的是行高,比较所拖动线与行内单元格上下两边任一条水平边线是否为同一个纵向坐标值,决定单元格的高度是否改变。当拖动的垂直线时,受影响的列宽,比较所拖动线与列内单元格左右两边任一条边线是否为同一个横向坐标值,决定单元格的宽度是否改变。

    下面,基于上述原理对该算法模型实现的算法操作进行介绍,如图6示出的拖动单元格边线改变行高列宽算法模型的执行流程图,主要包括以下步骤:

    声明整型变量rowId、columnId,把所选单元格行号赋于rowId、列号赋于columnId,

    声明整型变量cellIndex存储格子坐标值,

    声明整型变量lineIndex存储所拖动线坐标值,

    声明整型变量span存储单方向(水平或垂直)跨格子数,

    声明线性定位器lineLocalizer,用于指向所选单元格所在行或所在列,

    声明线性定位器toChangeLine,用于指向另一个需变化的行或列;

    当position的绝对值等于1(position==1或positrion==-1)时,变化的是行高,根据所选单元格行号取得行模型,赋于lineLocalizer;

    当position的绝对值等于2(position==2或positrion==-2)时,变化的是列宽,根据所选单元格列号取得列模型,赋于lineLocalizer;

    当所拖动的边线是所选单元格左侧线时,position=-2,应改变当前列和左侧列列宽,当所拖动的边线是所选单元格上侧线时,position=-1应改变当前行和上侧行行高。因此position<0时,把lineLocalizer的previous()方法返回的线性定位器引用赋于toChangeLine,即为相应的左侧列或上侧行,而position>0时,即position=1或position=2,把lineLocalizer的next()方法返回的线性定位器引用赋于to?ChangeLine,即为相应的右侧列或下侧行。

    另外,为了使拖动操作不破坏表格结构,拖动操作不允许跨越那条最近的与拖动线同方向的表格线。即:当position>0且delta>0,或者position<0且delta<0时,delta的绝对值应小于toChangeLine.getBandwidth();当position>0且delta<0,或者position<0且delta>0时,delta的绝对值应小于lineLocalizer.getBandwidth()。在执行拖动操作改变单元格宽高之前,应判断以上条件若满足,则执行拖动,否则直接返回结束操作。

    接下来遍历lineLocalizer、toChangeLine的所有单元格,比较坐标判断哪些单元格外观有变化,并对这些单元格进行变化:

    遍历过程中对单元格的引用设为iCell。当iCell是虚格时,受影响的是其占据者属性单元格的外观,因此要将iCell置为占据者属性(holder)所指的单元格;而后,调用如图7示出的判断单元格大小、位置是否发生变化的流程图,对单元格变化进行判断,主要包括下述步骤:

    计算坐标值:当position的绝对值等于1(position==1或positrion==-1)时:cellIndex=iCell.getRowId(),lineIndex=2×cellIndex+position,span=iCell.getRowSpan();

    当position的绝对值等于2(position==2或positrion==-2)时,cellIndex=iCell.getColumnId(),lineIndex=2×cellIndex+position/2,span=iCell.getColumnSpan();

    判断indexIndex==2×cellIndex-1成立或indexIndex==2×(cellIndex+span-1)+1成立,iCell大小会变化,否则拖动操作不影响iCell。

    确定单元格外观变化后,以下面的单元格变化规则进行变化:如果toChangeLine是lineLocalizer的next()方法返回的,则toChangeLine内的单元格要改变左上角x值或y值,lineLocalizer内的单元格左上角坐标值不变,如果toChangeLine是lineLocalizer的previous()方法返回的,则lineLocalizer内的单元格要改变左上角x值或y值,toChangeLine内的单元格左上角坐标值不变。具体来说,包括:

    遍历lineLocalizer范围内所有单元格时,如果坐标值比较等式成立,则按以下描述改变单元格外观:如果position绝对值=1,改变单元格高度为原高度加delta×position,且如果position=-1,改变单元格左上角y值为原值加delta;如果position绝对值等于2,改变宽度为原宽度加delta×position/2。且如果position=-2改变单元格左上角x值为原值加delta;

    遍历toChangeLine范围内所有单元格时,如果坐标值比较等式成立,则按以下描述改变单元格外观:如果position的绝对值=1,单元格高度为原高度减delta×position,且如果position=1,改变单元格左上角y值为原值加delta;如果position的绝对值=2,单元格宽度为原宽度减delta×position/2,且如果position=2,改变单元格左上角x值为原值加delta。

    四、插入行/插入列算法模型

    插入行/列是指:在选定单元格/行之前或之后插入一新行,新行行高与当前行行高相等,新行单元格大小与当前行对应位置单元格相同。原当前行下方所有单元格依次下移一个新行行高(插入列为右移)。如果当前行中有跨列不跨行的单元格,则新行对应位置也应为结构、大小相同的单元格。如果所选单元格为跨行复合单元格,则不允许执行插入行操作。如果某跨行复合单元格跨过当前行(所选单元格所在行),则把此复合单元格跨行数加1,高度为原高度加新行高度(对应插入列则为宽度)??墒褂孟咝远ㄎ黄魍迦胄杏氩迦肓胁僮?。

    该算法模型需要视图层传递过来的参数为:currentCell,表示当前所选的单元格,用来指定插入位置;isInsertRow,表示是否为插入行,值为true表示插入行,值为false表示插入列;position表示决定在当前单元格之前还是之后插入,取值为1或-1,1表示在当前单元格之后插入,-1表示在当前单元格之前插入。

    如图8示出了该算法模型的算法操作流程图,主要包括以下步骤:

    声明线性定位器:currentLine和newLine,

    声明单元格模型变量currentHolder用来存放可能即将作为占据者的单元格,

    声明整型变量currentId用来存放行号或列号,

    声明容器newCells临时存放新创建的单元格,

    声明容器allCells供删除过程中存放转移单元格,初始化为空容器,

    声明整型变量bandwidth存放当前带宽,即当前行首高度或当前列列首宽度,

    声明容器hasChangedCell用来存放本操作已经改变的单元格,防止二次改变,初始化为空容器;

    当插入行时,isInsertRow为true(这种情况下,当currentCell为跨行复合单元格时,则结束此操作),取当前行行号赋于currentId,根据currentId取得当前行赋于currentLine,创建新的空行赋于newLine。当插入列时,isInsertRow为false(这种情况下,当currentCell为跨列复合单元格时,则结束此操作)取当前列列号赋于currentId,根据currentId取得当前列赋于currentLine,创建新的空列赋于newLine;遍历currentLine的各单元格,遍历过程中设各单元格为cellInLine,创建一个宽高与cellInLine相等,跨行数、跨列数均为1的新单元格newCell;

    当isInsertRow为true时,调用如图9示出的插入行单元格处理流程,主要包括:

    如果cellInLine为跨列不跨行的单元格,则将newCell跨列数设为与cellInLine跨列数相等,并将newCell赋于currentHolder;

    如果cellInLine为跨行复合单元格且hasChangedCells不包含cellInLine,则把cellInLine跨行数加1,高度为原高度加bandwidth,并把cellInLine追加到hasChangedCells;

    如果cellInLine为虚格,则把newCell同样设为虚格,如果其占据者属性所指单元格为跨行复合单元格newCell占据者属性设为cellInLine占据者属性,且如果hasChangedCells不包含cellInLine占据者属性所指单元格,则把其占据者属性所指单元格跨行数加1,高度为原高度加bandwidth;如果其占据者属性所指单元格为非跨行复合单元格,newCell占据者属性设为currentHolder;

    当isInsertRow为false时,调用如图10示出的插入列单元格处理流程,主要包括:

    如果cellInLine为是跨行不跨列的单元格,则将newCell跨行数设为与cellInLine跨行数相等,并将newCell赋于currentHolder;

    如果cellInLine为跨列复合单元格且hasChangedCells不包含cellInLine,则把cellInLine跨列数加1,宽度为原宽度加bandwidth,并把cellInLine追加到hasChangedCells;

    如果cellInLine为虚格,则把newCell同样设为虚格,如果其占据者属性所指单元格为跨列复合单元格,newCell占据者属性设为cellInLine占据者属性,且如果hasChangedCells不包含cellInLine,则把其占据者属性所指单元格跨列数加1,宽度为原宽度加bandwidth;如果其占据者属性所指单元格为非跨列复合单元格,newCell占据者属性设为currentHolder;

    除了以上创建和设置newCell外,还要在循环中依次把newCell加入到newCells。至此已完成创建单元格及大小设置,然后按照下面步骤把所有新创建的单元格加入表格的适当位置并重画表格:

    声明容器allCells;声明整型变量n=0,o=0,a=0;

    改变行数或列数,并把新行或新列加入到行容器或列容器:如果isInsertRow为true,将表格rowNum属性设为rowNum+1,将newLine加入到表格rows属性的currentId+position位置,否则,将表格columnNum属性设为columnNum+1,将newLine加入到表格columns属性的currentId+position位置;

    新单元格加入表格cells属性:用两层循环控制单元格的加入位置:外层循环控制行,用i作循环变量,初值为0,步长为1,终止条件为i<rowNum,内层循环控制行内单元格,对应各列中的单元格,用j作循环变量,初值为0,步长为1,终止条件为:j<columnNum;

    在内循环中:

    当isInsertRow为true时,如果i==currentId+position,则取得newCells第n个单元格,追加到allCells,并将n设为n+1,否则取得表格的cells属性容器中第o个单元格,追加到allCells,并将o设为o+1;

    当isInsertRow为false时,如果j==currentId+position,则取得newCells第n个单元格,追加到allCells,并将n设为n+1,否则取得表格的cells属性容器中第o个单元格,追加到allCells,并将o设为o+1;

    循环结束后把allCells容器赋于表格cells属性,即完成了把新增单元格加入到表格cells属性。

    调用表格部分重画算法模型(将在后文描述),传入参数为currentLine和当前行行首高度,完成表格重画。

    五、删除行/删除列算法模型

    删除行/列是指:删除选定单元格所在行,原当前行下方所有单元格依次上移一个当前行行高(删除列则为原当前列右方所有单元格依次左移一个当前列列宽)。如果所选单元格为跨行复合单元格,则不允许执行删除行操作。如果某跨行复合单元格跨过当前行(所选单元格所在行),则把此复合单元格跨行数减1,高度为原高度减当前行高度(对应插入列则为宽度)。

    在表格初始状态下,所需删除的行或列中的所有单元格均为原始单元格,不涉及其它单元格,只需删除这些单元格,就完成了有关单元格的操作。但如果要删除的行或列含中复合单元格或虚格,会影响到其它单元格:

    在删除行时,当该行内含跨行复合单元格时,在删除该复合单元格前,先把其正下方单元格做以下改变:由虚格状态变为实格状态,高度设为该复合单元格高度减去当前行行首高度??矶任酶春系ピ窨矶?,跨行数为该复合单元格跨行数减去1,跨列数为该复合单元格跨列数。其次将行号与列号均在该复合单元格所跨范围内的单元格(所有占据者属性指向该复合单元格的单元格,当前行的虚格除外)的占据者属性设为该复合单元格正下方的单元格;当该行含有虚格时,在删除此虚格前,先取得它的占据者属性指向的单元格,设此单元格为cellA,如果cellA为跨行复合单元格,且与所要删的虚格不在同一行,则cellA的跨行数设为原跨行数减去1,高度设为原高度减去当前行行首高度。且cellA在此整个删除操作中只做一次这样的改变;

    在删除列时,当该列内含跨列复合单元格时,在删除该复合单元格前,先把其正右方单元格做以下改变:由虚格状态变为实格状态,高度设为该复合单元格高度??矶任酶春系ピ窨矶燃跞サ鼻傲辛惺卓矶?,跨行数为该复合单元格跨行数,跨列数为该复合单元格跨列数减去1。其次将行号与列号均在该复合单元格所跨范围内的单元格(占据者属性均指向该复合单元格的单元格,当前列的虚格除外)的占据者属性设为该复合单元格正右方的单元格;当该列含有虚格时,在删除此虚格前,先取得它的占据者属性指向的单元格,设此单元格为cellA,如果cellA为跨列复合单元格,且与所要删的虚格不在同一列,则cellA的跨列数应设为原跨列数减去1,宽度设为原宽度减去当前列列首宽度。且cellA在此整个删除操作中只做一次这样的改变。

    该算法模型需要视图层传递过来的参数为:currentCell,表示当前所选的单元格,用来指定删除行或列的所在位置;isDeleteRow,表示是否为删除行,值为true表示删除行,值为false表示删除列。

    删除行与删除列操作步骤一致,只是方向不一致。因此可使用线性定位器同化删除行与删除列操作步骤。

    如图11示出了删除行/删除列算法模型的操作流程图,主要包括以下步骤:

    声明线性定位器:currentLine用来指定要删除的行或列;

    声明整型变量currentRowId、currentColumnId用来存放行号或列号;

    声明容器hasChangedCells用来存放本操作已经改变的单元格,防止二次改变,初始化为空容器;

    声明整型变量bandwidth存放当前带宽,即当前行首高度或当前列列首宽度;

    声明容器allCells供删除过程中存放转移单元格,初始化为空容器;

    当删除行时,isDeleteRow为true(这种情况下,当currentCell为跨行复合单元格时,则结束此操作),取当前行行号赋于currentRowId,当前列列号赋于currentColumnId,根据currentRowId取得当前行赋于currentLine;

    当删除列时,isDeleteRow为false(这种情况下,当currentCell为跨列复合单元格时,则结束此操作)取当前行行号赋于currentRowId,当前列列号赋于currentColumnId,根据currentColumnId取得当前列赋于currentLine;

    将bandwidth置为currentLine.getBandwidth();遍历currentLine的各单元格,遍历过程中设当前访问单元格为cellInLine;

    当isDeleteRow为true时,执行如图12示出的删除行单元格流程图,主要包括:

    如果cellInLine为跨行复合单元格,则取得行号为currentRowId+1,列号为currentColumnId的单元格,设此单元格为replaceCell,如果hasChangedCells不包含replaceCell,则将replaceCell做以下改变:isPhantom属性置为false,rowSpan置为cellInLine的rowSpan-1,高度置为cellInLine的高度减去bandwidth;columnSpan置为cellInLine的columnSpan,宽度置为cellInLine的宽度,并把realCell追加到hasChangedCells。循环遍历行号大于currentRowId,且小于currentRowId+replaceCell跨行数,列号大于等于currentColumnId且小于currentColumnId+replaceCell跨列数的所有单元格将它们的占据者属性置为replaceCell;

    如果cellInLine为虚格,取得其占据者属性指向的单元格,设为realCell,如果realCell为跨行复合单元格,且hasChangedCells不包含realCell,则把realCell跨行数置为原跨行数减1,高度置为原高度减bandwidth,并把realCell追加到hasChangedCells;

    当isDeleteRow为false时,执行如图13示出的删除列单元格流程图,主要包括:

    如果cellInLine为跨列复合单元格,则取得行号为currentRowId,列号为currentColumnId+1的单元格,设此单元格为replaceCell,如果hasChangedCells不包含replaceCell,则将replaceCell做以下改变:isPhantom属性置为false,rowSpan置为cellInLine的rowSpan,高度置为cellInLine的高度;columnSpan置为cellInLine的columnSpan-1,宽度置为cellInLine的宽度减去bandwidth,并把realCell追加到hasChangedCells。循环遍历行号大于等于currentRowId,且小于currentRowId+replaceCell跨行数,列号大于currentColumnId且小于currentColumnId+replaceCell跨列数的所有单元格将它们的占据者属性置为replaceCell;

    如果cellInLine为虚格,取得其占据者属性指向的单元格,设为realCell,如果realCell为跨列复合单元格,且hasChangedCells不包含realCell,则把realCell跨列数置为原跨列数减1,宽度置为原宽度减bandwidth,并把realCell追加到hasChangedCells;

    循环遍历结束。至此已完成受影响的单元格变化。然后,按照下面步骤把currentLine范围内的单元格删除并重画表格:

    用两层循环控制单元格删除哪些单元格:外层循环控制行,用i作循环变量,初值为0,步长为1,终止条件为i<rowNum,内层循环控制行内单元格,对应各列中的单元格,用j作循环变量,初值为0,步长为1,终止条件为:j<columnNum;

    在内循环中:

    当isDeleteRow为true时,如果i不等于currentRowId,则取得表格的cells属性容器中第i×columnNum+j个单元格,追加到allCells;

    当isDeleteRow为false时,如果j不等于currentColumnId,则取得表格的cells属性容器中第i×columnNum+j个单元格,追加到allCells;

    循环结束后把allCells容器赋于表格cells属性,即完成了从表格cells属性删除currentLine范围内的单元格;

    改变行数或列数,并把当前行或当前列从行容器或列容器中删除:如果isDeleteRow为true,将表格rowNum属性设为rowNum-1,将currentLine从表格rows属性中删除,否则,将表格columnNum属性设为columnNum-1,将currentLine从表格columns属性中删除;

    调用表格部分重画算法???将在后文描述),传入参数为currentLine和当前行行首高度的负值,完成表格重画。

    六、表格绘画算法模型:

    如图14示出的该算法模型的操作流程图,其主要包括以下三种算法模型的操作:

    1.表格初始化算法子模型

    该方法负责构造表格、初始化所有行、列、单元格。并按初始参数绘画表格。表格初始化时,只有数值型属性行数、列数和单元格宽度、高度是已知量,其他模型及变量都在此方法中创建。以上四个变量都有默认值,并提供表格构造函数传入这四个参数的自定义值。

    由于初始化时,把所有单元格设为等高、等宽,单元格的位置与大小很方便控制。用两层循环控制行、列、单元格的初始化。外循环中生成行并加入行容器,循环变量范围:0<=外循环变量<表格行数;内循环中,判断如果是第一行则生成列并加入列容器,循环变量范围:0<=内循环变量<表格列数;单元格在内循环中生成,单元格左上角坐标x值=(单元格宽度+水平表格边线间距)×内循环变量+水平表格边线间距;单元格左上角坐标y值=(单元格高度+垂直表格边线间距)×外循环变量+垂直表格边线间距。表格高度=(单元格高度+垂直表格边线间距)×表格行数+重直表格边线间距;表格宽度=(单元格宽度+水平表格边线间距)×表格列数+水平表格边线间距。

    2.整个表格重画算法子模型:

    表格初始化完成后,要改变整个表格外观,如表格整体缩放,调用此方法即可。该方法负责表格大小缩放后,计算单元格位置与大小。

    表格初始化完成后,有些操作会改变个别单元格高宽和状态,因此这个方法就不能像初始化那样构造等宽、等高的表格。

    在表格重画之前有可能已经执行了合并单元格执行,产生了虚格,所有虚格是不需要交给视图层显示的,只有实格才显示。重画之前声明一个空容器toShowCells,用于存放需要显示的单元格即实格。遍历所有单元格,此容器。遍历结束后把此容器传递到视图层显示。

    初始化方法已经创建了行、列模型,通过遍历所有行模型或所有列模型均可完成表格的重画。这里我们采用行方式。先取得第一行,把它赋于row变量引用,设置循环遍历所有行,跳出循环条件为row.hasNext()为false,在循环中通过row.createIterator(),遍历行内所有单元格,设置单元格的大小和位置(设置方法见下文),如果单元格为实格则加入到toShowCells容器。当前行遍历结束,把row.next()赋于row来访问下一行的所有单元格。直到row.hasNext()为false结束编历。将toShowCells传递给视图层显示。

    单元格位置的确定是相对比表格左上角位置的,即表格左上角点x值、y值均为0,单元格依次按列数向右排放,按行向下排放,则第一行单元格位置y值为:0+verticalSpacing,其它行单元格位置y值为:上一行单元格y值+上一行行高+verticalSpacing。同样第一列x值为:0+horizontalSpacing,其它单元格x值为:左侧列单元格x值+左侧列列宽+horizontalSpacing,为了提高效率,免去在循环中每次取上一行行高和左侧列列宽计算当前单元格y值、x值。在循环中用两个临时变量分别保存当前行行高(取当前行第一个单元格高度)、当前列列宽(取当前列第一个单元格宽度),以备下一行、下一列使用。

    单元格大小改变量由缩放偏移量决定。水平偏移量除以表格列数取整,得到每列列宽改变量;垂直偏移量除以表格行数取整得到每行行高改变量。循环中每个单元格列宽加上列宽改变量,行高加上行高改变量。

    另外,表格总宽度应设为原宽度与水平偏移量除以表格列数取余之差;总高度设为原高度与垂直偏移量除以表格行数取余之差。

    3.部分表格元素重画算法子模型:

    在执行插入行、删除行、插入列、删除列时,完成单元格大小变化后,调用此方法重画表格中受影响的部分,拆分单元格时有些情况下要间接执行插入行、插入列操作,其过程中也调用了此方法。

    插入行、删除行操作会影响表格高度,并影响处于当前行下方及以下所有单元格的位置。插入列、删除列操作会影响表格宽度,并影响处于当前列右方及以下所有单元格的位置。拆分单元格涉及到边线增多及均平取整余数调整,表格高度、宽度有可能微调,当前单元格右侧所有列中的单元格和下侧所有行的单元格位置都有可能微调。

    可以看出,这些操作均不影响上边和左边所有单元格,可以通过线性定位器根据方向参数改变单元格外观的相应属性(x值或y值)。

    此方法接收两个参数:线性定位器lineLocalizer、一个移动偏移量delta。

    设置循环遍历lineLocalizer以后的所有线性定位器,用lineLocalizer.hasNext()作为终止循环条件,在循环中设置lineLocalizer=lineLocalizer.next(),用lineLocalizer.createrIterator()创建迭代器访问其范围内所有单元格,判断如果lineLocalizer.getDirection()等于0,则单元格左上角坐标y值设为原值加delta,否则单元格左上角坐标x值设为原值加delta。循环结束后,判断如果lineLocalizer.getDirection()等于0,则表格外观总高度设为原值加delta,否则表格外观总宽度设为原值加delta。

    通过上述各个算法模型,便可实现算法模型层对各个算法模型的调用,实现对表格模型的各个操作。

    以上所述,仅为本发明的较佳实施例而已,并非用于限定本发明的?;し段?,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的?;し段е?。

    关于本文
    本文标题:一种表格模型操作的方法.pdf
    链接地址://www.4mum.com.cn/p-5865333.html
    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    [email protected] 2017-2018 www.4mum.com.cn网站版权所有
    经营许可证编号:粤ICP备17046363号-1 
     


    收起
    展开
  • 四川郎酒股份有限公司获第十二届人民企业社会责任奖年度环保奖 2019-05-13
  • 银保监会新规剑指大企业多头融资和过度融资 2019-05-12
  • 韩国再提4国联合申办世界杯 中国网友无视:我们自己来 2019-05-11
  • 中国人为什么一定要买房? 2019-05-11
  • 十九大精神进校园:风正扬帆当有为 勇做时代弄潮儿 2019-05-10
  • 粽叶飘香幸福邻里——廊坊市举办“我们的节日·端午”主题活动 2019-05-09
  • 太原设禁鸣路段 设备在测试中 2019-05-09
  • 拜耳医药保健有限公司获第十二届人民企业社会责任奖年度企业奖 2019-05-08
  • “港独”没出路!“梁天琦们”该醒醒了 2019-05-07
  • 陈卫平:中国文化内涵包含三方面 文化复兴表现在其中 2019-05-06
  • 人民日报客户端辟谣:“合成军装照”产品请放心使用 2019-05-05
  • 【十九大·理论新视野】为什么要“建设现代化经济体系”?   2019-05-04
  • 聚焦2017年乌鲁木齐市老城区改造提升工程 2019-05-04
  • 【专家谈】上合组织——构建区域命运共同体的有力实践者 2019-05-03
  • 【华商侃车NO.192】 亲!楼市火爆,别忘了买车位啊! 2019-05-03
  • 北京pk是最稳全天计划 大乐透预测大乐透开奖 幸运飞艇计划全天计划金鹰 北京pk10下载 pk10软件有用吗 五星组选包胆保守倍投 五分赛车计划软件 pk10赛车开奖记录照片 重庆时时破解的方法 竞足混合投注什么意思 pk10滚雪球计划 11选5任三追号稳赚计划 幸运飞艇计划哪个比较稳呢 北赛车pk10官方投注 黄大仙的特马 双色球走势图新浪爱彩一号店