Handle the Big Iron
Introduction:
About the Author :
or integrating A5 with SAP/R3.
by H.P.B.
SAP/R3 is one of the most successful ERP tools on the market.1 It enables the management of all areas of business like logistics, financial information, human resources, manufacturing and inventory management. For the smaller business SAP has it's Business One, which is a more PC-like solution that competes with other typical PC-based accounting systems. In a later article I will show you how you can access, handle and program Business One with Alpha Five as an additional language to Visual Basic, Java or C++, but this article has it's focus on SAP/R3.
The Need:
You might have a customer say to you, "I have a system based on Alpha Five, but I need to show some information from our SAP system and I need to update customer information from your Alpha Five in the SAP system. What can you do to help me?"
Normally those updates and information are handled by text files, XML or other common formats.
I will show you a way to do this without "Text-File-Integration," doing all the work online with Alpha Five.
The Challenge:
Normally such an integration can be done using the SAP .NET Connector, a Web-Service or JCo (Java Connector). But also COM and DCOM are valid ways to communicate with the SAP Environment.
If you have installed the SAP GUI you have all the DLL's and COM stuff you need to do this.
So with some Abap Knowledge (the SAP 4GL Language) and the COM functionality of Alpha Five you have everything you need.
I will show you what can be done in a few minutes and some lines of Code (Abap and XBasic) in 2 examples.
Some words about Abap:
Abap/Abap-Objects is the core programming language of SAP. Most of the stuff in R3 is written in
Abap. Abap is a language mix of some Cobol, Basic, Java and some other 4GL style languages. It's perfect for business programming because of it's SQL enhancements and it's easy-to-understand (even for non-Abap programmers). So I think that you will be able to understand the code I use in these examples.
With Abap you can create reports, screens, business objects and functions. These functions which can work as "Remote Functions" are the base of our solution.
That's enough introduction. Let's rock !
Example 1:
Your customer might ask, "I have this wonderful Alpha Five solution to handle my point-of-sale, but I need information about how much inventory I really have enterprise-wide."
Well, this isn't really a problem. You only need a small Abap program which is implemented as an RFC (Remote Function Call) and some lines of XDialog and XBasic.
Let's start with the Abap part:
1. Create an RFC Function called "Z_A5_SHOW_MAT" with the SE80 transaction in the SAP Dev environment.
2. After you've done this, create the import parameters which are passed to the RFC with XBasic. In this case you pass the material number.
The parameter name is PMATNR and it references to a type ZPMATNR which is declared in the SAP Data Dictionary. It is Character based and has a length of 18.
Now you can switch to the source code tab and start to code the Abap function:
****** ABAP CODE **********************************************
FUNCTION z_a5_show_mat.
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" VALUE(PMATNR) TYPE ZPMATNR
*"----------------------------------------------------------------------
DATA:
* it_bdcdata is an internal table which i use to create a table with
* some commands to control the transaction i want to call. In this case
* the transaction to show the material
it_bdcdata TYPE STANDARD TABLE OF bdcdata,
wa_bdcdata TYPE bdcdata,
* it_lerreor is an iternal table which handles the errors from the
* called transaction
it_lerror TYPE STANDARD TABLE OF bdcmsgcoll.
* Here i fill the internal table IT_BDCDATA with informations about the
* transaction i want to call.
* I want to call the Programm RMMMBEST starting with Dynpro 1000 wich is
* formular / form of R3.
CLEAR wa_bdcdata.
wa_bdcdata-program = 'RMMMBEST'.
wa_bdcdata-dynpro = 1000.
wa_bdcdata-dynbegin = 'X'.
wa_bdcdata-fnam = ''.
wa_bdcdata-fval = ''.
APPEND wa_bdcdata TO it_bdcdata.
* Here i send some "keystrokes" to the form.
CLEAR wa_bdcdata.
wa_bdcdata-program = ''.
wa_bdcdata-dynpro = 0.
wa_bdcdata-dynbegin = ''.
wa_bdcdata-fnam = 'BDC_OKCODE'.
wa_bdcdata-fval = '=ONLI'.
APPEND wa_bdcdata TO it_bdcdata.
* At this point i pass the parameter PMATNR to the called screen to the
* field 'MS_MATNR-LOW'
CLEAR wa_bdcdata.
wa_bdcdata-program = ''.
wa_bdcdata-dynpro = 0.
wa_bdcdata-dynbegin = ''.
wa_bdcdata-fnam = 'MS_MATNR-LOW'.
wa_bdcdata-fval = pmatnr.
APPEND wa_bdcdata TO it_bdcdata.
* Now some additional informations
CLEAR wa_bdcdata.
wa_bdcdata-program = 'SAPMSSY0'.
wa_bdcdata-dynpro = 120.
wa_bdcdata-dynbegin = 'X'.
wa_bdcdata-fnam = ''.
wa_bdcdata-fval = ''.
APPEND wa_bdcdata TO it_bdcdata.
CLEAR wa_bdcdata.
wa_bdcdata-program = ''.
wa_bdcdata-dynpro = 0.
wa_bdcdata-dynbegin = ''.
wa_bdcdata-fnam = 'BDC_OKCODE'.
wa_bdcdata-fval = '=/BDA'.
APPEND wa_bdcdata TO it_bdcdata.
* Here i call a function that passes all the informations of the
* internal control table IT_BDCDATA to a transaction MMBE. This
* transactions calls the Program RMMMBEST and passes the parameters
CALL FUNCTION 'RFC_CALL_TRANSACTION_USING'
EXPORTING
tcode = 'MMBE'
mode = 'E'
TABLES
bt_data = it_bdcdata
l_errors = it_lerror
.
ENDFUNCTION.
****** END ABAP CODE *******************************************
After that you can save your function and activate it.
Now comes the A5 XBasic part.
1. Create a XBasic Script called "SapShowMat". This script contains a XDialog and the code to connect to SAP and handle the RFC call etc.etc.
****** XBasic CODE **********************************************
dim FunctionCtrl as P
dim SapConnection as P
dim func1 as P
'Prompt for Material Number and store result in a variable called 'vMatNr'.
dim prmpt_title as c
dim prmpt_prompt as c
dim prmpt_default as c
prmpt_title = "Please enter Material Number"
prmpt_prompt = "Material Number "
prmpt_default = ""
DIM SHARED vMatNr AS C
vMatNr = ui_get_text(prmpt_title,prmpt_prompt,prmpt_default)
'Here i create an OLE Object to the SAP.Functions Control
FunctionCtrl = ole.create("SAP.Functions")
'Start / Make the connection
SapConnection = FunctionCtrl.Connection()
'Set the property RFCWihtDialog to 1. This shows the COM logon dialog.
SapConnection.RFCWithDialog = "1"
'Now logon
SapConnection.logon()
'Here i tell the control with the Method ADD which RFC funktion it has to call
func1 = FunctionCtrl.Add("Z_A5_SHOW_MAT")
'Here i pass the parameter PMATNR to the SAP RFC Function
func1.exports("PMATNR") = vMatNr
'And now i "call" the transaction with some error handling if it works etc.etc.
if .not. func1.call()
'Damned..... no connection
DIM SAPError_result as N
DIM SAPError_OK_Button as L
SAPError_OK_Button = .F.
title_var = "Test"
message_text_var = <<%text%
Error. SapGui Problem !
%text%
SAPError_result=ui_msg_box(title_var,message_text_var,UI_OK+ UI_FIRST_BUTTON_DEFAULT+ UI_INFORMATION_SYMBOL)
else
'Thanks.....GUI was shown and will be closed when pressing "BACK" button in SAP
DIM SAPOK_result as N
DIM SAPOK_OK_Button as L
SAPOK_OK_Button = .F.
title_var = "SAP Gui"
message_text_var = <<%text%
Everythin OK. SapGui will be closed !
%text%
SAPOK_result=ui_msg_box(title_var,message_text_var,UI_OK+ UI_FIRST_BUTTON_DEFAULT+ UI_INFORMATION_SYMBOL)
end if
'And finally close the connection to SAP and logoff.
SapConnection.logoff()
******END XBasic CODE ******************************************
That's all. It's not really complicated. If everything is OK, it should work like this :
1. Open A5 and start the XBasic Script "SapShowMat"
2. Enter a Material Number and press the OK button. In the upper code I haven't all the exception stuff to validate a Material Number etc.etc. so be sure that you enter a valid Material Number ;-))
3. After pressing OK, the SAP logon dialog opens and you have to select a SAP Connection, enter a valid user name and password.
4. And that's it. SAP opens the SAP GUI, calls the transaction and shows you how much material for the Material Number AS2-1200 you have.
5. After pressing the "Back" button Alpha Five gives you the information that everything is OK and closes the SAP GUI.
As you can see it's very easy to integrate an SAP Online Transaction into an Alpha Five application. In such Online Transactions you can enter new data, update data, enter invoices and so on. But everything can be controlled by Alpha Five and XBasic.
But what if you want to update data in SAP/R3 without using an Online Transaction? If you have other apps running using MS-SQL or Oracle or other server-centric DB data, you can use some ODBC or OLE-DB or ADO.NET tools to update these data.
SAP's database is normally such a server-centric DB like MS-SQL, Oracle or the SAP-DB (now called MAX-DB and owned by MySQL). Well, if you think that you can use the SAP Database with ODBC trying to connect to such a DB, forget it. First, the DB contains more than 30,000 Tables, depending on what modules you have installed. Second, SAP is using a technique inside of the DB which has Tables "in" Tables (each record has a BLOB, which also has a Table inside). There is an ODBC Driver on the market for this. But it costs round about $30,000 for each server machine.
Hmmmm. Ok, here is the example showing how you can do it without this ODBC stuff. Just some plain Abap and some plain XBasic.
Example 2:
After implementing the upper Online Transaction (in 30 Minutes) your customer comes to you and says: "What? You've done it so fast? OK. Here is a real challenge for you. I need to update my customers in SAP with my Alpha Five point-of-sale application, without opening an online transaction and enter the data by hand."
You start smiling, turn around and go back to your office. You open your CD player and start hearing an old "Simple Minds" CD.
Starting the first song "Alive and kicking" you begin with the Abap Part of the challenge.
1. Create an RFC Function called "Z_A5_UPDATE_CUST" with the SE80 transaction in the SAP Dev environment.
2. After you've done this you create the import parameters which are passed to the RFC with XBasic. In this case you pass the Customer number, Customer name and Customer Phonenumber.
The parameters do also reference to some types that are declared in the SAP Data Dictionary.
Now you can switch to the source code tab and start to code the Abap function :
****** ABAP CODE **********************************************
FUNCTION z_a5_update_cust.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*" IMPORTING
*" VALUE(ZA5CUSTNR) TYPE ZA5CUSTNR
*" VALUE(ZA5NAME1) TYPE ZA5NAME1
*" VALUE(ZA5TEL) TYPE ZA5TEL
*"----------------------------------------------------------------------
* update the customer master data table KNA1 with ABAP-SQL
UPDATE kna1 SET
name1 = za5name1
telf1 = za5tel
WHERE kunnr = za5custnr.
* send the commit to the application server
COMMIT WORK.
ENDFUNCTION.
****** END ABAP CODE ******************************************
After that you can save your function and activate it.
Starting the second song "Don't you" you begin with the A5 Part of the challenge.
1. Create a form and a button similar like the screenshot.
2. In the OnPush Event of the Button "Update SAP Customer" put the following XBasic Code.
****** XBasic CODE **********************************************
dim FunctionCtrl as P
dim SapConnection as P
dim func1 as P
'Here i create an OLE Object to the SAP.Functions Control
FunctionCtrl = ole.create("SAP.Functions")
'Start / Make the connection
SapConnection = FunctionCtrl.Connection()
'Set the property RFCWihtDialog to 1. This shows the COM logon dialog.
SapConnection.RFCWithDialog = "1"
'Now logon
SapConnection.logon()
'Here i tell the control with the Method ADD which RFC funktion it has to call
'In this case the Function Z_A5_UPDATE_CUST
func1 = FunctionCtrl.Add("Z_A5_UPDATE_CUST")
'Here i pass the parameters of the adress to the SAP RFC Function
func1.exports("ZA5CUSTNR") = customers->Customernr
func1.exports("ZA5NAME1") = customers->Customername
func1.exports("ZA5TEL") = customers->Customerphone
'And now i "call" the transaction with some error handling if it works etc.etc.
if .not. func1.call()
'Damned..... no connection
DIM SAPError_result as N
DIM SAPError_OK_Button as L
SAPError_OK_Button = .F.
title_var = "Test"
message_text_var = <<%text%
Error. RFC Problem !
%text%
SAPError_result=ui_msg_box(title_var,message_text_var,UI_OK+ UI_FIRST_BUTTON_DEFAULT+ UI_INFORMATION_SYMBOL)
else
'Thanks.....GUI was shown and will be closed when pressing "BACK" button in SAP
DIM SAPOK_result as N
DIM SAPOK_OK_Button as L
SAPOK_OK_Button = .F.
title_var = "SAP Gui"
message_text_var = <<%text%
Everything OK. Customer Update sucessfull !
%text%
SAPOK_result=ui_msg_box(title_var,message_text_var,UI_OK+ UI_FIRST_BUTTON_DEFAULT+ UI_INFORMATION_SYMBOL)
end if
'And finally close the connection to SAP and logoff.
SapConnection.logoff()
****** END XBasic CODE ******************************************
After that, and if everything is OK, your application should run like this:
1. This is the original value in the SAP Database (shown in a transaction SE16 which shows you the data of a table in the SAP DB)
2. Here is the A5 Form with the data (Customer) I want to update on SAP/R3
As you can see, the customer name and the phone number in Alpha Five have other values than those in SAP/R3.
3. Now press the "Update SAP Customer Button". Once again, the SAP Logon Dialog comes up and you have to enter your client name, user name and password. After you've done this (press the OK Button of the Logon Dialog) you get a message by Alpha Five that the customer has been updated.
4. And here is the result in the SAP Database (again in the SE16 Data Browser)
Now, the second song ("Don't you") of "Simple Minds" is over. You can go to your customer and say,
"It's done!" They will be surprised at the speed of the development, and you will have one more happy customer.
Some words about the second solution: Normally, you have hundreds of customers working with SAP in a concurrent environment. So, you have to think about carefully if you lock the record before you update it.
For this you can use an internal technique called "Dequeue" and "Enqueue". But that's another story.
So. I'm ready. Hope you have an idea now of how you can deal with SAP/R3. Of course, there are many more things you can do. And after you've explored the world of SAP, you'll have many new ideas about what you can do to enhance your application with the Back Office power of SAP.
H.P. is working as a full-time Developer for one of top SAP Partners in Germany. Working with Abap and Abap Objects all day and Alpha Five for his private work, his idea was to combine Alpha Five, SAP/R3 and SAP Business One. He also works with C# and .NET on a small project that you can access and deal with SAP without the need of ABAP RFC's in the background direct from Alpha Five. He can be reached by private eMail hbach1968@aol.com.
Trademarks:
SAP, SAP/R3, SAP Business One, Abap, Abap-Objects, SAP .NET Connector, JCo are registered trademarks by SAP.
.NET, Visual Basic are registered trademarks by Microsoft Corp.
Java is a registered trademark by SUN.
1 SAP is the biggest German Software Company and AFAIK in the top 10 of the biggest Software Companies in the World. The Name SAP stands for "Systems, Applications and Programs".
ERP is the Acronym of "Enterprise Resource Planing". A common word for software for Accounting, Payroll, Inventory, Production planing etc.