Subscribe

RSS Feed (xml)



Powered By

Skin Design:
Free Blogger Skins

Powered by Blogger

Showing posts with label Abap macros. Show all posts
Showing posts with label Abap macros. Show all posts

Wednesday, October 13, 2010

Vb codes (or VBA macro code) for access SAP, and run one RFC

I am looking for, Vb codes (or VBA macro code) for access SAP, and run one RFC .

Does anyone have example VB to SAP code?

I can give you some code, but not sure it will work for you. When you ( or the help desk ) installs the SAP GUI, you can also install the SAP RFC development kit, if you do this you will have in your c:\program files\SAP??? ( in my case C:\Program Files\SAP620 ) a folder with a .frm extension
( in my case C:\Program Files\SAP620 \SAPGUI\rfcsdk\ccsamp\RFCSamp.VB\RFCsamp.frm )

From there you can start then, because you also need the vbp file and the vbw file in order to really make it work. If you just need the code, then here you go :

Option Explicit

Private Sub Command1_Click()
'Dim Foo As RFCSampObj ' Due to an acknowledged problem in MTS
Dim Foo As Object ' we Dim Foo as Object instead of as RFCSampObj
Dim searchterm As String
Dim custlist As Recordset

Set Foo = CreateObject("RFCSampObj.RFCSampObj.1")
Foo.Destination = "IDES"
'Foo.Client = "800"
'Foo.Language = "E"
'Foo.UserID = "test"
'Foo.Password = "pw"

If Not Foo Is Nothing Then
searchterm = Text1.Text
'Unfortunately RFC_CUSTOMER_GET does not convert
' a SPACE selction into a * so we do it here....
If IsEmpty(searchterm) Then searchterm = "*"

On Error Resume Next
Call Foo.GetCustList(searchterm, "", custlist)

If Err.Number = 0 Then
If Not custlist Is Nothing Then
custlist.MoveFirst
While Not custlist.EOF
Debug.Print "------------------"
Debug.Print "custlist.Fields(name1) " &
custlist.Fields("NAME1")
Debug.Print "custlist.Fields(stras) " &
custlist.Fields("STRAS")
Debug.Print "custlist.Fields(ort01) " &
custlist.Fields("ORT01")
Debug.Print "custlist.Fields(pstlz) " &
custlist.Fields("PSTLZ")
Debug.Print "custlist.Fields(telf1) " &
custlist.Fields("TELF1")
Debug.Print "custlist.Fields(telfx) " &
custlist.Fields("TELFX")
custlist.MoveNext
Wend
Else
Debug.Print "ERROR: custlist is Nothing"
End If
Else
Debug.Print "ERROR" & Err.Description
MsgBox Err.Description, vbCritical, "Error:"

End If
Else
Debug.Print "Foo is nothing"
MsgBox "Foo is nothing"
End If

End Sub

Private Sub Command2_Click()

'Dim Foo As RFCSampObj ' Due to an acknowledged problem in MTS
Dim Foo As Object ' we Dim Foo as Object instead of as RFCSampObj

Dim rs As Recordset
Dim HeaderIn As Recordset
Dim ItemsIn As Recordset
Dim Partners As Recordset
Dim OrderNumber As String
Dim BapiReturn As Recordset
Dim SoldTo As Recordset
Dim ShipTo As Recordset
Dim Payer As Recordset
Dim ItemsOut As Recordset

'Input tables can be crafted in two different ways:
' - either using the DimAsXXXX method which returns a fully
' described but empty Recordset.
' - or using the AdvancedDataFactory to craft up a disconnected
' Recordset.
' An example of the later is shown with the Partners Table
' the remaining input tables are crafted with the dim as.
Dim adf As Object
' Describe the shape of a disconnected recordset

Dim vrsShape(1)
Dim vrsParvw(3)
Dim vrsKunnr(3)

vrsParvw(0) = "PARTN_ROLE"
vrsParvw(1) = CInt(8)
vrsParvw(2) = CInt(2)
vrsParvw(3) = False

vrsKunnr(0) = "PARTN_NUMB"
vrsKunnr(1) = CInt(8)
vrsKunnr(2) = CInt(10)
vrsKunnr(3) = False

vrsShape(0) = vrsParvw
vrsShape(1) = vrsKunnr

' Create a disconnected recordset to pass as an input

Set adf = CreateObject("RDSServer.DataFactory")
If adf Is Nothing Then
MsgBox "ADF == NOTGHING"
End If
Set Partners = adf.CreateRecordSet(vrsShape)

Set Foo = CreateObject("RFCSampObj.RFCSampObj.1")
If Not Foo Is Nothing Then

' Get an empty recordset which will be used as input in
CreateOrder call

Call Foo.DimHeader(HeaderIn)
HeaderIn.AddNew
HeaderIn.Fields("DOC_TYPE") = "TA"
HeaderIn.Fields("SALES_ORG") = "1000"
HeaderIn.Fields("DISTR_CHAN") = "10"
HeaderIn.Fields("DIVISION") = "00"
HeaderIn.Fields("PURCH_NO") = "SM-1177-3"
HeaderIn.Fields("INCOTERMS1") = "CPT"
HeaderIn.Fields("INCOTERMS2") = "Hamburg"
HeaderIn.Fields("PMNTTRMS") = "ZB01"
HeaderIn.Update

Call Foo.DimItems(ItemsIn)
ItemsIn.AddNew
ItemsIn.Fields("MATERIAL") = "R-1120"
ItemsIn.Fields("PLANT") = "1200"
ItemsIn.Fields("REQ_QTY") = 2000
ItemsIn.Update

Partners.AddNew
Partners.Fields("PARTN_ROLE") = "AG"
Partners.Fields("PARTN_NUMB") = "0000001177"
Partners.Update

'set logon information
Foo.Destination = "IDES"
'Foo.Client = "800"
'Foo.Language = "E"
'Foo.UserID = "test"
'Foo.Password = "pw"

Call Foo.OrderCreate(HeaderIn, _
ItemsIn, _
Partners, _
OrderNumber, _
SoldTo, _
ShipTo, _
Payer, _
ItemsOut, _
BapiReturn)
Debug.Print "OrderNumber" & OrderNumber
If BapiReturn Is Nothing Then
MsgBox "BapiReturn is Nothing"
Else
BapiReturn.MoveFirst
Debug.Print "BapiReturn.Type...." & BapiReturn.Fields("TYPE")
Debug.Print "BapiReturn.Code...." & BapiReturn.Fields("CODE")
Debug.Print "BapiReturn.Message." & BapiReturn.Fields
("MESSAGE")
Debug.Print "BapiReturn.LogNo..." & BapiReturn.Fields
("LOG_NO")
Debug.Print "BapiReturn.LogMsgNo" & BapiReturn.Fields
("LOG_MSG_NO")
End If
Else
MsgBox "Foo is nothing"
End If

End Sub


Private Sub Command3_Click()

'Dim Foo As RFCSampObj ' Due to an acknowledged problem in MTS
Dim Foo As Object ' we Dim Foo as Object instead of as RFCSampObj

Dim SalesOrders As Recordset
Dim BapiReturn As Recordset

Set Foo = CreateObject("RFCSampObj.RFCSampObj.1")

If Not Foo Is Nothing Then

'set logon information
Foo.Destination = "IDES"
'Foo.Client = "800"
'Foo.Language = "E"
'Foo.UserID = "test"
'Foo.Password = "pw"


