输入接口增加两个字段PAGE_NUM 类型 INT4 调取第几页如果不传默认第一页PAGE_SIZE 类型 INT4 每页多少数据如果不传默认一页500条数据输出增加两个字段TOTAL_COUNT 类型 INT4 一共多少数据TOTAL_PAGES 类型 INT4 一共多少页以下是两个案例FUNCTION zmes_me03_mm083. *---------------------------------------------------------------------- **本地接口 * IMPORTING *VALUE(INPUT)TYPE ZMES083_S_INPUT * EXPORTING *VALUE(OUTPUT)TYPE ZMES083_S_OUTPUT *---------------------------------------------------------------------- 1. 初始化 CLEAR output. 2. 基础输入校验 IF input-zsysid IS INITIAL. output-type E. output-message 错误外围系统调用必须传入系统编号(ZSYSID)。. RETURN. ENDIF. 3. 分页参数初始化(防御性容错处理) 如果外部没传或者传了负数/0给予默认值以保护 SAP 内存DATA(lv_size) CONDi(WHEN input-page_size 0 THEN 500 ELSE input-page_size).DATA(lv_page) CONDi(WHEN input-page_num 0 THEN 1 ELSE input-page_num). 计算底层 SQL 需要的偏移量(例如第 2 页每页 500则偏移量为 500)DATA(lv_offset)(lv_page - 1)* lv_size. 4. 第一步获取满足条件的总数据条数(极其轻量级的 COUNT 查询)SELECTCOUNT(*)FROM resb AS a INNER JOIN rkpf AS h ON a~rsnum h~rsnum WHERE a~bdart MRAND a~xloek space AND a~kzear space AND(a~werks input-werks OR input-werks IS INITIAL).DATA(lv_total_count) sy-dbcnt. IF lv_total_count 0. output-type S. output-message 未找到符合条件的预留单数据。. output-total_count 0. output-total_pages 0. RETURN. ENDIF. 计算总页数(利用 ABAP 整型运算特性自动进位处理)output-total_count lv_total_count. 使用 DIV 进行向下取整的整数除法完美实现向上进位 output-total_pages (lv_total_count lv_size - 1)DIV lv_size. 5. 第二步分页执行精准取数(OFFSET UP TO ROWS) 注意使用 OFFSET 时必须配合 ORDER BY 保证每次分页取数的一致性 SELECT a~rsnum,a~rspos,h~usnam,a~werks,a~bdart,a~xloek,a~kzear,a~matnr,t~maktx,a~meins,a~sobkz,a~lgort,l1~lgobe,a~charg,a~bdmng,a~enmng,a~bdter,a~shkzg,a~aufnr,a~kdauf,a~kdpos,a~bwart,a~umwrk,a~umlgo,l2~lgobe AS lgobe1 FROM resb AS a INNER JOIN rkpf AS h ON a~rsnum h~rsnum LEFT OUTER JOIN makt AS t ON a~matnr t~matnr AND t~spras 1LEFT OUTER JOIN t001l AS l1 ON a~werks l1~werks AND a~lgort l1~lgort LEFT OUTER JOIN t001l AS l2 ON a~umwrk l2~werks AND a~umlgo l2~lgort WHERE a~bdart MRAND a~xloek space AND a~kzear space AND(a~werks input-werks OR input-werks IS INITIAL)ORDER BY a~rsnum,a~rspos --- 必须排序否则分页数据会混乱 INTO TABLE DATA(lt_result)UP TO lv_size ROWS --- 限制返回条数(Limit)OFFSET lv_offset. --- 设定起始位置(Offset) 6. 数据处理与格式转换 output-item CORRESPONDING #(lt_result). LOOP AT output-item ASSIGNINGFIELD-SYMBOL(fs_item). 计算剩余未发货数量 fs_item-zwfsl fs_item-bdmng - fs_item-enmng. 去除前导零 fs_item-rsnum |{fs_item-rsnum ALPHA OUT}|. fs_item-matnr |{fs_item-matnr ALPHA OUT}|. fs_item-aufnr |{fs_item-aufnr ALPHA OUT}|. fs_item-kdauf |{fs_item-kdauf ALPHA OUT}|. 单位内外码转换 CALL FUNCTIONCONVERSION_EXIT_CUNIT_OUTPUTEXPORTING input fs_item-meins IMPORTING output fs_item-meins EXCEPTIONS unit_not_found 1 OTHERS 2. ENDLOOP. 7. 成功返回 output-type S. output-message |查询成功。当前第{lv_page}页本页读取{lines(output-item)}条。共计{output-total_count}条数据。|. ENDFUNCTION.FUNCTION zmes_me02_mm052a. *---------------------------------------------------------------------- **本地接口 * IMPORTING *REFERENCE(INPUT)TYPE ZMMS052A_INPUT * EXPORTING *REFERENCE(OUTPUT)TYPE ZMMS052A_OUTPUT *----------------------------------------------------------------------CLEAR:output.REFRESH:output-body.DATA:lr_werks TYPE RANGE OF eban-werks,ls_werks LIKE LINE OF lr_werks.DATA:lv_tdid TYPE thead-tdid VALUEB01,lv_name TYPE thead-tdname,lv_objt TYPE thead-tdobject VALUEEBAN,lt_line TYPE TABLE OF tline.DATA:lv_ekorg TYPE ekorg,lrs_lifnr TYPE RANGE OF lifnr,lv_index TYPE sy-tabix,lv_fldname TYPE fieldname. 临时变量用于 SQL 逃逸DATA:lv_tmp_matnr TYPE matnr,lv_tmp_lifnr TYPE lifnr,lv_tmp_infnr TYPE infnr,lv_tmp_werks TYPE werks_d,lv_tmp_ekorg TYPE ekorg,lv_tmp_esokz TYPE esokz,lv_tmp_kschl TYPE kschl.TYPES:BEGIN OF ty_vendor_price,matnr TYPE matnr,werks TYPE werks_d,ekorg TYPE ekorg,lifnr TYPE lifnr,infnr TYPE infnr,zname TYPE name1,mwskz TYPE mwskz,esokz TYPE esokz,knumh TYPE knumh,kbetr TYPE kbetr,kpein TYPE kpein,konwa TYPE konwa,delete TYPE char1,END OF ty_vendor_price.DATA:lt_price TYPE TABLE OF ty_vendor_price.FIELD-SYMBOLS:fs_val TYPE any. 声明一个临时内表用于存放全量基础数据DATA:lt_base LIKE output-body. 1. 入参校验与分页参数初始化 IF input-zsysid IS INITIAL. output-type E. output-message 系统编号 ZSYSID 为必填项. RETURN. ENDIF. 分页参数防御性处理DATA(lv_size) CONDi(WHEN input-page_size 0 THEN 500 ELSE input-page_size).DATA(lv_page) CONDi(WHEN input-page_num 0 THEN 1 ELSE input-page_num). IF input-werks IS NOT INITIAL. ls_werks-sign I. ls_werks-option EQ. ls_werks-low input-werks. APPEND ls_werks TO lr_werks. ELSE. lr_werks VALUE #((sign Ioption EQlow 1000)(sign Ioption EQlow 1100)(sign Ioption EQlow 2000)(sign Ioption EQlow 3000)). ENDIF. 2. 主数据查询(取入临时表 lt_base并加入 ORDER BY) SELECT eban~ekgrp,eban~zgroup,eban~werks,eban~bsart,eban~frgkz,eban~banfn,eban~bnfpo,eban~pstyp,eban~knttp,eban~infnr,ebkn~vbeln,ebkn~vbelp,ebkn~aufnr,ebkn~anln1,eban~matnr,eban~txz01,eban~badat,eban~lfdat,eban~menge,eban~bsmng,(eban~menge - eban~bsmng)AS zwqsl,eban~meins,eban~lgort,eban~lifnr AS lifnr1,a~zcpjd INTO CORRESPONDING FIELDS OF TABLE lt_base FROM eban LEFT JOIN ebkn ON ebkn~banfn eban~banfn AND ebkn~bnfpo eban~bnfpo AND ebkn~loekz INNER JOIN mara AS a ON a~matnr eban~matnr WHERE eban~werks IN lr_werks AND eban~bsart NENBAND eban~loekz AND eban~ebakz ORDER BY eban~banfn,eban~bnfpo. --- 必须通过主键绝对排序 IF sy-subrc 0. output-type S. output-message 未找到符合条件的数据. output-total_count 0. output-total_pages 0. RETURN. ENDIF. 直接在临时表中进行条件过滤 DELETE lt_base WHERE zwqsl 0. 3. 内表精准切片分页(在耗时的 LOOP 之前进行切片大幅提升性能) output-total_count lines(lt_base). IF output-total_count 0. output-type S. output-message 查询成功但所有记录均不满足交货未清条件。. output-total_pages 0. RETURN. ENDIF. 使用 CEIL 避免四舍五入 Bug output-total_pages ceil(output-total_count / lv_size).DATA(lv_from)(lv_page - 1)* lv_size 1.DATA(lv_to) lv_page * lv_size. IF lv_from output-total_count. CLEAR output-body. ELSE. IF lv_to output-total_count. lv_to output-total_count. ENDIF. 将切片数据写入真正的输出表 INSERT LINES OF lt_base FROM lv_from TO lv_to INTO TABLE output-body. ENDIF. 4. 数据加工(仅仅 LOOP 当前页的数据省去海量无用计算) LOOP AT output-body ASSIGNINGFIELD-SYMBOL(fs_alv). 获取文本 lv_name |{fs_alv-banfn}{fs_alv-bnfpo}|. CALL FUNCTION READ_TEXT EXPORTING id lv_tdid language 1 name lv_name object lv_objt TABLES lines lt_line EXCEPTIONS not_found 1 OTHERS 2. IF sy-subrc 0. LOOP AT lt_line INTO DATA(ls_line). fs_alv-zbz |{fs_alv-zbz},{ls_line-tdline}|. ENDLOOP. IF fs_alv-zbz IS NOT INITIAL. fs_alv-zbz fs_alv-zbz1. ENDIF. ENDIF. --- 供应商价格处理 --- IF fs_alv-knttp F. CHECK fs_alv-lifnr1 IS NOT INITIAL. SELECT SINGLE name1 INTO fs_alv-zname1 FROM lfa1 WHERE lifnr fs_alv-lifnr1. lv_tmp_werks fs_alv-werks. lv_ekorg COND #(WHEN lv_tmp_werks 1000THEN1000WHEN lv_tmp_werks 1100THEN1000WHEN lv_tmp_werks 2000THEN2000WHEN lv_tmp_werks 3000THEN3000ELSE). SELECT SINGLE mwskz INTO fs_alv-mwskz1 FROM eine WHERE infnr fs_alv-infnr AND ekorg lv_ekorg AND esokz fs_alv-pstyp AND werks fs_alv-werks AND loekz . 注意这里需取 b 表中的 kbetr,kpein,konwa SELECT b~kbetr,b~kpein,b~konwa INTO TABLEDATA(lt_p2)FROM a025 AS a INNER JOIN konp AS b ON b~knumh a~knumh WHERE a~lifnr fs_alv-lifnr1 AND a~ekorg lv_ekorg AND a~infnr fs_alv-infnr AND a~werks fs_alv-werks AND a~kschl PB00AND a~datbi GE sy-datum AND a~datab LE sy-datum. IF sy-subrc 0. READ TABLE lt_p2 INTODATA(ls_p2)INDEX 1. fs_alv-kbetr1 ls_p2-kbetr. fs_alv-kpein1 ls_p2-kpein. fs_alv-konwa1 ls_p2-konwa. ENDIF. ELSE. CLEAR fs_alv-infnr. IF fs_alv-bsart Z06AND fs_alv-bsart Z12. CLEAR fs_alv-lifnr1. ENDIF. CLEAR lrs_lifnr[]. IF fs_alv-lifnr1 IS NOT INITIAL. lrs_lifnr VALUE #((sign Ioption EQlow fs_alv-lifnr1)). SELECT SINGLE name1 INTO fs_alv-zname1 FROM lfa1 WHERE lifnr fs_alv-lifnr1. ENDIF. lv_ekorg COND #(WHEN fs_alv-werks 1000THEN1000WHEN fs_alv-werks 1100THEN1000WHEN fs_alv-werks 2000THEN2000WHEN fs_alv-werks 3000THEN3000ELSE). CLEAR lt_price. SELECT DISTINCT a~matnr,b~werks,b~ekorg,a~lifnr,a~infnr,c~name1 AS zname,b~mwskz INTO CORRESPONDING FIELDS OF TABLE lt_price FROM eina AS a INNER JOIN eine AS b ON b~infnr a~infnr AND b~werks fs_alv-werks AND b~ekorg lv_ekorg INNER JOIN lfa1 AS c ON c~lifnr a~lifnr WHERE a~lifnr IN lrs_lifnr AND a~matnr fs_alv-matnr AND a~loekz AND b~loekz . LOOP AT lt_price ASSIGNINGFIELD-SYMBOL(fs_price). lv_tmp_matnr fs_price-matnr. lv_tmp_lifnr fs_price-lifnr. lv_tmp_esokz fs_alv-pstyp. lv_tmp_ekorg fs_price-ekorg. lv_tmp_kschl PB00. SELECT SINGLE b~kbetr,b~kpein,b~konwa INTO(fs_price-kbetr,fs_price-kpein,fs_price-konwa)FROM a017 AS a INNER JOIN konp AS b ON b~knumh a~knumh WHERE a~matnr lv_tmp_matnr AND a~lifnr lv_tmp_lifnr AND a~kschl lv_tmp_kschl AND a~esokz lv_tmp_esokz AND a~ekorg lv_tmp_ekorg AND a~datbi GE sy-datum AND a~datab LE sy-datum. IF sy-subrc 0. fs_price-delete X. ENDIF. ENDLOOP. DELETE lt_price WHERE delete X. SORT lt_price BY lifnr. lv_index 0. LOOP AT lt_price ASSIGNINGFIELD-SYMBOL(fs_final)FROM 1 TO 4. lv_index 1. ASSIGN COMPONENT |LIFNR{lv_index}| OF STRUCTURE fs_alv TO fs_val. fs_val fs_final-lifnr. ASSIGN COMPONENT |ZNAME{lv_index}| OF STRUCTURE fs_alv TO fs_val. fs_val fs_final-zname. ASSIGN COMPONENT |KBETR{lv_index}| OF STRUCTURE fs_alv TO fs_val. fs_val fs_final-kbetr. ASSIGN COMPONENT |KPEIN{lv_index}| OF STRUCTURE fs_alv TO fs_val. fs_val fs_final-kpein. ASSIGN COMPONENT |KONWA{lv_index}| OF STRUCTURE fs_alv TO fs_val. fs_val fs_final-konwa. ASSIGN COMPONENT |MWSKZ{lv_index}| OF STRUCTURE fs_alv TO fs_val. fs_val fs_final-mwskz. ENDLOOP. ENDIF. ENDLOOP. output-type S. output-message |查询成功。当前第{lv_page}页本页读取{lines(output-body)}条。共计{output-total_count}条数据。|. ENDFUNCTION.