经过了一个多星期的培训,在这里总结下ABAP入门的知识。由于网上关于SAP ABAP开发相关入门资料太少,关键很多都是跳过讲解的,导致很多人都浅尝辄止,下面我写的入门基础知识大部分人都能看得懂,我都会一一去解释。废话不多说进入正题。(第一次写,后续我会继续完善和更新,有什么好的建议和问题记得留言私信 我都会回复。)
一、 定义变量和赋值

输出结果:


二、 自定义类型
它的作用用于创建内表和结构,后面会讲到相关含义,这个比较重要。

types关键字用于定义类型,而data关键字用于定义变量,相当于实例化。Type后面接着的是类型,lifnr TYPE lfa1-lifnr 它的意思是字段lifnr 类型是数据库表lfa1中lifnr字段的类型一样。
后面进入se11可以看到这张表,或者双击也是可以的。se38是写程序的地方。以上内容是在se38写的。


Standard [0*3]他的意思是0条数据 3个字段
Lt_test2 ls_test 分别是定义是lty_test字段一样的内表和结构。

Lty_lfa1_2类型中包含数据库表lfa1所有字段加上char类型的zflag字段。

Type和like的区别
Type后面接的是类型而like后面接的是变量,记住这个后面经常用到。
三、 内表
内表的定义
先定义一个类型然后我们这样写

内表分为三种,第一种是标准表,第二种是排序表,第三种是哈希表。
四、 选择屏幕
这一款相当于我们以前写的UI前端页面,主要是要自己感受,下面我放两个示例好好感受。
示例1:

TABLES:sflight.  "用到哪张表 声明一下
SELECTION-SCREEN BEGIN OF BLOCK bk1 WITH FRAME TITLE TEXT-001."双击text-001
SELECTION-SCREEN SKIP 2.
PARAMETERS:p_connid TYPE sflight-connid, "范围  searchhelp
           p_carrid TYPE sflight-carrid.
SELECTION-SCREEN END OF BLOCK bk1.


SELECTION-SCREEN BEGIN OF BLOCK bk2 WITH FRAME TITLE TEXT-002.
SELECTION-SCREEN SKIP 1.
SELECT-OPTIONS: s_connid FOR sflight-connid OBLIGATORY,"必须填充内容
                s_plane FOR sflight-planetype NO-EXTENSION,"非必填
                s_curren  FOR sflight-currency NO-DISPLAY,"不显示
                s_price FOR sflight-price NO INTERVALS."没有间隔
SELECTION-SCREEN END OF BLOCK bk2.


SELECTION-SCREEN BEGIN OF BLOCK bk3 WITH FRAME TITLE TEXT-003.
SELECTION-SCREEN SKIP 2.
PARAMETERS:p_ckbox  TYPE char1 AS CHECKBOX,
           p_ckbox1 TYPE char1 AS CHECKBOX DEFAULT 'X',
           p_ckbox2 TYPE char1 AS CHECKBOX,
           p_ckbox3 TYPE char1 AS CHECKBOX.


SELECTION-SCREEN END OF BLOCK bk3.




SELECTION-SCREEN BEGIN OF BLOCK bk4 WITH FRAME TITLE TEXT-004.
SELECTION-SCREEN SKIP 1.
PARAMETERS: p_rb  RADIOBUTTON GROUP rg,
            p_rb1 RADIOBUTTON GROUP rg DEFAULT 'X',
            p_rb2 RADIOBUTTON GROUP rg,
            p_rb3 RADIOBUTTON GROUP rg,
            p_rb4 RADIOBUTTON GROUP rg.

SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS p_ckbox4 TYPE char1 AS CHECKBOX.
SELECTION-SCREEN COMMENT 3(10) TEXT-005.

PARAMETERS p_ckbox5 TYPE char1 AS CHECKBOX.
SELECTION-SCREEN COMMENT 16(10) TEXT-006.

PARAMETERS p_ckbox6 TYPE char1 AS CHECKBOX.
SELECTION-SCREEN COMMENT 29(10) TEXT-007.


SELECTION-SCREEN END OF LINE.

SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS: p_dwload AS CHECKBOX DEFAULT 'x'.
SELECTION-SCREEN COMMENT 5(8) TEXT-008.
PARAMETERS: p_file TYPE string.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK bk4.

示例2:

TABLES:sflight.
SELECTION-SCREEN BEGIN OF BLOCK bk WITH FRAME TITLE TEXT-001.
  PARAMETERS: p_carrid TYPE sflight-carrid OBLIGATORY,
              p_connid TYPE sflight-connid.
  SELECTION-SCREEN SKIP 1.
  SELECT-OPTIONS: s_carrid FOR sflight-carrid,
                  s_connid FOR sflight-connid,
                  s_price FOR sflight-price.
SELECTION-SCREEN END OF BLOCK bk.


SELECTION-SCREEN BEGIN OF BLOCK bk2 WITH FRAME TITLE TEXT-002.
SELECTION-SCREEN SKIP 1.
PARAMETERS:p_ckbox TYPE char1 AS CHECKBOX,
           p_ckbox1 TYPE char1 AS CHECKBOX DEFAULT 'X',
           p_ckbox2 TYPE char1 AS CHECKBOX.
    SELECTION-SCREEN SKIP 1.

PARAMETERS:p_rb RADIOBUTTON GROUP rg ,
           p_rb1 RADIOBUTTON GROUP rg,
           p_rb2 RADIOBUTTON GROUP rg DEFAULT 'X',
           p_rb3 RADIOBUTTON GROUP rg.
SELECTION-SCREEN END OF BLOCK bk2.

SELECTION-SCREEN BEGIN OF LINE.
  PARAMETERS p_chk TYPE char1 AS CHECKBOX.
  SELECTION-SCREEN COMMENT 3(10) TEXT-003.

  PARAMETERS p_chk1 TYPE char1 AS CHECKBOX DEFAULT 'X'.
  SELECTION-SCREEN COMMENT 16(10) TEXT-004.
 SELECTION-SCREEN END OF LINE.

如果有未定义的文本变量需要自己双击然后进行创建和修改。
五、 事件顺序

INITIALIZATION.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR s_curren-low.
  PERFORM frm_value_request_currency.

AT SELECTION-SCREEN OUTPUT."隐藏必须
*  PERFORM frm_modify_screen.

AT SELECTION-SCREEN."权限校验和数据校验

START-OF-SELECTION."取数

END-OF-SELECTION."清空变量

这个自己打好断点去调试 记住每个事件的执行顺序,后期改别人的项目才能知道哪里入手。

插播题外话,也是很关键的写一个报表的框架拿到FS
1.选择屏幕 2.取数 3.循环 4.内表 5.在alv显示
六、 结构和内表
前面虽然说讲了结构和内表了,现在有补充。如何用loop循环读内表和把结构添加到内表中。

TYPES: BEGIN OF ly_str,
      fied(3) TYPE c,
      fied1 TYPE n,
      fied2 TYPE p DECIMALS 2,
  END OF ly_str.
DATA: lt_str TYPE STANDARD TABLE OF ly_str,
      ls_str TYPE ly_str.

CLEAR ls_str.
ls_str-fied = 'as2'.
ls_str-fied1 = '123'.
ls_str-fied2 = '12.36'.
APPEND ls_str to lt_str.

CLEAR ls_str.
ls_str-fied = 's22'.
ls_str-fied1 = '345'.
ls_str-fied2 = '65.33'.
APPEND ls_str to  lt_str.

CLEAR ls_str.
ls_str-fied = 'sd3'.
ls_str-fied1 = '644'.
ls_str-fied2 = '96.88'.
APPEND ls_str to  lt_str.

LOOP AT lt_str into ls_str.
BREAK-POINT.
  ENDLOOP.

读内表是一行行的把数据传给结构的,内表可以存多行数据但是结构是能存一条结构。变量用之前都要清除一下,不然会一直保存着。

示例2

TYPES:BEGIN OF ty_ekko,
        ebeln TYPE ekko-ebeln,
        bukrs TYPE ekko-bukrs,
        absgr TYPE ekko-absgr,
      END OF ty_ekko.

DATA: ls_ekko  TYPE ty_ekko,
      lt_ekko  TYPE STANDARD TABLE OF ty_ekko,
      lt_ekko2 TYPE STANDARD TABLE OF ty_ekko.


CLEAR ls_ekko.
ls_ekko-ebeln = '450000'.
ls_ekko-bukrs = 'F000'.
ls_ekko-absgr = '00'.
APPEND ls_ekko TO lt_ekko.

CLEAR ls_ekko.
ls_ekko-ebeln = '450001'.
ls_ekko-bukrs = 'F001'.
ls_ekko-absgr = '01'.
APPEND ls_ekko TO lt_ekko.

