Nov 28, 2011

Dynamic Internal Table or Array

A sample code how to create a Dynamic Internal Table or Array using Class CL_ALV_TABLE_CREATE


TYPE-POOLS : abap.
FIELD-SYMBOLS: <dyn_table> TYPE STANDARD TABLE,
               <dyn_wa>,
               <dyn_field>.
DATA: dy_table TYPE REF TO data,
    dy_line  TYPE REF TO data,
    xfc TYPE lvc_s_fcat,
    ifc TYPE lvc_t_fcat.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME.
PARAMETERS: p_table(30) TYPE c DEFAULT 'T001'.
SELECTION-SCREEN END OF BLOCK b1.

START-OF-SELECTION.
  PERFORM get_structure.
  PERFORM create_dynamic_itab.

*******Creates a dynamic internal table*********
  PERFORM get_data.
  PERFORM write_out.

*&---------------------------------------------------------------------*
*&      Form  get_structure
*&---------------------------------------------------------------------*
FORM get_structure.
  DATA : idetails TYPE abap_compdescr_tab,
       xdetails TYPE abap_compdescr.
  DATA : ref_table_des TYPE REF TO cl_abap_structdescr.
* Get the structure of the table.
  ref_table_des ?=
      cl_abap_typedescr=>describe_by_name( p_table ).
  idetails[] = ref_table_des->components[].
  LOOP AT idetails INTO xdetails.
    CLEAR xfc.
    xfc-fieldname = xdetails-name .
    CASE xdetails-type_kind.
      WHEN 'C'.
        xfc-datatype = 'CHAR'.
      WHEN 'N'.
        xfc-datatype = 'NUMC'.
      WHEN 'D'.
        xfc-datatype = 'DATE'.
      WHEN 'P'.
        xfc-datatype = 'PACK'.
      WHEN OTHERS.
        xfc-datatype = xdetails-type_kind.
    ENDCASE.
    xfc-inttype = xdetails-type_kind.
    xfc-intlen = xdetails-length.
    xfc-decimals = xdetails-decimals.
    APPEND xfc TO ifc.
  ENDLOOP.
ENDFORM.                    "get_structure

*&---------------------------------------------------------------------*
*&      Form  create_dynamic_itab
*&---------------------------------------------------------------------*
FORM create_dynamic_itab.
* Create dynamic internal table and assign to FS
  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog  = ifc
      i_length_in_byte = 'X' "added by Paul Robert Oct 28, 2009 17:04
    IMPORTING
      ep_table         = dy_table.
  ASSIGN dy_table->* TO <dyn_table>.
* Create dynamic work area and assign to FS
  CREATE DATA dy_line LIKE LINE OF <dyn_table>.
  ASSIGN dy_line->* TO <dyn_wa>.
ENDFORM.                    "create_dynamic_itab

*&---------------------------------------------------------------------*
*&      Form  get_data
*&---------------------------------------------------------------------*
FORM get_data.
* Select Data from table.
  SELECT * INTO TABLE <dyn_table>
           FROM (p_table).
ENDFORM.                    "get_data

*&---------------------------------------------------------------------*
*&      Form  write_out
*&---------------------------------------------------------------------*
FORM write_out.
  LOOP AT <dyn_table> INTO <dyn_wa>.
    DO.
      ASSIGN COMPONENT  sy-index
         OF STRUCTURE <dyn_wa> TO <dyn_field>.
      IF sy-subrc <> 0.
        EXIT.
      ENDIF.
      IF sy-index = 1.
        WRITE:/ <dyn_field>.
      ELSE.
        WRITE: <dyn_field>.
      ENDIF.
    ENDDO.
  ENDLOOP.
ENDFORM.                    "write_out

Nov 6, 2011

Internal table to spool

A sampe code to display Internal table to spool:

*&------------------------------------------------------------------*
*& Form SEND_TO_SPOOL
*&------------------------------------------------------------------*
* text
*-------------------------------------------------------------------*
FORM send_to_spool.
DATA: val,
pripar LIKE pri_params,
arcpar LIKE arc_params.

CALL FUNCTION 'GET_PRINT_PARAMETERS'
EXPORTING
layout = 'X_65_255'
line_count = 65
line_size = 255
IMPORTING
out_parameters = pripar
out_archive_parameters = arcpar
valid = val.

NEW-PAGE PRINT ON NEW-SECTION
PARAMETERS pripar
ARCHIVE PARAMETERS arcpar
NO DIALOG.
IF val <> space.
LOOP AT it_spool.
......
ENDLOOP.
ENDIF.
NEW-PAGE PRINT OFF.
ENDFORM. "SEND_TO_SPOOL





Oct 8, 2011

How to Debug Popup Screen in ABAP

Debugging in ABAP for ABAP developers is a vital requirement during building application in SAP systems. There are numerous ways to debug ABAP code or debug SAP screens for ABAP developers. But many ABAP programmers who are new to ABAP development may not know how to debug popup screen in SAP platform. In this short ABAP tutorial, I'll try to share you ABAP trick to debug SAP popup screens.

Please note that, this tutorial does not cover debugging using "/H" option or using break points in ABAP code. I want to concentrate on developers requirement to debug an unknown ABAP code block which they want to discover.

First step is open your Notepad application and type or copy-paste the following commands in a new blank text file.

[FUNCTION]
Command=/H
Title=Debugger
Type=SystemCommand

