Pages

Wednesday 27 November 2013

Program Displaying Data Custom Table in a Specific Excel Template Using BDS

Program ini merupakan ujicoba sekaligus latihan menarik data table, menampilkannya pada sebuah template excel menggunakan class BDS dan SAPOFFICEINTEGRATION. Latihan ini saya mengikuti step-step pada tutorial BDS di : http://www.saptechnical.com/Tutorials/OOPS/BDS/Index.htm.

Langkah-langkahnya :  


1. Persiapkan Excel Template yang akan digunakan dan simpan di lokal directory dengan extensi .xls.







   

2. Membuat class BDS lewat TCODE SBDSV1, isikan parameter berikut.

3.  Upload excel template lewat TCODE OAOR. Masukkan nama class yang sudah dibuat, Class type : OT (Other), dan Object key. Klik Activate.

Double click Table Template in Create Tab. Kemudian pilih template excel yang sudah kita buat.



 















Masukkan nama description. 

















4. Create sebuah custom table dan isi contoh data. Pada contoh ini saya membuat table yang berisi atribut pegawai.

Mandt   (MANDT)   PK
NIK     (Char 10) PK
Name    (Char 40)
Age     (INT1)
Email   (Char 40)







 




5. Create program untuk menampilkan data di excel menggunakan class BDS.

*&---------------------------------------------------------------------*
*& Report  ZTEST_BDS01
*&---------------------------------------------------------------------*
*& Demo program for displaying table data in a specific excel template
*& using BDS. Also, reads the contents modified by user again into ABAP
*& program after validations and updates the table.
*&---------------------------------------------------------------------*
REPORT  ztest_bds01.

*----------------------------------------------------------------------
* Data Declaration
*----------------------------------------------------------------------
* Custom Table With 4 fields
* NIK  (PK), NAME, AGE, EMAIL

TABLES: ztest_bds.

TYPES: BEGIN OF ty_emp,
        nik    TYPE ztest_bds-nik,
        name   TYPE ztest_bds-name,
        age    TYPE ztest_bds-age,
        email  TYPE ztest_bds-email,
       END OF ty_emp.

TYPES: BEGIN OF ty_data,
         num TYPE i.
INCLUDE TYPE ty_emp.
TYPES: END OF ty_data.

DATA: lt_emp     TYPE TABLE OF ty_emp WITH HEADER LINE,
      lt_data    TYPE TABLE OF ty_data WITH HEADER LINE,
      wf_entries  TYPE i.

TYPE-POOLS: soi,
            sbdst.

DATA: r_document  TYPE REF TO cl_bds_document_set,
      r_container TYPE REF TO cl_gui_custom_container,
      r_excel     TYPE REF TO i_oi_spreadsheet,
      r_control   TYPE REF TO i_oi_container_control,
      r_proxy     TYPE REF TO i_oi_document_proxy,
      r_error     TYPE REF TO i_oi_error,
      wf_retcode  TYPE soi_ret_string.

*----------------------------------------------------------------------
* Selection Screen
*----------------------------------------------------------------------
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME.
* User will enter the agent ids to be modified
SELECT-OPTIONS: s_nik FOR ztest_bds-nik OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME.
* Details of table template in BDS to be entered
PARAMETERS: p_clsnam  TYPE sbdst_classname  DEFAULT 'ZHR_TESTBDS'    OBLIGATORY,
            p_clstyp  TYPE sbdst_classtype  DEFAULT 'OT'             OBLIGATORY,
            p_objkey  TYPE sbdst_object_key DEFAULT 'TPL01'           OBLIGATORY,
            p_desc    TYPE char255          DEFAULT 'TPLBDS01' OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b2.


*----------------------------------------------------------------------
* START OF SELECTION
*----------------------------------------------------------------------
START-OF-SELECTION.
* Call Excel Inplace Display
  CALL SCREEN 100. "Create a screen 100 with custom container 'EXCEL'

*----------------------------------------------------------------------
* SCREEN LOGIC
*----------------------------------------------------------------------
*&---------------------------------------------------------------------*
*&      Module  STATUS_0100  OUTPUT
*&---------------------------------------------------------------------*
MODULE status_0100 OUTPUT.

  SET PF-STATUS 'ZSTANDARD'.   "Enable SAVE, BACK, EXIT, CANCEL
  SET TITLEBAR  'TITLE100'.  "Set title

