C#连接SAP获取RFC函数数据 中文乱码变为#问题

本文主要记录C#这边的代码,至于SAP那边的操作不做讨论。

C#连接SAP获取RFC函数数据,一般有两种方法。

  1. 使用COM组件获取数据
  2. 使用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
" + 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
";
        }

/// <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;
        }

  描红处解决了中文变为#的问题。

原文地址:https://www.cnblogs.com/allenfly/p/8888695.html