列表屏幕(List Screen)

时间:2023-03-09 17:21:44
列表屏幕(List Screen)
列表屏幕(List Screen)
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4292407.html

列表屏幕(List Screen)

生成列表屏幕

在START-OF-SELECTION事件处理块中,用WRITE语句向列表缓冲区(List Buffer)输出要显示的内容,当该事件结束的时候,所有在列表缓冲区中的内容将被显示到一个基本列表屏幕(Basic List)上。

当用户在基础列表屏幕上双击一行或按功能键“F2”时,将会触发ABAP事件AT LINE-SELECTION,如果还想进一步显示该行数据的详细信息,则可以继续使用WRITE语句输出要显示的内容,这次生成另外一个详细列表屏幕(Details List Screen)。此详细列表屏幕将覆盖其上一层的基础列表屏幕,若在其界面的工具条上点“返回”或按功能键F3,将返回到基础列表屏幕。

在详细列表屏幕上,当用户双击一行数据或按功能键F2,AT LINE-SELECTION事件将会再次触发,因此还可以继续生成下一级的详细列表屏幕。因此,除了基础列表屏幕外,所有的详细列表屏幕的生成都是在AT LINE-SELECTION 事件块中一起处理的,因此应该有一个机制区别开是哪一个详细列表屏幕将被生成。

ABAP提供了全屏变量表示为基础列表屏幕,1表示第一级详细列表屏幕,依次类推,最多可以有20个详细列表。如果是返回上一次,则sy-lsind会自动减一:

列表屏幕(List Screen)

如果要在dialog program (module pool)生成屏幕列表,则可以通过LEAVE TO LIST-PROCESSING向屏幕发送列表。

此部分主要是通过WRITE语句来输出简单的列表,具体参考《ABAP BC Programming.docx》的Write语句用法

复杂LIST

标准LIST

) 'International Connections'.

列表屏幕(List Screen)

standard page header

至少包括二行standard header,第一行standard header包括了listheader和pagenumber,第二行standardheader是一条水平线。当程序是可执行报表程序时,listheader存储在SY-TITLE中。如果有必要,可以给standardheader添加最多四行的column headers与一条水平线。在水平或垂直滚动时standardheader是不会动的。

列表屏幕(List Screen)

自定义LIST

自定义Page Header

TOP-OF-PAGE.

WRITE: ....

在TOP-OF-PAGE事件里输出的为自定义Page Header,会在每页正文本输出前输出

另外,如果屏蔽掉standard header,使用下面语句压制:

REPORT <rep> NO STANDARD PAGE HEADING.

对于每个TOP-OF-PAGE事件,对于basic list设置的标准属性标题与列表头中的占位符 &0  -  &9 ,会自动使用系统变量SY-TVAR0到SY-TVAR9来替换他们,所以在TOP-OF-PAGE事件里对SY-TVAR0到SY-TVAR9进行设置即可

REPORT demo_list_page_heading NO STANDARD PAGE HEADING.
TOP-OF-PAGE.
  WRITE: sy-title, 40 'Page', sy-pagno. ULINE.
  WRITE: / 'SAP AG', 29 'Walldorf, ',sy-datum,
  / 'Neurottstr. 16', / '69190 Walldorf/Baden'.
  ULINE.
START-OF-SELECTION.
  DO 5 TIMES.
    WRITE / sy-index.
  ENDDO.

列表屏幕(List Screen)

LINE-SIZE

输出宽度由REPORT的LINE-SIZE来决定:

REPORT <rep> LINE-SIZE <width>.

如果<width>设置为0,则采用标准LIST的宽度来输出。缺省的列表的行宽为83个字符

一行最多只能显示255个字符,但大多数的打印机只能打印132个字符。当前页面宽度存储在SY-LINSZ系统变量中

.
WRITE:  'SY-LINSZ:', sy-linsz.
ULINE.
DO 20 TIMES.
WRITE sy-index.
ENDDO.

列表屏幕(List Screen)

LINE-COUNT

限制每页多少行

REPORT <rep> LINE-COUNT <length>[(<n>)].

如果指定了<n>参数,系统会保留<n>行给page footer。如果<length>设置为0,系统会使用标准页面长度。缺省每页的行数为6万行。

页面的实质可输出正本行数为<length>减去page header length,再减去<n>。每面的行数包含了列表头(headings)、列表内容与列表脚注行(footer lines)。

系统变量SY-LINCT会存储页面行数<length>,注意:如果REPORT语句没有设置该值,则该系统变量值为0,除非使用 NEW-PAGE语句进行了设置。

SY-PAGNO系统变量存储了当前页码。

).
WRITE: 'SY-LINCT:', sy-linct.
SKIP.
DO 6 TIMES.
  WRITE / sy-index.
ENDDO.

TOP-OF-PAGE.
  WRITE: / 'Page title', `              ` &
  `Pag NO.:`,sy-pagno NO-GAP LEFT-JUSTIFIED.
  ULINE.

END-OF-PAGE.
  WRITE: / '*****Page footer*****'.

列表屏幕(List Screen)

Page Footer

END-OF-PAGE.

WRITE: ....

触发的条件是数据要满一页时才触发,否则不会被触发:

).

END-OF-PAGE.
  ULINE.
  WRITE: /30 'Page', sy-pagno.

START-OF-SELECTION.
  DO 5 TIMES.
    WRITE / sy-index.
  ENDDO.

列表屏幕(List Screen)

强制分页

无条件分页使用NEW-PAGE

如果是想保留多少空行后再分页,使用RESERVE

NEW-PAGE

该语句结束当前页,所有的输出会在新的页面里显示。

该语句不会触发END-OF-PAGE事件(是否触发则要看执行该语句前数据是否已刚好满一页):

).

END-OF-PAGE.
  WRITE: '**page footer**'.

START-OF-SELECTION.
  DO 2 TIMES.
    WRITE / 'Loop:'.
    DO 3 TIMES.
      WRITE / sy-index.
    ENDDO.
    NEW-PAGE.
  ENDDO.

列表屏幕(List Screen)

RESERVE

RESERVE <n> LINES.

在调用此语句时,如果最后一次输出到Page Footer之间所剩行小于(注意:等于时不会分页)<n>时会进行分页,在开始新页之前会触发END-OF-PAGE事件(如果最后一页数据不足一页,还是不会显示页脚)。注意:该语句仅只影响后面紧挨着的输出语句,如果不满足分页条件,则后面的输出也不会再受该语句的影响。

另外,RESERVE可以定义后继的输出作为一个行块整体输出,请参照这里

列表屏幕(List Screen) 列表屏幕(List Screen)

).

END-OF-PAGE.
  WRITE: / '---page footer---'.
  WRITE: / '**page footer**'.

START-OF-SELECTION.
  DO 4 TIMES.
    WRITE / sy-index.
  ENDDO.
  DO 2 TIMES.
    WRITE / sy-index.
  ENDDO.
  RESERVE 3 LINES.
  WRITE: / 'LINE 1',
  / 'LINE 2'.
  RESERVE 3 LINES.
  WRITE:/ 'LINE 3'.

列表屏幕(List Screen)

控制分页是否使用标准page header

标准pageheader是由list header 与 column header组成的。在使用NEW-PAGE进行分页时,可以通过下面选择屏蔽或打开standard page header:

NEW-PAGE [NO-TITLE|WITH-TITLE] [NO-HEADING|WITH-HEADING].

WITH-TITLE or NO-TITLE:控制NEW-PAGE新开启的页面以及后面使用NEW-PAGE开启的页面是否使用标准的list header

NO-HEADING or WITH-HEADING:控制NEW-PAGE新开启的页面以及后面使用NEW-PAGE开启的页面是否使用标准的column header

即使在REPORT后面加上了NO STANDARDPAGE HEADING选项,你也可以单独使用WITH-TITLE and WITH-HEADING来打开。

该选项只对标准的pageheader有作用,对TOP-OF-PAGE中输出的不起作用。

列表屏幕(List Screen)

.
WRITE: 'Page', sy-pagno.
NEW-PAGE NO-TITLE.
WRITE: 'Page', sy-pagno.

NEW-PAGE NO-HEADING.
WRITE: 'Page', sy-pagno.

NEW-PAGE WITH-TITLE.
WRITE: 'Page', sy-pagno.

NEW-PAGE WITH-HEADING.
WRITE: 'Page', sy-pagno.

列表屏幕(List Screen)

控制分页中每页的行数

为了单独控制分页出页面允许的数据行数,可以使用:

NEW-PAGE LINE-COUNT <length>.

该选项决定了随后的所有(除非又重新通过该语句的这个选项重新指定了)使用NEW-PAGE语句分出的页面的允许的最大数据行数。如果为0,则使用标准页面的长度。pageheader与pagefooter都是要算行数的。另外,不能通过NEW-PAGE的选项控制footer的行数,这只能通过REPORT语句选项指定。

系统变量SY-LINCT会存储页面行数(即<length>)。

列表屏幕(List Screen)

.
  DO 6 TIMES.
    WRITE / sy-index.
  ENDDO.

列表屏幕(List Screen)

控制分页的页宽

NEW-PAGE LINE-SIZE <width>.

SY-SCOLS存储了当前窗口在没有滚动条的情况下允许的最大字符数(或叫Column),而LINE-SIZE选项指的是列表本身最大允许的字符数,与窗口大小没有关系(如果LIST列表的宽度LINE-SIZE大于了窗口允许的最大字符数SY-SCOLS,则会出现滚动条,否则窗口不会出现滚动条)

滚动列表

滚动成功后SY-SUBRC为0

SY-SROWS系统变量中存储了当前窗体可以输出的最大数据行数,包括Page Header

垂直滚动:by Window

SCROLL LIST FORWARD|BACKWARD [INDEX <idx>].

FORWARD向下滚动一屏(窗口)

FORWARD向上滚动一屏(窗口)

<idx>:移动哪一Level的List

.
TOP-OF-PAGE.
  "SY-SROWS系统变量中存储了当前窗体可以输出的最大数据行数,包括Page Header
  WRITE: 'Top of Page', sy-pagno, 'SY-SROWS:', sy-srows.
  ULINE.

START-OF-SELECTION.
  DO 100 TIMES.
    WRITE / sy-index.
  ENDDO.
  "向下翻一屏
  SCROLL LIST FORWARD.

列表屏幕(List Screen)

垂直滚动:by Pages

SCROLL LIST TO FIRST PAGE | LAST PAGE | PAGE <pag> [INDEX <idx>] [LINE <lin>].

如果省略了INDEX选项,该语句是针对当前List操作的。

如果指定LINE选项,则会滚动到列表的第<lin>行(不包括pageheader lines),否则滚动至列表的首行。

另一种滚动方式:

SCROLL LIST FORWARD | BACKWARD <n> PAGES [INDEX <idx>].

页的第3行会显示在窗体的第一行
SCROLL LIST TO PAGE pag LINE lin.

列表屏幕(List Screen)

水平滚动:滚动到页面最左或最右

SCROLL LIST LEFT | RIGHT [INDEX <idx>].

.
TOP-OF-PAGE.
  WRITE: AT 161 'Top of Page', sy-pagno,
          'SY-SCOLS:', sy-scols.
  ULINE.
START-OF-SELECTION.
  DO 200 TIMES.
    WRITE sy-index.
  ENDDO.
  "水平滚动到最右边
  SCROLL LIST RIGHT.