* Get table data
  PERFORM f_get_table_data.

* Open the excel template in BDS in-place
  PERFORM f_open_document USING p_clsnam
                                p_clstyp
                                p_objkey
                                p_desc.

* Display table data in the excel template
  PERFORM f_dis_table_data.

* Protect the whole sheet except the editable fields
  PERFORM f_protect_sheet.

ENDMODULE.                 " STATUS_0100  OUTPUT

*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
MODULE user_command_0100 INPUT.

  CASE sy-ucomm.
    WHEN 'BACK' OR 'EXIT' OR 'CANCEL' OR '&F03'.
* Close document
      PERFORM f_close_document.
      LEAVE TO SCREEN 0.
    WHEN '&SAVE'.
* Save the modified entries into database
      PERFORM f_save_document.
  ENDCASE.

ENDMODULE.                 " USER_COMMAND_0100  INPUT

*----------------------------------------------------------------------
* SUBROUTINES
*----------------------------------------------------------------------
*&---------------------------------------------------------------------*
*&      Form  f_get_table_data
*&---------------------------------------------------------------------*
*       Get fresh data from YSM_AGENTS
*----------------------------------------------------------------------*
FORM f_get_table_data .

DATA: l_counter TYPE i.
FIELD-SYMBOLS : <fs> TYPE ty_emp.

* Get all the agents from table
  SELECT   nik
           name
           age
           email
      FROM ztest_bds
       INTO TABLE lt_emp
        WHERE nik IN s_nik.

  IF sy-subrc NE 0.
    MESSAGE 'No Agent Details Found' TYPE 'E'.
  ELSE.
    CLEAR l_counter.
    UNASSIGN <fs>.
    LOOP AT lt_emp ASSIGNING <fs>.
      ADD 1 TO l_counter.
      lt_data-num    = l_counter.
      lt_data-nik    = <fs>-nik.
      lt_data-name   = <fs>-name.
      lt_data-age    = <fs>-age.
      lt_data-email  = <fs>-email.
      APPEND lt_data.
    ENDLOOP.
  ENDIF.

* Get the no of rows to be displayed
  DESCRIBE TABLE lt_emp LINES wf_entries.

ENDFORM.                    " f_get_table_data

*&---------------------------------------------------------------------*
*&      Form  f_open_document
*&---------------------------------------------------------------------*
*       Open the table template from BDS
*----------------------------------------------------------------------*
*  -->  l_clsnam         Class Name in OAOR
*  -->  l_clstyp         Class Type in OAOR
*  -->  l_objkey         Object key in OAOR
*  -->  l_desc           Description of the excel template in OAOR
*----------------------------------------------------------------------*
FORM f_open_document USING l_clsnam TYPE sbdst_classname
                           l_clstyp TYPE sbdst_classtype
                           l_objkey TYPE sbdst_object_key
                           l_desc   TYPE char255.

  DATA: locint_signature   TYPE sbdst_signature,
        locint_uris        TYPE sbdst_uri,
        locwa_signature    LIKE LINE OF locint_signature,
        locwa_uris         LIKE LINE OF locint_uris.

  IF NOT r_document IS INITIAL.
    RETURN.
  ENDIF.

* Create container control
  CALL METHOD c_oi_container_control_creator=>get_container_control
    IMPORTING
      control = r_control
      retcode = wf_retcode.

  IF wf_retcode NE c_oi_errors=>ret_ok.
    CALL METHOD c_oi_errors=>raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

* Initialize Custom Control
  CREATE OBJECT r_container
    EXPORTING
      container_name = 'CC_EXCEL'. "Custom Control Name

  CALL METHOD r_control->init_control
    EXPORTING
      r3_application_name      = 'EXCEL INPLACE BDS'
      inplace_enabled          = abap_true
      inplace_scroll_documents = abap_true
      parent                   = r_container
    IMPORTING
      retcode                  = wf_retcode.

  IF wf_retcode NE c_oi_errors=>ret_ok.
    CALL METHOD c_oi_errors=>raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

