本文主要记录C#这边的代码,至于SAP那边的操作不做讨论。
C#连接SAP获取RFC函数数据,一般有两种方法。
- 使用COM组件获取数据
- 使用SAP的NCO connector
一开始使用的COM组件来访问SAP,开发时安装好SAP,这样通过COM引用Interop.SAPFunctionsOCX.dll、Interop.SAPLogonCtrl.dll、Interop.SAPTableFactoryCtrl.dll这三个DLL
主要C#代码如下:
using SAPFunctionsOCX; using SAPLogonCtrl; using SAPTableFactoryCtrl; private void btnGetResult_Click(object sender, EventArgs e) { try { //Console.WriteLine("try to logon..."); string str = String.Empty; SAPLogonControlClass connctl = new SAPLogonControlClass(); //下面的参数值根据实际情况赋值 connctl.Client = ""; connctl.Language = Common.GetConfigMessage(@"", @"/Language");//语言 connctl.ApplicationServer = "";//Application server IP connctl.SystemNumber = ;// connctl.User = Common.GetConfigMessage(@"", @"/User"); connctl.Password = Common.GetConfigMessage(@"", @"/Password"); //自定义变量 string po = Common.GetConfigMessage(@"", @"/PO");//订单号 string materials = Common.GetConfigMessage(@"",@"/Materials");// //实例化连接对象 Connection conn = (Connection)connctl.NewConnection(); //conn.CodePage = "8400";//简体中文 -->Fail 会引发异常 未解决 //登陆 if (conn.Logon(null, true)) { //Console.WriteLine("SUCCESS!"); this.textResult.Text = "logon ok..."; } SAPFunctionsClass functions = new SAPFunctionsClass(); functions.Connection = conn; //这里就可以传入Function Name Function fucntion = (Function)functions.Add("*********"); //这里是传入值参数 Parameter parameter1 = (Parameter)fucntion.get_Exports("*******"); parameter1.Value = po; //调用函数 if (fucntion.Call()) { Tables Tables = (Tables)fucntion.Tables; Table table = (Table)Tables.get_Item("****");//传出Table参数 DataTable dt = ToDataTable(table);//转为DataTable string HtmlBody = ExportDatatableToHtml(dt); //DataTable输出HTML System.IO.File.WriteAllText(@"d:\abc.HTML", HtmlBody); foreach (DataRow row in dt.Rows) { string itemNo = row["POSNR"].ToString(); string material = row["MATNR"].ToString(); #region Get Bom if (materials.IndexOf(material) >=0) { //传入Function Function fucntion2 = (Function)functions.Add("*****"); //传入参数 Parameter parameter21 = (Parameter)fucntion2.get_Exports("*****"); parameter21.Value = po; Parameter parameter22 = (Parameter)fucntion2.get_Exports("****"); parameter22.Value = Convert.ToInt32(itemNo); Parameter parameter23 = (Parameter)fucntion2.get_Exports("*****"); parameter23.Value = "S"; Parameter parameter24 = (Parameter)fucntion2.get_Exports("*****"); parameter24.Value = "X"; //传出参数 Parameter parameter25 = (Parameter)fucntion2.get_Imports("*****"); SAPFunctionsOCX.Structure parameter26 = (SAPFunctionsOCX.Structure)fucntion2.get_Imports("****"); //调用函数 if (fucntion2.Call()) { Tables Tables2 = (Tables)fucntion2.Tables; SaveToFile(Path.Combine(folderPath, material + "-PE_INSTANCE.txt"), parameter25.Value.ToString()); for (int i = 1;i<=parameter26.ColumnCount; i ++) { SaveToFile(Path.Combine(folderPath, material + "-PE_SODATA.txt"), parameter26.ColumnName[(short)i] +":"+ parameter26.Value[i]); } } } #endregion } table.FreeTable(); //释放Table } //退出登陆 conn.Logoff(); this.textResult.Text = "ok\r\n" + str; } catch (Exception ex) { MessageBox.Show(ex.ToString()); this.textResult.Text = ex.ToString(); } }
/// <summary> /// 从SAP Table转DataTable /// </summary> /// <param name="itab"></param> /// <returns></returns> public static DataTable ToDataTable(SAPTableFactoryCtrl.Table itab) { DataTable dt = new DataTable(); // Header for (int col = 1; col <= itab.ColumnCount; col++) { dt.Columns.Add(itab.get_ColumnName(col), typeof(string)); } // Line items for (int row = 1; row <= itab.RowCount; row++) { DataRow dr = dt.NewRow(); for (int col = 1; col <= itab.ColumnCount; col++) { dr[col - 1] = itab.get_Cell(row, col); } dt.Rows.Add(dr); } return dt; }
其中描红的代码处出现异常,一旦不注释掉就会异常。
注释掉后数据可以正常获取,但是所有的中文都变为 "#"
实在找不到解决方法,最后就又换位NCO方式抓取。
通过VS的NuGet获取NCO
项目的目标框架变为.NET Framework4
主要代码如下:
using SAP.Middleware.Connector; //登陆SAP前的准备工作 public class MyConfig : IDestinationConfiguration { public RfcConfigParameters GetParameters(String destinationName) { if ("Test1".Equals(destinationName)) { RfcConfigParameters parms = new RfcConfigParameters(); parms.Add(RfcConfigParameters.AppServerHost, ""); //SAP主机IP parms.Add(RfcConfigParameters.SystemNumber, ""); //SAP实例 parms.Add(RfcConfigParameters.User, ""); //用户名 parms.Add(RfcConfigParameters.Password, ""); //密码 parms.Add(RfcConfigParameters.Client, ""); // Client parms.Add(RfcConfigParameters.Language, "ZH"); //登陆语言 parms.Add(RfcConfigParameters.PoolSize, "5"); parms.Add(RfcConfigParameters.MaxPoolSize, "10"); parms.Add(RfcConfigParameters.IdleTimeout, "60"); parms.Add(RfcConfigParameters.Codepage, "8400"); //解决中文问题 return parms; } else return null; } public bool ChangeEventsSupported() { return false; } public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged; } private void btnGetResult_Click(object sender, EventArgs e) { try { nco(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); this.textResult.Text = ex.ToString(); } } public void nco() { IDestinationConfiguration ID = new MyConfig(); RfcDestinationManager.RegisterDestinationConfiguration(ID); RfcDestination test = RfcDestinationManager.GetDestination("Test1"); RfcDestinationManager.UnregisterDestinationConfiguration(ID); ncoTest(test); } public void ncoTest(RfcDestination prd) { RfcRepository repo = prd.Repository; IRfcFunction companyBapi = repo.CreateFunction("***"); //调用函数名 companyBapi.SetValue("****", po); //设置Import的参数 companyBapi.Invoke(prd); //执行函数 IRfcTable table = companyBapi.GetTable("*****"); //获取相应的表 DataTable dt = ToDataTable(table); string HtmlBody = ExportDatatableToHtml(dt); System.IO.File.WriteAllText(@"d:\abc.HTML", HtmlBody); foreach (DataRow row in dt.Rows) { string itemNo = row["POSNR"].ToString(); string material = row["MATNR"].ToString(); #region Get Bom if (materials.IndexOf(material) >= 0) { IRfcFunction bomFunction = repo.CreateFunction("*****"); //调用函数名 bomFunction.SetValue("****", po); //设置Import的参数 bomFunction.SetValue("****", Convert.ToInt32(itemNo)); //设置Import的参数 bomFunction.SetValue("****", "S"); //设置Import的参数 bomFunction.SetValue("****", "X"); //设置Import的参数 bomFunction.Invoke(prd); //执行函数 //传出参数 object INSTANCE = bomFunction.GetValue("****"); IRfcStructure bomStr = bomFunction.GetStructure("****"); try { for (int i = 0; i <= bomStr.ElementCount - 1 ; i++) { RfcElementMetadata metadata = bomStr.GetElementMetadata(i); SaveToFile(Path.Combine(folderPath, material + "-PE_SODATA.txt"), metadata.Name + ":" + bomStr.GetString(metadata.Name)); } } catch (Exception ex2) { throw new Exception(ex2.ToString()); } } #endregion } prd = null; repo = null; this.textResult.Text = "ok\r\n"; } /// <summary> /// 从SAP Table转DataTable /// </summary> /// <param name="myrfcTable">IRfcTable</param> /// <returns></returns> public DataTable ToDataTable(IRfcTable myrfcTable) { DataTable loTable = new DataTable(); int liElement = 0; for (liElement = 0; liElement <= myrfcTable.ElementCount - 1; liElement++) { RfcElementMetadata metadata = myrfcTable.GetElementMetadata(liElement); loTable.Columns.Add(metadata.Name); } foreach (IRfcStructure Row in myrfcTable) { DataRow ldr = loTable.NewRow(); for (liElement = 0; liElement <= myrfcTable.ElementCount - 1; liElement++) { RfcElementMetadata metadata = myrfcTable.GetElementMetadata(liElement); ldr[metadata.Name] = Row.GetString(metadata.Name); } loTable.Rows.Add(ldr); } return loTable; }
描红处解决了中文变为#的问题。