posts - 156, comments - 211, trackbacks - 0, articles - 6

2007年9月2日

   传统上报表引擎主要完成两项工作:结构描述和结构转换。一般报表设计人员通过可视化设计工具完成对报表结构的描述,然后报表引擎根据这些描述生成不同格式的报表文件,如PDF格式,XLS格式等。这一图景中报表设计工具扮演着关键角色,因为它不仅仅是向用户提供一个直观的界面,更重要的是配置过程本身就是一种分步骤的结构构造过程。理想的情况是用户指定报表中具体有哪些单元格,表格具体有哪些列,而在运行期报表引擎负责向单元格中填充数据。但是对于设计期只能进行动态描述,无法预先确定所有结构元素的报表(例如交叉表的列只能在执行时确定),这种报表模型就会出现问题。一般处理方式都是在报表引擎中内置所有可能的动态报表模型。无论设计工具多么复杂,其内置的原理如果是基于静态结构模型,就无法建立一种抽象机制,这样我们就只能通过重复劳动来应对众多结构类似但是略有不同的报表。
   Witrix平台的报表引擎是对程序友好的,它引入了编译期结构运算,在报表编译时可以通过程序吸收大部分结构差异性。在Witrix平台中,报表制作分为三个阶段:设计期 -> 编译期 -> 运行期。报表引擎负责完成三种工作:结构描述,结构生成和结构转换。具体实现动态结构生成的过程其实非常简单。目前所有的Witrix配置文件都通过基础配置引擎进行解析,它定义了统一的dynamic和extends元机制。
   <report dynamic="true">
定义了dynamic="true"的报表定义文件首先作为tpl模板文件来运行,其运行结果再作为报表格式解析。在这种模型下,报表引擎并没有内置如何把动态结构拼接出来的知识,这些知识存在于编译期,而tpl标签的抽象能力使得我们可以把复杂的报表结构生成过程抽象成简单的标签调用形式。
   <report dynamic="true">
      <body>
        <table>
         <thead>
            <c:forEach var="_h" items="${cols}">
             ....
        </table>
      </body>
   </report>

==>
   <report dynamic="true">
      <body>
         <rpt:GenCrossTable tableMeta="${tableMeta}" loopVar="tableData" />
      </body>
   </report>

   在编译期通过tpl封装可以解决大部分结构生成问题,在运行期报表引擎主要负责的结构问题就简化为数据行展开和单元格合并等确定操作。
   Witrix报表引擎的另一个特点是运行期结构生成过程和结构转换过程同时进行,因此不需要在内存中构造一个完整的报表数据对象,大大减轻了内存压力。Witrix报表引擎输出的文件格式目前有html, XML格式的Word文件和XML格式的Excel文件等。每一种输出格式相当于定义了一种渲染模型,它们都是对报表模型的一种展现方式。从某种程度上说这些模型的结构都是等价的,但是完成模型转换所需要的操作往往不是局域化的。例如在html的table中某一单元格具体对应哪一列是受到其他单元格的rowspan和colspan属性影响的, 在Excel中则需要明确指定列的index属性。为了简化运行期逻辑,内置的报表模型必须提供一些冗余结构,从而兼容多种渲染模型。

posted @ 2007-09-02 09:45 canonical 阅读(877) | 评论 (1)编辑 收藏

    程序中大量的工作其实都是在定义结构以及结构之间的关系. 一般情况下我们应该识别出结构,并把它们封装到函数,对象和组件中去. 但是封装并不永远都是有利的. 将某个结构独立出来, 在某种程度上也就割裂了它和其他元素之间的关系, 这会引发结构融合的障碍, 也会造成思维上的负担. 事实上如果程序整体具有足够的可理解性和概念稳定性, 我们并不需要独立识别出什么子部分. 一个简单的例子是数组循环. 一般情况下我们应该尽量把循环查找等操作封装到函数中, 避免多重循环嵌套时产生过于复杂的代码块. 但是如果数组或者语言本身提供了each, map等函数式操作符,则这种封装需求就大大减弱了.
    随着系统结构的日益复杂化, 在系统中会积累大量的背景知识.此时当我们需要完成一个功能的的时候, 往往不再需要指定所有的信息, 而只需要指定背景知识之外的部分信息即可. 例如在界面上通过一个分页表格来显示实体列表这样一个功能, 在Witrix平台中通过模型驱动的标准页面即可自动完成. 一般的定制需求往往是过滤显示部分数据, 在表格行上增加一些操作按钮, 定制表格的表头等. Witrix平台实现这些需求并不需要封装出一个独立的表格组件, 调用它的属性修改方法等, 而是把定制部分嵌入到BizFlow的配置中, 这里并没有明确的结构界限.
  <biz id="default">
    <filter>
       <eq name="status" value="1" />
    <filter>
     <tpls>
        <tpl id="thead>
         <thead>
          <tr rowspan="2">...</tr>
          <tr>...</tr>
         </thead>
        </tpl>
        <tpl id="rowOps">
          <ui:FlatButton .../>
        </tpl>
     </tpls>
      其他与表格无关的信息
  </biz>
  注意到对于我们理解业务而言, 我们并不需要知道表格具有分页, 排序, 隔行变色等功能. 所有和业务相关的代码聚集到BizFlow文件中, 它们构成一个可以独立理解的整体, 在此过程中也通过背景知识实现了大量结构的消解.

posted @ 2007-09-02 09:45 canonical 阅读(647) | 评论 (3)编辑 收藏