Smart Form Tutorial(适用新手学习)

 
发现 Smart Form ECC6 中和 4.6C 相比改变了不少,最近重新研究了一下。 help.sap.com 上的文档基本上是针对新特性的,不过例子却还是旧的。做个笔记省的以后找不到最新的 example
最大的改变在 Table 上,现在 table header footer 比以前好做了。
还是用 IDES 自带的 SFLIGHT 表做例子,先看一下打印出来的效果:
Smart Form  相对 SAP Script 来说,系统给封装了很多功能,这样用户在 Form 中的代码写的少了一些,更容易维护,如果把 SAP Script 比作汇编语言的话, Smart Form 可以算上 C++ 了,不过个人感觉对于复杂表单的设计来说,用 SAP Script 更容易实现。在 Smart Form 中调整表格边线比较费劲。
1. Create a Form named 'ZBSUNTEST'
TCode: SMARTFORMS 创建一个空白的 Form 。双击左边树状结构中的 'Global Setting'->'Form Attributes' 。在 里头可以看到纸张的设置,默认是 A4 。这里还可以调正一页中可以打印多少行。
2. Form Interface
我们生成一个 Form 的同时,系统也创建了一个相应的 function module Form Application 的数据交换就是通过 function interface 来实现的。双击左边树状结构中的 'Global Setting'->'Form Interface' ,我们可以看到 ,这和我们在 SE37 中看到的 function module 的接口是一样的。点击 'Table' 这个 tab ,输入如下:
3. Global Definition
这里定义的是在 form 中共用的全局变量,还可以定义 subroutine form 初始化的时候调用的一个 routine ,可以在这里做一些 data 初始化的工作。   用来设置货币或者数量的单位关联用的。
下面是 'Global Data' 里头的定义:

上图中的 T_SUM 类型是我在 'Types' 里头定义的,其中 PRICE, CURRENCY 是用来做 sum 用的:
TYPES:
  BEGIN OF T_SUM,
    PRICE  TYPE S_PRICE,
    CURRENCY   TYPE S_CURRCODE,
  END OF T_SUM.
下面是 Currecy & Quantity 的单位关联设置。这样关联之后 Price 会按照 Currency 的不同,输出格式也不同:
 
4. Create a Style named 'Z_BSUN_TITEL01'
回过头我们要创建一个给这个 Form 使用的 Style 。还是用 SMARTFORMS 这个 TCode 来创建。在这个 Styel 里头我只创建了 'Paragrah Format' ,真正的项目中 'Character Format' 肯定也是不可缺少的。这个 Style 使用在 Step 1 中创建的 Form 所有的 Output Option 中。
M1: Aligned:left;Indent->left margin:0.20 CM;font family: Arial;font size: 12pt
M2: Aligned:right;Indent->right margin:0.20 CM;font family: Arial;font size: 11pt
M3: Aligned:right;Indent->right margin:0.20 CM;font family: Arial;font size: 12pt;font color:blue
T1: Aligned:center;font family: Arial;font size: 14pt;font style: Bold Italic
  5.Creat a Page named 'FIRSTPG'
下创建一个名为 'FIRSTPG' page ,并把它的 next page 设置为其本身。 Page Format 设置为 'Portrait Format'
  6.Create Windows under 'FIRSTPG'

Windows
Position and Size 如下 ( 单位都是 CM)
HEADER:  L2.60, U0.20, W14.70, H2.00
MAIN: L2.00, U2.00, W16.00, H25.00
FOOTER:  L2.60, U27.20, W14.70, H2.00
  7. Create Header's Text
'HEADER' Window node 下面创建一个 Text ,取名 'TITLE' Text type 设置成 'Text Element' 。再 PC Editor 中点   输入 T1 就是在 Step 3 里头定义的 Paragraph Format
  8. Create a table in 'MAIN' Window
