Showing posts with label ABAP Development. Show all posts
Showing posts with label ABAP Development. Show all posts

Thursday, 9 November 2017

ABAP Performance Test: Hashed Tables vs Database Buffers

There are two significant techniques to avoid repetitive access to database records: Hashed internal tables and database buffers.

If we decide to use the former method, we need to get the database record into a hashed internal table. Whenever we need to access the record, we read the internal table instead of the database table.

If we decide to use the latter method, all we need to do is to activate the table buffer in SE11. If we do that, the accessed data is cached on the application server, and the cache is used whenever possible. Thus, database access is reduced. There are exceptional cases where the buffer is bypassed, but that’s beyond the scope of this article.

Wondering how they compare in terms of performance, I created a fully buffered database table with example data.

SAP ABAP Development, SAP ABAP Guides, SAP Live, SAP Certifications

I also wrote a program, which accesses the data using both techniques and compares the runtime.

It turns out that hashed access is 3-4 times faster than database buffering.

SAP ABAP Development, SAP ABAP Guides, SAP Live, SAP Certifications

You can use the attached source code yourself and repeat the test; I would like to hear about any disproving results.

REPORT  zdummy01.

CLASS main DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS execute.
  PROTECTED SECTION.
  PRIVATE SECTION.

    CONSTANTS:
      c_do_times TYPE i     VALUE 100,
      c_matnr    TYPE matnr VALUE 'M1'.

    CLASS-DATA:
      go_text  TYPE REF TO cl_demo_text,
      gv_begin TYPE i.

    CLASS-METHODS:
      hash,
      select,
      start_chrono,
      stop_chrono.

ENDCLASS.                    "main DEFINITION

CLASS main IMPLEMENTATION.

  METHOD execute.

    go_text = cl_demo_text=>get_handle( ).

    start_chrono( ).
    hash( ).
    stop_chrono( ).

    start_chrono( ).
    select( ).
    stop_chrono( ).

    go_text->display( ).

  ENDMETHOD.                    "execute

  METHOD hash.

    DATA:
      lt_dummy
        TYPE HASHED TABLE OF zdummy01
        WITH UNIQUE KEY primary_key COMPONENTS matnr.

    FIELD-SYMBOLS:
      <ls_dummy> LIKE LINE OF lt_dummy.

    go_text->add_line( 'Starting hash read' ).

    SELECT * INTO TABLE lt_dummy FROM zdummy01.

    DO c_do_times TIMES.

      READ TABLE lt_dummy
        ASSIGNING <ls_dummy>
        WITH TABLE KEY primary_key
        COMPONENTS matnr = c_matnr.

    ENDDO.

  ENDMETHOD.                    "hash

  METHOD select.

    DATA ls_dummy TYPE zdummy01.

    go_text->add_line( 'Starting select' ).

    DO c_do_times TIMES.

      SELECT SINGLE *
        INTO ls_dummy
        FROM zdummy01
        WHERE matnr EQ c_matnr.

    ENDDO.

  ENDMETHOD.                    "select

  METHOD start_chrono.
    GET RUN TIME FIELD gv_begin.
  ENDMETHOD.                    "start_chrono

  METHOD stop_chrono.

    DATA:
      lv_diff  TYPE i,
      lv_difft TYPE cl_demo_text=>t_line,
      lv_end   TYPE i.

    GET RUN TIME FIELD lv_end.
    lv_diff = lv_end - gv_begin.
    WRITE lv_diff TO lv_difft LEFT-JUSTIFIED.

    go_text->add_line(:
      'Runtime result:' ),
      lv_difft ).

  ENDMETHOD.                    "stop_chrono

ENDCLASS.                    "main IMPLEMENTATION

START-OF-SELECTION.
  main=>execute( ).

Wednesday, 4 October 2017

Dynamic Programming in ABAP: Part 3 – An Example – ABAP RTTS

In my last blog I explained about the significance of field symbol and data references in dynamic programming.

https://saponlineguides.blogspot.in/2017/09/dynamic-programming-in-abap-part-1-introduction-to-field-symbols.html

https://saponlineguides.blogspot.in/2017/09/dynamic-programming-in-abap-part-2-introduction-to-data-reference.html

SAP ABAP RTTS, SAP Guides, SAP ABAP Learning, SAP Certifications

Now here we will see one example of dynamic programming approach and also a brief introduction to ABAP RTTS.

ABAP Runtime Type Services (RTTS) consists of two components:

◉ Runtime Type Identification (RTTI) – Provides the methods to get the type definition of data objects at runtime.

◉ Runtime Type Creation (RTTC) – Provides the methods to create the data objects at runtime with any type definition.

Basically, ABAP RTTS provides a set of classes, whose methods can be used for runtime type identification and runtime type creation. To know more about ABAP RTTS you can follow below link:

https://wiki.scn.sap.com/wiki/pages/viewpage.action?pageId=42965


An example of dynamic programming:


Requirement: As an ABAP developer, very often we get the situation where we need to write data from an internal table to a file on application server.

Solution: We will build one class having a method which will take any internal table as input and write its content in a file on application server.

Class Definition:

