Skip to Content

UPDATE 21/07/2012: because of some requests the program is now improved: it uploads Excel instead of processing hardcoded data, it converts texts from the input to the length that i suitable for PO03 transaction and also writes proficiencies for qualifications evaluated in the input.

I was asked to build a program that would upload HR-PD Job object (“C”) definitions from. I would like to share the experience as well as the example coding. I am not going to pretend the example coding will save an experienced developer more than twenty minutes, but in my experience it`s always better to start with something than from scratch, right?

Last time I blogged about development for HR-PD Qualifications and the coding made the blog more useful than just talking I hope. If interested, check the blog here: All you need to know about HR-PD Qualifications from the development perspective.

As I understood my task, it had multiple parts. Unfortunately only one fraction can be generalized and reused. That is the upload part when you have data in a suitable format and call the function modules to put them to the database.

Let me elaborate on the application parts first (you don`t need to stick to it, it`s just that the experience at the end helped me understand how I had better started):

  • First one needs to read the data from the data source (whatever the source is, can be an Excel file, XML file, web service – depends on your task). In most cases this part will be easy with the help from CL_GUI_FRONTEND_SERVICES class.
  • Once we have the data in the system, it`s time to translate them into a suitable upload format. My task was to use very VERY strange XML file as a data source. Then this part becomes really challenging. I have good news too – this is the most difficult part of the task in my opinion. Lesson learnt: split the “data transformation” part from the “data upload” part carefully. If you start creating or linking objects as you go through the input file, your coding becomes spaghetti very quickly (hint: I learnt the hard wayJ).
  • Last step is to upload the data. We all have the “same” SAP system with same function modules so my example coding should cover a great deal of basic scenarios, I believe.

What`s not covered by the example coding but is typically needed

My coding does not create the qualifications. I assume you already have the qualifications in the system. But what if the task is to create job descriptions with qualifications that are specific to the jobs (well, the power of the qualifications is to have a qualification created once and assigned many… so you`d better do it only if there is a catalog of qualifications used by job descriptions, that you`re uploading, and you want to create the qualification before the first use, so you don`t create more than you need)? Then you might want to reuse some of the coding from the previous blog.