'MAIN' Window node 下面创建一个 Table . Table 下面自带了三个 node: header, main area, footer ,颜色跟别的由用户创建的 node 有区别。其中 Table header node 下面我们可以放表头。 Table footer node 跟我们在 Step 6 创建的 FOOTER Window 有区别。 FOOTER Window 的位置是固定的, Table footer Table line 在哪里结束,它就紧跟在后面。 文章开头的打印结果中我们可以很直观的看到这两个的区别: FOOTER Window 在每页的最下面(打印了两次,尽管内容不一样), Table footer 在第二页中间只打印了一次。当然我们说的都是默认的情况。
9. Insert program line 'CODE_CLEAR' before 'MAIN' Window
Input Parameters:  G_TAB_DATA;
Output Parameters: G_REC_TOTAL, G_TAB_TOTAL, G_ITEMS_ONPAGE;
REFRESH: G_TAB_TOTAL, G_TAB_SUBTOTAL.
CLEAR: G_REC_TOTAL, G_REC_SUBTOTAL, G_ITEMS, G_ITEMS_ONPAGE.
DESCRIBE TABLE G_TAB_DATA LINES G_ITEMS. "Get total item number
 Programe Line 中使用到的全局变量必须在 Input/Output 中定义,否则 check 不通过。
10. Create some line types in Table 'FLIGHTINFO'
Line Type 是控制表格格式的,每一个 Table Line 都要指定一个 Line Type

Layout
如下图,注意这些 Line border 是框了线的
11. 'DATA' of Table 'FLIGHTINFO'

G_TAB_DATA
Step 2 Form Interface 定义的一个内部表,也就是从 Application 传过来准备给 Form 显示的数据。我们还想让显示的数据排一下序,当然这可以在外部程序中 SORT ,不过这里的排序还有触发 event 的作用,后面会讲到。如果内部表已经排好序了,只是想触发类似 LOOP AT NEW/AT END OF 这样的功能,那么把 这个勾上就好。下面是 SORT 的设置,我们对 CARRID(Airline),CONNID(Flight No.) 排序,并且要触发两个 events ,用来做 subtotal 统计。
12. 'Calculation' of Table 'FLIGHTINFO'
是用来对 Table Fields 做简单计算的,包括 'Number', 'Total', 'Mean Value' 。如果不是涉及到货币或者数量的统计我们可以用 'Total' 这个 Operation ,具体使用可以参考 help 。我这里用了 'Number' 做一个每页的 Items 统计, 'Number' 也可以用来做行号。
13. Insert a title in table header
Table 'FLIGHTINFO' header node 下增加 table line HEADER_LINE LINE TYPE 'Line1' tablbe line 自动带出 5 cell cell 的数目是根据 LINE TYPE :'Line1' 来的, Step 10 里头可以看到 Line1 是有 5 cell 的。我们在每一个 cell 下面添加一个 Text ,作为 colum title ,把 paragraph format 设置成 M1 。不过 'Price' 这个 Column 因为是数字, paragraph format 设置成 M3

P.S.Table
自带的 header Output Option->Print Time 有两个选项

at start of Table
就不说了,不过 at Page Break 工作不正常,第 2 页并没有打印出来 title ,也不知道是不是我写的问题。
  14. Insert table line into table main area
Main Area
是显示 Application 传进来的内部表的地方,和 Step 13 一样增加一个 Line Type=LINE1 Table Line ,每个 Cell 下各增加一个 Text ,属性设置成 'Text Element'

PC Editor ,编辑 Text 内容,以 CARRID 为例:  
15. Insert a Program Line Under 'DATA_LINES'
CURRENCY_DATA
下的 Programe Line: SUM ,是为了做合计用的,按照 Currecy 的不同将 Price 合计。(当然单价 Price 的合计没什么实际意义,权当是演示)
Input Parameters:  G_REC_DATA, G_TAB_SUBTOTAL;
Output Parameters: G_REC_TOTAL, G_TAB_TOTAL;
G_REC_TOTAL-PRICE = G_REC_DATA-PRICE.
G_REC_TOTAL-CURRENCY = G_REC_DATA-CURRENCY.
COLLECT G_REC_TOTAL INTO G_TAB_TOTAL.
COLLECT G_REC_TOTAL INTO G_TAB_SUBTOTAL.
CLEAR: G_REC_TOTAL.
  内部表 'G_TAB_TOTAL','G_TAB_SUBTOTAL' 保存的是合计和根据 'Airline' 进行小计的数据。
  16. Print 'Grand Total' in table footer
table footer node 下增加一个 loop node  
Loop
DATA 如下:

因为我只想在所有的记录打印结束之后显示总计,所以给这个 loop 增加一个 condition 。在 Condition Tab 里的 Output Condition 中增加一行:

G_ITEMS_ONPAGE
Step 12 中被赋值 Number, G_ITEM Step 9 被赋值内部表中的记录数,当这两个值相等的时候也就是记录输出完毕的时候。再给 loop node 下一级增加一行 table line LINE TYPE : LINE3
GRANDTOTAL: M2 -> 'Grand total:'
PRICESUM_TAB: M2 -> &G_REC_TOTAL-PRICE&
CURR_TAB: M2->&G_REC_TOTAL-CURRENCY&
  17. Print subtotal in table (1)
我们在 Step 10 里头的 Sort 中勾选了 CARRID 字段的两个事件之后就能够发现 table node 自动增加了两个节点:

首先在 'CARRID Event on Sort Begin' 下一级增加一个 Program Line:SUB_CLEAR ,用来在 CARRID 改变的时候清空 subtotal 内部表。
Output Parameters: G_REC_SUBTOTAL;
CLEAR: G_REC_SUBTOTAL.
REFRESH: G_TAB_SUBTOTAL.
  然后在 'CARRID Event on Sort End' 下一级增加一个 Program Line:CLEAR_SUBTITLE ,用来清空一个打印标志。
Output Parameters: G_FLG_SUBTITLE;
CLEAR: G_FLG_SUBTITLE.
每一个 CARRID(Airline) 下面可能会有多种不同的货币价格,这个标志的作用是为了限制下面的 'Subtotal of &G_REC_SUBTOTAL-CARRID& is' 这句话在小计的时候不至于 print 出来很多遍。
  18. Print subtotal in table (2)
'CARRID Event on Sort End' 下一级增加一个 Loop:PRINTSUBTOTAL:

Loop:PRINTSUBTOTAL:
下一级增加一个 table line:SUBTOTAL LINE TYPE : LINE3
AIRLINE_NAME: M2 -> 'Subtotal of&G_REC_DATA-CARRID& is'
SUB_PRICE: M2 -> &G_REC_SUBTOTAL-PRICE&
SUB_CURR: M2->&G_REC_SUBTOTAL-CURRENCY&
  其中 AIRLINE_NAME 是有显示条件的: G_FLG_SUBTITLE 没有赋值的时候才显示。

AIRLINE_NAME print
出来之后我们在 Program Line 'SET_SUBTITLE' 中将 G_FLG_SUBTITLE 设置为 'X'
Output Parameters: G_FLG_SUBTITLE;
G_FLG_SUBTITLE = 'X'.
  19. Print 'Grand Total' in page footer
FOOTER Window 的下一级添加一个 Table Line: FTTABLE, Line Type:

DATA:

然后,在 FTTABLE Main Area 下增加一行 Table Line: PRICESUM, Line Type: LINE1 

为了控制在最后一页的页脚打印出来金额合计,要给 PRICESUM 增加一个条件。在 Conditions Tab 里头的
And Additional Event
中勾选 'Only after end of main window' 'SUM' 'CURR' 这两个 Text 的设置如下:
SUM: M2 -> &G_REC_TOTAL-PRICE&
CURR: M2->&G_REC_TOTAL-CURRENCY&
最后,在 FTTABLE Footer 下增加一行 Table Line: FOOTER, Line Type: LINE1 

ITEMS: M2 -> ITEMS IN THIS PAGE:&G_ITEMS_ONPAGE(3)&
PAGE: M2->PAGE:&SFSY-PAGE&
  20. Calling a Smart Form from Application
生成 smart form 的同时系统会自动创建一个对应的 funtion module ,这个 function 的名字可以通过菜单 Enviroment->Function Module Name 得到。在程序中一般通过 function 'SSF_FUNCTION_MODULE_NAME' 来得到。下面是我们的测试这个 smart form 的代码:
*&---------------------------------------------------------------------*
*& Report  Z_SUN_SFORM
*&
*&---------------------------------------------------------------------*
REPORT  Z_SUN_SFORM NO STANDARD PAGE HEADING LINE-SIZE 150 MESSAGE-ID ZBSUN.
************************************************************************
* D E C L A R A T I O N   O F  I N T E R N A L    T A B L E S
************************************************************************
DATA:
  G_TAB_OUTPUT   TYPE STANDARD TABLE OF SFLIGHT.