Then save the above text file as a batch file. You can name it as debug.bat for example.

Now ABAP developers are ready to debug a modal popup SAP screen. Let's assume that you want to debug output processing log screen for an invoice output

ABAP debugging tips to debug popup screens in SAP

Now drag and drop debug.bat batch file from your Windows desktop onto the modal popup SAP screen.
Then the SAP GUI will inform you about the debugging status with message "Debugging switched on"

SAP screen debugging switched on

Now ABAP developers can easily activate debugging screen in ABAP on the modal popup SAP screen.



How to debug Smartforms

Debugging SmartForms using Function Module

If you want to debug Smartform document in non-modifiable client, then you can try debugging Smartforms Function Module using soft break point.

First you need to find the function module name of the target SmartForm for debugging.
If you do not know how to get the function module name of the SAP Smart Form, please read the Smart Form tutorial titled How to Find SAP SmartForms Function Module Name.
Without knowing the function module name, we can not debug SmartForms in non-modifiable clients.

After you find the function module name, we can now display the ABAP source codes of the SSF FM (Function Module) using the SAP Transaction SE37.

Within the ABAP codes of Smartform FM you can put a soft break-point any where suitable for your debugging Smartforms purposes.

It is better to copy the node name or some parts of the ABAP code in the SAP Smartform and search the text within the SE37 displayed source code of the Smartforms function module (FM).

You can place a soft break point in the source code using Ctrl+Shift+12 key combination or using the Stop icon sap-stop-icon-to-debug.

Let's assume that you want to debug Smartforms codes within program lines named '%CODE10' as seen in the followin Smartform screenshot,

search-code-node-in-sap-smart-form-function-module

First click on the Search button sap-search-icon-to-find-text-in-code, and not use the Ctrl+F since searc button has far more powerful functionalities than ordinary Ctrl+F search.

Enter the text you are searching in the Find text area.
You can search for the node name '%CODE10' as well as for a part of your SmartForm code.

What is important here in this Search is be sure that you selected the option "In main program".
Otherwise your search will take place only for a limited part of the Smartform function module codes.

search-code-node-in-sap-smart-form-function-module-main-program

When the place of the target code block is found, you can run the SAP Smart Form and start to debug Smartform document.

SAP Smartforms - How to Call Smartform within Example ABAP Program

Here is an SAP Smartforms step by step example to open and call Smartform within ABAP code.
Within ABAP programs an SAP Smartform can be called and opened by calling the ABAP function SSF_FUNCTION_MODULE_NAME, we will see in the example ABAP code which is included with this Smartforms tutorial.

First, create a SAP Smartform report using ABAP transaction code "smartforms" within ABAP Editor.
Or you can use an existing simple SAP Smartforms report to call from the example ABAP program.

In this SAP SmartForms tutorial, the example uses a SmartForm named "ZSMARTFORMS_SALES_DOCUMENTS".
The SmartForm application "ZSMARTFORMS_SALES_DOCUMENTS" takes a table valued parameter to use as an internal table within SmartForms ABAP codes.
This SmartForms parameter table is "it_vbak" which is declared in type table of VBAK SAP Sales and Distribution table.
SAP VBAK table is contains Sales Document header data.
As you will see in the below ABAP codes, the program select a range of VBAK Sales Document records into an internal table variable it_vbak.
Later the variable table is passed to the SAP SmartForm as a TABLE argument.

It is important that the table variable is correctly declared within the Smartform 's "Global Settings > Form Interface > Tables" section.
As you will see in the below screenshot, it_vbak is declared as :
IT_VBAK TYPE VBAK

sap-smartforms-global-settings-form-interface-tables-variable-declaration


Example ABAP Program to Call Smartform

Here is the example ABAP code to call SAP SmarForms from a program or an ABAP report.
Please note that we have ABAP codes which call ABAP function SSF_FUNCTION_MODULE_NAME with formname parameter is set to the target SAP Smartforms document.
The SSF_FUNCTION_MODULE_NAME ABAP call returns the FM_NAME which is the compiled ABAP program identifier and is in type rs38l_fnam.
The returned fm_name variable is then called using an ABAP Call Function method to open Smartform.
While calling Smartform, the Table parameter is passed as an input argument.

*&--------------------------------------------------------------*
*& Report Z_CALL_SMARTFORM *
*& Sample Function calls ZSMARTFORMS_SALES_DOCUMENTS smartform *
*&--------------------------------------------------------------*

REPORT Z_CALL_SMARTFORM.

DATA :
fm_name TYPE rs38l_fnam,
it_vbak TYPE TABLE OF vbak.

SELECT * FROM vbak into TABLE it_vbak
WHERE vbeln GE '0100000004'
AND vbeln LE '0100000010'.


CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
EXPORTING
formname = 'ZSMARTFORMS_SALES_DOCUMENTS'
IMPORTING
FM_NAME = fm_name
EXCEPTIONS
NO_FORM = 1
NO_FUNCTION_MODULE = 2
OTHERS = 3.

CALL FUNCTION fm_name
TABLES
it_vbak = it_vbak
EXCEPTIONS
FORMATTING_ERROR = 1
INTERNAL_ERROR = 2
SEND_ERROR = 3
USER_CANCELED = 4
OTHERS = 5.

I hope, SAP Smartforms developers will find this sample ABAP code useful as beginning to SAP Smartforms.


How to Spell Numbers using ABAP Spell_Amount Function Module

