前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ABAP ALV之自建表可编辑内表的增删改查

ABAP ALV之自建表可编辑内表的增删改查

作者头像
百里丶落云
发布2022-12-20 14:00:21
1.6K0
发布2022-12-20 14:00:21
举报
文章被收录于专栏:享~方法享~方法

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情

HELLO,这里是百里,一个学习中的ABAPER,在工作中,我们会遇到一些自建表进行维护数据,这些自建表需要给用户进行配置操作,如权限,关联性,基础数据等等,标准SAP中没有,但是有十分重要的字段. 我们可以通过SAP的SE11创建完表以后,通过表格维护生成器,在SM30里面,或者SE16N进行维护.我们也可以封装SM30进行操作.

为什么要用ALV的方式自开发增删改查

使用封装自建表的SM30时,会遇到锁屏的情况,就是一个人操作,另外一个人不能操作.会很难受,虽然可以减少部分的代码操作量.但是当公司很多时,会出现相互卡的情况,这就很难受.此时就出现了我们的需求.通过传统的增删改查直接操作内表.避免上述说出出现的相互制约的情况 .

技术解析

有的小伙伴私信我,说我只是单独把某个知识点拉出来,讲虽然能看懂,但是不知道怎么才能灵活组合应用,那么这个需求来了.讲内表,标准表,数据触发,指针等多项内容均放在一起的案例. 不过可能代码会比较多,但是只要学会了这个,真就ALV你肯定会了. 没有什么特别复杂的技术,就会单纯的通过edit进行逻辑操作. 但是其中会遇到一些问题,比如说慎用modify . 比如获取选择框.是多项技能的组合应用.

获取选择框

代码语言:javascript
复制
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'  
  IMPORTING  
    e_grid = gv_grid.

ALV CHANGED DATA

光标移动失焦触发.

代码语言:javascript
复制
LOOP AT pcl_data->mt_mod_cells INTO ls_cells.  
    READ TABLE gt_data  INTO  gs_data INDEX ls_cells-row_id.  
  
   ..........

  ENDLOOP.

屏幕刷新函数

代码语言:javascript
复制
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'  
    IMPORTING  
      e_grid = lo_grid.  
  
  lw_stable-row = 'X'.  
  lw_stable-col = 'X'.  
  lo_grid->refresh_table_display(  
    EXPORTING  
      is_stable = lw_stable  
    EXCEPTIONS  
      finished  = 1  
      OTHERS    = 2 ).

本质上是技术上的活灵活用.将多种基础内容合并在一起,这样才算是业务结合学习内容实际. 算是真实开发.

实际案例

今天的这个案例讲的是一个自建立表,我们要给他实现增加,删除,修改,查询的功能.同时,增加权限检查. 本案例会从如何自建立表及表格函数生成器到最后权限检查都讲解一遍,并加入多种基础并经常使用的技巧.如果是新手会很友好.

建表开始

我们通过SE11进行自建立表的创建.注意的是,自建立表一定要以Z或者Y开头,一般都是附加模块及号码 表示自建表顺序 .

image.png
image.png

数据准备

我们基础表建立完成后,就开始在SE38中开发程序.

代码语言:javascript
复制
"数据准备  
  
types : BEGIN OF ty_DAta  ,  
  
    zhh    TYPE i,  
  
EKORG TYPE ZSDT0015-EKORG ,  
MATNR TYPE ZSDT0015-MATNR ,  
VKORG TYPE   ZSDT0015-VKORG ,  
ZLSMATNR TYPE ZSDT0015-ZLSMATNR ,  
ERNAM TYPE  ZSDT0015-ERNAM ,  
ERDAT TYPE   ZSDT0015-ERDAT ,  
ERZET TYPE   ZSDT0015-ERZET ,  
  
  
  END OF ty_DAta .  
  
  
data  :  gs_data TYPE ty_DAta .  
data  :  gt_data TYPE TABLE of  ty_DAta .  
  
  
 DATA : lv_num TYPE I VALUE IS INITIAL.  
  
data  : flag TYPE   c.  
  
 data : ls_zsdt0015 TYPE ZSDT0015 .  