* Create object for cl_bds_document_set
  CREATE OBJECT r_document.

* Get Document with URL
  locwa_signature-prop_name  = 'DESCRIPTION'.
* Description of the table template in OAOR
  locwa_signature-prop_value = l_desc.
  APPEND locwa_signature TO locint_signature.

  CALL METHOD r_document->get_with_url
    EXPORTING
      classname       = l_clsnam
      classtype       = l_clstyp
      object_key      = l_objkey
    CHANGING
      uris            = locint_uris
      signature       = locint_signature
    EXCEPTIONS
      nothing_found   = 1
      error_kpro      = 2
      internal_error  = 3
      parameter_error = 4
      not_authorized  = 5
      not_allowed     = 6.

  IF sy-subrc NE 0.
    MESSAGE 'Error Retrieving Document' TYPE 'S' DISPLAY LIKE 'E'.
    EXIT.
  ENDIF.

  READ TABLE locint_uris INTO locwa_uris INDEX 1.

  CALL METHOD r_control->get_document_proxy
    EXPORTING
      document_type  = 'Excel.Sheet'
    IMPORTING
      document_proxy = r_proxy
      retcode        = wf_retcode.

  IF wf_retcode NE c_oi_errors=>ret_ok.
    CALL METHOD c_oi_errors=>show_message
      EXPORTING
        type = 'E'.
  ENDIF.

* Open Document
  CALL METHOD r_proxy->open_document
    EXPORTING
      document_url     = locwa_uris-uri
      open_inplace     = abap_true
      protect_document = abap_true "Protect Document initially
    IMPORTING
      retcode          = wf_retcode.

  IF wf_retcode NE c_oi_errors=>ret_ok.
    CALL METHOD c_oi_errors=>show_message
      EXPORTING
        type = 'E'.
  ENDIF.

* Get Excel Interface
  CALL METHOD r_proxy->get_spreadsheet_interface
    IMPORTING
      sheet_interface = r_excel
      retcode         = wf_retcode.

  IF wf_retcode NE c_oi_errors=>ret_ok.
    CALL METHOD c_oi_errors=>show_message
      EXPORTING
        type = 'E'.
  ENDIF.

ENDFORM.                    " f_open_document

*&---------------------------------------------------------------------*
*&      Form  f_dis_table_data
*&---------------------------------------------------------------------*
*       Display data in table template
*----------------------------------------------------------------------*
FORM f_dis_table_data .

  DATA: locint_fields TYPE TABLE OF rfc_fields.

* Create a range to insert data
  PERFORM f_create_range USING 9             "Begin on 9th row
                               2             "Begin on 2nd col
                               wf_entries    "No of rows reqd
                               5             "No of cols reqd
                               'AGENTS'.     "Range name
*-> Set Frame to the range
*# Calculation of TYP parameter
* The parameter has 8 bits
*0 Sets the left margin
*1 Sets the top margin
*2 Sets the bottom margin
*3 Sets the right margin
*4 Horizontal line
*5 Sets the left margin
*6 Thickness
*7 Thickness
* My figure will be 7 6 5 4 3 2 1 0
*                   1 0 1 1 1 1 1 1
* Binary 1011 1111 stands for 191 in decimal
* Check SAP help for more info.....
* http://help.sap.com/saphelp_NW04s/helpdata/en/
  " 21/b531bfe1ba11d2bdbe080009b4534c/frameset.htm

  CALL METHOD r_excel->set_frame
    EXPORTING
      rangename = 'AGENTS'
      typ       = 191
      color     = 21
    IMPORTING
      error     = r_error
      retcode   = wf_retcode.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

* Get field attributes of the table to be displayed
  CALL FUNCTION 'DP_GET_FIELDS_FROM_TABLE'
    TABLES
      data             = lt_data
      fields           = locint_fields
    EXCEPTIONS
      dp_invalid_table = 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.

* Insert the table entries into Excel
  CALL METHOD r_excel->insert_one_table
    EXPORTING
      fields_table = locint_fields[]  "Defn of fields
      data_table   = lt_data[]     "Data
      rangename    = 'AGENTS'         "Range Name
    IMPORTING
      error        = r_error
      retcode      = wf_retcode.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