列表屏幕(List Screen)

水平滚动:by Columns

SCROLL LIST TO COLUMN <col> [INDEX <idx>].

该语句作用是将滚动条滚动到LIST列表中的第<col>列(而不是滚动到当前窗口中的多少列)

SCROLL LIST LEFT | RIGHT BY <n> PLACES [INDEX <idx>].

该语句作用是向左或向右相对滚动多少列(即多少个字符)。

SY-SCOLS存储了当前窗口在没有滚动条的情况下允许的最大字符数(或叫Column),而LINE-SIZE选项指的是列表本身最大允许的字符数,与窗口大小没有关系(如果LIST列表的宽度LINE-SIZE大于了窗口允许的最大字符数SY-SCOLS,则会出现滚动条,否则窗口不会出现滚动条)

的位置
  .

列表屏幕(List Screen)

水平滚动控制

NEW-LINE NO-SCROLLING.

新起一行将不能水平滚动,但可以垂直滚动

NEW-LINE:相当于 Write: / ,表示换行,在Write之前调用了NEW-LINE时再没有 / 选项的 Write: 语句时会先换行再输出。

).

DO 3 TIMES.
    WRITE: / 'SY-INDEX:'.
    DO 10 TIMES.
      WRITE sy-index.
    ENDDO.
  ENDDO.

列表屏幕(List Screen)

列表屏幕(List Screen)

左边指定列不可滚动

SET LEFT SCROLL-BOUNDARY [COLUMN <col>].

.

列表屏幕(List Screen)

LIST布局

输出位置

可以指定WRITE与ULINE语句在当前页面的任何位置输出,并且WRITE, SKIP, or ULINE在指定输出位置时可能覆盖现有已经的输出。获取当前输出位置,可以通过下面两个变量来获得:

?    SY-COLNO

?    SY-LINN(注:这个系统变量指的是下次Write输出的行的位置,且是每页都从1开始,而不像SY-LILLI那样指整个列表屏幕中的决对行号)

ABAP提供了几个关键字以绝对或相对来改变输出位置

绝对定位

水平

ABP提供了两种水平绝对定位方式:

第一种是WRITE与ULINE语句的AT 选项

第二种是使用POSITION语句:POSITION <col>.

<col>会存储到SY-COLNO系统变量中

注意:对于每个WRITE语句输出的内容只会在一行中显示(显示不下时会被截断),不会换行显示,至于换行是因为第二次使用WRITE语句输出

垂直

SKIP TO LINE <lin>.

<lin>会存储到SY-LINNO系统变量中,如果<lin>不在1到pagelength之间时,将忽略此语句,从上一次输出位置后面继续接着输出。注意:这里所指的<lin>是指在一个分页里的行号,而不是指定整个当前窗口,另外,<lin>包括每页的Page Header与Page Footer行在内。

定位到Page Header下面的第一行的首列位置

BACK.

如果该语句不是放在RESERVE语句后面的行中使用时,后面的输出将会显示在Page Header下面开始显示输出。使用该语句后,系统变量SY-COLNO将设置为1,SY-LINNO将会设置为页面的Page Header的下一行。如果与RESERVE语句一起使用时,请参考这里的使用规则

).
  BACK.
  x = sy-colno.
  y = sy-linno.
  "在没有使用上面BACK的情况下,该WRITE语句会换行后输出,
  "原因是上一次输出画线之后,线后面没有足够的空间来存储
  "WRITE语句输出的内容,如果线后有足够空间输出,则是
  "会换行再输出。但在这里由于上面的BACK语句,下面的输出
  "行的位置又回到了Page Header下的第一行开始输出
  WRITE: 'Position after BACK:', x, y.

列表屏幕(List Screen)

相对定位

当使用WRITE时如果没有使用定位选项,则其输出位置是会相当于前一次输出后继位置,并且以空格分隔(在没有加 NO-GAP选项的情况下),如果没有足够的空间,将会自动换行。

产生一个换行(NEW-LINE)

NEW-LINE.

SY-COLNO会被设置为1,SY-LINNO会在原来基础上加1

定位到其他输出的下面(WRITE …UNDER)

WRITE <f> UNDER <g>.

该语句对跨页的<g>也有效

定位输出到 the First Line of a Line Block

RESERVE.

.....

BACK.

如果BACK用在了RESERVE后面,则BACK后继续的输出会输出到BACK与RESERVE之间的输出行块中的第一行。但要注意的是,RESERVE不能引起分页,否则BACK还是会定位到Page Header的后面第一行位置上。

REPORT demo_list_position_relative_2
NO STANDARD PAGE HEADING LINE-SIZE 40 .

DATA x TYPE i.

WRITE 'Some numbers:' NO-GAP.
x = sy-colno.
ULINE AT /(x).
RESERVE 5 LINES.
DO 6 TIMES.
  WRITE / sy-index.
ENDDO.
x = sy-colno.
BACK.
WRITE AT x '  <- Start of Loop'.

列表屏幕(List Screen)

格式化输出

使用WRITE、SKIP、ULINE输出语句输出的内容将被系统输出传递到标准列表屏幕中。请参考《ABAP BC Programming.docx》

FORMAT语句

请参考《ABAP BC Programming.docx》

其他格式化输出

上面章节讲了FORMAT常用的选项,这节讲一下比较特殊的选项,这些选项的格式输出是根据特定中的数据来进行的,通常用户会维护这些定制数据

Country-specific(国家) and User-specific(用户)相关格式化

数字与日期字段的输出格式是与用户主数据相关的,用户主数据可以使用SU3事务码来维护(或者点击相应菜单也可):

列表屏幕(List Screen)

或者也可能通过事务码SU01来维护:

列表屏幕(List Screen)

虽然可以通过上面的设置来格式化数字与日期时间的格式化输出,但你也可以在程序中使用下面语句来修改:

SET COUNTRY <c>.

<c>可以是国家代码,也可以SPACE,这些国家代码可以在T005X表中查找到

如果<c>不为SPACE,则系统会关闭掉用户主数据的设定,而是去到T005X中查找与国家代码<c>相对应的数据,如果在表中存在这样的数据时,该语句执行后SY-SUBRC为0,并且后继的所有WRITE语句都根据这个表中设定的数据来格式化输出;如果该语句执行失败则SY-SUBRC为4,并且后继的WRITE语句输出的数字的千分位以“,”显示,小数点是“.”来显示,日期显示为 MM/DD/YY格式。

如果<c>设置为SPACE,系统不会读T005X表,而是去使用用户设置的主数据,在这种情况下SY-SUBRC总是0

.
DATA: num TYPE p DECIMALS 3 VALUE '123456.789'.
ULINE.
WRITE: / 'INITIAL:'.
WRITE: / num, sy-datum.
ULINE.
SET COUNTRY 'US'.
WRITE: / 'US, SY-SUBRC:', sy-subrc.
WRITE: / num, sy-datum.
ULINE.
SET COUNTRY 'GB'.
WRITE: / 'GB, SY-SUBRC:', sy-subrc.
WRITE: / num, sy-datum.
ULINE.
SET COUNTRY 'DE'.
WRITE: / 'DE, SY-SUBRC:', sy-subrc.
WRITE: / num, sy-datum.
ULINE.
SET COUNTRY 'XYZ'.
WRITE: / 'XYZ, SY-SUBRC:', sy-subrc.
WRITE: / num, sy-datum.
ULINE.
SET COUNTRY space.
WRITE: / 'SPACE, SY-SUBRC:', sy-subrc.
WRITE: / num, sy-datum.
ULINE.

列表屏幕(List Screen)

Currency-specific(货币)格式化

WRITE <f> CURRENCY <c>.

输出金额<f>时,会根据该语句设置的货币代码<C>来决定其小数位置,如果货币代码<c>在表TCURX(CURRKEY)中存在,则系统将根据TCURX-CURRDEC值来设置<f>的小数点的位置,否则将<f>转换成具有2位小数的数字。这就意味着除非<f>本身就是类型为P(.2)(即货币的最大单位与最小单位换算为100时,如CNY人民币、USD美元)的金额字段,否则需要在TCURX表中配置所对应币种的小数位(因为不配置时会采用默认的2位)。

注意:这里的<f>一般是从数据库里读取出来的金额数据才需要这样格式化输出的,如果<f>本身存储的就是真实的金额,则不需要格式再输出,而是直接输出;另外,这里的格式化只是简单机械的根据TCURX表里所配置的小数位置来设置金额的小数点位置(而并不是乘以或除以某个转换率),并与金额变量<f>类型本身的具有多少小数位有关:如果<f>的类型为P(6.5),值为<f> = 1.234时,且TCURX表里配置的小数位为2时,最后输出的是 1234.00 ,而不是12.34(如果是根据转换率来除,则结果会正确),因为在格式化前,会将小数末的0也参与处理,并不理会<f>本身原来的小位数,而是将所有的数字位(抛开小数点,但包括末尾的0)看作是待格式会的数字字符串:

.
p = '1.234'.
WRITE: p CURRENCY 'aa'."1,234.00

 

TCURX货币小数位置表

TCURC:货币代码表

TCURR:汇率表

SAP表里存储的并不是货币的最小单位,一般是以货币最大单位(也是常用计量单元)来存储,不过在存储之前会使用经过转换:比如存储的金额是 100,则存储到表之前会除以一个转换因子后再存入数据表中(该转换因子是通过,JPY为100),所以如果要取出来自己使用,则需要再次乘以每次以这个因子才能得到真正的金额数(不知道SAP为什么这么设计,或者是一个什么国际标准吧)。另外,数据库中存储的虽然不是最小单位,但取出来后都是放在P类型的变量中的,所以取出来在内存中统计是不会有精度丢失的(P类型相当于Java中的BigDecimal类类型)。

TCURX表中存储的小数位实质上是根据同种币种的最大单位与最小的换算率 = 10来计算的,式中的X即TCURX表中的小数位,如CNY中的最大单位元与最小单位分相差100倍,所以100 = 10X,X就为2,最后TCURX-CURRDEC存储的就是2(但如果值为2是可以不需要在TCURX表中配置的,所以查不到CNY的配置数据,因为不配置时默认值也是2);另外,JPY日元没有最小单位,所以最大单位与最小单位的换算率就是1,所以X就为0,所以TCURX-CURRDEC存储的就是0。

数据库中用来存储金额的字段的类型都是P(.2),即带两位小数,因为转换因子最大也就是100,有的是零点几(在存入之前会将真实金额除以这个转换因子后再存入),所以存储类型为两位小数的数字类型即可。用来存储表中存储的内部金额的变量类型一定要具有两位类型的,否则在使用诸如CONVERT_TO_LOCAL_CURRENCY、CONVERT_TO_FOREIGN_CURRENCY转换函数或者是格式化输出时,都会有问题,所以在定义这些内部金额变量时,最好参照相应数据词典类型。

从表中读取日元并正确的格式化输出

列表屏幕(List Screen)

列表屏幕(List Screen)

倍,所以要还原操作界面上输入的日元金额,

倍,因为在存入表中时缩小了100倍
WRITE: / 'Calc factor:', jpy_netpr.

