2015-03-11 3 views
5

परिदृश्य:JasperReport: मुख्य रिपोर्ट चर गणना के लिए इनपुट के रूप में subreport वापसी मूल्यों का उपयोग कैसे

मैंने दो रिपोर्टों: मुख्य रिपोर्ट (के इसे कहते हैं, ए) और subreport (चलो इसे बुलाओ, बी)।

रिपोर्ट ए में विस्तार बैंड पर उप-रिपोर्ट बी शामिल है, इसलिए रिपोर्ट ए डेटासोर्स में प्रत्येक तत्व के लिए उप-रिपोर्ट बी प्रदर्शित होता है। सब-रिपोर्ट बी मुख्य रिपोर्ट ए

जो मैं चाहता हूं उप-रिपोर्ट बी से उन रिटर्न मानों को जोड़ना है और उन्हें मुख्य रिपोर्ट सारांश में कुल मिलाकर एक वैरिएबल देता है।

कि ऐसा करने के लिए, मैं एक नई रिपोर्ट चर कि उन रिटर्न मानों का योग बनाने के लिए ... इस तरह की कोशिश की है:

Variable Definition Example

हालांकि, मैंने पाया कि इस तरह के चर अभिव्यक्ति हमेशा से रहे हैं बैंड विवरण प्रस्तुत करने से पहले मूल्यांकन किया गया, इसलिए मुझे हमेशा पहले उप-रिपोर्ट रिटर्न वैल्यू याद आती है ...

अफसोस की बात है, मूल्यांकन समय (जैसा कि link कहता है) उन प्रकार के चर पर बदला नहीं जा सकता है, इसलिए मैं हूं अटक गया ...

+0

मैं सिवाय इसके कि मैं न केवल पहले उप रिपोर्ट वापसी मान याद आती है एक ही समस्या है,। – Gustavo

उत्तर

2

कुछ घंटों के लिए इसके साथ संघर्ष करने के बाद ... और समाधान के लिए इंटरनेट खोज रहा है ... मैं वर्कअराउंड के साथ आया था (प्रबुद्ध मंच इन थे: one और two)।

सबसे पहले, आपको एक जावा क्लास हेल्पर परिभाषित करने की आवश्यकता है जो आपको कुछ अंकगणितीय ऑपरेशन की गणना करने की अनुमति देता है, मेरे मामले में एक योग ऑपरेशन। मैं इन कक्षाओं में परिभाषित किया गया:

1) एक पाठ:

package reports.utils; 
 

 
import java.util.Map; 
 

 
/** 
 
* Utility that allows you to sum Integer values. 
 
*/ 
 
public class SumCalculator { 
 

 
    /** 
 
    * Stores a map of {@code SumCalculator} instances (A Map instance per thread). 
 
    */ 
 
    private static final ThreadLocalMap<String, SumCalculator> calculatorsIndex = new ThreadLocalMap<>(); 
 

 
    /** 
 
    * The sum total. 
 
    */ 
 
    private int total = 0; 
 

 

 
    /** 
 
    * No arguments class constructor. 
 
    */ 
 
    private SumCalculator() { 
 
     super(); 
 
    } 
 

 

 
    /** 
 
    * Instance a new {@code SumCalculator} with the given ID. 
 
    * 
 
    * @param id {@code SumCalculator}'s ID 
 
    * @return  the new {@code SumCalculator} instance 
 
    */ 
 
    public static SumCalculator get(String id) { 
 
     Map<String, SumCalculator> map = calculatorsIndex.get(); 
 
     SumCalculator calculator  = map.get(id); 
 

 
     if (calculator == null) { 
 
      calculator = new SumCalculator(); 
 
      map.put(id, calculator); 
 
     } 
 
     return calculator; 
 
    } 
 

 

 
    /** 
 
    * Destroy the {@code SumCalculator} associated to the given ID. 
 
    * 
 
    * @param id {@code SumCalculator}'s ID 
 
    * @return  {@code null} 
 
    */ 
 