On Error Resume Next
Call Foo.GetCustomerOrders(CustomerNumber.Text, _
SalesOrg.Text, _
, , , , _
BapiReturn, _
SalesOrders)

If Err.Number = 0 Then
If Not SalesOrders Is Nothing Then
SalesOrders.MoveFirst
While Not SalesOrders.EOF
Debug.Print "------------------"
Debug.Print "SalesOrders.Fields(SD_DOC).... " &
SalesOrders.Fields("SD_DOC")
Debug.Print "SalesOrders.Fields(ITM_NUMBER) " &
SalesOrders.Fields("ITM_NUMBER")
Debug.Print "SalesOrders.Fields(MATERIAL).. " &
SalesOrders.Fields("MATERIAL")
Debug.Print "SalesOrders.Fields(REQ_QTY)... " &
SalesOrders.Fields("REQ_QTY")
Debug.Print "SalesOrders.Fields(NAME)...... " &
SalesOrders.Fields("NAME")
Debug.Print "SalesOrders.Fields(NET_VALUE). " &
SalesOrders.Fields("NET_VALUE")
Debug.Print "SalesOrders.Fields(PURCH_NO).. " &
SalesOrders.Fields("PURCH_NO")
SalesOrders.MoveNext
Wend
Else
Debug.Print "ERROR: SalesOrders is Nothing"
End If
If BapiReturn Is Nothing Then
MsgBox "BapiReturn is Nothing"
Else
BapiReturn.MoveFirst
Debug.Print "BapiReturn.Type...." & BapiReturn.Fields
("TYPE")
Debug.Print "BapiReturn.Code...." & BapiReturn.Fields
("CODE")
Debug.Print "BapiReturn.Message." & BapiReturn.Fields
("MESSAGE")
Debug.Print "BapiReturn.LogNo..." & BapiReturn.Fields
("LOG_NO")
Debug.Print "BapiReturn.LogMsgNo" & BapiReturn.Fields
("LOG_MSG_NO")
End If
Else
Debug.Print "ERROR"
MsgBox Err.Description, vbCritical, "Error:"

End If
Else
MsgBox "Foo is nothing"
End If

End Sub

Macro in ABAP

REPORT ZMACRO.

DATA: RESULT TYPE I,
N1 TYPE I VALUE 5,
N2 TYPE I VALUE 6.

DEFINE OPERATION.
RESULT = &1 &2 &3.
OUTPUT &1 &2 &3 RESULT.
END-OF-DEFINITION.

DEFINE OUTPUT.
WRITE: / 'The result of &1 &2 &3 is', &4.
END-OF-DEFINITION.

OPERATION 4 + 3.
OPERATION 2 ** 7.
OPERATION N2 - N1.

*-- End of Program

Macros

If you want to reuse the same set of statements more than once in a program, you can include them in a macro. For example, this can be useful for long calculations or complex WRITE statements. You can only use a macro within the program in which it is defined, and it can only be called in lines of the program following its definition.

The following statement block defines a macro macro:

DEFINE makro.

statements

END-OF-DEFINITION.

You must specify complete statements between DEFINE and END‑OF‑DEFINITION. These statements can contain up to nine placeholders &1, &2,...., &9). You must define the macro before the point in the program at which you want to use it.

Macros do not belong to the definition part of the program. This means that the DEFINE statement block is not interpreted before the processing blocks in the program. At the same time, however, macros are not operational statements that are executed within a processing block at runtime. When the program is generated, macro definitions are not taken into account at the point at which they are defined. For this reason, they do not appear in the overview of the Structure of the Processing Logic [Structure of the Processing Logic-- see at the last of the discripation].

A macro definition inserts a form of shortcut at any point in a program and can be used at any subsequent point in the program. As the programmer, you must ensure that the macro definition occurs in the program before the macro itself is used. Particular care is required if you use both macros and include programs, since not all include programs are included in the syntax check (exception: TOP include).

To use a macro, use the following form:

makro [p1 p2... p9].

When the program is generated, the system replaces the macro by the appropriate statements and the placeholders &1, &2, …, &9 by the parameter p1, p2, …, p9. You can use macros within macros. However, a macro cannot call itself.


REPORT demo_mod_tech_macros.

DATA: result TYPE i,
n1 TYPE i VALUE 5,
n2 TYPE i VALUE 6.

DEFINE operation.
result = &1 &2 &3.
output &1 &2 &3 result.

END-OF-DEFINITION.

DEFINE output.
write: / 'The result of &1 &2 &3 is', &4.
END-OF-DEFINITION.

operation 4 + 3.
operation 2 ** 7.
operation n2 - n1.

This produces the following output:

The result of 4 + 3 is 7

The result of 2 ** 7 is 128

The result of N2 - N1 is 1

In this example, the two macros operation and output are defined. output is nested in operation. operation is called three times with different parameters. Note how the placeholders &1, &2,... are replaced in the macros.


The following example shows that a macro definition only works in the program lines following its definition. Do not copy it!

Let us have a look at a program with a subroutine test:

PROGRAM macro_test.

...

FORM test.
WRITE '...'.
ENDFORM.

We can rewrite the program by introducing a macro macro:

PROGRAM macro_test.

...

FORM test.

DEFINE macro.
WRITE '...'.
ENDFORM.
END-OF-DEFINITION.

MACRO.

Inserting the macro changes nothing in the generated form of the program. Processing blocks - here a subroutine - are always indivisible. We could also write the program as follows:

PROGRAM macro_test.

...

DEFINE macro.
WRITE '...'.
ENDFORM.
END-OF-DEFINITION.

...

FORM test.

MACRO.

The most essential feature of a macro definition is that it should occur before the macro is used.

___________________________________________________________________

Structure of the Processing Logic

Each ABAP program consists of an introductory program part, a global declaration part and a number of processing blocks which implement different functions depending on the application (procedures, dialog modules, event blocks). Processing blocks are inseparable syntactical modularization units which cannot comprise any other processing block. Normally they contain several ABAP statements which are organized into statement blocks by means of control structures.

The following diagram shows the structure of an ABAP program:

This graphic is explained in the accompanying text

Introductory Program Part

Every independent ABAP program begins with an introductory statement which depends on the program type. Some of these statements have additions which you can use to make program settings.

Declaration Part for Global Data, Classes and Selection Screens

In every ABAP program, the introductory program part is followed by the declaration part for global data, classes, and selection screens. This consists of:

· All declaration statements for global data. Global data is visible in all internal processing blocks. You define it using declarative statements that appear before the first processing block, in dialog modules, or in event blocks. You cannot declare local data in dialog modules or event blocks except the following:

· All selection screen definitions.

· All declarations of internal class definitions and interfaces.

Declaration statements which occur in procedures (methods, subroutines, function modules) form the declaration part for local data in those processing blocks. This data is only visible within the procedure in which it is declared.

Container for Processing Blocks

You can list the processing blocks of an ABAP program in the source code of the program in any sequence you like below the global declaration part as they are not executed consecutively. Only the source code contained in a statement block is executed sequentially.

The following types of processing blocks are available which can be exited prematurely using the RETURN statement.

· Dialog modules (no local data area)

· Event blocks (no local data area, with two exceptions)

· Procedures (methods, subroutines and function modules with their own local data area).

Whereas dialog modules and procedures are enclosed in the ABAP keywords which define them, event blocks are introduced with event keywords and concluded implicitly by the beginning of the next processing block.

