2010年2月22日 星期一

.NET Call SAP/RFC by Visual Basic & VS2010

原本以為這輩子應該是沒什麼機會碰到這種非個人領域內的技術(SAP),孰不知資訊IT的世界果然是很小,想起以往年少輕狂,第一個工作是當個程式設計師,寫的是JSP網頁程式的部分,也有部分的JAVA開發,後來因為否些因素轉而投向比爾蓋茲的懷抱,開始寫起VB和ASP等微軟技術來,到了中菲以後,莫名奇妙又多少接觸到AS400和Oracle相關的技術,雖然沒有真正下去開發這AS400的系統,不過大致上皮毛也算是有摸到,正所謂沒吃過豬肉,也看過豬走路,到了恆逸算是個人領域技術的萬流歸宗,幾乎所有的時間就只專精在MS的技術上面。

直到前一陣子,因為答應幫忙朋友的忙,結果居然扯到的SAP,朋友要的只是很簡單的一句話,用.NET Call SAP/RFC 將資料取回在微軟相關的產品上。媽呀,這又是一個完全陌生的領域,我甚至連RFC是啥東西都不清楚(雖然後來問一下google大神就知道了),就好像一個武林高手,一腳踏入一個飄邈虛無的危險聳聳森林中,也只能憑著自身的保命技能努力的生活下來,身邊一切的環境尚待自我摸索。當然這樣說是有點誇張了點,有那種嚇死人不償命的feel,不過老實說,亞當斯以往從來沒有接觸過SAP,因此也就把這個幫忙,當作是一個自我的挑戰,嘗試看看是否可以搞點什麼東西出來。

話說,為了幫這個忙,花了我幾乎快兩個禮拜的時間,心疼阿~我的光陰~

開始進入正題吧,欲使用.NET技術與SAP溝通,有很多種方式,但是對於亞當斯來說,最簡單也是做快速的方式就是直接使用SAP的Client元件,來個直搗黃龍。因此要使用這種最簡單,也是最直接的方式來連結SAP的話,就必須有一些事先的開發環境必須要準備一下,以下亞當斯分為兩個部分來做說明,第一部分是開發環境的需求,第二部分是程式語言的撰寫。

首先先來談談開發環境的部分,我用的是Vs2010+VB

  1. 安裝SAP Client應用程式
  2. 就如同用Oracle Client 連到Oracle Server、As400 client連到As400 Server一樣,在欲開發的機器上,安裝SAP Client,並且設定一個可以連接到SAP Server的 Client Setting
    image
  3. 確定這個client可以順利連結到SAP,設定好相關的IP、ID、系統號碼和登入的帳號密碼等等。

接著打開Visual Studio開發工具,新增一個專案挑選適當的語言,開始撰寫程式:

  1. 先在專案中加入以下四個參考組件,分別為參考COM頁簽中的SAP BAPI Control、SAP Logon Control、SAP Table Factory、SAP Remote Function Call Control。
    image image image image
  2. 加入完成參考,VS專案中會將這些COM元件轉換為相對應的 .NET Interop Assembly放在Bin資料夾中
     image
  3. 在此以ASP.NET為例,新增一個網頁,開發寫程式,首先當然就是把這幾個.NET Interop Assembly相關的命名空間加入到應用程式中:
    Imports SAPBAPIControlLib
    Imports SAPLogonCtrl
    Imports SAPTableFactoryCtrl
    Imports SAPFunctionsOCX
  4. 接著撰寫相關登入SAP的功能,建立SAPLogonCtrl.SAPLogonControlClass物件,用來設定帳號密碼等相關的登入訊息,以便連結

    Dim login As New SAPLogonCtrl.SAPLogonControlClass()
    login.ApplicationServer = "192.168.10.10"
    login.Client = "888"
    login.Language = ""
    login.User = "Adams"
    login.Password = "P@ssw0rd"
    login.SystemNumber = Integer.Parse("00")
    Dim conn As SAPLogonCtrl.Connection = CType(login.NewConnection(), SAPLogonCtrl.Connection)
    If conn.Logon(0, True) Then
      ' 這邊撰寫連結SAP成功之後,.NET所要運作的事項
    Else
       lblMsg.Text = "Login Fail"
    End If

  5. 在來說說SAP/RFC的情境,在這個示範中:
    假設SAP/RFC 的模組名稱叫做:BAPISDORDER_GETDETAILEDLIST
    需要一個Structure,命名為:I_BAPI_VIEW
    以及一個Table當作參數,這個Table命名為:SALES_DOCUMENTS
    如此一來程式碼如下:
    image
  6. 當叫用SAP/RFC成功之後,接著就把所得的資料結果接收回來,假設這邊叫用了SAP/RFC之後,會有3個Table會傳回給.NET,那個就可以使用.NET的相關物件(如:DataTable…)去接收以及使用了
    image