"格式化输出实质上是与存储金额的变量本身的类型小数位有关:上面将从表中
"读出的金额(小数两位)赋值给变量netpr1(小数三位),格式化后会扩大
"10倍(因为多了一位小数位)所以格式化正确输出的前提是要用来接收从
"表中读取的金额变量的类型要与数据表相应金额字段类型相同,否则格式化输出会出错
netpr1 = netpr.
WRITE: / netpr1, netpr1 CURRENCY waers."格式化的结果是错误的

列表屏幕(List Screen)

SAP 货币转换因子

一般而言,币种的小数位为2,所以系统默认的位数也是2.但是有一些特殊币种如日元JPY,没有小数位,或者其他对于2位的小数位。只要小数位不等于2,需要在系统中特殊处理(通过转换因子进行转换,具体请参看后面SAP提供的函数 currency_converting_factor 实现过程)。在编程中

1、List中,当输出CURR字段时,记得指定对应的货币:

如: WRITE: vbap-netwr CURRENCY vbap-waerk.

2、Screen中,对于CURR字段,需要设置对应的货币字段:

列表屏幕(List Screen)

3、ALV中,需要对FIELD CATALOG进行设置.

如: ls_cfieldname = ‘WAERS’. "这里的WAERS是内表中的另一货币字段,里面存储了相应金额的货币代码。

货币的是:fieldcat-cfieldname、fieldcat-ctabname(内表名,可以不设置)

随便数量也是相似的方法来处理的:

数量的是:fieldcat-qfieldname、fieldcat-qtabname(内表名,可以不设置)

下面是SAP转换因子函数,在金额存储与在ALV展示时都会自动除以与乘以这个转换因子:

就报错
  。如果表tcurx中的currdec = 0就默认转换比率为100
  cur_factor 的情况下循环currdec次,每次将转换比率除以10
    .
*- factor 0 not allowed; check data definition of factor
*- entry in tcurx with more than 5 decimals not allowed
    RAISE too_many_decimals.
  ENDIF.
  factor = cur_factor.
ENDFUNCTION.

简单的使用Function CURRENCY_CONVERTING_FACTOR,输入币别,就可以得到相应的转换比率了。我们在SE16中看到的货币金额基本上都经过了这个转换,如日元,都是除以100后存入数据库的。所以当我们从数据库中读取日元金额时也应该作相应的转换,乘以100 。

1、如果某货币的小数位不是2位,则需要通过OY04设置其小数位数,即需要在TCURX表中进行维护

2、系统中的数据表存放的日元JPY、俄卢布RUR等货币比前台输入的金额小100倍,因为它们没有小数位,所以转换因子为100,存入表之前SAP会先将金额除以这个因子后再存入

3、系统根据转换因子将原金额转换成含小位小数的金额后存储(据说根据ISO的什么标准),如日元为0位小数,转换因子为100,120日元除以因子100后转换后变成1.20,缩小100倍。如为USDN为5位小数,其转换因子为100/10/10/10/10/10=0.001,12.01230除以0.001后则转换成12012.30,扩大1000倍。SAP在金额数据存储时会自动的转换,其实SAP是有external及internal的数据格式,可以调用以以下函数实现相互转换。BAPI_CURRENCY_CONV_TO_INTERNAL:转换成跟数据库中存储一样的格式数据,BAPI_CURRENCY_CONV_TO_INTERNAL’:转换成外部实际金额

4、每次币别的汇率更改在正式生产系统中新创建一条记录,利用函数CONVERT_TO_LOCAL_CURRENCY自动会把当前最近的时间的汇率作为转化的汇率,而不是直接在原纪录上更改

5、OB07、OB08,维护各币种之间的汇率。

6、 碰到比较变态的货币,例如日元,它们是没有小数点的,系统内存储的和你看到的不同,有个BAPI可以使用:BAPI_CURRENCY_CONV_TO_INTERNAL

7、 还有一个FM:CONVERT_TO_FOREIGN_CURRENCY,和CONVERT_TO_LOCAL_CURRENCY基本没有区别,可以任选一个使用

货币内外格式转换


    foreign_currency 日元

,否则实质金额不准确,这里正是
,所以这里的金额实质上为0.01美元,而不是1美元
日元

即可
  IMPORTING
    amount_internal      = jpy "转换后的内部存储金额
    return               = ret.

CALL FUNCTION 'CONVERT_TO_LOCAL_CURRENCY'
  EXPORTING
    date             = sy-datum
    foreign_amount   = jpy "源货币金额(内部格式)
    foreign_currency = jpy_k"源货币类型
    local_currency   = usd_k"目标货币类型
  IMPORTING
    local_amount     = usd."目标货币金额(内部格式)
WRITE: jpy, jpy_k,usd, usd_k.
WRITE: / jpy CURRENCY jpy_k, jpy_k,
       usd CURRENCY usd_k, usd_k.

列表屏幕(List Screen)

Unit-specific(单位)格式

WRITE <f> UNIT <u>.

该语句根据Unit <u>的来设置<f>的小数位数。<u>必须要在T006中进行过配置,并且<u>的值就是T006-MSEHI字段值,T006-DECAN字段值决定<f>显示的小数位数,如果<u>在表T006中没有找到,将会忽略该UNIT选项。

该选项的使用限制如下:

?     <f>必须是P类型的

?     如果<f>本身的小数位比<u>所配置的小数位小时,系统会忽略该选项

?    如果<f>本身的小数位比<u>所配置的要多时,并且多余的小数位全部是零时,会被截断;如果多余的小数部分不是零时,会直接忽略该选项

注:该选项不像金额选项CURRENCY那样,格式化后可能会改金额本身的大小(如果存储金额的变量定义的类型中设定小数位与对应数据库表字段类型中定义的小数位不同时会发生),但这里的格式化只是确定数量输出时带几位小数而已。

,
num2 TYPE p DECIMALS 4 VALUE '2.5'.
SET COUNTRY 'US'.

WRITE: 'N/A',num1 , num2,
/ 'KG', num1 UNIT 'KG', num2 UNIT 'KG',
/ 'PC', num1 UNIT 'PC', num2 UNIT 'PC',
/ '%', num1 UNIT '%', num2 UNIT '%'.

列表屏幕(List Screen)

列表屏幕(List Screen)

数量格式化输出

问:通过se11我们可以看到ekpo中menge的数据元素是BSTMG,BSTMG的域是长度13小数位3位。在程序中我参照ekpo-menge定义的变量显示的时候后面都有3位小数,而我希望做好和me23n一样,去掉小数点后面多余的零,请问大侠们有没有比较好的办法。为什么me23n中“PO数量”显示的时候没有多余的零,而他们的数据元素是一样的。

列表屏幕(List Screen)

列表屏幕(List Screen)

列表屏幕(List Screen)

列表屏幕(List Screen)

答:MENGE实际上是个存储度量衡值的字段,他的基本数据类型是QUAN,他的小数位数并不是你看到的3,而是由这个字段关联的度量衡单位决定的,以MENGE为例,你可以在SE11的最右边一个Tab页,Currency/Quantity Fields里看到,他关联的单位是EKPO-MEINS

DATA: i_menge LIKE ekpo-menge, i_meins LIKE ekpo-meins.
START-OF-SELECTION.
  SELECT menge meins FROM ekpo INTO (i_menge, i_meins) WHERE ebeln = '4500000059'.
    WRITE: i_menge , i_meins.
    "格式化输出后也ME23N显示的格式是一样的
    WRITE: / i_menge UNIT i_meins, i_meins.
  ENDSELECT.

列表屏幕(List Screen)

不同单位之间的换算

列表屏幕(List Screen)

.
input = p_in.
CALL FUNCTION 'UNIT_CONVERSION_SIMPLE'
  EXPORTING
    input      = input
    round_sign = round"舍入方式(+ up, - down, X comm, SPACE.)
    unit_in    = unit_in
    unit_out   = unit_out
  IMPORTING
    output     = result.
WRITE: 'Result: ',result.

列表屏幕(List Screen)

交互式LIST

与屏幕一样,你可以通过SET PF-STATUS设置STATUS。在normal screen中,用户的动作可以触发PAI事件,并且在screen flow logic中可以调用相应的ABAP dialog modules来处理是这个动作。但在list processing中,事件会被list processor拦截,并在以下三种LIST事件块里进行处理(具体触发哪一个事件块,则与用户的动作相关):

?AT PF<nn>(obsolete已过时的)

?    AT LINE-SELECTION

?    AT USER-COMMAND

在各事件块中可以使用SY-UCOMM系统变量来捕获用户动作所对应的Function Code。在以上三种事件块中的任何输出,都会在事件块结束后写到新创建的detail lists中。在一个ABAP 程序中,你可以生成一个basic list与20个detail lists。

Detail Lists

如果输出语句不是在列表事件块(上面三种)里输出时,都会输出到basic list中,而在这三种事件块里输出的的内容都会输出到Detail Lists中去。

系统变量SY-LSIND存储了当前创建的list的索引,并且basic list的SY-LSIND为0。

在默认情况下,basic list具有standard list status和standard page header,并且basic list 在被创建时会触发TOP-OF- PAGE与END-OF-PAGE事件。

在可执行报表程序中,basic list会自动地传递给list processor并在END-OF- SELECTION事件后显示,否则,如果是在屏幕的PAI的ABAP dialog modules中显示basic list,则需要使用LEAVE TO LIST-PROCESSING语句来将basic list发送给list processor处理器,并且在PAI事件块执行完后才显示basic list。

创建Detail Lists

SY-,后面创建出来的Detail List的层次会依据创建的先后顺序自动的增加。凡事在AT PF<nn>、AT LINE-SELECTION、AT USER-COMMAND三个事件块里输出的内容,都会创建一个新的detail lists(每一个事件块结束后都会创建一个新的detail list)。在ABAP程序中,你可以维护一个basic list与20个detail lists。在创建新的List时,会将前面的层级的List保存下来,并且用户还可以选择显示哪层List。

默认情况下,list会完全覆盖前层次的list,但时你可以使用dialog box的方式来显示list。如果没有在事件块里为detail list设置dialog status,系统将会使用以前层次的status,但是,detail lists是没有standard page header的。

START-OF-SELECTION.
  WRITE: 'Basic List, SY-LSIND =', sy-lsind.
AT LINE-SELECTION.
  WRITE: 'Detail List, SY-LSIND =', sy-lsind.

每次在双击行都会新创建一个Detail List:

列表屏幕(List Screen)

Detail Lists不会显示standard page header(如上面的Page Title),创建时也不会触发TOP-OF-PAGE事件,但每个Detail Lists都会触发TOP-OF-PAGE DURING LINE-SELECTION事件,而END-OF-PAGE事件Basic Lists与Detail Lists在满页时都会触发。

Details Lists中的系统变量

Systemfield

Information

SY-LSIND

Indexof thelistcreatedduringthecurrentevent(basiclist= 0)

当前事件所创建的列表层级(下一列表),默认值为SY-LISTI加一,

除非重新设置了SY-LISTI

SY-LISTI

Indexof thelistlevelfrom whichtheeventwastriggered

事件触发所在列表层级(当前列表)

SY-LILLI

Absolutenumberof thelinefrom whichtheeventwastriggered

事件触发所在列表行的绝对行号(指整个输出列表的行号——所有分页算起来,且如果是SKIP等输出语句输出的空行是计算在内的,如果是分页之间的空行——严格的来讲是空隙,是不算行号的列表屏幕(List Screen)

请注意:该变量与SY-LINNO是有区别的)

