Powered By

Skin Design:
Free Blogger Skins

Powered by Blogger

Cari Blog Ini

28 Januari 2008

Customisasi Proses iReport dengan Scriptlet

Kemarin saya mendapat request pembuatan report baru. Yang dimaksud report adalah iReport nya Jasper. Report baru ini modelnya seperti kartu stok, tetapi produk yang ditampilkan tidak berurutan. Di kartu stok kan hanya menampilkan pergerakan satu produk dari tanggal sekian ke tanggal sekian. Jika pun ada lebih dari satu produk, maka pasti di group per produk, sehingga antara produk satu dengan yang lain tidak bercampur. Nah, report baru ini, modelnya group per Invoice, sehingga produk pasti bercampur.

Produk
Jual
Saldo
Petis ABC
100
1000
Kecap ABC
200
550
Petis ABC
300
700
Kecap ABC
500
50
Contoh Tampilan

Wah, lumayan sulit ini. Jika hanya menggunakan query, sepertinya gak bisa. Mungkin bisa sedikit permainan di iReport? Kalau kartu stok sih bisa bikin saldonya karena urut (tidak lompat-lompat). Ya di urutin juga donk! Wah tidak bisa, soalnya di group per nomor Order. Ada beberapa usul dari rekan-rekan. "Coding di Java, jadi report nya terintegrasi di Adempiere". Atau, "Pake cursor aja di postgres nya. Jadi tinggal panggil fungsi langsung jadi data mateng". Wah kalau coding di Adempiere, nantinya jadi gak customable lagi. Ubah report, ubah source code, dan akhirnya update program ke client-client di cabang. Opsi kedua, pakai cursor? Pertama, saya belum pernah sama sekali membuat script di database (di SQLServer saja belum pernah, apalagi di Postgres). Kedua, debugnya sulit setengah mati. Ketiga, maintenance juga repot karena jika update report harus update database. Sempat terlintas ide untuk menggabungkan keduanya, yaitu membuat function dalam PLJava. Mudah dalam programingnya dan terintegrasi di database. Tapi saya masih kurang sreg dengan cara ini....

Di saat pusing itu, tiba-tiba teringat bahwa di iReport terdapat Scriptlet. Suatu fasilitas untuk customisasi proses pengisian data. Karena iReport menggunakan Java, maka scriplet put menggunakan pure Java. Scriptlet di iReport adalah dalam bentuk satu class yang diturunkan dari obyek it.businesslogic.ireport.IReportScriptlet. Ada beberapa method yaitu:
  • afterColumnInit
  • afterDetailEval
  • afterGroupInit
  • afterPageInit
  • afterReportInit
  • beforeColumInit
  • beforeDetailEval
  • beforeGroupInit
  • beforePageInit
  • beforeReportInit
Kita dapat melakukan customisasi proses-proses diatas dengan bebas. Untuk mengakses field-field, variable atau paramter, kita tinggal menggunakan fungsi:
getFieldValue("")
getVariableValue("")
getParameterValue("")


Sedang untuk mengeset, tinggal ubah get menjadi set, dan parameter fungsi ditambah dengan value yang akan di masukkan. Selain itu, kita dapat menambah fungsi sendiri di dalam class Scriptlet nya, dan untuk mengakses fungsi tersebut dengan cara:
$P{REPORT_SCRIPTLET}.()

Untuk menggunakna scriptlet di iReport, kita harus menambah tools.jar di classpath iReport (tools.jar terdapat di JAVA_HOME\lib). Setelah itu, kita dapat menggunakan scriptlet editor milik iReport.


Tampilan Scriptlet Editor

Selain menggunakan internal editor, kita juga dapat menggunakan editor lain dan menggunakan langsung binnary class nya. Namun kita harus mengcopy binnary class pada folder cache iReport setiap kali kita mengubah scriptlet, karena ketika kita mencompile report di iReport, scriptlet tidak ikut terkompile ulang.

Contoh Scriptlet:
import net.sf.jasperreports.engine.*;
import java.util.*;
import java.math.*;

