Abap excel to sap

In this Blog-post I’d like to give a few insights on how we process XLSX file by using latest ABAP, which might be quite different than in most other implementations, for example:ABAP and OLE or Excel with SAP – An Overview

By using CL_XLSX_DOCUMENT (available from 2008), it is easy to load file, workbook, sheets, rows and columns. A good example code can be found within class CL_EHFND_XLSX(available on  ABAP AS 752 SP-Level 0004, Software Component S4CORE Release 102, SP 4.).

On the other hand, you can set document format by using IF_IXML_NODE, below example code show how …

lo_xlsx_doc = cl_xlsx_document=>load_document( <XSTRING of xlsx file> ) 
lo_workbookpart = lo_xlsx_doc->get_workbookpart( ).    
lo_wordsheetparts = lo_workbookpart->get_worksheetparts( ).    
lo_wordsheetpart = lo_wordsheetparts->get_part( 0 ).    
lo_sheet_content = lo_wordsheetpart->get_data( ).
CREATE OBJECT lo_xml_document.
lo_xml_document->parse_xstring( lo_sheet_content ).
DATA(lo_node_datavalidation_init) = lo_node_datavalidations->clone( ).

....
        DATA(lo_node_datavalidation) = lo_node_datavalidation_init->clone( ).
        lo_node_datavalidation->set_name( 'dataValidation' ).

        CONCATENATE ls_validation-column lv_begin_str ':' ls_validation-column lv_end_str INTO 
        DATA(lv_sqref).
        DATA(lo_attrs_map_datavalidation) = lo_node_datavalidation->get_attributes( ).
        DATA(lo_attr_sqref) = lo_attrs_map_datavalidation->get_named_item_ns( 'count' )->clone( ).
        lo_attr_sqref->set_name( 'sqref' ).
        lo_attr_sqref->set_value( lv_sqref ).
        lo_attrs_map_datavalidation->set_named_item_ns( lo_attr_sqref ).

        lo_attrs_map_datavalidation->remove_named_item_ns( 'count' ).

        DATA(lo_attr_showerrormsg) = lo_attr_sqref->clone( ).
        lo_attr_showerrormsg->set_name( 'showErrorMessage' ).
        lo_attr_showerrormsg->set_value( '1' ).
        lo_attrs_map_datavalidation->set_named_item_ns( lo_attr_showerrormsg ).
.....

Executable SE38 report.

Main functionalities of this report are:

  1. Download any DDIC table’s content into xlsx file
  2. Change value in the xlsx file
  3. upload xlsx file into DDIC table
  4. check changed value in DDIC table.

And the dynamic structure is used in this report. The code style is what I would like to present also.

User Interface

selection-screen begin of block b04 with frame title text-b04.
  parameters  p_exp radiobutton group radi user-command action default 'X'.
  parameters  p_imp radiobutton group radi.
selection-screen end of block b04.

selection-screen begin of block b01 with frame title text-b01.
  parameters p_table type dd02l-tabname modif id gp1 obligatory memory id ht.
  parameters p_file type localfile modif id gp2 obligatory memory id hf.
  parameters p_sql type string modif id gp3.
  selection-screen comment /1(75) comm.
selection-screen end of block b01.


initialization.
  comm = `e.g. RLDNR = 'Y1' AND RRCTY = 'U'`.


at selection-screen on value-request for p_file.
*  call function 'F4_FILENAME'
*    exporting
*      field_name = 'P_FILE'
*    importing
*      file_name  = p_file.

  data(title) = |Select Excel File, e.g. *.xlsx|.
  data(defaultextension) = |.xlsx|.
  data(filefilter) = `Excel Files (*.xlsx)|*.xlsx`.
  data it_tab type filetable.
  data returncode type i.

  call method cl_gui_frontend_services=>file_open_dialog
    exporting
      window_title      = title
      default_extension = defaultextension
*     default_filename  =
*     file_filter       = filefilter
*     with_encoding     =
*     initial_directory =
*     multiselection    =
    changing
      file_table        = it_tab
      rc                = returncode
*     user_action       =
*     file_encoding     =
*    exceptions
*     file_open_dialog_failed = 1
*     cntl_error        = 2
*     error_no_gui      = 3
*     not_supported_by_gui    = 4
*     others            = 5
    .
  if sy-subrc <> 0.
*   Implement suitable error handling here
  endif.

  read table it_tab assigning field-symbol(<selectedfilename>) index 1.
  if sy-subrc = 0.
    p_file = <selectedfilename>-filename.
  endif.

Main Functionality

Download table content into local excel file (xlsx)

Select action  “Export”

Input existing table , e.g. Table Name T000, File Full Path: c:demot000.xlsx

Change the value of non-key column in xlsx file.

start-of-selection.
  try.
      data(configurationhandler) =  new lcl_configuration( filefullpath = conv #( p_file )
                                                           tablename = conv #( p_table )
                                                           sqlscript = p_sql  ).
      if p_exp = abap_true.
        configurationhandler->export( ).
      else.
        configurationhandler->import( ).
      endif.
    catch lcx_configuration into data(configurationexception).
      write: / configurationexception->local_text.
  endtry.

Upload local excel file (*.xlsx) into table

Select action  “Import”

Input existing table , e.g. Table Name T000, File Full Path: c:demot000.xlsx

Empty row will be skip, and table entries will be modified (Insert or Update). It is not possible to delete existing table entry.

start-of-selection.
  try.
      data(configurationhandler) =  new lcl_configuration( filefullpath = conv #( p_file )
                                                           tablename = conv #( p_table )
                                                           sqlscript = p_sql  ).
      if p_exp = abap_true.
        configurationhandler->export( ).
      else.
        configurationhandler->import( ).
      endif.
    catch lcx_configuration into data(configurationexception).
      write: / configurationexception->local_text.
  endtry.

Exception Handling

You will get exception of structure infliction if xlsx file is not for that table.

    "check file structure, first line of excel file
    data(columncount) = firstsheet->get_last_column_number_in_row( 1 ).
    data column type i value 1.
    "data tablecomponents type cl_abap_structdescr=>component_table.
    data(tablecomponents) = me->tablestructure->get_components( ).

    data invalidcolumn type string.
    types: begin of columninfo,
             column     type i,
             columnname type string,
           end of columninfo.
    types columnsinfo type standard table of columninfo with empty key.

    data columnfromfile type columnsinfo.

    do columncount times.
      data(cellvalue) = firstsheet->get_cell_content(
                            exporting
                              iv_row     = 1
                              iv_column  = column ).

      append initial line to columnfromfile assigning field-symbol(<columnfromfile>).
      <columnfromfile>-column = column.
      <columnfromfile>-columnname = cellvalue.

      if line_exists( tablecomponents[ name = cellvalue ]   ).
        delete tablecomponents where name = cellvalue.
      else.
        invalidcolumn = invalidcolumn && |,{ cellvalue }|.
      endif.
      column = column + 1.
    enddo.

    data missingcolumns type string.
    loop at tablecomponents reference into data(currentcomponent).
      missingcolumns = missingcolumns && |, { currentcomponent->*-name }|.
    endloop.


    if not invalidcolumn is initial.
      raise exception type lcx_configuration
        exporting
          text = |Find invalid columns: { invalidcolumn } |.

    endif.

First row will be the table columns’ name

Local Class Definition

*&---------------------------------------------------------------------*
*& Include          ZZZZ_HOME_CFG_FINE_TUNING_LCL
*&---------------------------------------------------------------------*
class lcx_configuration definition
                         inheriting from cx_static_check.
  public section.
    data local_text type string.
    methods constructor importing text type string.
endclass.

class lcx_configuration implementation.
  method constructor.
    super->constructor( ).
    local_text = text.
  endmethod.
endclass.
*&---------------------------------------------------------------------*
*& Class lcl_configuration
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
class lcl_configuration definition.
  public section.
    data filefullpath type string.
    data tablename type string.
    data sqlscript type string.
    data tableinfo type tadir.
    data tablestructure type ref to cl_abap_structdescr.
    data tabletype      type ref to cl_abap_tabledescr.
    data tabledata type ref to data.

    class-methods validate_sql_script
      changing sqlscript type string.

    class-methods validate_table
      changing checkedtablename type string
      raising  lcx_configuration.

    methods constructor "Constructore method
      importing filefullpath type string
                tablename    type string
                sqlscript    type string
      raising   lcx_configuration.
    methods import raising   lcx_configuration.
    methods export raising   lcx_configuration.
  protected section.
    methods get_filecontent
      returning value(filecontent) type xstring
      raising   lcx_configuration.
    methods extract_data_from_table
      raising lcx_configuration.
    methods check_file
      raising lcx_configuration.
    methods extract_data_from_excel
      raising lcx_configuration.
    methods get_tablecontent
      exporting tablecontent type any table
      raising   lcx_configuration.
  private section.
endclass.