Technical hints:

  • When you create the qualifications together with the job descriptions, you may want to put the external qualification ID to the qualification “short” field. Then you don`t need a mapping table between the “old” IDs and the “new” ones.
  • When you create qualifications with the jobs, you typically group them (qualification groups) and for those groups you use one scale. But the interpretation of proficiency for one qualification often differs from the interpretation for other qualifications. You can define qualification specific proficiency interpretations (text descriptions). Check the qualifications blog for more info.

I wanted to use some custom text sub-types (of infotype 1002) to accommodate various text descriptions of my jobs. So I needed to create the sub-types first. That you can do/ define sub-type in table T778U and then define the time constraint in view V_T777ZIT.

While building your own program for the task, you will create plenty of text jobs I believe. Then you might wonder how to get rid of the test data.  Then you might find the SE38 program called RHRHDL00 handy (ok, I am a developer, so for normal mortals there is a transaction called RE_RHRHDL00).

Last but not least: you want to see your jobs. I assume you know how to display them, but if not, try transaction PO03. Hope that helps.

REPORT  zjobs.

 TYPES: BEGIN OF tt_input,
     job TYPE objid,
     type TYPE char4,
     param TYPE text40,
     value TYPE string,
   END OF tt_input.
 DATA lt_input TYPE TABLE OF tt_input.
 DATA ls_input LIKE LINE OF lt_input.
 DATA ls_main LIKE LINE OF lt_input.

 TYPE-POOLS: truxs.

 DATA lt_filetable TYPE filetable.
 DATA ls_file LIKE LINE OF lt_filetable.
 DATA lt_raw_data TYPE truxs_t_text_data.
 DATA lv_file TYPE rlgrap-filename.
 DATA lv_rc TYPE i.

 DEFINE upload_file.
   clear: lt_filetable[], lv_rc, lv_file.
   call method cl_gui_frontend_services=>file_open_dialog
     changing
       file_table              = lt_filetable
       rc                      = lv_rc
     exceptions
       file_open_dialog_failed = 1
       cntl_error              = 2
       error_no_gui            = 3
       not_supported_by_gui    = 4
       others                  = 5.
   if sy-subrc <> 0.
     message id sy-msgid type sy-msgty number sy-msgno
                with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
   endif.

   read table lt_filetable into ls_file index 1.
   if sy-subrc ne 0.
     message 'Cancelled by the user' type 'S'.
     exit.
   endif.
   lv_file = ls_file-filename.

   call function 'TEXT_CONVERT_XLS_TO_SAP'
     exporting
       i_tab_raw_data       = lt_raw_data
       i_filename           = lv_file
     tables
       i_tab_converted_data = &1
     exceptions
       conversion_failed    = 1
       others               = 2.
   if sy-subrc <> 0.
     message id sy-msgid type sy-msgty number sy-msgno
             with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
   endif.
 END-OF-DEFINITION.

 upload_file lt_input.

 CONSTANTS: c_limit TYPE i VALUE 69.

 DATA lv_hlp TYPE string.
 DATA lv_c TYPE i.
 DATA lv_split TYPE i.
 DATA lv_test TYPE c.
 DEFINE split_text.
   lv_hlp = &1.
   condense lv_hlp.
   while lv_hlp is not initial.
     lv_c = strlen( lv_hlp ).
 *** find the reasonable part shorter than 79 (until last space in 79 length)
     if lv_c > c_limit.
       clear lv_split.
       lv_c = c_limit.
 *** look for the last space
       lv_test = lv_hlp+lv_c(1).
       condense lv_test.
       while lv_c > 1 and lv_test is not initial.
         lv_c = lv_c - 1.
         lv_test = lv_hlp+lv_c(1).
         condense lv_test.
       endwhile.
       lv_split = lv_c.
       ls_txt-tline = lv_hlp(lv_split).      "put to the first instance of this line
       lv_hlp = lv_hlp+lv_split.
       condense lv_hlp.
       append ls_txt to lt_txt.
     else.
 *** take the rest
       ls_txt-tline = lv_hlp.
       append ls_txt to lt_txt.
       clear lv_hlp.
       exit. "the while
     endif.
   endwhile.
 END-OF-DEFINITION.


 ********************************************************
 ********************************************************
 ********************************************************
 *** get list of jobs to create
 DATA lt_jobs LIKE lt_input.
 lt_jobs[] = lt_input.
 DELETE lt_jobs WHERE type <> 'MAIN'.
 SORT lt_jobs BY job.
 DELETE ADJACENT DUPLICATES FROM lt_jobs COMPARING job.

 DATA lt_texts LIKE lt_input.
 DATA lt_txt TYPE TABLE OF pt1002.     "job subtype text lines
 DATA ls_txt LIKE LINE OF lt_txt.      "job subtype text one line

 FIELD-SYMBOLS <fs_jobs> LIKE LINE OF lt_jobs.
 FIELD-SYMBOLS <fs_line> LIKE LINE OF lt_input.
 FIELD-SYMBOLS <fs_text> LIKE LINE OF lt_texts.

 DATA lv_objid TYPE hrp1000-objid.     "job number
 DATA lv_stext TYPE hrp1000-stext.     "job text
 DATA lv_short TYPE hrp1000-short.     "job short text
 DATA lv_quali TYPE hrobjid.           "qualification ID
 DATA lv_subty TYPE p1002-subty.       "text subtype ID

 ********************************************************
 *** for all jobs to create
 LOOP AT lt_jobs ASSIGNING <fs_jobs>.
 *** 1) i need to create the job object first
 *** get the "header" information for this job
   READ TABLE lt_input INTO ls_main WITH KEY job = <fs_jobs>-job type = 'MAIN'.

   lv_stext = ls_main-value.
   lv_short = ls_main-param.

   CALL FUNCTION 'RH_OBJECT_CREATE'
     EXPORTING
       plvar               = '01'
       otype               = 'C'
       stext               = lv_stext
       short               = lv_short
       begda               = sy-datum
       endda               = '99991231'
     IMPORTING
       objid               = lv_objid
     EXCEPTIONS
       text_required       = 1
       invalid_otype       = 2
       invalid_date        = 3
       error_during_insert = 4
       error_ext_number    = 5
       undefined           = 6
       OTHERS              = 7.
   IF sy-subrc <> 0.
     MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
     CONTINUE.
   ELSE.
     WRITE: / 'Job ', lv_objid, ' created'.
   ENDIF.

 *** 2) i need to processs the texts
 *** 2.1) get a list of subtypes I need to process
   CLEAR lt_texts[].
   lt_texts[] = lt_input[].
   DELETE lt_texts WHERE job <> <fs_jobs>-job.
   DELETE lt_texts WHERE type <> 'TEXT'.
   SORT lt_texts BY param.
   DELETE ADJACENT DUPLICATES FROM lt_texts COMPARING param.
 *** 2.2) for every subtype, get all lines

   LOOP AT lt_texts ASSIGNING <fs_text>.
     CLEAR lt_txt[].
     LOOP AT lt_input ASSIGNING <fs_line>
       WHERE job = <fs_jobs>-job AND type = 'TEXT' AND param = <fs_text>-param.
 ***      ls_txt-tline = <fs_line>-value.
 ***      APPEND ls_txt TO lt_txt.
       split_text <fs_line>-value.
     ENDLOOP.
 *** 2.3) assign the description
     lv_subty = <fs_text>-param.
     CALL FUNCTION 'RH_OBJECT_DESCRIPTION_WRITE'
       EXPORTING
         langu                = sy-langu
         plvar                = '01'
         otype                = 'C'
         objid                = lv_objid
         begda                = sy-datum
         endda                = '99991231'
         subty                = lv_subty
       TABLES
         ptxt1002             = lt_txt
       EXCEPTIONS
         object_not_found     = 1
         description_required = 2
         no_authority         = 3
         error_during_insert  = 4
         invalid_date         = 5
         undefined            = 6
         OTHERS               = 7.
     IF sy-subrc <> 0.
       MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
     ENDIF.
   ENDLOOP.

 *** 3) i need to process the qualifications
   LOOP AT lt_input ASSIGNING <fs_line> WHERE job = <fs_jobs>-job AND type = 'QUAL'.
     lv_quali = <fs_line>-value. "qualification ID
     CALL FUNCTION 'RH_RELATION_MAINTAIN'
       EXPORTING
         act_fcode           = 'INSE'
         act_plvar           = '01'
         act_otype           = 'C'
         act_objid           = lv_objid "the job I created in step one
         act_rsign           = 'A'
         act_relat           = '031'
         act_sclas           = 'Q'
         act_sobid           = lv_quali
         act_begda           = sy-datum
         act_endda           = '99991231'
       EXCEPTIONS
         maintainance_failed = 1.
     IF sy-subrc <> 0.
       MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
     ENDIF.
   ENDLOOP.

 *** now maintain the qualification profile INCLUDING proficiencies for the Job
   DATA lt_profilec TYPE TABLE OF hrpe_relaq.
   DATA ls_profile LIKE LINE OF lt_profilec.
   CLEAR lt_profilec[].
   LOOP AT lt_input ASSIGNING <fs_line> WHERE job = <fs_jobs>-job AND type = 'QUAL'.
     CLEAR ls_profile.
     ls_profile-ttype = 'Q'.
     ls_profile-tbjid  = <fs_line>-value.
     ls_profile-profcy = <fs_line>-param.
     ls_profile-sbegd = sy-datum.
     ls_profile-sendd = '99991231'.
     ls_profile-vbegd = sy-datum.
     ls_profile-vendd = '99991231'.
     ls_profile-istat = 1.
     IF ls_profile-profcy IS INITIAL.
       ls_profile-not_rated = 'X'.
     ENDIF.
     APPEND ls_profile TO lt_profilec.
   ENDLOOP.

   DATA objid TYPE p1001-sobid.
   objid = lv_objid.
   CALL FUNCTION 'RHPP_R_PROFILE_WRITE'
     EXPORTING
       plvar                 = '01'
       otype                 = 'C'
       objid                 = objid
       vtask                 = 'B'
     TABLES
       profile               = lt_profilec
     EXCEPTIONS
       no_authority          = 1
       error_during_insert   = 2
       wrong_otype           = 3
       object_not_found      = 4
       object_required       = 5
       no_scale_defined      = 6
       scale_not_clear       = 7
       time_not_valid        = 8
       proficiency_not_valid = 9
       wrong_date_format     = 10
       undefined             = 11
       OTHERS                = 12.
   IF sy-subrc <> 0.
     MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
   ENDIF.

   CALL FUNCTION 'RH_UPDATE_DATABASE'
     EXPORTING
       vtask      = 'D'
       commit_flg = 'X'
     EXCEPTIONS
       corr_exit  = 1
       OTHERS     = 2.
   IF sy-subrc <> 0.
     MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
   ENDIF.

 ENDLOOP.
To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. Luke Marson

    Hi Otto,

    Thanks for another valuable blog for us SAP HCM folks. I’ll definitely be filing this one away for the future 🙂

    Keep up the good work.

    Best regards,

    Luke

    (0) 

Leave a Reply