ENDFORM.                    " f_dis_table_data

*&---------------------------------------------------------------------*
*&      Form  f_protect_sheet
*&---------------------------------------------------------------------*
*       Protect the whole sheet except the fields to edited
*----------------------------------------------------------------------*
FORM f_protect_sheet .

  DATA: loc_protect      TYPE c,
        loc_sheetname    TYPE char31.

* Check whether the sheet is protected
*  in case it's unprotected manually
  CALL METHOD r_excel->get_active_sheet
    IMPORTING
      sheetname = loc_sheetname
      error     = r_error
      retcode   = wf_retcode.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

  CALL METHOD r_excel->get_protection
    EXPORTING
      sheetname = loc_sheetname   "Active sheet name
    IMPORTING
      error     = r_error
      retcode   = wf_retcode
      protect   = loc_protect.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ELSE.
* If not protected, protect the sheet
    IF loc_protect NE abap_true.
      CALL METHOD r_excel->protect
        EXPORTING
          protect = abap_true
        IMPORTING
          error   = r_error
          retcode = wf_retcode.

      IF r_error->has_failed = abap_true.
        CALL METHOD r_error->raise_message
          EXPORTING
            type = 'E'.
      ENDIF.
    ENDIF.
  ENDIF.

* The user should not be allowed to change the primary fields.
* The sheet is protected against change and a particular range will
* be unprotected for editing

* Create a range to enable editing for non key fields
  PERFORM f_create_range USING 9           "Begin on 9th row
                               4           "Begin on 4th col
                               wf_entries  "No of rows reqd
                               3           "Only 3 columns are editable
                               'EDIT'.     "Range name

* Unprotect the range for editing
  CALL METHOD r_excel->protect_range
    EXPORTING
      name    = 'EDIT'
      protect = space
    IMPORTING
      error   = r_error
      retcode = wf_retcode.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

*->Set colour to editable range
*# Check SAP help link for colour codes
* http://help.sap.com/saphelp_NW04s/helpdata/en
  "/21/b531bfe1ba11d2bdbe080009b4534c/frameset.htm
  CALL METHOD r_excel->set_color
    EXPORTING
      rangename = 'EDIT'
      front     = 1
      back      = 4
    IMPORTING
      error     = r_error
      retcode   = wf_retcode.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

ENDFORM.                    " f_protect_sheet
*&---------------------------------------------------------------------*
*&      Form  f_close_document
*&---------------------------------------------------------------------*
*       Close the document when user leaves the program
*----------------------------------------------------------------------*
FORM f_close_document .

* Close document
  IF NOT r_proxy IS INITIAL.
    CALL METHOD r_proxy->close_document
      IMPORTING
        error   = r_error
        retcode = wf_retcode.

    IF r_error->has_failed = abap_true.
      CALL METHOD r_error->raise_message
        EXPORTING
          type = 'E'.
    ENDIF.
  ENDIF.

ENDFORM.                    " f_close_document

*&---------------------------------------------------------------------*
*&      Form  f_save_document
*&---------------------------------------------------------------------*
*       Save the modified entries into database table
*----------------------------------------------------------------------*
FORM f_save_document .

  DATA: locint_ranges      TYPE soi_range_list,
        locwa_ranges       TYPE soi_range_item,
        locint_moddata     TYPE soi_generic_table,
        locwa_moddata      TYPE soi_generic_item,
        loclt_emp_mod  TYPE TABLE OF ztest_bds,
        locwa_agents_mod   TYPE ztest_bds,
        loc_error_row      TYPE i.

* Initialize the colour of the editable range
  CALL METHOD r_excel->set_color
    EXPORTING
      rangename = 'EDIT'
      front     = 1
      back      = 4
    IMPORTING
      error     = r_error
      retcode   = wf_retcode.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

* Define the range from which data needs to be read
  locwa_ranges-name    = 'AGENTS'.
  locwa_ranges-rows    = wf_entries.
  locwa_ranges-columns = 3.
  APPEND locwa_ranges TO locint_ranges.

