Quantcast
Channel: SCN : Document List - ABAP Development
Viewing all 935 articles
Browse latest View live

SAP-PP-CRP - class based Capacity Evaluation and Leveling - CL_PRPL_*

$
0
0

Hi guys,

I am currently working on a capacity planning and evaluation report trying to use SAP standard objects or functions.

 

So far I was testing and analyzing the following ABAP-Classes:

CL_PRPL_CAP_WC_PERIOD_AREA

CL_PRPL_CAP_WC_PERIOD_HELPER

CL_PRPL_CAPACITY_LOAD

CL_PRPL_CAPACITY_LOAD_FEEDER

CL_PRPL_CONSTANTS

CL_PRPL_CONSTANTS_CAPA

CL_PRPL_DAYS_SUPPLY_FEEDER

CL_PRPL_SALES_ORD_DELAY_FEEDER

 

I am able to show capacity evaluation tables (standard + detailed view) as seen in CM0X-transactions based on a complex and rich selection-screen (using class framework CL_PRPL_CAPACITY_LOAD). The next goal to achieve is to provide dispatching/reallocating functions as you see in the capacity leveling section of SAP ECC (e.g. transactions CM22/CM23/CM28).

I have now reached a certain point, from where I don't know how to go ahead... The question that comes up now is are the classes capable of providing such functions? From a technical viewpoint (using and handling the class methods) I don't know how to go on... or if there generally is any function for it.

 

Is somebody of you familiar with the classes I mentioned above?

Are there any other systematical approaches to access capacity (evaluation) data and handle it via dispatching/deallocating or deleting (preferably SAP standard objects or function modules, function groups)?

 

Best regards

Stefan


Creating an Inbound IDOC in the same system.

$
0
0

The requirement is to create an Inbound IDOC in the same system. The input data can be from an input file with values in it.

 

We can create a custom program and call function module 'IDOC_INBOUND_WRITE_TO_DB' to create the Inbound IDOC.

 

1. Populating the Data Record:


  DATA:  lst_MATHEAD TYPE E1segment1,  
              lst_KEY   
TYPE E1segment2,

 

  DATA: li_idoc_data        TYPESTANDARDTABLEOF edidd,

             lw_idoc_data      TYPE edidd.

 

  CONSTANTS: lc_MATHEAD TYPE edilsegtyp  VALUE'HEAD',
                        lc_KEY 
TYPE edilsegtyp  VALUE'KKEY'.

 

* Header
Populate lw_idoc_data-sdata.
lw_idoc_data-hlevel =  01.
lw_idoc_data-segnam = <Header Segment Name>.
APPEND lw_idoc_dataTO li_idoc_data.
CLEAR : lw_idoc_data.

* Item
LOOPAT<Item Data>.
Populate lw_idoc_data-sdata.
lw_idoc_data-hlevel =  02.
lw_idoc_data-segnam = <Item Segment Name>.
APPENDlw_idoc_dataTO li_idoc_data.
CLEAR : lw_idoc_data.
ENDLOOP.

 

2. Populating the Control Record:

Getting the name of the current logical system we are working in:

 

CALLFUNCTION'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
OWN_LOGICAL_SYSTEM                   = lv_logsys
.
IF SY-SUBRC <> 0.
ENDIF.

 

lw_edidc-SNDPRN = lw_edidc-rcvprn = lv_logsys.

lw_edidc-status = '64'.
lw_edidc-direct = '2'.     
lw_edidc-stdmes =
'ARTMAS'.
lw_edidc-mestyp =
'ARTMAS'.

SELECT  single sndprt
FROM edp21
INTO l_sndprt
WHERE sndprn = lv_logsys

AND   mestyp = ‘ARTMAS’

AND   mescod = ''
AND   mesfct = ''.

IF sy-subrc EQ0.
rec_edidc-rcvprt = l_sndprt.
rec_edidc-sndprt = l_sndprt.
ENDIF.



lw_edidc-idoctp =
'ARTMAS05'.

lw_edidc-rcvpor = maintained in Set
lw_edidc-sndpor  =  maintained in Set


3. Call the IDOC creating Function module:

 

DATA: lw_edids TYPE edids,

           lv_sysubrc  TYPE sysubrc.

 

CALLFUNCTION'IDOC_INBOUND_WRITE_TO_DB'
EXPORTING
pi_status_message      = lw_edids
IMPORTING
pe_state_of_processing = lv_sysubrc
TABLES
t_data_records         = li_idoc_data
CHANGING
pc_control_record      = lw_edidc
EXCEPTIONS
idoc_not_saved         =
1
OTHERS                 = 2.

Delete custom tcodes for deleted custom reports

$
0
0

Why did we get the issues

 

One great security action on our systems last year was to delete and optimize hundreds of old and unsecure programs. But after that huge clean-up campaign we sometimes got shortdumps of type LOAD_PROGRAM_NOT_FOUND on our production system.

 

The reason was, that someone had called an existing transaction, where the assigned report has been deleted. This happens, because you can delete reports in SE38/SE80 that are assigned to a tcode in table TSTC. There is no check like a where-used list for that.

 

So I designed a report to list and optionally delete custom tcodes from tstc, where an assigned type 1 executable report is missing.

 


1. Get tcodes from database with missing type 1 reports

 

*  Left outer JOIN get TCODE/REPORT couples

   SELECT t~tcode t~pgmna p~progname   FROM  tstc AS t

                            LEFT OUTER JOIN  reposrc AS p

                                         ON  p~progname = t~pgmna

                                       INTO  CORRESPONDING FIELDS OF TABLE xt_tc

   WHERE  t~pgmna                        NE  space

   AND    t~cinfo                        EQ  xk_cinfo_80. "Type 1 only

                                                                                                                                                                                                                                                              

*  Delete entries for existing reports

   DELETE  xt_tc  WHERE progname         NE  space.

 

First all couples of tcodes and report names are merged in a left outer join of tables TSTC and REPOSRC. We nned those entries, where the join doesn't find entries in tables REPOSRC. Therefore all entries, where the program name is filled from table REPOSRC, are not of interest, In our internal table we now have all tcode entries with missing type 1 reports.

 

2. List all custom tcodes with missing type 1 reports

 

   CLEAR                                     xv_count.

 

*  Sorted list of tcodes without existing reports

   SORT  xt_tc.

                                                                                                                                                                                                                                                              

   LOOP                                  AT  xt_tc ASSIGNING <x_tc>.

     CHECK  <x_tc>-tcode(1)              CA  'YZ'     "Custom namespace

     OR     <x_tc>-tcode(5)              EQ  '/OWN/'. "Own namespace

                                                                                                                                                                                                                                                              

     ADD 1                               TO  xv_count.

                                                                                                                                                                                                                                                              

     WRITE:  /1                              <x_tc>-tcode COLOR COL_KEY,

                                             <x_tc>-pgmna.

     xv_tcode                             =  <x_tc>-tcode.

     HIDE                                    xv_tcode.

     CLEAR                                   xv_tcode.

   ENDLOOP.

                                                                                                                                                                                                                                                              

   IF  xv_count                         EQ  0.

     WRITE: /1                              text-ndt COLOR COL_TOTAL."No transaction to delete can be found

   ENDIF.

 

AT LINE-SELECTION.

                                                                                                                                                                                                                                                              

  IF  NOT  xv_tcode                      IS  INITIAL.

    CALL  FUNCTION                           'RS_TOOL_ACCESS'

      EXPORTING

         operation                        =  'CROSSREF'

         object_name                      =  xv_tcode

         object_type                      =  'TRAN'.

  ENDIF.

 

For we only want to delete custom tcodes or tcodes of our own namespace, we can list all found tcodes in a loop and check for the right prefix.The purple marked lines have to be adjusted in other systems. At line selection the where-used list of each tcode can be called.

 

3. Option to delete tcodes via SE80 and transport request (with break option)

 

PARAMETERS: xp_del     TYPE flag AS CHECKBOX DEFAULT space."delete option

 

*   Delete TCODE via SE80

    IF  xp_del                           EQ  'X'.

      CALL  FUNCTION                         'RS_TOOL_ACCESS'

        EXPORTING

           operation                      =  'DELETE'

           object_name                    =  <x_tc>-tcode

           object_type                    =  'TRAN'

           with_objectlist                =  'X'.

                                                                                                                                                                                                                                                              

*      continue?

       CALL FUNCTION 'POPUP_TO_CONFIRM'

         EXPORTING

           titlebar                       =  text-h01 "Tcode deletion process

           text_question                  =  text-q01 "Continue with next tcode?

           display_cancel_button          =  space

         IMPORTING

           answer                         =  xv_answer

         EXCEPTIONS

           OTHERS                        =  0.

                                                                                                                                                                                                                                                              

       IF  xv_answer                    NE  '1'.

         EXIT.

       ENDIF.

     ENDIF.

 

Normally we will run this programm in list mode without update first to see the result. If the result seems okay, whe can start it with the delete option. This is within the list loop. To delete the tcode function RS_TOOL_ACCESS (behaves like SE80) is called. This deletion will be added to a transport request. After each deletion there is the posibility to leave the loop,

 

4. The complete report

 

REPORT  zs_check_tcode_prog.

                                                                                                                                                                                                                                                              

TYPES: BEGIN OF x_tc,

         tcode         TYPE tcode,

         pgmna         TYPE program_id,

         progname      TYPE progname,

       END   OF x_tc.

                                                                                                                                                                                                                                                              

DATA: xv_answer        TYPE string.

DATA: xv_count         TYPE i.

DATA: xv_tcode         TYPE tcode.

DATA: xt_tc            TYPE TABLE OF x_tc.

                                                                                                                                                                                                                                                              

CONSTANTS: xk_cinfo_80 TYPE syhex01 VALUE '80'.

                                                                                                                                                                                                                                                              

FIELD-SYMBOLS <x_tc>   TYPE x_tc.

                                                                                                                                                                                                                                                              

PARAMETERS: xp_del     TYPE flag AS CHECKBOX DEFAULT space."delete option

                                                                                                                                                                                                                                                              

                                                                                                                                                                                                                                                              

START-OF-SELECTION.

                                                                                                                                                                                                                                                              

   CLEAR                                     xv_count.

                                                                                                                                                                                                                                                              

*  Left outer JOIN get TCODE/REPORT couples

   SELECT t~tcode t~pgmna p~progname   FROM  tstc AS t

                            LEFT OUTER JOIN  reposrc AS p

                                         ON  p~progname = t~pgmna

                                       INTO  CORRESPONDING FIELDS OF TABLE xt_tc

   WHERE  t~pgmna                        NE  space

   AND    t~cinfo                        EQ  xk_cinfo_80.

 

*  Delete entries for existing reports

   DELETE  xt_tc  WHERE progname         NE  space.

                                                                                                                                                                                                                                                              

*  Sorted list of tcodes without existing reports

   SORT  xt_tc.

                                                                                                                                                                                                                                                              

   LOOP                                  AT  xt_tc ASSIGNING <x_tc>.

     CHECK  <x_tc>-tcode(1)              CA  'YZ'     "Custom namespace

     OR     <x_tc>-tcode(5)              EQ  '/OWN/'. "Own namespace

                                                                                                                                                                                                                                                              

     ADD 1                               TO  xv_count.

                                                                                                                                                                                                                                                              

     WRITE:  /1                              <x_tc>-tcode COLOR COL_KEY,

                                             <x_tc>-pgmna.

     xv_tcode                             =  <x_tc>-tcode.

     HIDE                                    xv_tcode.

     CLEAR                                   xv_tcode.

                                                                                                                                                                                                                                                              

*   Delete TCODE via SE80

    IF  xp_del                           EQ  'X'.

      CALL  FUNCTION                         'RS_TOOL_ACCESS'

        EXPORTING

           operation                      =  'DELETE'

           object_name                    =  <x_tc>-tcode

           object_type                    =  'TRAN'

           with_objectlist                =  'X'.

                                                                                                                                                                                                                                                              