All ABAP statements (except declarative statements in the declaration part of the program) are part of a processing block. Non-declarative ABAP statements, which occur between the declaration of global data and a processing block are automatically assigned to the START-OF-SELECTION processing block.

Macro to validate Date in abap sap

* Programme : zdate_validate *
* Title : Macro to validate Date *
* Author : Abhishek Kumar *
* Description : This program has two macros and a sample code which is *
* showing how to use that. *
* Macro 1. > Val_date *
* Macro 2. > Valdate *
* It return SY-Subrc value if it 0 then the entered date *
* is valid else either the date is invalid or the *
* specified format is invalid *
*----------------------------------------------------------------------*
* Created and Designed by Abhishek Kumar in Nov 2001. *
*----------------------------------------------------------------------*
*Abhishek is not responsible for any damages caused by the use or *
*misuse of this program and cannot provide any warranty with this *
*program. Use it entirely at your own risk. *
* *
*You are not authorised to make any changes without prior written *
*permission from the author. *
*======================================================================*

PROGRAM ZDATE_VALIDATE .
* Validation of Date
DEFINE VAL_DATE.
CLEAR: %_DATE1,
%_DATE2.
%_DATE1(4) = &1. "Year
%_DATE1+4(2) = &2. "Month
%_DATE1+6(2) = &3. "Date
%_DATE2 = %_DATE1 - 1.
%_DATE2 = %_DATE2 + 1.
IF %_DATE1 <> %_DATE2.
SY-SUBRC = 1.
ELSE.
SY-SUBRC = 0.
ENDIF.
END-OF-DEFINITION.

DEFINE VALDATE.
***************************************************
* Passing Parameters: &1 - Date
* &2 - Date Format
*
* Date Format:
* DDMMYYYY MMDDYYYY YYYYMMDD YYYYDDMM
*
* SY-SUBRC Return Value:
* 1 invalid date
* 0 Valid Date
* 2 Invalid Format
***************************************************
DATA: %_DATE1 LIKE SY-DATUM ,
%_DATE2 LIKE SY-DATUM ,
%_DATE3(8).
case &2.
when 'DDMMYYYY'.
val_date &1+4(4) &1+2(2) &1+0(2).
when 'MMDDYYYY'.
val_date &1+4(4) &1+0(2) &1+2(2).
when 'YYYYMMDD'.
val_date &1+0(4) &1+4(2) &1+6(2).
when 'MMYYYYDD'.
val_date &1+2(4) &1+0(2) &1+6(2).
when others.
sy-subrc = 2.
endcase.
END-OF-DEFINITION.

***********************************************
* SAMPLE USE of above MACRO *
***********************************************

DATA: V_DATE(8).
V_DATE = '30022002'.
*=>
VALDATE V_DATE 'DDMMYYYY'.
*=>
IF SY-SUBRC = 0.
WRITE:/ 'Valid Date'.
ELSEIF SY-SUBRC = 1.
WRITE:/ 'Invalid Date'.
ELSEIF SY-SUBRC = 2.
WRITE:/ 'Invalid Format'.
ENDIF.
*********************************************************************

Unleash the power of macros in ABAP

Takeaway: Like many programming languages, SAP's ABAP makes liberal use of macros. Here are some scenarios that illustrate when using macros in SAP is the best choice.


As programs grow larger and larger, it becomes more difficult for programmers to enhance and debug source code. Luckily, computer languages make developers' lives easier by offering various modularization methods, making program code meaningful and easily understandable.

ABAP, SAP's programming language, is no exception. It leverages various modularization options, each having its own strengths and weaknesses. These options may have local access from a particular program—such as form routines and macros—or they may have global access, such as function modules or include programs.

Although a comprehensive discussion of all the modularization techniques available in ABAP is beyond the scope of this article, we can look at one option—macros—and consider some situations where they work better than other options.

Getting a feel of macros
The basic syntax of macros is as follows:
DEFINE macro_name. "Macro Definition
……………. Statements
……………. Statements
…………………
END-OF-DEFINITION. "Macro Definition

macro_name par1 par2 …par9. "Macro call -parameters separated by spaces

Within the DEFINE... and END-OF-DEFINITION lies the body of the macro—the statements that you wish to be executed each time the macro is called. These statements may be any valid ABAP statements, such as WRITE, CLEAR, FORM calls, or database statements such as SELECT or UPDATE.

To familiarize yourself with the working of macros, it's necessary to take a close look at exactly what happens when an ABAP program containing a macro call is generated. Consider Listing A.

All ABAP programs must be generated before they can be executed. At the time of program generation, the system supplants each macro call, as shown in Listing A, with the statement(s) placed between the macro definition. Furthermore, the parameters passed at the time of macro calling are copied in place of the any placeholders (numbered &1, &2 …&9) found in the body of the macro definition. The system simply ignores the presence of the macros during the execution of the program—that is, all statements are executed as a single block of code:
write : int1.
write : int2.
write : int3.

Other than readability and meaningfulness, macros also offer performance advantages. For testing purposes, I wrote a macro that incremented the value of a variable by 1 and called the macro N times via a DO loop, as shown here:
DEFINE INCREMENT.
ADD 1 TO &1.
END-OF-DEFINITION.

DO N TIMES.
INCREMENT VAR1.
ENDDO.

The runtime was measured using an SAP tool known as the Runtime Analyzer (SE30) for different values of N. To check performance, I copied the same program but replaced the macro call and definition with those of form routines. Table A shows a comparison of the performance of both macros and form routines(all times in microseconds). Macros, in this case, were nine times faster than forms routines.

N 1000 10000 100000
Form 731 6974 71236
Macros 74 708 7134

Applying macros to suit business needs
Apart from their readability and efficiency, macros can be more effective than other modularization techniques because of their versatility in replacing different ABAP statements in solving business problems.

ABAP provides only the syntax for creating macros. It's up to the programmer to devise ways that best suit the requirements. The power of macro programming lies in mastering the ways macros can be used in ABAP programs.

Macros can be used for different purposes within the SAP terrain. I have tried to compile the variety of ways I've seen macros adding elegance to ABAP applications. Here's a closer look.

Data declaration
You can use macros to define variables. A simple example is:
DEFINE table.
data: &1 like &2 occurs 0 with header line.
END-OF-DEFINITION.

table itab1 lfa1.
table itab2 pernr.

Instead of writing the same data declaration statement each time a new variable is declared, you can simply reuse the code via macros.

Complex WRITE statements
Programs often get unnecessarily verbose and difficult to understand because they contain lengthy and redundant WRITE statements. Macros allow you to maintain readability while writing complex WRITE statements. You can write macros to replace all variants supported by the WRITE statement. Here's a simple example:
DEFINE Write_stat.
Write : &1 no-zero right-justified color &2.
END-OF-DEFINITION.

The example declares a macro write_stat. The macro prints—after truncating their zeros—variables in a right-aligned format in the color specified by number &2. Instead of writing similar WRITE statements repeatedly, you can simply call the macro and pass the desired output specifications as parameters, like this:
Write_stat var1 1.
Write_stat var2 2.

Reading/changing variable values
You can use macros to replace any set of repetitive statements that check or modify values of variables. Typical examples are simple IF checks or CLEAR statements. For simplicity's sake, I'm showing only how the body of such macros may look:
If not &1 is initial.
Endif.

clear: &1,
&2.