class lcl_configuration implementation.
  method constructor.
    if filefullpath is initial or tablename is initial.
      raise exception type lcx_configuration
        exporting
          text = |File Name { filefullpath } and Table Name { tablename } should be provided|.
    endif.
    me->filefullpath = filefullpath.
    me->tablename = tablename.
    me->sqlscript = sqlscript.

    lcl_configuration=>validate_table( changing checkedtablename = me->tablename ).

    me->tablestructure ?= cl_abap_typedescr=>describe_by_name( me->tablename  ).
    if not me->tablestructure is bound.
      raise exception type lcx_configuration
        exporting
          text = |Exception occurs when parsing Table Structure for { tablename } |.
    endif.
    try.
        me->tabletype = cl_abap_tabledescr=>create( p_line_type = me->tablestructure ).
      catch cx_sy_table_creation into data(tabletypeexception).
        raise exception type lcx_configuration
          exporting
            text = |Exception occurs when parsing Table Type for { tablename } |.
    endtry.
    create data tabledata type handle me->tabletype.
  endmethod.
  method import.
    "Update DDIC table content from (client PC) excel file
    me->extract_data_from_excel( ).

    field-symbols <finaltabledata> type standard table.
    data finaltabledata type ref to data.
    create data finaltabledata type handle me->tabletype.
    assign finaltabledata->* to <finaltabledata>.

    field-symbols <tabledata> type standard table.
    assign me->tabledata->* to <tabledata>.
    loop at <tabledata> assigning field-symbol(<currenttabledata>).
      assign component 'MANDT' of structure <currenttabledata> to field-symbol(<lv_client>).
      if sy-subrc = 0.
        <lv_client> = ''.
        if not <currenttabledata> is initial.
          <lv_client> = sy-mandt.
          append <currenttabledata> to <finaltabledata>.
        else.
          "delete <tabledata> from <currenttabledata>.
        endif.
      else.
        if <currenttabledata> is initial.
          "delete <tabledata> from <currenttabledata>.
        endif.
      endif.
    endloop.

    data(checkedtablename) = me->tablename.
    lcl_configuration=>validate_table( changing checkedtablename = checkedtablename ).

    if not <finaltabledata> is initial.
      modify (checkedtablename) from  table <finaltabledata>.
      "break-point.
      if sy-subrc <> 0.
        rollback work.
        raise exception type lcx_configuration
          exporting
            text = |Exception occurs when modifying table:  { tablename } |.
      else.
        message s001(00) with |Table:  { tablename } is modified successfully.|.
      endif.
    endif.

  endmethod.
  method export.
    "Create client PC excel file from DDIC table
    data(filecontent) = me->get_filecontent( ).

    cl_scp_change_db=>xstr_to_xtab( exporting im_xstring = filecontent
                                    importing ex_xtab    = data(filecontenttab) ).

    cl_gui_frontend_services=>gui_download(
      exporting
        bin_filesize              = xstrlen( filecontent )
        filename                  = |{ me->filefullpath }|
        filetype                  = 'BIN'
        confirm_overwrite         = abap_true
      importing
        filelength                = data(bytestransferred)
      changing
        data_tab                  = filecontenttab
      exceptions
        file_write_error          = 1
        no_batch                  = 2
        gui_refuse_filetransfer   = 3
        invalid_type              = 4
        no_authority              = 5
        unknown_error             = 6
        header_not_allowed        = 7
        separator_not_allowed     = 8
        filesize_not_allowed      = 9
        header_too_long           = 10
        dp_error_create           = 11
        dp_error_send             = 12
        dp_error_write            = 13
        unknown_dp_error          = 14
        access_denied             = 15
        dp_out_of_memory          = 16
        disk_full                 = 17
        dp_timeout                = 18
        file_not_found            = 19
        dataprovider_exception    = 20
        control_flush_error       = 21
        not_supported_by_gui      = 22
        error_no_gui              = 23
        others                    = 24
    ).
    if sy-subrc <> 0.
      message id sy-msgid type sy-msgty number sy-msgno
                 with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    else.
      message s001(00) with bytestransferred ' bytes transferred'.
    endif.
  endmethod.

  method get_filecontent.
    me->extract_data_from_table( ).

    if me->tabledata is initial.
      raise exception type lcx_configuration
        exporting
          text = |Table { tablename } has no entry.|.
    endif.

    "Get file content from table
    clear filecontent.
    try.
        data(xlsx_handling) = cl_ehfnd_xlsx=>get_instance( ).
        data(xlsx_document) = xlsx_handling->create_doc( ).
        data(xlsx_sheets) = xlsx_document->get_sheets( ).
        data(first_xlsx_sheet) = xlsx_document->get_sheet_by_id( xlsx_sheets[ 1 ]-sheet_id ).
        first_xlsx_sheet->change_sheet_name( 'Data' ).
        data(lv_column) = 1.

        loop at me->tablestructure->components reference into data(component).
          first_xlsx_sheet->set_cell_content( iv_row = 1 iv_column = lv_column iv_value = component->name ).
          lv_column = lv_column + 1.
        endloop.

        data(lv_row) = 2.
        field-symbols <tabledata> type standard table.
        assign me->tabledata->* to <tabledata>.
        loop at <tabledata> assigning field-symbol(<currenttabledata>).
          lv_column = 1.
          loop at me->tablestructure->components reference into component.
            assign component component->name of structure <currenttabledata> to field-symbol(<columnvalue>).
            first_xlsx_sheet->set_cell_content( iv_row = lv_row iv_column = lv_column iv_value = <columnvalue> ).
            lv_column = lv_column + 1.
          endloop.
          lv_row = lv_row + 1.
        endloop.
        filecontent = xlsx_document->save( ).

      catch cx_openxml_format  into data(openxml_format_exception).
        raise exception type lcx_configuration
          exporting
            text = |Error occurs when constructing excel file instance. cx_openxml_format|.
      catch cx_openxml_not_found into data(openxml_not_found_exception).
        raise exception type lcx_configuration
          exporting
            text = |Error occurs when constructing excel file instance. CX_OPENXML_NOT_FOUND |.

      catch cx_openxml_not_allowed into data(openxml_not_allowed_exception).
        raise exception type lcx_configuration
          exporting
            text = |Error occurs when constructing excel file instance. CX_OPENXML_NOT_ALLOWED |.

    endtry.
  endmethod.

  method get_tablecontent.
    "Get table content from file

  endmethod.
  method validate_table.
    "raise exception if table does not exist
    select single * from tadir into @data(tableinfo) where obj_name = @checkedtablename and object = 'TABL'. "#EC CI_GENBUFF.
    if sy-subrc <> 0.
      raise exception type lcx_configuration
        exporting
          text = |Table { checkedtablename } does not exist.|.
    endif.

    try.
        checkedtablename =
           cl_abap_dyn_prg=>check_table_or_view_name_str(
            val = checkedtablename
            packages = conv #( tableinfo-devclass ) 
            incl_sub_packages = abap_true
            ).
      catch cx_abap_not_a_table
            cx_abap_not_in_package.
        return.
    endtry.
  endmethod.
  method extract_data_from_table.
    data sql_script type string.
    data checkedtablename type string.
    sql_script = me->sqlscript.
    checkedtablename = me->tablename.

    lcl_configuration=>validate_sql_script( changing sqlscript = sql_script ).
    lcl_configuration=>validate_table( changing checkedtablename = checkedtablename ).

    field-symbols <tabledata> type standard table.
    assign tabledata->* to <tabledata>.
    if me->sqlscript is initial.
      select * from (checkedtablename) into table <tabledata>.
    else.
      select * from (checkedtablename) into table <tabledata> where (sql_script).
    endif.

  endmethod.

  method validate_sql_script.
    if sqlscript is initial.
      return.
    endif.

    sqlscript = replace( val  = sqlscript
                          sub  = `'`
                          with = `''`
                          occ  = 0 ).
    concatenate `'`  sqlscript `'` into sqlscript separated by space.
    try.
        sqlscript =
         cl_abap_dyn_prg=>check_char_literal( sqlscript ).

        data(lv_len) = strlen( sqlscript ) - 2.
        sqlscript = sqlscript+1(lv_len).
        sqlscript = replace( val  = sqlscript
                                   sub  = `''`
                                   with = `'`
                                   occ  = 0 ).

      catch cx_abap_invalid_value into data(lo_exception).
        clear sqlscript.
    endtry.
  endmethod.

  method check_file.

  endmethod.
  method extract_data_from_excel.
    field-symbols <exceldata> type standard table.
    assign me->tabledata->* to <exceldata>.

    data(xlsxhandler) = cl_ehfnd_xlsx=>get_instance( ).
    check not xlsxhandler is initial.

    try.
        data(xstring_excel) = cl_openxml_helper=>load_local_file( me->filefullpath ).
      catch cx_openxml_not_found into data(openxml_not_found).
        return.
    endtry.

    try.
        data(xlsxdocument) = xlsxhandler->load_doc( iv_file_data = xstring_excel ).
      catch cx_openxml_format into data(openxml_format).
        return.
      catch cx_openxml_not_allowed into data(openxml_not_allowed).
        return.
      catch cx_dynamic_check into data(dynamic_check).
        return.
    endtry.

    "extract data from first sheet
    try.
        data(firstsheet) = xlsxdocument->get_sheet_by_id( iv_sheet_id = 1 ).
      catch cx_openxml_format  into openxml_format.
        raise exception type lcx_configuration
          exporting
            text = |Error occurs when extract data from first sheet: CX_OPENXML_FORMAT |.
      catch cx_openxml_not_found  into openxml_not_found.
        raise exception type lcx_configuration
          exporting
            text = |Error occurs when extract data from first sheet: OPENXML_NOT_FOUND |.
      catch cx_dynamic_check  into dynamic_check.
        raise exception type lcx_configuration
          exporting
            text = |Error occurs when extract data from first sheet: CX_DYNAMIC_CHECK |.
    endtry.
    "return if no sheet in xlsx file
    check not firstsheet is initial.

    "check file structure, first line of excel file
    data(columncount) = firstsheet->get_last_column_number_in_row( 1 ).
    data column type i value 1.
    "data tablecomponents type cl_abap_structdescr=>component_table.
    data(tablecomponents) = me->tablestructure->get_components( ).

    data invalidcolumn type string.
    types: begin of columninfo,
             column     type i,
             columnname type string,
           end of columninfo.
    types columnsinfo type standard table of columninfo with empty key.

    data columnfromfile type columnsinfo.

    do columncount times.
      data(cellvalue) = firstsheet->get_cell_content(
                            exporting
                              iv_row     = 1
                              iv_column  = column ).

      append initial line to columnfromfile assigning field-symbol(<columnfromfile>).
      <columnfromfile>-column = column.
      <columnfromfile>-columnname = cellvalue.

      if line_exists( tablecomponents[ name = cellvalue ]   ).
        delete tablecomponents where name = cellvalue.
      else.
        invalidcolumn = invalidcolumn && |,{ cellvalue }|.
      endif.
      column = column + 1.
    enddo.
    data missingcolumns type string.
    loop at tablecomponents reference into data(currentcomponent).
      missingcolumns = missingcolumns && |, { currentcomponent->*-name }|.
    endloop.
    if not invalidcolumn is initial.
      raise exception type lcx_configuration
        exporting
          text = |Find invalid columns: { invalidcolumn } |.
    endif.

    if not missingcolumns is initial.
      raise exception type lcx_configuration
        exporting
          text = |Columns do not exist in excel file: { missingcolumns } |.
    endif.

    tablecomponents = me->tablestructure->get_components( ).
    data(rowcount) = firstsheet->get_last_row_number( ).
    data currentrow type i value 2.
    while currentrow <= rowcount.
      append initial line to <exceldata> assigning field-symbol(<currentrow>).
      loop at columnfromfile reference into data(currentcolumn).
        cellvalue = firstsheet->get_cell_content(
                              exporting
                                iv_row     = currentrow
                                iv_column  = currentcolumn->*-column ).
        assign component currentcolumn->*-columnname of structure <currentrow> to field-symbol(<cellvalue>).
        <cellvalue> = cellvalue.
      endloop.
      currentrow = currentrow + 1.
    endwhile.
  endmethod.