public class testScriptlet extends it.businesslogic.ireport.IReportScriptlet {

/** Creates a new instance of JRIreportDefaultScriptlet */
private HashMap saldo;
private BigDecimal lastSaldo;
public testScriptlet() {
saldo = new HashMap();
lastSaldo = new BigDecimal(0);

}
public BigDecimal getLastSaldo(){
return lastSaldo;
}

/** Begin EVENT_AFTER_COLUMN_INIT This line is generated by iReport. Don't modify or move please! */
public void afterColumnInit() throws JRScriptletException
{
super.beforeColumnInit();
}
/** End EVENT_AFTER_COLUMN_INIT This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_AFTER_DETAIL_EVAL This line is generated by iReport. Don't modify or move please! */
public void afterDetailEval() throws JRScriptletException
{
super.afterDetailEval();
}
/** End EVENT_AFTER_DETAIL_EVAL This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_AFTER_GROUP_INIT This line is generated by iReport. Don't modify or move please! */
public void afterGroupInit(String groupName) throws JRScriptletException
{
super.afterGroupInit(groupName);
}
/** End EVENT_AFTER_GROUP_INIT This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_AFTER_PAGE_INIT This line is generated by iReport. Don't modify or move please! */
public void afterPageInit() throws JRScriptletException
{
super.afterPageInit();
}
/** End EVENT_AFTER_PAGE_INIT This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_AFTER_REPORT_INIT This line is generated by iReport. Don't modify or move please! */
public void afterReportInit() throws JRScriptletException
{

}
/** End EVENT_AFTER_REPORT_INIT This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_BEFORE_COLUMN_INIT This line is generated by iReport. Don't modify or move please! */
public void beforeColumnInit() throws JRScriptletException
{

}
/** End EVENT_BEFORE_COLUMN_INIT This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_BEFORE_DETAIL_EVAL This line is generated by iReport. Don't modify or move please! */
public void beforeDetailEval() throws JRScriptletException
{
BigDecimal prd = (java.math.BigDecimal)getFieldValue("kode_produk");
BigDecimal stok = (java.math.BigDecimal)getFieldValue("stok");
BigDecimal trans = (java.math.BigDecimal)getFieldValue("trans");
if(!saldo.containsKey(prd))//Berarti blm ada stok
saldo.put(prd,stok);
//
BigDecimal tmpStok = (BigDecimal) saldo.get(prd);
stok = tmpStok.add(trans);
saldo.remove(prd);
saldo.put(prd,stok);

lastSaldo = (BigDecimal) saldo.get(prd);
}
/** end EVENT_BEFORE_DETAIL_EVAL Please don't touch or move this comment*/

/** End EVENT_BEFORE_DETAIL_EVAL This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_BEFORE_GROUP_INIT This line is generated by iReport. Don't modify or move please! */
public void beforeGroupInit(String groupName) throws JRScriptletException
{

}
/** End EVENT_BEFORE_GROUP_INIT This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_BEFORE_PAGE_INIT This line is generated by iReport. Don't modify or move please! */
public void beforePageInit() throws JRScriptletException
{

}
/** End EVENT_BEFORE_PAGE_INIT This line is generated by iReport. Don't modify or move please! */
/** Begin EVENT_BEFORE_REPORT_INIT This line is generated by iReport. Don't modify or move please! */
public void beforeReportInit() throws JRScriptletException
{

}

/** End EVENT_BEFORE_REPORT_INIT This line is generated by iReport. Don't modify or move please! */

}

4 komentar:

Anonim mengatakan...

makasih pak buat kisi-kisinya
sangat membantu, walaupun agak membingungkan.... :D
maju terus!!!!

Gue!Shindu mengatakan...

Thx juga. Ya memang saya masih kesulitan dalam menuliskan isi pikiran saya.
Masih perlu latihan terus :)

Agus Pramono mengatakan...

Kalau mau membuat report yang isinya "seperti" bentuk form gimana ya mas?
Jadi, bagian atas report tersebut bentuknya seperti bentuk form pengisian ketika mendaftar di Yahoo/Google. Bagian tengah report itu bentuknya tabel dan bagian bawah report itu bentuknya kembali seperti form.
Semua data diambil dari view pada database.
Oh iya, saya memakai Compiere bukan Adempiere. Tapi sepertinya sama saja. :)

Terima kasih ya mas.

Gue!Shindu mengatakan...

Kalau sekedar tampilan spt form sih bisa, tapi klo sampai harus bisa buat mengisi form itu, rasanya ga bisa.

Logikanya, tinggal menbuat dataset/view yg master detail dimana master nanti ditampilkan sebagai group master (dalam band master) kemudian detailnya ditampilkan di band detail (akhirnya akan muncul sebagai tabel). Sedangkan bagian akhir kan mengikuti footer group master tadi