Formulas or calculations
You can use macros to define formulas for complex calculations. In this case, the placeholders may be operands (such as +, -), constant values, or local variables. Here's an example:
DEFINE operation.
result = ( &1 &2 &3 ) &4 ( &5 &6 &7 ).
END-OF-DEFINITION.
Operation 5 – 3 / var2 + 9.
Operation var1 + 7 * 6 + 5.

Nesting macros
The ability of macros to call other macros makes them even more powerful. Consider the following example:
DEFINE macro_1.
Write :/'Macro 1 called'.
Macro_2 .
END-OF-DEFINITION.

DEFINE macro_2.
Write :/'Macro 2 called'.
END-OF-DEFINITION.

Macro_1. "Macro Call for Macro 1.

In this example, only the first macro is called by the main program. After executing the write statement of Macro 1, the system executes the body of the second macro as well.

Program flexibility
Macros help you to minimize hard coding to make your applications more flexible. For example, you can call function modules dynamically. Consider the following program segment:
define dynamic_function_call .
CALL FUNCTION &1
EXPORTING
SECONDS = '10'.
end-of-definition.

dynamic_function_call 'ENQUE_SLEEP'.
dynamic_function_call funcname.

Here, we define a macro that calls a function module whose name is not hard coded, but rather passed as a parameter to be evaluated at runtime. You can use the same approach when making configurable applications. The name of the function may be kept in a database table whose records are read before the macro call. In this manner, program behavior may be adapted without a need to modify source code.

Working with heavy data
Many SAP programs use macros to export and import data to and from the database. Consumption of system resources is optimal if macros are employed, particularly when a large amount of data is involved:
DEFINE EXPORT_MACRO.
Export &1 &2 &3 to database indx(DB) id 'DATA'.
END-OF-DEFINITION.

EXPORT_MACRO itab1 itab2 itab3.

In this example, the data of three internal tables that may each consist of a large number of records is exported to the table INDX. Had we used form routines in this case, you can't imagine the resources (CPU time and memory) that would be consumed while passing tables as parameters.

Determine the best option
Macros are one of the modularization options provided by the ABAP language, and we've focused here on situations where macros are most appropriate. However, macros are not always the best choice. It is up to you to decide which of the modularization techniques suits a particular scenario.

Macro in ABAP

*
* Macro in ABAP
*
* Submitted by : SAP Basis, ABAP Programming and Other IMG Stuff
*
*
REPORT ZMACRO.

DATA: RESULT TYPE I,
N1 TYPE I VALUE 5,
N2 TYPE I VALUE 6.

DEFINE OPERATION.
RESULT = &1 &2 &3.
OUTPUT &1 &2 &3 RESULT.
END-OF-DEFINITION.

DEFINE OUTPUT.
WRITE: / 'The result of &1 &2 &3 is', &4.
END-OF-DEFINITION.

OPERATION 4 + 3.
OPERATION 2 ** 7.
OPERATION N2 - N1.

*-- End of Program

DEFINE

Basic form

DEFINE macro.

Effect

Defines a program component (macro) under the name macro . It must consist only of ABAP/4 statements and is expanded at compilation time.

A macro should always be concluded with the END-OF-DEFINITION statement.

In the definition, you can use &n to reference positional parameters (n = 0 .. 9). When the macro is called, &n is replaced by the n-th actual parameter.

Example

Define a macro called "++" for use in the program.

DEFINE ++.
ADD 1 TO &1.
END-OF-DEFINITION.

DATA: NUMBER TYPE I VALUE 1.
...
++ NUMBER.

Notes

  • In general, it is better to use subroutines (FORM, FUNCTION ) rather than macros because subroutines - unlike macros - are supported by all the ABAP/4 Development Workbench tools (including debugging, runtime analysis, runtime error handling, ...).
  • You cannot nest macro definitions.

hr abap- macro

Q1] from what I'm understanding you are saying that rp_provide_from_last and rp_provide_from_frst are resulting in the same data being taken in. If it is not a reading problem I bet that the infotype that you are reading only has one record in it, meaning the first and last record would defintly be equal

ANS>

Instead of using the rp-provide from last you can use the provide statement only. See attached a program here using the rp-read-infotype macro you can have a better control.



************************************************************************

  • AUTHOR : shekhar s kulkarni
  • DATE : 18th july 2003
  • DESCRIPTION :

*

  • DEV REQUEST :

************************************************************************

  • MODIFICATION LOGS
  • VERSION
  • DATE
  • REQUEST NO
  • DESCRIPTION

************************************************************************

REPORT zpyr_overseasemplist.

*Declaration for type pool

TYPE-POOLS :slis.



*Declaration for tables

TABLES : pa0000,pa0008, zhrrole, zhrband, zhrrole_assg,t001p,t503t,t500p

,t005h,t591s.



*Declaration for infotypes

INFOTYPES : 0000,0001,9009,0008,9001,9015.



*Declaration data for alv list

DATA: lv_tmplt LIKE disvariant VALUE 'ZPYR_ELIGIBLESALARY',

lv_fieldcat TYPE slis_t_fieldcat_alv,

lv_ls_layout TYPE slis_layout_alv,

driver LIKE sy-repid,

wa_lv_fieldcat TYPE slis_fieldcat_main,

farben TYPE slis_specialcol_alv, "color display

it_events TYPE slis_t_event,

wa_events TYPE slis_alv_event,

gs_extract1 LIKE disextract.



DATA: BEGIN OF it_leavedate OCCURS 0.

INCLUDE STRUCTURE hida.

DATA: END OF it_leavedate.

*Declaration data for program zpyr_overseasemplist

DATA : BEGIN OF it_overseas OCCURS 0,

empno LIKE pa0008-pernr,

name LIKE pa0001-ename,

c_role_desc LIKE zhrrole-zrole_desc,

band LIKE zhrband-zband_desc,

perband LIKE pa0008-trfgr,

category LIKE pa0001-ename,

country LIKE t591s-stext,

currency LIKE pa0008-waers,

pu LIKE pa0001-btrtl,

du LIKE pa9009-du_cd,

location LIKE t500p-name1,

region LIKE t005h-bezei,

doj LIKE sy-datum,

start_period LIKE sy-datum,

end_period LIKE sy-datum,

basic LIKE pa0008-bet01,

hra LIKE pa0008-bet01,

insurance LIKE pa0008-bet01,

oda LIKE pa0008-bet01,

car_all LIKE pa0008-bet01,

gross_1 LIKE pa0008-bet01,

bonus LIKE pa0008-bet01,

cpi LIKE pa0008-bet01,

gross_2 LIKE pa0008-bet01,

provision LIKE pa0008-bet01,

tax LIKE pa0008-bet01,

total LIKE pa0008-bet01,

gross LIKE pa0008-bet01,

END OF it_overseas.



DATA : BEGIN OF it_empoverseas OCCURS 0,

empno LIKE pa0008-pernr,

name LIKE pa0001-ename,

category LIKE pa0001-ename,

country LIKE t591s-stext,

currency LIKE pa0008-waers,

gross LIKE pa0008-bet01,

END OF it_empoverseas.



*Declaration data for program

DATA : gc_startdate TYPE pa0008-begda,

gc_enddate TYPE pa0008-endda,

lc_dt TYPE sy-datum,

li_tdt TYPE i,

li_days TYPE i,

lf_mon_bonus TYPE pa0008-bet01,