SY-LISEL

Contentsof thelinefrom whichtheeventwastriggered

触发事件的行(即光标所在行)的内容(只要单击某行,SY-LISEL的内容就是当前正被选中行的内容,即光标所在行的内容)

SY-CUROW

Positionof thelineinthewindowfrom whichtheeventwastriggered(countingstartswith1)

事件触发所在窗体中的行号(这是相对于窗体来说的,指触发事件的行在当前窗体中的行号,并且空行也算,注:每个窗体的行号只与窗口的大小有关,且窗口大小定以后,其能显示的最大行数也就固定了)

SY-CUCOL

Positionof thecolumninthewindowfrom whichtheeventwastriggered(countingstartswith2)

事件触发所在窗体中的行SY-CUROW中的列位置

SY-CPAGE

Pagenumberof thefirstdisplayedpageof thelistfrom whichtheeventwas triggered

触发事件的列表屏幕中所显示的第一页的页号

列表屏幕(List Screen)

SY-STARO

Numberof thefirstlineof thefirstpagedisplayedof thelistfrom whichtheevent wastriggered(countingstartswith1).Thislinemaycontainthepageheader.

事件触发所在列表中显示出来的第一页的第一行的行号

SY-STACO

Numberof thefirstcolumndisplayedinthelistfrom whichtheeventwastriggered

(countingstartswith1)

显示在列表行中的第一列(除开已被隐藏的列)的列的列号:

列表屏幕(List Screen)

列表屏幕(List Screen)

该系统变量会随着水平滚动条的滚动而变化。

SY-UCOMM

Functioncodethattriggeredtheevent

SY-PFKEY

Statusof thelistcurrentlybeingdisplayed.

Detail Lists中的消息

?    A(=Abend):Termination结束,停止

.消息会显示在弹出对话框中,且当用户回车确认后,整个程序会结束

?    E(=Error)orW(=Warning):

消息会显示在状态栏中。一旦用户使用ENTER确认了这个错误消息,则当前的事件块会终止并且显示前一级别的list。如果是在创建basiclist时出现错误消息,则整个程序也会被终止掉

?    I(=Information):

.消息会显示在弹出对话框中。一旦用户确认了消息(ENTER),程序会继续处理MESSAGE语句后面的语句

?    S(=status)

消息会在当前list状态栏显示

?    X(=Exit)Runtimeerror:

该消息类型会触发一个runtimeerror并且会产生一个shortdump

LIST屏幕导航

可以通过列表屏幕(List Screen)回退到上一级别的List。在以通过修改SY-LSIND来决定当前事件块里的输出内容将输出到哪一级别层次的LIST屏幕上

注:列表屏幕(List Screen)返回时,不会根据程序的导航轨迹来回退,如程序导航轨迹为: 0 à 1 à 2 à 1 à 2 à 1 à 2,在最后一个2号LIST屏幕上点击Back时,返回的轨迹为  2 à 1 à 0(只能回退两次,而不是6次)

当使用sy-lsind重新定位输出到哪个LIST屏幕上时,如果只是定位(当前事件块中根本没有任何的输出时),则定位到的一下屏幕不会被重画,而是原样显示历史数据屏幕,但一旦有任何输出,则屏幕则会被重画。

START.
  ENDIF.
  WRITE: 'Detail List, SY-LISTI =',sy-listi.

列表屏幕(List Screen)

START.
  ELSE.
    "sy-lsind = 3时,这里的内容不会输出到 Basic List上,
    "此时会Basic List屏幕不会被重画,还是显示成最初的样子
    WRITE: 'Detail List, SY-LSIND =', sy-lsind.
    WRITE: 'Detail List, SY-LISTI =',sy-listi.
  ENDIF.

列表屏幕(List Screen)

GUI Status for Lists

在LIST屏幕上对某行进行双击或按F2就会触发相应的列表事件(AT PF<nn>、AT LINE-SELECTION、AT USER-COMMAND)。在Menu Painter中,double-click 动作与F2绑定了(F2就代表了双击,双击也即F2),如果在GUI status中将某个Function code分配给了F2键,当你双击时,就会触发这个Function Code。

标准的 List Status(SET PF-STATUS space)及事件

你可以像普通屏幕那样,给LIST设计GUI status,并通过SET PF-STATUS语句进行绑定(如果想为特定的层次的LIS设置GUI status,则需要使用SY-LSIND进行判断)。

如果在报表程序(可执行程序)中没有设置(Basic List与Detail List都未设置时)特定的GUI status,则系统会将list screen的Status设置为系统内置的default list status;在其他类型的程序中(如当你在Screen中创建一个list时),你可以明确的调用下面语句来设置成系统内置的default list status(该Status与报表程序默认的Status是一样的):

SET PF-STATUS space.

该语句定义了Standard List所拥有的默认functions,

系统所提供的内置default list status如下(具体有以下这些Menu Bar与Standard toolbar,并且这些功能都已经被系统实现了,可以直接使用):

列表屏幕(List Screen)

如果在程序中还定义了如下事件,则系统还会自动为LIST分配额外的functions:

2  AT PF<nn>(obsolete)已过时

键盘上的F<nn>(01 到 24)键不再具有系统预置功能,它们都将与function codes PF<nn>关联,并且function codes PF<nn>与事件AT PF<nn>对应

REPORT demo_list_at_pf .
START-OF-SELECTION.
  "PF5, PF6 这些Function code并没有在Stauts中进行
  "过任何定义(这里也没有设置Status,使用的是Standard List Status)
  "但按 F5, F6 这些键时会触发相应的事件块 AT PF<nn>
  WRITE 'Basic List, Press PF5, PF6, PF7, or PF8'.
AT PF5.
  PERFORM out.
AT PF6.
  PERFORM out.
FORM out.
  WRITE: 'Secondary List by PF-Key Selection',
       / 'SY-LSIND =', sy-lsind,
       / 'SY-UCOMM =', sy-ucomm.
ENDFORM.

2  AT LINE-SELECTION

当用户在LIST屏幕上的某行上按F2或者鼠标双击时,就会触发该事件块,并且此时的function code默认名为PICK注:Function code PICK触发的前提是光标已经定位在了LIST列表中的某行上了。

REPORT demo_list_at_line_selection.
START-OF-SELECTION.
  WRITE  'Basic List'.
AT LINE-SELECTION."选中某行后按F2或在某行上双击就会触发
  WRITE: 'Secondary List by Line-Selection',
  / 'SY-UCOMM =', sy-ucomm.

2  AT USER-COMMAND

除上面PF<nn>与PICK两个Function code以外,其他的function codes将被runtime environment拦截或者是触发AT USER-COMMAND事件。

在LIST SCREEN中,那些触发AT USER-COMMAND事件的Function codes(除了PF<nn>与PICK)都是自己在GUI statu中进行自定义过的;而能被runtime environment所拦截直接进行处理的,都是系统提供的standard function codes(具体是哪此Function code请参见Dialog Status for Lists中两个表格中所提到的,但也除了PF<nn>与PICK)。

通过程序触发事件

除了通过手动触发LIST屏幕事件之外,还可以直接通过编程的方式来触发:

?SET USER-COMMAND <fc>.

该语句会在当前列表事件块里的所有输出结束后生效(这意味着该语句放在输出语句的前后都没有关系),并在列表显示之前触发与<fc>对应的事件。其作用与用户手动选择了相应的Function Code是一样的,换句话说,预置的列表function code将会被runtime environment捕获与处理,function codes PICK与PF<nn>将会分别触发AT LINE-SELECTION and AT PF<nn>事件,而用户自定义的Function code将会触发AT USER-COMMAND事件块。

如果在创建LIST时使用好几个SET USER-COMMAND这样的语句,则只有最的一个语句会被执行。

示例:事件连锁反应

.
  SET USER-COMMAND 'PICK'.
  "当 AT PF05 事件触发后会立即触发AT LINE-SELECTION事件
  WRITE 'Secondary List from PF05,'.
  WRITE: 'SY-LSIND', sy-lsind.
AT LINE-SELECTION.
  "当AT LINE-SELECTION事件触发后,又会立即触发 %SC 查找事件
  SET USER-COMMAND '%SC'.
  WRITE 'Secondary List from LINE-SELECTION,'.
  WRITE: 'SY-LSIND', sy-lsind.
  WRITE: / '-',sy-lisel NO-GAP.

最后显示屏幕如下:

列表屏幕(List Screen)

但前面的屏幕可以通过 BACK 回退时显示

Status for Lists

可以通过Menu Painter为LIST创建dialog status,先创建普通类型的Status:

列表屏幕(List Screen)

结果如下:

列表屏幕(List Screen)

再选择菜单ExtrasàAdjusttemplate,并在弹出框中选择系统内置的“List status”Status Template来填充上面的Status:

列表屏幕(List Screen)

结果如下:

列表屏幕(List Screen)

