8

Вопрос по reporting, report, jasper-reports, java – undefined

У меня есть отдельное приложение, и одна из его обязанностей - взять путь к файлу * .jrxml и скомпилировать его.

Я могу делать это без проблем, пока не появится отчет с вложенным отчетом, где компиляция мастера не скомпилирует ни одного из его дочерних элементов, в результате чего файл вложенного отчета * .jasper не будет найден позже.

Есть ли способ

1) Установить JasperCompileManager для автоматического получения подотчетов?

2) Получить список путей к вложенным отчетам, содержащимся в объекте JasperDesign или JasperReport?

У меня нет прямого доступа к файлам jrxml, поэтому изменение отчетов в соответствии с методом компиляции не является опцией, равно как и применение какой-либо стандартной схемы именования для определения того, какие подотчеты принадлежат каким отчетам.

Здесь есть похожая проблема:

http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=40683

где JRVisitor используется для создания списка объектов JRSubreport, однако нет никакого объяснения того, как использовать это, чтобы получить путь к подотчету, чтобы скомпилировать его и рекурсивно искать подотчеты подотчетов, и я не могу понять это.

  • Error: User Rate Limit Exceeded

    от Numeron
  • Error: User Rate Limit ExceededcompileReport()Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Я тоже хотел бы услышать ответ. В итоге я получил ссылку на файл * .jasper в подотчете, а не компилировал его на лету. :(

    от Rangi Lin
  • Подобная проблема решена без сохранения файлов на диске:stackoverflow.com/questions/9785451/…

    от Lukasz Stelmach
  • 8

    Хорошо

    так что потребовалось немного взлома, но я смог кое-что выяснить ...

    Subreport.getExpression (). GetText () возвращает поле выражения элемента виджета подотчета в основном отчете и представляет собой строку, которая выглядит примерно так

    $P{SUBREPORT_DIR} + "/report_sub1.jasper"
    

    Так что я смог разобрать его, чтобы получить имя, используя следующее. Это не идеально, но оно должно выдержать.

    JRElementsVisitor.visitReport(jasperReport, new JRVisitor(){
    
      // ** snip other overrides **
    
      @Override
      public void visitSubreport(JRSubreport subreport){
        String expression = subreport.getExpression().getText().replace(".jasper", ".jrxml");
        StringTokenizer st = new StringTokenizer(expression, "\"/");
        String subreportName = null;
        while(st.hasMoreTokens())
          subreportName = st.nextToken();
        compileReport(subreportName);
      }
    }
    

    EDIT:

    Вот весь мой метод compileReport, демонстрирующий, как рекурсивно компилировать вложенные отчеты вложенных отчетов и т. Д. Не идеально, но достаточно хорошо для моего приложения. Все скомпилированные файлы * .jasper сохраняются обратно на диск в том же месте, где были извлечены не скомпилированные файлы * .jrxml, но это не трудно изменить. Скомпилированный основной объект отчета передается обратно, если вы хотите запустить его или что-то еще.

    Помните, что этому коду на момент редактирования было 9 месяцев, и в более новых версиях Jasper Reports теперь могут быть встроенные функции для такого рода вещей.

    private static final String reportsPath = "someplace/nice/";
    private ArrayList<String>   completedSubReports = new ArrayList<String>(30);
    private Throwable           subReportException  = null;
    
    /**
     * Recursively compile report and subreports
     */
    public JasperReport compileReport(String reportName) throws Throwable{
      JasperDesign jasperDesign = JRXmlLoader.load(reportsPath + reportName + ".jrxml");
      JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
      JRSaver.saveObject(jasperReport, reportsPath + reportName + ".jasper");
      toLog("Saving compiled report to: " + reportsPath + reportName + ".jasper");
      //Compile sub reports
      JRElementsVisitor.visitReport(jasperReport, new JRVisitor(){
        @Override
        public void visitBreak(JRBreak breakElement){}
    
        @Override
        public void visitChart(JRChart chart){}
    
        @Override
        public void visitCrosstab(JRCrosstab crosstab){}
    
        @Override
        public void visitElementGroup(JRElementGroup elementGroup){}
    
        @Override
        public void visitEllipse(JREllipse ellipse){}
    
        @Override
        public void visitFrame(JRFrame frame){}
    
        @Override
        public void visitImage(JRImage image){}
    
        @Override
        public void visitLine(JRLine line){}
    
        @Override
        public void visitRectangle(JRRectangle rectangle){}
    
        @Override
        public void visitStaticText(JRStaticText staticText){}
    
        @Override
        public void visitSubreport(JRSubreport subreport){
          try{
            String expression = subreport.getExpression().getText().replace(".jasper", "");
            StringTokenizer st = new StringTokenizer(expression, "\"/");
            String subReportName = null;
            while(st.hasMoreTokens())
              subReportName = st.nextToken();
            //Sometimes the same subreport can be used multiple times, but
            //there is no need to compile multiple times
            if(completedSubReports.contains(subReportName)) return;
            completedSubReports.add(subReportName);
            compileReport(subReportName);
          }
          catch(Throwable e){
            subReportException = e;
          }
        }
        @Override
        public void visitTextField(JRTextField textField){}
    
        @Override
        public void visitComponentElement(JRComponentElement componentElement){}
    
        @Override
        public void visitGenericElement(JRGenericElement element){}
      });
      if(subReportException != null) throw new RuntimeException(subReportException);
      return jasperReport;
    }