如此一來,.NET Call SAP/RFC 的設計應該就完成了,到時候再依據不同的SAP/RFC所需要的參數,給予不同的數值即可達到動態叫用的功能,以上這幾個步驟和程式碼看起來雖然不多,但是老實說,可是把亞當斯搞得精疲力盡,原因一開始就說了,SAP是一個我從來沒有碰過的東西,又是必須在極短的時間內,也沒有其他人可以提供多餘的資源下,一步一腳印去測試出來,當然有問了一下google大神,但是得到的東西畢竟不多,例如:COM這些元件中的interface叫用的方式等等,都幾乎是一個method、一個method抓出來測試,說來真的是吐血。

不過,等到都測試完成,也搞懂一些有關整合SAP技術的時候,算是學習到一些新技術、新東西吧!當然也希望以上的經驗可以讓有需要的看倌有機會可以運用的上,這樣也算是亞當斯努力的心血中,有得到回報 ^_^y

34 則留言:

Danie 提到...

您好~
看到你的文章之後
宛如看到救星一樣
因為我目前正在做.NET呼叫SAP/RFC的功能
可是一直卡住很久
卻一直解不出來
我也試過您的Source Code修改一下測試
但一直到ifunc.Call()這一段就失敗了
雖然他沒有出現錯誤訊息
但我用if ifunc.Call() Then的語法去測試
發現他回傳都是False
表示呼叫RFC的時候是失敗的
但前面的Connection是正常的
就是這一段我一直卡住
不知道這位大哥是否有建議指導一下小弟
感激不盡~

Danie 提到...

我補充一下我使用ifunc.Call()的回傳訊息
No connection to SAP system available.

亞當斯(Adams) 提到...

如果是回傳false這樣的話,看起來是沒有連線成功唷,最基本的至少你叫用ifun.call的時候,要可以有回傳true才行,阿對了 建議你在叫用的時候 使用多執行緒 來設計

Danie 提到...

謝謝Adams的提醒
我後來step dubug之後才發現
在func.Connection = conn
就有發生Error了
訊息是Bad variant type
可是我前面的Logon是成功的
只有這一段是失敗的
不知道前輩之前是否又遇到同樣的問題
在麻煩給予小弟指教~謝謝!

亞當斯(Adams) 提到...

你試著把4-6這幾個步驟寫到工作執行緒就可以了

Danie 提到...

感謝Adams
終於可以測試成功了
小弟受教良多~謝謝!

亞當斯(Adams) 提到...

不客氣,如果您也有相關.NET / SAP整合的資訊,也可以一起討論分享一下!^^

Unknown 提到...

您好~
在func.Connection = conn時發生error
訊息是Bad variant type
試過把程式放在執行緒裡
但是功力太弱試不成功
後來把該行mark起來
程式就可以運行了
不過這樣在運行此程式時每次都要做登入的動作
是否有其他方法可以讓程式執行時免去登入動作
請前輩指導~~
感激不盡!!謝謝

亞當斯(Adams) 提到...

甯,你好:
解決的方式就是把 4-6這幾個步驟的程式碼寫到另一個執行緒緒中,去執行工作執行緒就可以了

Unknown 提到...

謝謝Adams!!
測試後成功了^^

匿名 提到...

Logon回傳是true,可是在func.Connection = conn
就會有Bad variant type的錯誤訊息,我是把整段放在asp.net中的page_load裏,請問我該如何修正呢? 謝謝!

亞當斯(Adams) 提到...

請參考上列的提問,答案就在其中,把程式碼放到多執行緒即可!!

馬小玲 提到...

我在業界幾家公司call RFC都是採用另一種做法,SAP有出一套工具免費的,叫SAP CONNECTOR,只支援到VS2003,我都直接在VS2003上使用這套工具,它會像程式拶生器把RFC變成.NET的CLASS,將類別檔整個GEN 出來 ,再COPY到VS20XX其他版本上,直接把類別NEW起來用就可以,非常方便喔,您可以查看看sap connector

亞當斯(Adams) 提到...

馬大大,多謝提供另一種解決的方案,我有查了一下,也找到一篇不錯的教學。

http://www.codeproject.com/KB/dotnet/Connect_SAP_from_VS2008.aspx

不過,我想唯一的缺點就是要借用VS2003來設計產生class or component,可能是因為SAP不支援後續的vs版本了。

匿名 提到...