*      continue?

       CALL FUNCTION 'POPUP_TO_CONFIRM'

         EXPORTING

           titlebar                       =  text-h01 "Tcode deletion process

           text_question                  =  text-q01 "Continue with next tcode?

           display_cancel_button          =  space

         IMPORTING

           answer                         =  xv_answer

         EXCEPTIONS

           OTHERS                        =  0.

 

       IF  xv_answer                    NE  '1'.

         EXIT.

       ENDIF.

     ENDIF.

   ENDLOOP.

                                                                                                                                                                                                                                                              

   IF  xv_count                         EQ  0.

     WRITE: /1                              text-ndt COLOR COL_TOTAL."No transaction to delete can be found

   ENDIF.

 

AT LINE-SELECTION.

                                                                                                                                                                                                                                                              

  IF  NOT  xv_tcode                      IS  INITIAL.

    CALL  FUNCTION                           'RS_TOOL_ACCESS'

      EXPORTING

         operation                        =  'CROSSREF'

         object_name                      =  xv_tcode

         object_type                      =  'TRAN'.

  ENDIF.

 

We have deleted nearly 150 custom tcodes in this way.

 

5. Possible Enhancements

 

For this sample program is for type 1 executable reports only, you also may have to find tcodes for module pools and function groups. Then you need to change the selection on field TSTCT-CINFO (remove the X80 limitation).

 

6. Further remaining issues

 

After deletion of the tcode the transaction can't be called anymore. But it may be still assigned to some menus or in the favourites. For this may be different between DEV and PROD systems I still have no solution for it.

Cancelling a Work item / User Decision Step based on an Event Using “Wait for Event Step”

$
0
0

Prerequisites: Basic Knowledge on Workflow

 

Summary: In this scenario we use a workflow step when an inbound delivery is created . The workflow is routed to a Buyer who can approve or reject the request.

If the Workflow is approved a PGR is created .

 

We encountered a case where the PGR could also be done manually before the Workflow approval.In such cases the User Decision Step which was waiting for buyer to approve should be cancelled.

 

Process:

Create a fork with one branch having the User Decision Step and its subsequent steps.

1.png

 

In the other branch

Create “Wait for Event “Step with the Event which should be caught by the Object. In this scenario we are capturing the Event when a PGR is done for a Inbound Delivery.

 

2.png

 

We use a process control step once the event is triggered and the Workitem in the user’s inbox gets cancelled and will not show up in the inbox/UWL.

3.png

 

The Workflow Template is as shown below:

 

4.png

 

 

Testing the Process:

 

Create a inbound delivery which will trigger a approval to the Buyer. The Workitem can be seen in the Buyer's inbox.

 

Goto Transaction VL32N and Press Post Goods Reciept to create a Goods Movement.

 

Check the Buyer's inbox after fews seconds . The Approval Workitem would have disappeared from the Inbox / UWL.

Webcam in ABAP via ActiveX

$
0
0


Playing With ActiveX in ABAP


Introduction:

In this document i will show you how to access your webcam in ABAP CFW via ActiveX controls and I will give you idea how to play with ActiveX .

 

Requirement:

Access Webcam/media player or any thing in ABAP via ActiveX .

I'd seen some issue How to CALL WEBCAM in SAP and decided to write a document.


Issue:

customer wants everything on ABAP screen not 3rd party eg. - 1) On security gate they want capture visitors photo but only ABAP screen

                                                                                                                                2) In Weighment system access/read COM port data but via ABAP only

                                                                                                                                3) RDP server get connected client IP

some times just for playing with ABAP means media player and other .


Solution:


1) You can create your own ActiveX control in VB6.0 , VB.net / C# - ActiveX - Wikipedia, the free encyclopedia

or download free available ActiveX .


2) Register it via Regsvr32 [/u] [/s] <OCX File Name>

 

3) Create your proxy class for our ActiveX control by inheriting CFW class CL_GUI_CONTROL and access methods.

 

4) Create your ABAP program and use your class and show your activeX

 

For understanding whole process please read blog by Thomas Jung - Using Classic ActiveX Controls in the ABAP Cont... | SCN

 

Example:

Access Webcam in ABAP -


1) (due to some company policy restriction) Here for ActiveX i'm gonna used already developed activeX  - Video Capture ActiveX SDK | VideoCap SDK ActiveX  - just download and install it even you don't need to register it.


2) Create your Proxy class ycl_gui_webcam- download it from My GitHub


Class.JPG


 

 


3) Create your program ygui_webcam - download it from My GitHub


Program.JPG


Download - Aashish28/ABAP · GitHub


Run your program -


webcam.JPG


Just Try It and Enjoy

 

You can also try it with your Media Player

Media.jpg


Goods Receiving slip printout - Example for using a Template

$
0
0

A template is a kind of table in a smart form which has a fixed layout i.e. the layout is defined before hand.

 

This is a example form for using Templates and Bar Codes in a Smart form:

 

Following are the Form attributes,Form Interface and Global Definitions:

 

image1.png

image1.png

image1.png

image1.png

 

 

Following is the output of the GR slip:

 

image1.png

 

 

For Bar code a character format has to be created;like:

 

image1.png

Following is the attached XML file for the form:

Create Dynamic Table using RTTS and display in ALV

$
0
0

This document stems from the documentDynamic Internal Table iIlustrated with an example of creating the transpose of internal tablewhich explains use of field symbols, data references and creating a dynamic internal table as a transpose of an internal table using cl_alv_table_create=>create_dynamic_table.

 

Exploring into the much recommended RTTS method, I have found that not only is it more powerful but that it is more simpler than the old method. I will be using the same example as mentioned in the previous document to explain the use of RTTS.

 

As already mentioned, creation and population of dynamic internal table can be done in three steps.

  1. Creating structure
  2. Creating dynamic internal table from this structure.
  3. Populating the table.

 

While using the old technique (cl_alv_table_create=>create_dynamic_table,), the first step was fulfilled by creating a field catalog  and the second step using the above mentioned method call.

 

When creating dynamic table using RTTS, the first and second steps can be done using the methods provided by RTTS.

 

Before going into the details, I shall brief you very shortly on RTTS and its methods.

 

In ABAP Objects, there is a class-based concept called Run Time Type Information (RTTI) that you can use to determine type attributes at run time. The methods used in this class replaces statements like describe table, describe field etc.

 

Another concept Run time Type Creation (RTTC) was added to the above to create data of any type dynamically.

 

Both these together comprise the RTTS (Run time Type Services).

 

The RTTS contains a hierarchy of classes having attributes and methods that are used to perform these dynamic functions, which could be to get the attributes of a data object at run time or to create a data object dynamically.

 

 

 

Lets see our scenario again.

 

We have an internal table IT_DEMO containing three columns – vendor name (vend), Month(month), Amount Due(amt).


TYPES : BEGINOF gfirst_typ,
vend(
6TYPEc,
month(
5) TYPEc,
amt     
TYPE  i.
TYPES : ENDOF gfirst_typ.

* Input table declarations
DATA :     it_zdemo TYPETABLEOF gfirst_typ,
wa_zdemo
LIKELINEOF it_zdemo.


VENDOR

MONTH

AMOUNT DUE

V100

Jan

100

V100

Feb

250

V200

Feb

216

V300

Feb

550

V200

Mar

200

V300

Mar

310

V100

Apr

145

V100

May

350

V200

May

600

V300

May

200

V400

May

800

 

We need to create something like a transpose for this table dynamically. The output should look like this.

 

VENDOR

JAN13

FEB13

MAR13

APR13

MAY13

V100

100

250

 

145

350

V200

 

216

200

 

600

V300

 

550

310

 

200

V400

 

 

 

 

800


Step 1 – Create Structure.

 

The RTTI contains attributes and methods that are used in this hierarchy of classes to get the property of variables whether it is a field or structure or table or an object instance of a class, at run time.

 

 

 

All these methods and attributes belong to the super class cl_abap_typedescr.

 

For our purpose, we shall be using the method describe_by_data to get the data type attribute of a field in the input table.

 

We shall be calling this method from the class cl_abap_datadescr, since the destination variable is an object type ref to cl_abap_datadescr. As we are calling the method of parent class from inherited class, we should use the casting operator ‘?=’ , rather than the simple assignment operator ‘=’, to avoid any type cast error.

 

ls_component-type ?= cl_abap_datadescr=>describe_by_data( wa_zdemo-vend ).

 

Here the data type attributes of the field wa_zdemo-vend which is declared as a six character variable will be passed to ls_component-type which is data reference pointing to an object of type cl_abap_datadescr. This is the first column of the dynamic table.

 

DATA :

ls_component    TYPE cl_abap_structdescr=>component,

gt_component    TYPE cl_abap_structdescr=>component_table.

 

ls_component-name = 'VEND'.
ls_component-
type ?= cl_abap_datadescr=>describe_by_data( wa_zdemo-vend ).
APPEND ls_component TO gt_component.

 

The rest of the columns are fields Jan, Feb containing the amount for that month depending on the data of the input table. (Refer the input table example shown above to understand better)

 

*Loop through the internal table creating a column for every distinct month in the internal table
LOOPAT it_zdemo INTO wa_zdemo.
* Search the component table if the month column already exists.
READTABLE gt_component INTO ls_component WITHKEY name = wa_zdemo-month.
IF sy-subrc NE0.
* The name of the column would be the month and the data type would be same as the amount field of internal table.    
ls_component-name = wa_zdemo-month.
ls_component-
type ?= cl_abap_datadescr=>describe_by_data( wa_zdemo-amt ).
APPEND ls_component TO gt_component.
ENDIF.
CLEAR : ls_component, wa_zdemo.
ENDLOOP.

 

Now we have the components of the structure and the table. To create the structure we shall be using the method in RTTC.


Methods in RTTC were added to the RTTS type classes to facilitate the creation of types at runtime.




To create the structure, we shall be using the static method create() in the class cl_abap_structdescr.

 

DATA :   gr_struct_typ   TYPEREFTO  cl_abap_datadescr.

gr_struct_typ  ?= cl_abap_structdescr=>create( p_components = gt_component ).

 

Step 2 – Create Table.


To create a table, first we create the table type from the structure created above. For this, we use the static method create() of the cl_abap_tabledescr.


DATA :   gr_dyntable_typ TYPEREFTO  cl_abap_tabledescr.

gr_dyntable_typ = cl_abap_tabledescr=>create( p_line_type = gr_struct_typ ).


Once the table type is created, we instantiate a reference variable to point to data object of this table type.


** Dynamic Table Declarations
DATA :  gt_dyn_table     TYPEREFTOdata,
gw_dyn_line     
TYPEREFTOdata,


CREATEDATA gt_dyn_table TYPE HANDLE gr_dyntable_typ.


Similarly a reference variable of the structure is also created from the structure created as a work area of the table.


CREATEDATA  gw_dyn_line TYPE HANDLE gr_struct_typ.


Step 3 - Populate internal table.

 

Now our dynamic table is alive and we just need to populate the data. This is done the same way it was done in the earlier document Dynamic Internal Table iIlustrated with an example of creating the transpose of internal table. You access each cell of the table using field symbols. Refer the above document for more information on field symbols and data references.


Populate the dynamic table
LOOPAT it_zdemo INTO wa_zdemo.
* Avoid duplicate entries for key field Vendor.
READTABLE<gfs_dyn_table> INTO<gfs_line1> WITHKEY ('VEND') = wa_zdemo-vend.
IF sy-subrc = 0.
*if <gfs_line1> is ASSIGNED.
*  UNASSIGN <gfs_line1>.
CONTINUE.
ENDIF.

ASSIGNCOMPONENT'VEND'OFSTRUCTURE<gfs_line> TO<fs1>.
*if <fs1> is ASSIGNED.
<fs1> = wa_zdemo-vend.
UNASSIGN <fs1>.
**endif.

LOOPAT gt_component INTO ls_component.
IF ls_component-name = 'VEND'.
CONTINUE.
ENDIF.
READTABLE it_zdemo WITHKEY vend = wa_zdemo-vend month = ls_component-name INTO wa_zdemo1.
IF sy-subrc = 0.
ASSIGNCOMPONENT ls_component-name OFSTRUCTURE<gfs_line> TO<fs1>.
IF<fs1> ISASSIGNED.
<fs1> = wa_zdemo1-amt.
UNASSIGN <fs1>.
ENDIF.
ENDIF.
CLEAR : wa_zdemo1.
ENDLOOP.
APPEND<gfs_line> TO<gfs_dyn_table>.
CLEAR: <gfs_line>.
CLEAR: wa_zdemo, wa_zdemo1.
ENDLOOP.



Display the contents of dynamic table in ALV


The contents of the dynamic internal table can be displayed using the factory method in cl_salv_table.

TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table   = lo_salv_table
CHANGING
t_table        = <gfs_dyn_table>
).
CATCH cx_salv_msg .
ENDTRY.