CLEAR ls_ekko.
ls_ekko-ebeln = '450002'.
ls_ekko-bukrs = 'F002'.
ls_ekko-absgr = '02'.
APPEND ls_ekko TO lt_ekko.
CLEAR ls_ekko.
ls_ekko-ebeln = '450003'.
ls_ekko-bukrs = 'F003'.
ls_ekko-absgr = '03'.
APPEND ls_ekko TO lt_ekko.


CLEAR ls_ekko.
ls_ekko-ebeln = '450004'.
ls_ekko-bukrs = 'F004'.
ls_ekko-absgr = '04'.
APPEND ls_ekko TO lt_ekko2.


CLEAR ls_ekko.
ls_ekko-ebeln = '450005'.
ls_ekko-bukrs = 'F005'.
ls_ekko-absgr = '05'.
APPEND ls_ekko TO lt_ekko.



APPEND LINES OF lt_ekko to lt_ekko2.
BREAK-POINT.

意思是把lt_ekko 里面的数据赋值到lt_ekko2中。

示例4

LOOP AT lt_ekko INTO ls_ekko.
  DELETE lt_ekko INDEX SY-TABIX .
  WRITE: / SY-TABIX.
  BREAK-POINT.
ENDLOOP.

输出几个一,以为它都是删除索引值为一的数据,也就是删了第一行,下面的数据向上顶,他们新的索引值是他们以前的索引值减一。

示例5:

CLEAR ls_ekko.
READ TABLE lt_ekko INTO ls_ekko WITH  KEY ebeln = '450001'.
BREAK-POINT.

读取内表数据.
示例6:

SORT lt_ekko BY ebeln ASCENDING.
BREAK-POINT.

READ TABLE lt_ekko TRANSPORTING NO FIELDS WITH KEY ebeln = '450008' BINARY SEARCH.

IF sy-subrc = 0.
  WRITE: '找到相关数据'.
ELSE.
  WRITE: '未找到相关数据'.
ENDIF.
Sy-subrc = 0他的意思是找到相关的数据。

七、 AT END OF
AT END OF他只在loop循环中起作用,他的作用是读取相同字段下最后一行数据,什么意思呢,下面结合示例来讲,它用于数据的统计。用之前一般要进行排序,默认是升序。

TYPES: BEGIN OF ty_mard,
         matnr TYPE  mard-matnr,
         werks TYPE  mard-werks,
         insme TYPE  mard-insme,
       END OF ty_mard.

DATA: ls_mard TYPE ty_mard,
      lt_mard TYPE STANDARD TABLE OF ty_mard.

CLEAR ls_mard.
ls_mard-matnr = 'M1'.
ls_mard-werks = '0001'.
ls_mard-insme = 1.
APPEND ls_mard TO lt_mard.

CLEAR ls_mard.
ls_mard-matnr = 'M1'.
ls_mard-werks = '0002'.
ls_mard-insme = 2.
APPEND ls_mard TO lt_mard.

CLEAR ls_mard.
ls_mard-matnr = 'M2'.
ls_mard-werks = '0003'.
ls_mard-insme = 3.
APPEND ls_mard TO lt_mard.

CLEAR ls_mard.
ls_mard-matnr = 'M2'.
ls_mard-werks = '0004'.
ls_mard-insme = 4.
APPEND ls_mard TO lt_mard.

CLEAR ls_mard.
ls_mard-matnr = 'M2'.
ls_mard-werks = '0005'.
ls_mard-insme = 5.
APPEND ls_mard TO lt_mard.


DATA: ls_mard_tmp LIKE ls_mard,
      lt_mard_sum LIKE lt_mard,
      l_insme     TYPE mard-insme.




LOOP AT lt_mard INTO ls_mard.
  ls_mard_tmp  = ls_mard.

  l_insme = l_insme + ls_mard-insme.

  AT END OF matnr.
    ls_mard_tmp-insme = l_insme.
    APPEND ls_mard_tmp TO lt_mard_sum.

    CLEAR l_insme.
  ENDAT.
ENDLOOP.
BREAK-POINT.

这是入门的写法
下面是做项目的写法:

SORT lt_mard BY matnr.
LOOP AT lt_mard ASSIGNING FIELD-SYMBOL(<lfs_mard>).
  l_insme = l_insme + <lfs_mard>-insme.
  AT END OF matnr.
    <lfs_mard>-insme = l_insme.
    APPEND <lfs_mard> TO lt_mard_sum.
    BREAK-POINT.

    CLEAR: <lfs_mard>,
           l_insme.
  ENDAT.
ENDLOOP.