************************************************************************
* D E C L A R A T I O N   O F  V A R I A B L E S
************************************************************************
DATA:
  G_REC_OUTPUT      TYPE SFLIGHT,
  G_REC_OPTIONS     LIKE ITCPO,
  G_REC_RESULT      TYPE ITCPP.
************************************************************************
* D E C L A R A T I O N   O F  C O N S T A N T S
************************************************************************
CONSTANTS:
  G_CON_FLG_ON      TYPE C VALUE 'X',
  G_CON_FORMNAME(8) TYPE C VALUE 'ZBSUN_01'.
************************************************************************
*    S E L E C T I O N   S C R E E N
************************************************************************
SELECTION-SCREEN BEGIN OF BLOCK BLOCK1 WITH FRAME.
SELECT-OPTIONS S_LINE FOR G_REC_OUTPUT-CARRID NO INTERVALS.
SELECT-OPTIONS S_DATE FOR G_REC_OUTPUT-FLDATE.
SELECTION-SCREEN END OF BLOCK BLOCK1.
************************************************************************
*  S T A R T - O F - S E L E C T I O N
************************************************************************
START-OF-SELECTION.
  PERFORM FRM_GET_DATA.
************************************************************************
*  E N D - O F - S E L E C T I O N
************************************************************************
END-OF-SELECTION.
  PERFORM FRM_OUTPUT.
*&---------------------------------------------------------------------*
*&      Form  FRM_GET_DATA
*&---------------------------------------------------------------------*
*       GET FLIGHT DATA
*----------------------------------------------------------------------*
FORM FRM_GET_DATA .
  SELECT *
    INTO TABLE G_TAB_OUTPUT
    FROM SFLIGHT
   WHERE CARRID IN S_LINE
     AND FLDATE IN S_DATE.
  IF SY-SUBRC <> 0.
    MESSAGE E000.
*   No data selected.
  ENDIF.
ENDFORM.                    " FRM_GET_DATA
*&---------------------------------------------------------------------*
*&      Form  FRM_OUTPUT
*&---------------------------------------------------------------------*
*       OUTPUT DATA
*----------------------------------------------------------------------*
FORM FRM_OUTPUT.
  DATA: FM_NAME TYPE RS38L_FNAM.
  CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
    EXPORTING
      FORMNAME                 = 'ZBSUNTEST'
*     VARIANT                  = ' '
*     DIRECT_CALL              = ' '
   IMPORTING
     FM_NAME                  = FM_NAME
*   EXCEPTIONS
*     NO_FORM                  = 1
*     NO_FUNCTION_MODULE       = 2
*     OTHERS                   = 3
            .
  IF SY-SUBRC <> 0.
*   MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*           WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.
  CALL FUNCTION fm_name
*  EXPORTING
*   ARCHIVE_INDEX =
*   ARCHIVE_PARAMETERS =
*   CONTROL_PARAMETERS =
*   MAIL_APPL_OBJ =
*   MAIL_RECIPIENT =
*   MAIL_SENDER =
*   OUTPUT_OPTIONS =
*   USER_SETTINGS = 'X'
* IMPORTING
*   DOCUMENT_OUTPUT_INFO =
*   JOB_OUTPUT_INFO =
*   JOB_OUTPUT_OPTIONS =
  TABLES
    G_TAB_DATA = G_TAB_OUTPUT
  EXCEPTIONS
    FORMATTING_ERROR = 1
    INTERNAL_ERROR = 2
    SEND_ERROR = 3
    USER_CANCELED = 4
    OTHERS = 5.
IF SY-SUBRC <> 0.
*   <error handling>
ENDIF.
ENDFORM.                    " FRM_OUTPUT
到这里这个 Tutorial 就结束了,我们没有用到的 node 还有 Command, Alternative,Graphic,Complex Section 等。其中 Command 主要用来插入分页或者打印控制语句的; Alternative 用来插入一个逻辑分支; Graphic 插入图片的; Complex Section 我自己没用过,看帮助文件说 SAP 不推荐使用。
real project 中的 form 不会有这么简单,但是也不会脱离这些 elements 的组合。
 
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值