SAP professionals can use ABAP Spell_Amount function module in order to spell numbers and currency values into string variables. It is very easy in different languages the answer of "How to Spell Numbers in SAP" using Spell_Amount ABAP function module.

In this ABAP tutorial, developers will find a sample ABAP report using Spell_Amount to convert numeric value or currency amount entered in the selection screen into string and display on the screen using Write command

What makes Spell_Amount perfect for spelling price, amount fields and number values is it can spell in different languages. The Spell_Amount function module excepts a Language input parameter and returns the spell in the input language. Either German, English, Turkish, Spanish, Russian, ABAP developers can easily return decimal values and integer part of the number seperately easily.

Since the Spell_Amount return a SPELL type structure, developers should be aware of both fields word and decword of the output structure. The decword will return limited values from 0 to 99 for example. But the integer part word can handle greater numeric values.

Here is the ABAP report source code that ABAP developers can use in order to convert numeric values, numbers and currencies into string. The following ABAP report is using Spell_Amount in order to spell numbers into string variables and display on the output screen.

PARAMETERS:
pLANGU LIKE T002-SPRAS DEFAULT SY-LANGU,
pCURR LIKE TCURC-WAERS DEFAULT 'USD',
pAMOUNT LIKE VBAP-MWSBP ,
pFILLER(1) TYPE C DEFAULT ' '.

DATA :
WS_SPELL TYPE SPELL.

CALL FUNCTION 'SPELL_AMOUNT'
EXPORTING
AMOUNT = pAMOUNT
CURRENCY = pCURR
FILLER = pFILLER
LANGUAGE = pLANGU "SY-LANGU
IMPORTING
IN_WORDS = WS_SPELL
EXCEPTIONS
NOT_FOUND = 1
TOO_LARGE = 2
OTHERS = 3
.
IF sy-subrc <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ELSE.
WRITE :/ WS_SPELL-word , WS_SPELL-decword.
ENDIF.

Here is the selection screen of the ABAP report ZSPELLAMOUNT.

spell_amount function module

And this is the output screen displaying the spelling of input number value in given language

ABAP Spell Amount FM



Create Number Range Object using SAP Transaction Code SNRO

ABAP developers and SA professionals require an auto number field especially in the key fields of a database table during ABAP coding in their SAP applications.

Actually an auto incrementa field is a general requirement for al developers in all development environments and platforms
In SAP environment the solution is creating to create number range object and use number range object in ABAP codes for ABAP developers
Actually, database providers like Microsoft SQL Server and Oracle have more advanced solutions for such requirements that does not require maintanence and so much steps in number range creation process.

Let's start our task in this SAP tutorial, number range creation using SNRO SAP Transaction code.


Step by step Number Range Creation using SNRO SAP Transaction

In SAP Easy Access screen, call SAP transaction code SNRO

sap-transaction-code-snro-for-number-range

Enter Number Range name in the Number Range Object input text field.

sap-transaction-code-snro-number-range-screen

Enter Short Text and Long Text descriptive texts for Number Range Object.

Enter a number length domain for the number range object

If you want a warning define an integer smaller than 100 in the Warning % field.
You can enter 5 or 10 as common warning percentage values.

sap-transaction-code-snro-create-number-range-for-auto-number

Click on the Save button sap-save-button to save the number range definition.

sap-buffering-methods

Click on Yes button to continue.
The next screen displayed is Create Object Directory Entry screen.

sap-abap-create-object-directory-entry-for-number-range

I select Local Object

Now the Change documents and Number ranges buttons are displayed in the Number Range Object : Change SAP screen.

Click on "Number ranges" button.

change-number-range-object-abap

Click on Change Intervals buttons.

sap-change-intervals-in-number-range-object

Click on "Add Interval" button sap-number-range-add-interval-button

sap-maintain-number-range-intervals-screen

Enter an integer number like 1 at interval number and a range of numbers with integer values identifying from number and to number. If you have entered required fields press Enter button.

insert-interval-for-number-range-intervals-in-sap

Click on "Save" button. And the number range interval you have just declared will be listed in the Number Range object 's number intervals list.

snro-number-range-object-number-intervals-list

The following "Transport number range intervals" warning screen is displayed.

snro-abap-transport-number-range-intervals

The number range intervals are not included in automatic recording of customizing changes. Transport of all the changes made within number range interval maintenance must be triggered manually.

In the initial screen for number range interval maintenance choose the function Interval -> Transport.

Please note the information that you get when transporting number range intervals.

Here is the display screen of the Number Range object.

sap-snro-display-number-range-object


SAP professionals and ABAP developers have seen how to create Number Range Object till this point in this SAP tutorial.
Now ABAP developers are readyto go further and learn how to use number range objects in ABAP code.
Key ABAP function for implementing and using a number range in ABAP codes is NUMBER_GET_NEXT ABAP function.
In order to use a number range for auto increment column numbers safely in SAP, NUMBER_GET_NEXT ABAP function is used with NUMBER_RANGE_ENQUEUE and NUMBER_RANGE_DEQUEUE.

ABAP developers can copy and paste the following ABAP report source code and execute the ABAP program in their development and test environments.
The sample ABAP report reads the next number in an SAP Number Range Object and displays the auto number value on the screen.
The ABAP NUMBER_RANGE_ENQUEUE function sets a lock on the number range object.
If the lock is successfully set on the SAP number range, using NUMBER_GET_NEXT function call the next number in the number range interval is read and passed into an ABAP variable.
The last step is calling NUMBER_RANGE_DEQUEUE function and removing the loc on the relate SAP number range object.

