分类 SAP 下的文章

SAP 增强已经发展过几代了,可参考 SAP 标准教材 BC425 和 BC427。简单的说SAP的用户出口总共有四代:
1、第一代  基于源代码的增强。
SAP提供一个空代码的子过程,在这个子过程中用户可以添加自己的代码,控制自己的需求。这类增强都需要修改sap的标准代码。
示例:USEREXIT.. in SAPMV45A

源代码增强以子程序形式发布,在 SAP 的发行版本中,使用 PERFORM 调用这些子程序,它们在发布时都是空的,集中在一些文件名倒数第二个字符为 Z 的包含程序中。用户增强时,应首先到 service marketplace 申请对象键,然后才能修改这些子程序,这些子程序可以使用程序中所有的全局数据。
屏幕增强以客户屏幕形式发布,它们包含在标准程序中,没有什么特别规律。
这种源代码增强和屏幕增强的说明可以从事务码 spro 后台配置中相关模块的路径里面找到。
同时使用的针对数据表的增强是 append structure,可以在事务码 se11 中打开透明表,点击应用工具栏最右边的那个 append structure 按钮就能为数据表追加新的字段。
2、第二代 基于函数模块的增强。
SAP提供的是CUSTOMER-FUNCTION,它是通过SMOD和CMOD完成实现。

源代码增强以函数模块形式发布,在 SAP 的发行版本中,使用 CALL CUSTOMER-FUNCTION 调用这些函数模块,它们在发布时只有一句代码 INCLUDE xxxxxxx。用户增强时,无需申请对象键,直接双击这个包含,然后回车,就可以创建相关的包含文件,编写相应的代码了。这些函数模块中只能使用接口中传递的参数,不能使用调用程序的全局变量。
屏幕增强也包含在函数模块所属的函数组中。
针对数据表的增强是 CI_ 结构,这些结构以 .INCLUDE 结构的形式包含在 SAP 发布的数据表中,用户可以通过向这些结构中添加字段而对数据表进行增强。
上述这类增强通过事务码 SMOD 进行维护,CMOD 进行实现。SMOD 中的一个增强可以包含上述的源代码、屏幕和表结构增强,按照较容易理解的逻辑结构来管理这些增强,使用相对更加便利。
3、第三代  基于面向对象概念的增强。
SAP提供的第三代的用户出口就是BADI,它使用类、接口及方法等面向对象的概念,采用一种使用面向对象的方法来进行SAP 增强,他的调用方式是CALL METHOD (instance),(相关的TCODE是SE18和SE19),可以通过EXIT_HANDLER这个单词查找BADI。

BAdI(Business Add-Ins),源代码增强以接口形式发布,在 SAP 的发行版本中,也是通过接口的方法调用来使用。用户增强时,实际是实现一个(或多个)基于这个接口的实现类。由于接口可以有多个实现类,所以对一个增强可以有多种不同的源代码,它们通过过滤器应用于不同的业务场景。
这种增强使用事务码 SE18 创建、SE19 实现。

4、第四代:Switch Framework。
SAP 从 NetWeaver 7.0 以后推出的新增强体系,它对 BAdI 做出了改进,改叫新 BAdI 了。还新增 Enhancement Spot 和 Enhancement Section 以及隐式增强点的概念,基本可以在面向对象的程序里实现处处皆可增强的最高境界。


方法一、利用TCODE寻找增强(第二代的增强)
    执行一个程序(源代码后附),在选择屏幕处输入你所需要增强的程序TCODE,执行後,就会出现一个列表,那里就有关于如何增强这个的绝大部分SMOD增强。
    点击进去,本人手动寻找需要的增强。
    这是第二代增强

 

 方法二、利用系统函数寻找     
    MODX_FUNCTION_ACTIVE_CHECK
    在这个FUNCTION的代码最后添加一个断点。执行需要增强的TCODE,如果有增强,就会自动跳入DEBUG界面。在DEBUG界面,查看f_tab字段,这里面所显示的Smod就是关于这个TCODE所有的增强项目的列表。这些增强都是属于EXIT_XXXXXX_XXX这种形式。
    至于如何查看这个增强是属于哪个SMOD,查阅 MODSAP这个表(SAP Enhancements).
    这是第二代增强。


    还有一些FUNCTION供参考:
    [1].DYNP_VALUES_READ
    [2]. MODX_ALL_ACTIVE_MENUENTRIES(菜单增强)
    [3].MODX_FUNCTION_ACTIVE_CHECK(出口函数增强)
    [4].MODX_MENUENTRY_ACTIVE_CHECK(菜单增强)
    [5].MODX_SUBSCREEN_ACTIVE_CHECK(屏幕增强)
    这些的使用方法和上述的一样,能够针对各种情况寻找增强。


    方法三、从程序代码中找
对于第一代增强,可以用以下方法查找增强:
   在需要增强的程序里面,打开SYSTEM——》status,双击进入PROGRAM,打开欲增强的程序,点击工具栏上的“Display Object List”按钮,选择Subroutines,查找以“UserExit”开头的子程序,根据子程序前面的注释文档来查找用户出口, 由描述来确定合适的需要增强的FORM。

 

对于第二代增强,可以用以下方法查找增强

用户增强通常包括下面3类,顾名思义,就是增强SAP的可能没有提供的功能(通过后台配置也不能实现).
1.E Enhancement exits :就是常说User_exit (用户出口)
使用SE37搜索EXIT*的函数大都是做exit用的,通常里面预包含了一个Z开头
的程序. SE16查询TFDIR(函数表)输入EXIT*也可.
2.C GUI codes( GUI接口增强)
3. S Subscreens (屏幕增强)
Enhancement在表MODSAP可看到,而TFDIR字段 MAND(值为C表示此出口函数被激活).使用SMOD(CMOD)当然可激活exit function,有时候一时难以查询到相关Enhancement时可使用下面程序将出口函数激活.

REPORT Zactexitfun .
data ztfdir like tfdir .
* select single * from tfdir into ztfdir
* where FUNCNAME =
* 'EXIT_SAPMM06E_013'.
* ztfdir-MAND = 'C' .
* update tfdir from ztfdir.
* 将EXIT_SAPMM06E_013换成实际所需exit函数名
update tfdir set MAND = 'C'.
where FUNcname = 'EXIT_SAPMM06E_013'.

***当然也可SE16:MODSAP表enhancement输入EXIT_SAPMM06E_013然后得到enhancement name MM06E005后使用SMOD测试激活exit函数.

Table:
[1]. TFDIR->function module table
[2]. MODSAP->sap enhancement table
[3]. TSDIR->Dynpro Areas CALL CUSTOMER SUBSCREEN(屏幕增强)
[4]. CUATEXTS-> GUI Interface: Menu Texts Changed(GUI 菜单文本增强)

***注意,为了确保一个出口被真正应用,必须同时激活相关程序(SE38)和出口函数(SMOD|CMOD,反正就是要保证tfdir-mandt=’C’,用程序也可.
    方法四、针对BADI的增强 
     
    1、badi对象的消息存储在SXS_INTER, SXC_EXIT, SXC_CLASS 和SXC_ATTR 这四个表中。
来源:www.va1314.com/bc
    2、sap程序都会调用cl_exithandler=>get_instance来判断对象能否具有,并前往实例;其实get_instance就是对上述几个表和他们的视图(V_EXT_IMP 和 V_EXT_ACT)进行查询和搜索。

因此可以通过SE24-> CL_EXITHANDLE->方法GET_INSTANCE设置断点,获取相关的BADI。
    3、基于这个机理,用ST05来监控一个TCODE来跟踪,然后选择查找有关上述几个表和视图的操做,就可获得相关BADI。
    4、se18 查找接口,se19 实现接口就能够实现用户增强。

 

方法五、通过SPRO后台配置相关模块下的菜单查找,此处的增强组件有比较详细的说明

 

原文链接丢失,如有侵权,请与我联系删除

 

原文链接:https://blog.csdn.net/dobear_0922/article/details/2393235

--1.删除测试用表
IF OBJECT_ID(N'Test', N'U') IS NOT NULL
    DROP TABLE Test

--2.建立测试表,并填充测试数据
SELECT * INTO Test 
FROM
(
    SELECT CONVERT(DATETIME, '2008-1-1', 120) AS dt UNION ALL SELECT '2008-1-15' UNION ALL SELECT '2008-1-31'
    UNION ALL SELECT '2008-2-1' UNION ALL SELECT '2008-2-15' UNION ALL SELECT '2008-2-29'
    UNION ALL SELECT '2007-2-1' UNION ALL SELECT '2007-2-15' UNION ALL SELECT '2007-2-28'
    UNION ALL SELECT '2007-4-1' UNION ALL SELECT '2007-4-15' UNION ALL SELECT '2007-4-30'
) T

--3.根据日期计算当月有多少天
SELECT *
    --当月天数=32-[(上月最后最后一天+32天)的日期值]
    --e.g. '2008-1':32-day('2008-2-1') '2008-2':32-day('2008-3-3')
    , ds1=32-DAY(dt-DAY(dt)+32)
    
    --当月天数=当月最后一天的日期值
    --e.g. '2008-1':day('2008-1-31') '2008-2':day('2008-2-29')
    , ds2=DAY(DATEADD(mm,1,dt)-DAY(DATEADD(mm,1,dt)))    
    , ds3=DAY(DATEADD(mm, MONTH(dt), dt-DATEPART(dy,dt)))    
    , ds4=DAY(DATEADD(d, -1, CONVERT(VARCHAR(8), DATEADD(m,1,dt), 120)+'01'))

    --当月天数=本月一号到下月一号的天数差值
    --e.g. datediff(d, '2008-1-1', '2008-2-1')
    , ds5=DATEDIFF(d, DATEADD(dd,1-DAY(dt),dt), DATEADD(mm, 1, DATEADD(dd,1-DAY(dt),dt)))
    , ds6=DATEDIFF(d, DATEADD(m, DATEDIFF(m, 0, dt), 0), DATEADD(m, datediff(m, 0, dt)+1, 0))
    , ds7=DATEDIFF(d, CONVERT(VARCHAR(8), dt, 120)+'01', CONVERT(VARCHAR(8), DATEADD(m,1,dt), 120)+'01')        
from Test

/*
dt                      ds1         ds2         ds3         ds4         ds5         ds6         ds7
----------------------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
2008-01-01 00:00:00.000 31          31          31          31          31          31          31
2008-01-15 00:00:00.000 31          31          31          31          31          31          31
2008-01-31 00:00:00.000 31          31          31          31          31          31          31
2008-02-01 00:00:00.000 29          29          29          29          29          29          29
2008-02-15 00:00:00.000 29          29          29          29          29          29          29
2008-02-29 00:00:00.000 29          29          29          29          29          29          29
2007-02-01 00:00:00.000 28          28          28          28          28          28          28
2007-02-15 00:00:00.000 28          28          28          28          28          28          28
2007-02-28 00:00:00.000 28          28          28          28          28          28          28
2007-04-01 00:00:00.000 30          30          30          30          30          30          30
2007-04-15 00:00:00.000 30          30          30          30          30          30          30
2007-04-30 00:00:00.000 30          30          30          30          30          30          30

(12 row(s) affected)
*/

--4.删除测试表
DROP TABLE Test
————————————————
原文链接:https://blog.csdn.net/dobear_0922/article/details/2393235

如图,打印内容压在框线上,但是打印预览是正常的

预览图如下,预览是正常的

预览用PDF!命令,导出PDF,也是正常的,就直接打印有问题,不是打印机的问题,用Adobe PDF打印机也是不行

如果只有一例的话用上述命令保存PDF文件可以解决,

如果大批量的话,调整样式,右缩进0.05CM 

让多余的显示在下一行就可以了,哪怕多缩进一些

 

最近凭证打印需要附加打印条形码,遂做了一个小例子,结果还出现了很多的小问题,按领导的话说,这就是经验!

首先:SE73 -> 系统条形码 -> 更改 -> 创建 -> 选择 NEW 

 

然后输入名字和短文本:

选择编码类型,此处我选择Code 128。关于编码类型介绍引用一个博主的链接:https://www.cnblogs.com/mingdashu/p/7007747.html

选择条码对齐方式:

设置大小:

确定,生成请求号以后,该条码样式创建结束,先来测试一下:找到刚才创建的条码,运行

选择打印预览,可以自定义条码数据

 然后用你的手机扫一扫,或者扫码枪

 如果扫不到,不要担心,电脑分辨率的问题,把条码放大一下就扫到了

下面就要把这个条码样式应用在smartforms里面了

smartforms创建样式:

字符样式创建节点,标准设置条形码名称选择刚才创建的条码样式

激活,然后创建smartforms:ZTEST_TXM

定义一个变量,并赋值

创建条形码文本:附加创建的条形码字符格式,拖进变量字段

注意:如果附加不上字符格式,去除该段落格式和字符格式的字体大小,及间距数据,并且不要复制变量或者文本,先选择字符格式,然后手输或者从字段列表拖拽字段就可以

 

 

然后激活,运行smartforms:要是扫描还不识别,就运行命令:PDF!  导出本地PDF放大条形码

喏:放大

就识别了!

到此就完结了,有点过于详细是不是,哈哈!

 

一、FOR ALL ENTRIES IN 案例

今天碰到工单报工统计分析表查询速度特别慢

经查看源代码:

  SELECTafpo~dwerk afko~aufnr afpo~matnr AS plnbez afpo~charg afpo~psmng afko~fevor afko~aufplFROMafko INNER JOIN afpoON afko~aufnr =afpo~aufnrINTO CORRESPONDING FIELDS OF TABLEit_afpoWHERE afpo~dwerk =p_dwerkAND afpo~aufnr INp_aufnrAND afpo~matnr INp_matnrAND afko~fevor INp_fevorAND afpo~charg INp_charg.IF f_wr = 'X'.SELECT *
      FROMafruINTO CORRESPONDING FIELDS OF TABLEit_afruFOR ALL ENTRIES INit_afpoWHERE werks = it_afpo-dwerkAND aufnr = it_afpo-aufnrAND ersda INp_ersdaAND prdut INp_prdutAND stokz <> 'X'
       AND stzhl = 0.ELSE.SELECT *
      FROMafruINTO CORRESPONDING FIELDS OF TABLEit_afruFOR ALL ENTRIES INit_afpoWHERE werks = it_afpo-dwerkAND aufnr = it_afpo-aufnrAND ersda INp_ersdaAND prdut INp_prdut.ENDIF.