lo_salv_table->display( ).


 

Complete Code

*&---------------------------------------------------------------------*
*& Report  ZDYNAMIC_TABLE
*&---------------------------------------------------------------------*

REPORT  zdynamic_table_rtts.
*Author : Susmitha Susan Thomas

TYPE-POOLS : slis.
TYPES : BEGINOF gfirst_typ,
vend(
6TYPEc,
month(
5) TYPEc,
amt     
TYPE  i.
TYPES : ENDOF gfirst_typ.

* Input table declarations
DATA :     it_zdemo TYPETABLEOF gfirst_typ,
wa_zdemo
LIKELINEOF it_zdemo,
wa_zdemo1
LIKELINEOF it_zdemo.

** Dynamic Table Declarations
DATA :  gt_dyn_table     TYPEREFTOdata,
gw_dyn_line     
TYPEREFTOdata,
gw_dyn_line1    
TYPEREFTOdata.

* Field Symbold Declaration
FIELD-SYMBOLS: <gfs_line>,<gfs_line1>,
<gfs_dyn_table>
TYPESTANDARDTABLE,
<fs1>.

* RTTS Declaratoins.
DATA :   gr_struct_typ   TYPEREFTO  cl_abap_datadescr,
gr_dyntable_typ
TYPEREFTO  cl_abap_tabledescr,
ls_component   
TYPE cl_abap_structdescr=>component,
gt_component   
TYPE         cl_abap_structdescr=>component_table.

* SALV Declarations.
DATA  : lo_cols TYPEREFTO cl_salv_columns,
lo_salv_table         
TYPEREFTO cl_salv_table,
lo_column
TYPEREFTO cl_salv_column,
col_name(
30),
col_desc(
20).

*START-OF-SELECTION.
* Populate the initial input table. Usually this input table contents will be populated at run time, which raises the requirement of dynamic table. The table contents are filled here for illustration purpose.
perform fill_table using :
'V100''JAN''100',
'V100''FEB''250',
'V200''FEB''200',
'V300''FEB''150',
'V200''MAR''250',
'V300''MAR''300',
'V100''APR''200',
'V100''MAY''100',
'V200''MAY''50',
'V300''MAY''125',
'V400''MAY''475'.

WRITE : / 'Initial Internal Table', /.
WRITE :/(6) 'Vendor',(12) 'Month' ,  (3) 'Amt' .
LOOPAT it_zdemo INTO wa_zdemo.
WRITE :/ wa_zdemo-vend, wa_zdemo-month, wa_zdemo-amt.
ENDLOOP.

* Create structure of dynamic internal table - Vendor Jan13 Feb13 Mar13 ....
ls_component-name =
'VEND'.
ls_component-
type ?= cl_abap_datadescr=>describe_by_data( wa_zdemo-vend ).
APPEND ls_component TO gt_component.

*Loop through the internal table creating a column for every distinct month in the internal table
LOOPAT it_zdemo INTO wa_zdemo.
* Search the component table if the month column already exists.
READTABLE gt_component INTO ls_component WITHKEY name = wa_zdemo-month.
IF sy-subrc NE0.
* The name of the column would be the month and the data type would be same as the amount field of internal table.
ls_component-name = wa_zdemo-month.
ls_component-
type ?= cl_abap_datadescr=>describe_by_data( wa_zdemo-amt ).
APPEND ls_component TO gt_component.
ENDIF.
CLEAR : ls_component, wa_zdemo.
ENDLOOP.

gr_struct_typ  ?= cl_abap_structdescr=>create( p_components = gt_component ).
gr_dyntable_typ = cl_abap_tabledescr=>create( p_line_type = gr_struct_typ ).

CREATEDATA:
gt_dyn_table
TYPE HANDLE gr_dyntable_typ,
gw_dyn_line
TYPE HANDLE gr_struct_typ,
gw_dyn_line1
TYPE HANDLE gr_struct_typ.

ASSIGN gt_dyn_table->* TO<gfs_dyn_table>.
ASSIGN gw_dyn_line->* TO<gfs_line>.
ASSIGN gw_dyn_line1->* TO<gfs_line1>.
*
** Populate the dynamic table

*
LOOPAT it_zdemo INTO wa_zdemo.

* Avoid duplicate entries for key field Vendor.
READTABLE<gfs_dyn_table> INTO<gfs_line1> WITHKEY ('VEND') = wa_zdemo-vend.
IF sy-subrc = 0.
*if <gfs_line1> is ASSIGNED.
*  UNASSIGN <gfs_line1>.
CONTINUE.
ENDIF.

ASSIGNCOMPONENT'VEND'OFSTRUCTURE<gfs_line> TO<fs1>.
*if <fs1> is ASSIGNED.
<fs1> = wa_zdemo-vend.
UNASSIGN <fs1>.
**endif.

LOOPAT gt_component INTO ls_component.
IF ls_component-name = 'VEND'.
CONTINUE.
ENDIF.
READTABLE it_zdemo WITHKEY vend = wa_zdemo-vend month = ls_component-name INTO wa_zdemo1.
IF sy-subrc = 0.
ASSIGNCOMPONENT ls_component-name OFSTRUCTURE<gfs_line> TO<fs1>.
IF<fs1> ISASSIGNED.
<fs1> = wa_zdemo1-amt.
UNASSIGN <fs1>.
ENDIF.
ENDIF.
CLEAR : wa_zdemo1.
ENDLOOP.
APPEND<gfs_line> TO<gfs_dyn_table>.
CLEAR: <gfs_line>.
CLEAR: wa_zdemo, wa_zdemo1.
ENDLOOP.

TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table   = lo_salv_table
CHANGING
t_table        = <gfs_dyn_table>
).
CATCH cx_salv_msg .
ENDTRY.

* get columns object
lo_cols = lo_salv_table->get_columns( ).