REPORT ztreenodes .

" INRI : Number ranges function module interface structure
CONSTANTS :
" Name of number range object - CHAR 10
c_rangeobj LIKE inri-object VALUE 'Z_TREENODE',
" Number range number - CHAR 2
c_rangeno LIKE inri-nrrangenr VALUE '1'.

DATA : " NodeId from Number Generator Object
gv_nodeid TYPE i.


START-OF-SELECTION.

PERFORM nextnum USING gv_nodeid c_rangeobj c_rangeno.
WRITE gv_nodeid.

END-OF-SELECTION.

FORM nextnum USING

le_nextnum TYPE i
le_rangeobj LIKE inri-object
le_rangeno LIKE inri-nrrangenr.

DATA :
lv_nextnum TYPE i.

CALL FUNCTION 'NUMBER_RANGE_ENQUEUE'
EXPORTING
object = le_rangeobj
EXCEPTIONS
foreign_lock = 1
object_not_found = 2
system_failure = 3
OTHERS = 4.
IF sy-subrc NE 0.
* message e086 with 'Lock error' sy-subrc.
ENDIF.

CALL FUNCTION 'NUMBER_GET_NEXT'
EXPORTING
nr_range_nr = le_rangeno
object = le_rangeobj
* QUANTITY = '1'
* SUBOBJECT = ' '
* TOYEAR = '0000'
* IGNORE_BUFFER = ' '
IMPORTING
number = lv_nextnum " Number generated by Range Generator Object
* QUANTITY =
* RETURNCODE = lv_returncode
EXCEPTIONS
interval_not_found = 1
number_range_not_intern = 2
object_not_found = 3
quantity_is_0 = 4
quantity_is_not_1 = 5
interval_overflow = 6
buffer_overflow = 7
OTHERS = 8.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.

CALL FUNCTION 'NUMBER_RANGE_DEQUEUE'
EXPORTING
object = le_rangeobj.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

le_nextnum = lv_nextnum.

ENDFORM. " NEXTNUM

I hope ABAP developers will fing this number range and NUMBER_GET_NEXT function call implementation useful.

Aug 24, 2011

Program to Hide ABAP's Source Code and Protect it

Program to Hide ABAP's Source Code and Protect it


Protect ABAP program with this code


REPORT zproghide NO STANDARD PAGE HEADING.

************************************************************************
* This program hides any ABAP's source code and protects it with a
* password in this source code.
*
* After hiding, you can still run the abap (the load version is intact)
* but it cannot be displayed, edited, traced, transported or generated.
*
* If the ABAP is not hidden, the program hides it, if it is hidden, it
* unhide it.
* Remember to hide this program first!
************************************************************************

SELECTION-SCREEN BEGIN OF BLOCK block.
PARAMETERSprogram(30) OBLIGATORY.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(8) pwd.
SELECTION-SCREEN POSITION 35.
PARAMETERS: password(8) MODIF ID aaa.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK block.


