Jasper Reports сортировка кросс-таблиц с помощью comptorExpression - PullRequest
8 голосов
/ 23 февраля 2010

Я пытаюсь отсортировать мои динамические столбцы в кросс-таблице по какой-то пользовательской схеме.

В документах я обнаружил упоминание выражение сравнения: выражение компаратора группы групп перекрестных таблиц. Результатом этого выражения является используется для сортировки ведер в порядке возрастания или убывания. Если нет компаратора выражение указано, будет использован естественный порядок.

но я не понимаю, как должно выглядеть выражение. Можно ли как-нибудь использовать обычный компаратор Java? Может кто-нибудь поделиться примером?

Ответы [ 3 ]

7 голосов
/ 22 ноября 2013

Возможны гораздо более простые и понятные решения:

Я использую Jasper Reports Studio (Eclipse Plugin).

  1. , наконец, не сработало для меня :-( ... (см. Комментарий под моим ответом - может быть ошибка), вы можете просто проверить [x ] Данные предварительно отсортированы в Свойства кросс-таблицы . Конечно, это работает только в том случае, если вам не нужен другой порядок в другом месте отчета, основанный на предварительно отсортированном наборе результатов.

  2. с использованием невидимого заголовка группы кросс-таблицы , что довольно сложно:

    1. создайте новую группу строк / столбцов (например, с помощью представления Outline), оставьте исходное имя Row Group1 или подобное ему, как сейчас
    2. установить для Total Position значение None (мы не хотим, чтобы общий столбец создавался для каждой строки / столбца)
    3. переместить группу в 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
      
      • проще всего сделать это в 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>
        

        =>

        ...
        <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>
        
    6. (может быть пропущено :) удалить ненужные сгенерированные <crosstabCell ... column/rowTotalGroup="..."> ячейки

      • может быть лучше сравнить отчет с предыдущей версией, чтобы надежно и быстро идентифицировать эти места в XML
      • возможно, это не решающий шаг, но взгляд на существующий XML достаточно запутанный; -)
    7. добавить выражение (ведро) вашего столбца сортировки, например. $F{ORDER_FOR_X}
      • не забудьте назначить Value Class Name на java.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
        
      • в противном случае вы, конечно, можете использовать что-то еще здесь

      • если вы должны получить

        ...
        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)
        ...
        

        Вы можете просто изменить выражение на $V{ORDER_FOR_X} == null ? 0 : $V{ORDER_FOR_X}, что должно сработать

    9. установить все поля высокой / ширины фиктивной группы на 0 и текстовые поля Print When Expression на false

    10. (возможно, проверьте через сравнение с предыдущей версией отчета, что ничего не изменилось, чтобы убедиться, что вы не испортили что-то еще)
  3. с использованием порядка на основе итогов измерения (как описано в нижней ссылке)

  4. с использованием пользовательского класса Java Comparator (как описано в ответе от Pieter VN 2011-11-16 )

далее, может быть, полезные ссылки, которые я нашел:

6 голосов
/ 16 ноября 2011

У меня была такая же проблема, и я не нашел ни примеров, ни объяснений, но я нашел, как это сделать. Я объясню, так что, надеюсь, другие люди могут использовать это решение.

Я использовал приведенный ниже код для jasperreports 3.1.0 и iReport 3.1.4, но, думаю, он работает практически для всех версий.

Сначала вам нужно убедиться, что вы знаете, какой у вас класс в выражении группы для вашей группы строк / столбцов. По умолчанию это java.lang.String, но у меня там есть свой класс. Чтобы это работало, мне нужно было отредактировать xml следующим образом для моей группы столбцов:

<bucketExpression class="java.lang.String"><![CDATA[$F{customObj}]]></bucketExpression>

до

<bucketExpression class="com.project.CustomObj"><![CDATA[$F{customObj}]]></bucketExpression>

Очевидно, что это значение 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);
    }
});

Теперь добавьте такой параметр OVERRIDE_Comparator в jasperreport, используя класс параметров java.util.Comparator.

Последний шаг: поместите $ P {OVERRIDE_Comparator} в качестве выражения компаратора в нужную вам группу строк / столбцов.

При компиляции такого отчета наиболее вероятной ошибкой компиляции будут проблемы приведения. Jasperreports по умолчанию равен java.lang.String. Возможно, вам придется вручную редактировать xml отчета, чтобы получить правильный класс на каждом шаге.

(я узнал этот метод с какого-то азиатского сайта, к счастью, сам код был читабелен! :-))

2 голосов
/ 18 января 2016

orderByExpression

Как правило, для заказа столбцов кросс-таблицы используется orderByExpression

  1. Определите меру для того, что вы хотите заказать (другое поле или выражение, используйте правильное определение класса в моем случае a Integer)
<measure name="orderByField_measure" class="java.lang.Integer">
     <measureExpression><![CDATA[$F{orderByField}]]></measureExpression>
</measure>
  1. Используйте меру в orderByExpression в bucket
<columnGroup name="myColumnGroup" height="10">
      <bucket class="java.lang.String">
        <bucketExpression><![CDATA[$F{MyField}]]></bucketExpression>
        <orderByExpression><![CDATA[$V{orderByField_measure}]]></orderByExpression>
    </bucket>
    .....
</columnGroup>

comparatorExpression

Установить Comparator (создать класс в Java. MyCustomComparator, который реализует Comparator)

<bucket class="java.lang.String">
    <bucketExpression><![CDATA[$F{MyField}]]></bucketExpression>
    <comparatorExpression><![CDATA[new com.my.package.MyCustomComparator()]]></comparatorExpression>
</bucket>

Сопоставимые

Если вы отображаете значение из собственного объекта ($F{MyField} - это определенный пользователем объект), вы можете просто реализовать Comparable , чтобы отобразить порядок, как вам нравится.

...