如何對報表資料新增目錄

xiaohuihui發表於2019-11-21

需求描述:

在做一些類似 word 報告格式報表時,為了有更好的閱讀效果,經常需要在首頁增加一個目錄導航頁,這樣就能夠快速的知道關心的資料在第幾頁,但是報表不同於 word 文件,word 文件中格式都是固定的,所以能夠方便快速的生成目錄頁,在報表中資料都是動態變化的,並且通常會涉及到動態擴充套件,這樣很難固定目錄項,並且由於資料動態擴充套件,對應的頁碼也很難精確獲得,下面透過一個例項看下,如果在報表中動態增加目錄。

解決方案:

報表資料是動態的,所以設計時就不能用固定的目錄,需要報表計算後才能知道資料在第幾頁,潤乾報表提供了一個報表計算偵聽類,在 java 程式中可以動態獲取報表計算後的結果,並能夠在程式中動態更改單元格的值。

首先,看下報表模板的設計介面:

1jpg

這個報表要對訂單資料按照地區進行彙總分析,並展示詳細資料,要求目錄中以地區為導航進行設定,報表前 5 行是目錄頁,第三行中,概要分析一般是固定的,這裡就寫了固定一行,頁碼設定 2 就行。

A4:=ds1.group(貨主地區; 貨主地區:1),表示式按照地區進行分組,也就是目錄這塊按照地區進行展示,對應 E4 單元格後續要設定成目錄頁,此處暫時為空。

A5:目錄通常在第一頁,所以此處設定一個行後分頁

A7:就是一個固定的彙總描述,裡邊可以用字串拼接方式將固定文字和動態資料拼接在一起展示。

A8:=ds1.group(貨主地區; 貨主地區:1),按照地區進行分組

A9:對該地區資料做一個彙總說明

A10:=ds1.select(訂單 ID),取數訂單資料,B10 往後依次類推。

將 A9,A10,A11,A12 單元格的左主格設定成 A8,此片資料根據 A8 進行縱向擴充套件,這樣報表展示結果為:

2jpg

這裡可以看到,目錄項處列出了對應地區,接下來看下,如果給地區增加對應頁碼。

從報表結果中看到,第一頁中的目錄名稱和報表中的地區名稱相同,這樣就可以根據這兩個名稱做匹配,判斷如果名稱相同獲取資料區域的名稱所在的頁碼,放到對應目錄行就行,如資料區域的“東北”在第 2 頁,那麼目錄中東北的頁碼應該為 2,接下來看下,如何給目錄設定動態的頁碼。

這裡就用到了之前說到的報表偵聽類的使用,原始碼如下:

import com.raqsoft.common.Area;
import com.raqsoft.report.usermodel.Context;
import com.raqsoft.report.usermodel.IPagerListener;
import com.raqsoft.report.usermodel.IReport;
import com.raqsoft.report.usermodel.IReportListener;
import com.raqsoft.report.usermodel.PageBuilder;
import com.raqsoft.report.util.ReportUtils;
public class createmulu implements IReportListener {
	 public void afterCalc(Context arg0, IReport arg2) { 
		 PageBuilder arg1 = null;
		try {
			arg1 = new PageBuilder(arg2);
		} catch (Throwable e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
			System.out.println("報表總頁數"+arg1.getPageCount());
			IReport p1;
			try {
				 p1=arg1.getPage(1);//目錄通常在第一頁,所以獲取第一頁為目錄頁
				 int page=2;//設定資料初始迴圈頁,通常為第二頁
				 for(int i=3;i<=p1.getRowCount();i++){//目錄行從第三行開始
					String muluName=(String)p1.getCell(i, 2).getValue() ;//報表中設定第二頁為目錄名稱
					for(int j=page;j<=arg1.getPageCount();j++){//按照頁數進行迴圈,分別取分頁後每頁報表物件
						for(int k=1;k<=arg1.getPage(j).getRowCount();k++){//每頁中按照每行進行迴圈		
						String mName=arg1.getPage(j).getCell(k,1).getValue() != null ? arg1.getPage(j).getCell(k,1).getValue().toString() : "";//本例中目錄項在報表中的第一列,也就是A8單元格
						if(mName!="" && mName==muluName){//判斷每頁中的目錄項和第一頁中的目錄名稱是否相同
							arg2.getCell(i, 5).setValue(j);//如果相同,則設定目錄頁第5列對應的值為對應頁碼,注意,此處是arg2物件
							arg2.getCell(i, 5).setHyperlink("javaScript:toPage('report1',"+j+")");//設定超連結
							page=j;//為提高計算效率,下次在迴圈時,不用從第2頁開始,從上次終端的頁碼開始就行
							break;//找到頁碼,跳出此處迴圈,提高效率
						}	
						}
					} 
				 }
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
	   } 
	   public void beforeCalc(Context arg0, IReport arg1) { 
	   } 
	
}

核心思路就是在類中根據名稱進行匹配,獲取頁碼,放到對應單元格中,將編譯好的類放到報表類路徑中,如:應用的 WEB-INF\classes 下,注意如果有包路徑,此處要要帶相應的路徑,放置過去後重啟應用,在頁面端訪問報表,結果如下:

3jpg

可以看到,目錄後邊會生成對應的頁碼,word 中目錄有個功能點是,點選頁碼,能夠快速跳轉到對應的頁數,報表中同樣可以增加對應的功能,報表提供了一個跳轉頁數的 js 函式,toPage,在 java 類中,在對應的頁碼單元格設定了一個超連結,呼叫這個 js 就行:

arg2.getCell(i, 5).setHyperlink("javaScript:toPage('report1',"+j+")");

這樣,在頁面端點選頁碼,就能夠快速跳轉到對應頁數,當然,此功能要求報表在頁面端分頁後才有效,否則無法跳轉,並且如果匯出到 word 的話,只能顯示頁數,無法跳轉。

透過這個例子可以看到,透過拿目錄項中的單元格資料和資料表中的單元格進行匹配,來獲取頁碼,但是在實際使用中,目錄頁中的目錄名稱和報表中的資料名稱可能並不完全一致,比如目錄頁中叫東北,報表資料中叫東北地區,很難嚴格匹配,這樣可以換種變通的方法,報表單元格屬性欄中有個註釋屬性,可以在這個裡邊寫上和目錄項匹配的值,然後 java 類中可以根據這個屬性的值做匹配,這樣能夠實現更加靈活的效果,更多 api 介面可以參考報表幫助文件《程式設計師參考》,後續帶來更多 api 在報表實際需求中的應用。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900830/viewspace-2665125/,如需轉載,請註明出處,否則將追究法律責任。

相關文章