ABAP:SmartForms 之二--設計

 報表要求:(見下表)


要求:
1、不是套打,表格線也需要輸出
2、每張報表打印8行記錄,不足的空白行也需要輸出
3、按憑證號打印單據,可以連續打印多張報表。

 、創建樣式:
在創建Form之前,需要創建多種段落和字體樣式,供Form中的文字使用。需要設置多種“段落格式”,並且必須在“表頭數據”中設定“標準段落”

1.創建段落格式,一般有RH(Report Header),PD(Page Header), PB(Page Bottom),LD(Line Header and Details),字體:CNSONG,9pt。注意最好在各段落的“首行縮”中設定1mm的縮進,否則,在Form中表格線和文字之間會沒有任何間隙。
2.設置“表頭數據”中“標準段落”
3、保存並激活樣式文件。

二、創建SmartForm

1、在“全局設置”-〉“表格屬性”-〉“輸出選項”中
設定“頁格式”:即紙張的大小
“樣式”:設定本Form使用的默認樣式文件,這裏指定爲第一步創建的樣式文件。

2、在“全局設置”-〉“表格接口”-〉“導入”
設置兩個參數:
ptr_header type c
ptr_items  type c
這兩個參數用來傳入我們在Report中Export內表數據的句柄(ID key)。

3、在“全局設置”-〉“全局定義”中進行多項設定
a、“類型”設定,在這裏需要定義4個類型,一個用來保存表頭數據的工作區和內表,一個用來保存明細數據的工作區和內表,它們的結構必須與Report中Export到數據庫中的內表的結構完全對應一致,否則,我們將不能從傳入的句柄(ID key)中恢復內表數據。

* 領料單擡頭信息
TYPES:
BEGIN OF TYP_header_ROW ,
        mblnr          LIKE mseg
-mblnr,    " 憑證號
        bldat          LIKE rkpf-rsdat,    " 憑證日期
        c_so(16)       TYPE c,             " 銷售訂單號
        c_issdt        LIKE sy-datum,      " 發貨日期
        werks          LIKE mseg-werks,    " 地點
        PLNAT_NAME     LIKE t001w-name1,   " 出貨單位名稱
        kokrs          LIKE mseg-kokrs,    " 控制範圍
        kostl          LIKE mseg-kostl,    " 成本中心
        cc_name        LIKE cskt-ktext,    " 成本中心名稱名稱
        c_depart(45)   TYPE c,             " 領料部門
        bwart          LIKE mseg-bwart,    " 移動類型代碼
        btext_mt       LIKE t156t-btext,   " 移動類型描述
        c_btext_mt(60) TYPE c,             " 移動類型次數
        C_TOTAL(17)    TYPE C,             "合計輸出時由用戶手工填寫
END OF TYP_header_ROW .

TYPES: TYP_HEADER_TABLE TYPE TYP_HEADER_ROW OCCURS 
0.

* 領料單明細信息
TYPES:
BEGIN OF TYP_ITEMS_ROW ,
        mblnr       LIKE mseg
-mblnr,      " 物料憑證編號 : 物料憑證
        rsnum       LIKE rkpf-rsnum,      " 憑證號 : 預留單
        mjahr       LIKE mseg-mjahr,      " 物料憑證年度
        zeile       LIKE mseg-zeile,      " 序號
        bwart       LIKE mseg-bwart,      " 移動類型代碼
        werks       LIKE mseg-werks,      " 地點
        kokrs       LIKE mseg-kokrs,      " 控制範圍
        kostl       LIKE mseg-kostl,      " 成本中心
        matnr       LIKE mseg-matnr,      " 物料號碼
        maktx       LIKE makt-maktx,      " 物料描述
        erfme       LIKE mseg-erfme,      " 計量單位
        c_planc     LIKE resb-bdmng,      " 計劃數量(手工填寫)
        c_outc      LIKE mseg-erfmg,      " 實發數量
        c_count(6)  TYPE c,               " 件數(手工填寫)
        lgort       LIKE mseg-lgort,      " 倉儲地點
        charg       LIKE mseg-charg,      " 備註
END OF TYP_ITEMS_ROW.

TYPES: TYP_ITEMS_TABLE TYPE TYP_ITEMS_ROW OCCURS 
0.


b、在“全局數據”中,定義全局的變量,我們需要定義如下幾個變量
  wa_header type typ_header_row    "表頭數據工作區,由於SmartForms中的內表不能有HeaderLine,因此必須定義一個與內表結構一樣的工作區

  ig_header type typ_header_table  "表頭數據內表
  wa_items  type typ_items_row     "表單明細工作區
  ig_items  type typ_items_table   "表單明細內表
  wa_blanks type typ_items_row     "空白行工作區
  ig_blanks type typ_items_table   "空白行內表
  g_count   type i                 "記錄一張報表的明細的記錄數量
  G_CURRLINE type i                "記錄所有報表共計打印了多少行,用於判斷最後一頁
  G_TOTALLINES type i              "記錄內表ig_items總行數,用於判斷最後一頁
  G_CURRPAGE type i                "一個憑證的當前頁碼
  G_TOTALPAGE type i               "一個憑證的總頁碼