上面通过内置“List status”Status模板(通过Status内在模板,这样我们就不必一个个输出设置了)填充的Function Code其实就是系统为List Screen提供的默认标准Status(标准的Status的具体样子可以参照上一节内容中的截图Standard List Status

standard list status所提供的standard function codes分布在Menu、Standard toolbar、Function key三大Interface中,具体分如下:

Func Code

所在的的

Menu

所在的

Standard toolbar

Function key

Description

%PC

List

Savelisttofile

%SL

List

Savelist in SAPoffice

%ST

List

Savelist inreporttree

%PRI/ PRI

List

列表屏幕(List Screen)

CTRL-P

Printdisplayedlist

%EX

List

列表屏幕(List Screen)

Shift-F3

Exitprocessing

PICK

Edit

列表屏幕(List Screen)

F2

EventAT LINE-SELECTION

RW

Edit

列表屏幕(List Screen)

F12,ESC

Cancelprocessing

%SC

Edit

列表屏幕(List Screen)

CTRL-F

Find

%SC+

Edit

列表屏幕(List Screen)

CTRL-G

Findnext

BACK

Goto

列表屏幕(List Screen)

F3

Back onelevel

P--

列表屏幕(List Screen)

CTRL-PgUp

Scrolltofirstwindowpage

注:这4个翻页按键是对整个LIST Window起作用的,而不是针对程序软分页,它们的滚动是针对当前LIST所在Window,窗体高度不一样,则滚动的长度不一样

P-

列表屏幕(List Screen)

PgUp

Scrollto previouswindowpage

P+

列表屏幕(List Screen)

PgDn

Scrollto nextwindowpage

P++

列表屏幕(List Screen)

Ctrl-PgDn

Scrollto lastwindowpage

%CTX

鼠标右击

Shift-F10

Contextmenuonlist

上表格Standard toolbar中的图标所对应的按键是已经预置好了的(这些键不能再分配给其他Function Code了),具体如下:

列表屏幕(List Screen)

另外,下面这些function codes也是系统内置的,它们并没有在上面的Status中直接给我们进行了设置,但你可以*的将这些Function Code在status 中定义它们来使用:

Func Code

Description

PF<nn>

EventAT PF<nn>

PP<n>

Scrolltotopof listpage<n>

PP-[<n>]

Scrollback onelistpageor<n>pages

PP+[<n>]

Scrollforwardonelistpageor<n>pages

PS<n>

Scroll to column <n>

PS--

Scroll to first column of the list

PS-[<n>]

Scroll left by one or <n> columns

PS+[<n>]

Scroll right by one or <n> columns

PS++

Scroll to last column of the list

PZ<n>

Scroll to line <n>

PL-[<n>]

Scroll back to first line of the page or by <n>lines

PL+[<n>]

Scroll to last line of the page or by <n>lines

/....

For other system commands

除了PICK and PF<nn>这两Function code以外,上面两个表格中所列的Function code都将直接被runtime environment拦截下来进行处理,我们不需要捕捉这些Function Code,也不需要实现它们(因为这些Function Code根本不会触发事件的,所以不能在AT USER-COMMAND中使用它们)。

只要光标在List Screen中的某行上,Function code PICK会触发AT LINE-SELECTION事件;而function codes PF<nn>总是会触发AT PF<nn>事件,所以不能在AT USER-COMMAND事件中使用(因为没有触发此事件)。

如果自己定义的Function Code名不是上面两个表格中所预置的Function Code,则才会触发AT USER-COMMAND 事件。

请注意下面功能键的分配:

?    FunctionkeyF2:

双击相当于按功能键F2,所以分配给F2键的functionn code都将具有鼠标双击的功能。但要触发AT LINE-SELECTION事件,则分配给F2的Function code只能是PICK,否同双击或按F2时,将会去触发AT USER- COMMAND事件或者被runtime environment拦截处理。

?    FunctionkeySHIFT-F10:

SHIFT-F10键相当于鼠标右击,如果要弹出右键菜单,则需要将此键与名为%CTX的function code进行绑定。

你也可以修改上面Status图中的由list-specific template模板所填充的默认Function code,以满足其他需求:

?     使用自己定义的Function code名替换换掉PICK,这样将不会再触发AT LINE-SELECTION事件,你可以在AT USER-COMMAND中统一进行处理也可。

?     你可以删除那些你不想要的功能Function code。例如,阻止打印与保存。

?     修改内置标准的Key(内置Key有哪此可以参看上面截图中快捷键所示)所对应的Function Code。例如,你可以重新给F3分配自己的Function Code,而不是BACK,这样按列表屏幕(List Screen)时就不会被runtime environment拦截处理,也就是说不会走系统提供的默认回退功能,我们可以在AT USER-COMMAND事件中重新来实现自己特殊的回退功能(比如在回退前弹出一个警告提示框等)

Setting Status

SET PF-STATUS <stat> [EXCLUDING <f>|<itab>] [OF PROGRAM <prog>] [IMMEDIATELY].

所有层次级别的后续List都会使用<stat>,除非重新使用语句进行了设置。系统变量SY-PFKEY存储了当前LIST所使用的Status。

使用SET PF- STATUS SPACE语句可以设置成standard list status。

IMMEDIATELY选项是特定为list processing所设计的(即LIST Screen才具有,其他类型的屏幕没有这个选项)。如果在创建detail list的事件块里使用了该选项,则当前(index SY- LISTI)LISTScreen的Status也会被修改,并且当前事件块所创建出的Detail List也会使用这个设置的Status(因为根本没有为Detail List设置Status,所以使用前一LIST屏幕的Status);如果没有使用该选项,将会在事件块处理结束后修改当前后续(SY- LSIND) List屏幕的Status。

START-OF-SELECTION.
  WRITE: 'SY-LSIND:', sy-lsind.
AT LINE-SELECTION.
  SET PF-STATUS 'TEST' OF PROGRAM 'DEMO_LIST_SET_PF_STATUS_2' IMMEDIATELY.

上面实例程序中AT LINE-SELECTION.事件块中没有输出内容,所以不会产生新的Detail List,所以SET PF-STATUS语句执行后,我们可以立刻看到Basic List的Status以修改了:

列表屏幕(List Screen)

其他选项请参考SET PF-STATUS

列表屏幕(List Screen)

REPORT demo_list_menu_painter.
START-OF-SELECTION.
  SET PF-STATUS 'TEST'.
  WRITE:  'Basic list, SY-LSIND =', sy-lsind.

AT LINE-SELECTION."F2或双击行  点击菜单 Edit-->Choose时触发
  WRITE:  'LINE-SELECTION, SY-LSIND =', sy-lsind.

AT USER-COMMAND.
  CASE sy-ucomm."F5或点击工具条中的Test for demo按键时触发
    WHEN 'TEST'.
      WRITE:  'TEST, SY-LSIND =', sy-lsind.
  ENDCASE.

列表屏幕(List Screen)

Setting a Title for a List

请参考SET TITLEBAR

右键菜单 for Lists

如果想为LIST屏幕设置右键菜单,先需要为Status分配Context Menu(分配后们可以在Menu Painter中看到快捷键Shift+F10分配一个Function Code名为%CTX,注:Function Code名一定要为%CTX,否则不会触发右键菜单),然后再激活它,最后并使用SET PF-STATUS将这个分配并激活了右键的Status分配给LIST Screen,这样才能使用右键。其分配与激活过程如下:

1、 在Dialog Status for Lists章节中创建的Status基础上,分配右键Context Menu:

列表屏幕(List Screen)

2、 再激活Function Code:%CTX

列表屏幕(List Screen)

3、 在列表屏幕的行上右击,则会触发右键菜单并回调以下形式的Form:

FORM on_ctmenu_request USING l_menu TYPE REF TO cl_ctmenu.

在该Form中可以通过cl_ctmenu静态的加载(加载静态的右键菜单请参考Context Menus for Screen中的代码示例)已设计好的Context Menu或动态的新增或删除菜单项。

开计号)
  (或第3以后的)列表行右击,并且列表层次是在第0层上时
  .

ENDFORM.

以框模窗口显示LIST

你可以WINDOW语句以对话框方式来显示当前(indexSY-LSIND)的LIST,而不是全屏显示(屏幕与选择屏幕的对话框模式请参考Call屏幕Call选择屏幕):

WINDOW STARTING AT <left><upper> [ENDING AT <right><lower>].

<left><upper>分别指定了窗口最左上角所在的column 与 line。如果<upper>为0,将会全屏显示。

<right><lower>分别指定了窗口最右下角所在的column 与 line。通常默认值为事件所发生的窗体的右小角所在的位置。

如果窗体指定的宽度小于了预置的列表LIST的宽度,则会出一水平滚动条。为了防止出现滚动条,可以使用下的语句来调LIST列表的输出宽度:

NEW-PAGE LINE-SIZE<width>.

注:WINDOW语句只能用于detaillists,也就是说只能出现在上面Standard List Status及事件所提到的三种交互式事件里。

Dialog boxes(包括对话框模式的LIST、对话模式模式的屏幕与选择屏幕)都是没有menu barstandard  toolbar标准工具栏,并且application toolbar会显示在LIST对话框的左下角下面,这是R/3系统的公共特点。

如果对话框模式的LIST屏幕没有设置status,但在程序中定义了AT LINE-SELECTION 或者 AT PF<nn>事件处理块,则系统会为dialog box使用standard list status 。

如果需要为dialog box类型的LIST定义一个Status,则在创建时需要在Menu Painter中选择Dialog box类型的Status:列表屏幕(List Screen)

这种类型的Status系统不会为我们提供menu bar 与 standard toolbar,但在application toolbar中系统提供了预置的Function Code PRI, %SC, %SC+, and RW允许用户打印、搜索、关闭窗口。

列表屏幕(List Screen)

列表屏幕(List Screen)

Detail ListStatus
        Detail ListStatus
        SET PF-STATUS 'DIALOG' EXCLUDING 'SELE'.
        SET TITLEBAR 'WI2'.
        WINDOW STARTING AT 45 10 ENDING AT 60 12.
        WRITE 'Last window'.
      ENDIF.
  ENDCASE.

列表屏幕(List Screen)

列表屏幕上的数据与程序间的传递

通过系统变量传递

列表交互事件触发时会填充系统变量

.
DO 100 TIMES.
  WRITE: / 'Loop Pass:', sy-index.
ENDDO.

"只有在创建Basic List时才触发
TOP-OF-PAGE.
  WRITE: 'Basic List, Page', sy-pagno.
  ULINE.
  "该事件只在创建Detail List时触发
TOP-OF-PAGE DURING LINE-SELECTION.
  WRITE 'Secondary List'.
  ULINE.

AT LINE-SELECTION.
  WRITE: 'SY-LSIND:', sy-lsind,"当前事件所创建的列表层级(下一列表)
       / 'SY-LISTI:', sy-listi,"事件触发所在列表层级(当前列表)
       / 'SY-LILLI:', sy-lilli,"事件触发所在列表行的绝对行号(指整个输出列表的行号,不管是否有分页,且空行不算)
       / 'SY-CUROW:', sy-curow,"事件触发所在窗体中的行号(这是相对于窗体来说的,指触发事件的行在当前窗体中的
       "行号,并且格也算,注:每个窗体的行号只与窗口的大小有关,且窗口大小定以后,其能显示的最大行数也就固定了)
       / 'SY-CUCOL:', sy-cucol,"事件触发所在窗体中的行SY-CUROW中的列位置
       / 'SY-CPAGE:', sy-cpage,"事件触发所在列表中显示的第一页的页号
       / 'SY-STARO:', sy-staro,"事件触发所在列表中显示的第一页的第一行的行号
       / 'SY-LISEL:',sy-lisel. "事件触发所在列表行的内容

使用SY-LISEL

SY-LISEL类型为C(255),SY-LISEL存储的内容最大只有255(好像一行最多也只能输出255,请参考LINE-SIZE),所以每行输出长度不应该超过这个数,并且它是将整行的内容都存储下来了,所以要取得每个Field,则需要通过offset方式来截取。所以SY-LISEL只适合于取 List的Header行内容,以及检测是否选中了行,

行输出。当双击此行时,会求1到100各数的平方数
行输出。当双击此行时,会求1到100各数的立方数
行时
        行时
        .
          WRITE: / sy-index, num.
        ENDDO.
    ENDCASE.
  ENDIF.

通过程序语句

当存储的信息不是整行时,而是某些输出列时,可以使用这些技术。

HIDE (列表隐藏域)

HIDE<f>.

变量<f>可以是整行或部分输出列的变量,甚至是其他与行内容无关的变量。

当单击(即光标所在的行)List屏幕中的行时,如果对应的行设置了隐藏字段,则HIDE隐藏字段变量<f>会自动被存储值填充;当然也可以使用READ LINE来手动控制读取填充。

注:局部变量不能存储到HIDE区域中

示例请参考右键菜单 for Lists中的代码示例

为了在AT LINE-SELECTION事件的处理块中能够访问到用户在上层列表屏幕上选中的行的主键,应该在上一级列表屏幕每一条记录被显示的时候将该记录的主键保存到隐藏域中,这样当用户在上层屏幕上选中一行的时候,该行保存在隐藏域中的主键在AT LINE-SELECTION事件块中将自动有效:

HIDE :  wa_spfli-carrid,
           wa_spfli-connid.

而且该保存语句要在本行数据被WRITE语句输出到列表缓冲区后在后面紧着编写(为了隐藏的数据与当前输入的数据一致)。这样当被双击时,保存在隐藏域中的字段的值将自动被传回到原始字段中:

列表屏幕(List Screen)

