在项目中我们经常会遇到SAP与其他应用系统对接的情况,如OA对接SAP的FI、HR模块,生产系统对接SAP的MM模块等等。这里和大家介绍下C#如果调用SAP接口,从而调用SAP接口函数。
下面先贴出代码。这里我创建的是一个C# WInform程序。用于登录接口测试。界面如下图所示:
这里说明下,对于SAP连接来说,用户名、密码、服务器、系统版本号、SYStemID是缺一不可的。并且需要全部正确才行。一般SAP分为正式环境和测试环境。如下所示,是SAP的登录界面。
下面贴出SAP的登录代码,如下所示,在登录按钮的双击事件里面,调用如下代码,进行代码测试。记住要引用SAPnco文件才可以调用。dll的下载地址为:https://download.youkuaiyun.com/download/shenjqiang/12727993。
private void testSave()
{
#region login
RfcConfigParameters parms = new RfcConfigParameters();
parms.Add(RfcConfigParameters.SystemID, textBox2.Text); // Set actual System ID
parms.Add(RfcConfigParameters.SystemNumber, txtaccid.Text); // Set actual System Number
parms.Add(RfcConfigParameters.User, txtUserCode.Text);
parms.Add(RfcConfigParameters.Password, txtPassword.Text);
parms.Add(RfcConfigParameters.Client, "900"); // Set actual client ID
parms.Add(RfcConfigParameters.Language, "ZH");
parms.Add(RfcConfigParameters.PoolSize, "5");
parms.Add(RfcConfigParameters.MaxPoolSize, "10");
parms.Add(RfcConfigParameters.IdleTimeout, "6000");
parms.Add(RfcConfigParameters.AppServerHost, textBox1.Text);
parms.Add(RfcConfigParameters.GatewayHost, textBox1.Text);
parms.Add(RfcConfigParameters.Name, "dev");
//提供必要的登录参数和获得RfcDestination对象对应到SAP系统中,你要调用的fm。
RfcDestination SapRfcDestination = RfcDestinationManager.GetDestination(parms);
RfcRepository SapRfcRepository = SapRfcDestination.Repository;
/// return SapRfcDestination;
#endregion
#region
提供必要的登录参数和获得RfcDestination对象对应到SAP系统中,你要调用的fm。
RfcDestination prd = RfcDestinationManager.GetDestination(parms);
使用RfcDestination对象的repository属性创建一个IRfcFunction对象为fm提供调用
//RfcRepository SapRfcRepository = prd.Repository;
IRfcFunction function = SapRfcRepository.CreateFunction("BAPI_MATERIAL_AVAILABILITY");
IRfcTable tTable = function.GetTable("WMDVSX");
function.SetValue("PLANT", "A000");
function.SetValue("MATERIAL", "8550C0519002");
function.SetValue("UNIT", "只");
function.SetValue("STGE_LOC", "0053");
function.Invoke(prd);
MessageBox.Show("c");
string errMsg = "";
errMsg = function.GetValue("AV_QTY_PLT").ToString();
MessageBox.Show("ddd" + errMsg);
IRfcTable RETURN = function.GetTable("RETURN");
if (RETURN.GetString("MESSAGE").ToString() != "")
{
string se = RETURN.GetString("TYPE").ToString().Trim();
if (se == "I")
{
//Suess.Text = RETURN.GetString("MESSAGE").ToString();
errMsg = "error code:" + function.GetString("NUMBER").Trim();
}
else if (se == "E" || se == "W")
{
errMsg = RETURN.GetString("MESSAGE").ToString();
}
}
MessageBox.Show(errMsg);
MessageBox.Show("cCCC");
#endregion
}
然后,我们就可以调用相关的接口函数了。如下所示,是我写的一个调用移库接口的函数:
/// <summary>
/// 移库接口(将仓库中的地址移到线边仓,线边仓的地址用模板文件名称作为参数传过来)
/// </summary>
/// <param name="prd"></param>
/// <param name="OrderNum"></param>
/// <param name="errMsg"></param>
/// <returns></returns>
public void StorageMoveToLineSilo()
{
#region login
RfcConfigParameters parms = new RfcConfigParameters();
parms.Add(RfcConfigParameters.SystemID, textBox2.Text); // Set actual System ID
parms.Add(RfcConfigParameters.SystemNumber, txtaccid.Text); // Set actual System Number
parms.Add(RfcConfigParameters.User, txtUserCode.Text);
parms.Add(RfcConfigParameters.Password, txtPassword.Text);
parms.Add(RfcConfigParameters.Client, "900"); // Set actual client ID
parms.Add(RfcConfigParameters.Language, "ZH");
parms.Add(RfcConfigParameters.PoolSize, "5");
parms.Add(RfcConfigParameters.MaxPoolSize, "10");
parms.Add(RfcConfigParameters.IdleTimeout, "6000");
parms.Add(RfcConfigParameters.AppServerHost, textBox1.Text);
parms.Add(RfcConfigParameters.GatewayHost, textBox1.Text);
parms.Add(RfcConfigParameters.Name, "dev");
//提供必要的登录参数和获得RfcDestination对象对应到SAP系统中,你要调用的fm。
RfcDestination prd = RfcDestinationManager.GetDestination(parms);
//使用RfcDestination对象的repository属性创建一个IRfcFunction对象为fm提供调用
RfcRepository SapRfcRepository = prd.Repository;
#endregion
string errMsg = "";
IRfcFunction function = SapRfcRepository.CreateFunction("BAPI_GOODSMVT_CREATE");
IRfcStructure strCode = function.GetStructure("GOODSMVT_CODE");
strCode.SetValue("GM_CODE", "04");
IRfcStructure strHeader = function.GetStructure("GOODSMVT_HEADER");
strHeader.SetValue("PSTNG_DATE", DateTime.Today.ToString("yyyy-MM-dd"));
strHeader.SetValue("DOC_DATE", DateTime.Today.ToString("yyyy-MM-dd"));
strHeader.SetValue("PR_UNAME", txtUserCode.Text);
IRfcFunction functioncmt = SapRfcRepository.CreateFunction("BAPI_TRANSACTION_COMMIT");
IRfcTable tTable = function.GetTable("GOODSMVT_ITEM");
functioncmt.SetValue("WAIT", "X");
RfcSessionManager.BeginContext(prd);
for (int i = 0; i < 1; i++)
{
tTable.Append();
tTable.CurrentRow.SetValue("MATERIAL", "77040600001258");//物料编号
tTable.CurrentRow.SetValue("PLANT", "A000");//工厂
tTable.CurrentRow.SetValue("STGE_LOC", "0039");//仓库
tTable.CurrentRow.SetValue("MOVE_TYPE", "311");//同一工厂不同库存移库
tTable.CurrentRow.SetValue("ENTRY_QNT", 5);
//tTablw.SetValue("ENTRY_UOM", mdList[i].ENTRY_UOM);
//tTablw.SetValue("QUANTITY", mdList[i].iquantity);//单位
tTable.CurrentRow.SetValue("MOVE_PLANT", "A000");
tTable.CurrentRow.SetValue("MOVE_STLOC", "0153");//移库到线边仓
tTable.CurrentRow.SetValue("RESERV_NO", "0001");//预留编号
tTable.CurrentRow.SetValue("RES_ITEM", "0017683144");//预留项目编号
}
function.Invoke(prd);
//functioncmt.Invoke(prd);
RfcSessionManager.EndContext(prd);
IRfcStructure strReturn = function.GetStructure("GOODSMVT_HEADRET");
errMsg = strReturn.GetValue("MAT_DOC").ToString();
IRfcTable Return = function.GetTable("RETURN");
if (Return.RowCount > 0)
{
if (Return.GetString("TYPE").ToString().Trim() == "I")
{
errMsg = "凭证号:" + function.GetString("NUMBER").Trim();
MessageBox.Show(errMsg);
prd = null;
}
else if (Return.GetString("TYPE").ToString().Trim() == "E")
{
errMsg = Return.GetString("MESSAGE").ToString();
MessageBox.Show(errMsg);
prd = null;
return;
}
}
else
{
//IRfcStructure strReturn = function.GetStructure("GOODSMVT_HEADRET");
//errMsg = strReturn.GetValue("MAT_DOC").ToString();
}
}
SAP 的接口使用ABAP开发的,这里我们调用时,一般需要和SAP开发人员进行接口参数对接,由SAP开发人员提供所需参数,然后我们来传递参数即可。所有的接口调用方式大同小异。只是传参和返回的数据不一样。因此其他函数也可以参考上面的来进行扩展。
欢迎有兴趣的小伙伴一起交流讨论!