DATA : ls_data TYPE ty_data.  
  DATA : lt_rows  TYPE lvc_t_row.  
  
DATA : GT_LSDATA  TYPE TABLE OF ty_DAta .  
" ALV 常量 .  
  
*--------------------------------------------------------------------*  
*  ALV变量  
*--------------------------------------------------------------------*  
DATA: wa_layout   TYPE lvc_s_layo.  
DATA:wa_fieldcat TYPE lvc_s_fcat,  
     gt_fieldcat TYPE lvc_t_fcat.  
  
DATA gs_grid TYPE lvc_s_glay.   "新  
DATA:  gv_grid TYPE REF TO cl_gui_alv_grid.  
  
DATA:gs_glay TYPE  lvc_s_glay.  
DATA : gv_error TYPE c.  
DATA : bs1 TYPE c.

选择屏幕

代码语言:javascript
复制
TABLES : EKKO ,EKPO,VBAK .

SELECTION-SCREEN BEGIN OF BLOCK block  WITH FRAME TITLE text-001 .

"select-OPTIONS s_EKORG for EKKO-EKORG .
PARAMETERS p_EKORG TYPE EKORG  OBLIGATORY .
select-OPTIONS s_MATNR for EKPO-MATNR  .
"select-OPTIONS s_VKORG for VBAK-VKORG .
PARAMETERS p_VKORG TYPE  VKORG  OBLIGATORY .

SELECTION-SCREEN END OF BLOCK block .

子例程建立

代码语言:javascript
复制
*&---------------------------------------------------------------------*
*& 包含               ZSDR026AF
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form get_Data
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM get_Data .

SELECT * FROM  ZSDT0015  AS  A INTO CORRESPONDING FIELDS OF TABLE  gt_data where EKORG = p_EKORG  and  VKORG = p_VKORG .

SORT gt_data by  ERZET   ." DESCENDING .


GT_LSDATA  =  Gt_DATA .

ENDFORM.
*&amp;---------------------------------------------------------------------*
*&amp; Form diaplay_data
*&amp;---------------------------------------------------------------------*
*&amp; text
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM display_data .
  PERFORM set_alv_layout.
  PERFORM bulid_fieldcat.
  PERFORM call_alv_func.


ENDFORM.
*&amp;---------------------------------------------------------------------*
*&amp; Form set_alv_layout
*&amp;---------------------------------------------------------------------*
*&amp; text
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM set_alv_layout .
 CLEAR: wa_layout.
  wa_layout-zebra      = 'X'.      "斑马线
  wa_layout-cwidth_opt = 'X'.      "自动列宽
ENDFORM.
*&amp;---------------------------------------------------------------------*
*&amp; Form bulid_fieldcat
*&amp;---------------------------------------------------------------------*
*&amp; text
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM bulid_fieldcat .
 DEFINE add_col.

*    ADD 1 TO pos.
*    lw_fieldcat-col_pos = pos.
    wa_fieldcat-fieldname = &amp;1.
    wa_fieldcat-ref_field = &amp;2.
    wa_fieldcat-ref_table = &amp;3.
    wa_fieldcat-scrtext_l = &amp;4.
    wa_fieldcat-outputlen = &amp;5.
    wa_fieldcat-no_zero = &amp;6.
    wa_fieldcat-edit = &amp;7.
    wa_fieldcat-edit_mask = &amp;8.
    wa_fieldcat-key = &amp;9.


   CASE  wa_fieldcat-fieldname.
          WHEN 'EKORG' or  'MATNR'  or 'VKORG' or  'ZLSMATNR'.
     IF  FLAG is INITIAL .
    wa_fieldcat-edit = 'X' .
 "  wa_fieldcat-checkbox = 'X' .

 " wa_fieldcat-edit_mask = 'X'.
 ELSE .
    wa_fieldcat-edit = 'X' .
     ENDIF.

      WHEN OTHERS.