* Get modified data
  CALL METHOD r_excel->get_ranges_data
    IMPORTING
      contents = locint_moddata
      error    = r_error
    CHANGING
      ranges   = locint_ranges.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ENDIF.

  LOOP AT locint_moddata INTO locwa_moddata.
    CASE locwa_moddata-column.
      WHEN 1.
        locwa_agents_mod-nik = locwa_moddata-value.
      WHEN 2.
        locwa_agents_mod-name    = locwa_moddata-value.
      WHEN 3.
        locwa_agents_mod-email   = locwa_moddata-value.

*-> Validate the email id entered

* Get the current row no taking account the rows
*  in the sheet above the range
        loc_error_row = locwa_moddata-row + 8.
        PERFORM f_validate_email USING locwa_agents_mod-email
                                       loc_error_row.
    ENDCASE.

    AT END OF row.
      locwa_agents_mod-mandt = sy-mandt.
      APPEND locwa_agents_mod TO loclt_emp_mod.
      CLEAR  locwa_agents_mod.
    ENDAT.

  ENDLOOP.

* Update Table
  MODIFY ztest_bds FROM TABLE loclt_emp_mod.
  COMMIT WORK.

  IF sy-subrc EQ 0.
    MESSAGE 'DATA UPDATED' TYPE 'S'.
  ELSE.
    MESSAGE 'DATA NOT UPDATED' TYPE 'E'.
  ENDIF.

ENDFORM.                    " f_save_document

*&---------------------------------------------------------------------*
*&      Form  f_validate_email
*&---------------------------------------------------------------------*
*       Validate the email id entered
*----------------------------------------------------------------------*
*      -->l_email  Email Id
*----------------------------------------------------------------------*
FORM f_validate_email  USING    l_email   TYPE c
                                l_err_row TYPE i.

  TYPE-POOLS:sx.
  DATA: locwa_address TYPE sx_address.

* Check Email Id
  locwa_address-type = 'INT'.
  locwa_address-address = l_email.

  CALL FUNCTION 'SX_INTERNET_ADDRESS_TO_NORMAL'
    EXPORTING
      address_unstruct    = locwa_address
    EXCEPTIONS
      error_address_type  = 1
      error_address       = 2
      error_group_address = 3
      OTHERS              = 4.

  IF sy-subrc <> 0.

* Create a range to highlight the error cell
    PERFORM f_create_range USING l_err_row
                                 5   "Column no for email id
                                 1
                                 1
                                 'ERROR'.

* Display the error cell in red
    CALL METHOD r_excel->set_color
      EXPORTING
        rangename = 'ERROR'
        front     = 1
        back      = 3
      IMPORTING
        error     = r_error
        retcode   = wf_retcode.

    IF r_error->has_failed = abap_true.
      CALL METHOD r_error->raise_message
        EXPORTING
          type = 'E'.
    ENDIF.

    MESSAGE 'Invalid Email Address' TYPE 'E'.
  ENDIF.

ENDFORM.                    " f_validate_email
*&---------------------------------------------------------------------*
*&      Form  f_create_range
*&---------------------------------------------------------------------*
*       Create a range dynamically in excel sheet
*----------------------------------------------------------------------*
*      -->l_top       Begin on row
*      -->l_left      Begin on column
*      -->l_row       No of rows
*      -->l_column    No of columns
*      -->l_range     Range Name
*----------------------------------------------------------------------*
FORM f_create_range  USING  l_top    TYPE i
                            l_left   TYPE i
                            l_row    TYPE i
                            l_column TYPE i
                            l_range  TYPE char255.


* Select area for entries to be displayed
  CALL METHOD r_excel->set_selection
    EXPORTING
      top     = l_top
      left    = l_left
      rows    = l_row
      columns = l_column.

* Define Range
  CALL METHOD r_excel->insert_range
    EXPORTING
      name    = l_range
      rows    = l_row
      columns = l_column
    IMPORTING
      error   = r_error.

  IF r_error->has_failed = abap_true.
    CALL METHOD r_error->raise_message
      EXPORTING
        type = 'E'.
  ENDIF.


ENDFORM.                    " f_create_range

Result.

No comments:

Post a Comment