gc_chkdate TYPE pa0000-begda,

lc_flag TYPE c.



DATA: BEGIN OF ppbwla OCCURS 10.

INCLUDE STRUCTURE pbwla.

DATA: END OF ppbwla.

***********************Selection screen *******************************

SELECTION-SCREEN BEGIN OF BLOCK blk1 WITH FRAME TITLE text-001.

PARAMETERS: p_pabrp LIKE qppnp-pabrp,

p_pabrj LIKE qppnp-pabrj.

PARAMETERS: p_prcnt LIKE pa0008-bet01 DEFAULT '8',

p_bprcnt LIKE pa0008-bet01 DEFAULT '50'.

SELECTION-SCREEN END OF BLOCK blk1.

***********************************************************************



***********************Initialization**********************************

INITIALIZATION.

lv_ls_layout-group_change_edit = 'X'.

lv_ls_layout-get_selinfos = 'X'.

driver = 'ZPYR_OVERSEASEMPLIST'.

p_pabrp = sy-datum+4(2).

p_pabrj = sy-datum+0(4).



***********************************************************************



**********************Start of selection******************************

START-OF-SELECTION.

PERFORM data_selection. "Data selection from tables

PERFORM alv_listdisplay. "alv grid display



END-OF-SELECTION.

&---------------------------------------------------------------------

*& Form INIT_FIELDCAT

&---------------------------------------------------------------------

  • Intialization of text for columns in the internal table

----------------------------------------------------------------------

FORM init_fieldcat.

LOOP AT lv_fieldcat INTO wa_lv_fieldcat.

CASE wa_lv_fieldcat-fieldname.

WHEN 'EMPNO'.

wa_lv_fieldcat-seltext_l = 'Emp Number'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'DOJ'.

wa_lv_fieldcat-seltext_l = 'Join Date'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'NAME'.

wa_lv_fieldcat-seltext_l = 'Name'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'BAND'.

wa_lv_fieldcat-seltext_l = 'Job Band'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'PERBAND'.

wa_lv_fieldcat-seltext_l = 'Personal Band'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'COUNTRY'.

wa_lv_fieldcat-seltext_l = 'Country'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'CURRENCY'.

wa_lv_fieldcat-seltext_l = 'Currency'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'BASIC'.

wa_lv_fieldcat-seltext_l = 'Basic'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'HRA'.

wa_lv_fieldcat-seltext_l = 'HRA'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'INSURANCE'.

wa_lv_fieldcat-seltext_l = 'Insurance'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'ODA'.

wa_lv_fieldcat-seltext_l = 'ODA'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'CAR_ALL'.

wa_lv_fieldcat-seltext_l = 'Car Allow.'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'GROSS_1'.

wa_lv_fieldcat-seltext_l = 'Total excl. Bonus & CPI'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'BONUS'.

wa_lv_fieldcat-seltext_l = 'Bonus'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'CPI'.

wa_lv_fieldcat-seltext_l = 'CPI'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'GROSS_2'.

wa_lv_fieldcat-seltext_l = 'Total incl. Bonus & CPI'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'PU'.

wa_lv_fieldcat-seltext_l = 'PU'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'DU'.

wa_lv_fieldcat-seltext_l = 'DU'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'LOCATION'.

wa_lv_fieldcat-seltext_l = 'Location'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'REGION'.

wa_lv_fieldcat-seltext_l = 'Region'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'PROVISION'.

wa_lv_fieldcat-seltext_l = 'Bonus @ 100 %'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'TAX'.

wa_lv_fieldcat-seltext_l = 'Tax'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'TOTAL'.

wa_lv_fieldcat-seltext_l = 'Total Bonus Cost @ 100%'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'START_PERIOD'.

wa_lv_fieldcat-seltext_l = 'Start Period'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'END_PERIOD'.

wa_lv_fieldcat-seltext_l = 'End Period'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'CATEGORY'.

wa_lv_fieldcat-seltext_l = 'Category'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.

WHEN 'GROSS'.

wa_lv_fieldcat-seltext_l = 'Expected Bonus Payout'.

wa_lv_fieldcat-ddictxt = 'L'.

wa_lv_fieldcat-ddic_outputlen = 13.

MODIFY lv_fieldcat FROM wa_lv_fieldcat.



ENDCASE.

ENDLOOP.

ENDFORM. " INIT_FIELDCAT



&---------------------------------------------------------------------

*& Form ALV_LISTDISPLAY

&---------------------------------------------------------------------

  • Use the function to display the alv list

----------------------------------------------------------------------

FORM alv_listdisplay.

CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'

EXPORTING

i_program_name = driver

i_internal_tabname = 'IT_OVERSEAS'

i_client_never_display = 'X'

i_inclname = driver

CHANGING

ct_fieldcat = lv_fieldcat[]

EXCEPTIONS

inconsistent_interface = 1

program_error = 2

OTHERS = 3.

IF sy-subrc 0.

ENDIF.



*Add correct column names..

PERFORM init_fieldcat.



*Display the list.

CALL FUNCTION 'REUSE_ALV_LIST_DISPLAY'

EXPORTING

i_callback_program = driver

it_fieldcat = lv_fieldcat[]

i_default = 'X'

i_save = 'A'

is_variant = lv_tmplt

is_layout = lv_ls_layout

i_callback_user_command = 'USER_COMMAND'

TABLES

t_outtab = it_overseas

EXCEPTIONS

program_error = 1

OTHERS = 2.

IF sy-subrc 0.

ENDIF.



ENDFORM. " ALV_LISTDISPLAY



&---------------------------------------------------------------------

*& Form DATA_SELECTION

&---------------------------------------------------------------------

  • Select the data from various tables and logical database

----------------------------------------------------------------------

FORM data_selection.

CONCATENATE p_pabrj p_pabrp '01' INTO lc_dt.



*Get the last date of the month

CALL FUNCTION 'RP_LAST_DAY_OF_MONTHS'

EXPORTING

day_in = lc_dt

IMPORTING

last_day_of_month = gc_enddate

EXCEPTIONS

day_in_no_date = 1.

IF sy-subrc 0.

WRITE : / 'Error in date entry'.

ENDIF.



CONCATENATE p_pabrj p_pabrp '01' INTO gc_startdate. "startdate



SELECT * FROM pa0008

WHERE (

( begda BETWEEN gc_startdate and gc_enddate )

OR ( endda BETWEEN gc_startdate AND gc_enddate )

OR ( begda >= gc_startdate AND endda >= gc_enddate )

OR ( begda <= gc_startdate AND endda = '99991231' ) ) AND subty NE '0' AND subty NE '11'. it_overseas-empno = pa0008-pernr. IF sy-subrc = 0. *Check whether employee has left.



CALL FUNCTION 'HR_LEAVING_DATE'

EXPORTING

persnr = pa0008-pernr

IMPORTING

leavingdate = gc_chkdate

TABLES

leaving_dates = it_leavedate

EXCEPTIONS

leaving_date_not_found = 1

pernr_not_assigned = 2

OTHERS = 3.

IF sy-subrc <> 0.

  • MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
  • WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.



ENDIF.



IF sy-subrc = 0.

IF gc_chkdate BETWEEN gc_startdate AND gc_enddate

OR gc_chkdate >= gc_startdate.

ELSE.

CONTINUE.

ENDIF.

ENDIF.



*Check whether the start date is less than the enddate of the month

*If it is less than the enddate of the month then only take that record.