CLASS cl_appserver_writer DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: write IMPORTING
                           iv_filename  TYPE string
                           it_data      TYPE ANY TABLE
                           write_header TYPE abap_bool DEFAULT space
                         EXPORTING
                           ev_message   TYPE string.
ENDCLASS.

Here importing parameter it_data is of TYPE ANY TABLE so that it can receive any internal table.

Class Implementation:

CLASS cl_appserver_writer IMPLEMENTATION.
  METHOD write.
    TYPES: BEGIN OF ty_comp_detail,
             name  TYPE abap_compname,
             descr TYPE scrtext_m,
           END OF ty_comp_detail.
    DATA: lo_type_def    TYPE REF TO cl_abap_typedescr.
    DATA: lo_struct_def  TYPE REF TO cl_abap_structdescr.
    DATA: lo_table_def   TYPE REF TO cl_abap_tabledescr.
    DATA: lo_data_def    TYPE REF TO cl_abap_datadescr.
    DATA: lo_element_def TYPE REF TO cl_abap_elemdescr.
    DATA: lt_components  TYPE abap_compdescr_tab.
    DATA: wa_components  LIKE LINE OF lt_components.
    DATA: lv_str         TYPE string.
    DATA: lv_filerow     TYPE string.
    DATA: lv_counter     TYPE i VALUE 0.
    DATA: lw_field_info  TYPE dfies.
    DATA: ls_comp_detail TYPE ty_comp_detail.
    DATA: lt_comp_detail TYPE TABLE OF ty_comp_detail.

    FIELD-SYMBOLS: <row> TYPE any.
    FIELD-SYMBOLS: <field_value> TYPE any.

* Using RTTS to get the runtime type information of the internal table
    lo_type_def  = cl_abap_tabledescr=>describe_by_data( it_data ).
    lo_table_def ?= lo_type_def.
    lo_data_def = lo_table_def->get_table_line_type( ).
    lo_struct_def ?= lo_data_def.

* Get the components of the structure
    lt_components = lo_struct_def->components.

    CLEAR: lo_data_def.

* If the WRITE_HEADER is ABAP_TRUE then fetch the label
* of data element associated to each component of the
* line type structure of internal table, if no data element
* is associated then use component name as the header text
    IF write_header EQ abap_true.
      LOOP AT lt_components INTO wa_components.
        lo_data_def = lo_struct_def->get_component_type( wa_components-name ).
        lo_element_def ?= lo_data_def.
        lw_field_info = lo_element_def->get_ddic_field( ).
        ls_comp_detail-name = lw_field_info-rollname.  "Get the data element name

* Calling FM to get data element text
        CALL FUNCTION 'WCGW_DATA_ELEMENT_TEXT_GET'
          EXPORTING
            i_data_element = lw_field_info-rollname
            i_language     = sy-langu
          IMPORTING
            e_scrtext_m    = ls_comp_detail-descr
          EXCEPTIONS
            error          = 1.
        IF ls_comp_detail-descr IS INITIAL.
          ls_comp_detail-descr = wa_components-name.
        ENDIF.
        APPEND ls_comp_detail TO lt_comp_detail.
        CLEAR: ls_comp_detail.
      ENDLOOP.
    ENDIF.

    OPEN DATASET iv_filename FOR OUTPUT IN TEXT MODE ENCODING DEFAULT.
    IF sy-subrc EQ 0.
* Writing header text for each column separated by comma
      IF write_header EQ abap_true.
        LOOP AT lt_comp_detail INTO ls_comp_detail.
          lv_counter = lv_counter + 1.
          IF lv_counter EQ 1.
            lv_filerow = ls_comp_detail-descr.
          ELSE.
            CONCATENATE lv_filerow ',' ls_comp_detail-descr INTO lv_filerow.
          ENDIF.
        ENDLOOP.
        TRANSFER lv_filerow TO iv_filename.
        CLEAR: lv_filerow, lv_counter.
      ENDIF.

* Writing internal table content separated by comma
      LOOP AT it_data ASSIGNING <row>.
        LOOP AT lt_components INTO wa_components.
          lv_counter = lv_counter + 1.
          ASSIGN COMPONENT wa_components-name OF STRUCTURE <row> TO <field_value>.
          IF <field_value> IS ASSIGNED.
            lv_str = <field_value>.
            IF lv_counter EQ 1.
              lv_filerow = lv_str.
            ELSE.
              CONCATENATE lv_filerow ',' lv_str INTO lv_filerow.
            ENDIF.
            UNASSIGN <field_value>.
          ENDIF.
        ENDLOOP.
        TRANSFER lv_filerow TO iv_filename.
        CLEAR: lv_filerow, lv_counter.
      ENDLOOP.
      CLOSE DATASET iv_filename.
      ev_message = 'Success'.
    ELSE.
      ev_message = 'Failure'.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

Here the classes CL_ABAP_*DESCR are provided by the ABAP RTTS and used to get the type definition of data objects at runtime. Also we have extracted the data element name of each component of line type structure of internal table it_data using RTTS classes. Then we fetched the data element label using the FM WCGW_DATA_ELEMENT_TEXT_GET. This label is used to write the header for each column of internal table it_data if WRITE_HEADER parameter of class is provided with ABAP_TRUE.

Using the Class – The above designed class can be used as:

DATA: lt_data  TYPE STANDARD TABLE OF mara.
  DATA: lv_filename TYPE string.
  DATA: lv_message  TYPE string.

  SELECT * FROM mara INTO TABLE lt_data UP TO 5 ROWS.

  cl_appserver_writer=>write(
    EXPORTING
      iv_filename  = 'D:\usr\sap\testdata.csv'
      it_data      = lt_data
      write_header = abap_true
    IMPORTING
      ev_message   = lv_message
  ).

  WRITE: / lv_message.

Here we are passing one internal table of structure MARA to the class, and subsequently its content will be written on application server as comma separated values. However, we can pass internal table of any structure. This file can also be downloaded from application server to an excel spreadsheet.

So this is how field symbol, data reference, generic data type, RTTS helps in dynamic programming approach.

The complete code:


App Server Writer.txt

REPORT zwrite_appserver.

CLASS cl_appserver_writer DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: write IMPORTING
                           iv_filename  TYPE string
                           it_data      TYPE ANY TABLE
                           write_header TYPE abap_bool DEFAULT space
                         EXPORTING
                           ev_message   TYPE string.
ENDCLASS.

CLASS cl_appserver_writer IMPLEMENTATION.
  METHOD write.
    TYPES: BEGIN OF ty_comp_detail,
             name  TYPE abap_compname,
             descr TYPE scrtext_m,
           END OF ty_comp_detail.
    DATA: lo_type_def    TYPE REF TO cl_abap_typedescr.
    DATA: lo_struct_def  TYPE REF TO cl_abap_structdescr.
    DATA: lo_table_def   TYPE REF TO cl_abap_tabledescr.
    DATA: lo_data_def    TYPE REF TO cl_abap_datadescr.
    DATA: lo_element_def TYPE REF TO cl_abap_elemdescr.
    DATA: lt_components  TYPE abap_compdescr_tab.
    DATA: wa_components  LIKE LINE OF lt_components.
    DATA: lv_str         TYPE string.
    DATA: lv_filerow     TYPE string.
    DATA: lv_counter     TYPE i VALUE 0.
    DATA: lw_field_info  TYPE dfies.
    DATA: ls_comp_detail TYPE ty_comp_detail.
    DATA: lt_comp_detail TYPE TABLE OF ty_comp_detail.

    FIELD-SYMBOLS: <row> TYPE any.
    FIELD-SYMBOLS: <field_value> TYPE any.

* Using RTTS to get the runtime type information of the internal table
    lo_type_def  = cl_abap_tabledescr=>describe_by_data( it_data ).
    lo_table_def ?= lo_type_def.
    lo_data_def = lo_table_def->get_table_line_type( ).
    lo_struct_def ?= lo_data_def.
    lt_components = lo_struct_def->components.

    CLEAR: lo_data_def.

* If the WRITE_HEADER is ABAP_TRUE then fetch the label
* of data element associated to each component of the
* line type structure of internal table, if no data element
* is associated then use component name as the header text
    IF write_header EQ abap_true.
      LOOP AT lt_components INTO wa_components.
        lo_data_def = lo_struct_def->get_component_type( wa_components-name ).
        lo_element_def ?= lo_data_def.
        lw_field_info = lo_element_def->get_ddic_field( ).
        ls_comp_detail-name = lw_field_info-rollname.

* Calling FM to get data element text
        CALL FUNCTION 'WCGW_DATA_ELEMENT_TEXT_GET'
          EXPORTING
            i_data_element = lw_field_info-rollname
            i_language     = sy-langu
          IMPORTING
            e_scrtext_m    = ls_comp_detail-descr
          EXCEPTIONS
            error          = 1.
        IF ls_comp_detail-descr IS INITIAL.
          ls_comp_detail-descr = wa_components-name.
        ENDIF.
        APPEND ls_comp_detail TO lt_comp_detail.
        CLEAR: ls_comp_detail.
      ENDLOOP.
    ENDIF.


    OPEN DATASET iv_filename FOR OUTPUT IN TEXT MODE ENCODING DEFAULT.
    IF sy-subrc EQ 0.
* Writing header text for each column separated by comma
      IF write_header EQ abap_true.
        LOOP AT lt_comp_detail INTO ls_comp_detail.
          lv_counter = lv_counter + 1.
          IF lv_counter EQ 1.
            lv_filerow = ls_comp_detail-descr.
          ELSE.
            CONCATENATE lv_filerow ',' ls_comp_detail-descr INTO lv_filerow.
          ENDIF.
        ENDLOOP.
        TRANSFER lv_filerow TO iv_filename.
        CLEAR: lv_filerow, lv_counter.
      ENDIF.

* Writing internal table content separated by comma
      LOOP AT it_data ASSIGNING <row>.
        LOOP AT lt_components INTO wa_components.
          lv_counter = lv_counter + 1.
          ASSIGN COMPONENT wa_components-name OF STRUCTURE <row> TO <field_value>.
          IF <field_value> IS ASSIGNED.
            lv_str = <field_value>.
            IF lv_counter EQ 1.
              lv_filerow = lv_str.
            ELSE.
              CONCATENATE lv_filerow ',' lv_str INTO lv_filerow.
            ENDIF.
            UNASSIGN <field_value>.
          ENDIF.
        ENDLOOP.
        TRANSFER lv_filerow TO iv_filename.
        CLEAR: lv_filerow, lv_counter.
      ENDLOOP.
      CLOSE DATASET iv_filename.
      ev_message = 'Success'.
    ELSE.
      ev_message = 'Failure'.
    ENDIF.
  ENDMETHOD.
