Reporting Service報表的群組概念十分實用,例如: 若要以報表方式產出信用卡帳單,只需加上Group By ClientId,就可將上百名客戶的數千筆消費記錄,依客戶別彙整成一份份帳單,再整合成一大份報表,方便一次全部列印出來,再分裝寄發。

但問題來了,每個客戶的帳單可能有多頁,帳單印上”第幾頁/共幾頁”本是天經地義的事。Reporting Service中有Global!PageNumber及Globals!TotalPages的屬性,做到這一點似非難事。但是這兩個屬性只能在整個報表的Page Header區使用(也就是只能算報表中所有客戶帳單總頁數),在Group Header或Detail中呼叫會產生Error,網路上有人試過了Me.Report.Globals繞路法,可以在Group Header或Detail區讀到這兩個數字,但它們的值卻會永遠傳回1。有人想出了Reset PageNumber的巧妙做法,但仍無法知道該Group共幾頁? 我靈光一現,想說何不每個客戶一個SubReport,在SubReport中的Page Header區,總頁數總會正確吧? 很可惜,事情並不像憨人所想的哈泥甘單,SubReport的Header & Footer一律會被忽略而無法顯示,精心想出的妙計又摃龜了。

搞了半天,幾頁之幾這麼基本的要求,Reporting Service做不到就是做不到,我Google了好一陣子,最後自己做過實驗後,終於死心了。由於Group Header跟Detail要全部Render完,Reporting Service才依這些Content的高度算出總共有幾頁,等算出來時,Group Header與Detail的內容早就定死了。故得證,除非Reporting Service改變Rendering的機制,要在Group中取得TotalPages肯定是無解了!! 莫非得砸下銀子改買Crystal Report之類的報表工具才能解脫? 

眼看為一個理所當然的小小頁碼,Reporting Service竟形同廢物,心有不甘。我決定換個方向,不再硬碰硬,逃出PageNumber跟TotalPages的死胡同。一個另類的想法是,如果單一份報表中, PageNumber跟TotalPager才能正常使用,那就一個客戶獨立出一份報表吧!

利用ASP.NET設計如下的查詢介面,依User提供的條件,可列出多個客戶的報表連結(每個報表參數不同,等同於多份彼此獨立的報表),點下連結後可檢視該客戶的報表。這樣就解決了查詢單一客戶報表的功能,足以應付大部分的查詢需求。(如下圖)

然而,這種做法與多客戶帳單組成一份報表,最大差別在於無法一次列印全部的帳單。於是,我從Reporting Service線上列印的功能偷出以下的程式碼,寫成一隻直接印表程式(RptPrint.aspx):

RSIssue3

只要在hdnRptSvr及hdnRptUrl中填妥報表相關的網址及參數,RptPrint.aspx就會直接啟動Reporting Service的線上列印功能,跳出選擇印表機的對話框,可預覽報表,或按確定直接列印。(如下圖)

有了這隻好用的直接列印程式,只要在剛才的清單頁面上用javascript跑個for loop,將N個客戶的報表URL當作參數,再以showModalDialog方式循序開啟RptPrint.aspx,就可以一口氣將N個客戶的帳單印完。現在只剩下一個棘手的問題---RSClientPrint.Print()時並不會直接輸出到印表機,而是帶出如上的印表對話框,User必須按下確定後才開始印表。這意味著如果要出1000個客戶的帳單,User得泡杯茶,帶本小說,坐在電腦前等著按1000次確定,既無聊又無奈。

留下這個尾巴,這個解決方案還不算可行。因此我參考IEUnit中威力強大的Win32Dom.Desktoop物件,寫了一個會自動按"確定"的小幫手程式。當要大量印表時,它會不斷監控是否有RSClientPrint彈出的印表對話框,一旦發現,就瞄準"確定"鈕大力按下去,由預設印表機輸出報表。如此,批次印表的流程總算是一氣喝成了!

透過這幾記怪招的巧妙組合,算是克服了頁碼與批次列印無法兼得的困境。但還是祈禱MS能在未來的Reporting Service改版中,從核心層次解決Group中使用頁碼的問題,才是治本之道;在此之前,大家可考慮用這種方法頂著先。

【2016-12-13 更新】

十年之後,收到同事 Karin 回報,Reporting Service 2008 起已支援依群組計算分頁,只需開啟 ResetPageNumber 屬性即可,不用再如此搞剛了。細節可參考網友的文章


Comments

# by steve

自動按確定是吧......<BR/>怎麼覺得好像蠻適合拿來當某種木馬程式的....<BR/>管你IE安全性怎麼設,跳出幾個提示確認視窗<BR/>一律給你按YES.......

# by Darkthread

安啦! 我的程式還是有一定的嚴謹性,會識別列印對話框的某些特徵才按鈕,不至於發狂地見確定就按。不過,會不會有人偷去改寫為非做歹,這我就不敢保證。咳... 萬一檢察官來問話,我倒是會提供幾個有這類意圖的"疑犯"姓名就是了。

# by 阿毛

請問Reporting Service線上列印的功能在哪邊偷呢@@? 我找好久都找不到阿= = 大感謝阿

# by Jeffrey

to 阿毛,在線上列印的過程中,網站會在背地裡送出文中的那個網頁,由於從介面是不可見的,因此得用Fiddler或Firebug之類的工具攔截瀏覽器與Server間暗地傳送的網頁內容。

# by Irene

不好意思,請問方便提供你那支會自動按"確定"的小幫手程式嗎?...或給點提示也可以....最近也遇到一樣的問題,頭快爆炸了...>.<

# by Jeffrey

to Irene, 程式內含一些工作相關的東西,暫無法直接提供原始碼,請見諒。但其運作原理參考自IEUnit,並不複雜,在http://code.google.com/p/ieunit/source/browse/trunk/lib/Win32Dom.js 裡可以找到一段程式碼,會每隔0.1秒去查特定標題的對話框/視窗,找到後再去找其中的Button,大力按下去,程式的運作原理幾乎一模一樣。

# by sky

請問一下大大,如果我報表是用矩陣來做的,但長度超過列印紙張大小時,印表機會自動分成兩頁,如果我想分成兩頁時,第二頁也帶有表頭的話,要怎麼做才行呢 ?

Post a comment


75 + 25 =