IF pa0008-begda <= gc_enddate.

  • Getting the name of the employees

CALL FUNCTION 'CATS_GET_EMPLOYEE_NAME'

EXPORTING

pernr = it_overseas-empno

IMPORTING

name = it_overseas-name

EXCEPTIONS

pernr_not_found = 1.



IF sy-subrc <> 0.

ENDIF.

*Get the joining date of the employees

CALL FUNCTION 'RP_GET_HIRE_DATE'

EXPORTING

persnr = it_overseas-empno

check_infotypes = '0000'

IMPORTING

hiredate = it_overseas-doj.



*Get the role information for the employee

rp-read-infotype pa0008-pernr 9001 p9001 gc_startdate gc_enddate.

PROVIDE * FROM p9001 BETWEEN gc_startdate AND gc_enddate.

*Get the role description for that particular period.

SELECT SINGLE zrole_desc INTO (it_overseas-c_role_desc)

FROM zhrrole WHERE zrole_cd = p9001-zrole_cd.

*Get the job Band for that employee

SELECT SINGLE * FROM zhrrole_assg WHERE zrole_cd = p9001-zrole_cd.

SELECT SINGLE zband_desc INTO it_overseas-band

FROM zhrband

WHERE zband_cd = zhrrole_assg-zband_cd.

ENDPROVIDE.

*Get Personal Sub Band

it_overseas-perband = pa0008-trfgr.



*Get pay data

CALL FUNCTION 'RP_FILL_WAGE_TYPE_TABLE'

EXPORTING

appli = 'E'

begda = pa0008-begda

endda = pa0008-endda

infty = '0008'

pernr = pa0008-pernr

subty = pa0008-subty

TABLES

ppbwla = ppbwla "output

EXCEPTIONS

error_at_indirect_evaluation = 1.



IF sy-subrc 0.

REFRESH ppbwla.

CLEAR ppbwla.

ELSE.

LOOP AT ppbwla.

it_overseas-currency = ppbwla-waers.

IF ppbwla-lgart = '8101'

OR ppbwla-lgart = '6001' OR ppbwla-lgart = '6002'

OR ppbwla-lgart = '6003' OR ppbwla-lgart = '6004'

OR ppbwla-lgart = '7151' OR ppbwla-lgart = '6005'

OR ppbwla-lgart = '6006' OR ppbwla-lgart = '6007'

OR ppbwla-lgart = '6008' OR ppbwla-lgart = '6009'

OR ppbwla-lgart = '6010' OR ppbwla-lgart = '6011'

OR ppbwla-lgart = '6012' OR ppbwla-lgart = '6013'

OR ppbwla-lgart = '6014' OR ppbwla-lgart = '6015'.

it_overseas-basic = ppbwla-betrg.

ELSEIF ppbwla-lgart = '8301'.

it_overseas-hra = ppbwla-betrg.

ELSEIF ppbwla-lgart = '7801'.

it_overseas-insurance = ppbwla-betrg.

ELSEIF ppbwla-lgart = '8302' OR ppbwla-lgart = '7802'

OR ppbwla-lgart = '6301' OR ppbwla-lgart = '6303'

OR ppbwla-lgart = '6302' OR ppbwla-lgart = '6304'

OR ppbwla-lgart = '6305' OR ppbwla-lgart = '6306'

OR ppbwla-lgart = '6307' OR ppbwla-lgart = '6308'

OR ppbwla-lgart = '6309' OR ppbwla-lgart = '6310'

OR ppbwla-lgart = '6311' OR ppbwla-lgart = '6312'

OR ppbwla-lgart = '6313' OR ppbwla-lgart = '6314'.

it_overseas-oda = ppbwla-betrg.

ELSEIF ppbwla-lgart = '6409'

OR ppbwla-lgart = '6410' OR ppbwla-lgart = '6411'

OR ppbwla-lgart = '6412' OR ppbwla-lgart = '6413'

OR ppbwla-lgart = '6414' OR ppbwla-lgart = '8303'

OR ppbwla-lgart = '6401' OR ppbwla-lgart = '6402'

OR ppbwla-lgart = '6403' OR ppbwla-lgart = '6404'

OR ppbwla-lgart = '6405' OR ppbwla-lgart = '6406'

OR ppbwla-lgart = '6407' OR ppbwla-lgart = '6408'

OR ppbwla-lgart = '7803' OR ppbwla-lgart = '6415'.

it_overseas-car_all = ppbwla-betrg.

ELSEIF ppbwla-lgart = '8945'

OR ppbwla-lgart = '6101' OR ppbwla-lgart = '6102'

OR ppbwla-lgart = '6103' OR ppbwla-lgart = '6104'

OR ppbwla-lgart = '7945' OR ppbwla-lgart = '6105'

OR ppbwla-lgart = '6106' OR ppbwla-lgart = '6107'

OR ppbwla-lgart = '6108' OR ppbwla-lgart = '6109'

OR ppbwla-lgart = '6110' OR ppbwla-lgart = '6111'

OR ppbwla-lgart = '6112' OR ppbwla-lgart = '6113'

OR ppbwla-lgart = '6114' OR ppbwla-lgart = '6115'.

it_overseas-bonus = ppbwla-betrg.

ELSEIF ppbwla-lgart = '8975'

OR ppbwla-lgart = '6201' OR ppbwla-lgart = '6202'

OR ppbwla-lgart = '6203' OR ppbwla-lgart = '6204'

OR ppbwla-lgart = '7975' OR ppbwla-lgart = '6205'

OR ppbwla-lgart = '6206' OR ppbwla-lgart = '6207'

OR ppbwla-lgart = '6208' OR ppbwla-lgart = '6209'

OR ppbwla-lgart = '6210' OR ppbwla-lgart = '6211'

OR ppbwla-lgart = '6212' OR ppbwla-lgart = '6213'

OR ppbwla-lgart = '6214' OR ppbwla-lgart = '6215'.

it_overseas-cpi = ppbwla-betrg.

ENDIF.

ENDLOOP.

REFRESH ppbwla.

ENDIF.



*Add which country according to the subtype of the record

SELECT SINGLE stext INTO it_overseas-country

FROM t591s WHERE subty = pa0008-subty

AND infty = '0008'

AND sprsl = sy-langu.

*Addition to gross components

it_overseas-gross_1 = it_overseas-basic + it_overseas-hra

+ it_overseas-insurance + it_overseas-oda

+ it_overseas-car_all.



it_overseas-gross_2 = it_overseas-bonus + it_overseas-cpi

+ it_overseas-gross_1.



*Get PU DU Location and Region for the employee

rp-read-infotype pa0008-pernr 0001 p0001 gc_startdate gc_enddate.

PROVIDE * FROM p0001 BETWEEN gc_startdate AND gc_enddate.

SELECT SINGLE * FROM t001p WHERE btrtl = p0001-btrtl.

SELECT SINGLE * FROM t503t WHERE persk = p0001-persk.

SELECT SINGLE * FROM t500p WHERE persa = p0001-werks.

SELECT SINGLE * FROM t005h WHERE land1 = t500p-land1 AND

regio = t500p-regio AND cityc = t500p-cityc.



it_overseas-pu = t001p-btext.

it_overseas-location = t500p-name1. "dev903953

it_overseas-region = t005h-bezei.

ENDPROVIDE.



*Get the DU Details from infotype 9009