ENDCLASS.


START-OF-SELECTION.
  DATA: lt_data  TYPE STANDARD TABLE OF mara.
  DATA: lv_filename TYPE string.
  DATA: lv_message  TYPE string.

  SELECT * FROM mara INTO TABLE lt_data UP TO 5 ROWS.

  cl_appserver_writer=>write(
    EXPORTING
      iv_filename  = 'D:\usr\sap\testdata.csv'
      it_data      = lt_data
      write_header = abap_true
    IMPORTING
      ev_message   = lv_message
  ).

  WRITE: / lv_message.

Sunday, 24 September 2017

ABAP Group Operations in Internal Tables

SAP ABAP Tutorials and Materials, SAP ABAP Live, SAP Learning, SAP ABAP Certifications

First, let’s get familiar with our context. We will read the table T001K, where BWKEY (valuation area) is the table key, but BUKRS (company code) is repeated multiple times in various lines. Let’s start off by reading this table.

SELECT * INTO TABLE @DATA(gt_t001k) FROM t001k ORDER BY bukrs.

So far so good. Now, our goal is to build a list of unique BUKRS values. Using classical ABAP, this is possible via the COLLECT command.

TYPES:
  BEGIN OF t_bukrs,
    bukrs TYPE bukrs,
  END OF t_bukrs,

  tt_bukrs TYPE STANDARD TABLE OF t_bukrs WITH DEFAULT KEY.

DATA:
  gs_bukrs TYPE t_bukrs,
  gt_bukrs TYPE tt_bukrs.

LOOP AT gt_t001k ASSIGNING FIELD-SYMBOL(<gs_t001k>).
  gs_bukrs-bukrs = <gs_t001k>-bukrs.
  COLLECT gs_bukrs INTO gt_bukrs.
ENDLOOP.

If we move forward to ABAP 7.40, we can achieve the same result with a better approach:

DATA(gt_bukrs) = CORRESPONDING tt_bukrs( gt_t001k ).
SORT gt_bukrs BY bukrs.
DELETE ADJACENT DUPLICATES FROM gt_bukrs COMPARING bukrs.

However, we can reduce the code even more by using the group command.

DATA(gt_bukrs) = VALUE tt_bukrs(
  FOR GROUPS gr1 OF gs_t001k
  IN gt_t001k
  GROUP BY gs_t001k-bukrs (
    bukrs = gr1
) ).

Cool eh? Just one line of code, and you are there!

Things get cooler when you want to do operations by grouping the data in an internal table. For example; you want to write the BWKEY’s corresponding to each BUKRS. Without grouping, you would first build GT_BUKRS, and then write two nested LOOPs to achieve that.

LOOP AT gt_bukrs ASSIGNING FIELD-SYMBOL(<gs_bukrs>).

  NEW-LINE.
  WRITE AT 1(5) 'Group'.
  WRITE AT 7(20) <gs_bukrs>-bukrs.

  LOOP AT gt_t001k
    ASSIGNING FIELD-SYMBOL(<gs_t001k>)
    WHERE bukrs EQ <gs_bukrs>-bukrs.

    NEW-LINE.
    WRITE <gs_t001k>-bwkey.

  ENDLOOP.

ENDLOOP.

However; using the grouping option, you don’t even need to build GT_BUKRS. You can achieve the same goal by using GT_T001K alone.

LOOP AT gt_t001k
  INTO DATA(gs_line)
  GROUP BY ( gr_bukrs = gs_line-bukrs )
  ASCENDING
  ASSIGNING FIELD-SYMBOL(<gs_bukrs>).

  NEW-LINE.
  WRITE AT 1(5) 'Group'.
  WRITE AT 7(20) <gs_bukrs>-gr_bukrs.

  LOOP AT GROUP <gs_bukrs> ASSIGNING FIELD-SYMBOL(<gs_sub>).
    NEW-LINE.
    WRITE: <gs_sub>-bwkey.
  ENDLOOP.

ENDLOOP.

And voila! This technique can be used for multi level grouping as well. Check the following code sample:

SELECT
    ekko~ebeln,
    ekpo~ebelp, ekpo~matnr,
    eket~etenr, eket~eindt, eket~menge
  INTO TABLE @DATA(gt_all)
  FROM
    ekko
    INNER JOIN ekpo ON ekpo~ebeln EQ ekko~ebeln
    INNER JOIN eket ON
      eket~ebeln EQ ekko~ebeln AND
      eket~ebelp EQ ekpo~ebelp
  WHERE
    ekko~ebeln EQ '5500000026' OR
    ekko~ebeln EQ '5500000027'.

LOOP AT gt_all
  INTO DATA(gs_1)
  GROUP BY ( ebeln = gs_1-ebeln
             ebelp = gs_1-ebelp
           )
  ASCENDING
  ASSIGNING FIELD-SYMBOL(<gs_all>).

  NEW-LINE.
  WRITE:
    'Outer loop for ',
    <gs_all>-ebeln,
    <gs_all>-ebelp.

  LOOP AT GROUP <gs_all>
    INTO DATA(gs_2)
    GROUP BY ( ebeln = <gs_all>-ebeln )
    ASCENDING
    ASSIGNING FIELD-SYMBOL(<gs_sub>).

    NEW-LINE.
    WRITE:
      'Inner loop for ',
      <gs_sub>-ebeln.

  ENDLOOP.
ENDLOOP.

GROUP command has many further applications in internal table operations, which I might write in more detail someday. You can check Google or ABAP help for further use.

Friday, 22 September 2017

Wonders in ABAP Editor SE38

I was wondering in ABAP editor se38.

See the below screen shots..

SAP ABAP Tutorial and Material, SAP Certifications, SAP Guides, SAP Learning, SAP SE38, SAP Module, SAP All Modules

SAP ABAP Tutorial and Material, SAP Certifications, SAP Guides, SAP Learning, SAP SE38, SAP Module, SAP All Modules

From the above screen shots the  program name’s are different while checking it is not throwing any syntax error.

As well As i didn’t pass any report name like below screen shots, but it did not throw any syntax error.

SAP ABAP Tutorial and Material, SAP Certifications, SAP Guides, SAP Learning, SAP SE38, SAP Module, SAP All Modules

I gave the following report name which i already created ZRTEST_REP_KEY1 then i want find the program using the where used list it throws the below error screen shot.

SAP ABAP Tutorial and Material, SAP Certifications, SAP Guides, SAP Learning, SAP SE38, SAP Module, SAP All Modules

Using SUBMIT key i submitted that report into my report. Then i clicked the where used list it does display like the below screen shot.

SAP ABAP Tutorial and Material, SAP Certifications, SAP Guides, SAP Learning, SAP SE38, SAP Module, SAP All Modules

SAP ABAP Tutorial and Material, SAP Certifications, SAP Guides, SAP Learning, SAP SE38, SAP Module, SAP All Modules

And also i created one subroutine which met all the above first three screen shots behavior.

SAP ABAP Tutorial and Material, SAP Certifications, SAP Guides, SAP Learning, SAP SE38, SAP Module, SAP All Modules

As well as i created  one more include program it is also met the same.

SAP ABAP Tutorial and Material, SAP Certifications, SAP Guides, SAP Learning, SAP SE38, SAP Module, SAP All Modules

What ever it may be the ABAP editor will not consider any thing on report first it will search the program has the key word report or program if not it will leave the syntax error otherwise it will read the program from the repository through the program attributes.

Thursday, 21 September 2017

How to attach a Document in SE38

Downhere is the step by step info on how to attach a Technical Specification or User Training Document or any other Information Document in SE38.

Launch the  T Code SE61.

Create a Word Document using the Create Button.

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

We can copy paste the Technical Specification or User Training Document or any Technical Info Document

(Or)

We can start maintaining this Document with all the necessary Technical Info right from the day one  and keep updating it as and when required

(Or)

We can even attach for ex Technical Specification  here using INSERT OBJECT.

I prefer this way as it is much easier way to attach the latest document whenever required, replacing the older one and getting it transported to Q and P

For our ex, I had attached the updated Technical Document as shown below :-

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

Save these changes to a Transport Request.

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

After saving it to a TR,you can go back to SE61 and click on DISPLAY to view the attachment Document.

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

Now,let’s see how to attach this ZTECHNICAL SPEC into the Documentation of SE38.

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

Click on Change

Click on Goto >> Change Editor

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

<DS:WORD.ZTECHNICALSPEC>Click here to view the Technical Spec</>

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

Now,click on DISPLAY to view the Documentation attached in the Text Editor.

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

SAP ABAP Tutorials and Materials, SAP ABAP Certification, SAP Guides, SAP Learning, SAP SE38, SAP Live Access

Now we can view the attached Tech Spec by clicking on it.

Tuesday, 19 September 2017

Implementing Fuzzy Search Using CDS & SAP HANA

The following steps show how to implement fuzzy searching using SAP HANA.

In this example we will be performing a fuzzy search on first name and last name of business partners in SAP CRM.

Note: You can only do this through SAP HANA Studio or equivalent tool such as Eclipse Neon/Eclipse Mars etc. It cannot be done using the SAP GUI editor. The reason for this will be explained in the steps below.

Create Your CDS


Right click on your system, select New > ABAP Repository Object.

SAP ABAP Certification, SAP ABAP CDS, SAP HANA, SAP Learning, SAP Guides, SAP CDS

From the popup window select Core Data Services > Data Definition.

SAP ABAP Certification, SAP ABAP CDS, SAP HANA, SAP Learning, SAP Guides, SAP CDS

Fill in the fields:

SAP ABAP Certification, SAP ABAP CDS, SAP HANA, SAP Learning, SAP Guides, SAP CDS

This will open the code editor.

Type your view details in here

@AbapCatalog.sqlViewName: 'ZVWCDSDEMO'

@AbapCatalog.compiler.compareFilter: true

