스크립틀릿보고

이전 장에서 보았던 것처럼 보고서에 표시된 데이터는 일반적으로 보고서 매개 변수 및 보고서 필드에서 가져옵니다. 이 데이터는 보고서 변수 및 해당 표현식을 사용하여 처리 할 수 ​​있습니다. 보고서 식이나 변수를 사용하여 복잡한 기능을 쉽게 구현할 수없는 상황이 있습니다. 이에 대한 예로는 복잡한 문자열 조작, 맵 빌드, 메모리의 객체 목록 또는 타사 Java API를 사용한 날짜 조작이 있습니다. 이러한 상황에서 JasperReports는이를 통해이를 수행 할 수있는 간단하고 강력한 수단을 제공합니다.Scriptlets.

스크립틀릿은 보고서 이벤트가 발생할 때마다 실행되는 Java 코드 시퀀스입니다. 보고서 변수의 값은 스크립틀릿을 통해 영향을받을 수 있습니다.

Scriptlet 선언

두 가지 방법으로 스크립틀릿을 선언 할 수 있습니다.

  • <사용scriptlet> 요소. 이 요소에는 이름 속성과 클래스 속성이 있습니다. 클래스 속성은 확장하는 클래스의 이름을 지정해야합니다 JRAbstractScriptlet의 클래스를. 클래스는 보고서 작성 시간에 클래스 경로에서 사용할 수 있어야하며 엔진이 즉석에서 인스턴스화 할 수 있도록 빈 생성자가 있어야합니다.

  • 속성 사용 scriptletClass 요소 <jasperReport>, 보고서 템플릿 (JRXML). 이 속성을 완전한 스크립틀릿 이름 (전체 패키지 이름 포함)으로 설정함으로써 스크립틀릿을 사용하고자 함을 나타냅니다. 이 속성으로 생성 된 스크립틀릿 인스턴스는 스크립틀릿 목록에서 첫 번째 스크립틀릿처럼 작동하며 미리 정의 된 이름이 REPORT입니다.

Scriptlet 클래스

스크립틀릿은 다음 클래스 중 하나를 확장해야하는 Java 클래스입니다.

  • net.sf.jasperreports.engine.JRAbstractScriptlet−이 클래스는 모든 구현에서 재정의되어야하는 여러 추상 메서드를 포함합니다. 이러한 메서드는 적절한 순간에 JasperReports에 의해 자동으로 호출됩니다. 개발자는 모든 추상 메서드를 구현해야합니다.

  • net.sf.jasperreports.engine.JRDefaultScriptlet−이 클래스는 JRAbstractScriptlet의 모든 메소드의 기본 빈 구현을 포함합니다. 개발자는 자신의 프로젝트에 필요한 방법을 구현하기 만하면됩니다.

다음 표에는 위 클래스의 메서드가 나열되어 있습니다. 이러한 메서드는 보고서 작성 단계에서 적절한 시간에 보고서 엔진에 의해 호출됩니다.

S.NO 방법 및 설명
1

public void beforeReportInit()

보고서 초기화 전에 호출됩니다.

2

public void afterReportInit()

보고서 초기화 후에 호출됩니다.

public void beforePageInit()

각 페이지가 초기화되기 전에 호출됩니다.

4

public void afterPageInit()

각 페이지가 초기화 된 후 호출됩니다.

5

public void beforeColumnInit()

각 열이 초기화되기 전에 호출됩니다.

6

public void afterColumnInit()

각 열이 초기화 된 후 호출됩니다.

7

public void beforeGroupInit(String groupName)

매개 변수에 지정된 그룹이 초기화되기 전에 호출됩니다.

8

public void afterGroupInit(String groupName)

매개 변수에 지정된 그룹이 초기화 된 후 호출됩니다.

9

public void beforeDetailEval()

보고서의 세부 사항 섹션에있는 각 레코드가 평가되기 전에 호출됩니다.

10

public void afterDetailEval()

보고서의 세부 사항 섹션에있는 각 레코드가 평가 된 후 호출됩니다.

보고서 당 원하는 수의 스크립틀릿을 지정할 수 있습니다. 보고서에 스크립틀릿이 지정되지 않은 경우 엔진은 여전히 ​​단일 JRDefaultScriptlet 인스턴스를 생성하고 내장 REPORT_SCRIPTLET 매개 변수를 사용하여 등록합니다.

스크립틀릿에 필요한 추가 메서드를 추가 할 수 있습니다. 보고서는 내장 매개 변수 REPORT_SCRIPTLET을 사용하여 이러한 메소드를 호출 할 수 있습니다.

글로벌 스크립틀릿