endclass.

Conclusion

Thank you for your interest in XLSX2ABAP and ABAP2XLSX. Example code is tested on SAP_BASIS 755, S4CORE 105.

Skip to content Skip to blog sidebar

ABAP code to upload XLSX file to SAP using ABAP. The method shown in the blog will work in SAP GUI and Webgui (program launched from Fiori Launchpad). This approach will also work with OData.

Code is based on class CL_FDT_XL_SPREADSHEET which can be instantiated using the file name and excel file in XSTRING variable. This processing of file as XSTRING is particularly useful in case of Fiori Apps, OData CREATE_STREAM method pass uploaded file already in XSTRING which can be simply passed on to class CL_FDT_XL_SPREADSHEET constructor.

After instantiating the class get list of worksheets in the file using IF_FDT_DOC_SPREADSHEET~GET_WORKSHEET_NAMES. Method GET_WORKSHEET_NAMES returns internal table. In most of the case, you would read the first worksheet name and call method IF_FDT_DOC_SPREADSHEET~GET_ITAB_FROM_WORKSHEET with worksheet name to get data in a dynamic internal table. However, if you have data over multiple worksheets then you would have to call method GET_ITAB_FROM_WORKSHEET in the loop for each worksheet.

There are some function modules (TEXT_CONVERT_XLS_TO_SAP) available in SAP which can help you read data from XLS/XLSX file but these are based on Office Integration and requires MS Office installed on your PC. Also, this Office Integration solution (along with a range of other features) is not supported in WebGUI. In other words, these FMs will only work when you are running your program in SAP WebGUI.

I have structured the logic in standalone SE38 program so you can copy-paste and have it ready for testing in your system. Obviously, you would have to adapt the code to use it in your application but you get the idea of how it works.

*---------------------------------------------------------------------*
* Report ZPW_EXCELUPLOAD
*---------------------------------------------------------------------*
REPORT zpw_excelupload.

FIELD-SYMBOLS : <gt_data>       TYPE STANDARD TABLE .

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME .
  PARAMETERS : p_file TYPE ibipparms-path OBLIGATORY,
               p_ncol TYPE i OBLIGATORY DEFAULT 10.
SELECTION-SCREEN END OF BLOCK b1 .

*--------------------------------------------------------------------*
* at selection screen
*--------------------------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.

  DATA: lv_rc TYPE i.
  DATA: lt_file_table TYPE filetable,
        ls_file_table TYPE file_table.

  CALL METHOD cl_gui_frontend_services=>file_open_dialog
    EXPORTING
      window_title = 'Select a file'
    CHANGING
      file_table   = lt_file_table
      rc           = lv_rc.
  IF sy-subrc = 0.
    READ TABLE lt_file_table INTO ls_file_table INDEX 1.
    p_file = ls_file_table-filename.
  ENDIF.

START-OF-SELECTION .

  PERFORM read_file .
  PERFORM process_file.

*---------------------------------------------------------------------*
* Form READ_FILE
*---------------------------------------------------------------------*
FORM read_file .

  DATA : lv_filename      TYPE string,
         lt_records       TYPE solix_tab,
         lv_headerxstring TYPE xstring,
         lv_filelength    TYPE i.

  lv_filename = p_file.

  CALL FUNCTION 'GUI_UPLOAD'
    EXPORTING
      filename                = lv_filename
      filetype                = 'BIN'
    IMPORTING
      filelength              = lv_filelength
      header                  = lv_headerxstring
    TABLES
      data_tab                = lt_records
    EXCEPTIONS
      file_open_error         = 1
      file_read_error         = 2
      no_batch                = 3
      gui_refuse_filetransfer = 4
      invalid_type            = 5
      no_authority            = 6
      unknown_error           = 7
      bad_data_format         = 8
      header_not_allowed      = 9
      separator_not_allowed   = 10
      header_too_long         = 11
      unknown_dp_error        = 12
      access_denied           = 13
      dp_out_of_memory        = 14
      disk_full               = 15
      dp_timeout              = 16
      OTHERS                  = 17.

  "convert binary data to xstring
  "if you are using cl_fdt_xl_spreadsheet in odata then skips this step
  "as excel file will already be in xstring
  CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
    EXPORTING
      input_length = lv_filelength
    IMPORTING
      buffer       = lv_headerxstring
    TABLES
      binary_tab   = lt_records
    EXCEPTIONS
      failed       = 1
      OTHERS       = 2.

  IF sy-subrc <> 0.
    "Implement suitable error handling here
  ENDIF.

  DATA : lo_excel_ref TYPE REF TO cl_fdt_xl_spreadsheet .

  TRY .
      lo_excel_ref = NEW cl_fdt_xl_spreadsheet(
                              document_name = lv_filename
                              xdocument     = lv_headerxstring ) .
    CATCH cx_fdt_excel_core.
      "Implement suitable error handling here
  ENDTRY .

  "Get List of Worksheets
  lo_excel_ref->if_fdt_doc_spreadsheet~get_worksheet_names(
    IMPORTING
      worksheet_names = DATA(lt_worksheets) ).

  IF NOT lt_worksheets IS INITIAL.
    READ TABLE lt_worksheets INTO DATA(lv_woksheetname) INDEX 1.

    DATA(lo_data_ref) = lo_excel_ref->if_fdt_doc_spreadsheet~get_itab_from_worksheet(
                                             lv_woksheetname ).
    "now you have excel work sheet data in dyanmic internal table
    ASSIGN lo_data_ref->* TO <gt_data>.
  ENDIF.

ENDFORM.

*---------------------------------------------------------------------*
* Form PROCESS_FILE
*---------------------------------------------------------------------*
FORM process_file .

  DATA : lv_numberofcolumns   TYPE i,
         lv_date_string       TYPE string,
         lv_target_date_field TYPE datum.


  FIELD-SYMBOLS : <ls_data>  TYPE any,
                  <lv_field> TYPE any.

  "you could find out number of columns dynamically from table <gt_data>
  lv_numberofcolumns = p_ncol .

  LOOP AT <gt_data> ASSIGNING <ls_data> FROM 2 .

    "processing columns
    DO lv_numberofcolumns TIMES.
      ASSIGN COMPONENT sy-index OF STRUCTURE <ls_data> TO <lv_field> .
      IF sy-subrc = 0 .
        CASE sy-index .
*          when 1 .
*          when 2 .
          WHEN 10 .
            lv_date_string = <lv_field> .
            PERFORM date_convert USING lv_date_string CHANGING lv_target_date_field .
            WRITE lv_target_date_field .
          WHEN OTHERS.
            WRITE : <lv_field> .
        ENDCASE .
      ENDIF.
    ENDDO .
    NEW-LINE .
  ENDLOOP .
ENDFORM.

*---------------------------------------------------------------------*
* Form DATE_CONVERT
*---------------------------------------------------------------------*
FORM date_convert USING iv_date_string TYPE string CHANGING cv_date TYPE datum .

  DATA: lv_convert_date(10) TYPE c.

  lv_convert_date = iv_date_string .

  "date format YYYY/MM/DD
  FIND REGEX '^d{4}[/|-]d{1,2}[/|-]d{1,2}$' IN lv_convert_date.
  IF sy-subrc = 0.
    CALL FUNCTION '/SAPDMC/LSM_DATE_CONVERT'
      EXPORTING
        date_in             = lv_convert_date
        date_format_in      = 'DYMD'
        to_output_format    = ' '
        to_internal_format  = 'X'
      IMPORTING
        date_out            = lv_convert_date
      EXCEPTIONS
        illegal_date        = 1
        illegal_date_format = 2
        no_user_date_format = 3
        OTHERS              = 4.
  ELSE.

    " date format DD/MM/YYYY
    FIND REGEX '^d{1,2}[/|-]d{1,2}[/|-]d{4}$' IN lv_convert_date.
    IF sy-subrc = 0.
      CALL FUNCTION '/SAPDMC/LSM_DATE_CONVERT'
        EXPORTING
          date_in             = lv_convert_date
          date_format_in      = 'DDMY'
          to_output_format    = ' '
          to_internal_format  = 'X'
        IMPORTING
          date_out            = lv_convert_date
        EXCEPTIONS
          illegal_date        = 1
          illegal_date_format = 2
          no_user_date_format = 3
          OTHERS              = 4.
    ENDIF.

  ENDIF.

  IF sy-subrc = 0.
    cv_date = lv_convert_date .
  ENDIF.

ENDFORM .

Uploaded this excel file.

Below results from SAP GUI and WebGUI.

ABAP программа загрузки данных из EXCEL в SAP систему. Разберу на примере загрузку Excel файла, проверку и преобразование данных, полученных при загрузке ABAP. 
Это полезная и часто используемая задача.

Загрузка данных из Excel

Рассмотрим один из вариантов загрузки данных из Excel на примере программы ABAP. Подробно разберу каждый блок программы для лучшего понимания. Ссылку на файл Excel для тестирования данной программы приведу в конце данной статьи.

Программа ABAP Excel. Загрузка из Excel в SAP

Селекционный экран ABAP для выбора файла

Создаю селекционный экран ABAP на который добавлю одно поле для выбора файла из которого будут загружаться данные.

PARAMETERS p_file TYPE string LOWER CASE.

Селекционный экран ABAP для выбора файла Excel.

Селекционный экран ABAP для выбора файла Excel.

Средство поиска ABAP для файла

Так же в этой части кода добавляю средство поиска ABAP для поля файла через использование события AT SELECTION-SCREEN ON VALUE-REQUEST.

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.

  cl_salv_test_data=>select_file( IMPORTING filename = p_file ).

Окно выбора файла стандартный проводник

Окно выбора файла стандартный проводник

Определяю тип для внутренней таблицы результата

Я определил локальный тип структуры результата для большей наглядности в статье, но на его месте может быть и тип ABAP словаря.

START-OF-SELECTION.

  TYPES:

    BEGIN OF ts_data,

      carrid    TYPE s_carr_id,

      connid    TYPE s_conn_id,

      fldate    TYPE s_date,

      price TYPE s_price,

      currency  TYPE s_currcode,

      planetype TYPE s_planetye,

      seatsmax  TYPE s_seatsmax,

      seatsocc  TYPE s_seatsocc,

      gjahr     TYPE gjahr,

      monat     TYPE monat,

    END OF ts_data.

Внутренняя таблица lt_sflight это таблица в которую будет помещён итоговый уже преобразованный результат загрузки. А таблица lt_intern это внутренняя таблица abap в которую изначально будут помещены данные из Excel для дальнейшей обработки.

  DATA:

    lt_sflight TYPE STANDARD TABLE OF ts_data,

    lt_intern  TYPE TABLE OF alsmex_tabline.

Структура ABAP словаря alsmex_tabline

Структура ABAP словаря alsmex_tabline

ФМ ALSM_EXCEL_TO_INTERNAL_TABLE

Сама загрузка происходит при вызове функционального метода ALSM_EXCEL_TO_INTERNAL_TABLE, разберём подробно его параметры:

    CALL FUNCTION ‘ALSM_EXCEL_TO_INTERNAL_TABLE’

      EXPORTING

        filename                = CONV rlgrapfilename( p_file )

        i_begin_col             = 1

        i_begin_row             = 2

        i_end_col               = 10

        i_end_row               = 10000

      TABLES

        intern                  = lt_intern

      EXCEPTIONS

        inconsistent_parameters = 1

        upload_ole              = 2

        OTHERS                  = 3.

  • filename – путь к файлу Excel. Использование конструкции CONV в этом случае преобразует параметр p_file к нужному типу.
  • i_begin_col – номер колонки с которой начинать загрузку
  • i_begin_row – номер строки с которой начинаем загрузку. В нашем случае установил значение 2 так как мне не нужно обрабатывать первую строку заголовка.
  • i_end_col – сколько колонок нам нужно анализировать при загрузке
  • i_end_row – сколько записей максимум берётся для анализа.
  • intern – внутренняя таблица в которую будут загружаться данные из файла.

Обработка результата загрузки данных из Excel

С использованием конструкции нового синтаксиса LOOP AT GROUP BY обходим таблицу сгруппировав её по столбцу row, в котором расположен номер строки. И после обработки всей группы с одинаковым номером строки мы добавляем запись в таблицу результата и переходим к следующей группе.

Более подробно загрузка и обработка данных после разбирается в видео и не забывайте подписаться на мой канал YouCoder.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

      LOOP AT lt_intern INTO DATA(ls_intern)

        GROUP BY ( row = ls_internrow )

        REFERENCE INTO DATA(lr_grp).

        DATA(ls_alv) = VALUE ts_data( ).

        LOOP AT GROUP lr_grp REFERENCE INTO DATA(lr_item).

          CHECK lr_item>value IS NOT INITIAL.

          CASE lr_item>col.

            WHEN 1.

              ls_alvcarrid = lr_item>value.

            WHEN 2.

              ls_alvconnid = lr_item>value.

            WHEN 3.

              ls_alvfldate = |{ lr_item>value+6(4) }{ lr_item>value+3(2) }{ lr_item>value(2) }|. » 29.04.2015 20150429

            WHEN 4.

              lr_item>value = replace( val = lr_item>value regex =‘[,]’ with = ‘.’ occ = 0 ). » 427,94

              ls_alvprice = lr_item>value.

            WHEN 5.

              ls_alvcurrency = lr_item>value.

            WHEN 6.

              ls_alvplanetype = lr_item>value.

            WHEN 7.

              ls_alvseatsmax = lr_item>value.

            WHEN 8.

              IF strlen( lr_item>value ) > 10.

                ls_alvseatsocc = lr_item>value.

              ENDIF.

            WHEN 9.

              IF lr_item>value CO |0123456789| AND lr_item>value >= 1 AND lr_item>value <= 9999.

                ls_alvgjahr = lr_item>value.

              ENDIF.

            WHEN 10.

              IF lr_item>value CO |0123456789| AND lr_item>value >= 1 AND lr_item>value <= 12 .

                ls_alvmonat = lr_item>value.

              ENDIF.

            WHEN OTHERS.

              CONTINUE.

          ENDCASE.

        ENDLOOP.

        APPEND ls_alv TO lt_sflight.

      ENDLOOP.