@AccessControl.authorizationCheck: #CHECK

@EndUserText.label: 'CDS View Demo'

@OData.publish: true

define view zvw_cds_demo as select from but000 as b {

key b.partner,

b.name_last,

b.name_first

}

NOTE: sqlViewName cannot be the same as the name of the view you define.


View Created


Right click and select refresh:

SAP ABAP Certification, SAP ABAP CDS, SAP HANA, SAP Learning, SAP Guides, SAP CDS

You will now see your new view:

SAP ABAP Certification, SAP ABAP CDS, SAP HANA, SAP Learning, SAP Guides, SAP CDS

Class Generated


Your class will now have been generated:

SAP ABAP Certification, SAP ABAP CDS, SAP HANA, SAP Learning, SAP Guides, SAP CDS

Implement Inferface


The next step is to implement the interface IF_AMDP_MARKER_HDB in your class.

NOTE: This will make your class READ ONLY in the SAP GUI. Hence why the Eclipse IDE is needed to continue the implementation of the fuzzy search.

In Eclipse click on Class and in the code editor after the Public Section declaration implement the inteface:

public section.

  interfaces IF_AMDP_MARKER_HDB .

Define Structure for returned data


Straight after the interface declaration, define the structure for the data you want returned from your fuzzy search.

In this case Score, Partner, Name_First and Name_Last.

types:

BEGIN OF ty_partner_view,

score type CRMT_UBB_FACTOR,

partner    TYPE bu_partner,

name_first TYPE bu_namep_f,

name_last  TYPE bu_namep_l,

END OF ty_partner_view .

*Define the type

types:

tt_partner_view TYPE TABLE OF ty_partner_view .


Define the Method


In the class definition, define the method.

class-methods FUZZY_SEARCH

importing

value(IV_FIRST_NAME) type BU_NAMEP_F

value(IV_LAST_NAME) type BU_NAMEP_L

exporting

value(ET_DATA) type TT_PARTNER_VIEW .


Implement the Method


METHOD fuzzy_search BY DATABASE PROCEDURE FOR HDB

LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING zvwcdsdemo.

et_data = select distinct score( ), partner, name_first, name_last

from ZVWCDSDEMO

where

(

contains( name_first, :iv_first_name, fuzzy(0.5) ) and

contains( name_last, :iv_last_name, fuzzy(0.8) )

)

ORDER BY score( ) desc;

endmethod.

Test the Fuzzy Search


Goto SE24 and enter your class name.

Select the test button.

Click on the Fuzzy_Search method.

Enter your parameters:

SAP ABAP Certification, SAP ABAP CDS, SAP HANA, SAP Learning, SAP Guides, SAP CDS

Select the Debugging button.

Step through the code and select the contents of ET_DATA when the select statement has been executed to see the results:

SAP ABAP Certification, SAP ABAP CDS, SAP HANA, SAP Learning, SAP Guides, SAP CDS

As the results show an exact match returns a score of 1.000. Non exact matches have a lower score.

Tuesday, 12 September 2017

Dynamic Programming in ABAP: Part 2 - Introduction to Data Reference

In my last blog I explained about field symbols, below is the link for same:

Dynamic Programming in ABAP: Part 1 - Introduction to Field Symbols

In this blog I am going to explain about data references and its significance in dynamic programming.

According to SAP documentation, Data references can point to any data objects or to their parts (components, rows of internal tables, or sections specified by offsets and lengths).

SAP ABAP, SAP ABAP Certifications, SAP ABAP Live, ABAP Learning, SAP ABAP Tutorials and Materials

So data references are nothing but pointers. It stores the memory address of any data object. But to access the actual data object which data reference is pointing to, we first need to deference it using dereferencing operator ->*.

Difference between field symbol and data reference:

Field symbol is a placeholder for data object to which it is assigned and points to the content of data object hence it can be used at any operand position (no need to dereference it) and works with the content of the referenced memory area (value semantics).

Data references are pointers to data objects and it contains the memory address of data object (reference semantics). Data reference cannot be used at operand position directly; it should be dereferenced first.

Working with data reference:

There can be two types of data references:

◉ Typed Data Reference
◉ Generic Data Reference


1. Typed Data Reference:


Typed data reference variable can be declared as:

DATA lr_num TYPE REF TO i.
CREATE DATA lr_num.

Here first statement declares a reference variable lr_num which can point to any data object of type “i”. And second statement creates an anonymous data object of type “i” and assigns the reference of this data object to lr_num. Now if we want to change the value of data object, then it can be done by dereferencing lr_num by using dereference operator ->* as shown below:

DATA lr_num TYPE REF TO i.
CREATE DATA lr_num.

lr_num->* = 2.
WRITE: / lr_num->*.

The output will be 2.

--------------------------------------------------------------------------------------------------------
NOTE:

◉ With ABAP 7.40, instead of CREATE DATA, the NEW operator can also be used to create an anonymous data object and assigns its reference to a data reference variable.
--------------------------------------------------------------------------------------------------------

DATA lr_num TYPE REF TO i.
lr_num = NEW #( ).

Assigning existing data object to data reference:

If you want to assign the reference of an existing data object to a data reference, you can use GET REFERENCE statement.

