PyRFC 调用自定义函数与调用 SAP 标准的 RFM (Remote enabled Function Module) 从技术上来说并没有任何区别。但从个人使用的体验来看,因为 Python 语言的简洁、灵活和强大,基于 PyRFC 的 RFC 调用,比完全在 ABAP 中编码,效率更高,也简单很多。
本篇基于这样一个任务:SAP 中通过 BDC 的方式录制事务码 AS01 来创建固定资产并生成自定义的函数 (ZFM_AS01),使用 Python 从 Excel 中读取数据,通过 PyRFC 调用 ZFM_AS01 来批量创建固定资产。本人之前写过关于批量创建固定资产以及如何使用 BDC 的文章,各位小伙伴如何需要参考,请点击下面的链接:
自定义函数
使用事务码 SHDB 录制 AS01 创建固定资产建后,在 SHDB 的 Overview 界面,点击 “Create Function Module” 按钮,生成函数 (function module)。
SAP 将 BDC 具有共性的几个子程序放在 include 程序 BDCRECXY 中。ZFM_AS01 函数的主要 importing 参数如下:
框起来的是与业务相关的重要参数,参数编号没有太大意义,所以我修改了参数的名称:
ZFM_AS01 已经是一个可以使用的函数,但函数的返回值 msgtab (结构体类型 bdcmsgcoll) 只包括消息编号,没有消息的描述:
为了增加友好性,根据消息编号,从数据表 T100 获取消息文本的内容,并写在 msgv1 字段中返回。函数获取消息文本的代码如下:
完成后 zfm_as01 的代码如下:
PyRFC 调用自定义函数
在 Python 中,将 SAP 连接参数放在 sap_systems.py
文件中,代码如下:
import pyrfc
# D01配置连接到D01系统
D01 = {
"user": "stone",
"passwd": "w123456",
"ashost": "192.168.44.100",
"sysnr": "00",
"lang": "ZH",
"client": "001"
}
def get_sap_connection(sap_logon_params):
conn = pyrfc.Connection(**sap_logon_params)
return conn
def current_sap_connection():
return get_sap_connection(D01)
对调用 ZFM_AS01
函数的进行一个简单的封装,方便后续调用,代码放在 fixed_assets.py
文件中:
from SAP.sap_systems import current_sap_connection
class FixedAsset(object):
def __init__(self) -> None:
self.sap_connection = current_sap_connection()
def create_asset(self, asset_info):
conn = self.sap_connection
result = conn.call('ZFM_AS01',
ANLKL=asset_info['asset_class'],
BUKRS=asset_info['company_code'],
NASSETS="1",
TXT50=asset_info['description'],
MEINS="EA",
KOSTL=asset_info['cost_center']
)
# 选取三个最重要的字段返回
raw_return = result['MESSTAB']
return_info = []
for item in raw_return:
line = {
"message type": item["MSGTYP"],
"message number": item["MSGID"] + item["MSGNR"],
"message": item["MSGV1"]
}
return_info.append(line)
return return_info
使用 pandas 从 Excel 文件中读取数据,然后调用 FixedAsset 类的 create_asset() 方法实现最终调用。代码放在 main.py 文件中:
from SAP.fixed_assets import FixedAsset
import pandas as pd
if __name__ == "__main__":
# 从Excel读取数据
asset_data = pd.read_excel("AS01_data.xlsx", sheet_name="Sheet1")
fixedasset_obj = FixedAsset()
# 遍历数据,每一行作为dict
for indx, row in asset_data.iterrows():
asset_info = {
"asset_class": row["Asset Class"],
"company_code": row["Company Code"],
"description": row["Description"],
"cost_center": row["Cost Center"]
}
# 创建固定资产
rv = fixedasset_obj.create_asset(asset_info)
print(rv)
要创建的固定资产数据放在 Excel 文件 AS01_Data.xlsx 中,文件的格式如下: