本來今天是要寫一篇關(guān)于NCO3.0的東西,就是關(guān)乎.NET調(diào)用SAP的RFC的,支持VS2010和.NET 4.0等?,F(xiàn)在網(wǎng)上到處都是充斥著NCO1.X和NCO2.0,需要用VS2003來使用,都是一些沒什么大用的東西,連.NET 2.0的不能支持,只能算是廢材一個。而且相關(guān)的資料非常的少,轉(zhuǎn)來轉(zhuǎn)去全部都是那么一個例子,絲毫沒有直觀的DEMO,更搞笑的是SAP里面的RFC是怎么建立的都沒有說明,只有該死的C#代碼。同時還有微軟發(fā)布的Data Provider for mySAP Business Suite這個,開始用的時候覺得還挺有趣,后來試了一下很失望,抓出來的字段居然是斷碼,不知道是我不懂還是怎么的。同時更讓人無語的是用它的話還必須要導(dǎo)入一個Request NO,加入一個自定義的Function才可以使用Data Provider for mySAP Business Suite,很腦殘也很不靠譜。
為容城等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及容城網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站制作、成都做網(wǎng)站、容城網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!后來發(fā)現(xiàn)NCO3.0也發(fā)布了,和以前的版本大不相同。后面試用了一下NCO3.0,效果很好。
公司有幾只程序,是在臺灣SAP端運行程序,自動下載品號等信息至廈門的SQL Server數(shù)據(jù)庫供OA使用的,每次要用到的品號都需要去SAP系統(tǒng)運行那個程序。雖然Basis設(shè)置了4個小時執(zhí)行一次,但是還是有些過慢。我就想著如果能在OA這邊用NCO3.0,然后調(diào)用SAP的RFC,就自動下載所需要的品號那就非常方便了。我在030也試用了一下,很OK!
既然.NET能夠和SAP互相通信,在RFC里就可以任意發(fā)揮了,想做什么就做什么。這樣可以免去SAP系統(tǒng)的賬戶成本壓力。
呵呵,下篇博文開始介紹一下NCO3.0這個東西。
.NET連接SAP系統(tǒng)專題:SAP中新建可遠(yuǎn)程調(diào)用的RFC(二)
分類: SAP顧問進行時 2011-08-22 22:34 2001人閱讀 評論(0) 收藏 舉報
何謂RFC,就是一個Function,可以被非SAP系統(tǒng)調(diào)用,比如VB,C#,Java等。如果我們在RFC中INCLUDE了相關(guān)的業(yè)務(wù)邏輯,那么我們就可以完全操控SAP中的業(yè)務(wù)數(shù)據(jù)了。就像在TTE里,有一只程序,前端是在OA開發(fā),設(shè)計了相關(guān)的客戶提領(lǐng)庫存,然后還要到SAP系統(tǒng)中去執(zhí)行程序扣減相應(yīng)的庫存,這樣是挺費勁的,如果能夠在OA中放一個按鈕,點擊這個按鈕就自動執(zhí)行了這個程序,方便省事。而這一切,可以利用C#調(diào)用RFC來實現(xiàn)。
要實現(xiàn)整個過程,則必須要現(xiàn)在SAP中建立好相應(yīng)的RFC函數(shù),然后用VS建立好相應(yīng)的程序,寫代碼調(diào)用就可以了。兩者關(guān)聯(lián)就是使用NCO3.0這個東西了。
OK,本節(jié)主要講在SAP中建立我們想要的RFC出來。
那么,我們假定要實現(xiàn)這樣的一個功能:運行在SAP系統(tǒng)外的一個程序窗體,上面有一個下拉框和文本框。程序運行之后自動載入SAP中某個Client的品號至該下拉框,用戶只要點擊了這個下拉框,內(nèi)容一改變,則旁邊的文本框就現(xiàn)實該品號的品名出來。夠簡單吧!
首先登陸SAP,比如我們要操作的Client為888(我自己建立的,圖個吉利)。運行SE37:
然后:
建立函數(shù)組,輸入相關(guān)內(nèi)容:
完了點擊保存。
之后回到SE37,輸入我們要調(diào)用的RFC函數(shù)名,比如:ZRFC_MARA_INFO 然后點擊新建(右一按鈕):
點擊保存之后會彈出如下對話框:
點擊打勾,忽略之。
主畫面如下:
畫面切換至 屬性 頁,設(shè)置該RFC為可遠(yuǎn)程調(diào)用。
因為我們到時候會傳遞一個品號進來讀取品名,SO,在Import頁面設(shè)置一個參數(shù)用來傳遞進來品號:
第一個復(fù)選框代表此參數(shù)可選可不選傳遞,第二個代表參考。在RFC里如果不打勾,保存會提示:
因為我們會要抓取品名,需要有一個欄位拋出品名出來。SO,Export頁面如下:
因為我們程序一開始需要拋出所有的品號表格出來,SO,此時我們需要有一個內(nèi)表專門用于拋出品號信息。Table屬性頁如下:
至此,所有參數(shù)設(shè)置完畢。接下去就要去代碼頁編寫相應(yīng)的代碼了。
代碼如下:
SELECT * INTO CORRESPONDING FIELDS OF TABLE IT_MARA FROM MARA.
SELECT SINGLE MAKTX INTO MAKTX FROM MAKT WHERE MATNR = MATNR AND SPRAS = '1'.
最后點擊激活!這里的激活不是單單激活這個RFC這么簡單,還有其他的項目,記得要勾選上:
至此,RFC建立完畢。
接下去就是在C#中調(diào)用它咯,下篇博文放出!
.NET連接SAP系統(tǒng)專題:C#調(diào)用RFC代碼(三)
分類: SAP顧問進行時 2011-08-22 22:34 2259人閱讀 評論(0) 收藏 舉報
本文就說明在C#中如何編寫代碼來調(diào)用SAP中的RFC函數(shù)獲取數(shù)據(jù)。(Winform32)
首先需要引用兩個NCO3.0的DLL,下載地址在文后。
然后在程序代碼頁面引用:
using SAP.Middleware.Connector;
然后所有的代碼如下:
namespace SAP_RFC
{
public partial class Form1 : Form
{
string MATNR = string.Empty;
public Form1()
{
InitializeComponent();
}
public void nco()
{
IDestinationConfiguration ID = new MyBackendConfig();
RfcDestinationManager.RegisterDestinationConfiguration(ID);
RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
RfcDestinationManager.UnregisterDestinationConfiguration(ID);
nco(prd);
}
public void nco(RfcDestination prd)
{
RfcRepository repo = prd.Repository;
IRfcFunction companyBapi = repo.CreateFunction("ZRFC_MARA_INFO"); //調(diào)用函數(shù)名
companyBapi.SetValue("MATNR", MATNR); //設(shè)置Import的參數(shù)
companyBapi.Invoke(prd); //執(zhí)行函數(shù)
IRfcTable table = companyBapi.GetTable("IT_MARA"); //獲取相應(yīng)的品號內(nèi)表
string MAKTX = companyBapi.GetValue("MAKTX").ToString(); //獲取品名
DataTable dt = new DataTable(); //新建表格
dt.Columns.Add("品號"); //表格添加一列
for (int i = 0; i < table.RowCount; i++)
{
table.CurrentIndex = i; //當(dāng)前內(nèi)表的索引行
DataRow dr = dt.NewRow();
dr[0] = table.GetString("MATNR"); //獲取表格的某行某列的值
dt.Rows.Add(dr); //填充該表格的值
}
if (MATNR == "")
{
for (int i = 0; i < dt.Rows.Count; i++)
{
this.comboBox1.Items.Add(dt.Rows[i][0].ToString()); //填充下拉框
}
}
this.label1.Text = MAKTX; //顯示品名
prd = null;
repo = null;
}
//登陸SAP前的準(zhǔn)備工作
public class MyBackendConfig : IDestinationConfiguration
{
public RfcConfigParameters GetParameters(String destinationName)
{
if ("PRD_000".Equals(destinationName))
{
RfcConfigParameters parms = new RfcConfigParameters();
parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.3"); //SAP主機IP
parms.Add(RfcConfigParameters.SystemNumber, "00"); //SAP實例
parms.Add(RfcConfigParameters.User, "MENGXIN"); //用戶名
parms.Add(RfcConfigParameters.Password, "5239898"); //密碼
parms.Add(RfcConfigParameters.Client, "888"); // Client
parms.Add(RfcConfigParameters.Language, "ZH"); //登陸語言
parms.Add(RfcConfigParameters.PoolSize, "5");
parms.Add(RfcConfigParameters.MaxPoolSize, "10");
parms.Add(RfcConfigParameters.IdleTimeout, "60");
return parms;
}
else return null;
}
public bool ChangeEventsSupported()
{
return false;
}
public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.Items.Clear();
nco();
comboBox1.SelectedIndex = 1;
}
//當(dāng)下拉框索引變化的時候傳遞品號進去查詢出品名出來
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
MATNR = comboBox1.Text.ToString();
nco();
}
}
}
我想這個C#代碼很簡單,我就不多做詳細(xì)說明了。結(jié)果如下:
SAP中品號信息如下:
由此可見數(shù)據(jù)完全OK,調(diào)用成功。
程序在第一次載入的時候有點慢,在鏈接SAP和登陸。后續(xù)在下拉框變化的時候就立馬顯示出品名出來了,絲毫沒有任何停頓。第二次鏈接SAP的時候大概是不必在登陸了,SAP系統(tǒng)中已有登陸信息,運行T-CODE:SM04
紅色框中這兩個即是我們的RFC調(diào)用所留下的登錄會話。一旦我們的C#程序退出之后,這兩個RFC也就退出了。
如果我們的C#程序是ASP.NET的話,頁面關(guān)閉之后這個RFC登錄信息都還在的。除非IIS關(guān)閉,否則只有等到SAP系統(tǒng)超時退出這兩個登陸會話了。
DLL下載地址:
https://files.cnblogs.com/mengxin523/SAP_DotNetConnector3.zip
.NET連接SAP系統(tǒng)專題:獲取RFC中自定義的異常(四)
分類: SAP顧問進行時 2011-08-22 22:35 1850人閱讀 評論(0) 收藏 舉報
有的時候我們需要在RFC中拋出一些自定義的異常,比如輸入一個不存在的品號,我們需要拋出一個異常,告知用戶品號不存在。有一個笨笨的做法就是通過返回值來判斷,但是這樣不靈活,同時也會因為品號不存在而繼續(xù)之行RFC。如果我們能自己拋出異常,程序自動停止執(zhí)行RFC,那將是兩全其美!
現(xiàn)在設(shè)定一個功能:輸入兩個數(shù),第一個數(shù)除以第二個數(shù)。2個異常:被除數(shù)不能為0和除數(shù)不能為100。
首先,在SE37中建立一個RFC,就用上篇博文的RFC吧。
在IMPORT頁設(shè)置如下:
Export頁面設(shè)置如下:
Changing和Table頁面放空
Exceptions頁面設(shè)置如下:
然后就是源碼咯:
代碼中,RAISE專門用于拋出異常,程序自動停止執(zhí)行,所有的返回值將被清空!RAISE 后面的內(nèi)容就是在Exceptions中定義的內(nèi)容了。
然后程序記得激活??!如此SAP端設(shè)置就結(jié)束了。
回到VS2010中,新建一個程序,界面如下:
于是,開始寫程序:
首先是引用兩個dll(參考上篇),并在程序開頭輸入:
using SAP.Middleware.Connector;
public void nco()
{
IDestinationConfiguration ID = new MyBackendConfig();
RfcDestinationManager.RegisterDestinationConfiguration(ID);
RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
RfcDestinationManager.UnregisterDestinationConfiguration(ID); //反注冊
nco(prd);
}
public void nco(RfcDestination prd)
{
string type = string.Empty;
RfcRepository repo = prd.Repository;
IRfcFunction companyBapi = repo.CreateFunction("ZRFC_MARA_INFO"); //指定RFC名稱
try
{
companyBapi.SetValue("NUM1", textBox1.Text.Trim()); //輸入?yún)?shù)復(fù)制
companyBapi.SetValue("NUM2", textBox2.Text.Trim()); //輸入?yún)?shù)復(fù)制
companyBapi.Invoke(prd); //開始調(diào)用執(zhí)行
textBox3.Text = companyBapi.GetValue("NUM3").ToString(); //獲取返回結(jié)果
}
catch (RfcAbapException ex) //此Exception專門用于獲取用戶自定義的異常信息?。。。?/p>
{
// companyBapi.Metadata.GetAbapException(ex.Key).Documentation 獲取對應(yīng)的異常的說明文字
MessageBox.Show(companyBapi.Metadata.GetAbapException(ex.Key).Documentation, "SAP RFC返回信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (RfcTypeConversionException ex) //此Exception專門用于獲取變量類型轉(zhuǎn)換的異常?。。。?/p>
{
MessageBox.Show("您輸入的不是數(shù)值", "SAP RFC返回信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch (RfcAbapRuntimeException ex) //此Exception專門用于獲取RFC執(zhí)行過程中的運行時異常?。。?!
{
MessageBox.Show(companyBapi.Metadata.GetAbapException(ex.Key).Documentation, "SAP RFC返回信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch (RfcBaseException ex) //此Exception是總Exception類,可以獲取所有的異常,如果有多個Catch,則不可以放第一位?。。?!
{
MessageBox.Show("其他所有錯誤", "SAP RFC返回信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
prd = null;
repo = null;
}
public class MyBackendConfig : IDestinationConfiguration
{
public RfcConfigParameters GetParameters(String destinationName)
{
if ("PRD_000".Equals(destinationName))
{
RfcConfigParameters parms = new RfcConfigParameters();
parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.3");
parms.Add(RfcConfigParameters.SystemNumber, "00");
parms.Add(RfcConfigParameters.User, "MENGXIN");
parms.Add(RfcConfigParameters.Password, "5239898");
parms.Add(RfcConfigParameters.Client, "888");
parms.Add(RfcConfigParameters.Language, "ZH");
parms.Add(RfcConfigParameters.PoolSize, "5");
parms.Add(RfcConfigParameters.MaxPoolSize, "10");
parms.Add(RfcConfigParameters.IdleTimeout, "60");
return parms;
}
else return null;
}
public bool ChangeEventsSupported()
{
return false;
}
public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
}
private void button1_Click(object sender, EventArgs e)
{
nco();
}
如此,C#運行結(jié)果如下:
以上可以正確得出我們自己拋出的異常的信息出來。程序測試OK?。?!
.NET連接SAP系統(tǒng)專題:C#(NCO3)調(diào)用BAPI(五)
分類: SAP顧問進行時 2011-08-22 22:35 1636人閱讀 評論(0) 收藏 舉報
周六加班,翻看以前寫OA程序的時候無意中發(fā)現(xiàn)了當(dāng)初的一個案子,就是讓用戶現(xiàn)在OA上申請一個SAP用戶,然后提交給相關(guān)人員審核,通過之后直接在SAP中生成這個用戶,不必在登陸到SAP中請系統(tǒng)管理員來做了。至于這一步,當(dāng)然是使用BAPI來實現(xiàn)了,不可能對用戶表進行新增數(shù)據(jù),這樣少了很多的關(guān)聯(lián)表和一些邏輯判斷,會是一場災(zāi)難。
前幾篇講的都是C#去調(diào)用RFC的東西,既然BAPI也是屬于RFC,如果標(biāo)準(zhǔn)的勾選了那個remote的話,那按道理來說是應(yīng)該可以實現(xiàn)調(diào)用的了。但難點是BAPI里面很多的參數(shù)都是引用結(jié)構(gòu)的,而不是單純的string和int的類型,這點有點困難。在C#中翻看了NCO3是否有相關(guān)的結(jié)構(gòu)類,可惜,都沒有!
查看了一下相關(guān)內(nèi)容,發(fā)現(xiàn)幾乎沒有任何調(diào)用BAPI的例子,看來使用NCO3的人極少。
只能自力更生了,還好,經(jīng)過很嚴(yán)密的思考和嘗試,終于實現(xiàn)了在C#中調(diào)用BAPI去實現(xiàn)錄入業(yè)務(wù)數(shù)據(jù)了。我嘗試的就是用BAPI_USER_CREATE這個BAPI,通過它可以新增一個用戶。
那么,相關(guān)內(nèi)容和代碼說明,就在下篇博文放出吧!
.NET連接SAP系統(tǒng)專題:NCO3調(diào)用BAPI的一些說明(六)
分類: SAP顧問進行時 2011-08-24 22:46 1647人閱讀 評論(0) 收藏 舉報
既然BAPI是一些特殊的RFC,封裝了業(yè)務(wù)邏輯,使得將業(yè)務(wù)都變成一個一個對象,使用者只需要傳入傳出參數(shù)就可以了。
NCO3連接BAPI之前先來看看BAPI的一些參數(shù)規(guī)則。我們以 BAPI_USER_CREATE 為例子。此BAPI調(diào)用了可以生成一個用戶,它當(dāng)然不是僅僅對USR02進行寫入那么簡單。生成之后該賬戶什么權(quán)限也沒有。
輸入T-CODE:BAPI,然后在第二個頁簽下找到該BAPI:
上圖中的紅色框框里就是我們要調(diào)用的BAPI的名稱。雙擊它,進入到該BAPI的一些說明里:
看到了,在屬性頁里它勾選了Remote... 說明它是可以遠(yuǎn)程操控的!
上圖里,注意到紅色框框都是不可選的,也就是后面的復(fù)選框沒有選中,它告訴我們,在調(diào)用BAPI的時候這些參數(shù)是必須要有值傳進來的!
這個就是返回的參數(shù)。當(dāng)然,這個Return也是必須要傳出來的值。
細(xì)心的人從上面幾個圖片可以看出,“參考打印”欄位里都是BAPI開頭的結(jié)構(gòu),或者是結(jié)構(gòu)里面的一個字段。雙擊這些結(jié)構(gòu)進去就可以看到相關(guān)的欄位組成。
現(xiàn)在回到Import頁簽里,雙擊USERNAME的“參考打印”——BAPIBNAME-BAPIBNAME?!?”前部分是結(jié)構(gòu),后面是這個結(jié)構(gòu)里的一個欄位。進入到里面:
這個BAPINAME結(jié)構(gòu)只有一個欄位,而且是CHAR型,12碼,SO,在傳 用戶名 進來的時候就是寫入字符串即可。
我們看看PASSWORD,對應(yīng)的結(jié)構(gòu)是:BAPIPWD 雙擊之,如下圖:
發(fā)現(xiàn)這里面只有一個欄位,CHAR型,40碼,傳密碼之用。
再看看ADDRESS欄位對應(yīng)的結(jié)構(gòu)BAPIADDR3,雙擊之:
這個結(jié)構(gòu)欄位就比較多了。雖然這里沒有規(guī)定那些是必須要有值的,但確實有些是需要賦值,有些則可以放空。
我們在SU01里面新建用戶的時候系統(tǒng)會提示要求輸入姓和名,那么這里的FIRSTNAME和LASTNAME是必須的了。
BAPI里傳入的參數(shù)LOGONDATA是放登陸數(shù)據(jù)的,具體的結(jié)構(gòu)不再贅述。而返回的信息RETURN里有一個MESSAGE是放調(diào)用結(jié)果的信息,我們在NCO3里調(diào)用要用到它來返回結(jié)果信息。
知道了這些原理之后就很清楚知道在C#中要怎么寫了,那些參數(shù)是必須的就一目了然了。SO,下篇博文放出NCO3調(diào)用BAPI的代碼!
NET連接SAP系統(tǒng)專題:NCO3調(diào)用BAPI的代碼(七)
分類: SAP顧問進行時 2011-08-25 22:43 1598人閱讀 評論(0) 收藏 舉報
上面博文可知BAPI_USER_CREATE的一些結(jié)構(gòu)和參數(shù)。所以在C#中要調(diào)用它就很清楚了要輸入哪些參數(shù)了。
1、首先引用dll,然后在程序開頭:using SAP.Middleware.Connector;
2、接下去就是設(shè)置登陸參數(shù)了,以前相關(guān)博文都有說明:
public class MyBackendConfig : IDestinationConfiguration
{
public RfcConfigParameters GetParameters(String destinationName)
{
if ("PRD_000".Equals(destinationName))
{
RfcConfigParameters parms = new RfcConfigParameters();
parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.3");
parms.Add(RfcConfigParameters.SystemNumber, "00");
parms.Add(RfcConfigParameters.User, "MENGXIN");
parms.Add(RfcConfigParameters.Password, "5239898");
parms.Add(RfcConfigParameters.Client, "888");
parms.Add(RfcConfigParameters.Language, "ZH");
parms.Add(RfcConfigParameters.PoolSize, "5");
parms.Add(RfcConfigParameters.MaxPoolSize, "10");
parms.Add(RfcConfigParameters.IdleTimeout, "60");
return parms;
}
else return null;
}
public bool ChangeEventsSupported()
{
return false;
}
public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
}
3、設(shè)置一個方法,引用這個登陸參數(shù)的類:
public void nco()
{
IDestinationConfiguration ID = new MyBackendConfig();
RfcDestinationManager.RegisterDestinationConfiguration(ID);
RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
RfcDestinationManager.UnregisterDestinationConfiguration(ID);
nco(prd);
}
4、然后就是開始了調(diào)用代碼,以下代碼全部放出,然后一行一行說明:
public void nco(RfcDestination prd)
{
//選擇要調(diào)用的BAPI的名稱
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_USER_CREATE");
//新建調(diào)用該BAPI的一個“實例”
IRfcFunction function = null;
function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction();
//因為用戶名稱是一個字段,所以直接賦予字符串即可
function.SetValue("USERNAME", USERID.Text.Trim());
//接下去是密碼。因為密碼是一個結(jié)構(gòu),該結(jié)構(gòu)只有一個欄位,所以這里先獲取這個密碼結(jié)構(gòu)
IRfcStructure PWD = function.GetStructure("PASSWORD");
//設(shè)置這個結(jié)構(gòu)中的這個欄位的內(nèi)容
PWD.SetValue("BAPIPWD", password.Text.Trim());
//再把這個結(jié)構(gòu)傳進去給作為密碼參數(shù)
function.SetValue("PASSWORD", PWD);
//這個是登陸信息,類型也是一個結(jié)構(gòu),所以這里獲取出這個登錄信息的結(jié)構(gòu)出來
IRfcStructure logo = function.GetStructure("LOGONDATA");
//以下兩個是設(shè)置這個登陸結(jié)構(gòu)的一些欄位的值
logo.SetValue("GLTGV", "20110821");
logo.SetValue("GLTGB", "99991231");
//將登陸信息的結(jié)構(gòu)傳進去給LOGONDATA
function.SetValue("LOGONDATA", logo); //設(shè)置參數(shù)
//這個是地址信息,取結(jié)構(gòu),然后賦值,再將它傳進去
IRfcStructure address = function.GetStructure("ADDRESS");
address.SetValue("FIRSTNAME", firstname.Text.Trim());
address.SetValue("LASTNAME", lastname.Text.Trim());
address.SetValue("DEPARTMENT", "資訊室");
function.SetValue("ADDRESS", address); //設(shè)置參數(shù)
//以下這個DEFAULTS是賬戶的默認(rèn)信息,不是必須要的。我們這里利用它設(shè)置登入賬戶的語言為ZH
IRfcStructure DEFAULTS = function.GetStructure("DEFAULTS");
DEFAULTS.SetValue("LANGU", "1"); //語言代碼,對應(yīng)簡體中文!
function.SetValue("DEFAULTS", DEFAULTS);
//以下這個是RETURN,是回傳結(jié)果的結(jié)構(gòu)。記住,這里跟上面不一樣,上面是Structure,這里則是Table??!
IRfcTable returnStructure = function.GetTable("RETURN");
function.Invoke(prd);//提交調(diào)用BAPI
//彈出對話框顯示調(diào)用結(jié)果
MessageBox.Show(returnStructure.GetString("MESSAGE").ToString());
prd = null;
}
5、程序運行結(jié)果如下:
6、登陸到SAP,運行SU01,輸入IT_XM01,看看結(jié)果:
當(dāng)然,如果該用戶已經(jīng)存在了你還去調(diào)用這個BAPI生成用戶,系統(tǒng)會很知趣的提示:
使用IT_XM01登陸系統(tǒng),一切OK,系統(tǒng)狀態(tài)如下:
新建的賬戶一點權(quán)限也沒有的,此時可以調(diào)用其他BAPI對其新增權(quán)限!!方法大同小異,這里不再詳述。
.NET連接SAP系統(tǒng)專題:C#調(diào)用BAPI給賬戶賦予權(quán)限(八)
分類: SAP顧問進行時 2011-08-28 11:23 1678人閱讀 評論(0) 收藏 舉報
接上篇博文。
上篇博文講到C#調(diào)用BAPI BAPI_USER_CREATE 來生成SAP賬戶,但是新建的賬戶一點權(quán)限也沒有,現(xiàn)在我們就再次利用BAPI給賬戶授予權(quán)限。
首先,我們在BAPI畫面里查找出相關(guān)的BAPI出來,利用角色去給用戶添加權(quán)限:
雙擊此BAPI,進入到BAPI預(yù)覽畫面:
Table屬性頁:
第一個ACTIVITYGROUPS是指我們要傳進去的表格內(nèi)容,不再是一個欄位和結(jié)構(gòu)內(nèi)容了。第二個的RETURN則是返回調(diào)用結(jié)果。
雙擊BAPIAGR的結(jié)構(gòu),進入結(jié)構(gòu)詳情畫面:
以上AGR_NAME是角色名,應(yīng)該是必須要的。
那么,接下去就是在C#中編寫相應(yīng)的代碼來調(diào)用它了。
1、首先引用dll,然后在程序開頭:using SAP.Middleware.Connector;
2、接下去就是設(shè)置登陸參數(shù)了,以前相關(guān)博文都有說明:
public class MyBackendConfig : IDestinationConfiguration
{
public RfcConfigParameters GetParameters(String destinationName)
{
if ("PRD_000".Equals(destinationName))
{
RfcConfigParameters parms = new RfcConfigParameters();
parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.3");
parms.Add(RfcConfigParameters.SystemNumber, "00");
parms.Add(RfcConfigParameters.User, "MENGXIN");
parms.Add(RfcConfigParameters.Password, "5239898");
parms.Add(RfcConfigParameters.Client, "888");
parms.Add(RfcConfigParameters.Language, "ZH");
parms.Add(RfcConfigParameters.PoolSize, "5");
parms.Add(RfcConfigParameters.MaxPoolSize, "10");
parms.Add(RfcConfigParameters.IdleTimeout, "60");
return parms;
}
else return null;
}
public bool ChangeEventsSupported()
{
return false;
}
public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
}
3、設(shè)置一個方法,引用這個登陸參數(shù)的類:
public void nco()
{
IDestinationConfiguration ID = new MyBackendConfig();
RfcDestinationManager.RegisterDestinationConfiguration(ID);
RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
RfcDestinationManager.UnregisterDestinationConfiguration(ID);
nco(prd);
}
4、然后就是開始了調(diào)用代碼,以下代碼全部放出,然后一行一行說明:
public void nco(RfcDestination prd)
{
//調(diào)用BAPI
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_USER_ACTGROUPS_ASSIGN");
IRfcFunction function = null;
function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction();
//傳入我們要賦予權(quán)限的用戶名
function.SetValue("USERNAME", USERID.Text.Trim());
//接下去就是傳入角色名。由于ACTIVITYGROUPS 是在Table屬性頁,所以我們是用Table 而不是Import和Export屬性頁里面用的Structure
IRfcTable ROFTable = function.GetTable("ACTIVITYGROUPS");
//上面語句產(chǎn)生的ROFTable 其實是一張空表,里面除了有那幾個欄位之外是沒有任何記錄的,所以在對表格賦值之前需要先進性新增一行
ROFTable .Insert();
//接下去就是對表格當(dāng)前行的相關(guān)欄位賦值。如下的角色名“MIS”是預(yù)選在SAP中建立好的
ROFTable .CurrentRow.SetValue("AGR_NAME", "MIS");
ROFTable .CurrentRow.SetValue("FROM_DAT", "20110825");
ROFTable .CurrentRow.SetValue("TO_DAT", "99991231");
//傳入該賦值后的表格
function.SetValue("ACTIVITYGROUPS", ROFTable);
//引用回傳結(jié)果
IRfcTable RETURNStructure = function.GetTable("RETURN");
//提交調(diào)用
function.Invoke(prd);
//顯示調(diào)用結(jié)果
MessageBox.Show(RETURNStructure.GetString("MESSAGE").ToString());
prd = null;
}
5、調(diào)用結(jié)果如下:
如此則此用戶已經(jīng)賦予相應(yīng)的權(quán)限了,運行所有T-CODE,沒問題!
對了,如果要賦予多個角色的話,那么就是多做ROFTable.Insert();然后再做相應(yīng)賦值即可。
PS:C#調(diào)用RFC系列專題就到此告一段落了,如果讀者有建議或者疑問歡迎交流指正~!
.NET連接SAP系統(tǒng)專題:sapnco.dll在ASP.NET中載入失敗的解決方法(九)
分類: SAP顧問進行時 2011-11-21 16:51 1646人閱讀 評論(0) 收藏 舉報
當(dāng)所有一切代碼準(zhǔn)備就緒之后,如果是ASP.NET那就是要發(fā)布網(wǎng)站到服務(wù)器了。如果服務(wù)器上的系統(tǒng)是WIN2003,那很不幸,系統(tǒng)會提示這樣的“紅臉”過來:
意思是說sapnco_utils.dll和sapnco.dll這兩個文件不能載入。
Could not load file or assembly "sapnco_utils,Version=3.0.0.42,...
網(wǎng)上查找了方法也不盡然,各說紛紜。但是在WIN2008下的IIS7跟WinXP下的IIS5.1都可以完全正常,但是這個WIN2003就不行。
后來在對這兩個DLL進行分析的時候發(fā)現(xiàn)它們是用VC++2005開發(fā)的,想到WIN2003系統(tǒng)可能沒有必要的運行庫。于是在工作站測試的時候安裝了VC++2005 32bit版,然后刷新一切就正常了!
解決方法:安裝相應(yīng)vc++2005運行庫即可?。▽嵺`證明:VC++2008不行!)
附VC++2005 32位運行庫下載地址:
https://files.cnblogs.com/mengxin523/vcredist2005sp1_x86_XiaZaiBa.zip
.NET連接SAP系統(tǒng)專題:BAPI_TRANSACTION_COMMIT的使用方法(十)
分類: SAP顧問進行時 2011-11-21 16:52 1518人閱讀 評論(1) 收藏 舉報
為什么.net調(diào)用SAP的BAPI接口需要調(diào)用BAPI_TRANSACTION_COMMIT呢?首先得明白BAPI_TRANSACTION_COMMIT這個BAPI的作用。它功勞很大,在SAP里面很多的BAPI直接調(diào)用是不會有結(jié)果的,因為需要COMMIT一下才能生效,比如生成資產(chǎn)編號的BAPI:BAPI_FIXEDASSET_CREATE1,如果對他直接在SE37中調(diào)用運行或者使用SE38調(diào)用它,雖然可以得到一個資產(chǎn)編號,但是在AS03里面查詢,系統(tǒng)會很白癡得提示你:該資產(chǎn)編號不存在于XX公司。更搞的是當(dāng)你在AS01中新建資產(chǎn)編號時,新建的資產(chǎn)編號會跳過之前用BAPI生成“失敗”的號碼。
那么,這就需要COMMIT一下,在調(diào)用這個BAPI之后再緊接調(diào)用BAPI_TRANSACTION_COMMIT這個。但是,在SE38中是可以這樣做,而在.net中就沒那么簡單了,直接在調(diào)用完BAPI_FIXEDASSET_CREATE1之后再緊接調(diào)用BAPI_TRANSACTION_COMMIT是不可以的,雖然還是生成了資產(chǎn)編號,但仍舊是個廢號。跟在SE37中調(diào)用無異。
怎么在.net中解決這個問題呢,這就需要用到RfcSessionManager.BeginContext和RfcSessionManager.EndContext這兩個方法了。只有在這兩個方法之間調(diào)用BAPI才能方保萬無一失!
代碼如下:
1、首先引用:using SAP.Middleware.Connector;
2、調(diào)用代碼:
public void nco(DataSet ds)
{
IDestinationConfiguration ID = new RfcConfig();
RfcDestinationManager.RegisterDestinationConfiguration(ID);
RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
RfcDestinationManager.UnregisterDestinationConfiguration(ID);
nco(prd, ds);
}
public void nco(RfcDestination prd, DataSet ds)
{
bool asset = false;
//選擇要調(diào)用的BAPI的名稱
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_REQUISITION_CREATE");
//新建調(diào)用該BAPI的一個“實例”
IRfcFunction function = null;
function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction();
IRfcTable ITEMS = function.GetTable("REQUISITION_ITEMS");
IRfcTable ACCOUNT = function.GetTable("REQUISITION_ACCOUNT_ASSIGNMENT");
IRfcTable RETURN = function.GetTable("RETURN");
int j = 0;
RfcSessionManager.BeginContext(prd); //因期間需要同一個時間調(diào)用BAPI,而且各個BAPI之間有順序關(guān)聯(lián),所以最好用這個包圍起來
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
ITEMS.Insert();
j = j + 1;
j = j * 10;
ITEMS.CurrentRow.SetValue("PREQ_ITEM", j.ToString());
ITEMS.CurrentRow.SetValue("PREQ_NAME", ds.Tables[0].Rows[i]["QGA27"].ToString());
ITEMS.CurrentRow.SetValue("CREATED_BY", ds.Tables[0].Rows[i]["QGA27"].ToString());
ITEMS.CurrentRow.SetValue("PREQ_DATE", Convert.ToDateTime(ds.Tables[0].Rows[i]["QGA15"].ToString()).Date);
ITEMS.CurrentRow.SetValue("MATERIAL", ds.Tables[0].Rows[i]["QGA04"].ToString());
ITEMS.CurrentRow.SetValue("SHORT_TEXT", ds.Tables[0].Rows[i]["QGA05"].ToString());
ITEMS.CurrentRow.SetValue("PLANT", "1201");
ITEMS.CurrentRow.SetValue("QUANTITY", Convert.ToDecimal(ds.Tables[0].Rows[i]["QGA07"].ToString()));
ITEMS.CurrentRow.SetValue("DELIV_DATE", Convert.ToDateTime(ds.Tables[0].Rows[i]["QGA09"].ToString()).Date);
ITEMS.CurrentRow.SetValue("C_AMT_BAPI", Convert.ToDecimal(ds.Tables[0].Rows[i]["QGA14"].ToString()));
ITEMS.CurrentRow.SetValue("ACCTASSCAT", ds.Tables[0].Rows[i]["QGA12"].ToString());
ITEMS.CurrentRow.SetValue("DOC_TYPE", ds.Tables[0].Rows[i]["QGA28"].ToString());
ITEMS.CurrentRow.SetValue("UNIT", ds.Tables[0].Rows[i]["QGA06"].ToString());
ACCOUNT.Insert();
ACCOUNT.CurrentRow.SetValue("PREQ_ITEM", j.ToString());
ACCOUNT.CurrentRow.SetValue("COST_CTR", ds.Tables[0].Rows[i]["QGA31"].ToString());
ACCOUNT.CurrentRow.SetValue("ORDER_NO", ds.Tables[0].Rows[i]["QGA10"].ToString());
if (ds.Tables[0].Rows[i]["QGA12"].ToString().Trim() == "A") //如果類別是A,即資產(chǎn),則需要資產(chǎn)編號
{
ACCOUNT.CurrentRow.SetValue("ASSET_NO", GetASSET(prd, i, ds)); //設(shè)置新建的資產(chǎn)編號
ACCOUNT.CurrentRow.SetValue("CO_AREA", "1000");
ACCOUNT.CurrentRow.SetValue("SUB_NUMBER", "0000");
}
}
function.SetValue("REQUISITION_ITEMS", ITEMS);
function.SetValue("REQUISITION_ACCOUNT_ASSIGNMENT", ACCOUNT);
function.Invoke(prd);//提交調(diào)用BAPI
RfcSessionManager.EndContext(prd);
if (RETURN.GetString("TYPE").ToString().Trim() == "I")
{
Suess.Text = RETURN.GetString("MESSAGE").ToString();
BANFN.Text = "返回的請購單號:" + function.GetString("NUMBER").Trim();
}
else if (RETURN.GetString("TYPE").ToString().Trim() == "E")
{
Error.Text = RETURN.GetString("MESSAGE").ToString();
}
prd = null;
}
///
/// 取得資產(chǎn)編號
///
///
///
public string GetASSET(RfcDestination prd, int i, DataSet ds)
{
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_FIXEDASSET_CREATE1");
IRfcFunction function = null;
function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction();
IRfcStructure KEY = function.GetStructure("KEY");
KEY.SetValue("COMPANYCODE", "2012");
IRfcStructure GENERALDATA = function.GetStructure("GENERALDATA");
GENERALDATA.SetValue("ASSETCLASS", "00005990");
GENERALDATA.SetValue("DESCRIPT", ds.Tables[0].Rows[i]["QGA05"].ToString());
IRfcStructure GENERALDATAX = function.GetStructure("GENERALDATAX");
GENERALDATAX.SetValue("ASSETCLASS", "X");
GENERALDATAX.SetValue("DESCRIPT", "X");
function.SetValue("KEY", KEY);
function.SetValue("GENERALDATA", GENERALDATA);
function.SetValue("GENERALDATAX", GENERALDATAX);
prd.Repository.ClearFunctionMetadata(); //貌似這句可以省略...
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD1 = prd.Repository.GetFunctionMetadata("BAPI_TRANSACTION_COMMIT");
IRfcFunction function1 = null;
function1 = BAPI_COMPANYCODE_GETDETAIL_MD1.CreateFunction();
function1.SetValue("WAIT", "X");
RfcSessionManager.BeginContext(prd);
function.Invoke(prd); //提交調(diào)用BAPI_FIXEDASSET_CREATE1 生成資產(chǎn)編號
function1.Invoke(prd); //提交調(diào)用BAPI_TRANSACTION_COMMIT 進行COMMIT一下
RfcSessionManager.EndContext(prd);
twMsgbox.AjaxAlert(function.GetValue("ASSET").ToString().Trim());
return function.GetValue("ASSET").ToString().Trim();
}
新建立之后的請購單一切OK,同時,建立的資產(chǎn)編號在AS03已經(jīng)可以認(rèn)出來了!!