One of HR Expert's readers thinks that it would be useful to have a report showing an employee's current and past positions, including salary and effective dates. Our HR expert agrees that there is a widespread need for such a report. In three steps, he explains how to create a concise, custom ABAP report that provides this information.
Key Concept
Dear HR Expert,
Is there a standard report in SAP that shows an employee’s current and past positions along with their salary and effective dates? Managers at our company use position and salary history to process pay increases, performance awards, and annual salary reviews for each of their direct reports. The ideal solution would be a single-page report with basic employee data at the top and a table in reverse chronological order showing job title, pay grade, change reason, FT/PT indicator, base pay, annualized pay, and effective date. If a standard report is not available, can SAP Query be used to produce this report?
Thanks,
Gerry Smith, Assistant VP - Human Resources
Dear HR Expert
,
Is there a standard report in SAP that shows an employee’s current and past positions along with their salary and effective dates? Managers at our company use position and salary history to process pay increases, performance awards, and annual salary reviews for each of their direct reports. The ideal solution would be a single-page report with basic employee data at the top and a table in reverse chronological order showing job title, pay grade, change reason, FT/PT indicator, base pay, annualized pay, and effective date. If a standard report is not available, can SAP Query be used to produce this report?
Thanks,
Gerry Smith, Assistant VP - Human Resources
Thanks for the question. While your specific requirement may be unique, it is not at all uncommon for R/3 users to desire information in a format that is not available in the standard system. The SAP Query or ABAP Query tools could be used to capture the basic information required for your report, but the resulting format would not be very pleasing to the eye. Most companies satisfy this type of requirement with a custom ABAP report program.
Some risks are involved when you develop a custom ABAP program, and it increases your total cost of ownership. Initially, you have the cost of developing and testing the program. In the future, there will be incremental costs each time you install a service package stack or an upgrade. Add to this the fear that the custom program could cause production downtime and you might be inclined to insist that your users make do with standard reports.
I’d like to take this opportunity to share a three-step strategy I use for building custom ABAP reports that can help you quickly build programs that are robust and reliable. (See the sidebar, “Programming Accelerators,” on page 10, for tips on how to speed up your development time.) The ideas contained in this article will reduce the cost/benefit ratio of custom ABAP programs, enabling you to provide your users with a superior system for the lowest possible cost.
Note
Before you begin programming, you should gather clear requirements. Your company most likely has a standard process for creating program specifications and you will still want standard information such as selection criteria, sort criteria, and output layout. (See the sidebar, “Tips for Gathering Requirements.”)
Organize Your Program into 3 Major Steps
With a good requirements document in hand, you are ready to write the program. A number of years ago I developed this three-step process as a solution for a particularly complex interface. Since then I have found that following these steps makes almost any HR ABAP program easy to write, easy to maintain, and efficient when it runs. I’ll show how to create the report requested in this “Ask the Expert” question.
Step 1. Build an Internal Table Containing the Employees to Be Processed
The purpose of this step is to limit the amount of database access and to keep the selection logic separate from the processing logic. You want to design this section to narrow the collection of all employees to the desired ones as quickly as possible. In this example, you want a list of active employees who report to a particular organizational unit on a certain day. Following the rule of quick elimination, you first locate all employees who report to the specified organizational unit. If the program started by locating all active employees, it would access infotype 0000 for every employee in the database. Using the organizational unit first allows the program to begin with a much smaller group of data.
Step 2. Gather Additional Information Required for Each Selected Employee
Now that you know who is included on the output, the process of collecting the remaining information is easy. Simply loop through the table of selected people and read the infotypes or tables that contain the required data items. In this step, you build a new internal table that contains all of the information needed for the output.
The salary history report requires two sub-steps, because the output includes evaluation of the same employee on multiple days. The first sub-step searches basic pay (IT0008) and organizational assignment (IT0001) to locate the days on which this employee experienced a change of either salary or job. The output of this sub-step is a table that lists the key event dates for each employee. This sub-step highlights the advantage of keeping the employee selection process separate from the data collection process. In the employee selection step, you identified the active employees who report to a particular organizational unit on the selection date. In this step, you gather job and salary information going backward in time. Some of the employees will have reported to other organizational units in the past. Trying to identify the employees and selecting their historical data at the same time would be unnecessarily confusing.
The second sub-step loops through the table of key dates and gathers the pieces of information required on the report. This is often the most complicated step in a program. You need to navigate from table to table following foreign keys to obtain the correct related information. The resulting internal table shows how the employee’s job title, pay grade, salary, and part-time status have changed over time.
Step 3. Sort the Data and Generate Output
This step organizes and outputs the collected information. If the output is an interface file, this step is where you create the exact output format, including headers and trailers if required. If the output is a report, you sort the internal table and loop through it to create the output. This design strategy puts all of the required output data in a single internal table and is more reliable than a strategy that involves creating output from multiple database tables. This program is much less likely to suffer ill effects if other programmers change it in the future.
Creating the Salary History Report
Now let’s use these ideas to create the salary history report. The requirements document is complete and you can begin programming with step 1. The program selection screen allows the user to specify an organizational unit and a date. The report should include all active employees reporting to the specified organizational unit on the specified date. The logic shown in Figure 1 builds a table called People that contains the personnel number of each employee who should be included in the report.