rp-read-infotype pa0008-pernr 9009 p9009 gc_startdate gc_enddate.

PROVIDE * FROM p9009 BETWEEN gc_startdate AND gc_enddate.

it_overseas-du = p9009-du_cd.

ENDPROVIDE.*Decide the category

PERFORM get_category.



*Calculate the Provision

*Start and enddate of the period

IF pa0008-begda <= gc_startdate. it_overseas-start_period = gc_startdate. ELSE. it_overseas-start_period = pa0008-begda. ENDIF. IF gc_enddate <= pa0008-endda. it_overseas-end_period = gc_enddate. ELSE. it_overseas-end_period = pa0008-endda. ENDIF. *The monthly bonus is bonus / 12 lf_mon_bonus = it_overseas-bonus / 12. *Working days onsite. Add 1 to days to consider todays day.

  • If employee has resigned.

li_tdt = it_overseas-end_period - it_overseas-start_period + 1.

li_days = gc_enddate - gc_startdate + 1.

it_overseas-provision = ( lf_mon_bonus * li_tdt ) / li_days.



*Tax Calculation.

it_overseas-tax = it_overseas-provision * p_prcnt / 100.



*Total Provision

it_overseas-total = it_overseas-provision + it_overseas-tax.



*Gross Provision

it_overseas-gross = it_overseas-total * p_bprcnt / 100.



APPEND it_overseas.

CLEAR it_overseas.

CLEAR gc_chkdate.

CLEAR : zhrrole, zhrband, zhrrole_assg,t001p,t503t,t500p.

CLEAR : p0001,p9001,p9009.

ENDIF.

ENDIF.

ENDSELECT.

ENDFORM. " DATA_SELECTION

---------------------------------------------------------------------

  • FORM USER_COMMAND SK *

---------------------------------------------------------------------

  • USER COMMAND FOR DYNAMIC REPORTING -SHEKHAR KULKARNI *

---------------------------------------------------------------------

  • --> UCOMM *
  • --> SELFIELD *

---------------------------------------------------------------------

FORM user_command USING ucomm LIKE sy-ucomm

selfield TYPE slis_selfield.

READ TABLE it_overseas INDEX selfield-tabindex.

CHECK sy-subrc = 0.

CASE ucomm.

WHEN '&IC1'.

CASE selfield-sel_tab_field.

*If clicked on BAND.

WHEN 'IT_OVERSEAS-EMPNO' OR 'IT_OVERSEAS-NAME'.

PERFORM display_details USING it_overseas-empno.

*If clicked on Purchase order.

ENDCASE.

ENDCASE.

ENDFORM.



&---------------------------------------------------------------------

*& Form DISPLAY_DETAILS

&---------------------------------------------------------------------

  • Display the selected employee details.

----------------------------------------------------------------------

  • -->P_IT_OVERSEAS_EMPNO text

----------------------------------------------------------------------

FORM display_details USING p_it_overseas_empno.

  • READ TABLE IT_OVERSEAS WITH KEY EMPNO = P_IT_OVERSEAS_EMPNO
  • BINARY SEARCH.



*transporting empno total.



IF sy-subrc = 0.

LOOP AT it_overseas.

it_empoverseas-empno = it_overseas-empno.

it_empoverseas-country = it_overseas-country.

it_empoverseas-currency = it_overseas-currency.

it_empoverseas-category = it_overseas-category.

it_empoverseas-name = it_overseas-name.

it_empoverseas-gross = it_overseas-gross.

APPEND it_empoverseas.

ENDLOOP.

SORT it_empoverseas BY category currency empno.

REFRESH lv_fieldcat[].

CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'

EXPORTING

i_program_name = driver

i_internal_tabname = 'IT_EMPOVERSEAS'

i_client_never_display = 'X'

i_inclname = driver

CHANGING

ct_fieldcat = lv_fieldcat[]

EXCEPTIONS

inconsistent_interface = 1

program_error = 2

OTHERS = 3.

IF sy-subrc <> 0.

ENDIF.



PERFORM init_fieldcat.



CALL FUNCTION 'REUSE_ALV_LIST_DISPLAY'

EXPORTING

i_callback_program = driver

it_fieldcat = lv_fieldcat[]

i_default = 'X'

i_save = 'A'

is_variant = lv_tmplt

is_layout = lv_ls_layout

TABLES

t_outtab = it_empoverseas

EXCEPTIONS

program_error = 1

OTHERS = 2.

IF sy-subrc <> 0.

ENDIF.

ENDIF.

REFRESH it_empoverseas.

ENDFORM. " DISPLAY_DETAILS



&---------------------------------------------------------------------

*& Form GET_CATEGORY

&---------------------------------------------------------------------

  • Find out the category of the person.

----------------------------------------------------------------------

FORM get_category.

CASE p0001-btrtl.

WHEN '30' OR '31' OR '35' OR '36' OR '39' OR '45' OR '47' OR '48'

OR '49' OR '65' OR '71' OR '74'.

it_overseas-category = 'Sales'.

WHEN '63'.

it_overseas-category = 'IBCS'.

WHEN '54' OR '18' OR '19' OR '20'.

it_overseas-category = 'Banking Bonus'.

WHEN OTHERS.

it_overseas-category = 'Others'.

ENDCASE.



IF ( p9001-zrole_cd = 'BM'

OR p9001-zrole_cd = 'GEM'

OR p9001-zrole_cd = 'KEYACMGR'

OR p9001-zrole_cd = 'AM'

OR p9001-zrole_cd = 'BSM'

OR p9001-zrole_cd = 'ENGMGR' ).

it_overseas-category = 'AM/BM/EM'.

ENDIF.



IF ( p9001-zrole_cd = 'PRINCIPAL'

OR p9001-zrole_cd = 'SRPRIN' ).

it_overseas-category = 'IBCS'.

ENDIF.



ENDFORM. " GET_CATEGORY

Q2] when i am using these macro in the the program i am getting the same result and the internal table has more that one record which i have checked for as u have told, if possible can u just provide me the sample code using the macro statements, it will be very much helful.

ANS>

Here's an example:

rp_provide_from_last p0032 space from-date to-date will return the last record of infty 32 valid between from-date and to-date, rp_provide_from_frst the first.

You might want to check whether reading was successful, to do so use pnp-sw-found (pnp-sw-found = '1' means reading was successful.)

Please note, that the macros will only provide data, that has been selected by the logical database pnp before, so if you make restrictions regarding validity date on the selection-screen of pnp, these apply for the infotypes and the rp_provide macros won't be able to read data valid before or after.

The syntax is



rp_provide_from_last p .

[/code]



The result will be at the header line of p.



e.g.



rp_provide_from_last p0001 space '18000101' '99991231' .

rp_provide_from_first p0185 '03' '18000101' '99991231' .



Check out date inputs (last two parameters) you pass to the macro.

Perl, RFC, ABAP and Macros

Summary

Perl, RFC, ABAP and Macros - what do they have to do with it all?

Macros - Just call me old fashioned ... But I love 'em!

By Piers Harding

09 Jun 2004

Macros

In my earlier SAP years, I used to go from project to project, and was forever finding that I wanted to do the same things that I did last time - programming wise. I quickly grew tired of this repetitiveness - so something just had to be done about it. It became a bit of a game - how could I alter the way I had to program, and record all those little juicy code snipets, for anything from updating the screen status bar, to speeding up DATA declarations? My answer was to have a personal program INCLUDE, and to accumulate the knowledge and experience in code fragments housed in MACROS. Before I knew it, an interesting side effect occurred - I had started creating my own version of ABAP - for example: I didn't like the "REFRESH" command , so I reinvented it as "zap".