隐藏域是一个内表,其行结构包含了三个字段:被选中行的行号、字段名、字段值,当保存数据时,每个被保存的字段在隐藏域中形成一行。

()  () ()  ()  ()  .
      () () .
      WRITE : / 'currrent list leve is : ' , sy-lsind.
  ENDCASE.

READ LINE

READ LINE <lin> [INDEX <idx>]

[FIELD VALUE <f1>[INTO <g1>]...<fn>[INTO <gn>]] [OF CURRENT PAGE|OF PAGE <p>].

该语句会将事件触发所在的List((index SY-LILLI))中的第<lin>行的内容存储到SY-LISEL系统变量中,并且随之将<lin>行所对应的HIDE字段也进行相应填充。另外会将Write显示输出的名为<fn>字段的值存储到<gn>全局变量中(如果加上了<gn>的前提下,否则会默认存储到名为<fn>的变量中去)。如果读取的行存在,则SY-SUBRC to 0, otherwise to 4

?    INDEX<idx>

从<idx>级别的LIST屏幕上读取行

?    FIELD VALUE<f1>[INTO<g1>]... <fn>[INTO<gn>]

系统会将输出字段<f1>的值以字符串的存储到同名的变量中,或者当使用INTO时,存储到<g1>变量中。在读取与存储的过程中会应用到相应的转换规则。

行中使用HIDE语句输出的字段不能使用该选项来显示读取(但在使用READ LINE语句会,HIDE字段会自动的被读取填充)。如果某个字段多个显示输出,则系统只会读取第一个。

此选项读取出来的值是Write语句的格式化后的值,即会保留格式字符:

).
START-OF-SELECTION.
  WRITE:/ p , c RIGHT-JUSTIFIED.
END-OF-SELECTION.
  CLEAR: p,c.
  READ LINE 3 FIELD VALUE p INTO PC  c INTO CC.

列表屏幕(List Screen)

列表屏幕(List Screen)

?    OFCURRENTPAGE

此时的<lin>不是整个列表(包括所有分页)中的行号,而是SY-CPAGE页面中的行号

?    OFPAGE<p>

此时的<lin>不是整个列表(包括所有分页)中的行号,而是<p>页面中的行号

,所以屏幕上已输出的实际行数需在sy-linno基础上减1
  .
            NEW-PAGE."换页输出
            "sflight-carridsflight-connidHIDE区域中读取,它们的值是在
            "前面的READ LINE之后自动填充
            WRITE: 'Company:', sflight-carrid,
                   'Connection: ',sflight-connid,
                 / 'Number of free seats:', free.
          ENDIF.
        ENDIF.
      ENDDO.
  ENDCASE.

列表屏幕(List Screen)列表屏幕(List Screen)

GET CURSOR FIELD、GET CURSOR LINE

GET CURSOR FIELD <f> [OFFSET <off>] [LINE <lin>] [VALUE <val>] [LENGTH <len>].

将光标所在字段名存储到变量<f>中。如果光标在字段上,则SY-SUBRC to 0, otherwise to 4

输出字段名可能是全局变量、常量、字段符号、或Form的引用参数,<f>存储的名就是相应名称(字段符号为所分配的变量名,而不是字段符号本身名)。对于字面常量、局部变量或Form的传递值方式的参数,系统会设置SY-SUBRC to 0,并且将<f>设置为SPACE

?    OFFSET<off>

<off>存储了光标所在字段里的位置。如果光标在字段的最前,则<off>=0

?    LINE<lin>

存储光标所在屏幕中位置行号(SY- LILLI

?    VALUE<val>

存储光标所在字段的内容,包括输出格式字符,取出的类型为字符类型,如果与<val>类型不兼容可能会发生类型转换

?    LENGTH<len>

存储光标所在位置字段的输出长度

GET CURSOR LINE <lin> [OFFSET <off>] [VALUE <val>] [LENGTH <len>].

将用户选择的行(光标所在行)的行号存储到变量<lin>中。如果光标在列表行上,则SY-SUBRC to 0,否则为4

?    OFFSET<off>

存储光标所在行中的偏移量,如果在行首,则<off> = 0

?    VALUE<val>

存储光标所在行的内容,包括格式字符

?    LENGTH<len>

存储光标所在行的输出长度

).
  WRITE:  / 'Line:  ', lin,
          / 'Offset:', off,
          / 'Value: ', val,
          / 'Length:', len.

列表屏幕(List Screen)

DESCRIBE LIST获取列表属性

DESCRIBE LIST NUMBER OF LINES|PAGES <n> [INDEX <idx>].

计算指定层次列表屏幕上的总行数或总页数,如果index <idx>的列表不存在,SY-SUBRC为非0

DESCRIBE LIST LINE <lin> PAGE <pag> [INDEX <idx>].

根据指定的<idx>与<lin>来确定指定行所在哪一页,并将页号存储到<pag>中。如果index <idx>的列表不存在,SY-SUBRC为8,如果指定的行<lin>不存在,SY-SUBRC为4

DESCRIBE LIST PAGE <pag> [INDEX <idx>] [<options>]

取回<idx>级LIST屏幕中<pag>页的属性,具体取哪些属性由<options>选项决定。如果index <idx>级的列表不存在,SY-SUBRC为8,如果指定的页<pag>不存在,SY-SUBRC为4

<options>如下:

?    LINE-SIZE<col>

将指定的页面宽度存储到<col>变量中

?    LINE-COUNT<len>

将指定的页面宽度允许的最大行数到<len>变量中,即程序开头或者NEW-PAGE 所带选项LINE-COUNT的值

?    LINES<lin>

将指定的页面中当前已输出的行数存储到<lin>变量中,所以<lin>只可能小于或等于上面的LINE-COUNT<len>

?    FIRST-LINE<lin1>

将指定页面的第一行(如果有Header,则指Header的第一行)所在绝对行号(SY-LILLI)存储到<lin1>变量中

?    TOP-LINES<top>

将指定页面的header行数存储到<top>变量中,包括standard page headerTOP-OF-PAGE里所输出的总行数。

?    TITLE-LINES<ttl>

将standard page header的行数存储到<ttl>变量中,

?    HEAD-LINES<head>

将standardpageheader部分中的,其中包括了一条下划线)

?    END-LINES<end>

将pagefooterlines行数存储到<end>变量中

列表屏幕(List Screen)

) pag NO-GAP,'的页面属性如下:' NO-GAP,
       / '页面行宽度:       ', 25 col,
       / '页面允许最大行数:      ', 25 len,
       / '当前页上已输出的总行数:       ', 25 lin,
       / '当前页第一行的绝对行号:  ', 25 lin1,
       / '页面头所占行数: ', 25 top,
       / '标准头所占行数: ',25  tit,
       / 'column header行数:', 25 head,
       / '页脚所占行数:',25 end.

列表屏幕(List Screen)

操控 Detail Lists

Scrolling in Detail Lists

可以使用SCROLL语句来滚动列表,章节滚动列表描述了basic lists中如何滚动。

当你在detail lists使用SCROLL语句,需要注意以下几点:

?    应该在所有输出语句之后,再使用该语句

?    如果没有指定INDEX选项,在创建下一个新secondarylist时,其滚动是针对当前事件触发所在列表屏幕的(indexSY-LISTI),而不是新创建的下一LIST(SY-LSIND)

?    仅只有当创建basiclist时,SCROLL是针对当前正在创建的LIST

?    你可以使用INDEX选项明确的指定SCROLL作用于哪个LIST。在SCROLL之前是不需要先显示的,可以先滚动,在显示时会滚动条会自动定位到相应位置。如果指定的INDEX列表不存在,则SY-SUBRC为8

具体示例请参考滚动列表章节的示例

也可以使用通过程序触发事件

设置光标位置

SETCURSOR语句只会地最近的已创建的列表(most recently-createdlist)起作用:当创建basiclist时,该语句是针对basiclist;对于正创建的detaillist,则针对以前list的(indexSY-LISTI)。

">SET CURSOR <col><lin>

SET CURSOR <col><lin>.

定位到输出窗口中的<lin>行的<col>(窗口中显示的第一列的<col>值为是1,即使水平滚动后也是这样)列。系统只能将光标定准到窗体中可见的位置上,在显示以外的区域,该语句不起作用。如果要定位目前没有显示出来的区域,则需要先SCROLL列表。

不能将光标定准到使用SKIP语句输出的空行上,但输出的下划线可以。如果<lin>超出来最大行,则会将光标定准到最后一行上面

注:<col>是基于当前窗口显示列,而不是整个LIST Page,即已被隐藏的列不会被计算到<col>里,如下图中使用行11列,即在第一个文本输出框中:

列表屏幕(List Screen)

当手动水平滚动到如下的位置后,再使用:

列表屏幕(List Screen)

示例:

列前
  SET CURSOR 11 3.

列表屏幕(List Screen)

SET CURSOR FIELD

SET CURSOR FIELD <f> LINE <lin> [OFFSET <off>].

将光标定位到行<lin>中名为<f>的列上,如果有多个这样的列,则定位到第一个字段上面。如果字段不存在或者字段不在显示区,则忽略该语句,但可以先通过SCROLL语句将它滚动到显示区再定位

使用OFFSET将光标定位到字段的<off>位置,<off> = 0表示字段的列(注:隐藏的部分也算)

注:<lin>是包括Header行在内在的

SET CURSOR LINE

SET CURSOR LINE <lin> [OFFSET <off>].

将光标定准到行<lin>。如果指定的行不存在或不在显示区,则会忽略此语句,可以先通过SCROLL语句滚动到显示区再定位

使用OFFSET选项会将光标定位到<lin>行中的<off>位置(<off>指整行的计数,隐藏的部分也算。<off> = 0表示行的第一列)

列表屏幕(List Screen)

.
  ENDCASE.

修改列表行(内容及输出格式)

有以下两种方式来修改LIST SCREEN中的行,

第一种是明确指定要修改的行:

MODIFY LINE <n> [INDEX <idx>|OF CURRENT PAGE|OF PAGE <p>] [<modifications>].

如果没有  [INDEX <idx>|OF CURRENT PAGE|OF PAGE <p>]  选项,则修改的行为事件发生的当前LIST SCREEN(index SY-LISTI)中的<n>行,如果附加了此选项,则各选项的意思如下:

INDEX <idx>选项指定了索引级别为<idx>中的第<n>

OF CURRENT PAGE选项指定了当前显示page (page number SY-CPAGE)中的第<n>行

PAGE <p>选项指定了page <p>的line <n>

第二种是针对最近一次读取到的行:

MODIFY CURRENT LINE [<modifications>].

该语句修改的是针对最近一次选择(F2)的行或使用READLINE语句读取到的行

如果没有<modifications>选项,则上面两个语句会直接使用系统变量SY- LISEL的内容来修改指定行的内容,并且行所对应的HIDE area也将被重写。如果指定的行修改成功,则SY-SUBRC to 0,否则为非0

选项<modifications>可以为以下几种:

修改行的格式

... LINE FORMAT <option1><option2>...

该选将修改整个行的输出格式,其具体的格式请参着FORMAT语句

.
  ENDIF.
  MODIFY CURRENT LINE LINE FORMAT COLOR = c.
  ADD 1 TO c.

列表屏幕(List Screen)

修改字段的内容

... FIELD VALUE <f1>[FROM <g1>]<f2>[FROM <g2>]...

