ABAP Tutorials
ABAP 的全称是 Advanced Business Application Programming-高级业务应用编程语言。
ABAP 是集成在 SAP 系统上的,底层是 SAP 的 ABAP 虚拟机,用来开发 C/S 架构的程序。Java 属于通用的开发语言,可以进行各种领域各种平台的开发,底层是 JVM,一般开发基于 B/S 架构的程序。
ABAP DEV
语法
CHECK、 EXIT、 RETURN 命令的区别
CHECK
CHECK 后面要跟一个表达式,当表达式值为假(false)时,CHECK 发生作用,退出循环(LOOP)或处理程序 (Processing Block)。
如果 CHECK 出现在循环中,则发生作用时,退出的是当前一次循环操作,程序会继续执行下一次循环操作,其作用类似于 Continue (Java 或 C++中 Continue 也是如此)。
如果 CHECK 出现在循环以外,则发生作用时,退出的是当前执行的程序块,例如一个 FORM、 METHOD 或 EVENT。EXIT
EXIT 如果出现在循环中,退出的是整个循环操作,程序会从循环结束处开始继续执行,其作用相当于 Java 与 C++中的 Break。
EXIT 如果出现在循环之外,退出的是当前执行的程序块(Processing Block),例如一个 FORM、 METHOD 或 EVENT,其作用与 RETURN 类似。RETURN
RETURN 用来退出当前执行的程序块,例如一个 FORM、 METHOD 或 EVENT。不管是否出现在循环(L00P)中,RETURN 都会退出当前执行的程序块,而不仅仅是退出循环。虽然 ABAP 中 EXIT 和 RETURN 都可以用来实现退出当前执行的语句块,但 SAP 的帮助文件建议只在循环中使用 EXIT,其他情况下要退出当前执行进程,使用 RETURN。
示例代码:
" CHECK 示例:在循环中跳过某些条件 |
初始化内表有几种方式
- 要初始化有或没有表头的内表,用 REFRESH 语句。
- 如果使用没有表格工作区城的内表,可以使用 CLEAR 语句代替 REFRESH 语。
- 如果使用有表头行的内表,CLEAR 语句仅清除表格工作区城,要重置整个内表而不清除表格工作区城,使用 REFRESH 语句或 CLEAR 语句。
- 使用 REFRESH 或 CLEAR 初始化内表后,系统保持在内存中保留的空间。可以用 FREE 语句释放内存。
示例代码:
" 定义内表 |
一个程序如何调用另外一个程序?
调用其他可执行程序使用”SUBMIT+程序名”语向,使用 WITH 关键字,可传递选择画面参数。使用 AND RETURN 关键字,可在该程序执行完毕后,自动返回调用他的程序。
示例代码:
" 方式1:SUBMIT 调用可执行程序 |
在一个程序中如何调用其他事物代码?
调用其他事务代码使用”CALL TRANSACTION + 事务代码”,使用 AND SKIP FIRST SCREEN 可以跳过第一个画面,进入下一个画面。
示例代码:
" 方式1:调用事务代码 |
在进行画面跳转时,CAL SCREEN 与 LEAVE TO SCREEN 的区别
CALL SCREEN 是将正在运行的画面挂起,进入所调用的画面,当使用 LEAVE TO SCREEN O 时,能够返回原画面,可理解为嵌套调用:而 LEAVE TO SCREEN 是立即结束本画面的执行,调用所指定的画面,在调用画面中,无法再返回原画面。
示例代码:
" CALL SCREEN 示例:嵌套调用 |
与索引相关的系统字段有哪些?分别有什么作用?
SY-INDEX 存储 DO 循环的索引;
SY-TABIX 存储 LOOP 循环到内表的第几行;
SY-DBCNT 存储从数据库中读取到的满足条件的记录条数;
SY-LISEL 存储被选中行的内容,在事件 ATLINE-SELECTION 时起作用,该系统字段中的内容到下一个屏幕的时候还存在。
示例代码:
" SY-INDEX 示例:DO 循环的索引 |
LOOP 循环中 AT 控制逻辑有哪些?分别有什么作用
- AT FIRST 功能:循环中第一条记录时调用。
- AT LAST 功能:循环中最后一条记录时调用。
- AT NEW 功能:循环中当指定字段之前(包括指定字段)的组合和上一条记录不一样时调用。
- AT END OF 功能:循环中当指定字段之前(包括指定字段)的组合和下一条记录不一样时调用。
- AT 事件的注意点:AT 事件中的工作区不同于 L00P 循环的工作区,该工作区中位于指定字段后面的值将不会被读取,如果需要用到则需 read 重新抽取一次。
示例代码:
" 定义内表 |
MESSAGE 消息有哪些类型和含义?如何自定义 MESSAGE 消息类?
A:Abend,立刻终止当前事务,弹出终止对话框。
X:Exit,立刻终止当前事务,进入 DUMP 的界面。
E:错误,画面的状态栏会弹出一个错误提示信息。
I:信息,弹出一个消息对话框。
S:确认,画面的状态栏会弹出一个正确提示信息。
W:警告,画面的状态栏会弹出一个警告提示信息。
可以通过语句 DISPLAY LIKE mtype 取代原错误图标:自定义 MESSAGE 消息类,通过事务代码 SE91
示例代码:
" 消息类型示例 |
ABAP 中,如何自定义异常类?如何捕捉异常?
通过事务代码 SE24,在 Class Type 中,选择 Exeeption Class 即可定义,在 TRY CATCH 语句中就能够使用。
捕获异常:语法和 JAVA 相似
TRY
CATCH 异常类
ENDTRY.
示例代码:
" 方式1:使用系统异常类 |
什么是事物变式?事务变式有什么用?
事务变式是一组屏幕变式,用于预定义屏雅行为和默认值。通过使用变式功能,可以將用户不需要的字段、子屏幕及全屏幕从用户视图中取消。可以给任何输入宇段设置默认值,字段也可以不用带”Ready for Input” 状态。只能为对话和报表事务创建事务变式:变式中只能包含普通屏幕、子屏幕及对话屏幕。
开发人员可以使用 GuiXT 脚本语言 t 通过事务变式维护对屏幕进行修改。修改屏幕布局的方式有:插入按钮、值帮助(Value Helps)、移动对象、插入屏幕等。
示例代码:
" 事务变式示例 |
RANGE 表内的字段有哪些?分别有什么含义?
RANGE 表包括 SIGN、OPTION、LOW、 HIGH 四个字段。RANGE 表和 select-option 的变量差不多,sign = ‘I’ 或 sign = ‘E’, 是指 INCLUDE 和 EXCLUDE, OPTION = ‘EQ’ 或其他操作符,LOW 是指最少值(操作符是范围的话),HIGH 指最大值(如果操作符是’EQ’,该字段不起作用)。
示例代码:
" 定义 RANGE 表 |
对于 FIELD SYMBOL 斌值将使用什么关键字?
ASSIGN
示例代码:
DATA: lv_var TYPE c LENGTH 10 VALUE 'Hello'. |
PERFORM 调用子程序时,分别对 USING、 TABLES、 CHANGING 3 个参数有什么影响?
USING 可以传入单值、工作区,加 VALUE 参数后只能使用,不能对值做修改,PERFORM 结束后传入参数的值还是传入之前的状态。
TABLES 只能传入一个内表,程序逻辑可以对其进行修改,PERFORM 结束后内表的值是影响后的值。
CHANGING 可以传入内表、单值,程序逻辑可以对其进行修改,PERFORM 结束后传入参数的值是影响后的值。
注意,在传入工作区、单值的情況下,USING 不加 VALUE 参数与 CHANGING 结果相同。
示例代码:
" 定义变量 |
如何在程序间传送数据?
可以使用 EXPORT 语句在 ABAP/4 内存中存储数据字段簇。
语句为:EXPORT
而调用程序就会检索数据。
语句为:IMPORT
其中:ID 参数标识唯一的数据簇。
示例代码:
" 程序1:导出数据到 ABAP 内存 |
SAP 和 ABAP 内存的区别?
- 读取时使用方法不同
SAP 内存使用 SET/GET parameters 方法。
ABAP 内存使用 EXPORT 和 IMPORT 方法。 - 共享范围不同
SAP 内存可以被所有的主 Sesion 访问,内存数据可以在同一个 Session 中的不同程序或者不同 Session 之间共享数据。
ABAP 只能在同个 Session 的不同程序之间共享數据。 - 作用范围不同
SAP 内存在整个终端 Session 时间内都有效。
ABAP 内存只能在一个 Session 时间内有效。 - 使用一般原则
SAP 内存用于屏幕默认值输入。
ABAP 内存用于模块之间传替数据。
示例代码:
" SAP 内存示例:使用 SET/GET parameters |
应用技术
自定义搜索帮助有几种方式?如何实现?
- SE11 创建搜索帮助。
- 调用函数 F4IF_INT_TABLE_VALUE_REQUEST。
在 POV 中或者 AT SELECTION-SCREEN ON VALUE-REQUEST FOR 中使用自定义的搜索帮助可以使用函数 “F4IF_INT_TABLE_VALUE_REQUEST”。
示例代码:
" 方式1:使用 SE11 创建搜索帮助 |
怎么创建编码范围(Number Range)
首先使用事务代码 SNUM/SNRO 创建,在使用编码范围的编号时,需要首先将其锁定(函数:NUMBER_RANGE_ENQUEUE),然后取出编号(函数:NUMBER_GET_NEXT),最
后解锁(函数:NUMBER_RANGE_DEQUEUE)。
示例代码:
" 假设编码范围对象名为 ZNR_OBJECT |
函数中,如何给出错误消息?
有以下两种方式:
- 在 TABLES 参数中增加返回表(Return Table),可以将执行过程中产生的错误消息返回,在函数外对返回表做处理。
- 定义 EXCEPTION,当出现错误时,用 RASING 语句抛异常,RASING 语句会直接影响 SY-SUBRC 的值,函数外可以直接根据 SY-SUBRC 来做处理。
示例代码:
" 方式1:使用返回表 |
如何优化 ABAP 程序?
- 可通过运行事务代码 SE30,运行待检查的程序,查看各操作的百分比。
- 避免在循环语句中使用 SELECT 语句,而是通过 FOR ALL ENTRIES IN 语句抽取数据到内表中。
- 通过运行事务代码 SLIN 进行扩展检查,根据 SAP 提供的反馈信息优化代码。
示例代码:
" 优化前:在循环中使用 SELECT(性能差) |
前导零的处理方式
CALL FUNCTION ‘CONVERSION_EXIT_ALPHA_INPUT’. “添加前导 0
CALL FUNCTION ‘CONVERSION_EXIT_ALPHA_OUTPUT’. “去掉前导 0
SHIFT 物料编码 LEFT DELETING LEADING ‘O. “去掉前导 0
示例代码:
" 添加前导零 |
怎样从文件服务器上读取文件?怎样写文件到文件服务器上?
从服务器上打开文件时,要确定文件的操作方式,调用语句:
OPEN DATASET dset FOR access IN mode [position] [os_addition] [error_handling].
从服务器上读取文件时,access 用 output 替换,再调用语句:
READ DATASET dset INTO dobj [MAXIMUM LENGTH mlen] [[ACTUAL] LENGTH alen].
写文件到服务器上 access 用 input 替换,再在调用语句:
TRANSFER dobj TO dset [LENGTH len] [NO END OF LINE].
示例代码:
" 写文件到服务器 |
在使用 ABAP 内存的程序间进行数据交换时用到的两个语句是什么?
EXPORT TO MEMORY ID 用于将数据复制到 ABAP 内存,IMPORT FROM MEMORY ID 用于将数据从 ABAP 内存复制到程序中。
在 ABAP 内存间进行交换的数据必须在两个程序中都进行声明,并包含同样的数据声明。
示例代码:
" 程序1:导出数据到 ABAP 内存 |
SELECT SINGLE 和 SELECT UP TO 1 ROWS 的区别是什么?
SELECT SINGLE WHERE 条件要确定唯一记录;
SELECT UP TO 1 ROWS 可以确定多条记录,只取第一条,一般用来进行存在性检查。
示例代码:
" SELECT SINGLE - 必须确定唯一记录 |
清空内表命令 CLEAR、 REFRESH 和 FREE 的区别?
如果内表有表头行:
CLEAR ITAB 同时清空内表数据行和表头行的内容;
CLEAR ITAB[] 只清空内表本身,保留表头行的内;
REFRESH 只清空内表本身,保留表头行的内容。
如果内表没有表头行:
CLEAR 和 REFRESH 一样,清空内表。
CLEAR ITAB.: 带表头行时只清空表头行,不带表头行时清空整个内表。
CLEAR ITAB[].:只清空整个内表对象数据,不清空表头行。
REFRESH ITAB 或 REFRESH ITAB[].:只清空整个内表对象数据,不清空表头行。
FREE ITAB.或 FREE ITAB[].:只清空整个内表对象数据,不清空表头行,同时释放内存。
示例代码:
" 带表头行的内表 |
FORM 中 USING、 CHANGING、 USING VALUE、 CHANGING VALUE 的区别?
- USING、 CHANGING 引用传递,改变值。
- USING VALUE 值传递,值不改变。
- CHANGING VALUE 值传递,当正常结束后值改变。
示例代码:
" 测试 USING 和 CHANGING 的区别 |
MESSAGE 参数最多几个占位符,占位符对应的消息文本长度最长?屏幕显示消息文本的长度最长?
最多占 4 个占位符,一个&为 50 个字节长,加上 MESSAGE 自身共有的长度为 240。
所有的消息都存储在系统数据库表 T100 中,该表包括四个字段:
SPRSL (Language Key):语言代码。
ARBGB (Message class):消息类,用于将消息按应用分类储存。
MSGNR (Message number):三个数字的消息序列号。
TEXT (Messege text): 消息文本,是显示在屏幕中的信息文字,最多可以有 72 个字符。
消息类型共六种:A(终止)、E(错误)、I(信息)、S(成功)、W(警告)、x(退出)。
示例代码:
" 消息占位符示例 |
使用 FOR ALL ENTRIES 时的注意事项有哪些?
类似外连接的时候,用一个表的某一字段为条件,从另一数据库表中取得数据。
向 LOOP 套 SELECT 的时候用 2 个表,为了提升效率用 FOR ALLL ENTRIES.
- 使用前要检查内表是否为空,否则会查询出全部数据。
- 要尽可能多的用关键字,否则会把重复的删掉。
- 此子句中不能使用 LIKE、 BETWEEN、 IN、 ORDER BY.
示例代码:
" 定义内表 |
删除内表重复数据前应该做什么,如果要按照给定字段如何刪除?
删除前应做 SORT 排序,如果要按照给定字段进行删除则需要 COMPARING 语句指定字段。
示例代码:
" 定义内表 |
哈希表和排序表的注意事项是什么?
排序表(SORTED TABLE) 与标准表相同,也具有一个逻辑索引,但其按关键字升序排序后再进行存储,其访问方式与标准表相同。
哈希表(HASHED TABLE) 没有索引,只能通过关键字来访问。系统用哈希算法管理表中的數据,因而其检索到一个数据行的时间与表的行数无关。
示例代码:
" 定义不同类型的内表 |
怎样做带按钮的选择画面?
类似 CHECKBOX 和 RADIOBUTTON,可通过 PARAMETER 进行设置。
示例代码:
" 定义带按钮的选择屏幕 |
求和函数(COLLECT)的注意事项?
- 所附加的内表必须具有扁平结构(组件中不可包含内表)。
- 工作区必须与内表的行类型兼容(不仅仅是可相互转换)。
- 所有的非表关键字段必须是数字类型。
- 将新行附加至内表末尾,已存在相同表关键字值的行,不附加新行,而是将数字字段的值累计到已有数据行。
示例代码:
" 定义内表结构 |
请列举 ABAP 程序的运行方式?它们一般表现为什么类型的程序?
可以分配事务代码并通过事务代码运行,用于完成一项系统功能,可以添加到最终用户的系统定制菜单中。
可执行程序(Report):模块池程序。
不能直接通过事务代码运行的程序:功能组、ABAP 类库、ABAP 接口库、子程序、类型组包含程序。
COLLECT 和 APPEND 的区别,以及 COLLECT 命令的限制是什么?
要逐行填充内表,可以使用 APPEND、 COLLECT 或 INSERT 语句。COLLECT 用于添加无相同表关键字的内表行,APPEND 可以添加相同表关键字的内表行。
COLLECT 命令的限制事项:
- 要填充没有重复条目的内表,应该使用 COLLECT.
- COLLECT 语句无法用于带深层结构的内表(组件中不可以包含内表)。
- 为 COLLECT 指定的工作区域必须与内表的行类型兼容(不仅仅是可互相转换)。
- 所有的非表关键字段必须是数字类型。
示例代码:
" 定义内表结构 |
APPEND 与 INSERT 对内表操作的区别?
语法:
APPEND WA TO ITAB
INSERT WA INTO TABLE ITAB
前者不能用于 HASHED 表,后者不能用于 SORTED 表的 NON-UNIQUE 操作。
示例代码:
" 定义内表 |
排序表还能插入和删除吗?
语法是允许的,但是规范里不推荐。因为会引起索引重排而导致的性能问题。
示例代码:
" 定义排序表 |
AT FIRST、 AT NEW、 AT END OF 有什么区别?
- AT FIRST:当前循环为内表的第一行,即当第一次循环操作时,系统会执行控制语句块。
- AT LAST:当前循环为内表的最后一行。
- AT NEW f:行组的开头,行组指的是字段 f 和 f 前面(即左边)的全部字段,如果行组中的任何字段内容不同于上一行,执行语句块中的内容。
- AT END OF f:行组的结尾,如果下一行行组中的任何字段内容不同于上一行,执行语句块中的内容。
示例代码:
" 定义内表 |
AT NEW、 AT END OF 指定字段之后的字段將发生怎样的变化,应该注意什么?
在 AT/END AT 语句块内部,目标区城并没有用当前表格行进行填充,而是将进行下述操作:对于 AT FIRST 和 AT LAST,系统用“*” 填充所有标准关键字段内容:对于 AT NEW f 和 AT END OF f,系统用“*”填充目标区域中所有出现在指定字段 f 后面(右边)的标准关键字段。对于所有非标准关键字段,将进行初始化。
示例代码:
" 定义内表 |
数据字典相关问题
激活锁对象时,产生的函数名字是什么?
首先要在 ABAP 字典中创建锁对象,才能在 ABAP 程序中设锁。创建锁对象时,系统会自动生成两个函数来进行锁管理。
用于设锁的函数为 ENQUEUE_<锁对象名>,它用于在锁表(Lock Table)中生成一个锁项(Lock Entry)。若设锁不成功的话,就会在 Return 中反映出来。
用于释放锁的函数为 DEQUEUE_<锁对象名>,它用于从锁表中删除一个锁项。在 ABAP 程序中,只需使用 “CALL FUNCITION..” 语句就可以调用它们。
这两个锁函数是在 SAP 系统的一个特殊工作进程中执行的,专门进行锁管理。它们运行在一个单独的服务器上,而该服务器专门用于维护整个 SAP 系统的主锁表(Central Lock Table)。
有两种锁类型:
- 共享锁 (shared)——只读锁,该模式允许多个用户访问指定表行,但只能读访问。任何时候都不允许写访问。
- 排他锁定 (exelusive,not cumulative)——该模式允许单个用户对指定表行进行读和访问,其他用户不能访问该行。
- 扩展排他锁定 (exclusive,cumulative)——该模式避免具有读写访问权限的单个用户获得对相同表行集的进一步锁定,当使用递归例程更新时,该模式很有用。
在事务 SM12 中查看锁表的情况。
示例代码:
" 假设锁对象名为 EZ_MARA |
向 SAP 表中添加字段的方法是哪两种?
这两种方法是 Append 结构(Append Structure) 和自定义 Include (Customizing Include).
Append 结构是在向表尾添加字段时创建的,自定义 Include 由 SAP 开发人员指定,使用户可以创建新字段。
Doman、 Data Element 和 Table 之间的关系,为什么要分三层?
同样字段定义一个字段可以方便使用。
城(Doman)是定义数据元素的技术属性,具休包括数据字典中的基本内置数据类型,长度和小数位,进而确定该数据元素的数值范围。如果不同的数据元素属于相同的域(Doman),它们就有相同的属性。数据字典中,每一个数据元素必须属于一个域,以确定其基本性质,定义好数据元素可以用作结构或表类型中的字段组件或者数据库表的字段,因而这些组件字段的基本属性也都由某个域决定。
数据元素(Data Elements) 相当于定义在数据字典中的 ABAP 基本类型和引用类型。
表(Table)是一种数据库对象,数据字典中的表独立于数据库存在,一旦创建,则同样结构的数据库表实体也将在物理数据库中创建。
创建数据库表时应注意哪些事项?
- 有 CURR 类型的字段必须有参照表和参照字段。
- 建表时主键必须连续排序,中间不能有非主键存在。
- 插入第一条数据时操作比较特殊
列举 ABAP 数据字典中的对象及作用有哪些?
- Tables
- Views
- Data elements
- Structure
- Domains
- Search Helps
- Local Objects
CHECK TABLE 和 VALUE TABLE 各指的是什么?关系怎么样?
如果一个表字段定义了外部关键字,则该表称为外部关键字表,而对应的参照表则称为 CHECK TABLE。如果在数据字典中为一个表字段指定了约束表,则其输入帮助可以是该表中的关键字段值列表,或者是约束表中对应自动制定的输入帮助。
- CHECK TABLE 用于字段级别的检查。
- VALUE TABLE 用于域级别的检查。
数据库表维护有哪些内容?
- 表字段。
数据库表与结构类型、表类型的区别:后二者是单纯的数据类型,前者还包合其他相关设定,如外码、索引等。 - 技术设定
通过 Technical Settings 按钮维护,主要维护定义表中所存储数据的类型等信息。例如操作数据库表时是否需要进行缓冲(对不需经常更新的数据库表提高后续查询效率)、是否创建系统日志等。 - 索引——仅包括部分字段的数据库表拷贝,通过 Indexes 按钮维护。
1、主索引:只包含表关键字和指向整个数据条目的指针,系统自动生成。
2、附属索引:根据其他字段生成索引,按指定方式排序,自行创建,协助主索引提高搜索效率。
报表相关问题
基本报表
报表事件
1)过程化事件有哪些?
INITIALIZATION.
START-OF-SELECTION.
END-OF-SELECTION.
2)选择屏幕事件有哪些?
AT SELECTION-SCREEN OUTPUT.
AT SELECTION-SCREEN.
AT SELECTION-SCREEN ON field.
AT SELECTION-SCREEN ON BLOCK block.
AT SELECTION-SCREEN ON RADIOBUTTON GROUP group1.
AT SELECTION-SCREEN ON seltab.
AT SELECTION-SCREEN ON END OF seltab.
AT SELECTION-SCREEN ON HELP-REQUEST FOR field.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR field.
3)在使用逻辑数据库时,如 HR 报表,涉及的逻辑数据库事件有哪些?
GET node.
GET node LATE.
4)报表操作事件有哪些?
TOP-OF-PAGE.
END-OF-PAGE.
AT-USER-COMMAND。
5)交互式报表事件有哪些?
AT USER-COMMAND.
AT LINE-SELECTION.
AT PF-FUNCTION KEY(设置功能键)。
6)按顺序举例说明各个 Report 事件及其作用?
LOAD-OF-PROGRAM:程序执行时,自动触发该 EVENT.
INITIALIZTION:对程序变量进行初始化。
AT SELECTION-SCREEN OUTPUT:选择屏幕 PBO 事件,显示选择屏幕之前触发。
AT SELECTION-SCREEN:选择屏幕 PAI 事件,用户在选择屏幕上执行某些功能。
START-OF-SELECTION: 选择开始事件。
END-OF-SELECTION:选择结束事件,一般在该事件中输出列表。
TOP-OF-PAGE:页眉控制。
END-OF-PAGE:页角控制。
AT LINE-SELECTION:行选择控制,用户选择某列表行时触发。
AT USER-COMMAND: 用户交互控制,用户选择某个 GUI 功能时触发。
报表选择画面
- 报表的选择画面上能否添加自定义工具栏?
能够添加,通过语句 SELECTION-SCREEN FUNCTION KEY n (n 为 1 至 3,最多定义 5 个
2)如何对报表的选择画面元素进行分组?
在 PARAMETERS 或 SELECT-OPTIONS 后使用附加语句 “MODIF ID+组名”
3)如何更改屏幕各元素的状态?举例一些比较常用的屏幕属性。
在报表 AT SELECTION-SCREEN OUTPUT 事件中或 PBO ( PROCESS BEFORE OUTPUT) 中,利用如下代码:
LOOP AT SCREEN.
…MODIFY SCREEN.
ENDLOOP.
SCREEN-NAME: 画面元素的名称。
SCREEN-GROUP1 ~ SCREEN-GROUP4:对画面元素的分组。
SCREEN-INPUT:能否输入。
SCREEN-INVISIBLE:是否可见。
SCREEN-LENGTH:可见长度。
SCREEN-ACTIVE:是否是可用的状态。
4)在什么时候触发 TOP OF PAGE 语句?
- 第一个 WRITE 命令。
- 输出行数超过 LINE-COUNT 属性值。
- NEW-PAGE 命令。
5)Report 的跳转语句是什么?PICK 是什么?怎么用?
该语句为 AT LINE-SELECTION。代码 PICK 为内部触发 AT LINE-SELECTION 事件。
在预定义界面中,将“编辑》选择”和
6)介绍一下下拉列表常用到的技术点?
下拉列表多用到 HIDE 指令、READ LINE 指令、事件 AT LINE-SELETION、 AT USER-COMMAND 及 AT PF
事件 AT LINE-SELECTTION 定义用户双击列表某行时触发的事件,
AT USER-COMMAND 定义用户按下某按钮,或者选择某一菜单项或输入命令后触发的事件及 AT PF
7)如果运行报表输出的程序,不想输出到屏幕上,而是直接打印应该怎么做?
在程序中利用代码 NEW-PAGE PRINT ON 将生成的列表直接发送到 SPOOL 系统进行打印,不在屏幕上显示。
ALV 报表
ALV 报表实现的流程是怎样的?
声明数据对象》定义选择画面》从数据库取数》处理数据》调用显示数据。
显示 ALV 常用的几个函数是什么?
REUSE ALVGRID_DISPLAY。
REUSE ALV_LIST_DISPLAY.
REUSE ALV_GRID DISPLAY_LVC.
ALV 显示中的小计如何实现?
使用 SUBTOT:
ALV 可以实现自动小计,首先字段目录参数中添加 DO_SUM = X,然后传入排序表,可以在排序表中指定需要小计的列。使用 AT 语句:
在 LOOP 循环中使用 AT END OF FIELD 逻辑。
函数 ALV 和面向对象 ALV 有什么不同?
函数 ALV 和 面向对象 ALV 都能够实现按钮自定义、数据修改、按钮处理自定义等操作。通常情況下函数 ALV 主要用于报表数据展示及简单交互;面向对象 ALV 主要用于 Dialog 程序开发,可以进行复杂的控制,比如单元格的修改控制(函数只能控制到列修改性)、自定义(F4)等。面向对象 ALV 可以根据容器排列很方便的定义布局,一个屏箱可以放多个 ALV,但是函数 ALV 只能一屏显示一个 ALV。
ALV 是什么,能简单介绍一下 ALV 的作用吗?
ALV (ABAP LIST VIEW) 是 ABAP 的报表显示工具,它把内表中的内容以设定的格式显示出来,附加一些功能,如下载为本地文件等。
SmartForm 报表
谈谈 SmartForm 中,Template 和 Table 表格的区别?
Template 是静态表格,单元格的输出是一定的。Table 是动态表格,包含在循环内,内表能够按条输出。
SmartForm 如何实现公司 LOGO 打印?
用 SE78 导入公司 L0G0,导入时只能导入位图和 GIF 文件。导入位图时,要注意用 256 色,否则会导致图片打印有问题。然后在 SmartForm 中添加图片即可。
SmartForm 中如何控制段落、单个字符的输出格式?
用 Styles 可以定义不同的段落、字符格式,在文本输出时可以指定格式。
什么是 SmartForm,简述其创建过程?
SmarForm 的基本思想是为了提高处理的效率,将数据筛选、整理过程与数据在 Form 中的应用处理及格式化过程相分离。
将数据库中的数据通过 SmatForms 格式化并输出的步菜如下:
- 提取应用数据。
- 定义 Form 格式及相关数据接口。
- 将数据传输至 Form 中,并批量输出。
对话程序
事件
Dialog 中的事件有哪些?
PBO (PROCESS BEFORE OUTPUT)。
PAI (PROCESS AFTER INPUT)。
POV (PROCESS ON VALUE-REQUEST)。
POH (PROCESS ON HELP-REQUEST).
介绍一下 Dynpro 程序结构以及运行机制?
- 逻辑上分为 PBO, PAI 以及 POV, POH
- 建立程序时物理上 TOP, 001, 101, FO1.
- 运行机制:TCODE->PBO->PAL……
解释一下 PBO, PAI 以及 POV,POH?
- PBO: PROCESS BEFORE OUTPUT(显示前处理过程,在向用户显示屏幕 GUI 之前触发,一般做面面初始化和设定 Status、Title、动态设定画面属性和清空变量。
- PAI: PROCESS AFTER INPUT(输入后处理过程)在用户进行某些屏幕行为后触发,对应一些用户操作、面面检查。
- POV: PROCESS ON VALUE-REQUEST 对应功能键
,用户选中画面上某个字段按 键,类似检索帮助。 - POH: PROCESS ON HELP-REQUEST 对应功能键
。
控件
如何在 Table Control 中实现选中一行或多行的效果?
将内表第一个字段定义为一个长度为 1,类型为 C 的变量,并在 Table Control 属性框中将该字段填写到选择字段属性中。
Dialog 开发的几个常用控件是什么?
子屏幕、文本、输入框、输出框、容器、表控制、按钮等。
简述表格控制和步循环的区别?
表格控制和步循环是用于屏幕表格显示的对象。表格控制只是增强了的步循环,它可以使用桌面应用程序中表格工具的“Look”和 “Feel”来显示数据。表格控制还提供使表格易于查看和使用的专用格式化功能。
步循环的一个特点是它们的表行能够在屏幕上跨越多行。相反,表格控制中的行总是单行,但可以很长(表格控制的行能够滚动)。
通常表格控制所提供的许多特征由系统的 SAPGUI 前端操纵,因此,不必在 ABAP/4 事务中编制任何特征。
语法
Dynpro 中画面调用的几种方式和各自的好处是什么?
- SET SCREEN next_screen_number:为当前屏幕指定后续屏幕,不会自动返回当前屏幕。
- CALL SCREEN screen_number 及 CALL TRANCTION tcode:挂起当前屏幕序列,进入新屏幕(序列)或事务。在新的屏幕序列中,通过语句 LEAVE SCREEN TO SCREEN 0 调用的屏幕就能够返回到挂起的屏幕序列上(返回到原程序)。
- LEAVE SCREEN:如果未完成当前屏幕控制流就要转入后续屏幕,使用此语句。
- LEAVE TO SCREEN screen_ number 及 LEAVE TO TRANCTION tcode:未完成当前屏幕就要转入后续屏幕,并且不返回原有程序。
举例说明 Dynpro 的动态属性有哪些?
- NAME 屏幕字段名称。
- GROUP1、 2、 3、4,屏幕字段属于哪个组。
- ACTIVE 1 可用,0 不可用。
- REQUIRED 1 必入力,O 非必入力。
- INPUT 1 可入力,0 不可入力。
- OUTPUT 1 可显示,0 不可显示。
- INTENSIFIED 1 强调显示,0 非强调显示。
- INVISIBLE1 为*,0 为输入即可见。
- LENGTH 字段输出长度。
- DISPLAY 3D 以三维框架显示字段。
- VALUE HELP 有直询帮助的字段。
Dynpro 逻辑块中,Field 的作用是什么?
- 用来传值。
- 进行字段输入检查(防止所有控件都变灰)。
Field Module 和 On Value-Request 有什么作用?
在 Dynpro 程序中,控制屏幕控件是否输入修改值等操作,主要用于屏幕数据的检查。
批处理
原理
BDC 录屏的事务代码是什么?
SHDB。
操作步骤:
- 执行事务代码 SHDB 进入录屏界面
- 点击「新建录屏」按钮,输入录屏名称
- 输入要录制的事务代码,执行操作
- 系统自动记录屏幕字段和用户操作
- 保存录屏后可生成 BDC 程序模板
示例代码:通过 SHDB 录屏数据生成 BDC 程序
" SHDB 录屏后生成的代码结构示例(以创建物料主数据为例) |
简述 BDC 与 BAPI 之间的区别?
都可以用作数据导入,但是 BDC 是完全模拟前台操作,而 BAPI 是 SAP 提供的标准 API,通过调用 BAPI 在后台生成相应数据,性能高于 BDC 导入方式。
对比总结:
| 特性 | BDC | BAPI |
|---|---|---|
| 原理 | 模拟前台屏幕操作 | 调用标准 API 函数 |
| 性能 | 较低,逐屏模拟 | 较高,直接后台处理 |
| 数据校验 | 依赖屏幕校验逻辑 | 内置业务校验 |
| 适用场景 | 无标准 BAPI 时使用 | 优先使用 |
| 错误处理 | 通过 BDCMSGCOLLECT | 通过 RETURN 参数 |
示例代码:使用 BAPI 创建物料主数据(对比 BDC)
" 使用 BAPI 创建物料(推荐方式) |
BDC 录制的注意事项?
将要填写的字段全部输入,保证其能正确被录制下来,不需要填写的字段不要操作,以免录制后产生冗余字段而产生错误。
操作要点:
- 录制前先手动执行一遍事务,确认操作路径最短
- 只操作必要字段,不要点击多余按钮
- 录制完成后检查生成的 BDCDATA,删除冗余字段
- 注意表控件(Table Control)中行号的动态处理
示例代码:检查和清理录屏数据
" SHDB 录制后,在程序中动态处理表控件行号 |
谈谈 BDC 的运行模式和更新模式?
运行模式包括:A.全屏幕显示;E.只有在发生错误时显示屏幕;N.不进行屏幕的显示将相关信息记录到信息内表里;P.不进行屏幕的显示,可进行 DEBUG 测试。
更新模式包括:A.异步更新;S.同步更新;L.本地更新。
示例代码:不同运行模式和更新模式的使用
" 运行模式示例 |
BDC 执行出错时,为查看设置错误处,显示模式应怎样设置,A、E、N 分别代表什么含义?
可以设置 E.出错时转前台运行,有机会输入修正数据。
如果不想马上转前台用 Insert_Group 插入一个 Session。
A.全画面表示;
E.碰到错误时弹出;
N.不弹出错误画面,后台运行。
示例代码:BDC 错误处理和 Session 方式
" 方式1:Call Transaction + 错误处理 |
什么是 BDC(Batch Data Communication)?简单介绍其流程?BDC 调查有哪些方式?BDC 有几种,分别是什么?
BDC 是 SAP 常用的一种数据传输方法。用于一些数据量大,但是对速度又要求不高的数据传输。
其流程大致分为如下几步:
- 提炼数据。
- 把提炼的数据转换到 BDCDATA 内表中。
- 根据 BDC 类型通过 Call Transaction 形式执行,或通过 Session 形式执行,如果 Session 执行成功,数据将被传送成功。
调查 BDC 的事务代码:SHDB,查看 Session 执行结果的事务代码:SM35。
BDC 有两种方式:
- Call Transaction 方式 —— 立即执行,同步/异步更新
- Session 方式 —— 先创建 Session,再通过 SM35 执行
示例代码:完整 BDC 程序框架
REPORT zbdc_material_create. |
如果想把一个 BDC 的程序定义为零点开始启动应该怎么做?
通过计划后台作业(事务代码 SM36),定义 Job 并设定 Job 起始时间为零点。
操作步骤:
- 执行 SM36 进入作业定义界面
- 输入作业名称(如 ZBDC_JOB_001)
- 输入作业类和服务器
- 添加步骤,指定要执行的程序名
- 设定开始时间为零点
- 保存作业
示例代码:在程序中通过代码定义后台作业
" 使用 JOB_OPEN / JOB_SUBMIT / JOB_CLOSE 创建后台作业 |
语法
在 BDC 程序中,BDC 内表所用的构造名及其字段是什么?
BDC 内表所用的构造名为 BDCDATA,其中字段分别是:
- PROGRAM:程序名(屏幕程序名)
- DYNPRO:屏幕编号
- DYNBEGIN:屏幕开始标志(’X’ 表示新屏幕开始)
- FNAM:字段名
- FVAL:字段值
示例代码:BDCDATA 结构详解
" BDCDATA 结构说明 |
BDC Session 如何创建?在程序中如何处理?
BDC Session 创建过程如下:
- CALL FUNCTION ‘BDC_OPEN_GROUP’
- BDC 内表做成。
- CALL FUNCTION BDC INSERT
- CALL FUNCTION BDC CLOSE GROUP
使用如下语句可以立即执行 BATCH INPUT SESSION。
SUBMIT RSBDCBTC AND RETURN WITH OUBUF-ID = WK_QID.
在 SM35 下查看 BATCH INPUT SESSION 执行结果。
示例代码:完整的 BDC Session 程序
REPORT zbdc_session_create. |
BDC 时如何确定表控件里各行的数据?
用括号数字确定 BDC 输入行数。
示例代码:表控件(Table Control)行号处理
" 表控件中的字段需要在字段名后加行号,格式:FIELD_NAME(行号) |
增强
什么叫增强?
增强就是 ERP 系统中标准程序的出口,在该出口中由用户根据企业实际需求编写客户化逻辑代码。为什么会有出口呢?因为正常的业务系统不能满足实际需求,这时可以在出口中增加一些功能,来达到要求,这也就是为什么它还叫增强。在 SAP 中,出口就是标准程序最后要调用的一个函数或者功能模块,这个函数或功能模块的输入已经由 SAP 定义。自己写的 SAP 出口程序在系统升级的时候会被保留,而更改标准程序则会在 SAP 系统升级的时候被覆盖。
SAP 增强的四代技术:
| 代次 | 名称 | 特点 |
|---|---|---|
| 第一代 | User Exit | 函数出口,以 EXIT_ 开头 |
| 第二代 | Customer Exit | SMOD/CMOD 管理,包含函数/菜单/屏幕出口 |
| 第三代 | BADI | 面向对象,SE18/SE19 管理 |
| 第四代 | Enhancement Spot | 隐式增强,可插入任意位置 |
示例代码:第一代增强(User Exit)实现
" User Exit 示例:在销售订单保存前校验 |
如何查找 SAP 的第一类增强(User Exit)?
通过 SE37,以 EXIT* 开头,找到的函数大多是做系统预留的出口函数。前面说过,用户出口是标准程序留给用户的接口,标准程序通常不允许用户任意修改,如果修改需要申请 Access Key。而且修改标准程序可能导致的错误,ERP 公司通常是不负责的。在 SAP 中,自定义的程序通常以字母 Y 或 Z 开头,因此,出口函数中都预包含了一个 Z 开头的程序。
操作步骤:
- 执行 SE37,搜索函数名 EXIT*
- 找到相关出口函数后,双击查看其源代码
- 在源代码中找到以 ZX 开头的 Include 程序
- 使用 SE38 创建该 Include 程序并编写自定义逻辑
示例代码:查找并使用 User Exit
" 方法1:通过 SE37 查找 |
如何查找 SAP 的第二类增强(Customer Exit)?其包含哪几方面?
客户自定义程序通过 Call Function 来调用 SAP 库中的一些系统函数,而用户增强的概念刚好与之相反,可以使用一个由 SAP 功能模块调用的功能模块出口。
可以在下面这几个层面对模块进行增强:在 ABAP 程序中的 Function Module Exit(E 类);在 GUI 接口中的 Menu Exit(C 类);在指定区域插入一个子窗口的 Screen Exit(S 类);在 ABAP 数据字典中表和结构的增强 Table Enhancement(T 类);还有在屏幕指定区域添加用户自定义功能的 Field Exit 和 Keyword Exit。
操作步骤:
- 执行 SMOD 查看增强组件
- 使用 CMOD 建立项目并实现增强
- 通过 Enhancement 查找相关增强点
示例代码:Customer Exit 的各种类型
" === E 类:Function Module Exit(函数出口)=== |
什么是 BADI?
即 Business Add-in,是基于 ABAP 对象的一种增强技术。SAP 预定了一些接口,供客户进行实现,完成增强。它是一种新的功能增强概念,使用 ABAP 对象技术。实现 BADI 要用到类、接口及方法等面向对象的概念。
在进行增强时,必须先定义 BADI,为 BADI 创建一个接口。接着创建一个适配器类(Adapter Class)来实现这个接口,然后创建这个适配器类的实例。
操作步骤:
- SE18 查找 BADI 接口定义
- SE19 创建 BADI 实现
- 在实现类中编写增强逻辑
- 激活 BADI 实现
示例代码:BADI 实现
" === 步骤1: SE18 查找 BADI 定义 === |
SAP 的第四类增强(Enhancement Spot)指什么?
可称为隐式增强,在代码中,可插入增强点对代码进行增强。Enhancement Spot 分为 ENHANCEMENT-POINT 与 ENHANCEMENT-SECTION,ENHANCEMENT-POINT 添加的新代码,能够与旧代码一起运行;ENHANCEMENT-SECTION 增加的新代码,将覆盖旧代码。
操作步骤:
- 打开标准程序(SE38/SE80)
- 在菜单中选择「编辑 → Enhancement Operations」
- 查看已有的隐式增强点
- 在增强点处编写自定义代码
- 激活增强
示例代码:Enhancement Spot 的两种类型
" === ENHANCEMENT-POINT(增强点)=== |
如何建立增强?
- 找到增强。
- 建立增强项目。
- 添加增强的组件添加进增强项目。
- 编辑增强,添加自己的代码。
- 激活增强代码。
示例代码:完整增强实施步骤(以 CMOD 为例)
" === 完整增强实施流程 === |
与增强相关的事务代码有哪些?
- 对于 Customer Exit:SMOD 查看增强组件,CMOD 建立项目后,实现增强。
- 对于 BADI:SE18 查找接口,SE19 对接口进行实现。
示例代码:各增强类型对应的事务代码和表
" === 增强相关事务代码汇总 === |
如何进行数据库表字段的增强?Append 和 Include 的方式有何区别?
Append 结构(Append Structure)是在向表尾添加字段时创建的,自定义 Include(Customizing Include)由 SAP 开发人员指定,以使用户可以创建新字段。
它们之间的区别在于 Append 结构只能由该表使用,其他表不可使用;Include 能够插入任意一个结构或表,其中当插入表时,该表会自动转换为相同字段的结构。
操作步骤:
" === 方式1: Append Structure(推荐)=== |
实现功能模块出口时 SAP,应使用应用程序中的哪条语句?
某些 SAP 应用程序中存在功能模块出口,它使用户能够向 SAP 程序中添加一些功能。通过搜索 “CALL CUSTOMER-FUNCTION” 可以发现是否存在功能模块出口。
示例代码:查找和使用功能模块出口
" === 方法1: 在标准程序中搜索 CALL CUSTOMER-FUNCTION === |
什么叫 BTE(Business Transaction Event),BTE 的两种类型?
BTE 可以通过函数的模式附加一个组件到 SAP 系统中,从本质上讲,BTE 也是预定义的访问接口。
BTE 的两种类型:
- Publish and Subscribe Interface:通过事件驱动的模式从 SAP 提供的参数触发一个或多个事件(函数),但是这些事件不会返回信息给 SAP,这种模式不影响 SAP 的正常业务流程。
- Process Interface:属于 SAP 控制业务流程的一部分,这个接口可能对应多个事件,但是每次运行的时候只能根据需要选择运行其中的一个事件,SAP 供给参数接口,并且返回参数给 SAP,这种模式影响了 SAP 的正常业务流程。
操作步骤:
- FIBF 查看 BTE 配置
- 查找相关事件编号
- 创建自定义函数模块
- 在 FIBF 中分配函数到事件
示例代码:BTE 实现
" === BTE 实现步骤 === |
接口
SAP 有哪些外部接口及其内容?
SAP 接口模式主要有 RFC、BAPI、IDOC。
RFC:RFC 是 SAP 系统和其他(SAP 或者非 SAP)系统间的一个重要而常用的双向接口技术,也被视为 SAP 与外部通信的基本协议。简单地说,RFC 过程就是系统调用当前系统外的程序模块,从而实现某个功能,而且调用系统和被调用系统中至少有一个必须是 SAP ABAP 系统。
BAPI:BAPI 实质上是一种特殊的、支持远程调用的业务对象方法,并通过远程支持的功能模块实现。BAPI 支持同步与异步的数据通信过程,典型的 BAPI 功能包括业务对象的创建、属性的读取与更新操作。
IDOC:IDOC 是 SAP 系统之间或 SAP 系统与外部系统之间电子数据交换的标准数据格式。通过 IDOC 接口可以实现 SAP 系统之间以及 SAP 系统与其他系统之间的数据交换。
示例代码:三种接口的基本调用方式
" === RFC 调用示例 === |
简述 ALE/EDI 接口类型概念及应用?
ALE:用于同一个企业中不同 SAP 系统之间的数据交换,通过 IDOC 格式的数据创建分布式的系统。
EDI(Electronic Data Exchange,电子数据交换):用于实现不同企业间的电子数据交换,是各应用系统间的结构化电子数据交换标准。EDI 中的 IDOC 符合 EDI 标准,SAP 格式的数据通过 EDI 子系统转换为 EDI 标准,然后与业务伙伴进行数据交换。
示例代码:ALE 配置和 IDOC 数据发送
" === ALE 分发模型配置 === |
什么是 RFC,有哪些通信模式?
RFC 是 Remote Function Call 的简称,是 SAP 系统和其他系统之间重要而常用的双向接口技术,它包含同步 RFC、异步 RFC、事务性 RFC、队列 RFC 和并行 RFC。
示例代码:五种 RFC 通信模式
" === 1. 同步 RFC(sRFC)=== |
RFC 中涉及的常用事务代码有哪些?
SM51:查看当前 SAP 系统中活动的应用服务器,包括 Server_Names,Hostname 和 Type(服务类型)。
SM49:查看、设定并执行外部命令。
SM59:配置 RFC 连接,其中相同类型的 RFC 目标被组合至同一个目录。这些远程目标的定义将保存在表 RFCDES 中。
示例代码:通过 RFC 相关事务代码查询信息
" === SM59 配置 RFC 连接 === |
根据调用的不同,RFC 接口提供了什么样的服务?
- ABAP 程序的调用接口:任何 ABAP 程序都可以使用 CALL FUNCTION…DESTINATION 预计调用远程函数。
- 非 SAP ABAP 程序的调用接口:SAP 系统为外部程序提供 RFC-supported interface 和 GUI-supported interface。
示例代码:ABAP 程序调用远程函数
" === ABAP 程序通过 RFC 调用远程函数 === |
RFC 接口的具体功能包括哪些?
- 登录并退出远程系统,并执行权限检查。
- 调用并管理远程系统会话所需的通信例程。
- 将参数转换成远程系统所需的格式。
- 处理通信过程中的错误。
示例代码:RFC 连接管理和错误处理
" === RFC 连接的完整生命周期 === |
在通过 CALL FUNCTION 语句进行远程功能调用的基本模式有哪些?
- CALL FUNCTION - DESTINATION:以同步 RFC 方式实现的远程函数调用。
- CALL FUNCTION - STARTING NEW TASK:以异步 RFC 方式实现的远程函数调用。
- CALL FUNCTION - IN BACKGROUND TASK:以事务性 RFC 方式实现的远程函数调用。
示例代码:三种 CALL FUNCTION 模式对比
" === 模式1: 同步 RFC - 立即执行并等待结果 === |
怎么创建一个支持远程调用的 RFC?
在 SAP 系统中,RFC 的创建方式与普通函数模块类似,只是编写函数模块时需要在 Attribute 选项卡中将 Processing Type 选项设为 Remote-Enable Module,在传入、传出参数那里需要选择参数为 Passing Value。
操作步骤:
- SE37 创建函数模块
- Attribute 选项卡中 Processing Type 选择「Remote-Enabled Module」
- 定义参数时选中 Pass Value 选项
- 编写函数逻辑
- 激活函数
示例代码:创建 RFC 函数模块
" === 在 SE37 中创建 RFC 函数 === |
怎么调用一个 SAP 标准 RFC?
在 SAP 中,功能模块的调用通过 CALL FUNCTION 语句实现。远程功能作为普通函数模块调用的扩展,可通过在 CALL FUNCTION 语句中添加 DESTINATION 子句完成,其语法格式与普通调用完全相同。
示例代码:调用 SAP 标准 RFC 函数
" === 调用标准 RFC 函数 === |
怎样建立 RFC 程序?RFC 程序传递的参数是传递值还是引用?如何建立函数组?
在 SE37 中建立函数模块的时候,Attributes 选项卡中选中 Remote Function。RFC 程序传递的参数都是值传递(选中 PassValue 选项)。
建立函数组可进入 SE80,选中屏幕左边的 Repository Browser 选项,在第一个输入框中选中函数组,在第二个输入框中输入需建立的函数组名,再按回车键就可以了。
或者从 SE37 进入,在菜单上选中 goto → function group → create group。
示例代码:创建函数组和 RFC 函数
" === 步骤1: SE80 创建函数组 === |
怎么维护 DESTINATION(远程目标)?
SM59 中包含链接和登录远程系统所需的全部参数信息。还可以在远程调用时直接指定当前系统的应用服务器作为 RFC 目标。通过 SM51 查看当前 SAP 系统中活动的应用服务器。
示例代码:RFC 目标配置和动态指定
" === SM59 配置步骤 === |
什么是 BAPI?你使用过哪些 BAPI 实现什么功能?
BAPI 业务应用程序接口(Business Application Programming Interface)是面向对象程序设计方法中的一组程序接口。它允许程序员通过 SAP 将第三方软件整合成 R/3 专有产品。
常用 BAPI 及功能:
| BAPI | 功能 |
|---|---|
| BAPI_SALESORDER_CREATEFROMDAT2 | 创建销售订单 |
| BAPI_GOODSMVT_CREATE | 物料凭证过账 |
| BAPI_ACC_DOCUMENT_POST | 会计凭证过账 |
| BAPI_MATERIAL_SAVEDATA | 创建/修改物料主数据 |
| BAPI_CUSTOMER_CREATEFROMDATA1 | 创建客户主数据 |
| BAPI_PO_CREATE1 | 创建采购订单 |
示例代码:常用 BAPI 调用示例
" === BAPI 创建销售订单 === |
什么是业务对象类型?它包含哪些组件?
业务对象类型是业务对象的定义和描述,面向对象构架的实现基础,也就是 SAP 系统中的类,它封装了业务功能和数据。它包含接口、关键字段、属性、方法和事件 5 个业务组件。
示例代码:通过 BOR(Business Object Repository)操作业务对象
" === 使用 SWO1 查看业务对象 === |
如何创建一个 BAPI?
- 定义 BAPI Structure(Structure 不能在 BAPI 中重复使用,因为一旦 BAPI 被释放,其 Structure 将被冻结)。
- 创建 FUNCTION MODULE(每个 BAPI 必须有自己的 Function Group,Function Group 属性必须为 RFC)。
- 创建 Business Object(SWO1)。
- 使用 BAPI WIZARD 创建 API Method(这样 BAPI 可以被外部程序调用)。
- 释放 BAPI Function Module,释放 Business Object Type,释放 BAPI 作为 BOR 的一种 Method。
示例代码:创建自定义 BAPI 的完整步骤
" === 步骤1: SE11 创建 BAPI 结构 === |
编写 BAPI 的注意事项有哪些?
BAPI 不能包括 Call Transaction 或 Submit Report 那些会跳转到别的程序的语句;BAPI 的结构中不能使用 Append 或 Include,并且每个 BAPI 的结构都必须新建;BAPI 中不能使用 Dialog,如需进行文件选择或用户交互的也不能在 RFC 中出现。
示例代码:BAPI 开发规范和错误处理模式
" === BAPI 标准开发模式 === |
谈谈与 BAPI 相关的事务代码。
SWO1 业务对象创建器。
SWO2 业务对象浏览器。
SWO3 业务对象仓库浏览器。
BAPI 对象浏览器。
示例代码:使用 BAPI 浏览器查找和测试 BAPI
" === BAPI 相关事务代码汇总 === |
RFC 和 BAPI 的区别?
- BAPI 和 RFC 不是同一个层次上的概念。BAPI 是 SAP 提供的基于业务对象的函数,关键是它们处理的对象是 R/3 的业务相关 Business Object,比如单据类销售订单、组织、公司等,它们是一系列实体。RFC 则是一种系统间通讯的方式(Remote Function Call),一个 BAPI 函数往往是一个 RFC 函数。
- BAPI 是 SAP 里一个很好的思想,把业务对象都对象化了。
示例代码:RFC 与 BAPI 的对比使用
" === 使用 RFC(通用远程调用)=== |
本地文件上传为 PDF、Excel 文件使用的函数是什么?
- KCD_EXCEL_OLE_TO_INT_CONVERT - 上传 EXCEL 文件。
- CONVERT_OTFSPOOLJOB_2_PDF - Converts a OTF spool to PDF.
- CONVERT_ABAPSPOOLJOB_2_PDF - Converts ABAP spool output to PDF.
示例代码:文件转换函数的使用
" === Excel 文件上传 === |
FTP 文件的上传、下载操作是什么?
FTP 程序大致流程为:
- FTP_CONNECT - 打开并登录 FTP 服务器的连接。
- FTP_COMMAND - 在 FTP 服务器上执行一个命令。
- FTP_DISCONNECT - 关闭指向 FTP 服务器的连接。
示例代码:FTP 文件上传下载完整程序
REPORT zftp_example. |
本地文件上传为 CSV 文件的函数?
- TEXT_CONVERT_CSV_TO_SAP:导入 CSV 数据到 SAP 系统。
- GUI_UPLOAD:文件上传。
示例代码:CSV 文件上传和解析
" === 方式1: GUI_UPLOAD 上传文件 === |
SAP 文件操作都有哪几种?分别有什么操作?版本有什么限制?
SAP 文件操作的有以下两种文件:
- 顺次文件(服务器文件)。
- 本地文件(客户端文件)。
顺次文件的操作包括:打开、读取、写入、关闭、删除。
本地文件的操作:上传、下载。4.7 版本以后使用 GUI_DOWNLOAD / GUI_UPLOAD;4.6 版本以前使用 WS_DOWNLOAD / WS_UPLOAD / DOWNLOAD / UPLOAD。
示例代码:服务器文件操作和本地文件操作
" === 服务器文件操作(应用服务器)=== |
在文件处理时,文件中出现乱码,应该从哪方面考虑?
OpenDataset 时指定字符编码。
示例代码:正确处理文件字符编码
" === 乱码问题的常见原因和解决方案 === |
简单描述 Web Service 的创建过程?
发布大体步骤:SE37 向导发布 Web Service,SOAMANAGER 配置端口。
调用大体步骤:SE80 创建代理类,LOCONFIG 创建逻辑端口,SE38 程序中调用,创建代理类对象,调用对象的方法。
示例代码:Web Service 发布和调用
" === 发布 Web Service === |
现阶段接口开发使用的技术?
企业服务总线(ESB:Enterprise Service Bus)+ WebService。
示例代码:ESB 集成模式
" === ESB 集成架构 === |
为一个远程调用函数(Remote-Enabled Module)创建 Web Service 都有什么相关的事务代码?
创建 Web Service:SE37/SE80。
示例代码:通过 SOAMANAGER 配置 Web Service
" === Web Service 创建和配置步骤 === |
在企业信息系统结构内企业服务总线是如何使用的?
企业服务总线来管理 ERP 和其他接口交互的信息,可以查看监听管理双发系统的交互信息。
示例代码:ESB 集成场景设计
" === 典型 ESB 集成场景 === |
数据库知识
ABAP 数据字典有哪些对象或元素?
Data element、Domain、structure、lock object、views。
示例代码:数据字典对象的创建和使用
" === 数据字典对象层次关系 === |
数据库提交确认和数据库回滚取消语句?
COMMIT WORK。
ROLLBACK WORK。
示例代码:数据库提交和回滚的正确使用
" === COMMIT WORK - 确认数据库操作 === |
什么是 LUW?
LUW 称为逻辑工作单位,同一个逻辑工作单位共享一段内存,将操作放置在同一个 LUW 中可以控制事务的同时提交和回滚。
示例代码:LUW 的理解和使用
" === LUW 概念 === |
简述 Modify、Insert、Update 对数据库表做操作时的影响。
- Modify 操作数据库时,可以使用 From 内表或者工作区来进行多条或单条的更新,要求内表或工作区跟数据库表的结构一致。当数据库表中存在重复记录时,执行更新操作,更新的值为内表或工作区的值;当数据库表中不存在记录时,执行插入操作,插入的值为内表或工作区的值。
- Insert 操作数据库时,可以用 From 内表或者工作区进行多条或单条的插入,要求内表或工作区跟数据库表的结构一致。当数据库中不存在重复记录时,执行插入操作,插入的值为内表或工作区的值;如果已经存在重复记录,会出现更新异常。
- Update 操作数据库时,可以直接 set 来进行单值更新,可以用 From Table 和工作区进行批量更新,要求内表和工作区跟数据库表的结构一致。当存在记录时执行更新操作;当不存在记录时,没有数据会被更新,同时也不会产生异常,sy-subrc=0。
示例代码:三种操作的对比
DATA: ls_mara TYPE mara, |
描述域、数据元素、表字段之间的关系。
域为数据字典中最小的单元,数据元素是基于域进行定义的,表字段则是通过数据元素进行定义的。
示例代码:三层结构的创建和关系
" === 层次关系 === |
数据字典有几种缓冲方式,适用范围是什么?
- Full Buffer(全缓冲),一个表的数据要么全在内存中要么全不在。当表记录很少,访问非常频繁且很少进行修改时使用。
- Generic Area Buffer(常规区域缓冲),语言代码相关的表是最常使用的情况,如文本描述表,缓存满足在 Generic Keys 中定义的字段的值的记录。
- Single-Record Buffer(单记录缓冲),数据库表记录比较多,并且经常都是读取一条记录,如 select single。
示例代码:缓冲方式的选择和配置
" === 缓冲配置(SE11 → 表 → 技术设置)=== |
ABAP 数据表的主索引是什么?索引的好处与坏处有哪些?建立索引的注意事项有哪些?
数据表的主键即是表的主索引;好的索引能加快数据读取的速度但会增加更新数据库表的时间;建立次级索引时应尽量选取那些查询条件经常使用到的字段。
示例代码:索引的创建和使用
" === 主索引(Primary Index)=== |
ABAP 透明表有哪几种数据类(Data Class)?对数据的存储有什么影响?
数据类主要分为以下三类:
- 主数据类:经常读取,很少修改的数据。
- 业务数据类:经常更新的数据。
- 组织数据类:系统初始化时存在的数据,也很少修改。
数据类决定了数据实际存放的物理区域。
示例代码:数据类的理解和配置
" === 数据类(Data Class)在 SE11 中配置 === |
SAP 中有几种表,他们的区别是什么?
Transparent table(透明表),Pooled table(共享表)和 Cluster table(簇表)。
透明表是和 DB 层的物理表(Physical Table)对应的,后两者则是不对应到 DB 表的。比如 TBSL 就是一个共享表,在 DB 层找不到此表。
然后多个簇表或共享表组成一个表簇(table cluster)或表池(Table Pool),表簇和表池是 DB 层的一个物理表。
示例代码:三种表类型的查询和使用
" === 1. 透明表(Transparent Table)=== |
什么是簇表(cluster table)?举出知道的簇表。
簇表是逻辑上有关联的几个表,在定义的时候分配给一个表簇,如 Bseg。
示例代码:簇表的特性和操作
" === 簇表特性 === |
找数据库表有哪些常用的方法?
- 单击画面上需要查找的字段,单击(F1)键,在弹出画面中的技术信息中查找。
- 通过 ST05 进行数据库操作的跟踪,对于在前台界面进行数据的新增或更新,在数据库中都会有所体现。
- 通过事务 SE80 → Repository Information System → ABAP 字典 → 数据库表格中,对某个字段进行查询。
示例代码:通过代码查找数据库表和字段
" === 方法1: F1 技术信息 === |
如何提高程序效率?
使用 OPEN SQL 时注意以下原则:
- 尽可能减少满足条件的数据条目数量。
- 减少数据的传输量,以减少网络流量。
- 减少访问的数据库表量。
- 减少查询难度,可以通过整理选择标准来实现。
- 减少数据库负载。
示例代码:程序优化的具体实践
" === 优化原则1: 不要在 LOOP 中访问数据库 === |
表内联(外联)限制条件有哪些?
- LEFT OUTER JOIN 限制条件:在 ON 附加项中,只能使用 “=” 操作符,且必须至少有一个条件是对主选择表和结合表中的字段进行比较。
- INNER JOIN 限制条件:不同逻辑条件之间只能通过 AND 连接。
- LEFT OUTER JOIN 与 INNER JOIN 的主要区别是 LEFT OUTER JOIN 中对于主选择表的数据,即使在结合数据表中结合条件字段值不存在,也将该数据行选出,结合表中不存在的字段保持空白。
示例代码:JOIN 的正确使用和限制
" === INNER JOIN(内连接)=== |
UPDATE、DELETE 数据库时的注意事项?
- DELETE 语句用以删除数据表里记录。注意:删除记录并不能释放 ORACLE 里被占用的数据块表空间,它只把那些被删除的数据块标成 unused。如果确实要删除一个大表里的全部记录,可以用 TRUNCATE 命令,TRUNCATE TABLE 表名,且此操作不可逆。
- UPDATE 语句用以修改数据表里记录。注意:以上 SQL 语句对表都加上了行级锁,确认完成后,必须加上事务处理结束的命令 COMMIT 才能正式生效。
示例代码:UPDATE 和 DELETE 的正确使用
" === DELETE 操作 === |
在程序中使用逻辑数据库的两种方法是什么?
在程序中使用逻辑数据库有两种方法,通常是通过 GET 事件或者功能模块进行调用,如 NODES node。
示例代码:逻辑数据库的使用
" === 方法1: GET 事件 === |
ABAP 声明结构体和内表
TYPES:BEGIN OF iline, "创建类型包含三个字段 TYPES:定义类型 DATA:创建的对象 |
嵌套结构体类型利用 INCLUDE STRUCTRER 语句,可以把 DATA 语句定义的结构体或者 ABAP 数据字典存在的结构体包含到嵌套结构体中
*声明结构体类型 |
————————————————
版权声明:本文为 CSDN 博主「诸秋白」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_36910300/article/details/120632412
常用系统变量
SY-ABCDE 常量,A-Z 字母表
SY-BATCH 后台的程序运行
SY-COLNO:当前选定列的列号
SY-CPAGE 列表的当前显示页
SY-CUCOL 屏幕,PAI 的水平光标位置
SY-CUROW 选择某行时光标列位置
sy-datar 在 PAI 中,如果屏幕上至少有一个输入字段的值被用户或其他数据传输所更改,
则为“X”,否则为初始值。
sy-datlo 用户的当前日期
SY-DATUM 服务器日期
SY-DYNNR 当前屏幕的编号
SY-INDEX 循环的次数(DO While)
SY-LANGU 当前登录语言
SY-LILLI:选择某行时光标行位置
SY-LINCT 当前报表长度 (REPROT 语句中设定的 LINE-COUNT)
SY-LINNO 当前选定行的行号
SY-LINSZ 当前报表宽度(REPROT 语句中设定的 LINE-SIZE)
SY-LISEL 选择行的内容,长度为 255
SY-LISTI 上一个列表的索引
SY-LOOPC:当前表格控件在屏幕中的总行数(Table Control)
SY-LSIND:当前列表索引,第一级列表为 1
SY-MSGID 消息, 消息类
SY-MSGTY 消息,消息类型
SY-MSGNO 消息, 消息编号
SY-MSGV1 消息,消息变量 1
SY-MSGV2 消息,消息变量 2
SY-MSGV3 消息,消息变量 3
SY-MSGV4 消息,消息变量 4
SY-PAGNO 当前页号
SY-SCOLS 当前窗口的列表栏目数
SY-SLSET 选择屏幕的变式名称
SY-SROWS 当前窗口的列表行数
SY-STARO 真实行号
SY-STEPL 返回当前操作的屏幕行号(Table Control)
SY-SUBRC 执行状态
SY-TABIX 当前处理的内表的 Index
SY-TCODE 当前的事务代码
SY-UCOMM PAI 所出发的功能代码
SY-ULINE 水平线
SY-UNAME 用户名
SY-UZEIT 服务器时间
SY-VLINE 垂直线
sy-mandt 当前客户端
================= FUNCTION MODULE (或 RFC 中) SY-SUBRC 的含义 ================
使用 SELECT 语句选择查询:
SY-SUBRC = 0: 至少有一行数据,当 ENDSELECT 语句执行完,SY-DBCNT 中保存着记录的个数。
SY-SUBRC = 4: 没有数据。
SY-SUBRC = 8: 只有使用“SELECT SINGLE FOR UPDATE”时才会有,
表示: WHERE 条件指定的记录不止一行,结果是没有记录被选中。
使用 INSERT 语句,向表中插入一行,必须注意 INSERT 的顺序与表中字段的顺序一致:
SY-SUBRC = 0: 插入成功,SY-DBCNT 包含了插入的行数,0 或 1。
SY-SUBRC = 4: 由于有相同的 KEY 存在,所以插入失败。
使用 LOOP 语句来遍历一个内表:
SY-SUBRC = 0: 循环至少被执行一次。
SY-SUBRC = 4: 循环没有被执行,可能是没有数据,也可能是没有符合条件的记录。
使用 DELETE 语句来删除一条记录:
SY-SUBRC = 0: 找到一行并删除之,如果该表有不唯一主键,也就是有多条重复的记录,则只删除第一条记录。
SY-SUBRC = 4: 没有找到符合条件的记录,也没有删除。
使用 UPDATE 语句来更新一条记录:
SY-SUBRC = 0: 找到记录并更新,(如果有多条记录呢?)
SY-SUBRC = 4: 没有找到符合条件的记录,也没有更新。
常用代码
循环 LOOP AT 的使用
LOOP AT GT_AFVV. |
SELECT INTO 语句
SELECT SINGLE |
定义常量变量
CONSTANTS GV_FORMNAME TYPE STRING VALUE ‘ZPP_CP_N’ .
ABAP 程序参考菜单
ZPLM_ROUTING_PRINT
MAIN1
定义选择屏幕字段变量
RANGES: S_MATNR FOR MARC-MATNR.
定义常量变量
CONSTANTS GV_FORMNAME(20) TYPE C VALUE ‘ZPP_CP_N’.
权限检查
AUTHORITY-CHECK OBJECT ‘ZPLMWERKS’ FOR USER ‘123456' |
ALV 编辑字段
ALV 字段:W_FCAT-EDIT = ‘X’.
用户命令:
"保存修改后的内容 |
项目维护
http://www.cnblogs.com/landina/articles/1131746.html
选择字段赋值
S_MATNR-SIGN = 'I'. |
MOVE-CORRESPONDING
MOVE-CORRESPONDING 用于将一个结构中的数据赋予另一个结构中的对应字段,只能存一行数据。
所以使用时应该是如下形式:
TABLES: spfli.
DATA : yp_wa LIKE spfli ,
yp_tab LIKE TABLE OF spfli .
TYPES : BEGIN OF sp ,
sel TYPE c .
INCLUDE STRUCTURE spfli .
TYPES : END OF sp .
DATA : wa TYPE sp ,
tab TYPE TABLE OF sp .
LOOP AT yp_tab INTO yp_wa .
MOVE-CORRESPONDING yp_wa TO wa .
APPEND wa TO tab .
ENDLOOP .
其中 yptab / tab 为两个自定义内表,yp_wa 中只有字段名相同的才可以被赋予 wa 的工作区中。
————————————————
版权声明:本文为 CSDN 博主「心丨悦蜗牛在裸奔」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qinyuezhan/article/details/39546147
LOOP AT A. |
其中 A\B 为两个自定义内表,A 中只有字段名相同的才可以被赋予 B 的表头中。
TYPES: |
CONCATENATE
DATA: t1 TYPE c LENGTH 10 VALUE 'We', |
常用函数
更具姓名获取工厂信息
"定义变量 |
确认执行
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' |
回滚操作
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK' |
负号前置
CALL FUNCTION ‘CLOI_PUT_SIGN_IN_FRONT’
单位转换
CALL FUNCTIO'RSW_UNIT_CONVERSION' |
获取工艺路线
CALL FUNCTION 'CARO_ROUTING_READ' |
文档下载
CALL FUNCTION ‘ZSCMS_DOC_READ’
获取工艺路线
CALL FUNCTION ‘CARO_ROUTING_READ’
获取 PRT
CALL FUNCTION ‘CF_DB_PLFH_READ’
获取对象-描述
CALL FUNCTION 'SO_OBJECT_READ' |
获取长文本
CALL FUNCTION 'READ_TEXT' |
打印 SmartForm
CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME' |
SO_NAME_CONVERT
获取用户名
CALL FUNCTION ‘BAPI_USER_GETLIST’
CM_BT_PLMZ_COPY 复制组件分配
BAPI_GOODSMVT_CREATE
BAPI_GOODSMVT_CANCEL
T158G
SMARTFORMS 打印
"打印输出 |
获取内表的行数
1、循环内表,累加(可加條件過濾)
LOOP AT it_itab where XXXX.
g_lines2 = g_lines2 + 1.
ENDLOOP.
2.使用函数来计算内部表行数
g_lines3 = lines(it_itab ). 使用函数来计算内部表行数。
3.获得内部表的属性,将内部表行数赋值给 g_lines1 , g_lines1 为 I 型变量。
DESCRIBE TABLE it_itab LINES g_lines1 .
DESCRIBE TABLE lt_mat LINES lv_cont. |
上传文件到 PDF
"定义输出内表,字段必须是字符串类型 |
SAP 前缀补零去零函数
SAP 中有很多 Char 类型的字段,如果都是数字,且不满该字段长度,则会自动在前缀补足零,然后保存在 Table 中,而在显示的时候却不显示这些前缀零。比如料号字段,长度是 18 位,如果一个料号都是数字 824500089012,因为不满 18 位的长度,其在存入 Table 之前会在前缀补上零,直到补足 18 位。
但是,在一些报表和 RFC 中,这些动作却需要代码来完成。不过,还好 SAP 系统中提供了一些现成的函数供使用。
Function group: ALFA (ALPHAconversion)
Function Module:CONVERSION_EXIT_ALPHA_INPUT (前缀补零)
Function Module:CONVERSION_EXIT_ALPHA_OUTPUT’(前缀去零)
lv_kunnr = |{ kunnr ALPHA = IN }|. "加前导零 |
Function group: OMCV (MaterialNumber Conversion)
Function Module:CONVERSION_EXIT_MATN1_INPUT (料号前缀补零)
Function Module:CONVERSION_EXIT_MATN1_OUTPUT(料号前缀去零)
CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT' "料号前缀补零 |
SORT 语法小记
1. SORT
Table
2.SORT
Table
3.SORT
默认 Table
SORT 在用于给内表排序时,后面可以用 ASCENDING 和 DESCENDING 进行升序和降序排列,但是这其中用法很多,经过尝试后总结如下:
1.SORT LT_TAB BY WERKS LGORT EMAIL.
正常排序并使用默认 ASCENDING。
2.SORT LT_TAB BY WERKS LGORT EMAIL DESCENDING.
前两个字段默认升序排列,EMAIL 字段为降序排列。
3.SORT LT_TAB BY WERKS LGORT DESCENDING EMAIL.
第一第三字段为默认升序,第二字段为降序。由此可知写在字段后面的 ASC 和 DES 只能控制这一个字段。
4.SORT LT_TAB DESCENDING BY WERKS LGORT EMAIL.
写在表名后面的 ASC 和 DEC 可以控制所有字段的排序。
5.SORT LT_TAB ASCENDING BY WERKS DESCENDING LGORT EMAIL.
此时第一个字段降序,其他为升序。
6.SORT LT_TAB DESCENDING BY WERKS LGORT ASCENDING EMAIL.
此时整体为降序,但第二个字段为升序。
总结,内表后的 DEC 会控制整个表的排序,如果此时某字段后面有 DEC 或者 ASC,则在整个内表排序完成之后再进行字段排序。
FIELD-SYMBOLS
https://blog.csdn.net/champaignwolf/article/details/51208881
CONVERT_DATE_TO_INTERNAL
CALL FUNCTION 'CONVERT_DATE_TO_INTERNAL' |
ABAP LOOP AT 内表循环事件块
https://blog.csdn.net/tao273849019/article/details/109713868
读取销售订单长文本(Read_text)
http://www.baidusap.com/abap/function/281
RANGE 内表
RANGES 语句:用与选择表相同的结构创建内表,可使用 RANGES 语句,如下所示:
语法:RANGES
该语句创建选择表
RANGES 语句是下列语句的短格式:
DATA: BEGIN OF <seltab> OCCURS 10, |
用 RANGES 语句创建的选择表不是选择屏幕的一部分,它们在程序 用 RANGES 创建的内表与选择表结构相同,但功能不同。注意:sign 和 option 的值必须是大写 OPTION 运算符可以取以下值: LOW 是指当前值,或区间最小值(操作符是范围的话) 定义:将字符串 A、B 拼接给 字符串 C 方法如下: 显示: abs(n):绝对值 内表统计执行数据统计大致有下述几种方式: https://blog.csdn.net/syjf1976/article/details/118216146 &field()& 设置输出长度. REFRESH . CLEAR. FREE. 1、Deletes all table lines. 其输出为: 内表:如果使用有表头行的内表,CLEAR 仅清除表格工作区域。例如 clear gs-school 清除工作区。 CLEAR、REFRESH 语句都不会释放掉内表所占用的空间。 DELETE ADJACENT DUPLICATES FROM 的功能是删除邻近、相同的行,如果是为了把内表 itab 里部相同的行去掉,则应该对内表先按某个字段排序。 解决方案:把 SORT 语句改成 SORT itab_sf01 BY bukrs belnr gjahr augdt.即可。 delete adjacent duplicates from itab 和 delete adjacent duplicates from itab comparing all fields 区别: 解决方案:要对全部字段进行比较,如果全部字段相同则删除,即 注意: MODIFY table gt_intable FROM gs_intable. 对于内表修改命令,MODIFY 与 MODIFY table 的区别: MODIFY : 上面的办法太麻烦,还有很多限制,好吧,用 FS 来修改内表,又快又简单: 调试例子代码: 系统变量 SY-INDEX 与 SY-TABIX 是用来记录循环的次数或者索引的,不同的是 SY-INDEX 在 DO….ENDDO 中是有效的,而 SY-TABIX 在 LOOP….ENDLOOP 中及 READ 内表时获取相应的索引。 “to lower “to upper “to lower To Lower Case: Ctrl + L ABAP Development Tool 中的大小写转换快捷键 To Lower Case: Ctrl + Shift + Y Pretty Printer 中的大小写设置 Data Element 中的大小设置 调试器中的大小写转换 ———————————————— https://www.cnblogs.com/jiangzhengjun/p/4265187.html https://blog.csdn.net/reagon2008/article/details/134523403 用户拥有某种功能的权限,用户、角色、权限对象。 1.SU20 创建权限字段 START-OF-SELECTION. 2)s_carrid 为空。 首先说明一点:更新是异步的,更新是由 SAP 中 UPD1 和 UPD2 两个进程执行的: 所以说 COMMIT WORK 是异步的,为了使其同步,所有就有了 COMMIT WORK AND WAIT. 上面是最简单的区别,再有: 有时,在继续处理前需要确认对数据库表所作的更改。另一方面,在 永久存储之前可能需要 取消一些对 数据库表所作的更改。 在 ABAP/4 报表中,可 能有几个作 业联系在一 起形成作业 的逻辑单元 (LUW) 。通常,可 能要处理 LUW 中的所有动 如果要保证 数据库中当 前所作的更 改立即被确 认,那么, 就必须使用 COMMIT WORK 语句结束 LUW。COMMIT WORK 在程序代码 中标记了 LUW 结束并启动 更新任务( 参见 COMMIT WORK 处理 )。在 COMMIT WORK 语句以后, 对数据库所 作的所有更 改都不能再 取消。 要确认对数 据库表的更 改并使它们 不能再取消 ,请按如下 格式使用 COMMIT WORK 语句: COMMIT WORK [AND WAIT]. ROLLBACK WORK. 除了在上述情况下使用,还经常在财务报表开发时累加名称类似的变量,这些变量名是有序的,即存在数字规律,比如 HSL01,HSL02,HSL03 或 WORD01,WORD02 等等的情况,DO-VARYING 语法可以很好的对数据进行累加。 例如:需要将 FAGLFLEXT 表中的 hsl01,hsl02…hsl16 累加,对应财务 1-16 账期每月发生额。 https://cxymm.net/article/yannickdann/115396015 在 F-02 录入会计凭证时候,使用 bapi:BAPI_ACC_DOCUMENT_POST,如果要求导入的数据里增加税码 TAX_CODE 使用场景:需要统计求和 AT - ENDAT 块中的语句块使用这些行条件代表预定义的控制结构。用户可以使用它们处理内表中的控制断点,而不必使用编程分支和循环中所述的控制语句自己编程。 1、AT New 事件触发说明 2、使用 AT NEW f. 和 .AT END OF f 时需要注意: lt_data_out1: ———————————————— AT NEW F. AT END OF F. AT FIRST. AT LAST. 使用条件: 用指针的方式计算科目余额,对该科目的 10 个条目数,每个条目 16 个记账期间求和 循环累计 faglflext-HSLXX 值 ABAP 提供了新语法 COND/SWITCH,可以用来给变量赋值,代替 if 以及 case when,使得代码更加简洁。一般情况下,在我们主观意愿上来说,以下代码,看似是等价的。 但是其实不是,因为 COND when 只是定义了 lv_str 为空时候的赋值,那么变量本身就有值呢?答案是,会给一个空值。 这显然会与我们的初衷背道而驰,解决的方式也很简单,那就是定义好 COND 的所有条件。 这是一个比较小的点,但是往往这些不引人注目的点,会带来较大的 BUG。 ABAP 实现动态的表达式计算,可以使用函数 EVAL_FORMULA 实现,参考代码在下面;同时也可以考虑用类 CL_JAVA_SCRIPT 调用 js 功能实现。 方法 1: CATS_NUMERIC_INPUT_CHECK 1.如果 flag = 1 则是英文,否则是中文 场景描述:BDC 或者 BAPI 返回的系统消息需要组成完整的文本,显示出来供查错误原因. 方法二,调用函数 MESSAGE_TEXT_BUILD() 屏幕-》布局修改字段文本 在表维护程序 SM30 的使用过程中,经常需要自动填充和修改一些值,比较常规的做法是修改屏幕逻辑流,但是如果重新激活了 SM30,那么逻辑流就要重写,相对比较麻烦,之前接触过表维护程序中的‘事件’,经过研究得出以下方法: 背景:SM30 在维护自建表中,经常需要自动填充和修改一些值,比如创建者、创建日期、创建时间、修改者、修改日期、修改时间等。 https://blog.csdn.net/weixin_41641081/article/details/102663146 SM30 维护试图时可以导入 excel 数据 DDIF_DTEL_GET 取 DATA ELEMENT 文本描述 DDIF_FIELDINFO_GET 取表文本描述 原文链接:https://blog.csdn.net/nancyln9711/article/details/108520236 需求 MB5S 增加含税单价、含税金额、税率、税额: 参考:https://www.cnblogs.com/rainysblog/p/10949888.html https://blog.csdn.net/stone0823/article/details/117920412 批导的时候,数值类型的数据会自动变大,把批导结构中的数值字段定义为字符型,解决了这个问题。但是在做计算的时候要转换回数值类型。 TAXTYPE 自动”CN0”转换成”CN5”问题 https://blog.csdn.net/qq_30797051/article/details/124347700 对于前台标识页签下的税号相关数据,需要采用 BAPI_BUPA_TAX_ADD 进行维护类别、税号数据; 第三种: 保存,激活。 版权声明:本文为 CSDN 博主「逆风的鱼」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 事物代码:SNRO 无翻滚间隔是指如果编号达到最大,是否自动从头开始,勾上就不从头开始,而在获取编号的时候提示出错。我们这里应该打勾。 编号范围处理属于翻译问题,实际就是编号范围的事务码,如果指定这个事务码,就可以不需要通过 SNUM 或者 SNRO 的主屏幕然后输入编号范围对象的名字来维护这个编号范围,而可以输入事务码直接进入它的号码范围维护屏幕。 警告百分比是指如果编号使用到一定比例,就发出系统警告,提示管理人员增大范围或者进行历史数据归档,避免编号全部用完后影响正常业务,这里我们填写 95,就是 95%的时候提示。 主内存缓冲是指系统为了提高性能而预先取出一些编号放在应用服务器上,当程序取用编号时直接从应用服务器获取,而无需再读取数据库了。通常,如果对号码的连续性要求不高的情况下可以使用这种方式,而如果是财务凭证等要求连续的编号,则应该把主内存缓冲关闭,方法是通过菜单“编辑-设置缓存-无缓存”。 ASSOCIATION 是一种通过 Join 条件从多个表中获取数据的连接,但这些是“按需连接”,也就是说,它们只会在用户访问需要关联表的所需数据时被触发 (1)第一板斧:系统变量 sy-dbcnt (2)第二板斧:select count (*) (3)第三板斧:describe table XXX lines XXX https://www.cnblogs.com/mingdashu/p/5099283.html 使用函数 RP_CALC_DATE_IN_INTERVAL 进行日期的年月日的加减 使用 cl_trex_json_serializer 类来将结构转为 JSON 格式,不建议使用: 使用 cl_trex_json_deserializer 来实现 JSON 的解析: 这两个对象返回的的 JSON 是{key: “value”},而规范的 JSON 应该是{“key”: “value”}的格式。如果使用它们来解析{“key”: “value”}的话,会因为双引号的问题导致出现异常,解析失败。在这种情况下,推荐使用/UI2/CL_JSON: https://blog.csdn.net/weixin_42959207/article/details/90476922 https://blog.csdn.net/sapliumeng/article/details/109652281 1、SO 没有创建过任何后续凭证时,可以直接删除:VA02-》输入单号-》进入后选择菜单栏“销售订单”-》删除。 这里提供一个批量 reject SO 的方法: 当遇到字符串拼接通过符号串联起来的时候,未尾会多出一个符号,此时需要将这个符号给删除,则需要采用 SE24 增强类:CL_CTMENU 方法:HIDE_FUNCTIONS 或 DISABLE_FUNCTIONS https://blog.csdn.net/qq_30797051/article/details/122820144 https://blog.csdn.net/wangjolly/article/details/80075531 使用 single : 在 where 语句中如果 使用了全部的 key 字段 可以使用 single 使用 up to 1 rows : 在 where 语句中如果 使用了部分或没有使用 key 字段 ,则只能使用 up to 1 rows 例题 : 表 kssk,其中 MANDT、OBJEK、MAFID、KLART、CLINT、ADZHL 为 key 字段。 使用 up to 1 rows : https://blog.csdn.net/XLevon/article/details/127265747 这里可以通过把释放的请求号取消释放来实现,如果请求号里只是对程序做修改可以这么做,但是对于有新增表、元素、结构等等在这里不建议这么做。 update E070 set TRSTATUS = ‘D’ where TRKORR = ‘ED1K913540’ –请求号 SAP 副本传输的主要原理是:仅释放你传输请求的子请求,然后把你的这个子请求,包到另外一个主请求下。这个主请求,也就是我们所说的副本请求了。然后,我们把这个副本请求进行传输至目标系统。这样就在不释放主请求的情况下,把修改内容直接传输至这目标系统。就是副本传输的主要原理。 https://blog.csdn.net/lmf496891416/article/details/111317377 1.格式: LOOP AT 内表 INTO DATA(工作区) GROUP BY ( 字段 = 工作区-字段 LOOP AT GROUP <组> ASSIGNING FIELD-SYMBOL(<指针>). 2.简而言之:就是第一个 loop 循环是把内表进行分组,第二 loop 循环是把组里的数据循环读出来进行修改判断等操作。 3.可以替代 AT END OF /AT NEW OF。 4.具体实例-复制就能用 https://blog.csdn.net/weixin_44911062/article/details/108650067 REDUCE 语句相当于是一个 LOOP,对内表的数据进行处理,累加汇总在一个字段内,并不会提高运行效率,在数据量小的时候使用,大数据量的累计还是推荐 GROUP BY。 客户、供应商:CONVERSION_EXIT_ALPHA_INPUT/OUTPUT; 物料:CONVERSION_EXIT_MATN1_INPUT/OUTPUT; 物料单位: https://www.cnblogs.com/hhelibeb/p/5802398.html {rep|(name)}:使用 rep 静态地指定一个程序,或者使用 name 动态地指定 1.ole 中如何保存和退出。 call method of sheetname ‘saveas’ exporting #1 = filepath #2 =1. call method of applicationname ‘quit’. 2.给 sheet 重命名。 call method of sheetname ‘name’ = ‘sheetname’. 3.创建 application. call method of XXX ‘excel.application’. 4.设置 XXX 的显示模式。 set property of XXX ‘visible’ = 1. 前台运行。为 0 时表示为后台运行。 5.创建 workbook. CALL METHOD OF EXCEL ‘WORKBOOKS’ = WORKBOOK . call method of workbook ‘ADD’. 6.在一个 workbook 中添加一个 worksheet. CALL METHOD OF applicationname ‘sheets’ = worksheet. call method of worksheet ‘Add’ . 7.给单元格赋值。 CaLL METHOD OF EXCEL ‘CELLS’ = CELL EXPORTING #1 = 2 #2 = 2. Set PROPERTY OF CELL ‘value’ = xxxx. 8.指定要被操作的 sheet. CALL METHOD OF applicationname ‘Worksheets’ = SHEET EXPORTING #1 = ‘sheet3’. 这里 sheet3 为要操作的 sheet 的名字。 call method of sheet ‘Activate ‘. 9.指定操作的单元格的范围。 CALL METHOD OF applicationname ‘Range’ = range EXPORTING #1 = ‘B2’ #2 = ‘c2’. 11.单元格内部属性的操作. call method of cell ‘INTERIOR’ = int. set property of int ‘ColorIndex’ = color. 颜色 set property of int ‘Pattern’ = pattern. 12.单元格内字体的操作. call method of CELL ‘FONT’ = font. set property of font ‘BOLD’ = bold. set property of font ‘SIZE’ = size. 13.边框的操作. call method of CELL ‘BORDERS’ = BORDERS EXPORTING #1 = ‘1’. 1-left 2-right 3-top 4-bottom set property of borders ‘Linestyle’ = plinestyle . set property of borders ‘Weight’ = pweight . free object borders. 在此之前应该指定 range. 14.复制与粘贴. call method of sheet ‘copy’. call method of sheet ‘paste’. 15.一点注意。 在操作 sheet 时,默认为上次操作的 sheet.如果想更换,参考 8。 16.一个问题。有时输入数据如 111111111111111111,会显示为 1E+17。 解决办法: CALL METHOD OF h_excel ‘COLUMNS’ = columnObj EXPORTING #1 = 6. “the column number SET PROPERTY OF columnObj ‘ColumnWidth’ = 10. SET PROPERTY OF columnObj ‘NumberFormat’ = ‘@’. 17.打开一个 workbook. call METHOD OF workbook ‘Open’ EXPORTING #1 = filename+path. 所有的操作方法都可以在 sell—-表 oleload 中 查询到。 执行宏。 CALL METHOD OF EXCEL ‘RUN’ EXPORTING #1 = ‘ZMACRO2’. 20.清除 range 内容 CALL METHOD OF EXCEL ‘Range’ = RANGE EXPORTING #1 = tar_cell #2 = tar_cell. call METHOD of RANGE ‘ClearContents’. 21.合并单元格 CALL METHOD OF EXCEL ‘Range’ = RANGE EXPORTING #1 = sor_cell #2 = tar_cell. SET PROPERTY OF RANGE ‘MergeCells’ = 1. 22.缩小字体填充 SET PROPERTY OF range ‘ShrinkToFit’ = 0 . note: 为 0 时取消缩小字体填充,为 1 时设置缩小字体填充。 note: 1.与 ole 相关的关键字存储在表 oleload 中。 https://blog.csdn.net/weixin_41641081/article/details/95036315 1.问题描述 2.原因分析 3.解决办法 技术解决办法 ———————————————— 源代码缺少了 Sheet Name 读取的部分; 增强后的数据结构 ZALSMEX_TABLINE 实现原理: 系统环境要求:INNER J0IN 内表是 ABAP 7.50+ 新特性。 INNER JOIN 激活警告消息 一个 SELECT 语句中不能 INNER JOIN 两个内表,INNER JOIN ITAB 前, ITAB 需要去重; 先弄清 External Session 和 Internal Session 区别: Internal Session: SAP memory 类似于全局变量,用于 Externalsession 间的通信,不同的 externalsession 都可以访问,当退出 userlogon session 时将清空 SAPmemory(不同 user 对应的 SAPmemory 不同)。 原文链接:https://blog.csdn.net/SAPmatinal/article/details/105706290 https://www.cnblogs.com/BinGeneral/p/18078759 SAP 内存(SAP Memory)和 ABAP 内存(ABAP Memory),两者都可用于编程中的数据传递,将数据通过 ID 进行绑定,之后在其他程序中通过 ID 获取。 语法区别: 2、ABAP 内存通过 EXPORT/IMPORT,来抛接内存值,如: 作用范围区别: 理解了这三个概念,现在回到主题,上文的 ABAP 内存是在 Internal Session 之间进行数据传递,而 SAP 内存是在 External Session 之间进行数据传递,当然也可以传数据到 Internal Session 中。 标准 SAP 内存 ID: ABAP 管理数据库过程是 SAP HANA 上的 ABAP 开发环境中用于 ABAP 代码优化的推荐模式之一。
该程序由下列语句启动:SUBMIT .
表可以在调用程序中用 RANGES 创建。
下面介绍以下 range 中四个参数的具体取值:
SIGN 可以取以下两种值:INCLUED 和 EXCLUDE
sign = ‘I’ ‘I’ 表示包含:LOW 、HIGH 的值
sign = ‘E’ ‘E’ 表示排除:LOW、HIGH 的值
‘EQ’ , ‘NE’ “等于,不等于 Equal ,Not Equal
‘GT’ , ‘LT’ “大于,小于 Greater Than ,Less Than
‘GE’ , ‘LE’ “大于等于,小于等于 Greater Than or Equal ,Less Than or Equal
‘CP’ , ‘NP’ “参考判断格式,如”ABC*“,NP 排除参考格式
‘BT’ , ‘NB’ “位于,不位于,功能与 Between 和 Not Between 一样。
LOW:LOW 的数据类型与数据库表的列类型相同,该表与选择标准相连接。
如果 Option 运算符不为 ‘BT’ 或 ‘NB’,LOW 的内容定义单值选择,它与 OPTION 中的运算符相结合,为数据库选择指定了条件。
如果 Option 运算符为 ‘BT’ 或 ‘NB’,并且 HIGH 不为空, LOW 和 HIGH 中的内容为间隔选择指定上界和下界,与 OPTION 中的运算符相结合,该间隔为数据库选择指定了条件。
HIGH 是指区间最大值
如果 Option 运算符为 ‘BT’ 或 ‘NB’,HIGH 的值才会生效,运算符不是 Between 和 Not Between 时,high 有值也不会参与计算字符串拼接的三种方法
DATA: A TYPE CHAR12 VALUE ‘A’.
DATA: B TYPE CHAR12 VALUE ‘B’.
DATA: C TYPE CHAR12.
方法一: CONCATENATE A B INTO C .
方法二: C = A && B.
方法三: C = |{ A }{ B }|.
START-OF-SELECTION.
WRITE: / C.
————————————————
版权声明:本文为 CSDN 博主「AllenFlyer」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_49707237/article/details/125164813ABAP 运算符
sign(n):符号值
ceil(n):向下取整
floor(n):向上取整
trunc(n):只取整数部分
frac(n):只取小数部分
strlen(n):取长度
lines(arg):取行数内表汇总数据的方式
COLLECT 语句实现
AT NEW 语句实现
LOOP AT GROUP 语句实现
READ 哈希表语句实现. SELECT SUM 也能汇总内表*&---------------------------------------------------------------------*
*& Report ZTS_ITAB_SUM
*&---------------------------------------------------------------------*
*&测试内表统计的几种方式
*&---------------------------------------------------------------------*
REPORT zts_itab_sum.
DATA: BEGIN OF lw_data,
matnr TYPE matnr,
werks TYPE werks_d,
menge TYPE menge_d,
END OF lw_data.
DATA: lt_data LIKE TABLE OF lw_data.
DATA: BEGIN OF lw_sum,
matnr TYPE matnr,
werks TYPE werks_d,
menge TYPE menge_d,
END OF lw_sum.
DATA: lt_sum LIKE TABLE OF lw_sum.
START-OF-SELECTION.
*准备数据
lt_data = VALUE
( matnr = 'M1' werks = 'W1' menge = 10 )
( matnr = 'M2' werks = 'W1' menge = 20 )
( matnr = 'M1' werks = 'W2' menge = 30 )
( matnr = 'M2' werks = 'W2' menge = 40 )
).
*方式一:通过COLLECT 语句汇总.
**该语句的局限性: 目标内表中所有字段区分未关键字和指标(数字型).系统底层会创建临时哈希表,解决汇总的性能问题
**该方式另外的局限是: 不参与统计的字段必须清空.
REFRESH lt_sum.
LOOP AT lt_data INTO lw_data.
CLEAR lw_sum.
lw_sum-matnr = lw_data-matnr.
lw_sum-werks = ''. "不能附加第一行或最后一行地点
lw_sum-menge = lw_data-menge.
COLLECT lw_sum INTO lt_sum.
ENDLOOP.
*方式二: 通过AT NEW 语句实现
**该语句的局限性: 参与统计的字段必须是内表前面的字段,并且需要实现排序
*如果统计结果中的地点需要放第一行或最后一行的地点, 可以通过特定逻辑实现
DATA: lw_data_help LIKE lw_data.
REFRESH lt_sum.
SORT lt_data BY matnr werks.
LOOP AT lt_data INTO lw_data.
lw_data_help = lw_data.
AT NEW matnr.
CLEAR lw_sum.
lw_sum-matnr = lw_data-matnr.
lw_sum-werks = lw_data_help-werks. "使用第一个地点放到统计表中
ENDAT.
lw_sum-menge = lw_sum-menge + lw_data-menge.
AT END OF matnr.
lw_sum-werks = lw_data_help-werks. "使用最后一个地点放到统计表中
APPEND lw_sum TO lt_sum.
ENDAT.
ENDLOOP.
*方式三: 通过LOOP AT GROUP 实现
*该语句无需排序,字段无需作为内表前面的字段, 但是性能比AT NEW 方式差.且无关字段只能使用第一行的
* LOOP AT LT_DATA INTO DATA(LW_GP) GROUP BY ( MATNR = LW_GP-MATNR WERKS = LW_GP-WERKS ). "多关键字情况
REFRESH lt_sum.
LOOP AT lt_data INTO DATA(lw_gp) GROUP BY ( matnr = lw_gp-matnr ).
CLEAR lw_sum.
lw_sum-matnr = lw_gp-matnr.
lw_sum-werks = lw_gp-werks. "只能使用第一个地点放到统计表中
LOOP AT GROUP lw_gp INTO lw_data.
lw_sum-menge = lw_sum-menge + lw_data-menge.
ENDLOOP.
APPEND lw_sum TO lt_sum.
ENDLOOP.
*方式四: 通过READ 哈希表实现
DATA: lt_sum_hs LIKE HASHED TABLE OF lw_sum WITH UNIQUE KEY matnr .
refresh lt_sum_hs.
LOOP AT lt_data INTO lw_data.
READ TABLE lt_sum_hs ASSIGNING FIELD-SYMBOL(<fs_sum>) WITH TABLE KEY matnr = lw_data-matnr.
IF sy-subrc <> 0.
CLEAR lw_sum.
lw_sum-matnr = lw_data-matnr.
lw_sum-werks = lw_data-werks. "使用第一行地点放到汇总表中
INSERT lw_sum INTO TABLE lt_sum_hs ASSIGNING <fs_sum>.
ENDIF.
IF <fs_sum> IS ASSIGNED.
<fs_sum>-menge = <fs_sum>-menge + lw_data-menge.
<fs_sum>-werks = lw_data-werks. "使用最后一行地点放到汇总表.
ENDIF.
ENDLOOP.SMARTFORMS 数量金额输出格式设置说明
&field(*)& 如果该字段类型是 abap 数据字典里定义的类型,系统将按照字典定义的长度设置输出长度
&field(S)& 禁止输出符号位
&field(<)& 符号位显示在数据的左边
&field(.)& 设置显示小数的位数
&field(E)& 设置为科学标示法
&field(T)& 禁止千分位的显示(适用于: DEC, CURR, INT 和 QUAN 几种数据类型).
&field(Z)& 禁止数字前导 0 的显示
&field(I)& 禁止显示空值
&field(K)& 禁止类型系统按数据字典定义的转换函数进行输出转换
&field(R)& 右对齐(只有在定义了输出长度时才有效)
&field(F)& 用指定的字符替换左边的空格.
&field(L)& 将日期转换为本地显示格式,使用 JDAT 指定的格式
&field(C)& 该设置效果和 ABAP 的 CONDENSE 语句相同.CLEAR/REFRESH/FREE 用法
该语句将内表重置为填充它以前的状态。这意味着表格将不包含任何行。如果使用没有表格工作区域的内表,可以使用 CLEAR 语句代替 REFRESH 语句
1、Deletes all table lines.
2、Storage space is not released.
3、Paging is released.
4、Header line remains unchanged.
如果使用有表头行的内表,CLEAR 仅清除表格工作区域。要重置整个内表而不清除表格工作区域,使用 REFRESH 语句或 CLEAR 语句 CLEAR[].内表名称之后的方括号指内表体。使用 REFRESH 或 CLEAR 初始化内表后,系统保持在内存中保留的空间 。可以用 FREE 语句释放内存
1、Initialises the header line.
2、Internal table lines remain unchanged.
也可以使用 FREE 语句重置内表并直接释放其内存, 而不必先使用 REFRESH 或 CLEAR。 与 REFRESH 一样,FREE 在表格体上 而不在表格工作区域上工作。
在 FREE 语句之后可以再次定位内表。这样系统就再次保留内存空间。
2、Storage space is released.
3、Header line remains unchanged.DATA: BEGIN OF LINE,
COL1,
COL2,
END OF LINE.
DATA ITAB LIKE LINE OCCURS 10.
LINE-COL1 = 'A'.
LINE-COL2 = 'B'.
APPEND LINE TO ITAB.
REFRESH ITAB.
IF ITAB IS INITIAL.
WRITE 'ITAB is empty'.
FREE ITAB.
ENDIF.
ITAB is empty.
在该程序中 ,先对内表 ITAB 进行填充,然后再用 REFRESH 初始化。在 IF 语句中,用 带 IS INITIAL 参数的逻辑 表达式检查 ITAB 是否为空。 如果空着,则释放内存 。
要重置整个内表而不清除表格工作区域,使用 REFRESH 语句或 CLEAR 语句 CLEAR
REFRESH 加不加中括号都是只清内表,另外 REFRESH 是专为清内表的,不能清基本类型变量,但 CLEAR 可以清基本类型变量。例如 clear gs-school[] 等价于 refresh gs-school 等价于 refresh gs-school[]。
如果想初始化内表的同时还要释放所占用的空间,请使用:FREE DELETE ADJACENT DUPLICATES FROM
排序也是有讲究的,排序语句使用 SORT itab BY comp1, comp2,…, compi ASCENDING|DESCENDING
通常我们会按一个字段进行排序,但是这有有可能相同的行排序不到一块去:
SORT itab_sf01 BY bukrs.
由于排序时只按 BUKRS 字段,所以第 1 行和第 3 行、第 2 行和第 4 行内容相同,但没有相邻,所以执行 DLETE ADJACENT DUPLICATES FROM itab_sf01 也没有达到预期目的。
————————————————
版权声明:本文为 CSDN 博主「JellyLin_SAP」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jellylin_sap/article/details/7599043
前者相邻两行数据,如果除金额字段以外的其他字段都相同,则去重复删除其中一行;
后者相邻两行数据,如果所有对应的字段都相同(包含金额字段),则去重复删除其中一行。
DELETE ADJACENT DUPLICATE FROM itab_sf02 COMPARING ALL FIELDS.
如果没有 COMPARING 选项,则标准关键字段 的内容必须相同(默认的内表关键字有 F、I 和 P 型),金额型不算,所以除金额型外其他相同的都被咔嚓(删除)了。COLLECT 语句也有类似的功能,除了金额型字段外其他的字段内容相同,则去掉相同行并把相同行的金额值累加到留下来的一行。内表修改 MODIFY 和 MODIFY table 的区别
MODIFY gt_intable FROM gs_intable.
MODIFY table :
1、是出现在 LOOP 外对内表的修改;
2、有一个前提是该内表的定义一定要有主键,如果没有,该语句不能成功。
3、排序表和散列表的主表键是只读的,不能修改。
4、sy-tabix 系统变量无关。
5、利用工作区只能修改一行数据。MODIFY table gt_intable FROM gs_intable.
1、没有主键的内表可以使用该语句。MODIFY gt_intable FROM gs_intable
2、如果不带 WHERE 条件,只能出现在 LOOP 中。
3、带 WHERE 条件,在 LOOP 外可以处理满足条件的多条数据。
MODIFY gt_intable FROM gs_intable TRANSPORTING a WHERE id = 10.LOOP AT gt_alv ASSIGNING FIELD-SYMBOL(<fs_alv>) WHERE SELXXX eq 'X' .
<fs_alv>-LES_DEL = 'X'."内表更新
UPDATE ZTSD0010 SET LES_DEL = 'X' WHERE ID = <fs_alv>-ID. "透明表更新
ENDLOOP.
COMMIT WORK AND WAIT.REPORT ZJAMES020.
TYPES: BEGIN OF ty_intable,
id TYPE i ,
a(10),
END OF ty_intable.
DATA gt_intable TYPE TABLE OF ty_intable." WITH NON-UNIQUE KEY id.
DATA gs_intable TYPE ty_intable.
DO 500 TIMES.
gs_intable-id = 10."gs_intable-id + 1.
gs_intable-a = 'something'.
APPEND gs_intable TO gt_intable.
ENDDO.
- _LOOP AT gt_intable INTO gs_intable._
-
- IF gs_intable-id = 10.
-
- gs_intable-a = 'xxxxx'.
-
- " MODIFY table gt_intable FROM gs_intable.
-
- ENDIF.\*
- \*ENDLOOP.
gs_intable-id = 10.
gs_intable-a = 'xxxxx'.
MODIFY gt_intable FROM gs_intable TRANSPORTING a WHERE id = 10.
"MODIFY gt_intable FROM gs_intable.
cl_demo_output=>display( gt_intable ).系统变量 SY-INDEX 与 SY-TABIX
ABAP 中字符大小写转换问题
DATA lv_text TYPE string value Barbcbdbarb.
“to upper
TRANSLATE lv_text TO UPPER CASE.
TRANSLATE lv_text TO LOWER CASE.
lv_text = to_upper( lv_text ).
lv_text = to_lower( lv_text ).
SE80 中大小写转换的快捷键
To Upper Case: Ctrl + U
To Upper Case: Ctrl + Shift + X
默认情况下,Char 类型的 Domain 会是大写的,如需要让其允许小写,勾选 Lowercase。
例如在 SE37 中,默认情况下 Case-sensitive 是没有勾选的,此时输入的小写字符会自动变成大写;如需要输入小写,请勾选 case-sensitive。
版权声明:本文为 CSDN 博主「SAP-nkGavin」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/nkGavinGuo/article/details/109749139SELECT-OPTIONS
权限对象
用户可以有多种角色,角色可以有多种权限对象。
整体步骤:
SU20: 维护权限字段
SU21: 创建权限对象,分配权限字段
SU24: 关联程序和自建权限对象(标准 TCODE 会默认存在标准权限对象)
PFCG: 创建角色
SU01: 给用户分配角色。
2.SU21 创建权限对象。
TABLES scarr.
DATA gs_scarr TYPE scarr.
DATA gt_scarr TYPE STANDARD TABLE OF scarr.
SELECT-OPTIONS s_carrid FOR scarr-carrid .
分两种情况讨论:
1)s_carrid 有值,需要将不符合权限的删除掉
IF s_carrid IS NOT INITIAL.
LOOP AT s_carrid.
AUTHORITY-CHECK OBJECT ‘ZCARRID’
ID ‘CARRID’ FIELD s_carrid-low.
IF sy-subrc <> 0.
DELETE s_carrid.
ENDIF.
ENDLOOP.
ENDIF.
SELECT * INTO TABLE gt_scarr FROM scarr WHERE carrid IN s_carrid.
LOOP AT gt_scarr INTO gs_scarr.
IF s_carrid IS INITIAL.
AUTHORITY-CHECK OBJECT ‘ZCARRID’
ID ‘CARRID’ FIELD gs_scarr-carrid.
IF sy-subrc <> 0.
* Implement a suitable exception handling here
ELSE.
WRITE : / gs_scarr.
ENDIF.
ELSE.
WRITE : / gs_scarr.
ENDIF.
ENDLOOP.COMMIT WORK && COMMIT WORK AND WAIT && ROLLBACK WORK
UPD1 先执行,主要是用于数据库表的更新,比如说写表
UPD2 后执行,主要是用于一些数据的收集统计等的更新,比如说为 BW 收集一下数据等等
同时这个是可以在 SM13 看到的,如果看到日志中 UPD1 成功,UPD2 失败,如有 BW 的取数,那肯定会丢数据的。
对于 COMMIT WORK AND WAIT 来说,是可以判断是否更新成功的,SY-SUBRC NE 0 就是有问题的。
由于系统中 COMMIT WORK 的数量是有限的,比如说我们系统是 4000 个,同时只能提交 4000 个更新进程,对于 COMMIT WORK 来说,执行完就释放了,可以为后面的 COMMIT WLRK 继续使用;而对于 COMMIT WORK AND WAIT 是要执行完才释放的,所以对于没有必要同步更新的,也尽快使用异步,使得资源得到释放。
要确认对数 据库表的更 改,请使用 COMMIT WORK 语句。要在 永久存储之 前取消一些 更改,请使 用 ROLLBACK WORK 语句。
这些语句在 对话编程( 即 SAP 事务、数据 库事务、打 开或关闭屏 幕等等,有 关对话编程 的概述,参 见编写 ABAP/4 事务)中起着 十分重要的 作用。在本 主题中,您 将了解到如 何在 ABAP/4 报表中使用 COMMIT WORK 和 ROLLBACK WORK( 参见编写 ABAP/4 报表)。
作,或什么 也不要处理 。假设 LUW 中包含了将 五行插入到 数据库表中 的进程。如 果事务成功 ,所有五行 都将存储在 数据库表中 (这包含一 个更新请求 和一个数据 库事务)。 在显示新屏 幕之前,数 据库事务将 自动结束( ABAP/4 报表的结束 )。在 ABAP/4 报表中不能 以任何方式 影响该进程
但是,如果 在 LUW 中出现了错 误,就必须 取消已经执 行的部分。 这意味着当 前没有任何 插入的行能 永久地保存 在数据库中 。要撤销当 前 LUW 对数据库的 更改,请使 用 ROLLBACK WORK, 它将取消前 一次数据库 提交后的所 有更改。
如果使用 AND WAIT 选项,那么 在程序继续 执行以前, 它要等到更 新任务的结 束。如果更 新是成功的 ,SY-SUBRC
就设置为 0。如果 SY-SUBRC 返回一个非 零值,就没 有成功的存 储所作的更 改。
要在保存之 前取消对数 据库表所作 的更改,请 按下列形式 使用 ROLLBACK WORK 语句:
如果对更改 的取消是成 功的,SY-SUBRC 就设置为 0。如果 SY-SUBRC 返回一个非 零值,就没 有成功地取 消所作的更 改
使用 COMMIT WORK 和 ROLLBACK WORK 语句的结果 是将丢失所 有的数据库 光标。因此 ,在 SELECT
循环中或在 处理 SQL 语句之前不 允许使用这 些语句。Do varying
自动计算税金 CALCULATE_TAX_FROM_GROSSAMOUNT
那么如何根据税码计算税金呢:
使用函数:CALCULATE_TAX_FROM_GROSSAMOUNT
————————————————
版权声明:本文为 CSDN 博主「weixin_43885987」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43885987/article/details/113522888AT NEW、AT LAST、AT FIRST、AT END OF 使用
其实在 loop…endloop 中间,有个 AT ,<…>,ENDAT 循环. 其中的包括: FRIST, LAST, NEW , END OF.这些可以用来进行内表中按某个字段进行分组统计.
FIRST 内表的第一行
LAST 内表的最后一 行
NEW 行组的开头,与 字段 和 剩余字段中 的内容相同
END Of 行组的结尾,与 字段 和 剩余字段中 的内容相同
在 AT - ENDAT 语句块中,工作区域没有用当前表格行进行填充。初始化所有不是标准关键字部件的字段( 参见标识表格行 )。对于行 条件 FIRST 和 LAST, 系统用星号 () 改写所有标 准关键字段 。对于行条件 NEW 和 END OF ,系统用星号 () 改写所有出现在工作区域中指定字段右边的标准关键字段。 用户可根据自己的需求 在 AT - ENDAT 语句块中填 充工作区域 。
如 AT New f.
f 是内表的一个字段,当 f 字段或者 f 字段左边的字段内容发生变化是该事件后面的语句都会执行。
使用 at new, at first, at last, at end of 的时候要注意:
loop 的时候不能加条件;at 和 endat 之间不能使用 loop into 的 working area。
手动实现 atnew, at end of 的时候,需要注意,容易出错,尤其是在 at end of 的时候。TYPES: BEGIN OF companies_type,
name(30),
product(20),
sales TYPE i,
END OF companies_type.
DATA: companies TYPE STANDARD TABLE OF companies_type WITH NON-UNIQUE DEFAULT KEY INITIAL SIZE 20,
wa_companies TYPE companies_type.
LOOP AT companies INTO wa_companies.
AT NEW product.
NEW-PAGE.
WRITE: / wa_companies-name, wa_companies-product.
ENDAT.
WRITE: / wa_companies-product, wa_companies-sales.
AT END OF name.
SUM.
WRITE: / wa_companies-name, wa_companies-sales.
ENDAT.
ENDLOOP.
DATA: BEGIN OF th_lifnr,
lifnr TYPE lfa1-lifnr,
item TYPE c,
END OF th_lifnr.
DATA: td_lifnr LIKE TABLE OF th_lifnr.
SELECT lifnr FROM ekko INTO TABLE td_lifnr
WHERE ebeln > 4500006374 AND ebeln < 4500006390.
SORT td_lifnr ASCENDING BY lifnr.
LOOP AT td_lifnr INTO th_lifnr.
AT NEW lifnr.
WRITE:/10 th_lifnr-lifnr.
WRITE:/ 'the next is NEW lifnr.'.
ENDAT.
ENDLOOP.DATA: wa_data TYPE ty_data,
lt_data TYPE TABLE OF ty_data,
lt_data_out1 TYPE TABLE OF ty_data,
lt_data_out2 TYPE TABLE OF ty_data,
lt_data_out3 TYPE TABLE OF ty_data.
lt_data = VALUE
( znum = 'CC' zcount = 1 matnr = '58M2221110' kwmeng = '100.000' zchar = 'JJ' )
( znum = 'CC' zcount = 2 matnr = '58M2221110' kwmeng = '200.000' zchar = 'JJ' )
( znum = 'CC' zcount = 1 matnr = '58M2221110' kwmeng = '300.000' zchar = 'JJ' )
( znum = 'CC' zcount = 2 matnr = '58M2221110' kwmeng = '400.000' zchar = 'JC' )
( znum = 'CC' zcount = 1 matnr = '58M2221110' kwmeng = '100.000' zchar = 'JC' )
( znum = 'CC' zcount = 2 matnr = '58M2221111' kwmeng = '200.000' zchar = 'JC' )
( znum = 'CC' zcount = 1 matnr = '58M2221111' kwmeng = '300.000' zchar = 'JJ' )
( znum = 'CC' zcount = 2 matnr = '58M2221111' kwmeng = '400.000' zchar = 'JJ' ) ).
SORT lt_data BY znum zcount matnr DESCENDING.
LOOP AT lt_data INTO wa_data.
AT NEW matnr.
APPEND wa_data TO lt_data_out1.
ENDAT.
ENDLOOP.
LOOP AT lt_data INTO wa_data WHERE znum = 'CC' AND matnr = '58M2221110'.
AT NEW matnr.
APPEND wa_data TO lt_data_out2.
ENDAT.
ENDLOOP.
LOOP AT lt_data INTO wa_data WHERE znum = 'CC' AND zchar = 'JJ'.
AT NEW matnr.
APPEND wa_data TO lt_data_out3.
ENDAT.
ENDLOOP.
cl_demo_output=>display( lt_data_out1 ).
cl_demo_output=>display( lt_data_out2 ).
cl_demo_output=>display( lt_data_out3 ).
ZNUM MATNER KWMENG ZCHAR
CC 58M2221110 0 *****
CC 58M2221111 0 *****
版权声明:本文为 CSDN 博主「酒剑仙 abc」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fengxin_/article/details/10701990
代码段..
ENDAT.
F 是内表的一个字段,当内表中 F 字段以及 F 左边的任何字段内容发生变化时,执行其中的代码段。
代码段..
ENDAT.
当 F 字段以及 F 左边字段内容即将发生变化时,执行代码段。
代码段..
ENDAT.
内表的第一行时,执行。
代码段..
ENDAT.
内表的最后一行时执行。
一般在 loop 中使用;
要提前对内表进行排序 sort;
Loop 不能加 where 条件;
在 at 和 endat 之间不能再使用 loop 语法。ABAP 指针的 6 种用法
*&---------------------------------------------------------------------*
*& Report ZLQT98
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZLQT98.
DATA LV_NUMB TYPE I .
"指针的6种用法
SELECT RYEAR ,RACCT , RBUKRS , TSLVT ,
TSL01 ,TSL02 , TSL03 , TSL04 ,
TSL05 ,TSL06 , TSL07 , TSL08 ,
TSL09 ,TSL10 , TSL11 , TSL12 ,
TSL13 ,TSL14 , TSL15 , TSL16
FROM FAGLFLEXT
WHERE RBUKRS = '1000'
AND RYEAR = '2020'
AND RACCT = '8035000001'
INTO TABLE @DATA(LT_FAG)
UP TO 10 ROWS.
""""""如果没有取到数据先加数据,加数据这段也使用指针,可以先看后面的代码再看这段
IF LT_FAG[] IS INITIAL. "
DO 10 TIMES.
APPEND INITIAL LINE TO LT_FAG ASSIGNING FIELD-SYMBOL(<FS_FAG>) .
DO 20 TIMES.
ASSIGN COMPONENT SY-INDEX OF STRUCTURE <FS_FAG> TO FIELD-SYMBOL(<FS_VIUE>) .
CASE SY-INDEX.
WHEN 1.
<FS_VIUE> = '2020'.
WHEN 2.
<FS_VIUE> = '8035000001'.
WHEN 3.
<FS_VIUE> = '1000'.
WHEN 4.
<FS_VIUE> = '0'.
WHEN OTHERS.
<FS_VIUE> = <FS_VIUE> + LV_NUMB .
ENDCASE.
LV_NUMB = LV_NUMB + 1 .
ENDDO.
ENDDO.
ENDIF.
"""""""
"1.READ语法中分配指针
READ TABLE LT_FAG ASSIGNING FIELD-SYMBOL(<FS_FAG1>) INDEX 1.
"2.静态分配。
ASSIGN <FS_FAG1>-TSL01 TO FIELD-SYMBOL(<FS_TSL01>) .
DATA LV_NUM TYPE N LENGTH 2 VALUE 1.
DATA LV_CHA TYPE C LENGTH 20 VALUE '<FS_FAG2>-TSL' .
DATA LV_CHA2 TYPE C LENGTH 20 VALUE 'TSL' .
DATA LV_SUM TYPE DMBTR .
"3.LOOP循环里面分配指针。
LOOP AT LT_FAG ASSIGNING FIELD-SYMBOL(<FS_FAG2>).
"4.1.动态分配,循环累计工作区中的 HSL01-HSL16 。将字符串组成字段名直接分配给指针。(字符串中带工作区类型)
DO 16 TIMES.
DATA(LV_FIED) = LV_CHA && LV_NUM .
ASSIGN (LV_FIED) TO FIELD-SYMBOL(<FS_TSL>) .
IF <FS_TSL> <> 0.
LV_SUM = LV_SUM + <FS_TSL> .
ENDIF.
LV_NUM = LV_NUM + 1 .
ENDDO.
"4.2.动态分配,循环累计工作区中的 HSL01-HSL16 。将字符串组成字段名直接分配给指针。(字符串中不带工作区类型)
CLEAR : LV_SUM .
LV_NUM = 1 .
DO 16 TIMES.
DATA(LV_FIED2) = LV_CHA2 && LV_NUM .
ASSIGN COMPONENT LV_FIED2 OF STRUCTURE <FS_FAG2> TO FIELD-SYMBOL(<FS_TSL2>) .
IF <FS_TSL2> <> 0.
LV_SUM = LV_SUM + <FS_TSL2> .
ENDIF.
LV_NUM = LV_NUM + 1 .
ENDDO.
"5.动态分配,循环累计工作区中的 HSL01-HSL16 。将工作区的第几个字段分配给指针。
CLEAR : LV_NUM ,LV_SUM .
DO 16 TIMES.
LV_NUM = 5 ."从第五个字段开始累加
ASSIGN COMPONENT LV_NUM OF STRUCTURE <FS_FAG2> TO FIELD-SYMBOL(<FS_TSL3>) .
IF <FS_TSL2> <> 0.
LV_SUM = LV_SUM + <FS_TSL3> .
ENDIF.
LV_NUM = LV_NUM + 1 .
ENDDO.
"注意事项:指针分配结束后应该判断是否被分配了,此处DEMO做了省略"
ENDLOOP.DATA:lv_kjqj TYPE i VALUE 10,
ls_faglflext TYPE faglflext,
lt_faglflext TYPE STANDARD TABLE OF faglflext,
lt_faglflext_1 TYPE TABLE OF faglflext,
lv_str TYPE string,
lv_sum TYPE acdoca-hsl.
FIELD-SYMBOLS:<fs>.
" 折扣后营收占比
SELECT hsl01,
hsl02,
hsl03,
hsl04,
hsl05,
hsl06,
hsl07,
hsl08,
hsl09,
hsl10,
hsl11,
hsl12,
hsl13,
hsl14,
hsl15,
hsl16
FROM faglflext
INTO CORRESPONDING FIELDS OF TABLE @lt_faglflext
WHERE ryear = 2022
AND rbukrs = '3001'
AND racct = '6001010000' AND rldnr = '0L'.
LOOP AT lt_faglflext INTO ls_faglflext.
COLLECT ls_faglflext INTO lt_faglflext_1.
CLEAR:ls_faglflext.
ENDLOOP.
LOOP AT lt_faglflext_1 INTO DATA(ls_faglflext_1).
lv_str = 'LS_FAGLFLEXT_1-HSL' && lv_kjqj.
ASSIGN (lv_str) TO <fs>.
lv_sum = <fs>.
ENDLOOP.通过列行配置表动态分配
DATA:gt_fieldcat TYPE lvc_t_fcat,
gs_fieldcat TYPE lvc_s_fcat.
FORM frm_fill_fieldcat USING p_col p_fieldname p_text.
APPEND INITIAL LINE TO gt_fieldcat ASSIGNING FIELD-SYMBOL(<fs_field>).
IF <fs_field> IS ASSIGNED.
<fs_field>-col_pos = p_col."输出列
<fs_field>-fieldname = p_fieldname."内部表字段的字段名称
<fs_field>-scrtext_m = p_text."字段标签
IF p_fieldname = 'COL1'.
<fs_field>-outputlen = '40'."宽度
ENDIF.
"列字段为行数的时候,宽度调整
IF p_fieldname = 'COL2'.
<fs_field>-outputlen = '3'."宽度
ENDIF.
IF p_fieldname <> 'COL1' AND p_fieldname <> 'COL2'.
<fs_field>-outputlen = '20'.
ENDIF.
ENDIF.
ENDFORM.
FORM frm_get_data .
DATA:lv_comps TYPE string, "内部表字段的字段名称
lv_text TYPE string. "字段标签
DATA:lv_index TYPE sy-tabix.
DATA:lv_hsl TYPE fins_vhcur12."金额
DATA:lt_acdoca TYPE TABLE OF acdoca,
LS_acdoca TYPE acdoca.
DATA:lt_SETLEAF TYPE TABLE OF setleaf,
ls_SETLEAF TYPE setleaf.
DATA:lt_where TYPE TABLE OF string."动态SQL,动态条件
"去重用于取行项目
DATA: lt_data TYPE TABLE OF ty_data,
ls_data TYPE ty_data.
RANGES: lt_poper FOR acdoca-poper."期间
RANGES: lt_PRCTR FOR acdoca-prctr."利润中心
RANGES: lt_racct FOR acdoca-racct. "科目
RANGES: lt_rfarea FOR acdoca-rfarea. "职能范围
RANGES: LT_rbukrs FOR acdoca-rbukrs."公司代码
"查行配置表
SELECT
a~zrowdes"行项目描述
a~zfsvsno "报表版本
a~zsortno "排序码
a~zrowid "行项目ID
a~zrowsubid "行项目索引
a~zcatg "项目类型
a~racct_start "起始科目号
a~RACCT_end "终止科目号
a~rfarea "功能范围
a~zfrm "计算公式
a~drcrk_s "借方
a~drcrk_h "贷方
a~zoppo "取反
a~rbukrs "公司
a~prctr "利润中心
a~setname "利润中心组
INTO CORRESPONDING FIELDS OF TABLE gt_data
FROM ztfi010 AS a
WHERE a~zfsvsno = p_fsvsno."版本号
IF sy-subrc <> 0.
MESSAGE '该版本无行配置数据,请检查行配置!' TYPE 'E'.
LEAVE LIST-PROCESSING.
ENDIF.
CLEAR:gs_data.
SORT gt_data BY zsortno.
"查列配置表
SELECT * FROM ztfi011 INTO TABLE @DATA(lt_ztfi011) WHERE zfsvsno = @p_fsvsno.
IF sy-subrc <> 0.
MESSAGE '该版本无列配置数据,请检查列配置!' TYPE 'E'.
LEAVE LIST-PROCESSING.
ENDIF.
"创建列
PERFORM frm_fill_fieldcat USING 1 'COL1' '项 目'. "动态列表创建项目描述列
PERFORM frm_fill_fieldcat USING 2 'COL2' '行数'. "动态列表创建行数列
SORT lt_ztfi011 BY zsortno.
LOOP AT lt_ztfi011 INTO DATA(ls_ztfi011).
lv_comps = |COL{ sy-tabix + 2 }|."内部表字段的字段名称,由于创建2个列,所以+2
lv_text = ls_ztfi011-zvoldes."字段标签
lv_index = sy-tabix + 2.
PERFORM frm_fill_fieldcat USING lv_index lv_comps lv_text.
ENDLOOP.
"列排序
SORT gt_fieldcat BY col_pos.
" 根据列创建动态内表
CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog = gt_fieldcat
IMPORTING
ep_table = lr_table.
" 将表对象分配给指针
ASSIGN lr_table->* TO <fs_table>.
" 根据表对象创建行对象
CREATE DATA lr_line LIKE LINE OF <fs_table>.
" 将行对象分配给指针
ASSIGN lr_line->* TO <fs_line>.
"取配置表数据至lt_data
lt_data = gt_data.
"删除排序码重复项(前台只展示 相同排序码的一条数据),用于行数创建和逻辑取值
DELETE ADJACENT DUPLICATES FROM lt_data COMPARING zsortno.
"初始化行
DO lines( lt_data ) TIMES.
APPEND INITIAL LINE TO <fs_table> .
ENDDO.
CLEAR:lv_index,gs_data,ls_ztfi011,ls_data.
"标准项指针赋值
LOOP AT <fs_table> ASSIGNING FIELD-SYMBOL(<a>).
READ TABLE lt_data INTO ls_data INDEX sy-tabix. "取相同行的值
IF <a> IS ASSIGNED .
"列循环赋值
DO lines( lt_ztfi011 ) + 2 TIMES .
DATA(lv_comp) = |COL{ sy-index }|.
"用指针指向这个字段
ASSIGN COMPONENT lv_comp OF STRUCTURE <a> TO FIELD-SYMBOL(<fs_comp>).
IF sy-subrc = 0.
"根据列字段名称进行赋值
IF lv_comp = 'COL1'.
<fs_comp> = ls_data-zrowdes.
ELSEIF lv_comp = 'COL2'.
<fs_comp> = sy-tabix.
ELSEIF lv_comp <> 'COL1' AND lv_comp <> 'COL2' AND ls_data-zcatg = '标准项'.
READ TABLE lt_ztfi011 INTO ls_ztfi011 INDEX sy-index - 2.
IF ls_data-rfarea IS NOT INITIAL.
lt_rfarea = VALUE
option = 'EQ'
low = ls_data-rfarea ).
APPEND lt_rfarea.
ENDIF.
"公司代码配置查询赋值
IF ls_data-rbukrs IN s_rbukrs.
lt_rbukrs = VALUE #( sign = 'I'
option = 'EQ'
low = ls_data-rbukrs ).
APPEND lt_rbukrs.
ENDIF.
LOOP AT s_prctr.
lt_prctr = VALUE #( sign = s_prctr-sign
option = s_prctr-option
low = s_prctr-low
high = s_prctr-high ).
APPEND lt_prctr.
ENDLOOP.
"期间
LOOP AT s_poper.
IF s_poper-option = 'EQ'.
DATA(lv_lowpoper) = s_poper-low.
ELSEIF s_poper-option = 'BT'.
lv_lowpoper = s_poper-high.
ENDIF.
ENDLOOP.
APPEND
'gjahr = @lv_jgahr' &&"会计年度
' AND poper IN @lt_poper' &&"期间(全年度)
' AND prctr IN @lt_prctr' && "利润中心
' AND rbukrs IN @lt_rbukrs' && "公司代码
' AND rfarea IN @lt_rfarea' && "职能范围
' AND racct IN @lt_racct' &&"科目范围取值
' AND ( drcrk = @ls_data-drcrk_h OR drcrk = @ls_data-drcrk_s )'"借贷方
TO lt_where.
"将
LOOP AT lt_where INTO DATA(ls_where).
REPLACE ALL OCCURRENCES OF '#' IN ls_where WITH space.
MODIFY lt_where FROM ls_where.
ENDLOOP.
SELECT hsl
INTO CORRESPONDING FIELDS OF TABLE @lt_acdoca
FROM acdoca
WHERE (lt_where).
"根据公司科目号排序
SORT lt_acdoca BY rbukrs racct.
LOOP AT lt_acdoca INTO ls_acdoca.
lv_hsl = lv_hsl + ls_acdoca-hsl.
ENDLOOP.
IF ls_data-zoppo = 'X'."取反
lv_hsl = lv_hsl * -1.
ENDIF.
"将金额\行id\列号插入表中,用于公式计算
gs_price-hsl = lv_hsl."金额
gs_price-zrowid = ls_data-zrowid."行id
gs_price-comp = lv_comp."列号
APPEND gs_price TO gt_price.
<fs_comp> = lv_hsl.
CLEAR:ls_ztfi011,lv_hsl,ls_acdoca,lt_where,lt_poper[],lt_poper,lt_PRCTR[],lt_PRCTR,lt_racct[],lt_racct,gs_price,lt_rfarea[],lt_rfarea,lt_rbukrs[],lt_rbukrs.
ENDIF.
ENDIF.
ENDDO .
ENDIF .
CLEAR:ls_data.
ENDLOOP .
ENDFORM.COND/SWITCH 的小坑
IF lv_str IS INITIAL.
lv_str = 'new value'.
ENDIF.
lv_str = COND
至此,我们就发现了一个小 BUG,所以新语法转化为旧的语法,是这样的,IF lv_str IS INITIAL.
lv_str = 'new value'.
ELSE.
lv_str = ''.
ENDIF.
lv_str = COND #( WHEN lv_str IS INITIAL THEN ‘new value’ ELSE lv_str ).
这样一来,我们便不会丢失原始的值了。SWITCH 的语法和 COND 道理相同。"New
lv_str = SWITCH #( n WHEN 1 THEN 'A'
WHEN 2 THEN 'B' ).
"Old
CASE n.
WHEN 1. lv_str = 'A'.
WHEN 2. lv_str = 'B'.
WHEN OTHERS. lv_str = ''.
ENDCASE.ABAP 函数 EVAL_FORMULA 计算公式
report ypwk_formula.
data: dataf type f,
datap type lbkum.
parameters: formula(40) default 'A*B*C*D',
a_val type lbkum default 3,
b_val type lbkum default 1,
c_val type lbkum default 2,
d_val type lbkum default 4.
start-of-selection.
call function 'CHECK_FORMULA'
exporting
formula = formula
program = sy-repid
routine = 'SUB_CHECK_FORMULA'
* UNIT_OF_MEASURE = ' '
* IMPORTING
* FUNCNAME =
* MESSAGE =
* POS =
* SUBRC =
exceptions
error_in_formula = 1
missing_parameter = 2
others = 3.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.
call function 'EVAL_FORMULA'
exporting
formula = formula
program = sy-repid
routine = 'SUB_GET_VALUE'
importing
value = dataf
exceptions
division_by_zero = 1
exp_error = 2
formula_table_not_valid = 3
invalid_expression = 4
invalid_value = 5
log_error = 6
parameter_error = 7
sqrt_error = 8
units_not_valid = 9
missing_parameter = 10
others = 11.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
else.
move dataf to datap.
write:/ formula, datap.
endif.
form sub_check_formula using value(name)
CHANGING value(subrc).
subrc = 0.
ENDFORM.
form sub_get_value using value(name)
changing value(value)
value(subrc).
subrc = 0.
value = 0.
case name.
when 'A'.
value = a_val.
when 'B'.
value = b_val.
when 'C'.
value = c_val.
when 'D'.
value = d_val.
endcase.
endform. "VAR_GETDATA: dataf TYPE f,
datap TYPE fins_vhcur12. "计算公式的金额
CALL FUNCTION 'EVAL_FORMULA'
EXPORTING
formula = lv_formula
program = sy-repid
routine = 'SUB_GET_VALUE'
IMPORTING
value = dataf
EXCEPTIONS
division_by_zero = 1
exp_error = 2
formula_table_not_valid = 3
invalid_expression = 4
invalid_value = 5
log_error = 6
parameter_error = 7
sqrt_error = 8
units_not_valid = 9
missing_parameter = 10
OTHERS = 11.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
MOVE dataf TO datap.
ENDIF.
FORM sub_get_value USING VALUE(name)
CHANGING VALUE(value)
VALUE(subrc).
subrc = 0.
value = 0.
LOOP AT gt_formula INTO gs_formula.
CASE name.
WHEN gs_formula-zrowid.
value = gs_formula-hsl.
ENDCASE.
CLEAR:gs_formula.
ENDLOOP.
ENDFORM.ABAP 常规检查
检查数字
方法 2: NUMERIC_CHECK
方法 3: 用 catch 命令自己做data c(10) type c.
data i type p.
c = '123X'.
catch system-exceptions convt_no_number = 1.
i = c.
endcatch.
if sy-subrc = 1.
write:/ 'not number'.
else.
write:/ 'number'.
endif.
1.如果返回X则是 否则不是
cl_abap_matcher=>matches(
pattern = '^(-?[1-9]\d*(\.\d*[1-9])?)|(-?0\.\d*[1-9])$'
text = 'XXX' )
2.定义数字变量进行赋值,如果不是则会异常
DATA l_num TYPE p LENGTH 15 DECIMALS 2.
CATCH SYSTEM-EXCEPTIONS convt_no_number = 8.
l_num = pu_num.
ENDCATCH.
IF sy-subrc = 8.
ENDIF.检查中文
CALL FUNCTION ‘NLS_VISUAL_CHARLEN’
EXPORTING
str = c1
IMPORTING
len_visual = flag.ABAP 如何得到完整的错误消息
方法一,用 message into,语法如下:MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
INTO DATA(mtext)
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
作用:将系统消息装换成一个字符串,消息转为文本函数。data:v_mess(60).
*&---错误消息处理
clear:v_mess.
loop at i_messtab where msgtyp = 'E' or msgtyp = 'A'.
call function 'MESSAGE_TEXT_BUILD'
exporting
msgid = i_messtab-msgid
msgnr = i_messtab-msgnr
msgv1 = i_messtab-msgv1
msgv2 = i_messtab-msgv2
msgv3 = i_messtab-msgv3
msgv4 = i_messtab-msgv4
importing
message_text_output = v_mess.
endloop.表维护生成器 SM30 表维护
https://blog.csdn.net/qq_40977705/article/details/109763552
事件编号 事件功能
01 保存前修改数据
05 创建数据时修改
21 退出单元格编辑时填充隐藏字段
————————————————
版权声明:本文为 CSDN 博主「长沙铁道学院-康帅傅」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012232542/article/details/90925845SM30 表维护自动更新值
实现:这些是通过 SE54 中的“事件(EVENT)”来实现的。
实例:SM30 自动填充创建者、创建日期、创建时间、修改者、修改日期、修改时间FORM FORM_INIT.
ZTFI014-ZNAME = SY-UNAME.
ZTFI014-ZDATE = SY-DATUM.
ZTFI014-ZTIME = SY-UZEIT.
ENDFORM.
FORM FORM_UPDATE.
IF X_HEADER-MAINTVIEW = 'ZTFI014'.
FIELD-SYMBOLS: <F> TYPE ZTFI014.
ASSIGN <TABLE1> TO <F>.
<F>-ZNAME = SY-UNAME.
<F>-ZDATE = SY-DATUM.
<F>-ZTIME = SY-UZEIT.
ENDIF.
UNASSIGN <F>.
ENDFORM.SM30 添加导入 excel 的功能按钮
https://blog.csdn.net/sinat_38119716/article/details/120330051LOOP GROUP BY
LOOP AT gt_list INTO DATA(ls_ekko)
GROUP BY ( ebeln = ls_ekko-ebeln ) ASCENDING ASSIGNING FIELD-SYMBOL(<group>)."按括号里的条件进行分组
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<ls_member>). "按分组后进行组员的访问
lv_count = lv_count + <ls_member>-EFFWR. "这里就是对同一组的进行某个字段的汇总
ENDLOOP.
<ls_member>-totol = lv_count.
CLEAR: lv_count.
ENDLOOP.内外码转换 ALPHA = IN
ls_accountgl-gl_account = |{ ls_item-hkont ALPHA = IN }|."总账科目
ls_accountgl-costcenter = |{ ls_item-kostl ALPHA = IN }|."成本中心
ls_accountgl-profit_ctr = |{ ls_item-prctr ALPHA = IN }|."利润中心
ls_accountgl-orderid = |{ ls_item-aufnr ALPHA = IN }|."内部订单DDIF_DTEL_GET、DDIF_FIELDINFO_GET 取 DATA ELEMENT、表的文本描述
DATA ELEMENT 的文本描述存于 DD04V 表中,在取得时可以从 DB 表中取 or 使用下面的 Function。
项目中为了在出力帐票时取得文本描述,使用此标准 Function 自定义了一个共通的 Function;传入 Data Element 名称,传出文本描述。
此 Function 与上面的使用效果类似,既可以取得单一 DATA ELEMENT,也可以取得整张表所有 DATA_ELEMENT 的文本描述。传出构造对应的项目名也一致。CALL FUNCTION 'DDIF_DTEL_GET'
EXPORTING
NAME = G_WRK_NAME "DATA ELEMENT名称
STATE = 'A'
LANGU = SY-LANGU
IMPORTING
DD04V_WA = G_REC_DD04V "取得的TEXT构造
EXCEPTIONS
ILLEGAL_INPUT = 1
OTHERS = 2.
CALL FUNCTION 'DDIF_FIELDINFO_GET'
EXPORTING
tabname = pv_tabname "表名
TABLES
dfies_tab = pt_tab
EXCEPTIONS
not_found = 1
internal_error = 2
OTHERS = 3.税码获取税率
CALL FUNCTION 'GET_TAX_PERCENTAGE'
EXPORTING
aland = 'CN' "国家语言
datab = sy-datum "当前时间
mwskz = <f>-zmwskz "税码
txjcd = ' '
TABLES
t_ftaxp = t_ftaxp.
"读取获取出来的数据
READ TABLE t_ftaxp INTO t_ftaxp WITH KEY kschl = 'MWAS'.
IF sy-subrc EQ 0.
lv_mwskz = t_ftaxp-kbetr / 10."税率
CONCATENATE lv_mwskz '%' INTO <f>-ztax.
ENDIF.取采购订单含税金额
含税单价:根据 ebeln 采购单号找到凭证条件编号(EKKO-KNUMV),根据凭证条件编号找到 PRCD_ELEMENTS 表中的记录;
其中 PRCD_ELEMENTS-KSCHL == PB00 的记录中 KBETR 代表含税单价,KWERT 代表含税金额;
其中 PRCD_ELEMENTS-KSCHL == ZTAX 的记录中 KBETR 代表税率,KWERT 代表税额;锁对象及使用方法
批导字符串转换为数值
用到以下函数:DATA: LV_DCPFM TYPE USR01-DCPFM.
DATA: LV_STR TYPE C LENGTH 18.
DATA: LV_OUT TYPE P DECIMALS 2.
SELECT SINGLE DCPFM
INTO LV_DCPFM
FROM USR01
WHERE BNAME EQ SY-UNAME.
CALL FUNCTION 'UNITS_STRING_CONVERT'
EXPORTING
UNITS_STRING = LV_STR "字符类型的数值数据
DCPFM = LV_DCPFM "USR01表中当前用户的配置
* MLLN = 'M'
* TSND = 'T'
IMPORTING
UNITS = LV_OUT "数值类型的字段
EXCEPTIONS
INVALID_TYPE = 1
OTHERS = 2.RFC_CVI_EI_INBOUND_MAIN BP 主数据创建/修改示例
RFC_CVI_EI_INBOUND_MAIN 创建后 CN0 默认转换为 CN5,可用 BAPI_BUPA_TAX_CHANGE 强制改成 CN0
对于前台控制页签下的税分类相关数据,需要用 BAPI_BUTX_FRG0010_ADD 才能添加进去税分类国家/地区 税收类型 税收组数据
https://blog.csdn.net/z_x_xing*/article/details/90079579SAP 金额等负号提前问题
这种方法相对于前两种方法的优点是,一.类型还是金额等数字类型,负号实现前置;二.几乎不用写很多代码,且可以保留千分位;三.适用于多个这样的字段修改需求。
实现步骤如下:
1.SE37,按下图命名规范创建 FUNCTION,输入函数组和描述,然后输入 import 和 export 参数,如图
添加代码:FUNCTION conversion_exit_z001_output.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" REFERENCE(INPUT)
*" EXPORTING
*" REFERENCE(OUTPUT)
*"----------------------------------------------------------------------
DATA: output1(20),
output2(20),
outnum(16) TYPE p DECIMALS 2.
IF input IS NOT INITIAL AND input NA '%'.
outnum = input.
IF input >= 0.
WRITE outnum TO output1.
ELSE.
outnum = outnum * ( -1 ).
WRITE outnum TO output1.
CONCATENATE '-' output1 INTO output1.
ENDIF.
ELSE.
* CLEAR output1.
output1 = input.
ENDIF.
CONDENSE output1 NO-GAPS.
WRITE output1 TO output2 RIGHT-JUSTIFIED.
output = output2.
CLEAR : output2.
ENDFUNCTION.
最后,在对应的 alv 设置 fieldcat 时针对设置金额等数字类型的字段添加代码:固定写成’ZXXX’形式。
WE_FIELDCAT-EDIT_MASK = ‘==Z001’.
原文链接:https://blog.csdn.net/u011576750/article/details/48029589SAP 号码范围(number range)的使用
编号长度域就填创建的域,但是一定要先激活。指定这个编号范围对象 ZDIAODUDAN 的长度,我们定义域长度为 10,因此这个编号范围对象生成的编号长度也是 10 位。*&---SNRO取值编号
clear : lv_nr1,lv_num1.
lv_nr1 = '01'.
call function 'NUMBER_RANGE_ENQUEUE'
exporting
object = 'ZFI016A1'
exceptions
foreign_lock = 1
object_not_found = 2
system_failure = 3
others = 4.
if sy-subrc = 0. "如果号码范围存在
call function 'NUMBER_GET_NEXT' "将号码累加,获得下一个流水号
exporting
nr_range_nr = lv_nr1
object = 'ZFI016A1'
importing
number = lv_num1
exceptions
interval_not_found = 1
number_range_not_intern = 2
object_not_found = 3
quantity_is_0 = 4
quantity_is_not_1 = 5
interval_overflow = 6
buffer_overflow = 7
others = 8.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
else.
call function 'NUMBER_RANGE_DEQUEUE'
exporting
object = 'ZFI016A1'
exceptions
object_not_found = 1
others = 2.
endif.
endif.ABAP CDS VIEW WITH ASSOCIATION
由于 ASSOCIATION 是按需触发,当 Join 较多实际访问时用户只访问单个或者少数 Join 时,相比较传统可以高效率地完成 SQL
ASSOCIATION 的关联基数:
[ 0 … 1 ] = 最多关联一个(at most one)
[ 1 … 1 ] = 只能一一对应关联(exactly one)
[ 0 … n ] = 关联任意数量(any number)
[ 1 … n ] = 至少关联一个(at least one)
[ 1 … 1 ] [ 1 … n ]保证了关联的主表始终至少有一条记录获取 select 某个条件下的条目数
DATA: L_COUNT TYPE I.
SELECT EQUI~EQUNR
EQKT~EQKTX
ILOA~SWERK
INTO TABLE GT_EQUI
FROM EQUI
LEFT JOIN EQKT ON EQUI~EQUNR = EQKT~EQUNR AND SPRAS = SY-LANGU
LEFT JOIN EQUZ ON EQUI~EQUNR = EQUZ~EQUNR AND EQUZ~DATBI = '99991231'
INNER JOIN ILOA ON EQUZ~ILOAN = ILOA~ILOAN
WHERE ILOA~SWERK IN S_SWERK
AND EQUI~ERDAT IN S_ERDAT .
IF SY-SUBRC = 0.
L_COUNT = SY-DBCNT.
ENDIF.DATA: L_COUNT TYPE I.
SELECT COUNT( * )
INTO L_COUNT
FROM EQUI
LEFT JOIN EQKT ON EQUI~EQUNR = EQKT~EQUNR AND SPRAS = SY-LANGU
LEFT JOIN EQUZ ON EQUI~EQUNR = EQUZ~EQUNR AND EQUZ~DATBI = '99991231'
INNER JOIN ILOA ON EQUZ~ILOAN = ILOA~ILOAN
WHERE ILOA~SWERK IN S_SWERK
AND EQUI~ERDAT IN S_ERDAT .
IF SY-SUBRC = 0.
ENDIF.DATA: L_COUNT TYPE I.
SELECT EQUI~EQUNR
EQKT~EQKTX
ILOA~SWERK
INTO TABLE GT_EQUI
FROM EQUI
LEFT JOIN EQKT ON EQUI~EQUNR = EQKT~EQUNR AND SPRAS = SY-LANGU
LEFT JOIN EQUZ ON EQUI~EQUNR = EQUZ~EQUNR AND EQUZ~DATBI = '99991231'
INNER JOIN ILOA ON EQUZ~ILOAN = ILOA~ILOAN
WHERE ILOA~SWERK IN S_SWERK
AND EQUI~ERDAT IN S_ERDAT .
IF SY-SUBRC = 0.
* L_COUNT = SY-DBCNT.
DESCRIBE TABLE GT_EQUI LINES L_COUNT.
ENDIF.SAP ABAP 日期,时间 相关函数
DATA: days TYPE i,
months TYPE i,
years TYPE i.
CALL FUNCTION 'FIMA_DAYS_AND_MONTHS_AND_YEARS'
EXPORTING
i_date_from = '20130101'
i_date_to = '20141001'
i_flg_separate = ' ' "是否单独计算 若有标识,则返回两日期相差的天数
IMPORTING
e_days = days "返回天数:638
e_months = months "返回月数:21
e_years = years. "返回年数:2
* 单独计算
CALL FUNCTION 'FIMA_DAYS_AND_MONTHS_AND_YEARS'
EXPORTING
i_date_from = '20130101'
i_date_to = '20141001'
i_flg_separate = 'X' "标识 'X'
IMPORTING
e_days = days "返回天数:0
e_months = months "返回月数:9
e_years = years. "返回年数:1
DATA LV_DATE type DATS.
CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
EXPORTING
DATE = LV_IN_DATE
DAYS = '00'
MONTHS = '01'
SIGNUM = '+'
YEARS = '00'
IMPORTING
CALC_DATE = LV_DATE.ABAP 中 JSON 格式的转换与解析
DATA:
serializer TYPE REF TO cl_trex_json_serializer,
lv_json TYPE string.
DATA: BEGIN OF ls_kv,
key1 TYPE string,
value TYPE string,
END OF ls_kv.
DATA: lt_kv LIKE HASHED TABLE OF ls_kv WITH UNIQUE KEY key1.
ls_kv-key1 = 'key'.
ls_kv-value = '值'.
INSERT ls_kv INTO TABLE lt_kv.
CREATE OBJECT serializer
EXPORTING
data = ls_kv.
serializer->serialize( ).
lv_json = serializer->get_data( ).
WRITE / lv_json.DATA: deserializer TYPE REF TO cl_trex_json_deserializer.
CLEAR ls_kv.
CREATE OBJECT deserializer.
deserializer->deserialize(
EXPORTING json = lv_json
IMPORTING abap = ls_kv ).
WRITE: / ls_kv-key1, / ,ls_kv-value.types: begin of t_record,
key1 type string,
key2 type string,
end of t_record.
data: json type string.
data: record type t_record.
json = '{"key1": "VALUE1", "key2": "VALUE2"}'.
/ui2/cl_json=>deserialize( exporting json = json changing data = record ).Message(消息)
类型定义 INCLUDE
TYPES: BEGIN OF ty_alv,
mark TYPE char1.
INCLUDE TYPE ztfi040.
TYPES END OF ty_alv.
DATA: gt_alv TYPE STANDARD TABLE OF ty_alv,
gs_alv TYPE ty_alv.SAP 业务顾问也会的增强——标准字段文本修改的 4 种方法
Copy PR header text to PO header
METHOD if_ex_me_process_po_cust~process_header.
*取值采购申请抬头文本填充采购订单抬头文本 EL-ZHOUZHOU 20230203
DATA: lt_lines TYPE TABLE OF tline,
ls_lines TYPE tline,
l_tdname TYPE tdobname.
DATA:lt_purchase TYPE purchase_order_items,
ls_purchase TYPE purchase_order_item,
ls_mepoitem TYPE mepoitem.
DATA: lt_textlines TYPE mmpur_t_textlines,
ls_textlines TYPE mmpur_textlines.
CLEAR: lt_lines[],ls_lines,l_tdname,lt_purchase[],ls_purchase,ls_mepoitem,
lt_textlines[],ls_textlines.
lt_purchase = im_header->get_items( ).
LOOP AT lt_purchase INTO ls_purchase.
ls_mepoitem = ls_purchase-item->get_data( ).
IF ls_mepoitem-banfn IS NOT INITIAL..
EXIT.
ENDIF.
ENDLOOP.
"取值采购申请抬头文本
l_tdname = ls_mepoitem-banfn.
CALL FUNCTION 'READ_TEXT'
EXPORTING
client = sy-mandt
id = 'B01'
language = sy-langu
name = l_tdname
object = 'EBANH'
TABLES
lines = lt_lines
EXCEPTIONS
id = 1
language = 2
name = 3
not_found = 4
object = 5
reference_check = 6
wrong_access_to_archive = 7
OTHERS = 8.
IF lt_lines IS NOT INITIAL.
LOOP AT lt_lines INTO ls_lines.
ls_textlines-tdobject = 'EKKO'.
ls_textlines-tdid = 'F01'.
ls_textlines-tdformat = ls_lines-tdformat.
ls_textlines-tdline = ls_lines-tdline.
APPEND ls_textlines TO lt_textlines.
CLEAR: ls_lines,ls_textlines.
ENDLOOP.
"设置抬头文本
CALL METHOD im_header->if_longtexts_mm~set_text
EXPORTING
im_tdid = 'F01'
im_textlines = lt_textlines.
ENDIF.
ENDMETHOD.批量删除销售订单
2、如果创建过后续凭证,即使全部冲销删除 DN 也是不能删除的,只能对 SO 进行 rejected。
不清楚你是现在是什么情况,如果你是第一种情况,那么你需要通过 LSMW 自己创建批处理工具。
当然即使是第一种情况,你同样可以采用 reject SO 的方式来取消 SO。
1、执行 Tcode MASS。
2、选择对象类型 BUS2032。
3、选择 MASSVBAP 后执行。
4、输入你要批量处理的订单号,执行。
5、点击“选择字段”,选择拒绝原因,后面的操作与 XD99,批量修改客户一样。SAPGUI_PROGRESS_INDICATOR
DATA: lv_lines(10), "行数
lv_lines1 TYPE i, "行数
lv_group TYPE i, "组
lv_tabix(10), "循环标号
lv_pecnt TYPE p LENGTH 6 DECIMALS 2, "百分比
lv_pecet(6), "百分数
lv_text(40). "消息
CLEAR: lv_lines,lv_tabix,lv_pecnt,lv_pecet,lv_text.
lv_tabix = lv_tabix + 1. "当前处理的行号
lv_pecnt = lv_tabix / lv_lines * 100."已处理百分比
lv_pecet = lv_pecnt.
"---拼接显示消息
CONCATENATE '已完成' lv_pecet '%,共' lv_tabix '条/' lv_lines '条' INTO lv_text.
CONDENSE lv_text. "整理格式,去掉多余空格
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' "调用进度条函数,传入百分比和消息
EXPORTING
percentage = lv_pecnt
text = lv_text.
CLEAR: lv_pecnt,lv_pecet,lv_text.DATA: g_lines1 TYPE i, "采购订单创建行数
g_lines2 TYPE i,
g_lines3 TYPE i, "总数据行数
lv_str TYPE string,
lv_per TYPE i,
lv_str = '共有' && g_lines3 && '条数据需要处理,已处理' &&
g_lines2 && '条,请勿关闭操作'.
IF g_lines2 <> g_lines3.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
percentage = 10
text = lv_str.
ELSE.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
percentage = 100
text = lv_str.
ENDIF.SAP 中去除末尾符号或开头字符
方法 shift_right( val = ‘’ sub =‘’)
开头采用的是:shift_left( val = sub =’”).DATA:zkqjg TYPE C.
CONCATENATE '(全天);' zkqjg INTO zkqjg .
zkqjg = shift_right( val = zkqjg sub = ';').SAP 增强实施禁止指定 TCODE 中 ALV 右键导出 Excel 文件
屏幕字段搜索帮助 F4IF_INT_TABLE_VALUE_REQUEST
AT SELECTION-SCREEN ON VALUE-REQUEST FOR s_name-low.
PERFORM frm_funcname_f4 USING 'FUNCNAME' 'S_NAME-LOW'.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR s_name-high.
PERFORM frm_funcname_f4 USING 'FUNCNAME' 'S_NAME-HIGH'.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_para.
CLEAR: dyfields[], dyfields.
CALL FUNCTION 'DYNP_VALUES_READ'
EXPORTING
dyname = sy-cprog
dynumb = sy-dynnr
request = 'A'
TABLES
dynpfields = dyfields.
READ TABLE dyfields WITH KEY fieldname = 'P_NAME'.
IF dyfields-fieldvalue IS INITIAL.
MESSAGE s000(oo) DISPLAY LIKE 'E' WITH '先填写函数名'.
EXIT.
ENDIF.
TRANSLATE dyfields-fieldvalue TO UPPER CASE.
CLEAR it_para[].
SELECT parameter INTO TABLE it_para
FROM fupararef
WHERE funcname = dyfields-fieldvalue AND
paramtype <> 'T' AND
r3state = 'A'.
* ORDER BY paramtype DESCENDING pposition.
SELECT parameter APPENDING TABLE it_para
FROM fupararef
WHERE funcname = dyfields-fieldvalue AND
paramtype = 'T' AND
r3state = 'A'.
* ORDER BY paramtype pposition.
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
retfield = 'PARA'
dynpprog = sy-repid
dynpnr = sy-dynnr
dynprofield = 'P_PARA'
value_org = 'S'
TABLES
value_tab = it_para
EXCEPTIONS
parameter_error = 1
no_values_found = 2
OTHERS = 3.
*&---------------------------------------------------------------------*
*& Form frm_funcname_f4
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM frm_funcname_f4 USING VALUE(pv_retfield) VALUE(pv_dynprofield).
SELECT a~funcname,b~stext INTO TABLE @DATA(lt_zfunc) FROM tfdir AS a
LEFT JOIN tftit AS b ON b~funcname = a~funcname AND b~spras = @sy-langu
WHERE a~funcname LIKE '%ZFM%' .
SORT lt_zfunc BY funcname.
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
retfield = pv_retfield
dynpprog = sy-repid
dynpnr = sy-dynnr
dynprofield = pv_dynprofield
value_org = 'S'
TABLES
value_tab = lt_zfunc
EXCEPTIONS
parameter_error = 1
no_values_found = 2
OTHERS = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDFORM.
FORM frm_f4_ny.
DATA: BEGIN OF mf_dynpfields OCCURS 1.
INCLUDE STRUCTURE dynpread.
DATA: END OF mf_dynpfields.
DATA: mf_returncode LIKE sy-subrc,
mf_monat LIKE isellist-month,
mf_hlp_repid LIKE sy-repid.
GET CURSOR FIELD mf_dynpfields-fieldname.
APPEND mf_dynpfields.
mf_hlp_repid = sy-repid.
DO 2 TIMES.
CALL FUNCTION 'DYNP_VALUES_READ'
EXPORTING
dyname = mf_hlp_repid
dynumb = sy-dynnr
TABLES
dynpfields = mf_dynpfields
EXCEPTIONS
invalid_abapworkarea = 01
invalid_dynprofield = 02
invalid_dynproname = 03
invalid_dynpronummer = 04
invalid_request = 05
no_fielddescription = 06
undefind_error = 07.
IF sy-subrc = 3.
mf_hlp_repid = 'SAPLALDB'.
ELSE.
READ TABLE mf_dynpfields INDEX 1.
TRANSLATE mf_dynpfields-fieldvalue USING '_ '.
EXIT.
ENDIF.
ENDDO.
IF sy-subrc = 0.
CALL FUNCTION 'CONVERSION_EXIT_PERI_INPUT'
EXPORTING
input = mf_dynpfields-fieldvalue
IMPORTING
output = mf_monat
EXCEPTIONS
error_message = 1.
IF mf_monat IS INITIAL.
mf_monat = sy-datlo(6).
ENDIF.
CALL FUNCTION 'POPUP_TO_SELECT_MONTH'
EXPORTING
actual_month = mf_monat
IMPORTING
selected_month = mf_monat
return_code = mf_returncode
EXCEPTIONS
factory_calendar_not_found = 01
holiday_calendar_not_found = 02
month_not_found = 03.
IF sy-subrc = 0 AND mf_returncode = 0.
CALL FUNCTION 'CONVERSION_EXIT_PERI_OUTPUT'
EXPORTING
input = mf_monat
IMPORTING
output = mf_dynpfields-fieldvalue.
mf_dynpfields-fieldvalue = mf_dynpfields-fieldvalue+0(5) && '0' && mf_dynpfields-fieldvalue+5(2).
COLLECT mf_dynpfields.
CALL FUNCTION 'DYNP_VALUES_UPDATE'
EXPORTING
dyname = mf_hlp_repid
dynumb = sy-dynnr
TABLES
dynpfields = mf_dynpfields
EXCEPTIONS
invalid_abapworkarea = 01
invalid_dynprofield = 02
invalid_dynproname = 03
invalid_dynpronummer = 04
invalid_request = 05
no_fielddescription = 06
undefind_error = 07.
ENDIF.
ENDIF.
ENDFORM.single 与 up to 1 rows
格式: SELECT single Field_Name_List
FROM Table_Name
WHERE Condition_List
格式 : SELECT Field_Name_List
FROM Table_Name
up to 1 rows
WHERE Condition_List
ENDSELECT
使用 single : SELECT single CLINT
INTO KSSK-CLINT
FROM KSSK
WHERE OBJEK EQ INOD-CUOBJ
AND MAFID EQ C_O_SIGN
AND KLART EQ C_KLART
SELECT CLINT INTO KSSK-CLINT
FROM KSSK
up to 1 rows
WHERE OBJEK EQ INOD-CUOBJ
AND MAFID EQ C_O_SIGN
AND KLART EQ C_KLART
ENDSELECT
在使用 single 时是错误的,而使用 up to 1 rows 是正确的。
因为 single,在 where 子句中要使用所有 key 字段的作为条件才能使用 single。
而 up to 1 rows 则使用了部分或没有使用 key 字段都可以使用。
single 取第一个符合条件的数据,不需要继续再查找下去。
up to 1 rows 先查找所有数据,再取一条符合条件的数据。
up to n rows 可以取 n 条数据已释放(发布)的请求号取消释放
取消释放的思路为修改表,把表的释放状态改为可修改的状态:
方式一:SE38 执行 RDDIT076 程序 输入请求号
方式二:直接改表 E070。第一种方式也是直接改表 E070。
delete from E070A where TRKORR = ‘ED1K913540’ and ATTRIBUTE = ‘EXPTIMESTAMP’ –过期时间副本请求
事务码:SE09
LOOP GROUP BY
size = GROUP SIZE “分组组数
index = GROUP INDEX ) “分组的组序号
ASCENDING ASSIGNING FIELD-SYMBOL(<组>).
“对指针进行操作,和普通的 loop 循环相似
ENDLOOP.
ENDLOOP.TYPES: BEGIN OF ty_employee,
name TYPE char30,
role TYPE char30,
age TYPE i,
sex TYPE char10,
END OF ty_employee,
ty_employee_t TYPE STANDARD TABLE OF ty_employee WITH KEY name.
"对内表进行赋值"
DATA(gt_employee) = VALUE ty_employee_t(
( name = 'John' role = 'ABAP guru' age = 34 sex = 'MAN' )
( name = 'Alice' role = 'FI Consultant' age = 42 sex = 'WOMAN' )
( name = 'Barry' role = 'ABAP guru' age = 54 sex = 'WOMAN' )
( name = 'Mary' role = 'FI Consultant' age = 37 sex = 'WOMAN' )
( name = 'Arthur' role = 'ABAP guru' age = 34 sex = 'MAN' )
( name = 'Mandy' role = 'SD Consultant' age = 64 sex = 'MAN' ) ).
DATA: gv_tot_age TYPE i,
gv_avg_age TYPE decfloat34.
"通过角色进行分组"
LOOP AT gt_employee INTO DATA(ls_employee) GROUP BY ( role = ls_employee-role
size = GROUP SIZE "分组组数"
index = GROUP INDEX ) "分组的组序号"
ASCENDING ASSIGNING FIELD-SYMBOL(<group>).
CLEAR: gv_tot_age.
WRITE: / | 组序号: { <group>-index } 角色: { <group>-role WIDTH = 15 }|
& | 这个组有几条数据: { <group>-size } |.
"loop循环组,将组里的数据读出来"
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<ls_member>).
gv_tot_age = gv_tot_age + <ls_member>-age.
WRITE: /13 <ls_member>-name .
ENDLOOP.
gv_avg_age = gv_tot_age / <group>-size.
WRITE: / |组平均年龄: { gv_avg_age }|.
SKIP.
ENDLOOP.LOOP AT gt_list INTO DATA(ls_ekko)
GROUP BY ( ebeln = ls_ekko-ebeln ) ASCENDING ASSIGNING FIELD-SYMBOL(<group>)."按括号里的条件进行分组
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<ls_member>). "按分组后进行组员的访问
lv_count = lv_count + <ls_member>-effwr. "这里就是对同一组的进行某个字段的汇总
ENDLOOP.
<ls_member>-totol = lv_count.
CLEAR: lv_count.
ENDLOOP.
DELETE gt_list WHERE totol IS INITIAL.REDUCE 汇总内表数字型字段的和
DATA:BEGIN OF ls_data,
a TYPE char1,
b TYPE numc2,
END OF ls_data,
lt_data LIKE TABLE OF ls_data.
lt_data = VALUE
( a = 'B' b = 30 )
( a = 'C' b = 50 ) ) .
DATA(lv_sum) = REDUCE
FOR ls_wa IN lt_data "创建一个工作区ls_wa对应内表
WHERE ( a = 'A' OR a = 'B' ) "汇总如果有条件,可以添加汇总条件
NEXT sum = sum + ls_wa-b )."把值和工作区wa取的值相加
WRITE lv_sum.转换例程
lv_kunnr = |{ kunnr ALPHA = IN }|. "加前导零
"给物料添加前导0"
CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
EXPORTING
input = pv_matnr
IMPORTING
output = pv_matnr
EXCEPTIONS
length_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
ENDIF.CALL FUNCTION 'CONVERSION_EXIT_CUNIT_INPUT'
EXPORTING
input = gs_upload-bstme
language = sy-langu
IMPORTING
output = gs_upload-bstme.SUBMIT
SUBMIT {rep|(name)}
[]
[]
[]
[]
[]
{ [WITH sel1 { {{EQ|NE|CP|NP|GE|LT|LE|GT} dobj [SIGN sign]}
| {[NOT] BETWEEN dobj1 AND dobj2 [SIGN sign]}
| {IN rtab} }]
[]}
| {[NOT] BETWEEN dobj1 AND dobj2 [SIGN sign]}
| {IN rtab} }]
... }
[]
[]
[]
{ [EXPORTING LIST TO MEMORY]
| [TO SAP-SPOOL SPOOL PARAMETERS pri_params
[]
WITHOUT SPOOL DYNPRO] }
[[USER user] VIA JOB job NUMBER n]
[].
USING SELECTION-SCREEN dynnr:指定要访问的选择屏幕 dynnr,如不使用该条目,系统调用标准选择屏幕。
VIA SELECTION-SCREEN:显示被调用的选择屏幕。如不使用该条目,选择屏幕过程(selection screen processing)将会在后台发生。
USING SELECTION-SET variant:选择屏幕使用变式
USING SELECTION-SETS OF PROGRAM prog:指定使用的变式的程序
WITH SELECTION-TABLE rspar:选择屏幕使用内表 rspar 中的值,内表的行结构为 RSPARAMS 或者 RSPARAMSL_255REPORT ztestcalling.
CONSTANTS: g_memory1(30) VALUE 'JACKYTESTA'."定义MEMORY ID
CONSTANTS: g_memory2(30) VALUE 'JACKYTESTB'.
DATA: val_return_from_accessed1 TYPE i,
val_return_from_accessed2 TYPE i.
DATA: selectable LIKE TABLE OF rsparams. "选择参数内表
DATA: selectline LIKE LINE OF selectable.
SELECTION-SCREEN BEGIN OF BLOCK blk.
PARAMETERS: p_value TYPE i.
SELECTION-SCREEN END OF BLOCK blk.
INITIALIZATION.
START-OF-SELECTION.
selectline-selname = 'P_VALUE'. "选择屏幕字段名
selectline-kind = 'P'. "选择类型为单选,如果是多选则为S
selectline-low = p_value. "选择字段的值
APPEND selectline TO selectable.
SUBMIT ztestACCESSED1 WITH SELECTION-TABLE selectable AND RETURN.
IMPORT val TO val_return_from_accessed1 FROM MEMORY ID g_memory1. "取出ABAP内存中的数据
FREE MEMORY ID g_memory1. "释放MEMORY ID
SUBMIT ztestACCESSED2 WITH SELECTION-TABLE selectable AND RETURN.
IMPORT val TO val_return_from_accessed2 FROM MEMORY ID g_memory2.
FREE MEMORY ID g_memory2.
SKIP.
WRITE: '程序ACCESSED1的运行结果是', p_value, '+ 1 =', val_return_from_accessed1 .
WRITE: /'程序ACCESSED2的运行结果是', p_value, '* 3 =', val_return_from_accessed2 .
REPORT ztestACCESSED1.
DATA val TYPE i.
CONSTANTS: g_memory1(30) VALUE 'JACKYTESTA'.
SELECTION-SCREEN BEGIN OF BLOCK blk1.
PARAMETERS: p_value TYPE i.
SELECTION-SCREEN END OF BLOCK blk1.
INITIALIZATION.
START-OF-SELECTION.
val = p_value + 1.
IF sy-calld = 'X'.
EXPORT val FROM val TO MEMORY ID g_memory1.
ELSE.
WRITE val.
ENDIF.根据 HTTP 地址将电子发票的 PDF 文件下载到本地
function zfm_if_demo_get_pdf.
*"----------------------------------------------------------------------
*"*"本地接口:
*"----------------------------------------------------------------------
data:lv_response_data type string,
lt_mfv type zif_t_http_mfv with header line,
lv_url type string.
data:lv_xstring type xstring,
lt_solix type solix_tab with header line,
lv_file_name type string,
lv_file_path type string,
lv_full_name type string,
lv_file_length type i,
lv_max_length type i,
lv_actual_length type i,
lv_window_title type string,
lv_default_file_name type string,
lv_prompt_on_overwrite type abap_bool,
lv_path type string,
lv_user_action type i.
perform:frm_add_mfv using 'SET_HEADER_FIELD' '~request_method' 'GET' '' changing lt_mfv[],
frm_add_mfv using 'SET_HEADER_FIELD' '~server_protocol' 'HTTP/1.1' '' changing lt_mfv[],"可不传
frm_add_mfv using 'SET_HEADER_FIELD' 'Accept' '*/*' '' changing lt_mfv[],"可不传
frm_add_mfv using 'SET_HEADER_FIELD' 'Content-Type' 'application/pdf' '' changing lt_mfv[]."可不传
lv_url = 'http://dzfp.ycansoft.com:........./2021/09/15/04400200041127629533.pdf'."这个放你自己的地址
call function 'ZFM_IF_OUTBOUND_HTTP' “这里我有公共封装,你可以自己写http调用,就是常规的调用。
exporting
iv_url = lv_url
importing
ev_response_data = lv_response_data
changing
ct_mfv = lt_mfv[].
lv_xstring = lv_response_data.
call function 'SCMS_XSTRING_TO_BINARY'
exporting
buffer = lv_xstring
* APPEND_TO_TABLE = ' '
importing
output_length = lv_file_length
tables
binary_tab = lt_solix.
lv_window_title = '选择文件夹'.
lv_default_file_name = '电子发票' && sy-datum && sy-uzeit.
lv_prompt_on_overwrite = abap_true.
clear:lv_file_name,lv_path,lv_file_path,lv_user_action.
call method cl_gui_frontend_services=>file_save_dialog
exporting
window_title = lv_window_title
default_extension = 'pdf'
default_file_name = lv_default_file_name
prompt_on_overwrite = lv_prompt_on_overwrite
changing
filename = lv_file_name
path = lv_path
fullpath = lv_file_path
user_action = lv_user_action
exceptions
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
invalid_default_file_name = 4
others = 5.
if sy-subrc <> 0.
message id sy-msgid type 'S' number sy-msgno display like 'E'
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
return.
endif.
if lv_user_action <> cl_gui_frontend_services=>action_ok.
return.
endif.
call method cl_gui_frontend_services=>gui_download
exporting
bin_filesize = lv_file_length
filename = lv_file_path
filetype = 'BIN'
changing
data_tab = lt_solix[]
exceptions
file_write_error = 1
no_batch = 2
gui_refuse_filetransfer = 3
invalid_type = 4
no_authority = 5
unknown_error = 6
header_not_allowed = 7
separator_not_allowed = 8
filesize_not_allowed = 9
header_too_long = 10
dp_error_create = 11
dp_error_send = 12
dp_error_write = 13
unknown_dp_error = 14
access_denied = 15
dp_out_of_memory = 16
disk_full = 17
dp_timeout = 18
file_not_found = 19
dataprovider_exception = 20
control_flush_error = 21
not_supported_by_gui = 22
error_no_gui = 23
others = 24.
if sy-subrc <> 0.
message id sy-msgid type 'S' number sy-msgno display like 'E'
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
return.
else.
message '文件保存成功' type 'S'.
endif.
endfunction.ABAP and Excel
SAP OLE
*--DATA DEFINITION OF OLE
DATA: gs_excel TYPE ole2_object,
gs_wbooklist TYPE ole2_object,
gs_application TYPE ole2_object,
gs_wbook TYPE ole2_object,
gs_activesheet TYPE ole2_object,
gs_sheets TYPE ole2_object,
gs_newsheet TYPE ole2_object,
gs_cell1 TYPE ole2_object,
gs_cell2 TYPE ole2_object,
gs_cells TYPE ole2_object,
gs_range TYPE ole2_object,
gs_font TYPE ole2_object,
gs_interior TYPE ole2_object,
gs_columns TYPE ole2_object.
DATA: v_filename TYPE string,
v_filename1 TYPE string.
DATA: gv_lines TYPE i.
DATA gv_sheet_name(20) TYPE c .
DATA gv_linno TYPE i . "LINE NUMBER
DATA gv_colno TYPE i . "COLUMN NUMBER
FORM frm_export_excel .
DATA: lv_flag.
"根据销售区域去重
DATA(lt_out) = gt_out[].
SORT lt_out BY bzirk.
DELETE ADJACENT DUPLICATES FROM lt_out COMPARING bzirk.
CLEAR: v_filename,lv_flag,gv_lines.
DESCRIBE TABLE gt_fieldcat LINES gv_lines.
IF lt_out[] IS NOT INITIAL.
CALL METHOD cl_gui_frontend_services=>directory_browse
CHANGING
selected_folder = v_filename.
IF v_filename IS INITIAL.
lv_flag = 'X'.
ELSE.
CONCATENATE v_filename '/' '销售发货明细表' '--' sy-datum '.xls'
INTO v_filename.
ENDIF.
ENDIF.
IF lv_flag = ''.
"循环销售区域,每个生成相应的SHEET
LOOP AT lt_out INTO DATA(ls_out).
*--FORMING SHEET NAME
IF ls_out-bzirk_txt IS NOT INITIAL.
gv_sheet_name = ls_out-bzirk_txt.
ELSE.
gv_sheet_name = '销售地区为空'.
ENDIF.
*--FOR THE FIRST LOOP, EXCEL IS INITIATED AND ONE NEW SHEET IS ADDED
IF sy-tabix = 1.
CREATE OBJECT gs_excel 'EXCEL.APPLICATION'.
SET PROPERTY OF gs_excel 'VISIBLE' = 0 .
GET PROPERTY OF gs_excel 'WORKBOOKS' = gs_wbooklist .
GET PROPERTY OF gs_wbooklist 'APPLICATION' = gs_application .
SET PROPERTY OF gs_application 'SHEETSINNEWWORKBOOK' = 1 .
CALL METHOD OF gs_wbooklist 'ADD' = gs_wbook.
GET PROPERTY OF gs_application 'ACTIVESHEET' = gs_activesheet .
SET PROPERTY OF gs_activesheet 'NAME' = gv_sheet_name .
ELSE.
GET PROPERTY OF gs_wbook 'Sheets' = gs_sheets .
CALL METHOD OF gs_sheets 'Add' = gs_newsheet.
SET PROPERTY OF gs_newsheet 'Name' = gv_sheet_name .
ENDIF.
CLEAR gv_colno.
LOOP AT gt_fieldcat INTO gs_fieldcat.
gv_colno = gv_colno + 1. "列
*--TITLE
*--SETTING TITLE DATA
CALL METHOD OF gs_excel 'CELLS' = gs_cell1
EXPORTING
SET PROPERTY OF gs_cell1 'VALUE' = gs_fieldcat-scrtext_l .
*--FORMATTING
GET PROPERTY OF gs_cell1 'FONT' = gs_font .
SET PROPERTY OF gs_font 'BOLD' = 1 .
GET PROPERTY OF gs_cell1 'INTERIOR' = gs_interior .
SET PROPERTY OF gs_interior 'COLORINDEX' = 15 .
CLEAR: gs_fieldcat.
FREE OBJECT: gs_interior,gs_cell1,gs_font.
ENDLOOP.
*--BORDERING TITLE DATA AREA
"行
CALL METHOD OF gs_excel 'CELLS' = gs_cell1
EXPORTING
#1 = 1
#2 = 1.
CALL METHOD OF gs_excel 'CELLS' = gs_cell2
EXPORTING
#1 = 1
#2 = gv_lines. "字段数量
CALL METHOD OF gs_excel 'RANGE' = gs_cells
EXPORTING
CALL METHOD OF gs_cells 'SELECT'.
CALL METHOD OF gs_cells 'INTERIOR' = gs_interior.
SET PROPERTY OF gs_interior 'COLORINDEX' = 6.
FREE OBJECT: gs_interior,gs_cells,gs_cell2,gs_cell1.
*** 后续行数据开始写入
CLEAR: gv_linno.
gv_linno = 1.
LOOP AT gt_out INTO gs_out WHERE bzirk = ls_out-bzirk.
gv_linno = gv_linno + 1.
PERFORM frm_insert_data USING gs_out.
CLEAR: gs_out.
ENDLOOP.
"优化列宽
CALL METHOD OF gs_excel 'COLUMNS' = gs_columns.
CALL METHOD OF gs_columns 'AUTOFIT'.
*--ACTIVATE CURRENT SHEET
CALL METHOD OF gs_excel 'WORKSHEETS' = gs_activesheet
EXPORTING
#1 = gv_sheet_name.
CALL METHOD OF gs_activesheet 'ACTIVATE'.
CLEAR ls_out.
ENDLOOP.
*** 保存 ***
GET PROPERTY OF gs_excel 'ACTIVEWORKBOOK' = gs_wbook.
CALL METHOD OF gs_wbook 'SAVEAS'
EXPORTING
#1 = v_filename
#2 = 1.
"关闭EXCEL
CALL METHOD OF gs_wbook 'CLOSE'.
CALL METHOD OF gs_excel 'QUIT'.
*--DEALLOCATING MEMORY
FREE: gs_excel, gs_wbooklist, gs_application, gs_wbook,
gs_activesheet,gs_sheets, gs_newsheet, gs_cell1,
gs_cell2, gs_cells, gs_range, gs_font, gs_interior,
gs_columns.
MESSAGE s208(00) WITH '已导出成功!'.
ELSE.
MESSAGE s208(00) WITH '已取消文件导出!' DISPLAY LIKE 'E'.
ENDIF.
ENDFORM.
FORM frm_insert_data USING ps_out LIKE gs_out.
DEFINE zset_data.
SET PROPERTY OF gs_cell1 'VALUE' = &1 .
END-OF-DEFINITION.
CLEAR: gv_colno.
FIELD-SYMBOLS: <fs>.
LOOP AT gt_fieldcat INTO gs_fieldcat.
gv_colno = gv_colno + 1.
CALL METHOD OF gs_excel 'CELLS' = gs_cell1
EXPORTING
ASSIGN COMPONENT gs_fieldcat-fieldname OF STRUCTURE ps_out TO <fs>.
IF <fs> IS ASSIGNED AND <fs> IS NOT INITIAL.
SET PROPERTY OF gs_cell1 'VALUE' = <fs> .
ELSE.
SET PROPERTY OF gs_cell1 'VALUE' = ' ' .
ENDIF.
ENDLOOP.
ENDFORM.OLE 下载数据到 EXCEL 模板及速度优化
Microsoft Excel 在剪贴板上有大量信息。是否保留其内容,以便此后粘贴到其他程序中?
弹窗文本在剪贴板上有大量信息。是否保留其内容,以便此后粘贴到其他程序中?
·要保存剪贴板上的信息,请单击”是”按钮。
·要删除其中的信息以释放内存,请单击”否”按钮。
技术原因
批导/上载程序使用了 ole2 技术,如 ABAP 经典 Excel 处理函数 ALSM_EXCEL_TO_INTERNAL_TABLE ,因为 ole2 技术是通过粘贴板 clipboard_import 和 clipboard_export 来实现数据复制的,所以如果在批导/上载前,存在大量数据的复制(CTRL + C)就会触发这个提示。
几种非技术解决办法
(1)任意复制一个单元格,然后关闭 Excel ,执行批导/上载
注意事项:如果批导/上载仍不成功,需要新开一个 SAP 窗口,关闭原 SAP 窗口,我猜这应该是原始 SAP 窗口还记录着这个信息,盲猜和 SAP GUI 选项的内容相关。
(2)关闭 Excel 剪贴板收集功能
(3)重启电脑,重启大法好
(1)通过 Application.CutCopyMode = False 直接关闭剪贴板,把复制的信息从剪贴板中清空
版权声明:本文为 CSDN 博主「李 BIN 的笔记」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/libin961797440/article/details/128542120ZALSM_EXCEL_TO_INTERNAL_TABLE 完整实施的源代码、附件、说明
实现中有不完美的地方,如 ZALSMEX_TABLINE 结构组件类型未使用数据元素;
其他不影响,可实施后直接使用;FUNCTION ZALSM_EXCEL_TO_INTERNAL_TABLE .
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(FILENAME) LIKE RLGRAP-FILENAME
*" VALUE(I_BEGIN_COL) TYPE I
*" VALUE(I_BEGIN_ROW) TYPE I
*" VALUE(I_END_COL) TYPE I
*" VALUE(I_END_ROW) TYPE I
*" TABLES
*" INTERN STRUCTURE ZALSMEX_TABLINE
*" EXCEPTIONS
*" INCONSISTENT_PARAMETERS
*" UPLOAD_OLE
*"----------------------------------------------------------------------
TYPE-POOLS: OLE2.
TYPES: TY_D_ITABVALUE TYPE ZALSMEX_TABLINE-VALUE,
TY_T_ITAB TYPE ZALSMEX_TABLINE OCCURS 0,
BEGIN OF TY_S_SENDERLINE,
LINE(4096) TYPE C,
END OF TY_S_SENDERLINE,
TY_T_SENDER TYPE TY_S_SENDERLINE OCCURS 0.
CONSTANTS: GC_ESC VALUE '"'.
DATA: EXCEL_TAB TYPE TY_T_SENDER.
DATA: LD_SEPARATOR TYPE C.
DATA: APPLICATION TYPE OLE2_OBJECT,
WORKBOOK TYPE OLE2_OBJECT,
RANGE TYPE OLE2_OBJECT,
WORKSHEET TYPE OLE2_OBJECT.
DATA: H_CELL TYPE OLE2_OBJECT,
H_CELL1 TYPE OLE2_OBJECT.
DATA:
LD_RC TYPE I.
* Rückgabewert der Methode "clipboard_export "
* Makro für Fehlerbehandlung der Methods
DEFINE M_MESSAGE.
CASE SY-SUBRC.
WHEN 0.
WHEN 1.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
WHEN OTHERS. RAISE UPLOAD_OLE.
ENDCASE.
END-OF-DEFINITION.
* check parameters
IF I_BEGIN_ROW > I_END_ROW. RAISE INCONSISTENT_PARAMETERS. ENDIF.
IF I_BEGIN_COL > I_END_COL. RAISE INCONSISTENT_PARAMETERS. ENDIF.
* Get TAB-sign for separation of fields
CLASS CL_ABAP_CHAR_UTILITIES DEFINITION LOAD.
LD_SEPARATOR = CL_ABAP_CHAR_UTILITIES=>HORIZONTAL_TAB.
* open file in Excel
IF APPLICATION-HEADER = SPACE OR APPLICATION-HANDLE = -1.
CREATE OBJECT APPLICATION 'Excel.Application'.
M_MESSAGE.
ENDIF.
CALL METHOD OF APPLICATION 'Workbooks' = WORKBOOK.
M_MESSAGE.
CALL METHOD OF WORKBOOK 'Open' EXPORTING #1 = FILENAME.
M_MESSAGE.
* set property of application 'Visible' = 1.
* m_message.
IF SHEET_NAME = SPACE.
GET PROPERTY OF APPLICATION 'ACTIVESHEET' = WORKSHEET.
M_MESSAGE.
ELSE.
CALL METHOD OF APPLICATION 'WORKSHEETS' = WORKSHEET.
EXPORTING #1 = SHEET_NAME.
CALL METHOD OF WORKSHEET 'Activate'.
M_MESSAGE.
ENDIF.
* mark whole spread sheet
CALL METHOD OF WORKSHEET 'Cells' = H_CELL
EXPORTING #1 = I_BEGIN_ROW #2 = I_BEGIN_COL.
M_MESSAGE.
CALL METHOD OF WORKSHEET 'Cells' = H_CELL1
EXPORTING #1 = I_END_ROW #2 = I_END_COL.
M_MESSAGE.
CALL METHOD OF WORKSHEET 'RANGE' = RANGE
EXPORTING #1 = H_CELL #2 = H_CELL1.
M_MESSAGE.
CALL METHOD OF RANGE 'SELECT'.
M_MESSAGE.
* copy marked area (whole spread sheet) into Clippboard
CALL METHOD OF RANGE 'COPY'.
M_MESSAGE.
* read clipboard into ABAP
CALL METHOD CL_GUI_FRONTEND_SERVICES=>CLIPBOARD_IMPORT
IMPORTING
DATA = EXCEL_TAB
EXCEPTIONS
CNTL_ERROR = 1
* ERROR_NO_GUI = 2
* NOT_SUPPORTED_BY_GUI = 3
OTHERS = 4.
IF SY-SUBRC <> 0.
MESSAGE A037(ALSMEX).
ENDIF.
PERFORM SEPARATED_TO_INTERN_CONVERT TABLES EXCEL_TAB INTERN
USING LD_SEPARATOR.
* clear clipboard
REFRESH EXCEL_TAB.
CALL METHOD CL_GUI_FRONTEND_SERVICES=>CLIPBOARD_EXPORT
IMPORTING
DATA = EXCEL_TAB
CHANGING
RC = LD_RC
EXCEPTIONS
CNTL_ERROR = 1
* ERROR_NO_GUI = 2
* NOT_SUPPORTED_BY_GUI = 3
OTHERS = 4.
* quit Excel and free ABAP Object - unfortunately, this does not kill
* the Excel process
CALL METHOD OF APPLICATION 'QUIT'.
M_MESSAGE.
* >>>>> Begin of change note 575877
* to kill the Excel process it's necessary to free all used objects
FREE OBJECT H_CELL. M_MESSAGE.
FREE OBJECT H_CELL1. M_MESSAGE.
FREE OBJECT RANGE. M_MESSAGE.
FREE OBJECT WORKSHEET. M_MESSAGE.
FREE OBJECT WORKBOOK. M_MESSAGE.
FREE OBJECT APPLICATION. M_MESSAGE.
* <<<<< End of change note 575877
ENDFUNCTION.
*&---------------------------------------------------------------------*
*& Form separated_to_intern_convert
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->I_TAB text
* -->I_INTERN text
* -->I_SEPARATOR text
*----------------------------------------------------------------------*
TYPES: TY_D_ITABVALUE TYPE ZALSMEX_TABLINE-VALUE,
* internal table containing the excel data
TY_T_ITAB TYPE ZALSMEX_TABLINE OCCURS 0,
* line type of sender table
BEGIN OF TY_S_SENDERLINE,
LINE(4096) TYPE C,
END OF TY_S_SENDERLINE,
* sender table
TY_T_SENDER TYPE TY_S_SENDERLINE OCCURS 0.
CONSTANTS: GC_ESC VALUE '"'.
*&---------------------------------------------------------------------*
*& Form SEPARATED_TO_INTERN_CONVERT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->I_TAB text
* -->I_INTERN text
* -->I_SEPARATOR text
*----------------------------------------------------------------------*
FORM SEPARATED_TO_INTERN_CONVERT TABLES I_TAB TYPE TY_T_SENDER
I_INTERN TYPE TY_T_ITAB
USING I_SEPARATOR TYPE C.
DATA: L_SIC_TABIX LIKE SY-TABIX,
L_SIC_COL TYPE KCD_EX_COL.
DATA: L_FDPOS LIKE SY-FDPOS.
REFRESH I_INTERN.
LOOP AT I_TAB.
L_SIC_TABIX = SY-TABIX.
L_SIC_COL = 0.
WHILE I_TAB CA I_SEPARATOR.
L_FDPOS = SY-FDPOS.
L_SIC_COL = L_SIC_COL + 1.
PERFORM LINE_TO_CELL_SEPARAT TABLES I_INTERN
USING I_TAB L_SIC_TABIX L_SIC_COL
I_SEPARATOR L_FDPOS.
ENDWHILE.
IF I_TAB <> SPACE.
CLEAR I_INTERN.
I_INTERN-ROW = L_SIC_TABIX.
I_INTERN-COL = L_SIC_COL + 1.
I_INTERN-VALUE = I_TAB.
APPEND I_INTERN.
ENDIF.
ENDLOOP.
ENDFORM. " SEPARATED_TO_INTERN_CONVERT
*---------------------------------------------------------------------*
FORM LINE_TO_CELL_SEPARAT TABLES I_INTERN TYPE TY_T_ITAB
USING I_LINE
I_ROW LIKE SY-TABIX
CH_CELL_COL TYPE KCD_EX_COL
I_SEPARATOR TYPE C
I_FDPOS LIKE SY-FDPOS.
DATA: L_STRING TYPE TY_S_SENDERLINE.
DATA L_SIC_INT TYPE I.
CLEAR I_INTERN.
L_SIC_INT = I_FDPOS.
I_INTERN-ROW = I_ROW.
L_STRING = I_LINE.
I_INTERN-COL = CH_CELL_COL.
* csv Dateien mit separator in Zelle: --> ;"abc;cd";
IF ( I_SEPARATOR = ';' OR I_SEPARATOR = ',' ) AND
L_STRING(1) = GC_ESC.
PERFORM LINE_TO_CELL_ESC_SEP USING L_STRING
L_SIC_INT
I_SEPARATOR
I_INTERN-VALUE.
ELSE.
IF L_SIC_INT > 0.
I_INTERN-VALUE = I_LINE(L_SIC_INT).
ENDIF.
ENDIF.
IF L_SIC_INT > 0.
APPEND I_INTERN.
ENDIF.
L_SIC_INT = L_SIC_INT + 1.
I_LINE = I_LINE+L_SIC_INT.
ENDFORM. "line_to_cell_separat
*---------------------------------------------------------------------*
FORM LINE_TO_CELL_ESC_SEP USING I_STRING
I_SIC_INT TYPE I
I_SEPARATOR TYPE C
I_INTERN_VALUE TYPE TY_D_ITABVALUE.
DATA: L_INT TYPE I,
L_CELL_END(2).
FIELD-SYMBOLS: <L_CELL>.
L_CELL_END = GC_ESC.
L_CELL_END+1 = I_SEPARATOR .
IF I_STRING CS GC_ESC.
I_STRING = I_STRING+1.
IF I_STRING CS L_CELL_END.
L_INT = SY-FDPOS.
ASSIGN I_STRING(L_INT) TO <L_CELL>.
I_INTERN_VALUE = <L_CELL>.
L_INT = L_INT + 2.
I_SIC_INT = L_INT.
I_STRING = I_STRING+L_INT.
ELSEIF I_STRING CS GC_ESC.
* letzte Celle
L_INT = SY-FDPOS.
ASSIGN I_STRING(L_INT) TO <L_CELL>.
I_INTERN_VALUE = <L_CELL>.
L_INT = L_INT + 1.
I_SIC_INT = L_INT.
I_STRING = I_STRING+L_INT.
L_INT = STRLEN( I_STRING ).
IF L_INT > 0 . MESSAGE X001(KX) . ENDIF.
ELSE.
MESSAGE X001(KX) . "was ist mit csv-Format
ENDIF.
ENDIF.
ENDFORM. "line_to_cell_esc_sep
使用 ALSM_EXCEL_TO_INTERNAL_TABLE 批导/上载大数据量 Excel
分批读取 Excel 数据;
通过减少 Excel 打开关闭次数以减少时间花费(仅需一次打开关闭);
基于 ZALSM EXCEL TO INTERNAL TABLE 封装服务级函数 ZALSM EXCEL2ABAP
封装服务级函数 ZALSM EXCEL2ABAP 实施过程
一般实施:非实施过程
实施过程 1:复制 ZALSM EXCEL TO INTERNAL TABLE 为 ZALSM EXCEL2ABAP
实施过程 2:取消 ZALSM EXCEL2ABAP 的 RFC 属性。
实施过程 3:将仍会使用的参数重新局部定义
实施过程 4:将 ZFM AT ALSM EXCEL2ABAP 的参数复制为此函数参数。
实施过程 5:在打开和关闭 Excel 之前循环执行复制粘贴(注意参数替换)。
说明:注意:此函数为 ZFM AT ALSM EXCEL2ABAP 的进阶版。说明:进阶内容:当分批量处理时无需重复打开和关闭 Excelcall function 'ZALSM_EXCEL2ABAP'
exporting
iv_fname = p_impfn
iv_sname = gt_mv23-sheet
iv_brow = gt_mv23-brow
iv_erow = gt_mv23-erow
iv_bcol = gt_mv23-bcol
iv_ecol = gt_mv23-ecol
iv_batch = 10000
iv_offset = 0
tables
et_data = <gt_main>
et_mesg = lt_mesg.
ABAP 新语法 INNER JOIN 内表 新特性详解
什么时候需要使用 INNER JOIN 代替 FOR ALL ENTRIES IN ?
连接内表,并且使用 聚合函数 时,例如 SUM( ),AVG( )。report ytest_008.
data:lt_key type table of mard with header line. "可以WITH HEADER LINE
if lt_key[] is not initial. "需要判断是否空表
select
matnr, "如果使用了@声明变量,则需要逗号分隔,否则不用
werks,
lgort,
labst
into table @data(lt_mard) "结果表lt_mard基于select字段自动去重
from mard
for all entries in @lt_key "lt_key如果基于连接字段有重复,对结果没有影响
where matnr = @lt_key-matnr
and werks = @lt_key-werks
and lgort = @lt_key-lgort.
endif.report ytest_007.
data:lt_key type table of mard with empty key. "尽量指定关键字,不能WITH HEADER LINE
if lt_key[] is not initial. "不需要判断连接表非空,判断不判断结果一样的,我还是喜欢判断,利用IF-ENDIF的结构化提高代码可读性
sort lt_key by matnr werks.
delete adjacent duplicates from lt_key comparing matnr werks. "需要对lt_key的真正关键字去重,否则可能结果表重复或聚合结果错误
select
a~matnr, "需要逗号分隔
a~werks,
sum( a~labst ) as labst
from mard as a
inner join @lt_key as b on a~matnr = b~matnr "需要@声明变量 如果lt_key基于连接字段有重复,对结果有影响
and a~werks = b~werks "内表与数据库表连接字段长度可以不一致
group by a~matnr,a~werks
into table @data(lt_mard_sum). "需要放在select语句结束句,结果表lt_mard_sum不会基于select字段自动去重
endif.开发注意事项
消息: The primary key of “LT KEY” is ignored because it is generic or is the standard key.
原因:未明确表 LT_KEY 的关键字。
解决:
(1)指定空关键字 with empty key
data:lt key type table of mard with empty key.
(2)指定正确的关键字 with key…
data:lt key type table of mard with key mandt matnr werks。M_TABLES System View 监控数据表行计数和存储大小
RADIOSCREEN
REPORT zjcb_radioscreen.
TABLES: sscrfields,pa0001.
TYPE-POOLS: slis.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001 .
SELECT-OPTIONS:
s_bukrs FOR pa0001-bukrs MODIF ID m1,
s_pernr FOR pa0001-pernr MODIF ID m1,
s_ename FOR pa0001-ename MODIF ID m1.
PARAMETERS: p_file LIKE rlgrap-filename MODIF ID m2.
SELECTION-SCREEN END OF BLOCK b1.
SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE TEXT-002.
PARAMETERS: rb1 RADIOBUTTON GROUP g1 DEFAULT 'X' USER-COMMAND u1,
rb2 RADIOBUTTON GROUP g1,
rb3 RADIOBUTTON GROUP g1
.
SELECTION-SCREEN END OF BLOCK b2.
INITIALIZATION.
*&---------------------------------------------------------------------*
*& SELECTION-SCREEN OUTPUT
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
IF rb2 EQ 'X'.
IF screen-group1 EQ 'M1'.
screen-active = '0'. "隐藏
ELSE.
screen-active = '1'. "显示
ENDIF.
ELSEIF rb1 EQ 'X' OR rb3 EQ 'X'.
IF screen-group1 EQ 'M2'.
screen-active = '0'.
ELSE.
screen-active = '1'.
ENDIF.
ENDIF.
MODIFY SCREEN.
ENDLOOP.SAP 内存与 ABAP 内存
External Session:
当 user 登陆 SAP 后, 就开启了一个 userlogon session。当 user 退出所有 sap window, 就结束了这个 user logon session。一个 userlogon session 最多有 6 个 external session(即 main session,对应有 6 个窗口).
在一个 external session 内调用其它程序将会生成新的 internal session, 比如 call FM, call transaction 或是 submit*** and return 等方式。 当关掉这个 external session 时,也就结束了 external session 下的所有 internal session。一个 External session 最多有 20 个 Internal session.
对于上面这几个 session 之间的关系可以这么简单概括:User session > external session > internal session。
ABAP memory 类似于局部变量,用于同一 externalsession 下 internalsession 间的通信,不同的 externalsession 有不同的 ABAPmemory,同一个 externalsession 里的 internalsession 只能访问相应 session 的 ABAP memory。区别与联系
1、SAP 内存通过 SET/GET PARAMETER,来抛接内存值,如:
SET PARAMETER ID ‘MAT’ FIELD p_matnr.
GET PARAMETER ID ‘MAT’ FIELD p_matnr.
EXPORT p_matnr TO MEMORY ID ‘MAT’.
IMPORT p_matnr FROM MEMORY ID ‘MAT’.
FREE MEMORY ID ‘MAT’.
在介绍作用范围区别之前,先引入三个概念,User Session、External Session 和 Internal Session。
当用户登录 SAP 就生成了 User Session。
打开一个窗口界面,就产生了一个 External Session,窗口关闭,则 External Session 释放。
SAP NW 7.0 之前的版本,一次最多打开 6 个窗口,也就是 6 个 External Session。之后的版本最多打开 16 个窗口。
在一个窗口内,通过 CALL TRANSACTION,SUBMIT 等方式调用程序,则会自动打开 Internal Session,此处会根据调用打开多个 Internal Session。
当窗口关闭时,则释放该 External Session 下的所有 Internal Session。
用户退出登录,则关闭所有 External Session 和 Internal Session。
通俗的讲,ABAP 内存是在同一个窗口内运行的程序之间,进行数据传递。而 SAP 内存可以在多个窗口之间进行数据传递。
在 SAP 中,定义了很多 SAP 内存 ID,存放在 TPARA 表中,通常也与数据元素绑定:DATA:lv_matnr TYPE mara-matnr.
lv_matnr = '2000000585'.
SET PARAMETER ID 'MAT' FIELD lv_matnr.
CALL TRANSACTION 'MM03'." AND SKIP FIRST SCREEN.AMDP-ABAP Managed Database Procedures
AMDP 允许您作为 ABAP 开发人员直接在 ABAP 中编写数据库过程。特殊的 ABAP 类(所谓的 AMDP 类)可以包含用于在 SAP HANA DB 层中生成 DB 过程的嵌入式代码(SQLScript)。AMDP 的基本思想是在 AS ABAP 服务器内管理 SAP HANA 过程及其生命周期。为了允许在 ABAP 层内本地使用 SAP HANA 功能, SAP HANA 数据库过程语言 SQLScript 已集成到 ABAP 堆栈中。AMDP 在 ABAP 类方法(所谓的 AMDP 方法)中实现,这些方法充当 SQLScript 代码的容器。
在 SAP HANA 中,有多种 “代码到数据” 技术可用于在数据库层实现数据密集型计算。SAP HANA 使用 SAP HANA 视图或存储过程在数据库层执行数据密集型计算。之后,这些成果会通过多种 “代码到数据” 技术在 ABAP 应用程序中得到利用。
ABAP 管理数据库过程(AMDP)是实现代码下推功能的一种推荐技术。该框架采用自上而下的方法在 ABAP 环境中创建和管理数据库存储过程。ABAP 管理数据库过程框架确保了 AMDP 存储过程从创建、更改、激活到传输的整个生命周期都由 ABAP 运行时环境在应用层完成。作为一名开发人员,你将在一个 AMDP 类的 AMDP 方法实现中编写存储过程。与传统的 ABAP 方法不同,AMDP 方法是一种独特的方法,它实现特定于数据库的编程语言,如 SQLScript、原生 SQL 以及 L(SAP 内部使用)。关键字 “LANGUAGE” 指定了用于实现存储过程的特定于数据库的语言。CLASS ztest_amdp DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_amdp_marker_hdb.
CLASS-DATA: scarr_tab TYPE ty_scarr.
CLASS-METHODS:
select_scarr IMPORTING VALUE(clnt) TYPE mandt
EXPORTING VALUE(scarr_tab) TYPE ty_scarr,
get_zywjkmx EXPORTING VALUE(et_zywjkmx) TYPE ztt_zywjkmx,
get_zywjkmx_v EXPORTING VALUE(et_zywjkmx) TYPE ztt_zywjkmx.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ztest_amdp IMPLEMENTATION.
METHOD select_scarr
BY DATABASE PROCEDURE FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING scarr.
scarr_tab =
SELECT *
FROM "SCARR"
WHERE mandt = clnt
ORDER BY carrid;
ENDMETHOD.
METHOD get_zywjkmx
BY DATABASE PROCEDURE FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY.
et_zywjkmx =
SELECT zid,zfylx,ZSCENECODE FROM "ZMSL"."ZMSL.SOURCE_TABLE::ZYWJKMX";
ENDMETHOD.
METHOD get_zywjkmx_v
BY DATABASE PROCEDURE FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY.
et_zywjkmx =
SELECT zid,zfylx,'sss' as ZSCENECODE FROM _SYS_BIC."ZMSL.DATA_PROCESS/ZYCDZMX"
where zfylx = 'TBJJT';
ENDMETHOD.
ENDCLASS.
*&---------------------------------------------------------------------*
*& Report zamdp_test
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zamdp_test.
DATA: result TYPE ty_scarr,
gt_zywjkmx TYPE ztt_zywjkmx,
gt_zywjkmx_v TYPE ztt_zywjkmx.
START-OF-SELECTION.
NEW ztest_amdp( )->select_scarr(
EXPORTING clnt = sy-mandt
IMPORTING scarr_tab = result
).
IF NOT cl_abap_dbfeatures=>use_features(
EXPORTING requested_features = VALUE
( cl_abap_dbfeatures=>call_amdp_method )
( cl_abap_dbfeatures=>amdp_table_function ) ) ).
cl_demo_output=>display( 'SYSTEM DOES NOT SUPPORT AMDP. PLEASE USE ANOTHER WAYS' ).
ELSE.
* ztest_amdp=>get_zywjkmx(
* IMPORTING et_zywjkmx = gt_zywjkmx ).
ztest_amdp=>get_zywjkmx_v(
IMPORTING et_zywjkmx = gt_zywjkmx_v ).
cl_demo_output=>display( gt_zywjkmx_v ).
ENDIF.