define zap.
  free &1. clear &1.
end-of-definition.
    
data: xtab like tab512 occurs 0 with header line.
    
    
zap xtab.

See - that was four less key strokes! And, it just sounds like what I want to do to an internal table. So, I would merrily accumulate these macros (I have approx 100), as I went from project to project. Each place I went to got the benefit of the macros that I had built up from the last place, and I took with me the new ones as they evolved. This was always an agreement that I made with the management, and they were usually quite happy when I explained that it would mean that I would code faster/be more productive as a result. (I'm sure we could get into "Holy Wars" over what this means in terms of IP, and also the issue of ABAP just not looking universal anymore, but I'll leave that discussion as an exercise for the reader :-). )

Perl

Now, as a Perl programmer the three tenets of Perl - "laziness, impatience and hubris" - are dear to my heart, and Macros play right into this.

Macros don't just save you time, by reducing the typing you have to do for repetitive tasks, they also allow you to define new actions and grammar in a programming language, like this:

define uc.
  translate &1 to upper case.
end-of-definition.
    
data: x type string value 'the quick brown fox'.
    
* convert to upper case
uc x.

or:

define cat.
  concatenate &1 &2 into &1.
end-of-definition.
    
data: x type string value 'the quick brown fox ',
      y type string value 'jumped over the lazy do'.
    
* concatenate two strings together
cat x y.

These time-saving devices have also allowed me to bring ABAP just that little bit closer to other more "natural" languages that I like programming with, while also gaining (a little) satisfaction by further obliterating it's COBOLesque roots.

RFC Requests and Macros

But - that is not the main thrust of this spiel - what I really wanted to show was how you can further push the boundaries of ABAP, by using RFC, and the "smoke and mirrors" quality of Macros, to bind other programming languages to your applications.

The example detailed below is a functioning Application Server that is RFC enabled. It just so happens that the Server is written in Perl, but there is no reason why it couldn't be Python, or Ruby, or any number of other programming languages - it was just easier (for me) to do it in Perl.

The Server provides the functionality of executing the various snippets of Perl code passed to it, but it is the Macros that hide away all the unpleasant verbosity of translating those RFC requests, into what looks like a new set of commands in the ABAP language. For instance, you can execute an arbitrary snippet of code:

perl_string = 'print "Hello + return!\n"; "the return bit";'.
  pexec_return perl_string result_string.
  write: /01 result_string.

and result_string will have "the return bit" in it, as it is the last evaluation in the Perl code block. "Well - what is the use of that?" I hear you say. Well - take a look at another example of what we can do:

method_name = 'MIME::Base64::encode_base64'.
  pstring_table = 'my piece of text'.
  append pstring_table.
  pstatic_method method_name pstring_table result_table.
  loop at result_table.
    write: /01 'base64 encoded string: ', result_table.
  endloop.

This piece of code allowed a static method name (encode_base64) from a Perl package (Mime::Base64) to be called, passing it an arbitrary list of parameters, and receiving an arbitrary list of results - in this case, specifically calling a function that base64 encoded a string. I now have a means of base64 encoding ABAP strings in any of my programs (if I really wanted that - your mileage may vary).

But even that is not the extent of the point that I'm trying to make here - CPAN has literally thousands of packages and libraries that could be useful in your code, and now they are all available! Also, because of other Macros available in this Perl Server, you can execute code blocks in various ways, perform Perl style regular expressions, instantiate Perl objects, call instance methods, and delete objects.

Note: to obtain the full details of what commands/macros are available and how they operate, please refer to the macro INCLUDE file (it is documented), and the test Report referenced in the What you need section.

Additionally, this is functionally no different from how the outbound communication with the SAP NetWeaver JAVA application server works, as it relies on the Registered RFC interface for communication with the JVM.

However - where Perl (and certain other languages) differs (and I think excels) is that Perl has a very universal set of data types (scalars, and arrays) and uses the concept of coercing values into the appropriate form for a given context (e.g. changing a string to an int if doing a numeric comparison, etc.), making it very easy to represent it inside another language - in this case, ABAP.

Making It Happen

The whole set of examples are available for you to try. There are two main components to this. First, you need to set up and run the Perl server, and second, you need to create the program INCLUDE containing the macros, and the test Executable ABAP program. You can download the code for steps 1, 3, and 4.

What You Need

  1. Perl Server (Registered RFC) -> code. Save this to a file called perl.pl.

  2. Ensure that you have the Perl module SAP::Rfc installed - you can get this from CPAN at search.cpan.org.

  3. ABAP Macros INCLUDE -> macro include. Upload this to an ABAP program include ZIBPERLMACROS.

  4. ABAP Test Report -> report code. Upload this to an Executable ABAP program called ZTEST_PERL.

  5. Create a registered RFC DESTINATION in transaction SM59 called 'PERL' with a TPNAME of 'perl' - these can be changed by reading the notes in the macro file, and using the switches associated with the program perl.pl.

  6. Run the Perl Server - you can discover the program options by running: perl perl.pl -h. You will most likely need to run it something like this: perl -MURI -MMIME::Base64 perl.pl -d -g -s -n

    Note: the "-MURI -MMIME::Base64" switches are only necessary for the running of the ABAP Test Report - they load the appropriate Perl packages that the tests rely on (URI and MIME::Base64). You would use similar options to load other libraries that you wanted to access from ABAP.

  7. Now execute the test Report program ZTEST_PERL.

The environment I used for developing this was:

  • RedHat 9

  • Perl 5.8.0

  • SAP::Rfc 1.31

  • SAP: NetWeaver 4 evaluation system, should work with R/3 4.x+

Output

If you are running the test suite, then you can expect output like this from the Perl Server:

Mon Jun  7 09:06:10 2004: Debugging is switched on...
Mon Jun  7 09:06:10 2004: VERSION: 1.31
Mon Jun  7 09:06:10 2004: START
Mon Jun  7 09:06:14 2004: Running do_exec_perl...
Mon Jun  7 09:06:14 2004: call type is: E
Mon Jun  7 09:06:14 2004: Command is: #print "Hello!\n";#
Hello!
Mon Jun  7 09:06:14 2004: Finished iteration - returning...
    
    
Mon Jun  7 09:06:14 2004: Running do_exec_perl...
Mon Jun  7 09:06:14 2004: call type is: ER
Mon Jun  7 09:06:14 2004: Command is: #print "Hello + return!\n"; "the return bit";#
Hello + return!
Mon Jun  7 09:06:14 2004: Exec result is: the return bit
Mon Jun  7 09:06:14 2004: Finished iteration - returning...
....

The test Report output should look something like this:

What Now?

A lot of the focus with SAP seems to be (to me) on how to make SAP more "open", and accessible to the rest of the (Computing) world, but why shouldn't we look for ways in which SAP (or more specifically - R/3) can be extended by bringing in applications from the outside.

In this example, I have hopefully shown how this can be achieved, as I have opened SAP up to the potential of the extensive code base of the Perl community. However - it is not just Perl that has something to offer. There are many other communities built up around programming languages that also have large application resources available - so why not these too?

Appendix

The code samples referred to above: perl.pl, zibperlmacros and ztest_perl can be downloaded from: