sap-erpsap-basisbapi

BAPI_CONVERSION_EXT2INT1 to convert external WBS element number to internal


I want to use the BAPI BAPI_CONVERSION_EXT2INT1 to convert external to internal WBS element numbers, but don't know how to fill its parameters for this.

Yes, I know I can create Z-BAPIs of other internal BAPIs to achieve this but I need to know how to use BAPI_CONVERSION_EXT2INT1 specifically, so I don't need any Z-BAPIs anymore the next time a customer wants to use that part of our software.

If you just know about BAPI_CONVERSION_EXT2INT or BBP_CONVERSION_EXT2INT you are welcome, too (they seem to be identical anyway).

THIS WAS SOLVED NOW!

Also you are legally required to upvote @sandra-rossi's answer below before continuing to read.

With BAPI_CONVERSION_INT2EXT1:

BAPI_CONVERSION_INT2EXT1 bapi = new BAPI_CONVERSION_INT2EXT1(destination);
SAPTable<BAPICONVRS> tblDATA = bapi.getDATAs();
BAPICONVRS data = tblDATA.newItem();
data.setOBJTYPE("BUS2031001");
data.setMETHOD("GetDetailBos");
data.setPARAMETER("QuotationHeader");
data.setFIELD("WBS_ELEM");
data.setINT_FORMAT("102882");
bapi.execute();        

I get:

EXT_FORMAT=REP_S01588 0001

And vice versa, with BAPI_CONVERSION_EXT2INT1:

BAPI_CONVERSION_EXT2INT1 bapi = new BAPI_CONVERSION_EXT2INT1 (destination);
SAPTable<BAPICONVRS> tblDATA = bapi.getDATAs();
BAPICONVRS data = tblDATA.newItem();
data.setOBJTYPE("BUS2031001");
data.setMETHOD("GetDetailBos");
data.setPARAMETER("QuotationHeader");
data.setFIELD("WBS_ELEM");
data.setEXT_FORMAT("REP_S01588 0001");
bapi.execute();        

I get:

INT_FORMAT=102882