Конструкции языка ABAP используемые в коде выше:
  • replace – замена символа в строке ABAP
  • strlen – длина строки ABAP
  • LOOP AT GROUP – группировка в цикле ABAP
Быстрый вывод внутренней таблицы ABAP на экран для тестирования:

cl_demo_output=>display( lt_sflight ).

Шаблон программы ABAP загрузки данных из Excel.

Ниже привёл полный код программы загрузки для удобства копирования и тестирования:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

START-OF-SELECTION.

  TYPES:

    BEGIN OF ts_data,

      carrid    TYPE s_carr_id,

      connid    TYPE s_conn_id,

      fldate    TYPE s_date,

      price     TYPE s_price,

      currency  TYPE s_currcode,

      planetype TYPE s_planetye,

      seatsmax  TYPE s_seatsmax,

      seatsocc  TYPE s_seatsocc,

      gjahr     TYPE gjahr,

      monat     TYPE monat,

    END OF ts_data.

  DATA:

    lt_sflight TYPE STANDARD TABLE OF ts_data,

    lt_intern  TYPE TABLE OF alsmex_tabline.

  IF p_file IS NOT INITIAL.

    CALL FUNCTION ‘ALSM_EXCEL_TO_INTERNAL_TABLE’

      EXPORTING

        filename                = CONV rlgrapfilename( p_file )

        i_begin_col             = 1

        i_begin_row             = 2

        i_end_col               = 10

        i_end_row               = 10000

      TABLES

        intern                  = lt_intern

      EXCEPTIONS

        inconsistent_parameters = 1

        upload_ole              = 2

        OTHERS                  = 3.

    IF sysubrc = 0.

      LOOP AT lt_intern INTO DATA(ls_intern)

        GROUP BY ( row = ls_internrow )

        REFERENCE INTO DATA(lr_grp).

        DATA(ls_alv) = VALUE ts_data( ).

        LOOP AT GROUP lr_grp REFERENCE INTO DATA(lr_item).

          CHECK lr_item>value IS NOT INITIAL.

          CASE lr_item>col.

            WHEN 1.

              ls_alvcarrid = lr_item>value.

            WHEN 2.

              ls_alvconnid = lr_item>value.

            WHEN 3.

              ls_alvfldate = |{ lr_item>value+6(4) }{ lr_item>value+3(2) }{ lr_item>value(2) }|. » 29.04.2015 20150429

            WHEN 4.

              lr_item>value = replace( val = lr_item>value regex =‘[,]’ with = ‘.’ occ = 0 ). » 427,94

              ls_alvprice = lr_item>value.

            WHEN 5.

              ls_alvcurrency = lr_item>value.

            WHEN 6.

              ls_alvplanetype = lr_item>value.

            WHEN 7.

              ls_alvseatsmax = lr_item>value.

            WHEN 8.

              IF strlen( lr_item>value ) > 10.

                ls_alvseatsocc = lr_item>value.

              ENDIF.

            WHEN 9.

              IF lr_item>value CO |0123456789| AND lr_item>value >= 1 AND lr_item>value <= 9999.

                ls_alvgjahr = lr_item>value.

              ENDIF.

            WHEN 10.

              IF lr_item>value CO |0123456789| AND lr_item>value >= 1 AND lr_item>value <= 12 .

                ls_alvmonat = lr_item>value.

              ENDIF.

            WHEN OTHERS.

              CONTINUE.

          ENDCASE.

        ENDLOOP.

        APPEND ls_alv TO lt_sflight.

      ENDLOOP.

    ENDIF.

    cl_demo_output=>display( lt_sflight ).

  ENDIF.

Если статья оказалась Вам полезна поддержите проект. Спасибо!

Сайт ABAP программирование YouCoder – это сборник статей и видео о языке программирования ABAP и работе в SAP системе. Есть как уроки abap для начинающих так и новый синтаксис в ABAP и SAP обучение для консультантов SAP.

Upload Excel File to internal table in SAP using the standard FM TEXT_CONVERT_XLS_TO_SAP is a common business requirement for fast upload data or mass data manipulation.

Find also a full ABAP Program, just copy and paste it and start playing with Excel.

The simplest way is to use standard function TEXT_CONVERT_XLS_TO_SAP

  • i_line_header: defines if the file has a header line (column for title)
  • i_filename : set the filename
  • i_tab_converted_data : is the internal table containing data from Excel file.

SAP Upload Excel File to ABAP Internal Table

Here a sample ABAP Program to upload Excel file to internal table in sap. It will take an Excel file as input and import the content to an ABAP internal table.

The step-step guide is :

  1. Call the Function F4_FILENAME: This function will help select the Excel file from your local driver.
  2. Call to the magical standard SAP TEXT_CONVERT_XLS_TO_SAP.
    Look above for the Function TEXT_CONVERT_XLS_TO_SAP signature and description.
    These function will return the data in Excel into SAP internal table.
  3. Display Excel content with a sample Write Structure.
    Do whatever you want with the data.