c、在“初始化”中,將數據句柄中的內表恢復到剛設定的全局變量中
輸入參數:ptr_header,ptr_items,ig_header,ig_items,g_totallines

perform Restor_buffer using ptr_header changing ig_header.
perform Restor_buffer using ptr_items  changing ig_items.

DESCRIBE TABLE IG_ITEMS LINES G_TOTALLINES.

d、在Freecode"格式化程序"中,定義Form Restor_buffer函數

form Restor_buffer using typeid type c changing t type table.
  import t from database indx(hk) id typeid.
endform.



至此,我們已經得到了表頭和明細這2個內表的數據,下面準備畫報表並輸出數據。

4、在“頁和窗口”中,在“%Page1”頁下,添加3個窗口
"MAIN主窗口": 在SmartForm中,只有窗口類型爲“主窗口”的窗口,才能被循環。例如,在最前面的樣表中,明細數據有20條,不能在一頁中打印輸出完畢,需要輸出4頁才能打印完一張單據的數據,在這4張單據中,表頭和表尾是不變的,但是表中間部分數據卻是變化的,中間這個窗口需要被循環輸出4次。因此需要將這個窗口類型設定爲“主窗口”。在本例中爲現實明細數據的這部分。
“窗口1”:從表最上面到明細欄的標題欄(包括標題欄)
“窗口2”:最底下2行。
注意:窗口的寬度加上遍距不能大於紙張寬度。

創建好這三個窗口,設定好窗口的寬度,高度,以及位置信息。下圖是整個SmartForm的結構

注意,我將輸出表頭的窗口“%windows1 頁頭”放在了輸出明細數據的窗口“主窗口”的下面,這是必須的,因爲表頭中的數據需要從表頭內表ig_header中來。loop1是循環內表ig_header,將數據放到表頭工作區wa_header中。因此,%windows1 頁頭窗口就可以直接使用工作區wa_header中的數據。如果該窗口放在了主窗口的前面,那麼至少第一頁中表頭會沒有數據,而且後面每一頁的表頭顯示的都是下一個表頭的內容。
注:雖然打印機輸出時,現打印%WINDOWS1 頁頭,再打印MAIN主窗口,最後打印%WINDOW2頁尾窗口,但是程序執行時,卻是按照上圖中樹結構從上到下進行處理的,是先處理MAIN主窗口,其次%WINDOWS1 頁頭,最後%WINDOW2頁尾窗口的邏輯順序,可以從跟蹤SMARTFORMS程序得知。

下面詳細介紹整個邏輯流程和代碼:

1、%LOOP1表頭循環
設置:數據-〉loop循環-〉操作數:ig_header into wa_header
作用:循環表頭內表中的數據,每次打印一個憑證的行項目數據。由於內表在這裏不能有工作區,因此將每個表頭數據放置到另外的工作區。

2、%LOOP4計算單個憑證總頁碼
設置:數據-〉loop循環-〉操作數:IG_ITEMS INTO WA_ITEMS
      WHERE條件:IBLNR = WA_HEADER-IBLNR
作用:由於在打印每張憑證及行項目之前,需要知道該憑證的總頁數,因此需要首先計算IG_ITEMS內表中有多少條當前憑證的行記錄數。

3、%CODE4累計單個憑證的行項目數
輸入參數:G_COUNT
代碼:

G_COUNT = G_COUNT + 1.

作用:累計當前憑證的行項目數。

4、%CODE1計算當前憑證總頁碼
輸入參數:G_TOTALPAGE,G_COUNT
代碼:

G_TOTALPAGE = 0.

*計算單個憑證的總頁碼
G_TOTALPAGE 
= G_COUNT MOD 8.

IF G_TOTALPAGE = 0.
  G_TOTALPAGE 
= G_COUNT DIV 8.
ELSE.
  G_TOTALPAGE 
= G_COUNT DIV 8 + 1.
ENDIF.

G_COUNT 
= 0.

作用:根據第三步累計的單個憑證的總行項目數,以及每頁打印的行記錄數(8),計算該憑證需要打印的總頁數。計算完畢以後,G_COUNT重新置0。

6、%LOOP2循環輸出明細
設置:數據-〉loop循環-〉操作數:IG_ITEMS INTO WA_ITEMS
      WHERE條件:IBLNR = WA_HEADER-IBLNR
作用:這裏的循環條件與第2步的條件完全一致,準備循環打印當前憑證的所有行項目。

7、%CODE2記錄行數加1
輸入參數:G_COUNT,G_CURRLINE
代碼:

* 每打印一行行記錄,記錄數量加1
G_COUNT 
= G_COUNT + 1.

G_CURRLINE 
= G_CURRLINE + 1.

作用:每循環一次,當前憑證打印的行記錄數加1,所有憑證打印的總行記錄數加1。