Solution

  • TL;DR Apologies for the length of the answer. If you want it short, there is an ABAP program which will give you the BAPI parameter values corresponding to various criteria (like VBAP-PS_PSP_NR), in the chapter "How to determine the parameters for BAPI_CONVERSION_INT2EXT1 and BAPI_CONVERSION_EXT2INT1 → 1) If you don't know the Business Object Type".

    Introduction

    BAPI is part of the Business Object Type concept (SWO1 transaction code).

    BAPI_CONVERSION_EXT2INT1 is closely integrated with the BO concept, and is originally meant to be called either before or after calling a "main" BAPI function module. There are many parameters, so you need to understand the BO concept I try to quickly explain hereafter.

    Let's suppose you are given the Internal value of a WBS Project and you want to get its WBS Elements. You also want to obtain both the External values (the value which is shown to the users on the screens) and Internal values (the value which is stored in the database).

    The main BAPI function module to get these details is BAPI_PROJECT_GETINFO which is intended to receive the External value of the Project ID (although the Internal value usually works too), and it returns the External values of its WBS Elements.

    The logic of the program will be:

    1. Convert the Internal value of the Project ID to its External value
    2. Call BAPI_PROJECT_GETINFO
    3. Convert the External values of the returned WBS Elements to their Internal values

    You may obtain the External and Internal values by calling BAPI_CONVERSION_INT2EXT1 (Internal to External) and BAPI_CONVERSION_EXT2INT1 (External to Internal), before or after calling the main BAPI function module, or even for scenarios without one.

    Their parameter values are easy to find if you know the BO type corresponding to the BAPI function used (e.g. BUS2054 for BAPI_PROJECT_GETINFO), but difficult otherwise (hence the question) and in that case the solution is explained in the next chapter.

    For information, the transaction code SE16N or S416N can be used to see the external and internal values:

    SE16N PRPS External and Internal values of PSPNR and POSID

    How to determine the parameters for BAPI_CONVERSION_INT2EXT1 and BAPI_CONVERSION_EXT2INT1

    1) If you don't know the Business Object Type

    Run the ABAP program below. Various input are possible, e.g. table VBAP and column PS_PSP_PNR, or table PRPS and column PSPNR, or data element PS_PSP_PNR, or domain PS_POSNR. All are equivalent and give the same result.

    REPORT.
    DATA:
      BEGIN OF dummy_for_select_options,
        objtype       TYPE swotdv-objtype,
        objtype_id    TYPE tojtb-editelem,
        objtype_stext TYPE tojtt-stext,
        objtype_ntext TYPE tojtt-ntext,
        method        TYPE swotdv-editelem,
        parameter     TYPE swotdq-editelem,
        field         TYPE dd03l-fieldname,
      END OF dummy_for_select_options.
    TABLES swotdv.
    
    PARAMETERS tabname TYPE dd53d-tabname.
    PARAMETERS fieldnam TYPE dd53d-fieldname.
    PARAMETERS rollname TYPE dd04l-rollname.
    PARAMETERS domname TYPE dd01l-domname.
    PARAMETERS convexit TYPE dd01l-convexit.
    PARAMETERS extvalue TYPE string LOWER CASE.
    PARAMETERS intvalue TYPE string LOWER CASE.
    PARAMETERS max_rows TYPE i DEFAULT 10.
    SELECT-OPTIONS s_objtyp FOR dummy_for_select_options-objtype.
    SELECT-OPTIONS s_objid  FOR dummy_for_select_options-objtype_id.
    SELECT-OPTIONS s_objstx FOR dummy_for_select_options-objtype_stext.
    SELECT-OPTIONS s_objntx FOR dummy_for_select_options-objtype_ntext.
    SELECT-OPTIONS s_method FOR dummy_for_select_options-method.
    SELECT-OPTIONS s_param FOR dummy_for_select_options-parameter.
    SELECT-OPTIONS s_field FOR dummy_for_select_options-field.
    
    
    DATA leng TYPE dd01l-leng.
    DATA outputlen TYPE dd01l-outputlen.
    DATA lowercase TYPE dd01l-lowercase.
    
    AT SELECTION-SCREEN.
    
      IF tabname IS NOT INITIAL
          AND fieldnam IS NOT INITIAL.
        SELECT SINGLE rollname, domname
            FROM dd03l
            WHERE tabname = @tabname
              AND fieldname = @fieldnam
            INTO (@rollname,@domname).
        IF sy-subrc <> 0.
          MESSAGE 'Table/field not found' TYPE 'E'.
        ELSEIF rollname IS INITIAL
            OR domname IS INITIAL.
          MESSAGE 'Table/field has no data element or no domain' TYPE 'E'.
        ENDIF.
      ENDIF.
    
      IF rollname IS NOT INITIAL.
        SELECT SINGLE domname
            FROM dd04l
            WHERE rollname = @rollname
            INTO @domname.
        IF sy-subrc <> 0.
          MESSAGE 'Data element not found' TYPE 'E'.
        ELSEIF domname IS INITIAL.
          MESSAGE 'Data element has no domain' TYPE 'E'.
        ENDIF.
      ENDIF.
    
      IF domname IS NOT INITIAL.
        SELECT SINGLE convexit, leng, outputlen, lowercase
            FROM dd01l
            WHERE domname = @domname
            INTO (@convexit,@leng,@outputlen,@lowercase).
        IF sy-subrc <> 0.
          MESSAGE 'Domain not found' TYPE 'E'.
        ENDIF.
      ENDIF.
    
      IF convexit IS NOT INITIAL.
        SELECT COUNT(*)
            FROM dd01l
            UP TO 1 ROWS
            WHERE convexit = @convexit.
        IF sy-subrc <> 0.
          MESSAGE 'Conversion exit not found' TYPE 'E'.
        ENDIF.
      ENDIF.
    
      IF extvalue IS NOT INITIAL.
        IF lowercase = abap_false.
          TRANSLATE extvalue TO UPPER CASE.
        ENDIF.
        IF strlen( extvalue ) > outputlen.
          MESSAGE |Value must be { outputlen } characters max| TYPE 'E'.
        ENDIF.
      ELSE.
        IF strlen( intvalue ) > leng.
          MESSAGE |Value must be { leng } characters max| TYPE 'E'.
        ENDIF.
        SELECT SINGLE dd04l~rollname
            FROM dd04l
            INNER JOIN dd01l
              ON dd04l~domname = dd01l~domname
            WHERE dd01l~convexit = @convexit
            INTO @DATA(dd04l_rollname).
        IF sy-subrc <> 0.
          MESSAGE 'Domain has no data element' TYPE 'E'.
        ENDIF.
        DATA dref TYPE REF TO data.
        CREATE DATA dref TYPE (dd04l_rollname).
        ASSIGN dref->* TO FIELD-SYMBOL(<intvalue>).
        TRY.
            <intvalue> = intvalue.
            DATA(back_intvalue) = CONV string( <intvalue> ).
            IF NOT back_intvalue CS intvalue.
              MESSAGE 'Invalid internal value for given domain' TYPE 'E'.
            ENDIF.
            intvalue = <intvalue>.
          CATCH cx_sy_conversion_error.
            MESSAGE 'Invalid internal value for given domain' TYPE 'E'.
        ENDTRY.
      ENDIF.
    
    START-OF-SELECTION.
    
      DATA(max_rows_bis) = COND i( WHEN max_rows > 0 THEN max_rows + 1 ).
      SELECT swotdv~objtype,
             tojtb~editelem  AS objtype_id,
             tojtt~stext     AS objtype_stext,
             tojtt~ntext     AS objtype_ntext,
             swotdv~editelem AS method,
             swotdq~editelem AS parameter,
             dd03l~fieldname AS field,
             swotdq~reffield AS swotdq_reffield,
             dd01l~convexit
          FROM swotdv
            INNER JOIN tojtb
              ON tojtb~name       = swotdv~objtype
            LEFT OUTER JOIN tojtt
              ON tojtt~name       = tojtb~name
             AND tojtt~language   = @sy-langu
            INNER JOIN swotdq
              ON swotdq~objtype   = swotdv~objtype
             AND swotdq~verb      = swotdv~verb
            INNER JOIN dd03l
              ON dd03l~tabname    = swotdq~refstruct
            INNER JOIN dd01l
              ON dd01l~domname    = dd03l~domname
          WHERE tojtb~active     = 'X'
            AND swotdq~paramtype = 'M'
            AND dd01l~convexit   = @convexit
            AND swotdv~objtype  IN @s_objtyp
            AND tojtb~editelem  IN @s_objid
            AND tojtt~stext     IN @s_objstx
            AND tojtt~ntext     IN @s_objntx
            AND swotdv~editelem IN @s_method
            AND swotdq~editelem IN @s_param
            AND ( swotdq~reffield = ' '
               OR swotdq~reffield = dd03l~fieldname )
            AND dd03l~fieldname IN @s_field
          INTO TABLE @DATA(fields)
          UP TO @max_rows_bis ROWS.
    
      TYPES ty_bapi_conversion_direction TYPE c LENGTH 7.
      TYPES ty_bapi_conversion_calls TYPE STANDARD TABLE OF ty_bapi_conversion_direction WITH EMPTY KEY.
      DATA(bapi_conversion_calls) = VALUE ty_bapi_conversion_calls( ).
      DATA(intvalue_2) = VALUE bapiconvrs-int_format( ).
      DATA(extvalue_2) = VALUE bapiconvrs-ext_format( ).
    
      bapi_conversion_calls = VALUE #( ( 'EXT2INT' ) ( 'INT2EXT' ) ).
    
      DATA(lo_grid) = NEW cl_salv_form_layout_grid( ).
      lo_grid->add_row( )->create_text( text = |Table:           { tabname }| ).
      lo_grid->add_row( )->create_text( text = |Field (column):  { fieldnam }| ).
      lo_grid->add_row( )->create_text( text = |Data element:    { rollname }| ).
      lo_grid->add_row( )->create_text( text = |Domain:          { domname }| ).
      lo_grid->add_row( )->create_text( text = |Conversion exit: { convexit }| ).
      lo_grid->add_row( )->create_text( text = |Internal length: { leng }| ).
      lo_grid->add_row( )->create_text( text = |External length: { outputlen }| ).
      lo_grid->add_row( ).
      IF extvalue IS NOT INITIAL.
        bapi_conversion_calls = VALUE #( ( 'EXT2INT' ) ( 'INT2EXT' ) ).
        lo_grid->add_row( )->create_text( text = |Start value (external): { extvalue }| ).
        lo_grid->add_row( ).
      ELSE.
        bapi_conversion_calls = VALUE #( ( 'INT2EXT' ) ( 'EXT2INT' ) ).
        lo_grid->add_row( )->create_text( text = |Start value (internal): { intvalue }| ).
        lo_grid->add_row( ).
      ENDIF.
      IF max_rows <> 0
          AND lines( fields ) > max_rows.
        lo_grid->add_row( )->create_header_information(
            text = |More results can be displayed by increasing MAX_ROWS > { max_rows }| ).
        DELETE fields INDEX max_rows + 1.
      ENDIF.
    
      TYPES:
        BEGIN OF ty_alv_line,
          objtype        TYPE swotdv-objtype,
          method         TYPE swotdv-editelem,
          parameter      TYPE swotdq-editelem,
          field          TYPE dd03l-fieldname,
          objtype_id     TYPE tojtb-editelem,
          objtype_stext  TYPE tojtt-stext,
          objtype_ntext  TYPE tojtt-ntext,
          extvalue_2     TYPE bapiconvrs-ext_format,
          external_error TYPE string,
          intvalue_2     TYPE bapiconvrs-int_format,
          internal_error TYPE string,
          diff_error     TYPE string,
        END OF ty_alv_line.
      TYPES ty_alv_table TYPE STANDARD TABLE OF ty_alv_line WITH EMPTY KEY.
      DATA(alv_table) = VALUE ty_alv_table( ).
    
      LOOP AT fields REFERENCE INTO DATA(ref_field).
    
        DATA(alv_line) = VALUE ty_alv_line( ).
    
        alv_line-objtype   = ref_field->objtype.
        alv_line-objtype_id     = ref_field->objtype_id.
        alv_line-objtype_stext  = ref_field->objtype_stext.
        alv_line-objtype_ntext  = ref_field->objtype_ntext.
        alv_line-method    = ref_field->method.
        alv_line-parameter = ref_field->parameter.
        alv_line-field     = COND #( WHEN ref_field->swotdq_reffield IS INITIAL THEN ref_field->field ).
    
        TYPES tt_data TYPE STANDARD TABLE OF bapiconvrs WITH EMPTY KEY.
    
        DATA(lt_data) = VALUE tt_data( ).
        DATA(lt_return) = VALUE bapirettab( ).
    
        IF extvalue IS NOT INITIAL.
          extvalue_2 = extvalue.
        ELSE.
          intvalue_2 = intvalue.
        ENDIF.
    
        LOOP AT bapi_conversion_calls REFERENCE INTO DATA(bapi_conversion_call).
    
          CASE bapi_conversion_call->*.
            WHEN 'EXT2INT'.
              lt_data = VALUE #(
                ( objtype    = ref_field->objtype
                  method     = ref_field->method
                  parameter  = ref_field->parameter
                  field      = ref_field->field
                  "rownumber  = 0
                  "int_format = ''
                  ext_format = extvalue_2
                  "conv_len   = 0
                  ) ).
    
              CALL FUNCTION 'BAPI_CONVERSION_EXT2INT1'
                TABLES
                  data   = lt_data
                  return = lt_return.
    
              intvalue_2 = lt_data[ 1 ]-int_format.
              alv_line-internal_error = COND #( WHEN lt_return IS NOT INITIAL
                                        THEN 'Error in BAPI_CONVERSION_EXT2INT1' ).
    
            WHEN 'INT2EXT'.
              lt_data = VALUE #(
                ( objtype    = ref_field->objtype
                  method     = ref_field->method
                  parameter  = ref_field->parameter
                  field      = ref_field->field
                  "rownumber  = 0
                  int_format = intvalue_2
                  "ext_format = ''
                  "conv_len   = 0
                  ) ).
              lt_return = VALUE #( ).
    
              CALL FUNCTION 'BAPI_CONVERSION_INT2EXT1'
                TABLES
                  data   = lt_data
                  return = lt_return.
    
              extvalue_2 = lt_data[ 1 ]-ext_format.
              alv_line-external_error = COND #( WHEN lt_return IS NOT INITIAL
                                        THEN 'Error in BAPI_CONVERSION_INT2EXT1' ).
          ENDCASE.
    
        ENDLOOP.
    
        alv_line-diff_error = COND #( WHEN ( extvalue IS NOT INITIAL
                                AND extvalue_2 <> extvalue )
                               OR ( extvalue IS INITIAL
                                AND intvalue_2 <> intvalue )
                     THEN 'The final value is different from the Start value').
    
        alv_line-intvalue_2 = intvalue_2.
        alv_line-extvalue_2 = extvalue_2.
    
        INSERT alv_line INTO TABLE alv_table.
      ENDLOOP.
    
      cl_salv_table=>factory( IMPORTING r_salv_table = DATA(gr_table)
                              CHANGING  t_table = alv_table ).
      gr_table->get_functions( )->set_all( ).
      DATA(gr_columns) = gr_table->get_columns( ).
      gr_columns->set_optimize( ).
      gr_columns->get_column( 'EXTVALUE_2' )->set_fixed_header_text( 'L' ).
      gr_columns->get_column( 'EXTVALUE_2' )->set_long_text( 'Result of INT->EXT' ).
      gr_columns->get_column( 'INTVALUE_2' )->set_fixed_header_text( 'L' ).
      gr_columns->get_column( 'INTVALUE_2' )->set_long_text( 'Result of EXT->INT' ).
      IF extvalue IS NOT INITIAL.
        " New column sequence INT then EXT: INTVALUE_2, INTERNAL_ERROR, EXTVALUE_2, EXTERNAL_ERROR
        " (instead of EXT then INT: EXTVALUE_2, EXTERNAL_ERROR, INTVALUE_2, INTERNAL_ERROR)
        gr_columns->set_column_position( columnname = 'INTERNAL_ERROR' position = 8 ).
        gr_columns->set_column_position( columnname = 'INTVALUE_2' position = 8 ).
      ENDIF.
      gr_table->set_top_of_list( lo_grid ).
      gr_table->display( ).
    

    Here are the screen field values to find parameters of BAPI_CONVERSION_INT2EXT1 to get the external value from the internal value 00000106 of the column PS_PSP_PNR of the table VBAP (note that the S_OBJTYP field is optional and has been set only to simplify the result):

    Input to find parameter values for BAPI_CONVERSION_INT2EXT1

    Here is the result (each row is one possibility of BAPI parameter values and the BAPI parameters are grouped in the left columns):

    Result of possible parameter values for BAPI_CONVERSION_INT2EXT1

    It means that BAPI_CONVERSION_INT2EXT1 may be called for instance with these parameters:

    2) If you know the Business Object Type

    The diagram sequence below shows the screenshots of SWO1 transaction code.

    First, you need to find the business object type corresponding to the WBS Project via the search help (F4), which is BUS2054.

    The BAPI method name is GetInfo (which corresponds to BAPI_PROJECT_GETINFO if you look into the details of the method).

    The parameters you need are ProjectDefinition and EWbsElementTable.

    By looking at the details of the parameters, you may know if it's a single value/no compound fields (ProjectDefinition) or a structure or table made of many fields (EWbsElementTable).

    You may obtain the External value of the WBS Element in the field WBS_ELEMENT of the parameter EWbsElementTable.

    SWO1 How to get the Method, Parameter and Field for BAPI_CONVERSION_EXT2INT1

    Example of ABAP implementation with both BAPI_CONVERSION_INT2EXT1 and BAPI_CONVERSION_EXT2INT1

    Now that you know all the technical names, you may create the program. I hope the explanations given above are sufficient to understand the program.

    REPORT.
    
    TYPES tt_data TYPE STANDARD TABLE OF bapiconvrs WITH EMPTY KEY.
    TYPES ty_export_wbs_element_table TYPE STANDARD TABLE OF bapi_wbs_element_exp  WITH EMPTY KEY.
    
    *   Data type      External value     Interval value
    *   -----------    ---------------    ------------------
    *   Project        I.001              I 001000   000  00
    *   WBS element    I.0011             I0011000   000  00
    
    DATA(lt_data) = VALUE tt_data(
      ( objtype    = 'BUS2054'
        method     = 'Getinfo'
        parameter  = 'ProjectDefinition'
        "field      = ''
        "rownumber  = 0
        int_format = 'I 001000   000  00'
        "ext_format = ''
        "conv_len   = 0
        ) ).
    DATA(lt_return) = VALUE bapirettab( ).
    
    CALL FUNCTION 'BAPI_CONVERSION_INT2EXT1'
      TABLES
        data   = lt_data
        return = lt_return.
    
    WRITE : / 'Project internal value', lt_data[ 1 ]-int_format. " 'I 001000   000  00'
    WRITE : / 'Project external value', lt_data[ 1 ]-ext_format. " e.g. possibly contains 'I.001'
    
    DATA(project_definition) = CONV ps_pspid( lt_data[ 1 ]-ext_format ).
    DATA(e_project_definition) = VALUE bapi_project_definition_ex( ).
    DATA(ls_return) = VALUE bapireturn1( ).
    DATA(e_wbs_element_table) = VALUE ty_export_wbs_element_table( ).
    CALL FUNCTION 'BAPI_PROJECT_GETINFO'
      EXPORTING
        project_definition   = project_definition
      IMPORTING
        e_project_definition = e_project_definition
        return               = ls_return
      TABLES
        e_wbs_element_table  = e_wbs_element_table.
    
    IF ls_return IS NOT INITIAL.
      WRITE : / 'Error:', ls_return.
    ELSE.
    
      WRITE : / 'Success, project description is', e_project_definition-description.
    
      LOOP AT e_wbs_element_table REFERENCE INTO DATA(wbs_element).
    
        lt_data = VALUE #(
          ( objtype    = 'BUS2054'
            method     = 'Getinfo'
            parameter  = 'EWbsElementTable'
            field      = 'WBS_ELEMENT'
            rownumber  = sy-tabix " the line number in e_wbs_element_table
            "int_format = ''
            ext_format = wbs_element->wbs_element
            "conv_len   = 0
            ) ).
    
        CALL FUNCTION 'BAPI_CONVERSION_EXT2INT1'
          TABLES
            data   = lt_data
            return = lt_return.
    
        DATA(text_ext) = 'external value'.
        WRITE : / 'WBS element:', text_ext, lt_data[ 1 ]-ext_format. " e.g. contains 'I.0011'
        WRITE : / 'internal value' UNDER text_ext, lt_data[ 1 ]-int_format. " e.g. contains 'I0011000   000  00'
    
      ENDLOOP.
    
    ENDIF.
    

    Output:

    ABAP SAP ERP WBS Element and Project Internal and External values

    NB 1: direct call of BAPI_CONVERSION_INT2EXT1 via SE37:

    SE37 BAPI_CONVERSION_INT2EXT1

    NB 2: WBS = Work Breakdown Structure, and is part of the PS (Project System) module of SAP ERP and S/4HANA software.