.net connector已經不再改版了,每次都要在VS2003處理後再拿到VS2008上處理,debug上有點麻煩;SAP有出一套新的工具叫SAP Enterprise Services Explorer for Microsoft .NET可以取帶.net connector,只是必需要先在SAP上先安裝NetWeaver;但是因為公司的SAP沒有安裝NetWeaver所以才想找看看還有沒有別的方法

亞當斯(Adams) 提到...

所以說,最直覺也是最快的方式就是使用SAP原本的API,不過這些API也都是COM的感覺,比較麻煩的是沒有函式說明,一切都自己猜。這比較令人灰心~

匿名 提到...

您好,func.connection=conn
我用vs2005也是error,如果4-6這幾個步驟寫到工作執行緒就可以了,是要如何修改程式碼 ?

匿名 提到...

您好,我依您的範例練習,卻出現以下錯誤,不知是不是版本問題?
在func.connection=conn 出現
Bad variant type,請各位協助..

匿名 提到...

您好,
請問如果輸出的中文都變成#,
要如何解決?

匿名 提到...

您好,

我現在遇到一個問題,在SAP T-code ST22 會出現,User "xxx" has no RFC authorization for function group "RFC1".

可是在.Net 2003 的SAP Connecter不會有這種權限的問題.所以Basic同事覺得我們programer應該有別的寫法.可是功力太淺試不出來,請問大人有沒有什麼建議.謝謝!

匿名 提到...

您好!
我想請問一下 sap.net的連接tool在哪下載& 參考要去哪下載><~一直找不到...

ALIK ASP.NET 提到...

SAP Connector for Microsoft .NET已可 Compiled with .NET Framework 4.0

匿名 提到...

您好 不好意思 看到你的文章 讓我獲益良多

目前小弟有個問題 想請問一下 倘若 擷取的

SAP Table 需要給予參數值當作條件式篩選

要如何撰寫呢? 還請大大回覆了 感謝!!

亞當斯(Adams) 提到...

有兩個方式可以針對SAP Table下條件,一個是在Call RFC時,就丟入篩選條件,本範例就是這種方式,這種方式要在RFC就設計好,另一種方式比較簡單,也就是抓取SAP Table資料出來之後我是把結果資料放到一個DataTable的,你可以想像,只要資料放在.NET的DataTable中,你是否就可以隨意去篩選資料呢? 建議用LINQ比較快唷!!

匿名 提到...

感謝~

我順便想再問一下 第一個方式是需要SAP開發人員先撰寫篩選條件的RFC涵式嗎??
第二種方式應該不會要用了 因為想減低資料傳輸的負擔..才會設立條件~

亞當斯(Adams) 提到...

是的! 請你看一下我上面所寫的範例程式,參數就是訂單號碼(一個Table當作參數,再把訂單單號加入),也就是說,要請SAP開發人員先撰寫好可以允許篩選條件的RFC! 就可以啦

匿名 提到...

感謝 解決了 最後用這個寫法
Dim OPStart As SAPFunctionsOCX.Parameter = CType(iSAPCONN.Exports("START_DATE"), SAPFunctionsOCX.Parameter)
Dim OPEnd As SAPFunctionsOCX.Parameter = CType(iSAPCONN.Exports("END_DATE"), SAPFunctionsOCX.Parameter)
OPStart.Value = "20120101"
OPEnd.Value = "20120501"
搞定 @@

匿名 提到...

今天測試發現重大問題~發現傳接的資料 中文字串皆無法顯示~會出現####取代字元 英文字串及數字類別卻正常 請問有何方式可以解決這個問題呢?? 感謝!!

匿名 提到...

今天有找到解決中文#字不能正常顯示方式

但必須要換個寫法 不能使用OCX方式


參考資料:http://www.cnblogs.com/yqy542006/archive/2009/03/30.html
大陸簡體文

希望能給有需要的人參考看看

Unknown 提到...

中文####用Unicode的dll,問題就可以解決

匿名 提到...

你提供的程式,我都沒問題但是RFC傳回筆數卻是0,可是用SE37檢查又有資料,請問要如何解決. 感謝

匿名 提到...

您好~
因為是新手,有看沒有很懂,想透過完整的內容做學習,方便向您索取sample code 嗎?
麻煩了!感謝!

亞當斯(Adams) 提到...

已經將範例程式碼,提供在以下的說明中,請參考!
http://ms-net.blogspot.tw/2015/01/net-call-saprfc-by-visual-basic.html

匿名 提到...

請問在VB叫用COM元件時是否有遇到32位元與64位元的問題呢?
因SAP GUI目前只有32位元的
我是用Lotusscript(語法類似VB)欲叫用COM元件會無法取到
Google後是由於32位元與64位元的問題
若您有遇到請教一下如何解決呢?謝謝