八、 取数
学过mysql的人再学opensql是比较简单的。下面直接来示例。

TYPES: BEGIN OF ty_ekpo,
         ebeln TYPE  ekpo-ebeln,
         ebelp TYPE  ekpo-ebelp,
         menge TYPE  ekpo-menge,
       END OF ty_ekpo.

DATA: lt_ekpo TYPE STANDARD TABLE OF ty_ekpo,
      LS_EKKO LIKE LT_EKPO,"table
      LS_EKKO2 LIKE LINE OF LT_EKPO.
BREAK-POINT.


SELECT ebeln
       ebelp
       menge
  FROM ekpo
  INTO CORRESPONDING FIELDS OF TABLE lt_ekpo
 WHERE ebeln IN ('4500000024', '4500000030', '4500000038','4500000059').

九、 move-corresponding

TYPES: BEGIN OF ty_str,
         field  TYPE char10,
         field2 TYPE i,
         field3 TYPE p DECIMALS 2,
       END OF ty_str.

TYPES: BEGIN OF ty_str2,
         field  TYPE char10,
         field2 TYPE i,
         field3 TYPE CHAR10,
       END OF ty_str2.

DATA: ls_str  TYPE ty_str.
DATA: ls_str2 TYPE ty_str2.

ls_str-field   = 'A'.
ls_str-field2  = '1'.
ls_str-field3  = '0.11'.

MOVE-CORRESPONDING ls_str TO ls_str2."把ls_str全部值赋到ls_str2
它的用法是把字段值全部赋值到另一个字段中,字段顺序无所谓,它会自动选择匹配。

十、 COLLECT

TYPES: BEGIN OF ty_str,
         field  TYPE char10,
         field2 TYPE i,
         field3 TYPE p DECIMALS 2,
*         field4 type num5,
       END OF ty_str.

DATA: ls_str TYPE ty_str,
      lt_str TYPE STANDARD TABLE OF ty_str.

CLEAR ls_str.
ls_str-field   = 'A'.
ls_str-field2  = '1'.
ls_str-field3  = '0.11'.
*ls_str-field4  = '9'.
COLLECT ls_str INTO lt_str.

CLEAR ls_str.
ls_str-field   = 'A'.
ls_str-field2  = '2'.
ls_str-field3  = '1'.
*ls_str-field4  = '11'.
COLLECT ls_str INTO lt_str.

CLEAR ls_str.
ls_str-field   = 'A'.
ls_str-field2  = '3'.
ls_str-field3  = '1'.
*ls_str-field4  = '12'.
COLLECT ls_str INTO lt_str.

CLEAR ls_str.
ls_str-field   = 'B'.
ls_str-field2  = '10'.
ls_str-field3  = '1'.
*ls_str-field4  = '9'.
COLLECT ls_str INTO lt_str.

BREAK-POINT.

它的用法是COLLECT 以非数值类型的字段为主键,合计数值类型的字段的值。运算结果如下:

数值类型只有p和I,相信很多人都会认为n也是数值类型,其实他是char类型来的,是非数值类型。我们把fied4的注释给放开,我们的主键就有fied1和fied4了,他们完全一样的情况下才会是同一类,任意一个不一样都不是同一类,我们看看运行结果:

现在我们看到的是四组数据,他们并没有进行数据的合计。

十一、取数
1.抽取单个字段

DATA:lv_ebeln TYPE ekko-ebeln.

  SELECT SINGLE ebeln
    INTO lv_ebeln
    FROM ekko
    WHERE ebeln = '4500000001'.
  IF sy-subrc = 0 
    WRITE:/ lv_ebeln.
  ELSE.
    WRITE:/ '没有找到相关数据。'.

  ENDIF.
  BREAK-POINT.

运行结果如下:


2.抽取多个字段到结构

  TYPES:BEGIN OF lty_ekko,
          ebeln TYPE ekko-ebeln,
          bukrs TYPE ekko-bukrs,
          bstyp TYPE ekko-bstyp,
          statu TYPE ekko-statu,
        END OF lty_ekko.
DATA:LS_EKKO TYPE LTY_EKKO.

SELECT SINGLE BSTYP
              BUKRS
  INTO (LS_EKKO-BSTYP,
        LS_EKKO-BUKRS)
  FROM EKKO
  WHERE EBELN = '4500000001'.
IF SY-SUBRC = 0.
  WRITE:/ SY-SUBRC.
ELSE.
  WRITE: /'NO FOUND.'.
ENDIF.