8、%TEMPLATE4數據明細
作用:模板,行記錄的表格,以及相關文本內容。LOOP2每循環一次,就打印輸出一行該模板以及文本內容。行高一般爲5mm(根據實際調整),注意模板的寬度不能超過窗口的寬度。在“細節”中可以調整模板的每個單元格的寬度,以及每行的高度。

9、%TEXT22 - %TEXT30文本內容
%TEXT22    序號:&G_COUNT(CZT4R)&  輸出選項-〉輸出結構:第1行第1列 
%TEXT23物料號碼:&WA_ITEMS-MATNR&  輸出選項-〉輸出結構:第1行第2列
依此類推。

10、%CODE5計算當前頁碼
輸入參數:G_COUNT,G_CURRPAGE
代碼:

DATA: L_LINE TYPE I.
L_LINE 
= G_COUNT MOD 8.

IF L_LINE = 0.
  G_CURRPAGE 
= G_COUNT / 8.
ELSE.
  G_CURRPAGE 
= G_COUNT DIV 8 + 1.
ENDIF.

作用:每輸出一行,計算當前行所在的頁碼,即爲當前頁

11、%CODE3計算空行
輸入參數:G_COUNT,IG_BLANKS,WA_BLANKS
代碼:

G_COUNT = G_COUNT MOD 8.

* 需要的空記錄行數
IF G_COUNT <> 0.
  G_COUNT 
= 8 - G_COUNT.
ENDIF.

CLEAR IG_BLANKS[].
DO G_COUNT TIMES.
  APPEND wa_blanks 
to ig_blanks.
ENDDO.

G_COUNT 
= 0.

作用:在當前憑證的所有有效數據行打印完畢以後,還需要計算需要打印多少空行,才能剛好打印滿一張紙。用計算的數量,填充內表IG_BLANKS,計算完畢以後,G_COUNT必須清0。

12、%LOOP3 補充打印空行
設置:數據-〉loop循環-〉操作數:IG_BLANKSS INTO WA_BLANKS
      WHERE條件:無
作用:循環內表IG_BLANKS,次數爲內表中的記錄數,即空行數,打印輸出空行。

13、%TEMPLATE5空數據明細
作用:該模板與第8步的TEMPLATE4完全一樣,只是該模板下不需要有文本TEXT,只序號輸出模板的表格線即可。
到此步驟,已經打印完畢了當前憑證的所有有效數據行和補充的空行,如果當前憑證需要打印多頁,例如有30條行記錄,需要打印3個滿頁,第4頁數出6行數據,補充2個空行,這3次分頁是系統自動分頁的,分也之前,自動處理頁頭和頁尾窗口,輸出這兩個窗口的內容。自動分頁的條件是“MAIN主窗口”的高度被打印滿了,因此一定要注意,主窗口的高度必須等於你需要的高度,不要多,也不要少,在本例中,高度爲8行 x 5mm = 40mm


14、%CONDITION1分頁
設置:一般屬性-〉節點條件:G_CURRLINE <> G_TOTALLINES
作用:在一個憑證打印完畢以後,將要進入打印下一個憑證之前,需要分頁,但是在打印完最後一個憑證的最後一頁以後,卻不能有分頁,否則最後會多一個空行。

15、%COMMAND1強制分頁
設置:一般屬性-〉轉到新頁:%PAGE1
作用:在G_CURRLINE <> G_TOTALLINES 條件成立(不是最後一行)的情況下,強制分頁。
你也許會說,這裏不強制分頁,系統也會自動分頁,因爲前面輸出的高度正好都滿足的各窗口的高度,會自動進行分頁,確實如此,系統會自動進行分頁,但是在這裏強調:強制分頁是必須的,不能使用自動分頁,原因是:自動分頁發生的時間不是我們預想的,我們需要在第13步執行完畢以後,馬上進行分頁,這時,WA_HEADER中的內容還是當前憑證的數據,這樣,在處理頁頭和頁尾窗口時,數據是正確的。而自動分頁卻不在此時發生,而是在第1步LOOP1循環再次執行以後,也就是WA_HEADER之中的內容變成下一條以後才發生,這樣我們就不能輸出正確的表頭和表尾數據,因此必須使用強制的分頁命令。

16、表頭和表尾窗口
由於這兩個窗口非常簡單,僅輸出文字描述和WA_HEADER中的內容,因此不詳細說明。


Q&A
1.打印預覽表格線都正常,但是用針式打印機輸出出現部分表格線無法輸出。
答:這個可能是由於針式打印機的分辨率較小的緣故,使用激光或者噴墨打印機可以正常輸出,或者在SmartForms中加粗表格線,使用30TW。

2.在使用穿孔紙連續打印時,後面的紙張出現錯位現象。
答:原因不是很清楚,需要設置打印機中的紙張格式,將紙張高度根據錯位的距離進行加或者減,多次調整以後可以達到沒有錯位。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章