*
DATAmessage(60TYPE c.
*

AT SELECTION-SCREEN OUTPUT.

  LOOP AT SCREEN.
    IF screen-group1 = 'AAA'.
      screen-invisible = '1'.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.

*
INITIALIZATION.
  pwd = 'Password'.
*

START-OF-SELECTION.

  TABLES: trdir.

* User name and password check
  IF password <> 'ABCDEFG'.
    WRITE: / 'Wrong password'.
    EXIT.
  ENDIF.

* SAP owned?
  IF NOT program CP 'Z*' AND NOT program CP 'Y*'.
    WRITE: / 'Do not hide original SAP programs!'.
    EXIT.
  ENDIF.

* Exists?
  SELECT SINGLE * FROM trdir WHERE name = program.
  IF sy-subrc <> 0.
    WRITE: / 'Program does not exists!'.
    EXIT.
  ENDIF.

* Does it have a current generated version?
  DATA: f1 TYPE d, f3 TYPE d.
  DATA: f2 TYPE t, f4 TYPE t.
  EXEC SQL.
    SELECT UDAT, UTIME, SDAT, STIME INTO :F1, :F2, :F3, :F4 FROM D010LINF
    WHERE PROG = :PROGRAM
  ENDEXEC.

  IF f1 < f3 OR ( f1 = f3 AND f2 < f4 ).
    WRITE: / 'The program has no recent generated version!'.
    EXIT.
  ENDIF.

* Compose a new program name
  DATA: new_name(30), i TYPE i, j TYPE i.
  new_name = program.

  DO 30 TIMES.
    i = sy-index - 1.
    new_name+i(1) = '_'.

* Search for acceptable program name variations
    j = 0.

    SELECT * FROM trdir WHERE name LIKE new_name.
      j = j + 1.
    ENDSELECT.

    IF j = 1.
      EXIT.
    ENDIF.

    new_name = program.
  ENDDO.

* Cannot generate appropriate program name
  IF j > 1.
    WRITE: / 'Cannot generate appropriate program name'.
    EXIT.
  ENDIF.

* Check if it is already hidden
  DATA: f5(30).

  EXEC SQL.
    SELECT PROG INTO :F5 FROM D010S WHERE PROG = :NEW_NAME
  ENDEXEC.

  IF f5 IS INITIAL.

* There is no such hidden program, hide it
    EXEC SQL.
      UPDATE D010S SET PROG = :NEW_NAME WHERE PROG = :PROGRAM
    ENDEXEC.
    CONCATENATE 'Program' :program 'was hidden.'
    INTO message SEPARATED BY space.
  ELSE.

* There is already a hidden program there, unhide it
    EXEC SQL.
      UPDATE D010S SET PROG = :PROGRAM WHERE PROG = :NEW_NAME
    ENDEXEC.

    CONCATENATE 'Program' :program 'was restored.'
    INTO message SEPARATED BY space.

  ENDIF.

  WRITE message.

*** end of program

 
ref: http://www.sap-img.com/abap/program-to-hide-abap-source-code-and-protects-it.htm

How To Get The Records from the XML File

How To Get The Records from the XML File

Use these routines to get data/ records from XML

 

PERFORM f_parse_file USING wv_pifile
                    CHANGING wt_xml_table
                             wt_errdata .
*READ DATA FROM TEMPORARY INTERNAL TABLE TO FINAL STRUCTURE
PERFORM f_create_file USING wt_xml_table
                       CHANGING wa_liste_evt  .


*&---------------------------------------------------------------------*
*&      Form  F_PARSE_FILE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->FPU_PIFILE      text
*      -->FPC_WT_XML      text
*      -->FPC_WT_ERRDATA  text
*----------------------------------------------------------------------*
FORM f_parse_file    USING fpu_pifile TYPE string
                  CHANGING fpc_wt_xml TYPE tt_xml_table
                           fpc_wt_errdata TYPE tt_errdata.

  DATA: lo_pixml          TYPE REF TO if_ixml,
        lo_pdocument      TYPE REF TO if_ixml_document,
        lo_pstreamfactory TYPE REF TO if_ixml_stream_factory,
        lo_pistream       TYPE REF TO if_ixml_istream,
        lo_pparser        TYPE REF TO if_ixml_parser,
        lo_pnode          TYPE REF TO if_ixml_node,
        lo_pparseerror    TYPE REF TO if_ixml_parse_error,
        wlv_string        TYPE string,
        wlv_count         TYPE i,
        wlv_index         TYPE i,
        wlv_totalsize     TYPE i,
        wlt_xml_c         TYPE STANDARD TABLE OF t_xml_c,
        wlt_xml_x         TYPE STANDARD TABLE OF t_xml_x,
        wlv_xstring       TYPE xstring,
        wla_errdata       TYPE t_errdata.

*READ PHYSICAL FILE TO AN INTERNAL TABLE
  PERFORM f_read_file USING fpu_pifile
                   CHANGING wlt_xml_c .
*CONVERT TEXT TO XSTRING FORMAT
  IF NOT wlt_xml_c IS INITIAL.
    CALL FUNCTION 'SCMS_TEXT_TO_XSTRING'
      IMPORTING
        buffer   = wlv_xstring
      TABLES
        text_tab = wlt_xml_c
      EXCEPTIONS
        failed   = 1.

    IF sy-subrc <> 0.
      MESSAGE e030 WITH p_file.
    ENDIF.

  ELSE.
    MESSAGE e020 WITH p_file.
  ENDIF.
*Convert xstring to binary
  CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
    EXPORTING
      buffer        = wlv_xstring
    IMPORTING
      output_length = wlv_totalsize
    TABLES
      binary_tab    = wlt_xml_x.
*-- CREATE THE MAIN FACTORY
  lo_pixml = cl_ixml=>create( ).

*-- CREATE THE INITIAL DOCUMENT
  lo_pdocument = lo_pixml->create_document( ).

*-- CREATE THE STREAM FACTORY
  lo_pstreamfactory = lo_pixml->create_stream_factory( ).

*-- CREATE AN INPUT STREAM FOR THE TABLE
  lo_pistream = lo_pstreamfactory->create_istream_itable( table =
  wlt_xml_x
                                                          size  =
                                                          wlv_totalsize
                                                          ).
*-- CREATE THE PARSER
  lo_pparser = lo_pixml->create_parser( stream_factory =
  lo_pstreamfactory
                                        istream        = lo_pistream
                                        document       = lo_pdocument ).
*-- PARSE THE STREAM
  IF lo_pparser->parse( ) NE 0.
*Error handling for parser object
    IF lo_pparser->num_errors( ) NE 0.
      wlv_count = lo_pparser->num_errors( ).
      wlv_index = 0.
      WHILE wlv_index < wlv_count.
        lo_pparseerror = lo_pparser->get_error( index = wlv_index ).
        wlv_string = lo_pparseerror->get_reason( ).
        TRANSLATE wlv_string TO UPPER CASE.
*Gets the error description updated in the Error table
        CONCATENATE text-001 wc_colon wlv_string INTO wla_errdata-value.
        wla_errdata-typ = wc_err.
        APPEND wla_errdata TO fpc_wt_errdata.  CLEAR wla_errdata.
        wlv_index = wlv_index + 1.
      ENDWHILE.
    ENDIF.
  ENDIF.
*-- THE STREAM IS NO LONGER NEEDED, SO CLOSE IT...
  CALL METHOD lo_pistream->close( ).
  CLEAR lo_pistream.

*IF COUNT > 0 THEN THE XML FILE HAD TROUBLES LIKE INCOMPLETE TAGS,
*MISSING PARTS, ETC.
  IF wlv_count > 0.
    EXIT.
  ENDIF.
*-- PUT THE WHOLE DOM TREE AS A LIST...
  lo_pnode = lo_pdocument.
*  GETS THE TYPE AND VALUE OF EACH NODE OF THE DOCUMENT
  PERFORM f_fill_table USING lo_pnode
                   CHANGING fpc_wt_xml .

  FREE : wlt_xml_c, wlt_xml_x.
ENDFORM.                    " F_READ_FILE
*&---------------------------------------------------------------------*
*&      FORM  F_FILL_TABLE
*&---------------------------------------------------------------------*
*  GETS THE TYPE AND VALUE OF EACH NODE OF THE DOCUMENT
*----------------------------------------------------------------------*
*   -->FPU_WL_PNODE     NODE
*   <--FPC_WT_XML_TABLE OUTPUT TABLE WITH ALL THE NODES IN TABULAR FORM
*----------------------------------------------------------------------*
FORM f_fill_table   USING value(fpu_wl_pnode) TYPE REF TO if_ixml_node
                 CHANGING fpc_wt_xml_table    TYPE tt_xml_table.

* LOCAL DECLARATIONS
  DATA: wla_xml_wa     TYPE t_xml_list,
        wlv_ptext      TYPE REF TO if_ixml_text,
        wlv_name       TYPE string,
        wlv_value      TYPE string.

*THIS CODE CHECKS SERIALLY EACH NODE FOR ITS TYPE AND APPENDS IN THE
*COLUMN
*ELEMENT NAME OR ELEMENT VALUE ACCORDINGLY.
  CASE fpu_wl_pnode->get_type( ).
    WHEN if_ixml_node=>co_node_element.
      wlv_name = fpu_wl_pnode->get_name( ).

*HERE COMES THE FIELD NAME FROM THE XML FILE
      wla_xml_wa-name = wlv_name.

      TRANSLATE wla_xml_wa-name TO UPPER CASE.
*INSERT ALL FIELDS FROM XML INTO AN INTERNAL TABLE
      APPEND wla_xml_wa TO fpc_wt_xml_table.
      CLEAR wla_xml_wa.

    WHEN if_ixml_node=>co_node_text.
      wlv_ptext ?= fpu_wl_pnode->query_interface( ixml_iid_text ).
      IF wlv_ptext->ws_only( ) IS INITIAL.
*HERE COMES THE FIELD VALUE
        wlv_value = fpu_wl_pnode->get_value( ).
        wla_xml_wa-value = wlv_value.
        MODIFY fpc_wt_xml_table FROM wla_xml_wa
                           INDEX sy-tabix
                    TRANSPORTING value.
        CLEAR wla_xml_wa.
      ENDIF.
    WHEN OTHERS .
*Do nothing.
  ENDCASE.

  fpu_wl_pnode = fpu_wl_pnode->get_first_child( ).

  WHILE NOT fpu_wl_pnode IS INITIAL.

    PERFORM f_fill_table USING fpu_wl_pnode
                      CHANGING fpc_wt_xml_table .

    fpu_wl_pnode = fpu_wl_pnode->get_next( ).

  ENDWHILE.
ENDFORM.                    " F_FILL_NODE


*&---------------------------------------------------------------------*
*&      Form  F_CREATE_FILE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->FPU_WT_XML_TABLE  text
*      -->FPC_WA_LISTE_EVT  text
*----------------------------------------------------------------------*
FORM f_create_file  USING fpu_wt_xml_table TYPE tt_xml_table
                 CHANGING fpc_wa_liste_evt TYPE t_wa_liste_evt.

  FIELD-SYMBOLS : <f_fieldname>  TYPE ANY,
                  <f_value>  TYPE ANY,
                  <wa>  TYPE ANY.
  DATA : wlv_fieldname  TYPE char15,
         wlv_fieldvalue TYPE char20,
         wlv_count      TYPE i VALUE 1,
         wla_xml_wa     TYPE t_xml_list,
         wla_psl        TYPE t_wa_psl ,
         wla_evt        TYPE t_evt.

  DATA : BEGIN OF wlt_psl,
          psl TYPE tt_psl,
         END OF wlt_psl.

  LOOP AT fpu_wt_xml_table INTO wla_xml_wa FROM 3.
*THIS CODE WILL FILL THE WA FOR LEVEL 2 DATA OF TECH SPECS
    IF wla_xml_wa-name = wc_flg_typ    OR
       wla_xml_wa-name = wc_cod_soc    OR
       wla_xml_wa-name = wc_num_uat_tc OR
       wla_xml_wa-name = wc_dat_etd    OR
       wla_xml_wa-name = wc_num_evt.

      wlv_fieldname = wla_xml_wa-name.
      wlv_fieldvalue = wla_xml_wa-value.
      CONDENSE wlv_fieldname.
      ASSIGN wlv_fieldname TO <f_fieldname>.
      ASSIGN wlv_fieldvalue TO <f_value>.
      ASSIGN COMPONENT <f_fieldname> OF STRUCTURE wla_evt TO <wa>.
      <wa> = <f_value>.

      UNASSIGN : <wa>, <f_fieldname>, <f_value>.
      CLEAR : wlv_fieldname, wlv_fieldvalue .

    ELSEIF
*THIS CODE WILL FILL THE LEVEL 5 DATA OF THE TECH SPECS
       wla_xml_wa-name = wc_num_ord     OR
       wla_xml_wa-name = wc_cod_psl     OR
       wla_xml_wa-name = wc_lib_psl     OR
       wla_xml_wa-name = wc_cod_pro     OR
       wla_xml_wa-name = wc_cod_sta     OR
       wla_xml_wa-name = wc_dat_prv     OR
       wla_xml_wa-name = wc_dat_prv_rea OR
       wla_xml_wa-name = wc_dat_eff     OR
       wla_xml_wa-name = wc_dat_cre     OR
       wla_xml_wa-name = wc_com1        OR
       wla_xml_wa-name = wc_flg_ale     OR
       wla_xml_wa-name = wc_cod_inct    OR
       wla_xml_wa-name = wc_cod_vil     OR
       wla_xml_wa-name = wc_cod_trs     OR
       wla_xml_wa-name = wc_cod_trs_mlt_stp .

* ASSIGN FIELD NAME TO FIELD SYMBOL
      wlv_fieldname = wla_xml_wa-name.
* ASSIGN FIELD VALUE TO FIELD SYMBOL
      wlv_fieldvalue = wla_xml_wa-value.

      CONDENSE wlv_fieldname.
*USE FIELD SYMBOLS TO FILL THE VALUES FROM
*WL_XML_WA TO STRUCTURE WA_LISTE_EVT
      ASSIGN wlv_fieldname TO <f_fieldname>.
      ASSIGN wlv_fieldvalue TO <f_value>.
      ASSIGN COMPONENT <f_fieldname> OF STRUCTURE wla_psl TO <wa>.
      <wa> = <f_value>.
*APPEND LINE OF WA_PSL TO TABLE WT_PSL-PSL
      IF wlv_fieldname = wc_cod_trs_mlt_stp.
        APPEND wla_psl TO wlt_psl-psl.
        CLEAR wla_psl.
*COUNTER TO SURPASS THE FIRST OCCURENCE OF FIELDNAME 'EVT'
        wlv_count = wlv_count + 1.
      ENDIF.
      UNASSIGN : <wa>, <f_fieldname>, <f_value>.
      CLEAR : wlv_fieldname, wlv_fieldvalue .
    ELSEIF
* TO APPEND ALL THE PSL ITEMS FOR SINGLE LINE OF EVT
* WLV_COUNT <> 1 MEANS OCCURENCE OF NEW DATA FOR LEVEL2 OF TS
      wla_xml_wa-name = wc_evt AND wlv_count <> 1.
      APPEND LINES OF wlt_psl-psl TO wla_evt-liste_psl-psl.
      APPEND wla_evt TO fpc_wa_liste_evt-liste_evt-evt.
      CLEAR : wlt_psl-psl[], wla_evt .
    ENDIF.
  ENDLOOP.

* TO APPEND THE LAST RECORD TO LEVEL 2 AND LEVEL 4 OF TS
  APPEND LINES OF wlt_psl-psl TO wla_evt-liste_psl-psl.
  APPEND wla_evt TO fpc_wa_liste_evt-liste_evt-evt.
  CLEAR wla_evt .

  FREE : wlt_psl-psl[].

ENDFORM.                    " F_CREATE_FILE

Aug 23, 2011

Debugging workflows and generating sub-workflows

Debugging workflows and generating sub-workflows

Comment:
Workflow Debugging
First of all, you cannot set breakpoints in a workflow, so I assume you mean that you have set a break-point in a method used in one of the task's used in your workflow?
If so, and if this task-method is a background method (i.e. a non-dialog task), debugging is not possible, since a background method, as the name states, is executed in another context in background.
To see how the workflow passes values from/to the different container's, you can use transaction SWUD (to see if the values needed for your method, are binded correctly).
Other useful tools for workflow error search, are: SWEL (first turn on even trace with SWELS) or simply look at the workitems created to see what kind of errors they may have encountered: SWI2_FREQ f.x.
If background task, I recommend you use SWUS for the specific task in question to create a WorkItem. Find the workitem with SWI2_FREQ, then display it. From there, display Container, to see the outcome.
You can debug the method, from SWO1 for the Object Type owning the method. From SWO1 simply click the test button. Then click "create instance". Execute the method for the object instance and you will be able to debug the method.

Generating Sub Workflow
1. Add one of your subflows to the main workflow as an activity step and define the binding. This subflow is just a place-holder and will be replaced by another subflow when the workflow runs.
2. In the step definition specify "Task to be determined using an expression" and specify which container element (or expression) contains the subflow ID to be used.
At run time, the place-holder subflow will be replaced by the subflow that is specified by the expression. In other words this expression reads the table that you created to find the subworkflow to call and this subworkflow is called by the main workflow instead of the (static) place-holder subflow.
Finding out the Object Types involved
  • Switch the event trace ON (Tcode SWELS), carry out your transaction and view the event log (Tcode SWEL).
  • If there is a standard event then the trace will tell you the name of the object and the event raised.
  • Otherwise create your own object and events and trigger it (them) using FM "SWE_EVENT_CREATE".

LSMW Step by Step

LSMW Step by Step

Go to transaction LSMW.
Enter Project name    : zkn_lsmw.
      Subproject name : zkn_lsmw.
      Object name     : zkn_lsmw.
Click on Create entry (Shift+f1) button.
It will ask for description, Give description for
      Project name    : zkn_lsmw project.
      Subproject name : zkn_lsmw subproject.
      Object name     : zkn_lsmw object.
Click on Continue(f8) button.
It will takes u 2 the LSMW steps screen and first step radio button already selected. 

Step1  ( Maitain object attributes ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Change object attributes" screen will appear.
Select Batch Input Rcording radio button.
Give Recording : zkn_rec and press Recordings:Overview button.
"Recordings of project 'ZKN_LSMW' : Overview" screen will apper.
Click on Create Recording(ctrl+f1) button.
It will gives u a small popup screen, here u can give
                Recording   : zkn_rec
                Description : zkn_rec recording
                Owner       : OBTDEV10, press Enter.
It will ask u for Transaction code.
                Transaction code : zknmp, press enter.
It will takes u 2 the zknmo transaction.
Give dummy vales and come back.
It takes u 2 the "Create Recording" screen.
Select 'BDC_CURSOR' and press 'Default all' button.
It will gives the Information popup screen, press 'Enter'.
Save and Back.
Then Back.
Then Save and Back.
Now u came back to  LSMW steps screen and second radio button will checked here already. 

Step2  ( Maitain source structures ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Change source structures" screen will appear.
Click on 'Create structure (ctrl+f4)' button.
It will gives a popup screen, here u can give
                Source structure : zkn_str
                Description      : zkn_str source structure, and press enter.
Then Save and Back.
Now u came back to  LSMW steps screen and third radio button will checked here already. 

Step3  ( Maitain source fields ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Change source fields" screen will appear.
Select zkn_str and press 'Copy fields (ctrl+f8)' button.
It will gives a popup screen, here u can select
                From data file (field names in 1 line ) radio button, and press 'Enter'.
It will gives another popup screen, here u can give
                Number of fields  : 6
                Max.Record length : 100 , and press 'Enter'.
It will gives another popup screen, here u can give path
                File name : "c:\windows\desktop\text.txt"
                Data format : ASC, and press 'Tranfer' button.
Then Save and Back.
Now u came back to  LSMW steps screen and fourth radio button will checked here already. 

Step4  ( Maitain structure relations ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Change structure relations" screen will appear.
Save and Back.
Now u came back to  LSMW steps screen and fifth radio button will checked here already. 

Step5  ( Maitain field mapping coversion rules ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Change field mapping coversion rules" screen will appear.
Select fields one by one and press 'Source field(ctrl+f2)' button.
It will givs u a popup screen, here u select related source field and press 'Enter'.
Repeate this process for all fields.
Then Save and Back.
Now u came back to  LSMW steps screen and 6th radio button will checked here already. 

Step6  ( Maintain fixed values, translations, user-defined routines ) :-
Here we con't do any thing.
Select next radio button(7th). 

Step7  ( Specify files ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Specify files (Change)" screen will appear.
Select "Legacy data" and press 'Create entery(ctrl+f2)' button.
It gives a "File on front end : Edit properties" popup screen.
Here        File        : "c:\windoes\desktop\text.txt"
                Description : Data uploading using LSMW
                Select 'Tabulator' radio button.
                Check 'Field names at the beginning of the file'.
                Uncheck 'Order of fields as in source structure definition.
Press 'Enter'.
Then Save and Back.
Now u came back to  LSMW steps screen and 8th radio button will checked here already. 

Step8  ( Assign files ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Assign files (Change)" screen will appear.
Then Save and Back.
Now u came back to  LSMW steps screen and 9th radio button will checked here already. 

Step9  ( Read data ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Read data for zkn_lsmw, zkn_lsmw, zkn_lsmw" screen will appear.
Give Transaction number 1 to 100, press 'Execute(f8)' button.
Back and Back.
Now u came back to  LSMW steps screen and 10th radio button will checked here already. 

Step10  ( Display read data ) :-
Click on Execute(ctrl+f8) button.
It will gives a popup screen, give
                From line : 1
                To line   : 100, press 'Enter'.
"LSM Workbench: Display read data" screen will appear.
Back.
Now u came back to  LSMW steps screen and 11th radio button will checked here already. 

Step11  ( Convert data ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Convert data for zkn_lsmw, zkn_lsmw, zkn_lsmw" screen will appear.
Give Transaction number 1 to 100, press 'Execute(f8)' button.
Back and Back.
Now u came back to  LSMW steps screen and 12th radio button will checked here already. 

Step12  ( Display converted data ) :-
Click on Execute(ctrl+f8) button.
It will gives a popup screen, give
                From line : 1
                To line   : 100, press 'Enter'.
"LSM Workbench: Display converted data" screen will appear.
Back.
Now u came back to  LSMW steps screen and 13th radio button will checked here already. 

Step13  ( Create batch input session ) :-
Click on Execute(ctrl+f8) button.
"LSM Workbench: Create batch input session" screen will appear.
Check 'Keep batch input session(s)?' check box, and press 'Execute(f8)' button.
It will gives an Information popup screen , press 'Enter'.
Now u came back to  LSMW steps screen and 14th radio button will checked here already. 

Step14  ( Run batch input session ) :-
Click on Execute(ctrl+f8) button.
"Batch input : Session ovrview" screen will appear.
Press 'Process(f8)' button.
It will gives a popup screen.
Select run mode Background/foreground , and press 'Process' button.
It will takes u 2 the actual transaction if u selected foreground option.
Press'Enter'.

Data upload using "LSMW" is successfully done.
-------------------------------------------------------------------------------------------------
Go to se11 and check for the data uploaded or not.