Figure 1
Employee selection logic
Next, you find the key dates for each employee. The salary history report should include a line for each date on which the employee experienced a change of job or salary. You can find these key dates by reading infotypes 0001 (personnel assignment) and 0008 (basic pay) from oldest to newest. Find the key dates by comparing adjacent records. The logic shown in Figure 2 builds a table called Keydates that contains these dates for each employee. Using the collect statement prevents duplicate entries should an employee have a change of job and a change of salary on the same date.

Figure 2
Gathering additional information
Now you gather the other required information. The Keydates table tells you for which employees and on which dates to gather the information. A new table called Salaryhistory is created in this step. The Salaryhistory table contains the same rows as the Keydates table with the additional fields required on the output. Since the complexity of locating the effective dates has already been dealt with, this step is a simple group of table reads.
With all of the required information available in the Salaryhistory table, you can easily produce the report. The table is sorted and then looped through. The ABAP language contains many statements that simplify report creation, provided the data is contained in a single internal table prior to display. The skeleton code in Figure 3 shows how you can use the AT NEW
and AT END OF
statements for the salary history report.

Figure 3
Generating the output
This program will work reliably for many years. It will survive through service packages, upgrades, and changes in your configuration. Should the managers decide they prefer different information on the report, it is easy to modify the program. You only need to add new fields to the Salaryhistory table and add a select statement in the gathering information section. The change has little risk of damaging the employee selection logic or of affecting the output format. Likewise, you can make changes to the output format or the employee selection pieces with only a small chance of undesired side effects.
Programming Accelerators
The ABAP development environment includes a number of methods to speed your development time and improve your program accuracy, including the following:
The Pattern Generator
A pattern generator in the ABAP editor inserts almost any ABAP statement into your program. This tool ensures that statements have the correct syntax. It also helps with the programming logic by displaying all possible parameters for each statement. This is helpful when calling functions and accessing database tables.
I’ll illustrate this tool with an example from the Salaryhistory report. When you are gathering data for the report, you need to get the name of the employee’s job. You know the job is stored on infotype 0001. From the ABAP editor, choose Edit>Pattern from the menu. The screen shown in Figure 1 appears. Click the radio button adjacent to SELECT * FROM and enter the name of the table. If you don’t know the name of the table, use the drop-down list to find it.
The pattern generator displays a screen that lists all of the fields available on the specified table. (See Figure 2.) Indicate with a check mark the fields that your program needs to specify when reading this table. The statement shown in Figure 3 is then inserted into the program. You can easily modify the inserted statement to reference your local variables.
Even skilled programmers can benefit from using the pattern generator. The field list has both technical and English field names. This helps ensure that similar fields are not transposed. The field list also shows which fields are key fields for the table. This helps minimize another common programming error — failure to specify all key fields when attempting to access unique records on a table.
When you use the pattern generator to insert a function call, the resulting skeleton statement includes all parameters of the function interface. Optional parameters will be listed as comment lines.
Integrated Data Dictionary
The ABAP development environment also includes an integrated data dictionary. This means that the program editor is aware of the data definition of all fields and tables used in the program. You can navigate to the definition of any data item by double-clicking on it. I make extensive use of this feature to verify the correct format for fields and to locate related fields.
One task required in the salary history report is to obtain the description of the personnel action found on infotype 0000. Here is how to use the data dictionary to quickly find the location of this information. While editing your program, double-click on the name of table PA0000. The screen shown in Figure 4 is displayed. Double-click on the name of the data element that describes the personnel action field to display its definition, as shown in Figure 5. A list of tables that use this data element is displayed when you click on the where-used button. A quick look at the list shown in Figure 6 reveals that table T529T contains the Personnel Action Texts. Use the pattern generator when coding the selections from this table to ensure that you consider all key fields for the table.

Figure 4
Data definition of table PA0000

Figure 5
Data definition of data element MASSN

Figure 6
Tables that use data element MASSN
Tips for Gathering Requirements
I want to mention two points that are especially important to document when designing an HR ABAP program. The overall goal is to strive for a requirements document that is unambiguous.
- Use the technical names for fields as often as possible. Using the common name or the screen name can be imprecise. Most ABAP programmers are not familiar enough with daily operations to completely understand the jargon. One of the required items for the salary history report is the employee’s job. If you use transaction PA20 to display infotype 0001, you can click on the job field, press the F1 key, and then click on the toolbox button. The technical name for this field is P0001-STELL. For fields like Job that have both a code and a description, specify whether you desire the code (59000220) or the description (Carpenter I). For the salary history report, you want the description of the job.
- Keep in mind that SAP HR data is driven by the effective date. Any part of a requirements document that says “Read field X from table Y” must also include instructions regarding the effective date. In my example, you need to display the employee’s job title. Specifically, you want the title of the job the person held on each day there was a change of job or salary.
Clay Molinari
Clay Molinari has 20 years of experience in the IT industry and has been working as an SAP HR consultant since 1997. He is currently president of C&C Savant, Inc., an SAP consulting firm that specializes in combining standard SAP configuration and custom ABAP programming to help its clients solve unique or complicated requirements.
You may contact the author at claymolinari@comcast.ne.
If you have comments about this article or publication, or would like to submit an article idea, please contact the editor.