从外部环境调用自定义函数 (FM, Function Module)与调用 SAP 内置的函数并没有不同,需要注意的是在 SAP 系统自定义 FM 的要点:
1)FM 必须是 Remote-enabled Module (属性(attribute)中设置)
2)参数必须是 pass by value,不允许 pass by reference
下面是具体的例子,当然不会采用加减乘除四则运算这样无聊的例子。我们自定义一个函数,根据透明表的表名获取所有字段,信息比RFC_READ_TABLE
函数要多,后面综合实例还会就这个函数实现 C# 的应用场景。
首先在 SAP 中使用 SE11 创建一个结构,作为函数输出的 table 参数。
然后使用 SE37 创建函数:Z_FM_TABLE_FIELDS
FUNCTION z_fm_table_fields.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(TAB_NAME) TYPE TABNAME
*" TABLES
*" TAB_FIELDS STRUCTURE ZTABFIELDS
*"----------------------------------------------------------------------
DATA: BEGIN OF gt_tabflds OCCURS 0 ,
tabname LIKE dd03l-tabname,
fieldname LIKE dd03l-fieldname,
keyflag LIKE dd03l-keyflag,
position LIKE dd03l-position,
rollname LIKE dd03l-rollname,
datatype LIKE dd03l-datatype,
leng LIKE dd03l-leng,
ddtext LIKE dd04t-ddtext,
scrtext_s LIKE dd04t-scrtext_s,
scrtext_m LIKE dd04t-scrtext_m,
scrtext_l LIKE dd04t-scrtext_l,
END OF gt_tabflds.
SELECT tabname
fieldname
keyflag
position
rollname
datatype
leng
INTO CORRESPONDING FIELDS OF TABLE gt_tabflds
FROM dd03l
WHERE tabname = tab_name.
SORT gt_tabflds BY position.
DELETE gt_tabflds WHERE fieldname+0(1) = '.'.
LOOP AT gt_tabflds.
SELECT SINGLE ddtext
scrtext_s
scrtext_m
scrtext_l
INTO CORRESPONDING FIELDS OF gt_tabflds
FROM dd04t
WHERE rollname = gt_tabflds-rollname
AND ddlanguage = sy-langu.
MODIFY gt_tabflds.
ENDLOOP.
LOOP AT gt_tabflds.
CLEAR tab_fields.
MOVE-CORRESPONDING gt_tabflds TO tab_fields.
APPEND tab_fields.
ENDLOOP.
ENDFUNCTION.
C# 通过 RFC 调用
1)定义 TableFields (TableFields.cs)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SAPZFunction
{
public class TableFields
{
public string TabName { get; set; } // table name
public string FieldName { get; set; } // field name
public string KeyFlag { get; set; } // flag to indicate whether the field is primary key
public string Positiion { get; set; } // position
public string RollName { get; set; } // data element name
public string DataType { get; set; } // data type
public int Leng { get; set; } // length
public string DDText { get; set; } // explaintory short text
public string ScrText_S { get; set; } // short field label
public string ScrText_M { get; set; } // medium field label
public string ScrText_L { get; set; } // long field label
}
}
- 调用 RFC (ZFunction.cs)
using System;
using System.Collections.Generic;
using SAPLogonCtrl;
using SAPFunctionsOCX;
using SAPTableFactoryCtrl;
using ConnectionProvider;
namespace SAPZFunction
{
public class ZFunction
{
private Connection conn; // sap connection
// demo how to use GetFields
public List<TableFields> GetTableFieldsDemo()
{
var fields = new List<TableFields>();
bool isSuccessful = SAPConnection.SilentLogon(
"192.168.65.100", "D01", 00, "001", "STONE", "PWD", "ZH");
if (isSuccessful) {
conn = SAPConnection.Connection;
fields = this.GetFields("SKB1");
SAPConnection.Logoff();
}
return fields;
}
// get fields from SAP table
public List<TableFields> GetFields(String tableName)
{
var fieldsList = new List<TableFields>();
if (conn == null
|| conn.IsConnected != CRfcConnectionStatus.tloRfcConnected) {
return null;
}
SAPFunctions functions = new SAPFunctions();
functions.Connection = conn;
Function fm = functions.Add("Z_FM_TABLE_FIELDS");
fm.get_Exports("TAB_NAME").Value = tableName;
fm.Call();
Table fields = fm.Tables["TAB_FIELDS"];
fieldsList = this.Convert(fields); // convert table to List<TableFields>
return fieldsList;
}
private List<TableFields> Convert(Table itab)
{
var fields = new List<TableFields>();
if (itab.RowCount == 0) return null;
for (int row = 1; row <= itab.RowCount; row++) {
var entity = new TableFields();
entity.TabName = itab.get_Cell(row, 1); // first column
entity.FieldName = itab.get_Cell(row, 2);
entity.KeyFlag = itab.get_Cell(row, 3);
entity.Positiion = itab.get_Cell(row, 4);
entity.RollName = itab.get_Cell(row, 5);
entity.DataType = itab.get_Cell(row, 6);
entity.Leng = itab.get_Cell(row, 7);
entity.DDText = itab.get_Cell(row, 8);
entity.ScrText_S = itab.get_Cell(row, 9);
entity.ScrText_M = itab.get_Cell(row, 10);
entity.ScrText_L = itab.get_Cell(row, 11);
fields.Add(entity);
}
return fields;
}
}
}
- 单元测试 (TestZFM.cs)
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SAPZFunction;
using System.Collections.Generic;
namespace UnitTestProject
{
[TestClass]
public class TestZFM
{
[TestMethod]
public void Test_ZFunction()
{
ZFunction zfm = new ZFunction(); // Customized fm in SAP
List<TableFields> fields = zfm.GetTableFieldsDemo();
foreach (TableFields item in fields) {
Console.WriteLine(item.TabName);
Console.WriteLine(item.FieldName);
Console.WriteLine(item.Positiion);
Console.WriteLine(item.KeyFlag);
Console.WriteLine(item.RollName);
Console.WriteLine(item.DataType);
Console.WriteLine(item.Leng);
Console.WriteLine(item.DDText);
Console.WriteLine(item.ScrText_S);
Console.WriteLine(item.ScrText_M);
Console.WriteLine(item.ScrText_L);
Console.WriteLine("---------------------------");
}
}
}
}