ENDCASE .

    APPEND wa_fieldcat TO gt_fieldcat.

  CLEAR : wa_fieldcat.
  END-OF-DEFINITION.
  REFRESH: gt_fieldcat.


  add_col 'EKORG'     space space '采购组织'           space space space space space.
  add_col 'MATNR'     'MATNR'  'MARA' '物料号'           space space space space space.
  add_col 'VKORG'     space space '销售组织'           space space space space space.
  add_col 'ZLSMATNR'    'MATNR'  'MARA' 'ZLSMATNR物料号'           space space space space space.
  add_col 'ERNAM'     space space '修改者'           space space space space space.
  add_col 'ERDAT'     space space '修改日期'           space space space space space.
  add_col 'ERZET'     space space '修改时间'           space space space space space.




ENDFORM.


*&amp;---------------------------------------------------------------------*
*&amp; Form call_alv_func
*&amp;---------------------------------------------------------------------*
*&amp; text
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM call_alv_func .
  DATA :gt_event TYPE slis_t_event,
        gs_event TYPE slis_alv_event.



  MOVE 'DATA_CHANGED'     TO gs_event-name.
 MOVE 'ALV_DATA_CHANGED' TO gs_event-form.
 APPEND gs_event TO gt_event.



  gs_glay-edt_cll_cb = abap_true.     " 选中复选款,立刻触发data changed 事件

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = sy-repid           "回调程序
      i_callback_pf_status_set = 'SET_PF_STATUS'
      i_callback_user_command  = 'USER_COMMAND'
      i_grid_settings          = gs_glay
      is_layout_lvc            = wa_layout
      it_fieldcat_lvc          = gt_fieldcat        "需要显示的内表的列
      i_save                   = 'A'
      it_events                = gt_event
    TABLES
      t_outtab                 = gt_data         "需要显示的数据
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.
  IF sy-subrc <> 0.
  ENDIF.

  ENDFORM.



FORM refresh_alv .
  DATA: lo_grid   TYPE REF TO cl_gui_alv_grid,
        lw_stable TYPE lvc_s_stbl.

  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_grid.

  lw_stable-row = 'X'.
  lw_stable-col = 'X'.
  lo_grid->refresh_table_display(
    EXPORTING
      is_stable = lw_stable
    EXCEPTIONS
      finished  = 1
      OTHERS    = 2 ).
ENDFORM.


" 用户子程序

FORM user_command  USING r_ucomm LIKE sy-ucomm
                         rs_selfield TYPE slis_selfield.



  CASE r_ucomm.
    WHEN  '&amp;C1' .


    " 输入料号 对应修改材料名称等信息.
      "  PERFORM frm_process_print .
   WHEN '&amp;INSERT' .
     IF  FLAG IS INITIAL.

       MESSAGE '新增前请先点编辑按钮'  TYPE 'E' .
       ELSE.
        PERFORM  FORM_INSERT.
       PERFORM refresh_alv.
     ENDIF.

   WHEN '&amp;UPDATE' .

      PERFORM FORM_UPDATE .

     PERFORM refresh_alv.
   WHEN  '&amp;DEL' .
  IF FLAG IS INITIAL .
       MESSAGE '删除请先点编辑按钮'  TYPE 'E' .
     ELSE .
    PERFORM  FORM_DEL .
       PERFORM refresh_alv.
  ENDIF.

   WHEN '&amp;DATA_SAVE'.



      PERFORM FORM_SAVE .



  PERFORM refresh_alv.

  ENDCASE.
ENDFORM.
*&amp;---------------------------------------------------------------------*
*&amp; Form FORM_INSERT
*&amp;---------------------------------------------------------------------*
*&amp; text   新增按钮
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM form_insert .

CLEAR ls_data .


  ls_data-zhh = lines( gt_data ) + 1.
      ls_data-EKORG  = p_EKORG.
      ls_data-MATNR  = ''.
      ls_data-VKORG  = p_VKORG.
      ls_data-ZLSMATNR  =  '' .
      ls_data-ERNAM = sy-uname.
      ls_data-ERDAT = sy-datum.
      ls_data-ERZET = sy-uzeit.
      INSERT  ls_data INTO gt_data INDEX lines( gt_data ) + 1.