    public static String destroy(String id) { 
 
     Map<String, SumCalculator> map; 
 

 
     map = calculatorsIndex.get(); 
 
     map.remove(id); 
 

 
     if (map.isEmpty()) { 
 
      calculatorsIndex.remove(); 
 
     } 
 
     return null; 
 
    } 
 

 

 
    /** 
 
    * Resets the {@code SumCalculator} total. 
 
    * 
 
    * @return {@code null} 
 
    */ 
 
    public String reset() { 
 
     total = 0; 
 
     return null; 
 
    } 
 

 

 
    /** 
 
    * Adds the given integer value to the accumulated total. 
 
    * 
 
    * @param i  an integer value (can be null) 
 
    * @return  {@code null} 
 
    */ 
 
    public String add(Integer i) { 
 
     this.total += (i != null) ? i.intValue() : 0; 
 
     return null; 
 
    } 
 

 

 
    /** 
 
    * Return the accumulated total. 
 
    * 
 
    * @return an Integer value (won't be null, never!) 
 
    */ 
 
    public Integer getTotal() { 
 
     return this.total; 
 
    } 
 
}

package reports.utils; 
 

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

 
/** 
 
* Thread Local variable that holds a {@code java.util.Map}. 
 
*/ 
 
class ThreadLocalMap<K, V> extends ThreadLocal<Map<K, V>> { 
 

 
    /** 
 
    * Class Constructor. 
 
    */ 
 
    public ThreadLocalMap() { 
 
     super(); 
 
    } 
 

 

 
    /* (non-Javadoc) 
 
    * @see java.lang.ThreadLocal#initialValue() 
 
    */ 
 
    @Override 
 
    protected Map<K, V> initialValue() { 
 
     return new HashMap<>(); 
 
    } 
 
}

दूसरा, अपने Jasper रिपोर्ट में, आप चार पाठ फ़ील्ड परिभाषित करने की जरूरत वह फ़ील्ड जो आपके कैलकुलेटर को अचयनित करता है; यह रिपोर्ट के शीर्षक खंड पर (आदर्श) होना चाहिए और इस तरह की अभिव्यक्ति होनी चाहिए: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").reset()। इस पाठ फ़ील्ड में मूल्यांकन का समय होना चाहिए: अब।

2) एक पाठ क्षेत्र वेतन वृद्धि फ़ंक्शन को कॉल (यानी SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").add($V{SUB_REPORT_RETURN_VALUE}) यह पाठ क्षेत्र अपने विस्तार बैंड पर, subreport तत्व के बाद निवास करेंगे, और यह मूल्यांकन समय होना चाहिए:। बैंड (यह बहुत महत्वपूर्ण है !!)

3) कैलकुलेटर कुल प्रिंट करने वाला एक टेक्स्ट फ़ील्ड। यह टेक्स्ट फ़ील्ड आपके सारांश बैंड पर रहेगा, यह अब का मूल्यांकन करेगा। इसकी अभिव्यक्ति होगी: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").getTotal()

4) कैलकुलेटर को नष्ट करने वाला एक टेक्स्ट फ़ील्ड। यह टेक्स्ट फ़ील्ड आपके सारांश बैंड पर भी रहेगा और टेक्स्ट फ़ील्ड 3 के बाद दिखाई देना चाहिए। टेक्स्ट फ़ील्ड में अभिव्यक्ति होनी चाहिए: SumCalculator.destroy("$V{SUB_REPORT_RETURN_VALUE}")।इस पाठ फ़ील्ड में मूल्यांकन का समय होना चाहिए: अब।

इसके अलावा, टेक्स्ट फ़ील्ड्स: 1, 2, और 4, में "नल" खाली होना चाहिए, इसलिए उन्हें कभी मुद्रित नहीं किया जाएगा (यही कारण है कि वे जावा ऑपरेशन हमेशा शून्य हो जाते हैं)।

और यही वह है। फिर, अपनी रिपोर्ट कुछ इस तरह देख सकते हैं:

