最近,公司由于要做保稅業務,需要向海關提供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的方式也寫一篇文章發出來。