ABAP Report to Upload Excel File in SAP

Here a sample ABAP Report ready to be copied and which, hopefully, will help you as a skeleton for your Excel File processing in SAP.
In fact, this ABAP code will

  • upload an Excel File for Local (using the F4_FILENAME to select the Excel file)
  • and transfer all the Excel data to ABAP internal Table using TEXT_CONVERT_XLS_TO_SAP (to be displayed later).

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

TYPEPOOLS: truxs.

PARAMETERS: p_file TYPE  rlgrapfilename.

PARAMETERS: p_head TYPE char01 DEFAULT ‘X’.

TYPES: BEGIN OF t_datatab,

      col1(30)    TYPE c,

      col2(30)    TYPE c,

      col3(30)    TYPE c,

      END OF t_datatab.

DATA: it_datatab TYPE STANDARD TABLE OF t_datatab,

      wa_datatab TYPE t_datatab.

DATA: it_raw TYPE truxs_t_text_data.

* At selection screen

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.

  CALL FUNCTION ‘F4_FILENAME’

    EXPORTING

      field_name = ‘P_FILE’

    IMPORTING

      file_name  = p_file.

START-OF-SELECTION.

  » Convert Excel Data to SAP internal Table Data

  CALL FUNCTION ‘TEXT_CONVERT_XLS_TO_SAP’

    EXPORTING

*     I_FIELD_SEPERATOR        =

      i_line_header            =  p_head

      i_tab_raw_data           =  it_raw       » WORK TABLE

      i_filename               =  p_file

    TABLES

      i_tab_converted_data     = it_datatab[]  «ACTUAL DATA

   EXCEPTIONS

      conversion_failed        = 1

      OTHERS                   = 2.

  IF sysubrc <> 0.

    MESSAGE ID symsgid TYPE symsgty NUMBER symsgno

            WITH symsgv1 symsgv2 symsgv3 symsgv4.

  ENDIF.

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

* END-OF-SELECTION.

END-OF-SELECTION.

  » For sample, Excel Data transfered to internal table is displayed with write

  LOOP AT it_datatab INTO wa_datatab.

    WRITE:/ wa_datatabcol1,

            wa_datatabcol2,

            wa_datatabcol3.

  ENDLOOP.

Managing Excel file with ABAP: ABAP2XLSX

If you want to go further with Excel in SAP, have a look on the SAPLINK ABAP2XLSX. It is available in GitHub.
I have already used it with a productive project, and I was surprised with how many opportunities it gives.

For example, you can manage very easily the formatting of Cell with the ABAP2XLSX classes.
Handling Data to and from Excel, is a way more completed and easily using the predefined methods.

Preface – This post is part of the ABAP Programs series.

To perform ABAP excel upload using ABAP report, we need to call a FM ‘TEXT_CONVERT_XLS_TO_SAP’. This FM converts the excel data to ABAP data. Now we can store the same in our internal table and later in our database table. The only mandatory requirement is that the table fields should match the header of excel in a synchronous way, else wrong data will be saved.

Introduction

Many times we need to upload an excel data from our local storage on PC and insert those data into our ABAP tables. This can be easily achieved using ABAP Function Module ‘TEXT_CONVERT_XLS_TO_SAP’. In the given program we convert our excel data into ABAP data and insert those data in our ztable.

ABAP Excel Upload

ABAP Excel Upload – Image Illustration of process

ABAP Program

TYPE-POOLS truxs.
PARAMETERS p_file TYPE rlgrap-filename.
TYPES : BEGIN OF t_tab,
          filename TYPE char100sm,
        END OF t_tab.
DATA : t_upload  TYPE STANDARD TABLE OF t_tab, 
       wa_upload TYPE t_tab,
       it_type   TYPE truxs_t_text_data.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  CALL FUNCTION 'F4_FILENAME'
    EXPORTING
      field_name = 'p_file'
    IMPORTING
      file_name  = p_file.
START-OF-SELECTION.
  CALL FUNCTION 'TEXT_CONVERT_XLS_TO_SAP'
    EXPORTING
      i_tab_raw_data       = it_type
      i_filename           = p_file
    TABLES
      i_tab_converted_data = t_upload[]
    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 .
  ENDIF.
END-OF-SELECTION.
  DATA : ls_cc_impl TYPE zBarry_upload,
         lt_cc_impl TYPE STANDARD TABLE OF  zBarry_upload.
  LOOP AT t_upload INTO wa_upload.
    ls_cc_impl-mandt      = sy-mandt.
    ls_cc_impl-filename   = wa_upload-filename.
    APPEND ls_cc_impl TO lt_cc_impl.
  ENDLOOP.
  MODIFY zBarry_upload FROM TABLE lt_cc_impl.

Table and Excel

Excel Data for Upload in ABAP Table

Excel Data for Upload in ABAP Table

Upload Excel Data

Upload Excel Data

Explanation

In the above program, we have implemented the following steps:

  1. Initially, we have defined TYPE-POOLS truxs. TYPE-POOLS have predefined methods that can be reused in multiple programs. Here we are using truxs, that is used later as truxs_t_text_data, a data type.
  2. Now, we have define parameters: p_file. This will be used to take the file location as input.
  3. Later, we have defined variables: t_tab which is a table type, t_upload, wa_upload and it_type.
  4. Now, we have called a function module “F4_FILENAME” to process the file upload.
  5. Then, we have called another function module ‘TEXT_CONVERT_XLS_TO_SAP’ to get the ABAP form of data into an internal table.
  6. Once we have our data in an internal table, then we can easily append it to our data base table using loop.

Понравилась статья? Поделить с друзьями:
  • A word приложение купить
  • A word without you слова
  • A word without clothes
  • A word with you today
  • A word with you ministries