reportExample

+0

बहुत जटिल। अगर वहाँ एक "बैंड" एक चर के लिए प्रकार रीसेट ... – Gustavo

+0

मैं कोई विशेषज्ञ हूँ, लेकिन मैं समझता हूँ कि इस तरह के केवल रीसेट चर अभिव्यक्ति के साथ काम करता है (जो मेरी आवश्यकता को कवर नहीं कर सकते हैं) की तरह कुछ –

+0

था मैं प्रकार को बढ़ा देते हैं, न मतलब रीसेट प्रकार। माफ़ कीजिये। वृद्धि तब होती है जब अभिव्यक्ति से मूल्य प्राप्त होता है ($ V {SUB_REPORT_RETURN_VALUE})। – Gustavo

0

अगर मैं समस्या को समझने के लिए, आप राशि मुख्य रिपोर्ट में उप रिपोर्ट द्वारा दिया संक्षेप में प्रस्तुत नहीं कर सकता, मैं एक ही समस्या थी और मैं में हल इस तरफ।

1.- एक कक्षा बनाएं जो net.sf.jasperreports.engine.JRDefaultScriptlet से फैली हुई है। और से पहले विधि को ओवरराइड करें रिपोर्ट()

यह इस कक्षा का कोड है।

package com.mem.utils; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 

import net.sf.jasperreports.engine.JRDefaultScriptlet; 

public class SumarizacionSubtotales extends JRDefaultScriptlet { 
    private final Log log = LogFactory.getLog(getClass()); 

    private Double total; 

    public Double getTotal() { 
     return total; 
    } 

    public Double add(Double cantidad) { 
     if(log.isDebugEnabled())log.debug("AGREGANDO LA CANTIDAD : " + cantidad); 
     this.total += cantidad; 
     return cantidad; 
    } 
    @Override 
    public void beforeReportInit() throws JRScriptletException { 
     if(log.isDebugEnabled())log.debug("beforeReportInit"); 
     total = 0.0D; 
    } 
} 

2.- अपने प्रोजेक्ट के जार को अपने आईरपोर्ट के क्लासपाथ में जोड़ें। ireport classpath config.

3.- रिपोर्ट स्क्रिप्टलेट की कक्षा को बदलें। default REPORT scriptlet

अपनी कक्षा के साथ गुण में

your class

3.- समूह पाद लेख में जोड़ें जहां आप निम्न अभिव्यक्ति के साथ एक पाठ फ़ील्ड उप-रिपोर्ट द्वारा लौटाए गए मान को मुद्रित करना चाहते हैं।

$P{REPORT_SCRIPTLET}.add($V{sum_detalles}) 

इस मामले $ वी {sum_detalles} मुख्य रिपोर्ट जो उप रिपोर्ट द्वारा दिए गए मान होता है में एक चर है।

4. निम्नलिखित अभिव्यक्ति के साथ एक और पाठ फ़ील्ड अंतिम पृष्ठ पाद लेख जोड़ें।

$P{REPORT_SCRIPTLET}.getTotal() 

report structure

+0

मेरी असली समस्या अभिव्यक्ति का मूल्यांकन समय था जो वैश्विक रिपोर्ट के लिए चर की गणना करता है (इसकी गणना प्रत्येक बैंड विवरण से पहले की गई थी, इसलिए मुझे हमेशा पहले सब्रेपोर्ट का रिटर्न मान याद आती है) ... ऐसा लगता है कि (आपके अनुसार उदाहरण) प्रत्येक बैंड विवरण के प्रस्तुत करने के बाद स्क्रिप्टलेट क्लास का मूल्यांकन किया जाता है ... –

+0

यदि आप कोड देखते हैं तो मैंने कक्षा में पहले एक रिपोर्ट ** पहले रिपोर्ट() ** जोड़ा है, यह आपको चर को प्रारंभ करने की अनुमति देता है, मैंने मेरे लिए ठीक काम किया । – OJVM

संबंधित मुद्दे