*…Individual Column Names
LOOPAT gt_component INTO ls_component.
TRY.
col_name = ls_component-name.
lo_column = lo_cols->get_column( col_name ).
" < <
IF col_name = 'VEND'.
col_desc =
'Vendor'.
ELSE.
CONCATENATE col_name '''13'INTO col_desc.
ENDIF.
lo_column->set_medium_text( col_desc ).
lo_column->set_output_length(
10 ).
CATCH cx_salv_not_found.                            "#EC NO_HANDLER
ENDTRY.
ENDLOOP.
* display table

lo_salv_table->display( ).


FORM fill_table
USING p_fld1 TYPE gfirst_typ-vend
p_fld2
TYPE gfirst_typ-month
p_fld3
TYPE gfirst_typ-amt.

clear wa_zdemo.
wa_zdemo-vend = p_fld1 .
wa_zdemo-month = p_fld2.
wa_zdemo-amt = p_fld3.
APPEND wa_zdemo TO it_zdemo.

ENDFORM.                    "FILL_TABLE


Output




Acknowledgements

The figures of RTTS class hierarchy were taken from the TAW study material.

Program to extract any ALV in background to Excel

$
0
0

The standard behavior of ECC when running a ALV report in background of sending the output to spool, which of course can be converted to a html table or plain text file, is slightly frustrating. What most end user would like is the results in a spread sheet. Of course many solutions are possible but the approach I most recently took was to develop a ALV scheduler program by which I mean a program that will run any other program that outputs an ALV and save the ALV contents to an excel readable format. This new program then either saves this content to the server or emails it to a specified address. As the program is quiet versatile, being able to extract any ALV, I thought I could share it as it may be of use to others.

 

The file format I have used is the xml for excel format and the reason for this choice was the easy integration of this format using the class CL_SALV_EXPORT_DB_STORAGE. Although, xml may not be the first format the springs to mind when you think spreadsheet I found that most users don't really care as long as the file open with excel and this is what will happen with the xml excel file due to the processing instructions given you have a fairly standard windows setup with office. In the future I would like to add the option to save the output to xlsx using the really nice looking set of classes from abap2xlsx - ABAP Development - SCN Wiki but I'm not sure when it will be finished.

 

Anyway, for anyone whose interested the code is attached as three text files. One for the main program, one for the top include and one for the forms. I had also wanted to attach a Nugget file generated using SAPlink but I'm getting an error that they content type is not permitted.

 

So here's an example of how it works. In this example, I want to run the same program ZSP_BOREPORT twice but with different variants. So I enter my program name twice in the first select options

 

Image.png

Then in the second select options we enter the variants with which we want each run of the program to be executed

Image.png

Then on the rest of the selection screen we specify that we want the output of the different ALVs saved as sheets of one file rather than separate files and also that we want the sheets named after the variants. We also give a name to our file. Finally in the lowest box we specify that we want to save to the server rather than email out the results and we specify the path where we would like the file saved.

Image.png

Then once we execute we have a file that looks like this:Image.png

Of course the point of this program is not to run it in foreground but to run it in the background. This does add another level of abstraction or complexity as we have to schedule this ALV background program to run other program to extract their data in the background. However, I have found that the slight increase in complexity is more than compensated for by the user friendly format the data comes out in.

 

That's about everything. I hope it is of use to someone.


Spain Modelo 340 - Interval OSS Note and Abap example

$
0
0

Hello,

 

For Spain, there is a standard transaction that allow you generate the monthly declaration called M340.

 

The standard transaction is S_E4A_94000356 - Report RFIDESM340

 

This transaction generates a report that is not totally complete, because the Interval columns are not populated, due to an absence of a counter dependent on the client business requirements.

 

to be able to populate the interval columns :

 

Step 1 : Implement OSS Note 1392825 - Modification of Exit LGL_RPT_EXIT_GET_ACC_INTERVAL.

 

Step 2 : Once Exit activated, you can start coding to populate the interval columns :

 

bellow the example used :

=============================

*&---------------------------------------------------------------------*

*&  Include           ZEXITM340

*&---------------------------------------------------------------------*

*types declaration

TYPES : BEGIN OF t_counter,

          belnr      LIKE tax_line_input-belnr,

          mwskz      LIKE tax_line_input-mwskz,

          fcount(3)  TYPE n,

          lcount(3)  TYPE n,

        END OF t_counter.

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

* data declaration

DATA lw_counter(3) TYPE n.

DATA lt_bseg       TYPE STANDARD TABLE OF bseg.

DATA ls_bseg       TYPE bseg.

DATA lw_belnr      LIKE tax_line_input-belnr.

DATA lt_counter     TYPE TABLE OF t_counter.

DATA ls_counter      TYPE t_counter.

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

 

IMPORT lt_counter FROM MEMORY ID 'ZEXITM340_Zcounter'.

 

lw_counter  =  1.

 

SELECT * FROM bseg INTO TABLE lt_bseg WHERE belnr = tax_line_input-belnr

                                        AND hkont = tax_line_input-hkont

                                        AND gjahr = tax_line_input-gjahr.

 

 

SORT lt_counter BY belnr lcount DESCENDING.

 

 

 

  READ TABLE lt_counter INTO ls_counter WITH KEY belnr = tax_line_input-belnr

                                             mwskz = tax_line_input-mwskz.

 

  IF sy-subrc = 0.

 

    CONCATENATE tax_line_input-belnr ls_counter-fcount INTO acc_int_first .

    CONCATENATE tax_line_input-belnr ls_counter-lcount INTO acc_int_last .

 

  ELSE.

 

    READ TABLE lt_counter INTO ls_counter WITH KEY belnr = tax_line_input-belnr.

 

    IF sy-subrc = 0 .

      MOVE  ls_counter-lcount TO lw_counter.

      ADD 1 TO lw_counter.

    ENDIF.

 

    CONCATENATE tax_line_input-belnr lw_counter INTO acc_int_first .

    SUBTRACT 1 FROM lw_counter.

 

    LOOP AT lt_bseg INTO ls_bseg

    WHERE mwskz  = tax_line_input-mwskz

      AND hkont BETWEEN 0070000000 AND 0070099999.

 

      lw_counter  =  lw_counter + 1.

 

    ENDLOOP.

 

 

    IF lw_counter = acc_int_first+10(3) .

      ADD 1 TO lw_counter.

    ENDIF.

 

* sometimes the lw_counter is 000 witch is due to bad selection of G/L Account in (TAX_LINE_INPUT = wa_tax_item)

* so the objectif is to correct this error hard coded way

    if lw_counter = 000.

      add 2 to lw_counter.

    endif.

 

 

    CONCATENATE tax_line_input-belnr lw_counter INTO acc_int_last .

 

    ls_counter-belnr   = tax_line_input-belnr.

    ls_counter-mwskz   = tax_line_input-mwskz.

    ls_counter-fcount  =  acc_int_first .

    ls_counter-lcount  =  acc_int_last .

 

    APPEND ls_counter TO lt_counter.

 

  ENDIF.

 

 

 

*export global data for counter

EXPORT lt_counter  TO MEMORY ID 'ZEXITM340_Zcounter'.

==========================

 

Of course you need to adapt the Exit depending on the client business requirement,

 

there is some new OSS notes regarding the modelo 340 for Spain, so do not hesitate to check and update your modelo

Enjoy!


Create Bex Broadcast settings dynamically Via ABAP Program step by step document

$
0
0

Applies to:

SAP BW

Summary

To create BEx broadcast settings via ABAP program dynamically instead of via portal.

Author(s):    Khaja Kamaluddin, Divya John, Vinay Singh.

Company:    Larsen and Toubro InfoTech.

Created on:  07 April 2014

Author Bio

   Kamaluddin has 6.4 years of experience in SAP BW and ABAP, started his career as an ABAP programmer over a period shifted to SAP BW/ BI, he worked in support and implementation projects and enhancement projects.

Vinay Singh has 3 Year of experience as a BI ABAP consultant.

Divya John has 3 years experience as an ABAP Programmer.

 

Need For Creating BEx Broadcast settings Dynamically

 

The Requirement is for pushing mails with BEx workbooks to subscribing users at a given frequency. For every user , in order to broadcast mail , settings need to be created manually in Portal . For a large number of users/subscribers it would be difficult to maintain settings manually. Hence the need for creating settings dynamically using ABAP Program.

Initially required Users and their relevant details like email id , workbook id , report name etc ate maintained in Z-Table. Settings and mail body are then created for each User and these settings are broadcast using Pre-Calculation server. Also if any settings have not been broadcast, then these settings are reprocessed and pushed.

 

In this document creation of BEx Broadcast settings using ABAP program is explained.

Assumptions:

Users for whom BEx broadcast settings are to be created are maintained in a Ztable with details like their email id , workbook id , report name etc.

 

Creating broadcast settings for the Budget Owner numbers.

  • Now that data required for broadcasting to a budget owner is stored in ZCONTROL, create settings required for broadcasting using Pre-calculation server.
  • Manually the settings can be created via. Portal as shown below.

 

Capture1.PNG

Enter the email address , authorization user in recipients tab.

 

Capture.PNG

 

Choose the method of distribution of document.

Capture.PNG

Provide email address, subject and body of mail.

Capture.PNG

Capture.PNG

 

Schedule the broadcast as per required frequency.

Capture.PNG

 

Capture.PNG

 

In above window assign variable and Pre calculation server and execute.

Capture.PNG

 

On successful execution, above log is displayed and the workbook is broadcast to the recipient.

 

Capture.PNG

The new settings created in this process is outlined in red.

 

The entire process is being done now with the ABAP program given below .

 

Advantages with the ABAP program:-

 

  • Multiple Broadcast settings can be created in one time exactions , so Workbook broadcasting can be performed for the Multiple Workbook and multiple Users at one time execution of ABAP program that we will see in below Doc .

 

  • Attachment in the Broadcasted mail can be changed by using ABAP classes and Methods such as Name and the type of the attachment can be changed as per the requirement.

 

  • Reprocessing of the Failed Broadcast settings can be executed again , because most of times the cause of failure of Broadcast settings is the time out, reprocessing ABAP program will be added in next document .

 

 

  • Troubleshooting or the Debugging is easy with the ABAP program in the scenario of any error occurs while the execution of the Workbook broadcasting .

 

ABAP program flow is given below :-

 

  • Execute program ZBEX_BROAD .
  • This program creates settings and maintains them in standard tables

RSRD_SETTING    
RSRD_SETTINGT

RSRD_SETT_NODE

RSRD_SETT_NODE_A
RSRD_SETT_NODE_T

 

And also maintains all the created settings for budget owners in Z-Table ZBROADSET

 

Here we also compose email body to which workbook will be attached and sent

 

The working of the program is as follows:

 

 

  1. 1.  The setting id’s are created by concatenating username , current date and current time separated by underscore.
  2. 2.  Populate in RSRD_SETTING, RSRD_SETTINGT, RSRD_SETT_NODE, RSRD_SETT_NODE_A, RSRD_SETT_NODE_T table the setting id and all other required fields.
  3. 3.  For mail content in html a class ZCL_RSRD_DISTRIBUTOR_MAIL is created and passed to RSRD_SETT_NODE table. This class is a copy of CL_RSRD_DISTRIBUTOR_MAIL and the method SET_BODY is changed for our requirement.

Capture.PNG

Capture.PNG

Attachments:



Figure 1.Program to create settings



Figure 2.Top include for settings program



Figure 3.Class used






Related Content

Please include at least three references to SDN documents or web pages.

Reference 1

Reference 2

Reference 3

CL_SALV_TABLE - Exception Column Text Change

$
0
0

This document helps in understanding the code to be implemented for displaying report using CL_SALV_TABLE for showing TRAFFIC LIGHTS

 

  1. Generally when displaying TRAFFIC LIGHTS, we use set_exception_column() method. When used this method, column text is displayed as ‘EXCEPTION’ for TRAFFIC LIGHTS column.
  2. Using the below code we set our custom text for the same column i.e in place of EXCEPTION for TRAFFIC LIGHTS column we can use our custom code.

 

 

**&---------------------------------------------------------------------*

**& Report ZMDR_SALV_TEST

**&

**&---------------------------------------------------------------------*

 

REPORT zmdr_salv_test.

TYPES: BEGIN OF ty_alv,

             lights(1) TYPE c, "Exception, Holding the value of the lights

             text(20) TYPE c,  "some text

            END OF ty_alv.

DATA: gs_alv TYPE ty_alv,

            gt_alv TYPE TABLE OF ty_alv,

           gr_alv TYPE REF TO cl_salv_table,

           gr_columns TYPE REF TO cl_salv_columns_table,

           gr_column TYPE REF TO cl_salv_column_table.

 

START-OF-SELECTION.

 

  gs_alv-lights = '1'.    "Color red

  gs_alv-text = 'RED SIGNAL'.

  APPEND gs_alv TO gt_alv.

 

  gs_alv-lights = '2'.    "Color yellow

  gs_alv-text = 'YELLOW SIGNAL'.

  APPEND gs_alv TO gt_alv.

 

  gs_alv-lights = '3'.    "Color green

  gs_alv-text = 'GREEN SIGNAL'.

  APPEND gs_alv TO gt_alv.

 

  CALL METHOD cl_salv_table=>factory

    IMPORTING

      r_salv_table = gr_alv

    CHANGING

      t_table      = gt_alv.

 

  gr_columns = gr_alv->get_columns( ).

gr_columns->set_exception_column( value = 'LIGHTS' ).

 

  TRY.

      gr_column ?= gr_columns->get_column( 'LIGHTS' ).

gr_column->set_medium_text( 'STATUS' ).

gr_column->set_long_text( 'STATUS' ).

gr_column->set_short_text( 'STATUS' ).

    CATCH cx_salv_not_found. "#EC NO_HANDLER

  ENDTRY.

 

 

  TRY.

      gr_column ?= gr_columns->get_column( 'TEXT' ).

gr_column->set_medium_text( 'TEXT' ).

gr_column->set_long_text( 'TEXT' ).

gr_column->set_short_text( 'TEXT' ).

    CATCH cx_salv_not_found. "#EC NO_HANDLER

  ENDTRY.

 

 

  CALL METHOD gr_alv->display.

 

Output looks like below:

 

 

 

Use the below code for changing the text of  ‘EXCEPTION’  to custom text(here I used ‘STATUS’)

 

REPORT  zmdr_salv_test.
*
TYPES: BEGIN OF ty_alv,
lights(4) TYPE c, "Exception, Holding the value of the lights
text(20) TYPE c"some text
END OF ty_alv.

DATA: gs_alv TYPE ty_alv,
gt_alv TYPE TABLE OF ty_alv,
gr_alv TYPE REF TO cl_salv_table,
gr_columns TYPE REF TO cl_salv_columns_table,
gr_column TYPE REF TO cl_salv_column_table.

TYPE-POOLS : icon.

START-OF-SELECTION.

WRITE icon_red_light TO gs_alv-lights.
*Commented below line

*  gs_alv-lights = '1'.    "Color red
gs_alv-text = 'RED SIGNAL'.
APPEND gs_alv TO gt_alv.

WRITE icon_yellow_light TO gs_alv-lights.

*Commented below line

*  gs_alv-lights = '2'.    "Color yellow
gs_alv-text = 'YELLOW SIGNAL'.
APPEND gs_alv TO gt_alv.

WRITE icon_green_light TO gs_alv-lights.

*Commented below line

 

*  gs_alv-lights = '3'.    "Color green
gs_alv-text = 'GREEN SIGNAL'.
APPEND gs_alv TO gt_alv.

CALL METHOD cl_salv_table=>factory
IMPORTING
r_salv_table = gr_alv
CHANGING
t_table      = gt_alv.

gr_columns = gr_alv->get_columns( ).

*Commented below line

*gr_columns->set_exception_column( value = 'LIGHTS' ).

TRY.
gr_column ?= gr_columns->get_column( 'LIGHTS' ).
gr_column->set_medium_text( 'STATUS' ).
gr_column->set_long_text( 'STATUS' ).
gr_column->set_short_text( 'STATUS' ).
CATCH cx_salv_not_found.                            "#EC NO_HANDLER
ENDTRY.

TRY.
gr_column ?= gr_columns->get_column( 'TEXT' ).
gr_column->set_medium_text( 'TEXT' ).
gr_column->set_long_text( 'TEXT' ).
gr_column->set_short_text( 'TEXT' ).
CATCH cx_salv_not_found.                            "#EC NO_HANDLER
ENDTRY.


CALL METHOD gr_alv->display.

 

 

 

Output looks like below:


 

Hope this helps you.

 

 

Regards,

Mohammed Rafi

Goods Receiving slip printout - Example for using a Template

$
0
0

A template is a kind of table in a smart form which has a fixed layout i.e. the layout is defined before hand.

 

This is a example form for using Templates and Bar Codes in a Smart form:

 

Following are the Form attributes,Form Interface and Global Definitions:

 

image1.png

image1.png

image1.png

image1.png

 

 

Following is the output of the GR slip:

 

image1.png

 

 

For Bar code a character format has to be created;like:

 

image1.png

Following is the attached XML file for the form:

Program to merge spool requests for a given job

$
0
0


There are sometimes specific need to create a single spool request combining number of spool requests together, generated for a given job.

The following program creates a single spool merging all the other spools creted when the job is run. The program needs to be added as the last member in the same job for which the other spool requests nee to be merged.

 

The main program is as follows:

 

REPORT  z_spool_merge NO STANDARD PAGE HEADING
                            MESSAGE-ID 00
                            LINE-SIZE 1023
                            LINE-COUNT 60.
************************************************************************
* Includes                                                             *
************************************************************************
  INCLUDE z_spool_top.     " Data Declaration
  INCLUDE z_spool_gui.     " Selection screen
  INCLUDE z_spool_cd1.     " Class definition
  INCLUDE z_spool_ci1.     " Class implementation


************************************************************************
*   START-OF-SELECTION                                                 *
************************************************************************
  START-OF-SELECTION.
    CREATE OBJECT ob_ref_application.

 

Include Programs:

 

INCLUDE z_spool_top.     " Data Declaration

************************************************************************
* Class Definition and Declaration
************************************************************************
CLASS lcl_application        DEFINITION DEFERRED.
DATA: ob_ref_application     TYPE REF TO lcl_application,
      bdcdata TYPE STANDARD TABLE OF  bdcdata WITH HEADER LINE.

 

 

 

  INCLUDE z_spool_cd1.     " Class definition

*----------------------------------------------------------------------*
*       INTERFACE if_data_declaration DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE if_data_declaration .
  TYPES: BEGIN OF ty_tbtcp,
            jobname   TYPE btcjob,
            jobcount  TYPE btcjobcnt,
            stepcount TYPE btcstepcnt,
            listident TYPE btclistid,
            pdest     TYPE sypdest,
            END OF ty_tbtcp,
            BEGIN OF ty_spoolid,
            spoolid TYPE btclistid,
            END OF ty_spoolid.
ENDINTERFACE.                    "if_data_declaration DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_application DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_application DEFINITION.

  PUBLIC SECTION.
    INTERFACES if_data_declaration.
    METHODS: constructor.

  PRIVATE SECTION.
* LOCAL DATA DECLARATION
    DATA:  lwa_tbtcp TYPE if_data_declaration~ty_tbtcp,
           ltb_tbtcp TYPE STANDARD TABLE OF if_data_declaration~ty_tbtcp,
           ltb_spoolid TYPE STANDARD TABLE OF if_data_declaration~ty_spoolid,
           lwa_spoolid TYPE if_data_declaration~ty_spoolid,
           lwa_buffer(200) TYPE c,
           ltb_buffer LIKE STANDARD TABLE OF lwa_buffer,
           ltb_buffer_final LIKE STANDARD TABLE OF lwa_buffer,
           lwa_handle TYPE sy-tabix,
           lw_rqident TYPE tsp01-rqident,
           lw_jobcount TYPE btcjobcnt.

    METHODS:   get_table_data,
               process_data.

ENDCLASS.                    "lcl_application DEFINITION
*----------------------------------------------------------------------*
*       CLASS lcl_exception DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_exception DEFINITION INHERITING FROM cx_static_check.

  PUBLIC SECTION.
    DATA: lw_text TYPE zadeu_s_ecm_data_alv-message.

    METHODS:
      constructor
        IMPORTING i_text TYPE zadeu_s_ecm_data_alv-message.

ENDCLASS.                    "lcl_exception DEFINITION

 

 

INCLUDE z_spool_ci1.     " Class implementation

----------------------------------------------------------------------*
*       CLASS lcl_application IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
  CLASS lcl_application IMPLEMENTATION.

    METHOD constructor.
      DATA: lob_exec TYPE REF TO lcl_exception.
      TRY.
          CALL METHOD me->get_table_data.
          CALL METHOD me->process_data.
        CATCH lcl_exception INTO lob_exec.
          MESSAGE s208  WITH lob_exec->lw_text.
      ENDTRY.
    ENDMETHOD.                    "constructor

    METHOD get_table_data.
      SELECT MAX( jobcount )
      INTO lw_jobcount
      FROM tbtcp
      WHERE  jobname = p_jbnam
      AND    sdldate = sy-datum.
      IF sy-subrc = 0.
        SELECT  spoolid
        INTO TABLE ltb_spoolid
        FROM  tbtc_spoolid
        WHERE jobname = p_jbnam
        AND jobcount = lw_jobcount.
      ENDIF.
    ENDMETHOD.                    "get_table_data

    METHOD process_data.
* Begin of changes************************
      DATA : w_arcpar TYPE arc_params  ,
             w_pripar TYPE pri_params ,
             w_val TYPE c .
* End of changes**************************

*   Begin of changes**********************
*      IF ltb_spoolid IS NOT INITIAL.
*        IF sy-batch = 'X'.
          CALL FUNCTION 'GET_PRINT_PARAMETERS'
            EXPORTING
              destination            = 'LOCL'
              layout                 = 'X_65_255'
              line_count             = 65
              line_size              = 255
              no_dialog              = ' '
            IMPORTING
              out_parameters         = w_pripar
              out_archive_parameters = w_arcpar
              valid                  = w_val.
*
*          NEW-PAGE PRINT ON NEW-SECTION
*                        PARAMETERS w_pripar
*                        ARCHIVE PARAMETERS w_arcpar
*                        NO DIALOG.
*          Write:/ 'Hello'.
*
*
*          NEW-PAGE PRINT OFF.
*        ENDIF.
*      ENDIF.
* End of changes*******************
      IF ltb_spoolid IS NOT INITIAL.
        LOOP AT ltb_spoolid INTO lwa_spoolid.
          CLEAR lw_rqident.
          lw_rqident = lwa_spoolid-spoolid.
          REFRESH ltb_buffer.
          CALL FUNCTION 'RSPO_RETURN_ABAP_SPOOLJOB'
            EXPORTING
              rqident              = lw_rqident
            TABLES
              buffer               = ltb_buffer
            EXCEPTIONS
              no_such_job          = 1
              not_abap_list        = 2
              job_contains_no_data = 3
              selection_empty      = 4
              no_permission        = 5
              can_not_access       = 6
              read_error           = 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.
          ELSE.
            IF ltb_buffer_final IS INITIAL.
              ltb_buffer_final = ltb_buffer.
            ELSE.
              LOOP AT ltb_buffer INTO lwa_buffer.
                APPEND lwa_buffer TO ltb_buffer_final.
              ENDLOOP.
            ENDIF.
          ENDIF.
        ENDLOOP.
        READ TABLE ltb_tbtcp INTO lwa_tbtcp INDEX 1.
        CALL FUNCTION 'RSPO_OPEN_SPOOLREQUEST'
          EXPORTING
            dest            = lwa_tbtcp-pdest
            name            = w_pripar
            suffix1         = w_arcpar
            suffix2         = w_val
            copies          = 1
            immediate_print = 'G'
            doctype         = 'LIST'
          IMPORTING
            handle          = lwa_handle.


        LOOP AT ltb_buffer_final INTO lwa_buffer.
          CALL FUNCTION 'RSPO_WRITE_SPOOLREQUEST'
            EXPORTING
              handle           = lwa_handle
              text             = lwa_buffer
            EXCEPTIONS
              handle_not_valid = 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.
        ENDLOOP.

        CALL FUNCTION 'RSPO_CLOSE_SPOOLREQUEST'
          EXPORTING
            handle           = lwa_handle
          EXCEPTIONS
            handle_not_valid = 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.
      ENDIF.
    ENDMETHOD.                    "process_data
  ENDCLASS.                    "lcl_application IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_exception IMPLEMENTATION
*----------------------------------------------------------------------*

  CLASS lcl_exception IMPLEMENTATION.
* Class for raising message & display it into the screen
    METHOD constructor.
      super->constructor( ).
      me->lw_text = i_text.

    ENDMETHOD.                    "constructor


  ENDCLASS.                    "lcl_exception IMPLEMENTATION

BATCH DETERMINATION Function Module

$
0
0

Purpose

 

This document explains how to get Batch using VB_READ_BATCH Function Module.

 

Requirement

 

We can see Batch for an Article through Transaction MMBE.

 

1.jpg

 

VB_READ_BATCH Function Module

 

The Function Module has following interface

 

2.jpg

Fill the Table  I_MCHB_KEY with Material Number, Plant and Storage Location as shown below

 

3.jpg

 

Execute the Function Module and it returns the Batch in the table E_MCHB.

 

4.jpg

 

In the Above Screen, filter the field CLABS whose Quantity is greater than zero and you get the Batch.

 

Regards

Sajid Shaik

The case of "Scalable Vector Graphics in mail attachments"

$
0
0

Recently I saw some requests to send some graphics in mail attachments.

 

I look around and as far as I know (Which is questionable....) I did not found any built in support in SAP

(Please correct me if I am wrong) .

 

The ingredients:

- SVG technology - http://en.wikipedia.org/wiki/Scalable_Vector_Graphics 
- cl_document_bcs - To send mail .

- cl_ixml - To create SVG documents which are ( surprise surprise !!! ) an XML documents .

- Some reading in http://www.w3schools.com .

 

The program included (Y_R_EITAN_TEST_10_05) send a mail message with SVG attachments .

 

SVG give us the capability to create (using code) geometric primitives and use them to compose some very nice stuff..(e.g. http://upload.wikimedia.org/wikipedia/commons/2/28/Beetle.svg)

 

The multi rectangles in "HTML5 inline SVG (2).HTM" is the result of a loop.

 

Tips: There are some open and free open source tools to create SVG files so using those can make life a little bit easier.

 

screenshot_01.png

 

screenshot_01.png

screenshot_03.png

 

screenshot_02.png


Two Different types of Parallel Processing examples

$
0
0

abhijit Passport.jpgPurpose & Overview:We all know how to upload data into SAP but many of us not aware of best possible way to upload the data in to sap. Now, if you are dealing with small volume of data then there will be no problem but when it comes to huge volume of data then execution time is important.

 

So, what will be best possible way?

 

There are different solutions available. But SAP has provided wonderful solutions called ‘Parallel Processing’.  There are two types of parallel processing available.

 

  • With Release 3.1G, SAP offers a solution to the “short nights” problem: parallel-processed background jobs. Long-running SAP reports can now implement parallel processing, which lets them parcel out the work to be done to available dialog work processes in the SAP system and then collect the results.Parallel-processing is implemented with a special variant of asynchronous RFC. It’s important that you use only the correct variant for your own   parallel processing applications: the CALL FUNCTION STARTING NEW TASK DESTINATION IN GROUP keyword.
  • Another one is the best one and most effective one. SPTA Framework. Performance wise this is best possible parallel process. It takes minimum time to execute compare to other parallel processes.

 

My attempt is to provide a good example of both and give a comparison between two parallel processes.

 

Business Requirement:In this example for both the cases we have to upload data from legacy file to Z table in SAP.

 

Lets’ Start with Process 1:

 

Step1: First create a Z table:  This is the table where we will update the data.

Create Table.jpg

Step2- Create Function Module:  We will create a function module, through which we will upload the data. Create import export parameter.


FM- New task.jpg

Step3: Function Module Coding:

FUNCTION zemp_data_upd1.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_DATA) TYPE  ZEMP_DATA OPTIONAL
*"  EXPORTING
*"     VALUE(EX_RESULT) TYPE  ZUPD_RESULT
*"----------------------------------------------------------------------
IF NOT im_data IS INITIAL.

INSERT zemp_data FROM im_data.

IF sy-subrc EQ 0.
ex_result
-empid   = im_data-empid.
ex_result
-message = 'Updated'.
ELSE.
ex_result
-empid   = im_data-empid.
ex_result
-message = 'Not-Updated'.
ENDIF.

COMMIT WORK.

ENDIF.

ENDFUNCTION.

Step4:  Build the report

Report ZABHI_PARA_PROCESS_1.

TABLES: zemp_data.

 

TYPES:

     ty_result TYPE  zupd_result,

     tty_result TYPE STANDARD TABLE OF zupd_result,

     tty_emp TYPE STANDARD TABLE OF zemp_data.

DATA:

   gt_emp TYPE tty_emp,

   gt_result TYPE tty_result.

 

DATA: gv_snd_task   TYPE i,

      gv_ptask      TYPE i,

      gv_rcv_task   TYPE i.

 

 

FIELD-SYMBOLS: <gfs_result> TYPE zupd_result.

 

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.

PARAMETERS:

   p_rfcgr TYPE spta_rfcgr OBLIGATORY MEMORY ID spta_rfcgr,

   p_file TYPE rlgrap-filename.

SELECTION-SCREEN END OF BLOCK b1.

  1. INITIALIZATION.

* Not just anybody may execute this report

  AUTHORITY-CHECK OBJECT 'S_ADMI_FCD'

    ID 'S_ADMI_FCD' FIELD 'PADM'.

  IF NOT sy-subrc IS INITIAL.

    RAISE no_authority_for_report.

  ENDIF.

 

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file .

  PERFORM f_get_file .

 

START-OF-SELECTION.

 

  PERFORM f_sub_get_data USING  p_file

                                  CHANGING gt_emp.

  DELETE FROM zemp_data WHERE empid NE space.

  IF sy-subrc = 0.

    COMMIT WORK.

  ENDIF.

 

  PERFORM f_sub_upload_data USING    gt_emp

                            CHANGING gt_result.

 

END-OF-SELECTION.

  WRITE: 'EMPLOYEE DETAILS'.

  SKIP.

  LOOP AT gt_result ASSIGNING <gfs_result>.

    WRITE:/ 'Emp-Id:', <gfs_result>-empid.

    WRITE: 'Status:', <gfs_result>-message.

  ENDLOOP.

 

*&---------------------------------------------------------------------*

*&      Form F_GET_FILE

*&---------------------------------------------------------------------*

*       text

*----------------------------------------------------------------------*

*  --> p1        text

*  <-- p2        text

*----------------------------------------------------------------------*

FORM f_get_file .

 

  CALL FUNCTION 'F4_FILENAME'

    EXPORTING

      program_name  = syst-cprog

      dynpro_number = syst-dynnr

      field_name    = ' '

    IMPORTING

      file_name     = p_file.

ENDFORM.                    " F_GET_FILE

*&---------------------------------------------------------------------*

*&      Form F_SUB_GET_DATA

*&---------------------------------------------------------------------*

*       text

*----------------------------------------------------------------------*

*      -->P_P_FILE  text

*      <--P_gt_emp  text

*----------------------------------------------------------------------*

FORM f_sub_get_data  USING    p_file TYPE localfile

                     CHANGING p_gt_tab TYPE tty_emp.

 

  DATA: ls_work_area  TYPE tty_emp,

        lv_filename   TYPE string.

 

  CLEAR lv_filename.

  MOVE p_file TO lv_filename.

 

  CALL FUNCTION 'GUI_UPLOAD'

    EXPORTING

      filename                = lv_filename

      filetype                = 'ASC'

      has_field_separator     = 'X'

    TABLES

      data_tab                = p_gt_tab

    EXCEPTIONS

      file_open_error         = 1

      file_read_error         = 2

      no_batch                = 3

      gui_refuse_filetransfer = 4

      invalid_type            = 5

      no_authority            = 6

      unknown_error           = 7

      bad_data_format         = 8

      header_not_allowed      = 9

      separator_not_allowed   = 10

      header_too_long         = 11

      unknown_dp_error        = 12

      access_denied           = 13

      dp_out_of_memory        = 14

      disk_full               = 15

      dp_timeout              = 16

      OTHERS                  = 17.

  IF sy-subrc <> 0.

* Implement suitable error handling here

  ENDIF.

 

 

ENDFORM.                    " F_SUB_GET_DATA

*&---------------------------------------------------------------------*

*&      Form F_SUB_UPLOAD_DATA

*&---------------------------------------------------------------------*

*       text

*----------------------------------------------------------------------*

*      -->P_GT_EMP  text

*      <--P_GT_RESULT  text

*----------------------------------------------------------------------*

FORM f_sub_upload_data  USING    p_gt_emp TYPE tty_emp

                        CHANGING p_gt_result TYPE tty_result.

 

  DATA: lv_lines      TYPE i,

        ls_result     TYPE zupd_result,

        ls_data       TYPE zemp_data,

        lv_msg(80) TYPE c,

        lv_taskname TYPE numc10 VALUE '0',

        lv_excp_flag  TYPE flag.

 

  FIELD-SYMBOLS: <lfs_emp> TYPE zemp_data.

 

 

  CLEAR:ls_data,

        ls_result,

        gv_snd_task,

        gv_rcv_task,

        lv_lines.

 

  DESCRIBE TABLE p_gt_emp LINES lv_lines.

*

  LOOP AT p_gt_emp ASSIGNING <lfs_emp>.

 

    gv_ptask = gv_ptask + 1.

    MOVE <lfs_emp> TO ls_data.

    CLEAR: lv_excp_flag.

    DO.

      ADD 1 TO lv_taskname.

      CLEAR lv_excp_flag.

      CALL FUNCTION 'ZEMP_DATA_UPD1'

        STARTING NEW TASK lv_taskname

        DESTINATION IN GROUP p_rfcgr

        PERFORMING process_callback_prog ON END OF TASK

        EXPORTING

          im_data               = ls_data

        EXCEPTIONS

          communication_failure = 1  MESSAGE lv_msg

          system_failure        = 2 MESSAGE lv_msg

          resource_failure      = 3 "No work processes are

          OTHERS                = 4. "Add exceptions generated by

 

*the called function module here.  Exceptions are returned to you and you can

* respond to them here.

      CASE sy-subrc.

        WHEN 0.

          ADD 1 TO gv_snd_task.

        WHEN 1 OR 2.

          CLEAR: ls_result.

 

          MOVE <lfs_emp>-empid TO ls_result-empid.

          MOVE 'Not_Updated'   TO ls_result-message.

          APPEND ls_result     TO p_gt_result.

          CLEAR ls_result.

        WHEN 3.

          lv_excp_flag = 'X'.

          WAIT UNTIL gv_rcv_task >= gv_snd_task UP TO '1' SECONDS.

        WHEN OTHERS.

          CLEAR ls_result.

      ENDCASE.

      IF lv_excp_flag IS INITIAL.

        EXIT.

      ENDIF.

    ENDDO.

  ENDLOOP.

 

*--- wait till everything ends

  WAIT UNTIL gv_rcv_task >= gv_snd_task UP TO 10 SECONDS.

 

ENDFORM.                    " F_SUB_UPLOAD_LINK

*&---------------------------------------------------------------------*

*&      Form PROCESS_UPLOAD_LINK

*&---------------------------------------------------------------------*

*       text

*----------------------------------------------------------------------*

 

*----------------------------------------------------------------------*

FORM process_callback_prog USING gv_task.

  DATA: ls_result TYPE zupd_result.

  gv_ptask = gv_ptask - 1.

  RECEIVE RESULTS FROM FUNCTION 'ZEMP_DATA_UPD1'

      IMPORTING

         ex_result   = ls_result

      EXCEPTIONS

           no_update = 1

           OTHERS    = 2.

  gv_rcv_task = gv_rcv_task + 1.

  APPEND ls_result TO  gt_result.

  CLEAR ls_result.

  1. ENDFORM.                    " PROCESS_CALLBACK_PROG

Step 5- Test the program: Activate the program and then execute it.  Select server group from existing otherwise you can create a Z server group by executing transaction code RZ12 - RFC Server Group Maintenance.

Execute p1.jpg


emp1.jpg

   Step 5: Execute it and see the result:  Employee details in Ztable will be updated and the report is also generate.


simple para-result.JPG

*------------------------------------------------------------------------PROCESS 1 IS COMPLETE ----------------------------------------------------------------------------------------------------------------*

Lets’ Start Process 2:


Step1-Creation of Ztable: For this process also, we will use same table to update employee details:  


Create Table.jpg

Step2- Create Function Module:We will create a function module, through which we will upload the data. Create import export parameter.

FM- SFP framework.jpg

Step3: Function Module Coding:

 

See the difference of two function module. In this FM no COMMIT WORK inside the function module.

 

FUNCTION zemp_data_upd.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IM_DATA) TYPE  ZEMP_DATA OPTIONAL
*"  EXPORTING
*"     VALUE(EX_RESULT) TYPE  ZUPD_RESULT
*"----------------------------------------------------------------------
IF NOT im_data IS INITIAL.

INSERT zemp_data FROM im_data.

IF sy-subrc EQ 0.
ex_result
-empid   = im_data-empid.
ex_result
-message = 'Updated'.
ELSE.
ex_result
-empid   = im_data-empid.
ex_result
-message = 'Not-Updated'.
ENDIF.


ENDIF.

ENDFUNCTION.

Step4:  Build the report:

 

REPORT zabhi_para_process_2 .

*---- ZEMP_DATA - This table is getting updated through this process

 

TABLES: zemp_data.

 

TYPE-POOLS: spta.

 

* Define a type that contains ALL the input & output data

* needed for the RFC

TYPES:

     ty_result TYPE  zupd_result,

     tty_result TYPE STANDARD TABLE OF zupd_result,

     tty_emp      TYPE STANDARD TABLE OF zemp_data.

 

DATA:

   gt_emp           TYPE tty_emp,

   gt_result        TYPE tty_result,

   gv_repid         TYPE syrepid,

   gv_error_count   TYPE syindex.

 

TYPES: BEGIN OF gty_rfcdata,

 

         BEGIN OF importing,

           emp_data LIKE  gt_emp , " TYPE ty_emp,

         END OF importing,

 

         BEGIN OF exporting,

           emp_result LIKE  gt_result , "TYPE ty_result,

         END OF exporting,

 

       END OF gty_rfcdata.

 

FIELD-SYMBOLS: <gfs_result> TYPE zupd_result.

 

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.

 

PARAMETERS:

   p_rfcgr TYPE spta_rfcgr OBLIGATORY MEMORY ID spta_rfcgr,

   p_maxtak LIKE sy-index DEFAULT '10',

   p_start LIKE sy-index DEFAULT '1',

   p_end LIKE sy-index DEFAULT '100',

   p_file TYPE rlgrap-filename.

SELECTION-SCREEN END OF BLOCK b1.

 

 

  1. INITIALIZATION.

* Not just anybody may execute this report

  AUTHORITY-CHECK OBJECT 'S_ADMI_FCD'

    ID 'S_ADMI_FCD' FIELD 'PADM'.

  IF NOT sy-subrc IS INITIAL.

    RAISE no_authority_for_report.

  ENDIF.

 

AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file .

  PERFORM f_get_file .

 

START-OF-SELECTION.

 

  PERFORM f_sub_get_data USING  p_file

                         CHANGING gt_emp.

 

  DELETE FROM zemp_data WHERE empid NE space.

  IF sy-subrc = 0.

    COMMIT WORK.

  ENDIF.

  gv_repid = sy-repid.


  CLEAR: gv_error_count.

 

  CALL FUNCTION 'SPTA_PARA_PROCESS_START_2'

    EXPORTING

      server_group             = p_rfcgr

      max_no_of_tasks          = p_maxtak

      before_rfc_callback_form = 'F_BEFORE_RFC'

      in_rfc_callback_form     = 'F_IN_RFC'

      after_rfc_callback_form  = 'F_AFTER_RFC'

      callback_prog            = gv_repid

    EXCEPTIONS

      invalid_server_group     = 1

      no_resources_available   = 2

      OTHERS                   = 3.

 

 

END-OF-SELECTION.

  WRITE: 'EMPLOYEE DETAILS'.

  SKIP.

  LOOP AT gt_result ASSIGNING <gfs_result>.

    WRITE:/ 'Emp-Id:', <gfs_result>-empid.

    WRITE: 'Status:', <gfs_result>-message.

  ENDLOOP.

 

*&---------------------------------------------------------------------*

*&      Form F_before_rfc

*&---------------------------------------------------------------------*

*       text

*----------------------------------------------------------------------*

*      -->P_BEFORE_RFC_IMP      text

*      -->P_BEFORE_RFC_EXP      text

*      -->PT_RFCDATA            text

*      -->P_FAILED_OBJECTS      text

*      -->P_OBJECTS_IN_PROCESS  text

*      -->P_USER_PARAM          text

*----------------------------------------------------------------------*

FORM f_before_rfc

   USING

      p_before_rfc_imp     TYPE spta_t_before_rfc_imp

   CHANGING

      p_before_rfc_exp     TYPE spta_t_before_rfc_exp

      pt_rfcdata           TYPE spta_t_indxtab

      p_failed_objects     TYPE spta_t_failed_objects

      p_objects_in_process TYPE spta_t_objects_in_process

      p_user_param.

 

  DATA:

     lv_package_size   TYPE sytabix,

     ls_task_data      TYPE gty_rfcdata,            " ***CUSTOM

     ls_emp            TYPE zemp_data,               " ***CUSTOM

     ls_failed_obj     TYPE spta_t_failed_object,

     ls_obj_in_process TYPE spta_t_pending_object.

 

  FIELD-SYMBOLS:

        <lfs_work>      TYPE zemp_data.

* Delete list of objects in process

  CLEAR ls_obj_in_process.

 

* Check if there are objects from previously failed tasks left ...

  READ TABLE p_failed_objects INDEX 1 INTO ls_failed_obj.

  IF sy-subrc = 0.

* Yes there are.

* Take first object and delete it from list of failed objects

    DELETE p_failed_objects INDEX 1.

    ls_obj_in_process = ls_failed_obj.

    ls_emp-empid = ls_obj_in_process-obj_id(10).

    APPEND ls_emp TO ls_task_data-importing-emp_data.

* Add list of objects that are about to be processed

* to list of "objects in process"

* so the task manager has that information

    APPEND ls_obj_in_process TO p_objects_in_process.

  ELSE.

* No there aren't.

* Take objects from regular input list of objects

 

* The number of objects that are processed at once is determined

* by the application. This sample coding here uses a dynamically

* determined package size (one 5th of remaining objects).

* In order to avoid extremly large or extremly small packages

* there is a maximum and minimum package size.

 

    READ TABLE gt_emp ASSIGNING <lfs_work> INDEX 1.

    IF sy-subrc IS INITIAL.

      CLEAR ls_emp.

      MOVE <lfs_work> TO ls_emp.

      APPEND ls_emp TO ls_task_data-importing-emp_data.

      ls_obj_in_process-obj_id(10) = ls_emp-empid.

      DELETE gt_emp INDEX 1.

* Add list of objects that are about to be processed

* to list of "objects in process"

* so the task manager has that information

      APPEND ls_obj_in_process TO p_objects_in_process.

    ENDIF.

 

  ENDIF.

 

* If there is (currently) nothing to do, clear the

* START_RFC field and leave the form.

* This informs the task manager that no rfc has to be started.

* If there are no more RFCs in process this also ends

* the processing of the task manager

* If there are still RFCs in process the BEFORE_RFC form

* will be invoked after each RFC has been received to give

* the application an opportunity to launch new RFCs that have been

* waiting on the RFC that was just received.

  IF p_objects_in_process IS INITIAL.

    CLEAR p_before_rfc_exp-start_rfc.

    EXIT.

  ENDIF.

 

* Convert the input data into the INDX structure

* that is needed for the RFC

  CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'

    EXPORTING

      data = ls_task_data

    IMPORTING

      indxtab = pt_rfcdata.

 

* Inform task manager that an RFC can be started from the

* data compiled

  p_before_rfc_exp-start_rfc = 'X'.

 

ENDFORM.                               "BEFORE_RFC

 

 

*---------------------------------------------------------------------*

*       FORM IN_RFC *

*---------------------------------------------------------------------*

*       Callback-Form invoked within the RFC                          *

*---------------------------------------------------------------------*

FORM f_in_rfc

   USING

      p_in_rfc_imp  TYPE spta_t_in_rfc_imp

   CHANGING

      p_in_rfc_exp  TYPE spta_t_in_rfc_exp

      p_rfcdata     TYPE spta_t_indxtab.

 

  DATA:

     ls_taskdata    TYPE gty_rfcdata,

     ls_data        TYPE zemp_data,

     ls_result      TYPE zupd_result.

 

  FIELD-SYMBOLS:

      <lfs_data>    TYPE zemp_data.

 

* Force synchronous update

* This is the most efficient method for parallel processing

* since no update data will be written to the DB but rather

* stored in memory.

* This statement must be reissued after each COMMIT WORK !!!!

  SET UPDATE TASK LOCAL.

 

* Unpack RFC input data (that has been packed in the BEFORE_RFC form)

  CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'

    EXPORTING

      indxtab = p_rfcdata

    IMPORTING

      data = ls_taskdata.

 

*--- Begin processing of RFC

*------ Prepare your import data from -importing-workarea  ( can define as per req )

 

  CLEAR ls_data.

  READ TABLE ls_taskdata-importing-emp_data ASSIGNING <lfs_data> INDEX 1.

  IF sy-subrc EQ 0.

    MOVE <lfs_data> TO ls_data.

  ENDIF.

*------ Prepare your import data from -importing-workarea  ( can define as per req )

  CALL FUNCTION 'ZEMP_DATA_UPD'

    EXPORTING

      im_data = ls_data

    IMPORTING

      ex_result = ls_result

    EXCEPTIONS

      no_update = 1

      OTHERS = 2.

  IF sy-subrc <> 0.

* Implement suitable error handling here

  ENDIF.

 

* Fill result tables

* This would include data for result lists, message handler etc.

*  lS_taskdata-exporting-workarea = lS_taskdata-importing-workarea.

 

* Clear all data that is unnecessary for the AFTER_RFC form

* This keeps the amount of data transfered over the network

* small and makes the RFC more efficient!

 

  REFRESH: ls_taskdata-exporting-emp_result[].

 

  APPEND ls_result TO ls_taskdata-exporting-emp_result.

* Repack output data for AFTER_RFC form

  CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'

    EXPORTING

      data = ls_taskdata

    IMPORTING

      indxtab = p_rfcdata.

 

* Don't forget to COMMIT your data, because if you don't, the

* RFC will end with an automatic rollback and data written to the

* database will be lost.

  COMMIT WORK.

 

ENDFORM.                    "F_in_rfc

 

 

 

*&---------------------------------------------------------------------*

*&      Form F_after_rfc

*&---------------------------------------------------------------------*

*       text

*----------------------------------------------------------------------*

*      -->P_RFCDATA             text

*      -->P_RFCSUBRC            text

*      -->P_RFCMSG              text

*      -->P_OBJECTS_IN_PROCESS  text

*      -->P_AFTER_RFC_IMP       text

*      -->P_AFTER_RFC_EXP       text

*      -->P_USER_PARAM          text

*----------------------------------------------------------------------*

FORM f_after_rfc

   USING

      p_rfcdata            TYPE spta_t_indxtab

      p_rfcsubrc           TYPE sy-subrc

      p_rfcmsg             TYPE spta_t_rfcmsg

      p_objects_in_process TYPE spta_t_objects_in_process

      p_after_rfc_imp      TYPE spta_t_after_rfc_imp

   CHANGING

      p_after_rfc_exp      TYPE spta_t_after_rfc_exp

      p_user_param.

 

  DATA:

     ls_obj_in_process     TYPE spta_t_pending_object,

     lv_tabsize            TYPE sytabix,

     ls_taskdata           TYPE gty_rfcdata.

  DATA:

      ls_emp TYPE zemp_data.

 

  IF p_rfcsubrc IS INITIAL.

* No RFC error occured

 

* Unpack RFC output data and add RFC-results to global data,

* e.g. output list, message handler etc.

    CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'

      EXPORTING

        indxtab = p_rfcdata

      IMPORTING

        data = ls_taskdata.

    APPEND LINES OF ls_taskdata-exporting-emp_result

           TO gt_result.

    EXIT.

  ENDIF.

 

* Error handling

 

  DESCRIBE TABLE p_objects_in_process LINES lv_tabsize.

  IF lv_tabsize = 1.

* The failed task contained one object

* Inform task manager not to resubmit objects

    p_after_rfc_exp-no_resubmission_on_error = 'X'.

 

* about the nature of the error.

    READ TABLE p_objects_in_process INDEX 1

               INTO ls_obj_in_process.

    IF sy-subrc NE 0.

      CLEAR ls_obj_in_process.

    ENDIF.

  ELSE.

* The failed taks contained several objects.

* Enable resubmission to process objects individually.

    CLEAR p_after_rfc_exp-no_resubmission_on_error.

  ENDIF.

 

ENDFORM.                               "AFTER_RFC

*&---------------------------------------------------------------------*

*&      Form F_GET_FILE

*&---------------------------------------------------------------------*

*       text

*----------------------------------------------------------------------*

*  --> p1        text

*  <-- p2        text

*----------------------------------------------------------------------*

FORM f_get_file .

 

  CALL FUNCTION 'F4_FILENAME'

    EXPORTING

      program_name  = syst-cprog

      dynpro_number = syst-dynnr

      field_name    = ' '

    IMPORTING

      file_name     = p_file.

  1. ENDFORM.                    " F_GET_FILE

*&---------------------------------------------------------------------*

*&      Form F_SUB_GET_DATA

*&---------------------------------------------------------------------*

*       text

*----------------------------------------------------------------------*

*      -->P_P_FILE  text

*      <--P_gt_emp  text

*----------------------------------------------------------------------*

FORM f_sub_get_data  USING    p_file TYPE localfile

                     CHANGING p_gt_tab TYPE tty_emp.

 

  DATA: ls_work_area  TYPE tty_emp,

        lv_filename TYPE string.

 

  CLEAR lv_filename.

  MOVE p_file TO lv_filename.

 

  CALL FUNCTION 'GUI_UPLOAD'

    EXPORTING

      filename                = lv_filename

      filetype                = 'ASC'

      has_field_separator     = 'X'

    TABLES

      data_tab                = p_gt_tab

    EXCEPTIONS

      file_open_error         = 1

      file_read_error         = 2

      no_batch                = 3

      gui_refuse_filetransfer = 4

      invalid_type            = 5

      no_authority            = 6

      unknown_error           = 7

      bad_data_format         = 8

      header_not_allowed      = 9

      separator_not_allowed   = 10

      header_too_long         = 11

      unknown_dp_error        = 12

      access_denied           = 13

      dp_out_of_memory        = 14

      disk_full               = 15

      dp_timeout              = 16

      OTHERS                  = 17.

  IF sy-subrc <> 0.

    REFRESH: p_gt_tab.

  ENDIF.


ENDFORM.                    " F_SUB_GET_DATA


Step 5 - Test the program:

 

Activate the program and then execute it.  Select server group from existing otherwise you can create a Z server group by executing transaction code RZ12 - RFC Server Group Maintenance.


For this case one extra selection field has been taken for defining maximum task.


sfp sel screen.jpg

We will delete first from the table and upload the same file which has been used earlier.

emp1.jpg

Step 5: Execute it and see the resultEmployee details have been updated.


Result 2.jpg

*----------------------------------------------------------------------------- End of Process 2---------------------------------------------------------------------------------------------------------------------------*


Now we are going to compare which parallel process performance is better. For better comparison, take large volume of data because in small volume of data you will not find the difference.

 

Go to SE30 or SAT and Compare the result:


Process 1: 

Process 1.jpg

Execute it :

Process 1-result.jpg


Process 2:

Process 2.jpg

Result:


Process 2-Result.jpg

See the time difference is very less. For better statistics use large volume of data.


Reference: Sap standard report for parallel processing.


Suggestion:Please feel free to suggest.



Display the technical name of transaction

$
0
0

Transactions are mentioned with a short text but not with the technical name.

Each transaction has a technical code name.

Showing the transaction code technical name allows a user to execute the transaction directly.

In SAP, When you are logged, the first interface is SAP Easy Access.

Here, following path extras --> setting (shift+F9) is possible to set with flag the check-box Display technical names.

At the end of this section is possible to find technical names of each transaction code near the description of each transaction.

The transparent table AGR_DATEU contains personal settings roles.

About this setting the information are stored with ID = 'BROWSER_OPT' and UNAME = user name.

It is possible to use standard function module PRGN_SET_BROWSER_OPTIONS_USER to maintain this customizing.

For allowing a mass maintenance is necessary write an ABAP program.

In Attach, there is an example program to do this activity.

Objectify: ABAP Objects Model for BDC

$
0
0

This is my first contribution to Project Objectify which is being "revived" by Bruno Esperança.

 

This an Object-Oriented approach for BDC processing. I'm aware that there is already a model published here but this is my own attempt at the design which includes the functionality to process the BDC via Call Transaction or Batch Input Session.


I develop in ABAP Objects wherever I can, so this is one of the classes where I bring along to every new project I start on as it is highly reusable. I am aware of the never-ending debate between developing ABAP in OO vs. procedural in SCN, but I will not get into that here. Please feel free to reuse this model and/or leave any comments if it can be improved any further.

 

 

Source Code

The corresponding objects and code for this article can be found in the following public repository on Github.

GitHub repository for BDC Model

 

 

Class Design

The design of the class is based on the Singleton pattern whereby there can be only 1 active instance of the class in a single session.

 

Methods

The screenshot below displays the methods available in the class.

methods.png

 

Methods Explanation


1) Instantiation

Instantiation of the class is via static method S_INSTANTIATE, whereby the type of processing (CT = Call Transaction, BI = Batch Input) and related T-Code are mandatory inputs.

Additionally, other parameters are available for finer control of the BDC processing. All the input values are stored into the instance's private attributes.

instant.png

2) Construct BDC table

Once the class is instantiated, instance methods ADD_FIELD and ADD_SCREEN are used to construct the BDC table.

 

3) BDC Processing

After the BDC table has been fully populated, instance method PROCESS is used to process that data. Depending on the processing type (CT/BI), private methods CALL_TRANSACTION or CREATE_BATCH_INPUT_SESS will be executed.

 

4) Reset BDC table

If there is a need to execute the same BDC T-Code multiple times (i.e. in a loop), instance method CLEAR_BDC_DATA can be used to clear the BDC table so that it can be reconstructed again.

 

5) Garbage collection

Finally, if the BDC instance is no longer required during an internal session, static method S_FREE_INSTANCE can be used to free the instance of the singleton, which then allows the memory to be freed during the next run of the garbage collector.

 

 

Usage Example

Below is an example of a simple report program to illustrate the usage of the class. It shows both processing by Call Transaction and Batch Input Session.

*&---------------------------------------------------------------------*

*& Report  ZESY_CALL_OO_BDC

*&

*&---------------------------------------------------------------------*

REPORT  zesy_call_oo_bdc.

 

*----------------------------------------------------------------------*

*  Selection Screen

*----------------------------------------------------------------------*

PARAMETER:

   p_kunnr  TYPE kna1-kunnr DEFAULT '2400',

   p_vkorg  TYPE knvv-vkorg DEFAULT '1000',

   p_vtweg  TYPE knvv-vtweg DEFAULT '10',

   p_spart  TYPE knvv-spart DEFAULT '00'.

SELECTION-SCREEN SKIP 1.

PARAMETER:

   p_delblk TYPE kna1-lifsd DEFAULT '01',

   p_bilblk TYPE kna1-faksd DEFAULT '01'.

SELECTION-SCREEN SKIP 1.

 

PARAMETER:

   p_tran RADIOBUTTON GROUP r1 DEFAULT 'X',

   p_sess RADIOBUTTON GROUP r1.

 

*----------------------------------------------------------------------*

*  Data Declarations

*----------------------------------------------------------------------*

DATA:

   g_bdc       TYPE REF TO zcl_bc_bdc,

   g_messages  TYPE tab_bdcmsgcoll,

   g_message   LIKE LINE OF g_messages,

   g_subrc     TYPE sy-subrc,

   g_exception TYPE REF TO zcx_batch_input_error,

   g_error     TYPE string.

 

*----------------------------------------------------------------------*

*  Initialization

*----------------------------------------------------------------------*

*INITIALIZATION.

 

*----------------------------------------------------------------------*

*  Start of Selection

*----------------------------------------------------------------------*

START-OF-SELECTION.

 

* Create an object for BDC

   IF p_tran = 'X'.

     g_bdc = zcl_bc_bdc=>s_instantiate( i_bdc_type = 'CT'

                                        i_tcode    = 'VD05' ).

   ELSEIF p_sess = 'X'.

     g_bdc = zcl_bc_bdc=>s_instantiate( i_bdc_type = 'BI'

                                        i_tcode    = 'VD05'

                                        i_group    = 'MY_SESSION'

                                        i_keep     = 'X'

                                        i_holddate = '20140528' ).

   ENDIF.

 

* Populate first screen

   g_bdc->add_screen( i_repid = 'SAPMF02D' i_dynnr = '0507').

   g_bdc->add_field( i_fld = 'BDC_OKCODE'  i_val = '/00').

   g_bdc->add_field( i_fld = 'RF02D-KUNNR' i_val = p_kunnr ).

   g_bdc->add_field( i_fld = 'RF02D-VKORG' i_val = p_vkorg ).

   g_bdc->add_field( i_fld = 'RF02D-VTWEG' i_val = p_vtweg ).

   g_bdc->add_field( i_fld = 'RF02D-SPART' i_val = p_spart ).

* Populate second screen

   g_bdc->add_screen( i_repid = 'SAPMF02D' i_dynnr = '0510').

   g_bdc->add_field( i_fld = 'BDC_OKCODE' i_val = '=UPDA').

   g_bdc->add_field( i_fld = 'KNA1-LIFSD' i_val = p_delblk ).

   g_bdc->add_field( i_fld = 'KNA1-FAKSD' i_val = p_bilblk ).

 

*----------------------------------------------------------------------*

*  End of Selection

*----------------------------------------------------------------------*

END-OF-SELECTION.

 

   IF p_tran = 'X'.

     g_bdc->process( IMPORTING e_subrc    = g_subrc

                               e_messages = g_messages ).

*   Display processing status

     IF g_subrc = 0.

       WRITE:/ 'Success:'.

     ELSE.

       WRITE:/ 'Error:'.

*     Display messages in list

       LOOP AT g_messages INTO g_message.

         MESSAGE ID g_message-msgid

                 TYPE g_message-msgtyp

                 NUMBER g_message-msgnr

                 WITH g_message-msgv1

                      g_message-msgv2

                      g_message-msgv3

                      g_message-msgv4

                 INTO g_error.

         WRITE:/ g_error.

       ENDLOOP.

     ENDIF.

   ELSEIF p_sess = 'X'.

     TRY.

         g_bdc->process( ).

         WRITE: 'Success: Check session in SM35'.

       CATCH zcx_batch_input_error INTO g_exception.

         WRITE:/ 'Error creating batch input session:'.

         MESSAGE ID g_exception->msgid

                 TYPE 'E'

                 NUMBER g_exception->msgno

                 WITH g_exception->msgv1

                      g_exception->msgv2

                      g_exception->msgv3

                      g_exception->msgv4

                 INTO g_error.

         WRITE:/ g_error.

     ENDTRY.

   ENDIF.

Very simple ALV in pop-up window

$
0
0

Hello, colleagues!

It may be useful in everyday programming to use quick and simple solutions.

So, I wrote a function module 'Z_VERY_SIMPLE_ALV' which allows you to display an ALV grid in a pop-up window at railway speed.

Here you can see the FM:

FUNCTION z_very_simple_alv.

*"----------------------------------------------------------------------

*"*"Local interface:

*"  IMPORTING

*"    REFERENCE(I_START_COLUMN) TYPE  I DEFAULT 25

*"    REFERENCE(I_START_LINE) TYPE  I DEFAULT 6

*"    REFERENCE(I_END_COLUMN) TYPE  I DEFAULT 100

*"    REFERENCE(I_END_LINE) TYPE  I DEFAULT 10

*"    REFERENCE(I_TITLE) TYPE  STRING DEFAULT 'ALV'

*"  TABLES

*"      IT_ALV TYPE  STANDARD TABLE

*"----------------------------------------------------------------------

 

  DATA:

    go_popup  TYPEREFTO cl_reca_gui_f4_popup,

    gf_choice TYPE flag.

 

 

  CALLMETHOD cl_reca_gui_f4_popup=>factory_grid

    EXPORTING

      it_f4value    = it_alv[]

      if_multi      = abap_false

      id_title      = i_title

    RECEIVING

      ro_f4_instance = go_popup.

 

  CALLMETHOD go_popup->display

    EXPORTING

      id_start_column = i_start_column

      id_start_line  = i_start_line

      id_end_column  = i_end_column

      id_end_line    = i_end_line

    IMPORTING

      et_result      = it_alv[]

      ef_cancelled    = gf_choice.

 

ENDFUNCTION.

You can use it like this:

REPORT z_very_simple_alv.

 

DATA gt_tab TYPESTANDARDTABLEOF sflights.

 

SELECT * FROM sflights INTOTABLE gt_tab.

 

CALLFUNCTION'Z_VERY_SIMPLE_ALV'

  TABLES

    it_alv = gt_tab.

As a result, you can see the ALV pop-up window:

1.png

ABAP source code in this document was coloured using the ABAP code lighter for SCN.

 

Best regards,

George Shlyahov

Enhancement Framework - Extension Index

$
0
0

Extension Index

Most known practice to speed up searches on the standard tables is to create secondary indexes. SAP has introduced a new enhancement technique called Extension index as part of Enhancement Framework. It is same as creating secondary index for the standard table.


Advantage

SAP has already delivered secondary indexes for most of the standard table.  It is not necessary that the existing secondary index fulfill all scenarios. In such cases, creating a secondary index on a standard table comes under modification. During upgrade, they will be deleted and need to be re-created in a system. This involves efforts and cost. Extension indexes are automatically copied over during upgrades and no modification adjustment takes place.


How to create

1. Go to SE11-> Enter table name-> click on Indexes-> Create Extension Index

2.JPG

 

2. System will display screen same as ‘Creating Secondary Index’.  Enter the required data.

3.JPG

3. Save and activate it. Assign a package and transport request for the extension index.

Viewing all 935 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>