SAP HELP对ALV的定义如下:The ALV grid control is a flexible tool for displaying lists. The tool provides common list operations as generic functions and can be enhanced by self-defined options。
ALV Grid控件用来创建非层次的友好的交互式报表。作为一个控件,他被安装在本地机的客户端上。
ALV Grid控件提供了典型的常用功能,比如排序,筛选和总计等。同时他也提供了自开发功能的接口。它提供了大量与excel和水晶报表的接口。
类CL_GUI_GRID用来实现ALV GRID控件的各种功能。还可以使用:REUSE_ALV….这些功能模块,来实现ALV报表。
当我们想通过ALV来实现报表时,我们通常需要准备一下几个部分:
1) List data;就是你要显示的内表。除排序功能之外,ALV GRID的控件只是读取所要显示的内表中的内容。然而,排序将会改表内表的状态。所要显示的内表可以包含任何flat type的数据。如果要显示deep type的数据,那可能就要设定ALV GRID的某些特定功能。
2) Field Catalog: 使用另外一个内表来定义ALV报表的每一个字段的显示方式。Field catalog可以通过三种方式来实现:自动生成,半自动和手动生成。这个内表的类型必须是LVC_T_FCAT
3) Layout Structure: 我们可以通过这个结构来设置ALV的显示格式。用这个结构我们可以用来设置ALV的常用选项,对GRID控件的配置,汇总选项已经颜色等。这个结构的类型必须是LVC_S_LAYO
4) Event Handler: 如果我们想在alv grid中触发时间,可以通过事件处理类来实现,必须注册一个事件处理类的实例来处理alv grid的事件。
5) Additional data: 通过alv其他的一些参数可以用来设置alv grid的其它的一些特征。例如设置初始的排序顺序,把某些按钮置为非激活状态等。
下面我们来简单看一下alv的实现步骤,作为一个控件对象必须有一个容器来实现与屏幕的连接。我们用cl_gui_custom_container这个类的实例来实现这个目的。另外还有一些其他类的实例也可能会用到,比如cl_gui_docking_container,cl_gui_dialogbox_container。首先我们要在屏幕上创建custome control区域。
下面简单描述一下ALV GRID的创建过程;
1. 在屏幕上创建custom control区域,比如我们把这个区域的名字定位cc_alv
. 定义alv grid的全局变量
2. *–GLOBAL DATA DEFINITIONS FOR ALV
*— ALV GRID instance reference
DATA: gr_alvgrid TYPE REF TO cl_gui_alv_grid.
*— Name of the custome control added on the screen
DATA: gc_custome_control_name TYPE scrfname VALUE ‘CC_ALV’.
*– Custome container instance reference
DATA: gr_container TYPE REF TO cl_gui_custom_container.
*– Field catalog table
DATA gt_fieldcat TYPE lvc_t_fcat.
*– Layout structure
DATA gs_layout TYPE lvc_s_layo.声明用来创建容纳显示内容的内表
3. 根据自己的具体需求把取出来的数据放到内表中
4. 建立PBO MODULE用来创建ALV GRID的实例
PROCESS BEFORE OUTPUT.
* MODULE STATUS_0100.
MODULE display_alv.
MODULE display_alv OUTPUT.
PERFORM display_alv.
ENDMODULE.
5. 下面是显示alv的主要步骤,先检查一下alv容器的实例是否存在,如果存在的话就把刷新,否则的话就创建它,并调用显示alv的方法。
FORM display_alv.
IF gr_alvgrid IS INITIAL.
CREATE OBJECT GR_CONTAINER
EXPORTING
CONTAINER_NAME = gc_custome_control_name
EXCEPTIONS
CNTL_ERROR = 1
CNTL_SYSTEM_ERROR = 2
CREATE_ERROR = 3
LIFETIME_ERROR = 4
LIFETIME_DYNPRO_DYNPRO_LINK = 5
others = 6.
IF SY-SUBRC <> 0.
ENDIF.
CREATE OBJECT GR_ALVGRID
EXPORTING
I_PARENT = GR_CONTAINER
EXCEPTIONS
ERROR_CNTL_CREATE = 1
ERROR_CNTL_INIT = 2
ERROR_CNTL_LINK = 3
ERROR_DP_CREATE = 4
others = 5.
IF SY-SUBRC <> 0.
ENDIF.
*– preparing field catalog
* PERFORM prepare_fieldcatalog CHANGING gt_fieldcat.
*– preparing layout structure
* PERFORM prepare_layout CHANGING gs_layout.
*– display alv list
CALL METHOD GR_ALVGRID->SET_TABLE_FOR_FIRST_DISPLAY
EXPORTING
* I_BUFFER_ACTIVE =
* I_BYPASSING_BUFFER =
* I_CONSISTENCY_CHECK =
* I_STRUCTURE_NAME =
* IS_VARIANT =
* I_SAVE =
* I_DEFAULT = ‘X’
IS_LAYOUT = gs_layout
* IS_PRINT =
* IT_SPECIAL_GROUPS =
* IT_TOOLBAR_EXCLUDING =
* IT_HYPERLINK =
* IT_ALV_GRAPHICS =
* IT_EXCEPT_QINFO =
CHANGING
IT_OUTTAB = gt_list
IT_FIELDCATALOG = gt_fieldcat
* IT_SORT =
* IT_FILTER =
EXCEPTIONS
INVALID_PARAMETER_COMBINATION = 1
PROGRAM_ERROR = 2
TOO_MANY_LINES = 3
others = 4.
IF SY-SUBRC <> 0.
ENDIF.
ELSE.
CALL METHOD GR_ALVGRID->REFRESH_TABLE_DISPLAY
* EXPORTING
* IS_STABLE =
* I_SOFT_REFRESH =
EXCEPTIONS
FINISHED = 1
others = 2.
IF SY-SUBRC <> 0.
ENDIF.
ENDIF.
通过CREATE OBJECT来实例化类,在上面的一小段代码中使用了cl_gui_alv_grid的两个实例方法。第一个便是‘set_table_for_first_display’,他的名字也就说明了他的用途。创建了alv grid的实例后我们使用这个实例来显示ABAP报表。通过这个方法来传入list data table, field catalog, layout structure以及其他一些信息。下面是帮助文档中这些参数的含义:
Parameter Meaning
I_BUFFER_ACTIVE 如果方法的调用是静态的,这个参数被设置。这意味着这个方法总是用同样的field catalog来调用。这种情况下,field catalog被保存到特殊的缓存区域中。这边加速了列表的显示。
I_STRUCTURE_NAME 要显示的数据表的数据字典结构,如果给了这个参数field catalog会被自动产生。
IS_VARIANT 决定了数据表格的显示格式。如果用这个参数的话必须这是结构类型DISVARIANT的REPORT字段。
I_SAVE 决定了用户是否可以保存显示样式:
‘X’: global saving only
‘U’ user-specific saving only
‘A’ corresponds to ‘X’ and ‘U’
SAPCE:no saving
I_DEFAULT 决定了用户是否可以设置缺省的显示样式:
‘X’ default layouts allowed
SPACE default layouts not allowed
如果显示样式已存在并且在IS_LAYOUT中没有其他的显示样式,在调用这个方法时这个样式将被自动调用
IS_LAYOUT 用来决定grid control的属性。它与过滤,排序和字段的属性无关。
IS_PRINT 与打印相关的参数
IT_SPECIA_GOUPS 在FIELD CATALOG中如果字段被SP_GROUP分组,你必须为这些组传输一个文本表。通过这个参数你就可以限制这些组中的某一组的列
IT_TOOLBAR_EXCLUDING 这个表用来包含想在工具条中隐藏某些功能的功能代码。这些功能代码都是一些常量属性,都以MC_FC_开头。
IT_HYPERLINK 这个表为每个操作柄(field HANDLE OF LVC_S_HYPE)提供了一个超级链接(field HREF OF LVC_S_HYPE)
IT_ALV_GRAPHICS 用来在ALV中显示图片,这个表的行类型有两个字段(variables/value pairs): PROP_ID:把以CO_PROP_ID_开头的类CL_ALV_GRAPHICS_CU的常量属性付给这个字段来决定对图像所做的个改变。用CL_GUI_ALV_GRAPHICS_CU=>CO_PROPID_TITLE来决定图片的标题。
IT_OUTTAB 要显示的数据的表
IT_FIELDCATALOG 决定了要显示表的结构和数据的显示方式
IT_SORT 各个列的初始的排序方式
IT_FILTER 一些列的初始的筛选方式
这段代码中还使用了grid实例的另外一个方法; refresh_table_display , 正如他的名字,它是用来刷新alv表的显示,我们并不希望每次的PBO事件中都创建ALV列表。开始的时候我们需要创建它而这之后我们只需刷新它就可以了。然而,有些时候我们需要改变列表的显示方式,比如layout ,field catalog等,这种情况下我们可能需要ALV GRID的其他方法来实现这一目的,这个方法有下面两个参数:
Parameter meaning
IS_STABLE 用来固定某行或某列的位置,在使用滚动条时,保证这些位置不变。
I_SOFT_REFRESH 这个参数用来保证等你刷新列表示,以前产生的总计,排序和筛选等保持不变。如果你只是想刷新列表的显示格式时,比如layout ,fieldcatalog 等时,这个参数非常有用。
建立FIELD CATALOG
正如前面所提到的建立field catalog需要三个步骤。如果我们的表与数据字典中的表的结构一样的话,我们就可以用最简单的方式实现。我们就可以省去form: prepare_catalog只把数据字典中的结构名字传给参数I_STRUCTURE_NAME就可以了。首先我们来看一下field
Catalog的结构。
FIELD CATALOG的结构
FIELD CATALOG的行类型是LVC_S_FCAT,这里提供了很多字段来确定列表字段的显示方式。下表列出了一些基础的字段:
FIELDNAME 这个字段的名字便是要显示的内表中的一个字段,下面的一些设置都是针对的这个字段。
REF_FIELD 如果要显示的内表中的字段在数据字典中有某个字段可以描述,但是数据字典中的字段的名字和内表中的字段的名字不一致,那么这个字段必须设置。如果一致的话那只要制定数据字典的结构或REF_TABLE就可以了
REF_TABLE 如果要显示的内表中的字段需要用数据字典中的字段加以描述,那么必须设置这个参数。
CHECKBOX 该字段显示为checkbox
COL_POS 如果想使alv中显示列的顺序与field catalog中字段的顺序不一致,那么就可以使用这个参数。如果这个参数为空的话,alv显示的顺序便于field catalog中字段的顺序一致。
DO_SUM 如果这个值被选中的话,那么这个字段会被进行汇总计算。
EMPHASIZE 如果这字段被设置成‘X’,alv就会用高亮的方式用预定义的颜色显示这个字段。如果被设置成’Cxyz‘下面列出了他们的含义:
X;color number
Y: intensified on/off
Z: inverse display on/off
HOTSPOT 如果这个字段被设置,那么这个字段的框都会有热点感应
ICON 如果这个字段被设置那么这个字段将被设置为图标,要显示的内表中的字段的值必须是正确的图标字符串。
JUST 只对NUMC和CHAR类型的字段有效,它有三个值:即R,L,C,字段的头信息和字段的内容的对齐方式是一致的。
LZERO 只对NUMC类型的字段有关。缺省的情况下ALV不显示签到零。如果你设置了这个字段,他就会显示前导零。
COLDDICTXT 只对参考数据字典的字段有效。通过值’L’,’M’,’S’或者’R’来决定要显示什么样的列头。
COLTEXT 列头的内容,如果你没有指定参考数据字典,那么需要设置这个值。
REPTEXT 只对参考数据字典的字段有效。对于这些字段ALV会把相应的数据元素的描述信息拷贝过来。
SCRTEXT_L 只对参考数据字典的字段有效。设置这个字段,alv会把数据元素的长文本拷贝过来
SCRTEXT_M 只对参考数据字典的字段有效。设置这个字段,alv会把数据元素的较长文本拷贝过来
SCRTEXT_S 只对参考数据字典的字段有效。设置这个字段,alv会把数据元素的较短文本拷贝过来
SELDDICTXT 只对参考数据字典的字段有效。选择字段文本通过使用值L,M,S,OR R使用SCRTEXT_L,SCRTEXT_M,SCRTEXT_S或REPTEXT
SELTEXT 如果这个字段没有参考数据字典的话,在选择字段的时候来决定选择字段的文本。
TIPDDICTXT 只对参考数据字典的字段有效。TIP文本通过使用值L,M,S,OR R使用SCRTEXT_L,SCRTEXT_M,SCRTEXT_S或REPTEXT
TOOLTIP 决定TOOLTIP的文本,如果该字段没有参考数据字典的话。
INITYPE ABAP数据类型
SP_GROUP 使用它可以用来给显示的字段分组。
建立field catalog下面的步骤便是如何填充FIELD CATALOG内表。上面介绍了field catalog的行类型的各个字段。为了正确的填充每一列的field catalog 的字段,下面的这几个字段必须被填充。
Output table fields with DDIC reference Output table fields without DDIC reference Explanation
FIELDNAME FIELDNAME 要显示内表的字段
REF_TABLE 参考的数据字典结构
REF_FIELD 要参考的数据字典字段
INITYPE 要显示的内表的字段的ABAP数据类型
OUTPUTLEN 列的宽度
COLTEXT 列头文本
SELTEXT 选择列的描述信息
FORM prepare_field_catalog CHANGING pt_fieldcat TYPE lvc_t_fcat.
DATA: ls_fcat TYPE lvc_s_fcat.
Ls_fcat-fieldname = ‘CARRID’.
Ls_fcat-inttype = ‘C’.
Ls_fcat-outputlen = ‘3’.
Ls_fcat-coltext = ‘CARRIER ID’.
Ls_fcat-seltext = ‘CARRIER ID’.
APPEND ls_fcat TO pt_fieldcat.
DATA: ls_fcat TYPE lvc_s_fcat.
Ls_fcat-fieldname = ‘CONNID’.
Ls_fcat-ref_table =’SFLIGHT’.
Ls_fcat-ref_col = ‘CONNID’.
APPEND ls_fcat TO pt_fieldcat.
ENDFORM.
半自动的产生field catalog
把我们要显示的字段都一行一行的插入到field catalog内表中确实是一件烦人的事情。并且如果想自动产生field catalog的话那也不是十分理想。幸运的是有一种方法可以半自动的产生field catalog。
这种方法需要调用一个功能模块。我们传入一个结构模版,他就会自动为我们产生field catalog内表。可以遍历这张内表,改变我们想要改变的东西。这个功能模块的名字是’LVC_FIELDCATALOG_MERGE’。下面的代码展示了这种方法的使用。
FORM frm_field_catalog CHANGING pt_fieldcat TYPE lvc_t_fcat.
DATA ls_fcat TYPE lvc_s_fcat.
CALL FUNCTION ‘LVC_FIELDCATLOG_MERGE’
EXPORTING
I_structure_name = ‘SFLIGHT’
CHANGING
Ct_fieldcat = pt_fieldcat
EXCEPTIONS
Inconsistent_interface = 1
Program_error = 2
Oters = 3.
IF sy-subrc <> 0.
ENDIF.
LOOP AT pt_fieldcat INTO ls_fcat.
CASE ls_fcat-fieldname.
WHEN ‘CARRID’.
Ls_fcat-outputlen = ‘10’.
Ls_fcat-coltext = ‘Airline carrid’.
MODIFY pt_fieldcat FROM ls_fcat.
WHEN ‘PAYMENTSUM’.
Ls_fcat-no_out = ‘X’.
MODIFY pt_fieldcat FROM ls_fcat.
ENDCASE.
ENDLOOP.
ENDFORM.
这个例子中首先使用结构SFLIGHT建立了fieldcatlog内表。然后我们又改变了CARRID的输出长度和字段文本。然后我们又改变字段paymentsum为不输出。
紧接着带来的问题是假如我们把i_structure_name和i_fieldcatlog这两个字段都传进去了将会发生什么。显然这是个优先级的问题。I_structure_name的优先级要高。