DATA: lv_num TYPE i VALUE 2.
DATA: lr_num TYPE REF TO i.

GET REFERENCE OF lv_num INTO lr_num.
lr_num->* = 4.
WRITE: / lv_num.

Here lv_num is an existing data object (not anonymous data object). The output would be 4.

---------------------------------------------------------------------------------------------------------
NOTE:

◉ With ABAP 7.40, instead of GET REFERENCE, the REF operator also can be used to assign the reference of an existing data object to a data reference.
---------------------------------------------------------------------------------------------------------

Working with structures:

DATA: lr_mara TYPE REF TO mara.

CREATE DATA lr_mara.
lr_mara->matnr = '1111'.
lr_mara->matkl = '03'.

Here individual components of the structure can be accessed with -> operator on data reference variable.

Working with internal tables:

While processing internal table row, we can use REFERENCE INTO statement to set references to table rows as shown below:

DATA: lr_mara TYPE REF TO mara.
DATA: lt_mara TYPE TABLE OF mara.

SELECT * FROM mara INTO TABLE lt_mara UP TO 10 ROWS.

LOOP AT lt_mara REFERENCE INTO lr_mara.
  WRITE: / lr_mara->matnr.
ENDLOOP.

2. Generic Data Reference:


Generic data reference can be declared as:

DATA: lr_num TYPE REF TO data.
CREATE DATA lr_num TYPE i.

Here first statement declares a generic data reference lr_num which can point to any data object. And second statement creates an anonymous data object of type “i” and assigns its reference to lr_num.

‘data’ in ABAP is a generic data type.

Now since lr_num is generic, lr_num->* cannot be directly used at operand position. Hence the below statement would not be allowed.

lr_num->* = 2.

So in case of generic data reference, it can only be dereferenced using a field symbol, and this field symbol can be used at any operand position to manipulate the value of data object as shown below:

DATA: lr_num TYPE REF TO data.
FIELD-SYMBOLS: <num> TYPE any.

CREATE DATA lr_num TYPE i.
ASSIGN lr_num->* TO <num>.

<num> = 3.

----------------------------------------------------------------------------------------------------------
NOTE:

After ASSIGN statement you should check sy-subrc If field symbol assignment is successful, sy-subrc will be 0 otherwise it will be 4.
----------------------------------------------------------------------------------------------------------

Working with structures:

DATA: lr_str TYPE REF TO data.
FIELD-SYMBOLS: <str> TYPE any.
FIELD-SYMBOLS: <data> TYPE any.
CREATE DATA lr_str TYPE mara.

ASSIGN lr_str->* TO <str>.
ASSIGN COMPONENT 'MATNR' OF STRUCTURE <str> TO <data>.
<data> = '112'.

Here CREATE DATA statement creates an anonymous data object (MARA structure) and assigns its reference to the generic data reference lr_str, which then can be dereferenced into a generic field symbol <str>. Now, to access individual component of MARA structure, ASSIGN COMPONENT statement can be used.

Dynamically create data objects:

Requirement: Selection screen parameter “Table Name” will take a table name as input and display the corresponding table entries as output.

Solution:

PARAMETERS: p_tname TYPE tabname.
DATA: lr_tab TYPE REF TO data.
FIELD-SYMBOLS: <tab> TYPE ANY TABLE.

CREATE DATA lr_tab TYPE TABLE OF (p_tname).
ASSIGN lr_tab->* TO <tab>.
IF sy-subrc EQ 0.
  SELECT * FROM (p_tname) INTO TABLE <tab> UP TO 10 ROWS.
  cl_demo_output=>display( <tab> ).
ENDIF.

Explanation:

Here lr_tab is a generic data reference and <tab> is a generic field symbol for internal table. In CREATE DATA statement, the type of data object is mentioned in parenthesis which means that the type will be determined at runtime based on the value of parameter p_tname. After that we have dereferenced the data reference lr_tab into a generic field symbol <tab>. Now this field symbol can be used to do any valid operation on the internal table.

Difference between data reference and object reference:

There are two types of reference variable:

◉ Data reference and
◉ Object reference

Data reference variable can store the reference to any data object (variable, structures, internal tables etc.) whereas Object reference variable can store the reference to any class object.

For data reference variables, either the generic data type or a completely specified data type can be specified. For object reference variables, either a class or an interface can be specified.

Credits: https://help.sap.com/http.svc/rc/abapdocu_751_index_htm/7.51/en-US/abendata_reference_type.htm

Follow us on Twitter: https://twitter.com/saponlineguides
Google+: https://plus.google.com/b/107454975947044053086/107454975947044053086
Facebook:  https://www.facebook.com/saponlineguides/

Monday, 11 September 2017

Image in Mail body in ABAP

Objective


The requirement was to send the Birthday Mails to Employee along with image in mail body. Generally, the images are send as attachment in mail but to send the image in the mail body different approach is to be used.The main objective of this document is to send the image in email body. I searched on portals and google to resolve it but couldn’t find proper solution , so decided to post the document on finding solution.

Challenges


To use image in mail there are many options through direct HTML code and CL_BCS class but image appears as attachment and in body “X” icon appears, browsers and mail servers behaves  differently for HTML code.

There are four possible solutions according to me

