(相关资料图)
最近,公司由于要做保税业务,需要向海关提供Excel格式的资料,需要用到多层级BOM,并且主料要放第一行,替代料要放第一行后面。由于SAP的BOM替代料的顺序是不固定的,所以就试着C#用RFC方式实现。下面简单说下顺序。
首先NuGet添加SapNwRfc
接下来可以直接创建RFC连接并调用
//创建SAP远程连接字符串string connectionString = "AppServerHost=10.10.0.31; SystemNumber=00; User=SAP_RFC_USR; Password=123456; Client=100; Language=EN; PoolSize=5; Trace=8";/// <summary>/// 获取层级BOM列表/// </summary>private void GetBOMExplList(){ var connection = new SapConnection(connectionString); connection.Connect(); //提交调用BAPI 需要运行 RZ11->ucon/rfc/check_blacklist ->更改值按钮 设置为0 ISapFunction bomFunction = connection.CreateFunction("CS_BOM_EXPL_MAT_V2_RFC"); BOM_EXPL_MAT_FunctionParameters parameters = new BOM_EXPL_MAT_FunctionParameters() { CAPID = "PP01", DATUV = DateTime.Now, MEHRS = "X", MTNRV = "JS47081F002", WERKS = "1010" }; var result = bomFunction.Invoke<BOM_EXPL_MAT_FunctionResult>(parameters); List<STB> List_STB = result._STB.ToList(); connection.Disconnect();}
重点是构建输入参数类输出参数类
1:输入参数类BOM_EXPL_MAT_FunctionParameters
public class BOM_EXPL_MAT_FunctionParameters { /// <summary> /// 物料编码 /// </summary> [SapName("MTNRV")] public string MTNRV { get; set; } [SapName("WERKS")] public string WERKS { get; set; } /// <summary> /// 工厂 /// </summary> [SapName("CAPID")] public string CAPID { get; set; } /// <summary> /// 有效日期自 /// </summary> [SapName("DATUV")] public DateTime DATUV { get; set; } /// <summary> /// 是否展多层 /// </summary> [SapName("MEHRS")] public string MEHRS { get; set; } /// <summary> /// 是否展虚拟件 /// </summary> [SapName("MDMPS")] public string MDMPS { get; set; } }
2:输出参数类BOM_EXPL_MAT_FunctionResult,因为输出的是一个表数据,所以要构建表数据类
/// <summary> /// CS12:BOM层级明细列表查询结果 /// </summary> public class BOM_EXPL_MAT_FunctionResult { [SapName("STB")] public STB[] _STB { get; set; } } /// <summary> /// BOM层级明细列表查询结果 /// </summary> public class STB { /// <summary> /// 层 /// </summary> [DisplayName("层")] [SapName("STUFE")] public decimal STUFE { get; set; } [SapName("WEGXX")] public int WEGXX { get; set; } /// <summary> /// 项目 /// </summary> [DisplayName("项目")] [SapName("POSNR")] public string POSNR { get; set; } /// <summary> /// 组件 /// </summary> [SapName("IDNRK")] public string IDNRK { get; set; } /// <summary> /// 组件数量 /// </summary> [SapName("MNGKO")] public decimal MNGKO { get; set; } /// <summary> /// 替代项目组 /// </summary> [DisplayName("替代项目组")] [SapName("ALPGR")] public string ALPGR { get; set; } [SapName("MENGE")] public decimal MENGE { get; set; } /// <summary> /// 上级ID /// </summary> [DisplayName("上级ID")] [SapName("STLNR")] public string STLNR { get; set; } [SapName("XTLNR")] public string XTLNR { get; set; } [SapName("XTLAL")] public string XTLAL { get; set; } /// <summary> /// 使用概率 /// </summary> [DisplayName("使用概率")] [SapName("EWAHR")] public decimal EWAHR { get; set; } /// <summary> /// 物料描述 /// </summary> [DisplayName("物料描述")] [SapName("OJTXP")] public string OJTXP { get; set; } /// <summary> /// 物料类型 /// </summary> [DisplayName("物料类型")] [SapName("MTART")] public string MTART { get; set; } /// <summary> /// 物料状态 /// </summary> [DisplayName("物料状态")] [SapName("MMSTA")] public string MMSTA { get; set; } /// <summary> /// 排序字符串 /// </summary> [DisplayName("排序字符串")] [SapName("SORTF")] public string SORTF { get; set; } /// <summary> /// 撒装物料 /// </summary> [DisplayName("撒装物料")] [SapName("SORTF")] public string SCHGT { get; set; } /// <summary> /// 优先级 /// </summary> [DisplayName("优先级")] [SapName("ALPRF")] public decimal ALPRF { get; set; } }
补充一个读表数据(RFC_READ_TABLE )的实例代码
/// <summary>/// 获取物料信息/// </summary> private void GetMaterialInfo() { var connection = new SapConnection(connectionString); connection.Connect(); var rfcFunction = connection.CreateFunction("RFC_READ_TABLE"); //https://stackoverflow.com/questions/27633332/rfc-read-table-passing-options-and-fields-parameters-c OPTIONS[] par = { new OPTIONS { TEXT = #34;MATNR = "JS47081F002"" } }; RFC_READ_TABLE_FunctionParameters parameters1 = new RFC_READ_TABLE_FunctionParameters() { QUERY_TABLE = "MAKT", ROWCOUNT = 0, DELIMITER = "|", OPTIONS = par }; var result1 = rfcFunction.Invoke<RFC_READ_TABLE_FunctionResult>(parameters1); var list_MAKT = result1._DATA.ToList(); connection.Disconnect(); } /// <summary> /// 读取表数据条件参数类 /// </summary> public class OPTIONS { [SapName("TEXT")] public string TEXT { get; set; } } /// <summary> /// 读表数据输入参数类 /// </summary> public class RFC_READ_TABLE_FunctionParameters { /// <summary> /// 表名 /// </summary> [SapName("QUERY_TABLE")] public string QUERY_TABLE { get; set; } /// <summary> /// 返回数据条数 /// </summary> [SapName("ROWCOUNT")] public int ROWCOUNT { get; set; } /// <summary> /// 分隔符 /// </summary> [SapName("DELIMITER")] public string DELIMITER { get; set; } /// <summary> /// 查找条件 /// </summary> [SapName("OPTIONS")] public OPTIONS[] OPTIONS { get; set; } } /// <summary> /// 表查询输出参数 /// </summary> public class RFC_READ_TABLE_FunctionResult { [SapName("DATA")] public DATA[] _DATA { get; set; } }
做个Mark,回头把基于.net framework的方式也写一篇文章发出来。