该语句的作用是先使用<f1>或者是<g1>变量的值来修改SY-LISEL系统变量中<f1>字段所在位置的值,然后再使用SY-LISEL系统变量的内容来进行整行内容的修改(这样就确保了显示的行与SY-LISEL内容一致)。如果有必要会在修改前会将值转换为C类型。如果<f1>在行中多次出现,则仅修改第一个,如果不存在,则系统会忽略该选项

) = '*'.
  MODIFY CURRENT LINE FIELD VALUE c.

列表屏幕(List Screen)

修改字段的格式

... FIELD FORMAT <f1><options1><f2><options2>...

该选将针对行中的某个字段的的输出格式进行修改,其具体的格式请参着FORMAT语句

选项将覆盖LINE FORMAT选项指定的相应字段的输出格式。如果<f1>在行中多次出现,则仅修改第一个,如果不存在,则系统会忽略该选项

) TYPE c.
SET PF-STATUS 'CHECK'.
DO 5 TIMES.
  num = sy-index.
  WRITE: / box AS CHECKBOX, 'Line', num.
  HIDE: box, num.
ENDDO.
"屏幕上输出的总行数
lines = sy-linno.
TOP-OF-PAGE.
  WRITE  'Select some checkboxes'.
  ULINE.
AT USER-COMMAND.
  CASE sy-ucomm.
    WHEN 'READ'.
      SET PF-STATUS 'CHECK' EXCLUDING 'READ'.
      box = space.
      DO lines TIMES.
        "读取屏幕上指定行中box字段的内容
        READ LINE sy-index FIELD VALUE box.
        IF box = 'X'.
          WRITE: / 'Line', num, 'was selected'.
          box = space.
          MODIFY LINE sy-index
                      FIELD VALUE  box
                      FIELD FORMAT box INPUT OFF
                                   num COLOR 6 .
        ENDIF.
      ENDDO.
  ENDCASE.

列表屏幕(List Screen)

Lists 与 Screens之间的切换

当你运行一个可执行程序时,list processor(列表处理器)会在最后一个processing block(事件处理块END-OF- SELECTION)结束时自动的运行,与此同时basic list将会被创建并显示

如果你想在screen processing(屏幕处理)过程中显示 lists,你必须对此进行编程控制,相反,你也可以编程从list processing(列表处理)切换到screen processing(屏幕处理)

从Screen Processing 屏幕处理切换到Lists列表输出

CALL SCREEN屏幕调用或Tcode都会开启screen sequence,系统会进行Screen processing。在Screen processing期间,ABAP program将会被dialog processor(对话处理器)接管控制,screen flow logic中调用的PBO 与 PAI modules将会被执行

为了将dialog processor控制权转交给list processor,你可在PBO dialog modules 中调用下面这样的语句:

LEAVE TO LIST-PROCESSING [AND RETURN TO SCREEN<nnnn>].

该语句可以使用在PBO或者PAI event中。它的作用是在当前屏幕的PAI processing(一般在PBO块里使用SUPPRESSDIALOG.或LEAVESCREEN.语句后不会显示这个屏幕,此时在PBO事件块结束后立即显示Basic List)结束后开始list processor并显示Basic List。调用该语句所在屏幕的PBO and PAI modules中的list output(列表输出)都会被输出到Basic List中缓存起来,待该屏幕处理完后(如果没有使用SUPPRESSDIALOG.或LEAVE SCREEN.语句,则在PAI结束后显示;如果使用了这两个语句,则会在PBO块结束后就会显示)。如果在ABAP Program事件块AT LINE-SELECTION,AT USER-COMMAND中输出了内容,将会产生更多层次的detail lists

可以使用以下两种方式来离开list processing:

?    在basiclist中点击Back,Exit,orCancel

?    在list processing程序中使用:LEAVE LIST-PROCESSING.

以上两种方式都会使控制权从list processor转交到dialog processor。

在默认的情况下,不带AND RETURN TO SCREEN选项的LEAVE TO LIST-PROCESSING语句在当list processor 处理结束后(如关闭list列表输出窗体时),dialog processor将会又会返回到LEAVE TO LIST-PROCESSING语句调用所在屏幕的PBO事件块,并重新执行PBO事件块(所以这样使用会出现死循环:关不掉List列表输出窗口);选项AND RETURN TO SCREEN允许你指定当前屏幕序列(即LEAVE TO LIST-PROCESSING语句调用所在屏幕所在的屏幕序列)中的某个屏幕,当list processor 处理结束后,dialog processor将会回到指定的屏幕并执行其相应的PBO事件块;另外可以通过下面语句:

LEAVE TO LIST-PROCESSING AND RETURN TO SCREEN 0.

来实现当结束List列表输出窗口时,结束当前屏幕序列(即LEAVE TO LIST-PROCESSING语句调用所在屏幕所在的屏幕序列),并返回到该屏幕序列启动(调用)的地方(如果是该屏幕序列是在屏幕的PAI事件块里的某个MODULE里开启的,则返回到PAI事件块里的相应MODULE调用语句处,并继续后面的PAI事件块语句的执行;如果该屏幕序列是在ABAPProgram中开启的,则会回到 ABAP程序中call screen语句处,继续执行后面程序):

如果你想在screen processing屏幕处理中显示 lists 列表输出屏幕时(即从Screen 切换到 List 屏幕输出时),你需要为这个将要输出的Basic List 屏幕设计一个单独的空的Screen,并在这个空的屏幕(不需要PAI事件块)的PBO事件块中某个module里创建(使用上面语句LEAVE TO LIST-PROCESSING来创建)与显示Basic List,这个空屏幕可以使用CALL SCREEN语句在任何想调用的地方进行调用即可。

实际上,如果在PBO MODULE里没有使用 SUPPRESS DIALOG. 或  LEAVE SCREEN. 语句时,调用LEAVE TO LIST-PROCESSING语句的屏幕还是会显示出来,这时我们只需要在该屏幕上触发一下Function code即可(回车、双击都可)切换到由该屏幕PBO MODULE生成的Basic List,并显示Basic List。

列表屏幕(List Screen)

只要切换到了List输出屏幕,则可以对List屏幕进行相关事件的编程

从屏幕生成的Basic List的SY-DYNNR还是为当前屏幕的屏幕号,不过所有的Detail List的屏幕号都为 120

请参考这里

REPORT demo_leave_to_list_processing.

列表屏幕(List Screen)

列表屏幕(List Screen)
,就会结束整个程序,因为当前100屏幕的
  ,所以如果不重新指定下一屏幕,则会结束屏幕
  的意思是:当前屏幕(100)的下一屏幕还是100
  屏幕的PBO事件

屏幕并触发其PBO事件
.
  SET PF-STATUS space.
  SUPPRESS DIALOG.
  SELECT  carrid connid cityfrom cityto
    FROM  spfli
    INTO  CORRESPONDING FIELDS OF wa_spfli
    WHERE carrid = demo_conn-carrid.
    WRITE: / wa_spfli-carrid, wa_spfli-connid,
             wa_spfli-cityfrom, wa_spfli-cityto.
    HIDE: wa_spfli-carrid, wa_spfli-connid.
  ENDSELECT.
  CLEAR: wa_spfli-carrid.
ENDMODULE.                    "call_list_500 OUTPUT

TOP-OF-PAGE.
  WRITE text-001 COLOR COL_HEADING.
  ULINE.

TOP-OF-PAGE DURING LINE-SELECTION.
  WRITE sy-lisel COLOR COL_HEADING.
  ULINE.

AT LINE-SELECTION.
  CHECK NOT wa_spfli-carrid IS INITIAL.
  SELECT  fldate
    FROM  sflight
    INTO  flightdate
    WHERE carrid = wa_spfli-carrid AND
          connid = wa_spfli-connid.
    WRITE / flightdate.
  ENDSELECT.
  CLEAR: wa_spfli-carrid.

从List Processing 中调用SCREEN

从list processing处理过程中调用Screen:

CALL SCREEN <nnnn>.

该语句会将生成一个screen sequence,并将它穿插到list processing处理过程中,list processor会将控制权交给dialog processor,并且直到dialog processor处理screen sequence中的Screen 0才会结束dialog processor,并再次将控制权从dialog processor转交到list processing,继续执行CALL SCREEN后面的语句

示例请参考:demo_call_screen_from_list

LIST 打印输出

在默认情况下,系统会将list(basic list and secondary lists)输出到screen。该章节将讨论将lists发送到SAP spool system来代替output screen。

一般来讲,我们将list发送到SAP spool system叫 'printing lists'(打印列表),也就是说,不需要真正的将list输出到打印机上,而是使用spool system临时存储。

ABAP提供了两种打印list方式:标准打印与编程控制打印输出。

在使用系统提供的标准打印时,有时不能立即输出打印内容,可以像下面这样来设置立即打印与默认打印设备:

列表屏幕(List Screen)

使用系统提供的标准打印

使用标准打印会出现以下几个问题:

?    如果list屏幕输出中,某逻辑页行数超过了实际打印输出的页大小时,会将这一逻辑页分成多(具体多个与打印输出设备有关)个物理页面,系统会将每个物理页面的pageheader设置成该逻辑页的pageheader,这时如果page header含有页号(SY-PAGNO)是时,就会有问题:页号不会自动更新

REPORT XXX NO STANDARD PAGE HEADING LINE-SIZE 60 .
TOP-OF-PAGE.
  WRITE: sy-title, 20 'SY-LINSZ:', sy-linsz, 40 'Page', sy-pagno.
  ULINE.
START-OF-SELECTION.
  DO 64 TIMES.
    WRITE / sy-index.
  ENDDO.

列表屏幕(List Screen)

?    如果REPORT或者NEW-PAGE语句中使用了LINE-COUNT,且指定的页面大小超过了实际输出设置的页面大小时,超出的部分不会打印出来(这与未设置LINE-COUNT时超出部分会打印到下一个物理页面是不一样的):

) .
TOP-OF-PAGE.
  WRITE: sy-title, 20 'SY-LINSZ:', sy-linsz, 40 'Page', sy-pagno.
  ULINE.
END-OF-PAGE.
  ULINE.
  WRITE: /30 'Page', sy-pagno.
START-OF-SELECTION.
  DO 163 TIMES.
    WRITE / sy-index.
  ENDDO.

打印时,会弹出警告框:

列表屏幕(List Screen)

列表屏幕(List Screen)

?    如果REPORT语句中设置的行LINE-SIZE大于打印设备的最大行宽时,超出的部分是不会打印出来的

?    使用标准的打印时,不能写printcontrol语句来控制打印输出

通过编程来控制打印输出

在程序中向打印输出设置输出时,系统会根据打印输出设备来格式化List,系统会根据打印输出设备的格式来确定页宽与页长,物理页满后会自动换页。

在选择屏幕上点击“执行与打印”

SET_PRINT_PARAMETERS函数的各输入参数与弹出的打印输出设置对话框中的参数相对应,打印输出设置对话框中的参数都可以在该函数中进行设置:

列表屏幕(List Screen)

).
PARAMETERS p TYPE i.
INITIALIZATION.

