今日心血来潮,想自己做一些VS2005调用SAP的RFC的程序例子来学习学习。
1、 SE37,进入FUNCTION BUILDER主界面;
2、 转到主菜单上的Goto->Function Group->Create Group,然后输入名称等,由于只是测试,所以就选择本地对象进行保存,对应的开发类为$TMP;
3、 SE80,进入对象浏览器,选择自己刚才创建的函数组,点击右键,在弹出菜单中选择激活选项进行激活,如图:
4、 重新回到SE37,创建函数YCTF_RFC2,选择刚才创建的函数组Y_CTF_FUN_GROUP,然后进入,选择,这样整个函数就可以被外部系统进行RFC了。IMPORT这边我就输入参数INPUT,类型为I,EXPORT处我也只输入参数OUTPUT,类型为I,其它的就修改下源代码,输入output = input * 2.
5、 激活此函数
6、 现在开始进行VS2005的操作了,新建一个类库,然后在引用中导入Interop.SAPFunctionsOCX、Interop.SAPLogonCtrl和Interop.SAPTableFactoryCtrl。
7、 添加Conn类的编写,代码如下:
1、 namespace Sap 2、 { 3、 public class Conn 4、 { 5、 /// <summary> 6、 /// sap连接 7、 /// </summary> 8、 private static SAPLogonCtrl.Connection conn = null; 9、 10、 /// <summary> 11、 /// 登录 12、 /// </summary> 13、 /// <param name="ip"></param> 14、 /// <param name="client"></param> 15、 /// <param name="language"></param> 16、 /// <param name="user"></param> 17、 /// <param name="password"></param> 18、 /// <param name="systemNumber"></param> 19、 /// <returns></returns> 20、 public static bool logon( 21、 string ip, 22、 string client, 23、 string language, 24、 string user, 25、 string password, 26、 int systemNumber) 27、 { 28、 SAPLogonCtrl.SAPLogonControlClass logon = new SAPLogonCtrl.SAPLogonControlClass(); 29、 logon.ApplicationServer = ip; //SAP system’s IP 30、 logon.Client = client; //SAP system’client 31、 logon.Language = language; //Lauguage 32、 logon.User = user; //Username 33、 logon.Password = password; //Password 34、 logon.SystemNumber = systemNumber; //System number 35、 conn = (SAPLogonCtrl.Connection)logon.NewConnection(); 36、 return conn.Logon(0, true); 37、 } 38、 39、 /// <summary> 40、 /// 获取某个值 41、 /// </summary> 42、 /// <param name="functionName"></param> 43、 /// <param name="importNames"></param> 44、 /// <param name="importValues"></param> 45、 /// <param name="exportFieldName"></param> 46、 /// <returns></returns> 47、 public static string getValue(string functionName, 48、 List<string> importNames, 49、 List<string> importValues, 50、 string exportFieldName) 51、 { 52、 SAPFunctionsOCX.SAPFunctionsClass func = new SAPFunctionsOCX.SAPFunctionsClass(); 53、 func.Connection = conn; 54、 SAPFunctionsOCX.IFunction ifunc = (SAPFunctionsOCX.IFunction)func.Add(functionName); 55、 for (int i = 0; i < importNames.Count; ++i) 56、 { 57、 SAPFunctionsOCX.IParameter parameter = (SAPFunctionsOCX.IParameter)ifunc.get_Exports(importNames[i]); 58、 parameter.Value = importValues[i]; 59、 } 60、 ifunc.Call(); 61、 SAPFunctionsOCX.IParameter output = (SAPFunctionsOCX.IParameter)ifunc.get_Imports(exportFieldName); 62、 return output.Value.ToString(); 63、 } 64、 65、 /// <summary> 66、 /// 获取表 67、 /// </summary> 68、 /// <param name="functionName"></param> 69、 /// <param name="importNames"></param> 70、 /// <param name="importValues"></param> 71、 /// <returns></returns> 72、 public static DataSet getDs( 73、 string functionName, 74、 List<string> importNames, 75、 List<string> importValues) 76、 { 77、 DataSet ds = new DataSet(); 78、 79、 SAPFunctionsOCX.SAPFunctionsClass func = new SAPFunctionsOCX.SAPFunctionsClass(); 80、 func.Connection = conn; 81、 SAPFunctionsOCX.IFunction ifunc = (SAPFunctionsOCX.IFunction)func.Add(functionName); 82、 for (int i = 0; i < importNames.Count; ++i) 83、 { 84、 SAPFunctionsOCX.IParameter parameter = (SAPFunctionsOCX.IParameter)ifunc.get_Exports(importNames[i]); 85、 parameter.Value = importValues[i]; 86、 } 87、 ifunc.Call(); 88、 //SAPFunctionsOCX.IParameter NUMBER = (SAPFunctionsOCX.IParameter)ifunc.get_Imports("P_SUBRC"); 89、 SAPTableFactoryCtrl.Tables tables = (SAPTableFactoryCtrl.Tables)ifunc.Tables; 90、 91、 for (int i = 1; i <= tables.Count; ++i) 92、 { 93、 SAPTableFactoryCtrl.Table t = (SAPTableFactoryCtrl.Table)tables.get_Item(i); 94、 DataTable dt = new DataTable(); 95、 dt.TableName = t.Name; 96、 for (int j = 1; j <= t.ColumnCount; ++j) 97、 { 98、 string title = t.get_ColumnName(j); 99、 DataColumn column = new DataColumn(title, typeof(string)); 100、 dt.Columns.Add(column); 101、 } 102、 for (int j = 1; j <= t.RowCount; ++j) 103、 { 104、 DataRow dr = dt.NewRow(); 105、 for (int col = 0; col < dt.Columns.Count; ++col) 106、 { 107、 string title = dt.Columns[col].Caption; 108、 dr[title] = t.get_Cell(j, title).ToString(); 109、 } 110、 dt.Rows.Add(dr); 111、 } 112、 ds.Tables.Add(dt); 113、 } 114、 115、 return ds; 116、 } 117、 } 118、 } 119、 |
8、 编写部分代码进行RFC函数编写:
1、 List<string> importNames = new List<string>(); 2、 List<string> importValues = new List<string>(); 3、 importNames.Add("INPUT"); 4、 importValues.Add("13"); 5、 6、 string output = Sap.Conn.getValue("YCTF_RFC2", importNames, importValues, "OUTPUT"); 7、 MessageBox.Show(output); 8、 OK,很正常。 9、 |
来个复杂的,整个太简单了点,可是由于自己水平有限,写不出什么来,原来有个顾问写的一个获取批次属性的函数,我们都用它,逻辑还是有点复杂,所以打算直接调用整个函数来试试看,此函数既有返回的单个值,也有表格返回。
10、 编写测试代码:
1、 List<string> importNames = new List<string>(); 2、 List<string> importValues = new List<string>(); 3、 importNames.Add("P_MATNR"); 4、 importNames.Add("P_CHARG"); 5、 importValues.Add("000000000064000024"); 6、 importValues.Add("N10052501 "); 7、 8、 DataSet ds = Sap.Conn.getDs("Y_FIG001_GET_CHAR_FROM_BATCH", importNames, importValues); 9、 if (ds.Tables.Count > 0) 10、 { 11、 dataGridView1.DataSource = ds.Tables[1]; 12、 dataGridView1.Visible = true; 13、 } |
测试,表格中没有返回任何值,但在SAP中进行测试是有的。跟踪IFunc变量,在调用call方法之前都是正常的,但是在调用之后,里面的RFC结果显示SYSTEM_FAILURE.,不知道什么原因,马上GOOGLE一下,有人建议说用ST22可以查看运行时错误信息。
11、 ST22,选择今天错误信息进行查看,马上定位到了,打开日志信息,显示如下:
哦,原来在函数的属性中不是Remote Enable Module,不行,恩,应该就是这个原因。
12、 拷贝Z_FIG001_GET_CHAR_FROM_BATCH,新生成函数Y_ FIG001_GET_CHAR_FROM_BATCH,函数组选择前面自己创建的那个函数组,OK,进去激活,没想到错误一大堆,不管了,定位错误地方,到原来的Z_FIG001_GET_CHAR_FROM_BATCH,把引用的代码都给拷贝过来,现在也差不多慢慢懂得了函数组的一些用户了,就是可以自己定义一些结构、变量等供该函数组下面的功能模块调用。
13、 代码没错之后,激活、测试,OK,通过。
另外要注意的是,因为物料代码是18位,所以前面一定要补0以合乎要求,否则是取不到结果的。
涉及TCODE:SE37、SE80、ST22。