스크립틀릿을 전역 적으로 선언하는 다른 방법으로 스크립틀릿을 보고서에 연결할 수 있습니다. 이렇게하면 주어진 JasperReports 배포에 채워지는 모든 보고서에 스크립틀릿이 적용됩니다. 이는 스크립틀릿을 JasperReports에 확장으로 추가 할 수 있다는 사실로 인해 쉽게 이루어집니다. 스크립틀릿 확장 점은 net.sf.jasperreports.engine.scriptlets.ScriptletFactory 인터페이스로 표시됩니다 . JasperReports는 런타임에 확장을 통해 사용 가능한 모든 스크립틀릿 팩토리를로드합니다. 그런 다음 실행중인 현재 보고서에 적용 할 스크립틀릿 인스턴스 목록을 각각 요청합니다. 스크립틀릿 인스턴스 목록을 요청할 때 엔진은 팩토리가 현재 보고서에 실제로 적용 할 스크립틀릿을 결정하기 위해 사용할 수있는 컨텍스트 정보를 제공합니다.

총재보고

거버너는 보고서를 생성하는 동안 런타임에 무한 루프에 진입하는 보고서 엔진 문제를 해결할 수있게 해주는 글로벌 스크립틀릿의 확장 일뿐입니다. 대부분의 경우 무한 루프를 입력하기위한 조건은 런타임에 엔진에 공급되는 실제 데이터에 따라 다르기 때문에 디자인 타임에는 잘못된 보고서 템플릿을 감지 할 수 없습니다. 보고서 관리자는 특정 보고서가 무한 루프에 들어 갔는지 여부를 결정하는 데 도움을 주며이를 중지 할 수 있습니다. 이렇게하면 보고서를 실행하는 시스템의 리소스 고갈을 방지 할 수 있습니다.

JasperReports에는 지정된 최대 페이지 수 또는 지정된 시간 초과 간격에 따라 보고서 실행을 중지하는 두 개의 간단한 보고서 관리자가 있습니다. 그들은-

  • net.sf.jasperreports.governors.MaxPagesGovernor− 현재 실행중인 보고서에 적용할지 여부를 결정하기 위해 두 가지 구성 속성을 찾는 글로벌 스크립틀릿입니다. 구성 속성은-

    • net.sf.jasperreports.governor.max.pages.enabled=[true|false]

    • net.sf.jasperreports.governor.max.pages=[integer]

  • net.sf.jasperreports.governors.TimeoutGovernor− 이것은 또한 적용 여부를 결정하기 위해 다음 두 가지 구성 속성을 찾는 글로벌 스크립틀릿입니다.

    구성 속성은-

    • net.sf.jasperreports.governor.timeout.enabled=[true|false]

    • net.sf.jasperreports.governor.timeout=[milliseconds]

두 관리자의 속성은 jasperreports.properties 파일에서 전역 적으로 설정하거나 보고서 수준에서 사용자 정의 보고서 속성으로 설정할 수 있습니다. 이는 서로 다른 보고서가 서로 다른 예상 크기 또는 제한 시간 한계를 가질 수 있고 또한 모든 보고서에 대해 관리자를 켜고 일부에 대해서는 끄거나 그 반대로 할 수 있기 때문에 유용합니다.

스크립틀릿 클래스 (MyScriptlet). C : \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint \ MyScriptlet.java 파일의 내용은 다음과 같습니다.

package com.tutorialspoint;

import net.sf.jasperreports.engine.JRDefaultScriptlet;
import net.sf.jasperreports.engine.JRScriptletException;


public class MyScriptlet extends JRDefaultScriptlet {

   public void afterReportInit() throws JRScriptletException{
      System.out.println("call afterReportInit()");
      // this.setVariableValue("AllCountries", sbuffer.toString());
      this.setVariableValue("someVar", new String("This variable value 
         was modified by the scriptlet."));
   }

   public String hello() throws JRScriptletException {
      return "Hello! I'm the report's scriptlet object.";
   }

}

위의 스크립틀릿 클래스에 대한 자세한 내용은 다음과 같습니다.

  • 에서 afterReportInit에 있어서, 우리는 변수에 값을 설정"someVar" this.setVariableValue ( "someVar", new String ( "이 변수 값은 스크립틀릿에 의해 수정되었습니다.")).

  • 클래스가 끝나면 추가 메서드가 호출됩니다. 'hello'정의되었습니다. 이것은 변수를 설정하는 대신 실제로 값을 반환하는 Scriptlet에 추가 할 수있는 메서드의 예입니다.

다음으로 기존 보고서 템플릿 ( 보고서 디자인 장)에 스크립틀릿 클래스 참조를 추가합니다 . 수정 된 보고서 템플릿 (jasper_report_template.jrxml)은 다음과 같습니다. C : \ tools \ jasperreports-5.0.1 \ test 디렉토리에 저장하십시오-

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<jasperReport xmlns = "http://jasperreports.sourceforge.net/jasperreports"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://jasperreports.sourceforge.net/jasperreports
   http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
   name = "jasper_report_template" pageWidth = "595"
   pageHeight = "842" columnWidth = "515"
   leftMargin = "40" rightMargin = "40" topMargin = "50" bottomMargin = "50"
   scriptletClass = "com.tutorialspoint.MyScriptlet">
	
   <style name = "alternateStyle" fontName = "Arial" forecolor = "red">
      
      <conditionalStyle>
         <conditionExpression>
            <![CDATA[new Boolean($V{countNumber}.intValue() % 2 == 0)]]>
         </conditionExpression>
			
         <style forecolor = "blue" isBold = "true"/>
      </conditionalStyle>
   </style>
   
   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>

   <queryString>
      <![CDATA[]]>
   </queryString>

   <field name = "country" class = "java.lang.String">
      <fieldDescription>
         <![CDATA[country]]>
      </fieldDescription>
   </field>

   <field name = "name" class = "java.lang.String">
      <fieldDescription>
         <![CDATA[name]]>
      </fieldDescription>
   </field>

   <variable name = "countNumber" class = "java.lang.Integer" 
      calculation = "Count">
      <variableExpression><
         ![CDATA[Boolean.TRUE]]>
      </variableExpression>
   </variable>

   <variable name = "someVar" class = "java.lang.String">
      <initialValueExpression>
        <![CDATA["This is the initial variable value."]]>
      </initialValueExpression>
   </variable>

   <title>
      <band height = "100">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
              <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
              <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
				
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
        
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
         
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "50" width = "515" 
               height = "30" forecolor = "#993300"/>
             
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$V{someVar}]]>
            </textFieldExpression>
				
         </textField>

      </band>
   </title>

   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" 
               width = "535" height = "15"
               backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
				
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
                
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
				
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" 
               width = "535"	height = "14"
               backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement style = "alternateStyle" x="414" y = "0" 
               width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
				
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
   
   <summary>
      <band height = "45">
            
         <textField isStretchWithOverflow = "true">
            <reportElement x = "0" y = "10" width = "515" height = "15" />
            <textElement textAlignment = "Center"/>
               
            <textFieldExpression class = "java.lang.String">
               <![CDATA["There are " + String.valueOf($V{REPORT_COUNT}) +
                  " records on this report."]]>
            </textFieldExpression>
         </textField>
         
         <textField isStretchWithOverflow = "true">
            <reportElement positionType = "Float" x = "0" y = "30" width = "515"
               height = "15" forecolor = "# 993300" />
               
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
               
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{REPORT_SCRIPTLET}.hello()]]>
            </textFieldExpression>
            
         </textField>
         
      </band>
   </summary>
	
</jasperReport>

수정 된 보고서 템플릿의 세부 사항은 다음과 같습니다.

  • <jasperReport> 요소의 scriptletClass 속성에서 MyScriptlet 클래스를 참조했습니다 .

  • 스크립틀릿은 보고서 필드 및 매개 변수에 액세스 할 수만 있고 수정할 수는 없습니다. 그러나 스크립틀릿은 보고서 변수 값을 수정할 수 있습니다. 이는 setVariableValue () 메서드를 호출하여 수행 할 수 있습니다. 이 메서드는 항상 모든 스크립틀릿의 부모 클래스 인 JRAbstractScriptlet 클래스에 정의되어 있습니다. 여기에서 변수 someVar를 정의했습니다.이 변수 는 MyScriptlet에서 This value was modified by the scriptlet 값 을 갖도록 수정됩니다 .

  • 위의 보고서 템플릿에는 요약 밴드에 새 메서드 (스크립틀릿에서)를 작성하고 보고서 템플릿에서 사용하는 방법을 보여주는 메서드 호출이 있습니다. ($P{REPORT_SCRIPTLET}.hello())

보고서 채우기를위한 Java 코드는 변경되지 않습니다. 파일의 내용C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java 다음과 같습니다-

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO 파일의 내용 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java 다음과 같습니다-

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

파일의 내용 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java 다음과 같습니다-

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

보고서 생성

일반 ANT 빌드 프로세스를 사용하여 위 파일을 컴파일하고 실행합니다. build.xml 파일 (C : \ tools \ jasperreports-5.0.1 \ test 디렉토리에 저장 됨)의 내용은 다음과 같습니다.

가져 오기 파일-baseBuild.xml은 환경 설정 장에서 선택 되며 build.xml과 동일한 디렉토리에 있어야합니다.

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview 
      the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>

</project>

다음으로 명령 줄 창을 열고 build.xml이있는 디렉터리로 이동합니다. 마지막으로 명령을 실행하십시오.ant -Dmain-class=com.tutorialspoint.JasperReportFill (viewFullReport는 기본 대상입니다)-

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to bu
   [javac] Compiling 4 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.
   [java] call afterReportInit()
   [java] call afterReportInit()

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 18 minutes 49 seconds

위의 컴파일 결과 아래 주어진 화면과 같이 JasperViewer 창이 열립니다.

여기 MyScriptlet 클래스에서 두 개의 메시지가 표시됩니다.

  • 제목 섹션에서- 이 변수 값은 스크립틀릿에 의해 수정되었습니다
  • 하단- 안녕하세요! 나는 보고서의 스크립틀릿 개체입니다.