1. To upload image on any server open to Internet and use that image path in html code. It will work in all case except those were external links are blocked by mail server or the image is removed from the given path.

2. To convert image to base64 code and append the whole string in image. It will work but string is very long and if not converted properly then image does not appears in mail body as required.

3. To upload image in smart-form and convert that smart-form to HTML then create html document and embed image to the mail using BCS class. It will work but the limitation is that in smartforms only BMP image types are supported which reduces the quality of image. The styles applied in smartforms are available in html but browsers suppresses the CSS and styles. So no styles will be seen in mail.To use the style they are to be applied inline through html code using tags like <font>,<i>&<b>,etc.

4. To upload image in MIME Repository. Get the Image from MIME Repository in report and convert it to xstring table form.Using class cl_gbt_multirelated_service combine HTML content and image. Create HTML content and attach image to mail body using BCS class  and assign sender and receivers.

The 4th Approach was more feasible and appropriate as it has high availabilty of image in mail body which fulfills the primary requirement.

Advantage


◉ It is quite simple and easy approach to embed image in mail body.
◉ It can be reused for sending images in mail body.
◉ We can give desired styling using inline HTML tags which avoids the usage of css as they are not rendered by many web browsers and mail severs.
◉ High availabilty of image in mail and no other objects like smartforms are required,use multiple images in mail body. 

Disadvantage


◉ The web browsers and mail severs behave differently while rendering HTML page. We use CID (Context Id ) to display image in HTML body.It is possible that some browsers/mail servers don’t allow to render image in mail body using CID but atleast we would have the image as attachment.
◉ Tested for OUTLOOK, ZIMBRA works well on it.

Steps for sending the image in mail.


1. Upload Image in MIME repository.
2. Get image from mime reporsitory in form of xstring
3. Convert the image from xstring to table form ( i.e. solix_tab )
4. Attach Image in xstring form to HTML form.
5. Create mail content.
6. Create HTML form with HTML content.
7. Create Mail using BCS class.

1. Upload Image in MIME repository.


There are many options to upload image in Mime Repository. I have implemented using SE80 TCODE.

It can also be implemented through report using

◉ Class: CL_MIME_REPOSITORY_API
◉ Method: IF_MR_API~PUT

1. Provide TCODE SE80.

2. Click on Mime Repository.

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

3. Select Directory where the image is to be uploaded , right click on directory and select “Import MIME Objects” ( Here the directory is “PUBLIC” ).

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

4. Browse the System and Select the required image to be uploaded from the system then following screen would appear,provide description and click on save button.

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

5. On Saving the image the system would prompt for object package , Save it in associated package or local object as per the requirement.

6. Now the image would appear in the folder and by clicking on image we can get the preview as shown below.

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

2. Get image from mime repository in form of xstring


Create the report as per the logic required(requirement was to send birthday mails) and we can add the image part and html body      to it

Get the image stored in mime repository in the report using 
◉ Class: cl_mime_repository_api 
◉ Method: if_mr_api~get_api

Here in parameter i_url the image path is to be given to obtain the image in xstring form.

Code:

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

3. Convert the image from xstring to table form ( i.e. solix_tab )


In variable gv_content the image is in form of xstring.

To attach that image in mail we have to convert it to table form of Xstring which contains      row of type xstring and length 255 char

The lt_solix table contains the image in xstring table form which would be attached to mail body.

Code:

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

4. Attach Image in xstring


◉ In variable l_filename the name is given to the image that is created and in variable l_content_id the content id (CID) is assigned which   would be later used in the html content.

◉ The variable lt_solix contains the image in xstring table form.

◉ The variable l_obj_len contains the length of image which was calculated earlier

◉ The content type is the mime type of the content in lt_solix

◉ For .jpg image it is image/jpg. Similarly for bmp – image/bmp, gif – image/gif , etc

◉ Attach image using 

1. Class: cl_gbt_multirelated_service
2. Method: add_binary_part
3. Object: lo_mime_helper

Code:

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

◉ If mimetype/content type is not available in system then we need to add it through following steps

TCODE : SMW0.

1. Execute TCODE : SMW0

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

 2. Press F8    

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

3. Press F8

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

 4. In Menu , Goto Settings –> Maintain MIME Types.Click on Create button

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

◉ If the desired mime type is not present then the required mime type can be created using above steps

5. Create HTML mail content.


◉ The HTML content is prepared and filled in table lt_soli which would be later used to create      HTML form.

◉ <font> tag is used to use to give the style to the content.

◉ <img> tag is used for using image in html body.

◉ In <img> the content id (CID) should be same as the content Id given in above step while      attaching image.

Code:

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

6. Create HTML form with HTML content.


The created html content in table lt_soli is to be attached to create a HTML form using

◉ Class: cl_gbt_multirelated_service
◉ Method: set_main_html
◉ Object: lo_mime_helper

Code:

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

7. Create Mail using BCS class.


Now using the CL_BCS class we can embed html body and image assigning sender and receivers.

Code:

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

Output in SOST.

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP

Output in Mail Client.

SAP ABAP, SAP ABAP Tutorials and Materials, SAP ABAP Certifications, SAP Guides, SAP Learning, SAP Live Access, SAP