SORT gt_data  by ERZET DESCENDING   .

ENDFORM.
*&amp;---------------------------------------------------------------------*
*&amp; Form FORM_UPDATE
*&amp;---------------------------------------------------------------------*
*&amp; text  修改按钮 ,如果不点这个按钮只能查询
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM form_update .
" 修改flag
FLAG =  'X' .
PERFORM bulid_fieldcat .

REFRESH gt_data  .
gt_data = GT_LSDATA .
PERFORM refresh_alv .
MESSAGE '可以编辑' TYPE 'S' .


ENDFORM.




"得到选择框

FORM get_grid.
  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
  IMPORTING
    e_grid = gv_grid.
ENDFORM.
*&amp;---------------------------------------------------------------------*
*&amp; Form FORM_DEL
*&amp;---------------------------------------------------------------------*
*&amp; text
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM form_del .



  PERFORM get_grid.
      CALL METHOD gv_grid->get_selected_rows
        IMPORTING
          et_index_rows = lt_rows.

    LOOP AT lt_rows INTO DATA(LS_ROWS).
        CLEAR ls_data .
           READ TABLE gt_data INTO ls_data INDEX ls_rows-index.



          MOVE-CORRESPONDING ls_data to  ls_zsdt0015 .

       DELETE ZSDT0015  FROM ls_zsdt0015 .   " 删除透明表数据
        DELETE gt_data INDEX ls_rows-index.       " 删除内表


    ENDLOOP.
 " 更新当前序号
   LOOP AT gt_data ASSIGNING FIELD-SYMBOL(<lfs_item>).
        lv_num = lv_num + 1.
        <lfs_item>-zhh = lv_num.
      ENDLOOP.


ENDFORM.
*&amp;---------------------------------------------------------------------*
*&amp; Form FORM_SAVE
*&amp;---------------------------------------------------------------------*
*&amp; text
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM form_save .

  IF FLAG =  'X'.
 LOOP AT GT_DATA INTO GS_DATA.


       MOVE-CORRESPONDING gs_data TO ls_zsdt0015.
      MODIFY ZSDT0015 FROM  ls_zsdt0015 .

      CLEAR GS_DATA .
     ENDLOOP.


  MESSAGE '保存成功' TYPE 'I' .
  SORT gt_data .


  ELSE .

  MESSAGE '未点编辑只能看' TYPE 'I' .
  ENDIF.

ENDFORM.


FORM set_pf_status USING rt_extab TYPE slis_t_extab.
  DATA : lw_tab LIKE LINE OF rt_extab.
  REFRESH rt_extab.
  IF gv_error IS INITIAL.

  ELSE.
    " 删除按钮
    lw_tab-fcode = '&amp;PRINT'.
    APPEND lw_tab TO rt_extab.

  ENDIF.
  SET PF-STATUS 'STD' EXCLUDING rt_extab.

  "  SET TITLEBAR 'TIT_1000'.
ENDFORM.



FORM alv_data_changed USING pcl_data TYPE REF TO cl_alv_changed_data_protocol.
  DATA:
  l_name(100),
  ls_cells TYPE lvc_s_modi.
  FIELD-SYMBOLS: <f_field> TYPE any .

  IF FLAG =  'X'.
  LOOP AT pcl_data->mt_mod_cells INTO ls_cells.
    READ TABLE gt_data  INTO  gs_data INDEX ls_cells-row_id.

        gs_data-ERNAM = sy-uname.
      gs_data-ERDAT = sy-datum.
      gs_data-ERZET = sy-uzeit.
        MODIFY gt_data FROM GS_DATA TRANSPORTING  ERNAM  ERDAT ERZET WHERE  zhh = GS_DATA-zhh and EKORG = gs_Data-ekorg and MATNR = gs_Data-matnr and  VKORG = gs_Data-VKORG  and ZLSMATNR = GS_DATA-ZLSMATNR.
            CLEAR gs_Data.






  ENDLOOP.
  ENDIF.

  DATA: ls_stbl TYPE lvc_s_stbl.

  PERFORM refresh_alv  .
