Jasper使用comparatorExpression报告交叉表排序

Jay*_*ayL 8 sorting jasper-reports crosstab comparator

我正在尝试根据一些自定义方案在交叉表中对动态列进行排序.

在文档中我发现了compareExpression:Crosstab group bucket比较表达式.此表达式的结果用于按升序或降序对存储桶进行排序.如果未指定比较器表达式,则将使用自然顺序.

但我不明白表达式应该是什么样的.我可以以某种方式使用常规的Java比较器吗?有人可以分享一个例子吗?

And*_*ich 7

可能有更容易和直接的解决方案:

我正在使用Jasper Reports Studio(Eclipse插件).

  1. 最终没有为我工作:-( ...(请参阅1.我的回答下面的评论 - 可能是一个错误)你可以检查[x]数据预先交叉表属性中排序.当然这只有你不这样做才有效需要根据预先排序的结果集在报告中的其他位置进行另一次排序.

  2. 使用不可见的交叉表组头,这是相当棘手的:

    1. 创建一个新的行/列组(例如通过大纲视图),保留原始名称Row Group1或类似于现在
    2. 将其设置Total PositionNone(我们不希望每行/每列生成一个总列)
    3. 在旧XML之前移动XML中的组
    4. 将组重命名为某个说话名称,例如name="invisible sort column ..."
      • (不再在XML中存在对该组的进一步引用)
    5. 如果您在使用组总计(Total Position!=None),则必须将这些总计元素/设置基本上移动到第一个虚拟排序组,否则总计将不再显示总数(=每第2组总数)组列/行,例如(此处仅显示列组,但行组遵循相同的原则)

      a|b|c|sum      a|sum|b|sum|c|sum
      =========  =>  =================
      1|2|3|6        1|1  |2|2  |3|3
      
      Run Code Online (Sandbox Code Playgroud)
      • 最简单的可能是在XML中执行此操作,类似于此转换(不要忘记移动totalPosition=...columnTotalGroup=...属性并更改总和,如果适用于您的方案$V{SomeSum_..._ALL}):

        ...
        <columnGroup name="OrderXDummy" height="0">
          ...
          <crosstabTotalColumnHeader>
            <cellContents/>
          </crosstabTotalColumnHeader>
        </columnGroup>
        ...
        <columnGroup name="X" ... totalPosition="End">
          ...
          <crosstabTotalColumnHeader>
            <cellContents ...>
              ...
            </cellContents>
          </crosstabTotalColumnHeader>
        </columnGroup>
        ...
        <crosstabCell ... columnTotalGroup="X">
          ...
           <textFieldExpression><![CDATA[$V{SomeSum_X_ALL}]]></textFieldExpression>
          ...
        </crosstabCell>
        
        Run Code Online (Sandbox Code Playgroud)

        =>

        ...
        <columnGroup name="OrderXDummy" height="0" totalPosition="End">
          ...
          <crosstabTotalColumnHeader>
            <cellContents ...>
              ...
            </cellContents>
          </crosstabTotalColumnHeader>
        </columnGroup>
        ...
        <columnGroup name="X" ... >
          ...
          <crosstabTotalColumnHeader>
            <cellContents/>
          </crosstabTotalColumnHeader>
          ...
        </columnGroup>
        ...
        <crosstabCell ... columnTotalGroup="OrderXDummy">
          ...
           <textFieldExpression><![CDATA[$V{SomeSum_OrderXDummy_ALL}]]></textFieldExpression>
          ...
        </crosstabCell>
        
        Run Code Online (Sandbox Code Playgroud)
    6. (可以跳过:) 删除不必要的生成的<crosstabCell ... column/rowTotalGroup="...">单元格

      • 最好将报告与以前的版本进行比较,以便可靠,快速地识别XML中的这些位置
      • 也许这不是一个关键的步骤,但看着现有的XML足够令人困惑;-)
    7. 添加排序列的(bucket)表达式,例如$F{ORDER_FOR_X}
      • 不要忘记分配Value Class Namejava.lang.Integer或者您的值适合在这里(看看你的数据集,其类型是通过一些列那里分配如果正在使用它)
    8. 一些变量表达式添加Order By Expression原始组中,例如$V{ORDER_FOR_X}

      • $V{...}是诀窍,不要用$F{...}!
      • (编辑说这是无效的,但它会起作用)
      • 意味着您是否可以提供一些定义排序的字段并与您的待排序列值相关,例如(Oracle SQL)

        select            1 as order_for_x,  'foo' as x,  'bla blu' as y  from dual
        union all select  2,                 'bar',       'ta tu'         from dual
        union all select  2,                 'bar',       'na na'         from dual
        union all select  1,                 'foo',       'check it'      from dual
        union all select  3,                 'queue',     'sap'           from dual
        
        Run Code Online (Sandbox Code Playgroud)
      • 否则你当然可以在这里使用别的东西

      • 如果你应该得到一些

        ...
        Caused by: java.lang.NullPointerException
        at org.apache.commons.collections.comparators.ComparableComparator.compare(ComparableComparator.java:92)
        at net.sf.jasperreports.crosstabs.fill.BucketExpressionOrderer.compareOrderValues(BucketExpressionOrderer.java:70)
        ...
        
        Run Code Online (Sandbox Code Playgroud)

        你可以简单地改变表达$V{ORDER_FOR_X} == null ? 0 : $V{ORDER_FOR_X}应该做的伎俩

    9. 设置所有的高/宽域虚设组的0文本字段Print When Expressionfalse

    10. (也许通过与之前的报告版本进行比较检查,没有其他任何改变,以确保你没有搞乱别的东西)
  3. 使用基于度量总计订单(如下面的链接所述)

  4. 使用自定义Java Comparator类(如Pieter VN 2011-11-16的答案中所述)

我发现可能有用的链接:


Pie*_* VN 6

我有同样的问题,没有找到任何例子或解释,但我发现如何做到这一点.我会解释,所以希望其他人可以使用这个解决方案.

我已将jasperreports 3.1.0和iReport 3.1.4的代码用于下面,但我猜它适用于几乎所有版本.

首先,您必须确保您知道行/列组的存储区表达式中的类.默认情况下这是java.lang.String,但我有一个自定义类.为此,我需要为我的列组编辑这样的xml:

<bucketExpression class="java.lang.String"><![CDATA[$F{customObj}]]></bucketExpression>
Run Code Online (Sandbox Code Playgroud)

<bucketExpression class="com.project.CustomObj"><![CDATA[$F{customObj}]]></bucketExpression>
Run Code Online (Sandbox Code Playgroud)

显然,这个customObj值是一个具有相应类的字段,在报告本身中定义.

然后,您需要添加一个Comparator作为参数,例如:

parameters.put("OVERRIDE_Comparator", new Comparator<CustomObj>() {
    public int compare(CustomObj c1, CustomObj c2) {
        //create your custom compare logic over here, this code works as if no custom Comparator is used
        return c1.compareTo(c2);
    }
});
Run Code Online (Sandbox Code Playgroud)

现在使用java.util.Comparator参数类在jasperreport中添加这样的OVERRIDE_Comparator参数.

最后一步:将$ P {OVERRIDE_Comparator}作为比较器表达式放在您需要的行/列组中.

编译此类报告时,最可能的编译错误是转换问题.Jasperreports默认为java.lang.String,您可能需要手动编辑报表的xml以在每一步获取正确的类.

(我从一些亚洲网站发现了这个方法,幸好代码本身是可读的!:-))