通过程序对弹出的打印对话框中的默认值进行设置,在打印时,弹出的打印参数对话框中的参数默认值就是该函数所设置的值。注:该函数与GET_PRINT_PARAMETERS不一样,SET_PRINT_PARAMETERS本身不会弹出打印参数设置对话框,它只是起到设置默认打印参数的一个作用,而通过GET_PRINT_PARAMETERS除可以设置某些打印参数,而且会自动弹出打印参数设置对话框(不过也可以设置不弹出):

line_size      
      list_name       = 'Test'
      list_text      = 'Test for User''s Guide'
      new_list_id    = 'X'
      receiver       = 'CNZHJIA6'
      release        = ' '
      sap_cover_page = ' '.不打印SAP提供的封面页
START-OF-SELECTION.
  DO p TIMES.
    WRITE / sy-index.
  ENDDO.
TOP-OF-PAGE.
  WRITE: 'Page', sy-pagno.
  ULINE.
END-OF-PAGE.
  ULINE.
  WRITE: 'End of', sy-pagno.

注:SET_PRINT_PARAMETERS函数只是对弹出的打印参数设置对话框中的默认值有影响,输出的内容是否能得到正确的格式化,还是看你运行程序时,点击的是“执行”按钮还是“执行与打印”按钮(或者在程序中使用NEW-PAGE PRINT ON语句来强制输入到Spool System过程进行格式化,在选择屏幕上点击“执行”时,普通的Write语句会直接输了到List屏幕中,而不管里前面是否调用SET_PRINT_PARAMETERS函数):

1、 点击选择屏幕上工具条中的“执行与打印”按钮,输出的PDF与SAP spool System中的List内容的格式都是已按照程序中设置的打印参数格式化了

列表屏幕(List Screen)

2、 如果还是先点击“执行”,然后在输出List屏幕上点击“打印”,虽然此时弹出的打印参数设置对话框中的默认值为程序中SET_PRINT_PARAMETERS函数所设置的值,但此时打印出来的格式是未格式化的内容,这与点击上面执行与打印按钮输出是不一样的,因为此时的输出是直接Write到了屏幕上,然不是输出到了SAP spool System中:

列表屏幕(List Screen)

从程序中启动打印

如果想在创建List时启动打印处理,使用带PRINT ON选项的NEW-PAGE语句:

NEW-PAGE PRINT ON[NEW-SECTION] [PARAMETERS<pripar>]

[ARCHIVEPARAMETERS<arcpar>]

[NODIALOG].

该语句后的所有输出不再直接输出到屏幕上,而是输出到spool system中

在已经有过向spool system输出List后,如果不使用NEW-SECTION选项,则NEW-PAGE PRINT ON语句将失效。如果使用了NEW-SECTION选项,将会重置SY-PAGNO系统字段为1。如果系统已经向spool系统中输出过List,则NEW-SECTION选项有如下作用:

?    如果当前List指定的了打印参数(PARAMETERS )中的PRNEW为SPACE,系统不会创建新的spool request

?    如果当前List没有指定打印参数(PARAMETERS )中PRNEW打印参数,或者指定了但不为SPACE时,系统会关掉当前spool reques并重新创建新的spool request

事件结束时会自动的结束打印处理。如果要明确的结束当前List输出到spool system中,则使用以下语句:

NEW-PAGE PRINT OFF.

该语句的作用是结束向spool system中输出,此语句后的输出会直接显示输出到屏幕上显示

invalid_print_params  
    invalid_archive_params
    个参数会重新修改 pripar 中相应的参数
      layout                 = lay
      line_count             = lines
      line_size              = rows

no_dialog             
      invalid_print_params  
      invalid_archive_params
      ) sy-index.
  ENDDO.
ENDFORM.

SUBMIT 程序时打印List

如果将通过SUBMIT语句被调用的reports的输出发送到spool system中,可以使用TO SAP-SPOOL选项:

SUBMIT<rep>TO SAP-SPOOL

[SPOOLPARAMETERS<pripar>]

[ARCHIVEPARAMETERS<arcpar>]

[WITHOUTSPOOLDYNPRO].

如果使用TO SAP-SPOOL选项,List在创建时会使用格式化打印,然后将格式化后的List输出到spool system。SPOOLPARAMETERS与ARCHIVEPARAMETERS参数与NEW-PAGE PRINT ON语句是一样的。如果不想弹出打印参数设置对话框列表屏幕(List Screen)

与Spool对话框:

列表屏幕(List Screen)

,可以使用WITHOUT SPOOL DYNPRO选项进行压制。如果使用了WITHOUT SPOOL DYNPRO选项,则不会显示Spool对话框,此时如果想看Spool system中的格式化List,可以选择菜单:

System → Own Spool Requests

line_size              
 
    invalid_print_params  
    invalid_archive_params
    .
  SUBMIT YJZJ_TEST2 TO SAP-SPOOL
    SPOOL PARAMETERS pripar
    ARCHIVE PARAMETERS arcpar
    WITHOUT SPOOL DYNPRO.
ENDIF.

REPORT  yjzj_test2.
START-OF-SELECTION.
DO 100 TIMES.
  WRITE: sy-index.
ENDDO.

Print Control

SET MARGIN 与 PRINT-CONTROL语句仅对输出到spool系统中的List起作用,对直接显示在屏幕上的List ,并使用List → Print打印是无效的

限定左边距与上边距

SETMARGIN<x>[<y>].

该语句指定了左边与上边的空白,以列(X)和行(Y)为单位。并将X与Y分别存储到SY-MACOL与SY-MAROW系统变量中,在打印输出时,系统会使用这两个系统变量来决定页面的左边距与上边距。该语句对所有后续页面都起作用,除非一下个这样的语句重新设定。

.
SET MARGIN 10 6.
PARAMETERS: c.
START-OF-SELECTION.
  DO 100 TIMES.
    WRITE: sy-index.
  ENDDO.

列表屏幕(List Screen)

PRINT-CONTROL

PRINT-CONTROL { { formats|{FUNCTION code}
[LINE line] [POSITION col] }
| { INDEX-LINE index_line } }.

该语句只对通过NEW-PAGE PRINT ON, SUBMIT TO SAP-SPOOL或者是选择屏幕上的“Execute and Print”按钮创建的print lists起作用,对“Print”打印screen list(已显示在屏幕上的列表)是不起作用。

... formats|{FUNCTION code} [LINE line] [POSITION col]

该选项对从当前Page的line行col列所有后续输出内容的print format进行设置,如果没有设置line与col,则从当前位置(sy-linno, sy-colno)开始格式化,line会存储到sy-linno中,col会存储到sy-colno。

Formats参数选项可以是下表中的列表的选项,在运行时系统会将这些选项转换printer-independent (与打印机无关)的相应code,当List在实际打印时,这些code又会翻译成printer-specific(与打印相关)的control characters:

<formats>

Code

Meaning

CPI<cpi>

CI<cpi>

Charactersper inch

LPI<lpi>

LI<lpi>

Linesper inch

COLORBLACK

CO001

Colorblack

COLORRED

CO002

Colorred

COLORBLUE

CO003

Colorblue

COLORGREEN

CO004

Colorgreen

COLORYELLOW

CO005

Color yellow

COLORPINK

CO006

Colorpink

LEFTMARGIN<lfm>

LM<lfm>

Spacefrom theleftmargin

FONT<fnt>

FO<fnt>

Font

SIZE siz

SIsiz

font size

FUNCTION<code>

<code>

Fordirectlyspecifyinga code

<formats>可以这样使用:PRINT-CONTROL COLOR GREEN.,但好像没起作用?

Code可以使用FUNCTION方式来调用:PRINT-CONTROL FUNCTION t022d-prctl.

[LINE line] [POSITION col]选项表示设置的格式从哪行哪列起作用

 

将Code转换成device-specific(打印设备相关)的control characters是根据TSP03 与 T022D两个表来确定的,某个设备类型有效的print control codes可以通过事务码SPAD来查看:

列表屏幕(List Screen)

REPORT sapmztst.
PARAMETERS: c.
TABLES: t022d.
SELECT * FROM t022d WHERE typ = 'CNSAPWIN'.设备类型,与事务码SPAD中设置相同
  PRINT-CONTROL FUNCTION t022d-prctl.
  WRITE :/ t022d-prctl.
ENDSELECT.

点击选择屏幕上的“Execute and Print”按钮,运行结果如下:

列表屏幕(List Screen)

输出设备与设备类型:

列表屏幕(List Screen)

TSP03中存储了输出设备:

列表屏幕(List Screen)

T022D中存储了每种设备类型所对应的打印指令(输出设备属于某种设备类型):

列表屏幕(List Screen)

将文本文件转换成PDF

invalid_print_params          
     invalid_archive_params        
    
           
     err_no_spooljob               
     err_no_permission             
     err_conv_not_possible         
     err_bad_destdevice            
     user_cancelled                
     err_spoolerror                
     err_temseerror                
     err_btcjob_open_failed        
     err_btcjob_submit_failed      
     err_btcjob_close_failed       
    
           
     file_read_error              
     no_batch                     
     gui_refuse_filetransfer      
     invalid_type                 
     no_authority                 
     unknown_error                
     bad_data_format              
     header_not_allowed           
     separator_not_allowed        
     header_too_long              
     unknown_dp_error             
     access_denied                
     dp_out_of_memory             
     disk_full                    
     dp_timeout                   
    
            .
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

WRITE 'SAVED SUCCESSFULLY!'.
ENDFORM.                    " F_SAVE_FILE

输出到PDF打印

现在大家都在提倡节约能源,珍惜不可再生资源,减少大气二氧化碳排放量。IT界也提出了绿色IT的口号,要使现绿色IT就从减少打印做起吧。企业在应用SAP ERP时,可能需要大量打印通信文档如催款单,对账单,付款通知等。通过生成PDF格式的通信文件然后用电子邮件的方式发给客户或供应商,不仅大在降低打印成本和邮递费用,加快了与业务合作伙伴的信息沟通,而且还能可达到环保的目的,可谓一举三得。在SAP ERP中安装PDF打印机的方法如下:
1、使用T-Code:SPAD启动打印配置管理
2、在 “Configuration” 菜单下,执行"Output Device"
3.按“修改”按钮进入修改模式,用 "Output Device " 菜单上 "Create"
4.输入Output Device 的命字,例如LP02;设置Device Type 为“CNSAPWIN : MS Windows driver via SAPLPD” ,并将Device Class设置为 "Standard".
列表屏幕(List Screen)
5. 在 "Access Method" Tab的参数中设置如下:F 前端打印表示在打印时可以手动选择本地计算机上安装的打印机。
列表屏幕(List Screen)
6. 需要打印时,系统会提示选择客户端安装的PDF生成器,用户可选择立即打印;也可选择提交到打印池中,稍后用T-Code: SP02手工执行批量打印。
列表屏幕(List Screen)

以下是我们公司的使用本地设备进行打印的配置如下:

列表屏幕(List Screen)

这是相应后台打印设备配置:

列表屏幕(List Screen)

注:当使用函数CONVERT_OTF、或SX_OBJECT_CONVERT_OTF_PDF等函数转换PDF时,使用的是服务器上的PDF插件,不是使用的本地安装的软件,上面这种本地打印是使用的是本机的打印设备或软件,需要安装相应软件才有。

PDF生成器向大推荐PDF XChnageF 3.0,可以设置批量生成文件到指定文件夹,单张纸面上打印多页内容等,比Adobe Acrobat带的PDF生成器更强大。
列表屏幕(List Screen)