ENDFORM.
*&amp;---------------------------------------------------------------------*
*&amp; Form check_auth
*&amp;---------------------------------------------------------------------*
*&amp; text  权限检查
*&amp;---------------------------------------------------------------------*
*&amp; -->  p1        text
*&amp; <--  p2        text
*&amp;---------------------------------------------------------------------*
FORM check_auth .
 SELECT SINGLE ekorg
    FROM T024E
    INTO  @DATA(ls_ekorg)
    WHERE ekorg = @p_ekorg.
AUTHORITY-CHECK OBJECT 'M_EINF_EKO'
           ID 'ACTVT' DUMMY
           ID 'EKORG' FIELD ls_ekorg .
    IF sy-subrc NE 0.

        MESSAGE '没有权限查看采购组织' &amp;&amp;  p_ekorg &amp;&amp; '权限' TYPE 'E'.
      STOP.
    ENDIF.






 SELECT SINGLE vkorg INTO @DATA(lv_vkorg) FROM ztsd001 WHERE zrecon_no = @p_VKORG.
  IF sy-subrc EQ 0 .
    AUTHORITY-CHECK OBJECT 'V_VBAK_VKO'
     ID 'VKORG' FIELD lv_vkorg
     ID 'VTWEG' DUMMY
     ID 'SPART' DUMMY
     ID 'ACTVT' FIELD '03'.
    IF sy-subrc <> 0.
      MESSAGE '你无该销售组织权限,请检查!' TYPE 'S' DISPLAY LIKE 'E'..
      LEAVE LIST-PROCESSING.
    ENDIF.
  ENDIF.




ENDFORM.

程序调用

代码语言:javascript
复制
" 数据准备
INCLUDE ZSDR026AD .


" 选择屏幕
INCLUDE  ZSDR026AS .

" 子程序

INCLUDE ZSDR026AF .




"INITIALIZATION .
INITIALIZATION .


"at SELECTION-SCREEN
at SELECTION-SCREEN .

" 权限检查
  PERFORM check_auth.

"at SELECTION-SCREEN OUTPUT .
at SELECTION-SCREEN OUTPUT .


"START-OF-SELECTION .
START-OF-SELECTION .
  PERFORM get_Data .

"end-of-SELECTION .
end-of-SELECTION .

  PERFORM display_data.

结果

选择屏幕界面

image.png
image.png

ALV输入界面

image.png
image.png

当我们什么都不做的时候,就是对应的查询界面,当我们点新增和删除时会触发管制

image.png
image.png
image.png
image.png

当我们需要点击编辑后才能进行界面编辑

image.png
image.png

当操作后点击上方保存按钮后进行数据保存.

image.png
image.png

当我们未点击编辑按钮时,点击保存会提示,不点编辑只能看字样.

技术总结

今天百里将以往的资料融汇贯通,讲述了一个自建表如何通过ALV的形式,进行增删改查.这种方式虽然开发比封装SM30会慢一些,但是优点就是只需要少量替换代码就可以快速使用,总体技术难度不高.不过对技能知识结构的要求比较多,就是说你得知识点泛一些.

不过是技术就有一些弊端或者bug ,本程序存在着一个可能的问题,就是modify 及DELETE 的使用 毕竟对于使用不熟练的人,这里举例是一个极理想情况即每次修改都修改全部字段,可能会造成大面积修改的问题. 有机会百里会出一期update的使用方法.毕竟modify太危险了,虽然他很快也算方便 .

百里鸡汤

操千曲而后晓声,观千剑而后识器。——《文心雕龙》

这里是百里,一个努力的学习者. 努力学习好好记录,点滴进步,就是成功.

wallhaven-n6peol.jpg
wallhaven-n6peol.jpg
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-12-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要用ALV的方式自开发增删改查
  • 技术解析
    • 获取选择框
      • ALV CHANGED DATA
        • 屏幕刷新函数
        • 实际案例
          • 建表开始
            • 数据准备
              • 选择屏幕
                • 子例程建立
                  • 程序调用
                  • 结果
                  • 技术总结
                  • 百里鸡汤
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档