BREAK-POINT.

这个比较少用,大家记住抽取多个字段into后面是用小括号就行。
3.别名AS(了解就好)

  TYPES:BEGIN OF lty_ekko,
          ebeln   TYPE ekko-ebeln,
          bukrs   TYPE ekko-bukrs,
          zfiedld TYPE ekko-bstyp,
        END OF lty_ekko.

  DATA:ls_ekko TYPE lty_ekko.
  SELECT SINGLE ebeln
                bukrs
                bstyp AS zfield
      INTO CORRESPONDING FIELDS OF ls_ekko
    FROM ekko
    WHERE ebeln = '4500000001'.

4.抽取多行数据到内表

TYPES:BEGIN OF lty_ekko,
          ebeln TYPE ekko-ebeln,
          bukrs TYPE ekko-bukrs,
          bstyp TYPE ekko-bstyp,
          statu TYPE ekko-statu,
        END OF lty_ekko.

  DATA:lt_ekko TYPE STANDARD TABLE OF lty_ekko.

  SELECT ebeln
         bstyp
         bukrs
         statu
    INTO CORRESPONDING FIELDS OF TABLE lt_ekko
    FROM ekko
    WHERE ebeln IN ('4500000024','4500000030','500000038').

  BREAK-POINT .

5.动态取数
这个名字听上去很高大上,其实就加个if判断,别被吓着就可以了,直接上代码。

 DATA:lt_ekko  TYPE STANDARD TABLE OF lty_ekko,
       lv_falg  TYPE char1,
       lv_where TYPE string.
  IF  lv_falg = 'X'.
    lv_where = 'ebeln = ''4500000024'' '.
  ELSE.
    lv_where = 'ebeln = ''4500000038'' '.
  ENDIF.

SELECT ebeln
       bstyp
       bukrs
       statu
  INTO CORRESPONDING FIELDS OF TABLE lt_ekko
  FROM ekko
  WHERE (lv_where).
  BREAK-POINT.

6.表连接

TYPES:BEGIN OF lty_ekko,
          ebeln TYPE ekko-ebeln,
          bukrs TYPE ekko-bukrs,
          ebelp TYPE ekpo-ebelp,
          statu TYPE ekpo-statu,
        END OF lty_ekko.

  DATA:lt_ekko TYPE STANDARD TABLE OF lty_ekko.

  SELECT ekko~ebeln
         ekko~bukrs
         ekpo~ebelp
         ekpo~statu
    FROM ekko JOIN ekpo
    ON ekko~ebeln  = ekpo~ebeln
    INTO CORRESPONDING FIELDS OF TABLE lt_ekko
    WHERE ekko~ebeln = '4500000059'.

我们先创建一个内表来存放读取的数据,ekko和ekpo这两张表进行连接,通过ekko~ebeln = ekpo~ebeln他们的主键进行匹配,然后再用corresponding赋值到内表中,他的搜索条件是where后面。
十二、for all entries in

TYPES:BEGIN OF lty_ekpo,
          ebeln TYPE ekpo-ebeln,
          ebelp TYPE ekpo-ebelp,
          bukrs TYPE ekpo-bukrs,
          aedat TYPE ekpo-aedat,
        END OF lty_ekpo.
  DATA:ls_ekpo     TYPE lty_ekpo,
       lt_ekpo     TYPE STANDARD TABLE OF lty_ekpo,
       lt_ekpo_tmp TYPE STANDARD TABLE OF lty_ekpo.
  ls_ekpo-ebeln = '4500000030'.
  APPEND ls_ekpo TO lt_ekpo_tmp.

  IF lt_ekpo_tmp IS NOT INITIAL.
    SELECT ebeln
           ebelp
           bukrs
           aedat
      INTO CORRESPONDING FIELDS OF TABLE lt_ekpo
      FROM ekpo
      FOR ALL ENTRIES IN lt_ekpo_tmp
      WHERE ebeln = lt_ekpo_tmp-ebeln.

  ENDIF.

用FOR ALL ENTRIES IN 一般都要与if连用,因为不做if判断如果内表lt_ekpo为空的话它会把所有的数据都查出来,这样会很大程度上影响性能。我们来看看运行的结果。

Lt_ekpo只有一个字段有值。
相信很多人都不明白为什么要这样取数呢(新手),我也问过老师大概意思是说后面的业务有关,我就把疑问停留在这里了,慢慢再去解决。

后续会更新变量是如何命名的。

更多推荐

ABAP新手基础入门知识