Quantcast
Channel: ABAP Development
Viewing all 948 articles
Browse latest View live

Report to export SQ01 result ot applicaiton server file even in background job

$
0
0

This report is a work around standard SQ01 limitation, which limits the saving capability of report to GUI in foreground

.*&---------------------------------------------------------------------*
 *& Report  ZSQ01_TO_FILE
 *&
 *&---------------------------------------------------------------------*
 *&
 *&
 *&---------------------------------------------------------------------*
 REPORT  zsq01_to_file.
 PARAMETERS p_name TYPE rs38m-programm OBLIGATORY.
 PARAMETERS p_var  TYPE rsvar-variant OBLIGATORY.
 PARAMETERS p_con  TYPE c AS CHECKBOX DEFAULT ''.
 PARAMETERS p_file TYPE alk_string.
 DATA gt_strings TYPE STANDARD TABLE OF string.
 AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_name.   PERFORM program_f4 USING p_name                            p_var.
 AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_var.   PERFORM variant_f4 USING  p_name                             p_var .
 END-OF-SELECTION.   REFRESH gt_strings.   PERFORM do_the_job.   PERFORM save_file.
 *&---------------------------------------------------------------------*
 *&      Form  variant_f4
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 *      -->REPNAME    text
 *      -->VARNAME    text
 *----------------------------------------------------------------------*
 FORM variant_f4 USING repname TYPE programm                       varname TYPE rsvar-variant.   DATA: report  LIKE rsvar-report,         variant LIKE rsvar-variant.   DATA lt_dynpfields  TYPE STANDARD TABLE OF  dynpread.   DATA ls_dynpfields  TYPE dynpread.   CLEAR ls_dynpfields.   ls_dynpfields-fieldname = 'P_NAME'.   REFRESH lt_dynpfields.   APPEND ls_dynpfields TO lt_dynpfields.   DATA: repid LIKE sy-repid.   repid = sy-repid.   CALL FUNCTION 'DYNP_VALUES_READ'     EXPORTING       dyname                               = repid       dynumb                               = sy-dynnr     TABLES       dynpfields                           = lt_dynpfields    EXCEPTIONS      OTHERS             .   READ TABLE lt_dynpfields INTO ls_dynpfields INDEX 1.   p_name = ls_dynpfields-fieldvalue.   report = repname.   IF report(1) = '!'.                  " temporärer Report     report(1) = 'A'.   ENDIF.   CALL FUNCTION 'RS_VARIANT_CATALOG'     EXPORTING       report      = report     IMPORTING       sel_variant = variant     EXCEPTIONS       OTHERS      = 1.   IF sy-subrc = 0.     varname = variant.   ELSE.   ENDIF.
 ENDFORM.                    "variant_f4
 *&---------------------------------------------------------------------*
 *&      Form  PROGRAM_F4
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 *      -->P_P_PNAME  text
 *      -->P_P_VAR  text
 *----------------------------------------------------------------------*
 FORM program_f4  USING    repname TYPE programm                           varname TYPE rsvar-variant.   DATA: report  LIKE rsvar-report,          variant LIKE rsvar-variant.   DATA lt_dynpfields  TYPE STANDARD TABLE OF  dynpread.   DATA ls_dynpfields  TYPE dynpread.   CLEAR ls_dynpfields.   ls_dynpfields-fieldname = 'P_NAME'.   REFRESH lt_dynpfields.   APPEND ls_dynpfields TO lt_dynpfields.   DATA: repid LIKE sy-repid.   repid = sy-repid.   CALL FUNCTION 'DYNP_VALUES_READ'     EXPORTING       dyname                               = repid       dynumb                               = sy-dynnr     TABLES       dynpfields                           = lt_dynpfields    EXCEPTIONS      OTHERS             .   READ TABLE lt_dynpfields INTO ls_dynpfields INDEX 1.   p_name = ls_dynpfields-fieldvalue.   DATA l_programm LIKE rs38m-programm.   l_programm = p_name .   CALL FUNCTION 'REPOSITORY_INFO_SYSTEM_F4'     EXPORTING       object_type          = 'PROG'       object_name          = l_programm       suppress_selection   = 'X'     IMPORTING       object_name_selected = l_programm     EXCEPTIONS       cancel               = 01.   IF sy-subrc = 0.     p_name = l_programm.   ENDIF.
 ENDFORM.                    " PROGRAM_F4
 *&---------------------------------------------------------------------*
 *&      Form  DO_THE_JOB
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 *  -->  p1        text
 *  <--  p2        text
 *----------------------------------------------------------------------*
 FORM do_the_job .   FIELD-SYMBOLS <lt_report_data>   TYPE ANY TABLE.   DATA lr_report_data              TYPE REF TO data.   DATA ls_metadata  TYPE cl_salv_bs_runtime_info=>s_type_metadata.   DATA lv_string TYPE string.   DATA lv_lines TYPE i.   DATA lv_loop_index TYPE i.   DATA lt_field_cat  TYPE lvc_t_fcat.   DATA ls_f_cat TYPE LINE OF lvc_t_fcat.   DATA lv_value_condesed TYPE string.   FIELD-SYMBOLS <fs_dtab> TYPE ANY .   FIELD-SYMBOLS <fv_value> TYPE ANY .   FIELD-SYMBOLS <fs_listdesc>  TYPE LINE OF rsaqtldesc.   cl_salv_bs_runtime_info=>set(     EXPORTING display  = abap_false               metadata = abap_true               data     = abap_true ).   SUBMIT (p_name) USING SELECTION-SET p_var AND RETURN.   TRY.       cl_salv_bs_runtime_info=>get_data_ref(         IMPORTING r_data = lr_report_data ).       ASSIGN lr_report_data->* TO <lt_report_data>.       ls_metadata = cl_salv_bs_runtime_info=>get_metadata( ).     CATCH cx_salv_bs_sc_runtime_info.       cl_salv_bs_runtime_info=>clear_all( ).       MESSAGE `Unable to retrieve ALV data` TYPE 'E'.   ENDTRY.   cl_salv_bs_runtime_info=>clear_all( ).   CHECK <lt_report_data> IS ASSIGNED.   DESCRIBE TABLE <lt_report_data> LINES lv_lines.   CHECK lv_lines > 0.   lt_field_cat[] = ls_metadata-t_fcat[].   SORT lt_field_cat STABLE BY no_out col_pos .   CLEAR lv_string.   lv_loop_index = 1.   LOOP AT lt_field_cat INTO ls_f_cat     WHERE no_out IS INITIAL.     CLEAR lv_value_condesed.     lv_value_condesed = ls_f_cat-reptext.     IF p_con = 'X'.       CONDENSE lv_value_condesed .     ENDIF.     IF lv_loop_index <> 1.       IF p_con = 'X'.         CONCATENATE  lv_string ';' lv_value_condesed   INTO lv_string               RESPECTING BLANKS.       ELSE.         CONCATENATE  lv_string ';' ls_f_cat-reptext   INTO lv_string             RESPECTING BLANKS.       ENDIF.     ELSEIF lv_loop_index = 1.       IF p_con = 'X'.         CONCATENATE lv_string lv_value_condesed  INTO lv_string             RESPECTING BLANKS.       ELSE.         CONCATENATE lv_string ls_f_cat-reptext  INTO lv_string           RESPECTING BLANKS.       ENDIF.     ENDIF.     lv_loop_index = lv_loop_index + 1.   ENDLOOP.   APPEND lv_string TO gt_strings.   LOOP AT <lt_report_data> ASSIGNING <fs_dtab>.     CLEAR lv_string .     lv_loop_index = 1.     LOOP AT lt_field_cat INTO ls_f_cat     WHERE no_out IS INITIAL.        ASSIGN COMPONENT ls_f_cat-fieldname OF STRUCTURE <fs_dtab> TO <fv_value>.       IF <fv_value> IS ASSIGNED.         CLEAR lv_value_condesed.         lv_value_condesed = <fv_value>.         IF p_con = 'X'.           CONDENSE lv_value_condesed .         ENDIF.         IF lv_loop_index <> 1.           IF p_con = 'X'.             CONCATENATE lv_string ';' lv_value_condesed  INTO lv_string               RESPECTING BLANKS.           ELSE.             CONCATENATE lv_string ';' <fv_value> INTO lv_string             RESPECTING BLANKS.           ENDIF.         ELSEIF lv_loop_index = 1.           IF p_con = 'X'.             CONCATENATE lv_string lv_value_condesed INTO lv_string             RESPECTING BLANKS.           ELSE.             CONCATENATE lv_string <fv_value> INTO lv_string           RESPECTING BLANKS.           ENDIF.         ENDIF.         UNASSIGN <fv_value>.       ENDIF.       lv_loop_index = lv_loop_index + 1.     ENDLOOP.     APPEND lv_string TO gt_strings.   ENDLOOP.
 ENDFORM.                    " DO_THE_JOB
 *&---------------------------------------------------------------------*
 *&      Form  SAVE_FILE
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 *  -->  p1        text
 *  <--  p2        text
 *----------------------------------------------------------------------*
 FORM save_file .   CHECK gt_strings IS NOT INITIAL.   DATA lv_string TYPE string.   OPEN DATASET p_file FOR OUTPUT IN LEGACY TEXT MODE CODE PAGE     '1504' WITH WINDOWS LINEFEED     IGNORING CONVERSION ERRORS              REPLACEMENT CHARACTER '#'.   IF sy-subrc = 0.     LOOP AT gt_strings INTO lv_string.       TRY.           TRANSFER lv_string TO p_file.         CATCH cx_sy_conversion_codepage.       ENDTRY.     ENDLOOP.     CLOSE DATASET p_file.   ENDIF.
 ENDFORM.                    " SAVE_FILE

Adding custom fields to the Purchase Order transaction ME51N ITEM LEVEL.

$
0
0

Enhancement for ME51N Is : MEREQ001

 

Go to SMOD and search for Enhancement.

 

If enhancement is know then got to CMOD.

 

Go to CMOD and create Project For Example : ZMM_PR.

 

 

Click CREATE button and following Screen appears.

 

 

Give Short Text and Go to Enhancement assignment and give Enhancement for ME51N as MEREQ001 and Save.

 

 

Now go to Components and following Screen appears.

 

 

We can find Function Exit , Screen Exit, Include tables.

 

Now go to Include tables : Double click on CI_EBANDB Add ZZKOSTL Field and activate the STRUCTURE.


 

Now go to Screen Exit.

 

Double click on SAPLMEGUI Program and Create the Program.

After Program Create Screen with Field name EBAN-ZZKOSTL

 

 

 

And Activate it.

Now go to Function Exit


     EXIT_SAPLMEREQ_001
     EXIT_SAPLMEREQ_003

 

These are the two Function exits for ME51N.

 

EXIT_SAPLMEREQ_001 is the PBO .

 


EXIT_SAPLMEREQ_003 is the PAI.

 

Implementation in EXIT_SAPLMEREQ_001 --- PBO.

 

Double click on EXIT_SAPLMEREQ_001

You will find INCLUDE ZXM02U01 in Source code tab.

Now Doble click on Include FIle.

 

Now According to you Requirement add Your Custom Code.

 

I am adding Custom Field i.e COST CENTER - KOSTL .

 


TABLES : CI_EBANDB,
                  EBAN.

DATA :   L_MEREQ_ITEM  TYPE  MEREQ_ITEM,
                  L_HEADER            TYPE  REF TO IF_PURCHASE_REQUISITION,
                  L_EDIT                   TYPE  CHAR1,
                  T_ENQ                    TYPE  TABLE OF SEQG3,
                  L_GARG                 TYPE  EQEGRAARG,
                  L_HEAD                 TYPE  MEREQ_HEADER,
                  L_AKTVT              TYPE  AKTVT.


IF SY-TCODE EQ 'ME51N' OR SY-TCODE EQ 'ME52N' OR SY-TCODE EQ 'ME53N'.
        IF IM_REQ_ITEM IS INITIAL.
               CLEAR: CI_EBANDB.
        ELSE.
               L_MEREQ_ITEM = IM_REQ_ITEM->GET_DATA( ).
     MOVE-CORRESPONDING L_MEREQ_ITEM TO CI_EBANDB.

     EBAN-ZZKOSTL = L_MEREQ_ITEM-ZZKOSTL.

* Check Mode (Display/Edit)
     CALL METHOD IM_REQ_ITEM->GET_ACTIVITY
       RECEIVING
         RE_AKTVT = L_AKTVT.
*     * EXPORT MODE TO MEMORY
     EXPORT L_AKTVT TO MEMORY ID 'EDIT_MODE'.


   ENDIF.


        L_MEREQ_ITEM-ZZKOSTL = EBAN-ZZKOSTL.


ENDIF.

 

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

 

Implementation in EXIT_SAPLMEREQ_003--PAI

 


DATA : L_MEREQ_ITEM TYPE MEREQ_ITEM,
           L_AKTVT TYPE AKTVT.

IF SY-TCODE EQ 'ME51N' OR SY-TCODE EQ 'ME52N' OR SY-TCODE EQ 'ME53N'.


        IF NOT IM_REQ_ITEM IS INITIAL.


               L_MEREQ_ITEM = IM_REQ_ITEM->GET_DATA( ).

               L_AKTVT = IM_REQ_ITEM->GET_ACTIVITY( ).


* Display mode
     IF L_AKTVT EQ 'A'.


* Create Mode or Change mode
     ELSEIF L_AKTVT EQ 'V' OR L_AKTVT EQ 'H'.
*       * COPY DATA FROM SCREEN TO STRUCTURE
       IF EBAN-ZZKOSTL NE CI_EBANDB-ZZKOSTL.
       

           L_MEREQ_ITEM-ZZKOSTL = EBAN-ZZKOSTL.
           EX_CHANGED = 'X'.


       ENDIF.
* Move data to table EBAN


       IF EX_CHANGED EQ 'X'.
        

          CALL METHOD IM_REQ_ITEM->SET_DATA( L_MEREQ_ITEM ).
     

       ENDIF.
     ENDIF.
   ENDIF.
ENDIF.

 

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

 

The out put will be as follows.

 


 

...

New Technical Brief on ABAP for SAP HANA

$
0
0

Build real-time business applications leveraging the SAP HANA platform to the max with SAP NetWeaver Application Server for ABAP. It offers an excellent, standards-based development and runtime environment with highly responsive user interfaces for enabling business processes across on-premise and on-demand solutions. Read the technical brief here!

Recording Deep Structure to Database via Data Cluster

$
0
0

While writing with ABAP, many programer uses deep structure. Some case we need to record data in deep structure but normal SE11 dictionary type doesnt allow us.

 

So i came up with this :

 

Using Data Cluster for Deep structure Data Clusters in the Database

 

Now my example here is like this:

 

Purpose of this example saving email data ( I know SAP records all e-mail data, this is just a example of using data cluster )

 

First we need to create ZMAIL_INDX table

ZMAIL_INDX.PNG

First key is relid this is Area ID

Second key is our record unique ID

Third key is counter for our record

 

after this we can add as many line as we like for data identification

 

last two line CLUSTR and CLUSTD fill automaticaly and this is our deep structure data.

 

Now creating our Mail data Deep structure:

 

ZMAIL_S_DATA.PNG

 

Now we can write code:

 

DATA : ls_mail_data TYPE zmail_s_data,          ls_mail TYPE zmail_indx,          lv_keyid TYPE char20.

To save :

   ls_mail-ernam = sy-uname.   ls_mail-erdat = sy-datum.   ls_mail-pgmid = sy-repid.   ls_mail-tcode = sy-tcode.

EXPORT mail = ls_mail_data TO DATABASE zmail_indx(zm) ID lv_keyid FROM ls_mail.

 

ZM is RELID

lv_keyid our unique ID

 

For information we sent ernam, erdat etc.

 

To read :

IMPORT mail = ls_mail_data FROM DATABASE zmail_indx(zm) ID lv_keyid TO ls_mail.

You must give keyid

 

Just like this we can record deep structure to database.

 

PS : I use CL_BCS for e-mail, all mail data created for CL_BCS. I assume ls_mail_data is filled with data, so i dont give example of CL_BCS.

 

Now i wonder,

Advantage and Disadvantage of using Data Cluster?

Any idea?

Suggestions for Open XML documents Secnarios

$
0
0

Hello.

in my last blogs i gave some examples and information

about Open XML Documents Manipulation in SAP.

 

Open XML is an Open Standard for word processing documents ,  spreadsheets and presentations.

We use MS-Office tools to open the documents

but the Creation and manipulation of the documents can be done on any platform.

 

as SAP staff i'm sure that most of you have some ideas and wishes

for a good Integration between SAP and MS-Office,

 

for Example: dynamic forms creation in Word,

dynamic spreadsheets in Excel  and so on.

creativity is most welcome.

 

hope that  we can get here some new and  interesting ideas .

 

 

thanks

 

   Ronen Almog

ABAP Code Naming Conventions - A Rant

$
0
0

Take everything with big pinch of salt

(unless you have high blood pressure in which case do not read this rant, it'll probably make it worse.)

A pinch of salt required

It is not my intention to offend!

 

A couple of people have asked me to cross-post this rant to here on SCN. It's their fault that it's here.

Ok, you can probably guess that I’m not the most conventional person. I probably don’t fit the mould of the stereotypical developer either. I’m certainly not what one would call an introvert.

So please take this with the necessary pitch of salt. (especially if you’re one of the people who writes the code naming conventions that I have to follow from time to time ;) )

<rant>

 

Why on earth does every SAP project I go to insist on such inane naming standards for the code? The SAP editor is a wonderful IDE (caveat I did not say it was the best IDE) that allows you to see the definition of any variable with a simple double click – so why on earth are you so worried that I should prefix all my local variable definitions with an ‘L’? What on earth potential benefit can this have on the code readability? Perhaps it helps if you’re still one of my nemesis developers who are passing all your variables between methods through the use of global variables and/or singletons. Perhaps one needs to look at a piece of code, see lots of L’s and that gives satisfaction? The use of Hungarian Notation in ABAP code seems to be universal, although never it seems implemented in the same way.

Then when I define a structure, I must prefix it with a “S” just so you can be sure that it isn’t actually a table or a single field, or so help me, a woolly mammoth. When I look in the IDE view of the package I am developing, all of these different things are arranged in a tree so you can easily tell one from the other. Again a single double-click can bring me to the definition if it is ever referred to in a piece of code. Perhaps it might save some time looking at a variable definition to see if it is a table, a structure, object reference or a variable – but if I’m in the code, it should be pretty damn obvious! If I’m appending or inserting into it, it’s a table. If I’m referencing a sub-field of it, it’s a structure. If I’m assigning a value to it it’s a variable, if I’m creating an instance of it, it better be an object reference. There again may be cases of my nemeses developers still using tables with header lines and confusing the heck out of me. But I’m hoping that the code inspector might weed at least that out. Sometimes I'm tempted just to create structures containing nothing but tables so that people relying on the Hungarian notation get really confused, but those that realise that the syntax checker might just have mentioned something if I was trying to append to a variable are still cool.

Searching outside of the SAP world the use of Hungarian Notation within code is not universally disliked, but with such a clear list of disadvantages and such luminaries as Uncle “Bob” Martin and Linus Torvalds against it, you’d have to proclaim yourself a pretty die-hard supporter of “doing it the old way” not to just think a little – “is this really useful? Or is it even potentially bad?”.

Then there comes the requirement that every object should reference the area of use it is intended for. Thus the forth and fifth characters of the object name must be “HR” or “PA” or “XX” or whatever. The use of Positional Notation for implicit metadata about a component is, however not something I’ve seen outside of SAP projects except for the COBOL example given in the linked Wikipedia page. At this point when reading the naming convention guide, I casually check if there is any mention of packages and package hierarchies and hope upon hope, package interfaces. When there isn’t, I sigh again and just bite my tongue again. Because SAP has provided a wonderful way of helping us see what use a component is put to – as every component must belong to a package, and that package can (and should) have an application component defined. And to give even more clarity, the package can have a super-package, thus grouping all like component together, whatever types they are and where ever in their object names they have a ridiculous two character code. The package interface can even tell you if the object is safe for use outside of the package. What a great concept!

So instead of spending time thinking about whether the components we are building are truly reusable, and what the scope of that reuse is. We spend hours checking if we have the first n characters of our our objects correct according to the development standard book.

</rant>

 

One day someone will be silly enough to let me do it my way, I’ll confuse the bejeebers out of all the guys who’ve only been coding ABAP badly for the last 10 years and the project will potentially fail because I’ll spend my entire time looking for enough of a development team that can understand that following a rigid way of doing things isn't always the best way to do it…. <sigh>

Disclaimer:

I originally did not post this rant on SCN as I feared it might upset people. And I may yet make changes/remove it if it gets too political. I know lots of people who are quite attached to their development naming conventions and many will argue that they are a good thing. I'm certainly not arguing for a lack of rigour in code, but just that perhaps we could invest the time elsewhere.

 

I'd like to reiterate, these are my views (and I may have exaggerated them a little here too) and particularly in this case, do not represent the views of the company I work for. All errors, omissions, confusions and misunderstanding are mine. I serious have not set out to offend people, so please if this is offensive to you, let me know and I'll try to sort it out.

 

You can find the original post and my other thoughts on my blog at wombling.com

Base 10 to Base 26 conversion

$
0
0

Recently I came across a requirement to convert base 10(decimal) value to base 26(more info can be found at http://en.wikipedia.org/wiki/Hexavigesimal)

 

Here is the small piece of code which does the job

 

 

data l_num type char20.

l_num = '90000052'.


data digit type char3.


data num typei.
data result type string.
while ( l_num > 0 ).
num = l_num mod26.
digit = num .
CONCATENATE digit result INTO result  .
CONDENSE result NO-GAPS.
l_num = ( l_num - num ) / 26.
endwhile.

 

Result will hold the base26 value

 

Thanks

Bala Duvvuri


STMS: facing errors when importing transport requests? It's your fault!

$
0
0

Without any doubt: your fault it is... and not only because obviously you didn't pay enough attention to objects' dependencies when you released your transport requests, but mainly because you didn't take 3 seconds to start transaction SE38 and run report ZCEX_TRDA_START to let the system check those dependencies for you.

 

Remark: if you do not find this report in your system, that's probably because you missed this blog post:

How-to check dependencies between transport requests

 

What's new with code exchange project "TRDA - Transport request dependencies analyzer" then?

First of all, the first versions had been developed on SAP Netweaver 7.02 Developer edition which made its use limited to the happy few customers running one of the last versions of SAP Netweaver... Well, I believe this period is over as it has now been backported to SAP NetWeaver 7.0 Trial version:

  • Two missing classes have been copied from 702 into customer namespace.
  • Some statements have been adapted: for example every "&&" character has been replaced by the corresponding "CONCATENATE" statement.
  • ABAP Unit tests have been reviewed.
  • Etc.

 

Speaking of which, those ABAP Unit tests have been enhanced to make sure TRDA finds the following dependencies:

 

PredecessorFollower
DomainData element based on Domain
Data elementStructure with one component based on Data element
StructureTable type based on Structure
Table typeFunction group with one function module using Table type as importing parameter
Function groupClass implementing a method where a function module from Function group is called
InterfaceClass implementing Interface
ClassProgram using objects of type Class
Enhancement spotFunction module where Enhancement spot is implemented
Enhancement spotEnhancement spot implementation of Enhancement spot
Function module

Enhancement spot implementation in Function module

Enhancement spot implementationComposite enhancement implementation containing Enhancement spot implementation
Database tableEnqueue object for Database table
Database tableSearch help based on Database table
Database tableMaintenance view for Database table
Search helpDatabase table where one component is using Search help
Table maintenance viewGenerated function group for Table maintenance view

 

But that's not the only new feature you'll find on TRDA Code exchange project page: this program can now be installed very easily via SAPlink too (provided you follow the corresponding How-to guide available). Note however that this version released as a nugget file doesn't include any ABAP Unit test class to simplify the installation process (but of course all ABAP Unit tests have been passed before creating the nugget).

 

And even more new features can be found in the Release notes document:

  • Parameters to influence the scope of the dependency analysis.
  • Ability to check dependencies that have been added manually in transport request attributes.
  • New columns to display transport request status in TMS queues.
  • Ability to exclude successfully imported request.
  • Ability to start dependency analysis in background.
  • Etc.

 

So if you're interested do not hesitate to join the project and give it a try: even if SAP is working on a similar program at the moment, we don't know yet when it's released, and for which SAP Netweaver versions it will be delivered... hence TRDA may still have some fine days ahead of it!


Some Important Function Modules

$
0
0
Hi All,
These are some of the Function Modules which i found very useful and used repeatedly in my development projects. Hope these are useful for all your fellow ABAP-ers out there.
S.NoFM NameDescriptionInputOutput
1SO_SPLIT_FILE_AND_PATHSplit the File Name and PathFile PathFile Name with Extension
2RZL_READ_FILERead Data From Presentation Server

1.File Path

2.File Name

Internal Table with file contents.
3GUI_DOWNLOADDownload The Internal Tabel Contents to Local System

Internal Table with

Required data

File in Local System
4C13Z_FILE_UPLOAD_ASCII

Upload File From Local Server To Presentation

Server

File In LocalFile In Presentation Server
5OIL_MONTH_GET_FIRST_LASTTo Get first and last dates of a month

1.Month Year Or

2.Date

Start and End date
6PA03_PERIODDATES_GETTo Get calendar dates from payroll periodPayroll PeriodMonth Begda and Endda
7FIMA_DAYS_AND_MONTHS_AND_YEARSTo get the date diffBegda,EnddaGives the difference in no. of days,months,year separately
8F4_DATETo get the Calendar pop-upCurrent DateCalendar as in case of SY-DATUM
9GET_DOMAIN_VALUESTo Get the Values maintained in Search HelpsDomain NameThe Value Range data maintained.
10DYNP_VALUES_READTo Directly Read the Value of the Screen field at run time.Screen Field NameValue Entered in the Screen at run-time
Hope this list is helpful to you. Also please share the FMs you have used frequently.
-Regards,
Ragavan

New ABAP Features with ABAP 7.40

$
0
0

With the release of AS ABAP 7.40 the ABAP language has some nice new features. Following are few of them –

 

1.    Introduction of real expression oriented feature –

Suppose we have to output a value of column of an internal table for a particular row along with a string.

In earlier releases code look like this –

                        1.png

In SAP 7.40 code is

a.       In-line expression with helper variable, which removes concatenate statement.

     2.png

 

b.      Table expression with helper variable, which removes READ TABLE statement.

3.png

 

 

2.    New style of data declarations

In Prior releases values cannot be assigned in line with data declaration, but possible with release 7.40

                     4.png

          5.png

3.    New Constructor Operators

3.1.        Instantiation Operator NEW

The instantiation operatorNEWis a constructor operator that creates an object reference of class or data.

a.     Syntax ->

…. NEW dTyp | # ( val) …

Creates a data object of data type dTyp or data type of value val having value val

Example ->

6.png

b.     Syntax ->

…. NEW my_class | #(  p1 = v1 p2 = v2 … ) …

Creates an instance of class my_classor depending on the operand type and passes parameter list to instance constructor.

Example ->

7.png

 

3.2.        Constructor Operator VALUE

The value operatorVALUEis a constructor operator that constructs a value for the type specified withtype.

a)            ... VALUE dTyp|#( ) ...

   

Constructs an initial value for any data type.

b)           ... VALUE dTyp|#( comp1 = a1 comp2 = a2 ... ) ...

Constructs a structure where for each component a value can be assigned.

c)            ... VALUE dTyp|#( ( ... ) ( ... ) ... ) ...

Constructs an internal table, where for each line a value can be assigned.

                8.png

 

3.3.        Reference Operator REF

REF Operator is an alternative to the following abap statement.

GET REFERENCE OF dobj INTO r_obj.

Syntax ->

     ... REF dTyp|#(dobj ) ...

3.4.        Casting Operator CAST

CAST Operator performs the narrow or wide cast

 

                9.png

3.5.        Conditional Operator COND

New Conditional operator which assigns the value to an object based on some condition.

Syntax ->

... COND dTyp|#(WHEN log_exp1 THEN result1
                [ WHEN log_exp2 THEN result2 ]
                ...
                [ ELSE resultn ] ) ...

Example ->

                10.png

3.6.        Conditional Operator SWITCH

New Conditional operator which assigns the value to an object based on some condition.

Syntax ->

... SWITCH dTyp|#( operand
                    WHEN const1 THEN result1
                  [ WHEN const2 THEN result2 ]
                  ...
                  [ ELSE resultn ] ) ...

AMAZING !!! UNBELIEVABLE !!!

Warn Developers about released objects but not yet transported to Production

$
0
0

Hi ABAPers,

 

I would like to have the opportunity to share a useful development warning system.

 

Many of us have experienced problems when transporting objects from DEV- > QMS -> PRD. When more than one user starts working on a single object it becomes a problem to keep the transports in sync. The idea focuses in warning developers when he/she is about to make changes to an object that has been released from development server but is now in quality. This means the last development on the object will get overlapped if we make additional changes and transport them. The warning will help us know easily if anybody else is working on the same object.

 

To give warnings to developers when last change to an object is not in production


PROBLEM DESCRIPTION

It has often been observed that multiple developers are working on common objects, be it an ABAP report, a function module, or a change in a table structure. Such changes have a lot of dependency and often are the cause of conflicts during acceptance phase due to overwriting of changes.

 

PRELIMINARY DIAGNOSIS

For example, a user had added a lot of objects in a transport for PROJECTX and is in quality. Now a small change comes up and that change needs to be done to an object that is already included among the list of objects to be transported in PROJECTX transport. The developer makes the changes unaware of the dependency and moves his fix to production. Now the customer is happy, but when the PROJECTX transport goes to production, it overwrites the changes are restores it. The customer complains that the changes are not working after PROJECTX rollout to production.

 

DETAILED DIAGNOSIS

Suppose we consider a ticket IMXXXX001 in which a developer DEV01 is supposed to make some changes to REPORT ZREPORT_01. The developer opens the report, makes the desired changes to the report to meet the current requirements, creates a new transport request for the change and releases it and the updates the etracker for the changes to be transported to quality. Meanwhile, another developer, DEV02 is assigned a ticket IMXXXX002 for which he too has to make some changes to REPORT ZREPORT_01 to fix some issues. So he makes the changes and transports the changes to quality as well. Now that both their changes are in quality, they assign their etrackers to their respective Acceptance testers UAT01 and UAT02. Now UAT02 is quick and prompt and performs the acceptance test successfully. Both DEV02 and UAT02 are not aware that changes made by DEV01 are not yet acceptance tested and they decide to move their transports to production. Soon approvals are in place and the changes made by DEV02 alongwith the changes for DEV01 reach production. This means, the changes of DEV01 are in production without being acceptance tested. To complicate the issue further, UAT01 performs the acceptance test and finds the changes made by DEV01 are not working. Also, the customer starts complaining that the report is not working as expected (due to changes by DEV01). Such situations need to be avoided.

 

TEMPORARY WORKAROUND

The temporary workaround is to go to SE10, open the transports and check transport logs manually.

 

PERMANENT FIX

The permanent fix to this problem is to provide a warning to the developer in case the last change done (i.e. the transport number for the last version) is not yet in production. This means, the change is either in queue of being transported or currently in UAT phase. In case it is in UAT and it fails, there could be rework and make the changes further dependent.

The goal of the document is to make necessary adjustments in the development system in such a way that in case some developer is in the process of making changes to a dependent object, he/she will encounter a warning message, post to which the developer can identify and inform about the dependency to the respective IT manager and seek permission whether to continue with the changes ignoring the warning.

Here is an example of a table ZMSPOCEMAIL, the recent version of which is still in quality (as you can see below that the changes are still not in C0C and C05 which are the production systems). Though the solution works for any table whose recent changes are not in production, I will use this table as an example for the time being.

image002.jpg

 

Suppose a user goes to SE11 and opens the table ZMSPOCEMAIL, checks the fields and decides to add a new field to it as per the latest requirement.

 

image004.jpg

 

Now when he presses the change button a new screen pops up warning the developer that the last transport, though released from development, is not yet in production similar to the one shown below.

 

image006.jpg

 

This message would warn the developer that some other developer might be working on the same table he wants to make changes on. However the developer may select Yes and continue to make the changes at this point which will help him continue making changes being aware of the risks or select No if he wishes to notify ITAM about the dependency and seek approval to continue making changes.

 

TECHNICAL DETAILS

There are 3 customer exit function modules that need to be activated. They are:

EXIT_SAPLSEDD_001 - For data dictionary objects

EXIT_SAPMS38L_001 - For function modules

EXIT_SAPLS38E_001 - For reports, includes etc. through the ABAP Editor

For this we have to go to SMOD and search for the enhancements.

These are:

SEDD0001      Customer exits in ABAP/4 Dictionary

SEU00004      Customer exits in the Function Library

SEUED001      ABAP Editor

We have to create a new project in CMOD and assign these enhancements, and activate the project.

 

image008.jpg

 

After activation of project the necessary programming logic has to be written into the function modules mentioned. This would include using the function module GET_VERSION_LIST to fetch version information for the object to be edited, read the transport log for the highest version of the object using function module TR_READ_GLOBAL_INFO_OF_REQUEST, and finally using a popup message box which will prompt the developer that the last transport has not reached production.

This change needs to be implemented in the Development systems only.

POSSIBLE IMPROVEMENTS POST IMPLEMENTATION

  1. Reduction in dependency
  2. Efficient logging of dependent changes if any
  3. Reduction in rework
  4. Reduction in number of tickets reopened
  5. Increased compliance to quality processes and development standards

 

Given below is a working sample code for one of the exits which you can use with minor adjustments depending upon you system landscape.

 

Here is an example code for EXIT_SAPLSEDD_001 - Include ZXSEUU19

 

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

*&  Include           ZXSEUU19

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

 

DATA:

           i_verslist     TYPE TABLE OF vrsd_old,

           i_systems      TYPE ctslg_systems.

DATA:

           wa_verslist    TYPE vrsd_old,

           wa_log         TYPE ctslg_cofile,

           wa_system      TYPE LINE OF ctslg_systems,

           wa_step        TYPE LINE OF ctslg_steps,

           wa_action      TYPE LINE OF ctslg_actions.

DATA:

           h_objname      LIKE vrsd_old-objname,

           h_objtype      LIKE vrsd_old-objtype,

           h_answer       TYPE c,

           h_trans        LIKE e070-trkorr,

           h_message      TYPE char128.

 

CHECK operation = 'MODIFY'.

 

MOVE objectname TO h_objname.

MOVE objtype TO h_objtype.

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

Please note that most of the times the last character of the

object type needs to be changed to D. e.g. TABS should be TABD, etc.

This should be verified in-situ and adjusted accordingly

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

 

CALL FUNCTION 'GET_VERSION_LIST'

  EXPORTING

    objname      = h_objname

    objtype      = h_objtype

  TABLES

    version_list = i_verslist.

 

SORT i_verslist BY versno DESCENDING.

CHECK i_verslist[] IS NOT INITIAL.

READ TABLE i_verslist INTO wa_verslist INDEX 1.

 

CHECK wa_verslist-korrnum IS NOT INITIAL.

 

MOVE wa_verslist-korrnum TO h_trans.

 

*   read the transport log for the particular transport

CLEAR wa_log.

CALL FUNCTION 'TR_READ_GLOBAL_INFO_OF_REQUEST'

  EXPORTING

    iv_trkorr                 = h_trans

*   IV_DIR_TYPE               = 'T'

*   IS_SETTINGS               =

*   IV_SUPPRESS_DELETED_STEPS = ' '

*   IT_COMM_SYSTEMS           =

  IMPORTING

    es_cofile                 = wa_log

*   EV_USER                   =

*   EV_PROJECT                =

  .

 

i_systems[] = wa_log-systems[].

 

CHECK i_systems[] IS NOT INITIAL.

*When C05 /C0C are the production systems

READ TABLE i_systems INTO wa_system WITH KEY systemid = 'C05'.

IF sy-subrc NE 0.

*not in c05

  READ TABLE i_systems INTO wa_system WITH KEY systemid = 'C0C'.

  CHECK sy-subrc NE 0.

ELSE.

*in c05

  RETURN.

ENDIF.

 

h_message = 'The last transport & has not yet gone to production. Do you still want to edit the current object?'.

REPLACE ALL OCCURRENCES OF '&' IN h_message WITH wa_verslist-korrnum.

 

CALL FUNCTION 'POPUP_TO_CONFIRM'

  EXPORTING

*   TITLEBAR                    = ' '

*   DIAGNOSE_OBJECT             = ' '

    text_question               = h_message

   text_button_1               = 'Yes'(001)

*   ICON_BUTTON_1               = ' '

   text_button_2               = 'No'(002)

*   ICON_BUTTON_2               = ' '

*   DEFAULT_BUTTON              = '1'

   display_cancel_button       = ''

*   USERDEFINED_F1_HELP         = ' '

*   START_COLUMN                = 25

*   START_ROW                   = 6

*   POPUP_TYPE                  =

*   IV_QUICKINFO_BUTTON_1       = ' '

*   IV_QUICKINFO_BUTTON_2       = ' '

IMPORTING

   answer                      = h_answer

* TABLES

*   PARAMETER                   =

EXCEPTIONS

   text_not_found              = 1

   OTHERS                      = 2

          .

IF sy-subrc <> 0.

* Implement suitable error handling here

ENDIF.

 

IF h_answer NE '1'.

  sy-msgid = 'E2'.

  sy-msgno = '004'.

  sy-msgv1 = 'Action Cancelled'.

  RAISE cancelled.

 

ENDIF.


Display Company Logo (image) in Selection Screen

$
0
0

Have you ever wondered how we can place an image file in the selection screen of an ABAP Report? For example, if we go to the transaction SMARTFORMS we will find an image on the selection screen. Given below are the steps which you can follow to achieve the same in your own reports.

 

Go to SMW0 and for uploading the image.

 

image002.jpg

Select Binary Data

image004.jpg

Select the Find Button image006.jpg

 

Press image008.jpg

 

Press the Create button

 

image010.jpg

 

Enter name and description

 

image012.jpg

 

Select the image to upload

 

image014.jpg

 

Assign a package (must)

 

image016.jpg

Press Save and Okay

 

image018.jpg

 

Write the report as given below :

 

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

*& Report  ZGB_PROG06

*&

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

*&

*&

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

 

REPORT  zgb_prog06.

 

* START OF DO NOT CHANGE***********************************

DATA: docking TYPE REF TO cl_gui_docking_container,

      picture_control_1 TYPE REF TO cl_gui_picture,

      url(256) TYPE c .

DATA: query_table LIKE w3query OCCURS 1 WITH HEADER LINE,

      html_table LIKE w3html OCCURS 1,

      return_code LIKE  w3param-ret_code,

      content_type LIKE  w3param-cont_type,

      content_length LIKE  w3param-cont_len,

      pic_data LIKE w3mime OCCURS 0,

      pic_size TYPE i.

* END OF DO NOT CHANGE*************************************

 

DATA : sum(4) , num1(4) , num2(4).

PARAMETERS: p_dummy(4) DEFAULT '4' .

PARAMETERS: p_dummy1(4) DEFAULT '5' .

 

 

AT SELECTION-SCREEN OUTPUT.

  PERFORM show_pic.

 

START-OF-SELECTION.

 

 

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

*& Form show_pic

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

FORM show_pic.

 

  DATA: repid LIKE sy-repid.

 

  repid = sy-repid.

 

 

  CREATE OBJECT picture_control_1 EXPORTING parent = docking.

 

  CHECK sy-subrc = 0.

  CALL METHOD picture_control_1->set_3d_border

    EXPORTING

      border = 5.

 

  CALL METHOD picture_control_1->set_display_mode

    EXPORTING

      display_mode = cl_gui_picture=>display_mode_stretch.

  CALL METHOD picture_control_1->set_position

    EXPORTING

      height = 200

      left   = 100

      top    = 20

      width  = 400.

*CHANGE POSITION AND SIZE ABOVE***************************

 

  IF url IS INITIAL.

 

    REFRESH query_table.

    query_table-name  = '_OBJECT_ID'.

*CHANGE IMAGE NAME BELOW UPLOADED IN SWO0******************

    query_table-value = 'BIKER'.

    APPEND query_table.

 

    CALL FUNCTION 'WWW_GET_MIME_OBJECT'

      TABLES

        query_string        = query_table

        html                = html_table

        mime                = pic_data

      CHANGING

        return_code         = return_code

        content_type        = content_type

        content_length      = content_length

      EXCEPTIONS

        object_not_found    = 1

        parameter_not_found = 2

        OTHERS              = 3.

    IF sy-subrc <> 0.

*      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

*              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

    ENDIF.

 

    CALL FUNCTION 'DP_CREATE_URL'

      EXPORTING

        type     = 'image'

        subtype  = cndp_sap_tab_unknown

        size     = pic_size

        lifetime = cndp_lifetime_transaction

      TABLES

        data     = pic_data

      CHANGING

        url      = url

      EXCEPTIONS

        OTHERS   = 1.

 

  ENDIF.

 

  CALL METHOD picture_control_1->load_picture_from_url

    EXPORTING

      url = url.

 

*Syntax for URL

*url = 'file://D:\corp-gbanerji\pickut\cartoon_184.gif'.

*url = 'http://l.yimg.com/a/i/ww/beta/y3.gif'.

 

ENDFORM.                    "show_pic

 

Make changes in the report accordingly

 

image022.jpg

Once done, execute the report and it should come as below.

 

image024.jpg

Concept of Switch Framework in Enhancement

$
0
0

The main purpose of the Switch Framework is to simplify an ABAP-based system landscape by adopting one or more industry solutions in a standard system. The Switch Framework allows you to externally control the visibility of repository objects or their components by means of switches.

By using the Switch Framework, all industry solutions and a restricted list of repository objects are delivered in an inactive state in the system. With minor exceptions, you no longer need to install an industry solution – you can activate it when required.

 

Integration

The Switch Framework is integrated in the ABAP Workbench and works closely together with the Enhancement Framework.

 

Features
The Switch Framework enables you to:

● Switch on industry solutions and Enterprise Add-Ons

● Enhance delivered partner and customer systems

 

Contents of Enhancement Package

● Each enhancement package contains a set of business functions

● Each business function is optionally implemented and activated

 

Optional Installation

● Only install the business functions that are applicable to the business needs

● Post installation process changes will take place only on activation

● No impact on SAP netweaver platform

 

Optional Activation

● Activate components on demand

● End user regression testing by component activation

● SAP provides testing templates for the components

 

Bug finding using Switch Framework

● Use the switch framework to activate/deactivate enhancements to evaulate source of bug

● If bug is gone on deactivation it is part of the enhancement

● If bug is persistent on deactivation it is part of standard

 

Example:

Create at least 1 switch and 1 business function. Assign the switch to the packages containing the enhancement implementations. Use transaction SFW5 to activate/ deactivate the switch.

 

1.JPG

 

Please note that the business function must be reversible. Switching of BC-Sets and DDIC is not allowed.

 

Architecture of Switch Framework

 

2.JPG

After the business function is available, the switching of the business function will be possible using the switch framework.

 

3.JPG

Assignments can be made in both directions:

● Define the assignment in superordinate object if possible.

● Creating the assignment in the subordinate object has less flexibility and is comparable to an enhancement.

 

Switchable Objects by package Assignment:

● Enhancement Implementations

● Appends, SI-, CI- Includes for dictionary structures

● Fixed value appends to domains

● Append search helps

● Secondary Indexes

● Switch Business configuration sets.

 

Example of Switch in Dictionary Index.


 

Example of Switch in Append Structure:

 

 

Switchable objects by Direct Assignment:

● Screen elements and flow logic

● Menu entries

● IMG Nodes

● Easy access menus

● Customizing

 

Example of Switch in Screen Painter

 

 

Switch dependent screen elements in the element list – disabled. Elements are not visible at runtime.

 

Switch Dependent Module in Screen Painter

 

 

Switch in Menu Painter

 

 

Dependent Objects in given business function

 

 

Deactivating Business Functions:

● Reversible Business Functions must not contain dictionary objects or BC-Sets.

● Reversible Business Functions may be deactivated in development or test systems only.

● Do not deactivate a reversible Business Function in a production system to keep data integrity.

 

* Practical example coming soon

Transport Checking Tool (Object level)

$
0
0

Transport Checking Tool (on Object level)

Did you ever get the request to ‘quickly check the transport list’ two days before Go-Live?

Only to discover that the list has hundreds of transports with thousands of objects?

And after going through the first few transports you find out that the list is a mess. Checking one object will indicate other transports that are not in the list, or transports that are ‘not needed anymore’ but with changes that were never rolled back, or emergency transports already in production... Etc. etc.


So how do you check the list? You know that there is no way that this list of transports can go to production without issues. Clearing up the mess is impossible, takes too long or is too costly.

There will be issues, but which? How serious will they be?

The next question you’ll get is ‘What is the risk?’. Do you dare to answer ‘The system could go KABOOOM’?

 

Yes, most issues can be prevented if the responsible user is careful in creating transports and organizing them before releasing them. However, nobody’s perfect. Mistakes will be made and corners will be cut. When the pressure from above increases, strict rules suddenly become flexible.

 

Some possible risks:

  • Loss of functionality in production (if a newer transport is overwritten),
  • Moving untested code to production (if an older transport exists for the same object, that is not included in the transport list),
  • Objects use DDIC objects that are in Development and Acceptance, but NOT in production (causing dumps),
  • Different versions are active in Production and Acceptance.

 

In the past I ran into this problem. I had to check a list of transports for a project that lasted over a year. Multiple developers worked on it and each delivered a list of transports. This I had to check… I encountered so many problems that I decided to write a small program that would check for older and newer transports of all objects used and then give warnings. The program was far from perfect, but it did the trick. The project from hell went live with only minor issues. That was several years ago. Since that time the program has grown. More checks and functions were implemented.

 

I do not have the illusion that it is perfect. I tried to make it as flexible as possible, but there is always room for improvement.

 

Logo3.jpg

But if there are people who may have use for a tool like this, they can check it out and download it from SAP Code Exchange: https://cw.sdn.sap.com/cw/groups/ztct. It is a local program, available as a SAPLINK nugget, that only has program text and documentation.

It does not make changes to the database, but runs as a straightforward report. The only thing the program can create, is transport documentation, if the user decides to do so.

 

I would also like to take the opportunity to point out that there are other initiatives. For example the Transport request dependencies analyzer (https://cw.sdn.sap.com/cw/groups/transport-request-sequencer).

 

You can find that and other projects related to Transport Checking here:  https://cw.sdn.sap.com/cw/codex/projects#/?tags=transport.

 

Description of the Tool

Below is a short description of the tool, input, output and functionality. For more detailed information, please have a look at the User Manual on Code Exchange.

 

Selection Screen

This is what the selection screen looks like:

SelectionScreen.jpg

Output

This screenshot is an example of the output.

ZTCT_Output.jpg

Interesting is the Application toolbar, which has buttons to:

  • Recheck selected rows,
  • Add transports conflicting with selected rows,
  • Add a single transport,
  • Add another saved file (merge lists),
  • Remove selected transports (if you select one row, all rows for that transport will be removed)
  • Mark a transport that is in Production for Re-transport,
  • Jump to the next relevant Conflict,
  • Build a simple list (on header level, unique transport numbers only, no Object information).

 

Transport sequence: order and disorder

The order in which the transports should be moved to production is the order in which they were imported in the Acceptance environment.

This guarantees that the versions in Production will be the same as the versions in Acceptance at the time the User Acceptance Test was performed and signed off.

Determining the transport order is straightforward enough. The complicating factor will be other transports in acceptance, containing one or more objects that are the same as objects in your list.

These conflicting transports may belong to other projects or other people. Maybe those transports cannot yet go to production (code is untested) or may already have been transported to production (as emergency transports).

 

In general it is not the process to determine the transport sequence that will cause problems, but other transports that will cause disruptions to your list.

 

Preventing that these issues and risks arise is always better than trying to solve them. It all starts with a good understanding of which objects should be grouped together in the same transport and which objects should be transported separately.

 

The Developer or Functional consultant should always be very alert for these considerations.

As a rule, User-Exits should always be transported separately. The same rule would apply for DDIC elements that can/will be used in multiple objects.

Other considerations would be if the complete function group needs to be transported or only a single function. Should the complete Class be transported or only the implementation of a method? Should the complete program (including texts and documentation) be transported or only the Report code?

 

Keeping the transport list clean and simple may prevent a lot of hair-pulling later on. 

 

Risks when transporting to Production

When transports are moved to production, there are several possible risks. The chance, severity and impact of issues on the system will increase with the number of transports involved and the number of objects in these transports.

Other complicating factors are the number of developers working on the same project, the runtime of the project, developers working on the same objects, transports being moved in case of production issues (disrupting the alignment) etc. etc.

Frequent problems encountered when NOT using a transport checking tool are described in the next two paragraphs.

 

Objects overwrite newer versions already in Production

Result: loss of recent changes/functionality.

OvershootingATransport.jpg

 

Objects go to Production with previous versions in Acceptance

Result: unwanted (or even incorrect) changes go to Production without being signed off.
Code can also contain data elements that are not yet in production. The used/required data elements might exist in Acceptance, in another transport, but not yet in Production. When developing and testing there will be no syntax error. There will be no warning at all because the data element exists in Development and Acceptance. Only after the transport to production has been done, dumps will occur.

RiskIgnoringPreviousVersions.jpg

Will Code for Food

$
0
0

Yes, I know you've seen it before.

Coder.jpg

But lets go deeper than how funny it is.

 

I love coding!  But the life of a coder is not all that good.  So here's a guy who could choose anything to do for food.  In America, the government will pay him not to work.  But he is such a dedicated coder (I know it's a gag pic, but use your abstract thinking.  Imagine...) that he will write code for free just so long as he gets fed and has the fun of coding.

 

So one of my take homes from this is that if you don't love coding, get out.  There are fun things to do in the world for each person.  If yours isn't coding, find something that you do love.  Life is too short to do anything less.

 

Also, looking at this guy, can't you just see the bad times.  Bad times come and bad times go.  I remember salaries and rates being cut in half a few years back.  But like this guy, I worked right through it.  I never slowed down.

 

So I keep this picture on the wall beside my work desk.  And when I get tired I refresh myself by considering the messages in the picture.

 

I hope your coding goes well,

 

Neal Wilhite


Authorization check for selection option

$
0
0

I want to share AUTHORITY-CHECK OBJECT for selection opting.

 

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-002.
PARAMETERS:p_bukrs type bkpf-bukrs OBLIGATORY.
SELECT-OPTIONS :  so_audat FOR vbak-audat OBLIGATORY,
      so_auart FOR vbak-auart OBLIGATORY,
      so_kunnr FOR vbak-kunnr,
      so_matnr FOR vbap-matnr,
      so_vrkme FOR vbap-vrkme OBLIGATORY,
      so_lgort FOR vbap-lgort,
      so_werks FOR vbap-werks,
      so_vkorg FOR vbak-vkorg,
      so_vtweg FOR vbak-vtweg,
      so_spart FOR vbak-spart.
SELECTION-SCREEN END OF BLOCK b1.

 

Want to check Authorization for so_vkorg, so_vtweg, so_spart.

 

Go to AT SELECTION-SCREEN OUTPUT.

Now AT SELECTION-SCREEN.

Call FM V_VBAK_VKO.

 

Check the code.


SELECT *
FROM  vbak
          INTO TABLE tmp_vbak
         WHERE audat IN so_audat
      AND auart IN so_auart
      AND vkorg IN so_vkorg
      AND vtweg IN so_vtweg
      AND spart IN so_spart
      AND bukrs_vf = p_bukrs.

   LOOP AT tmp_vbak INTO  wa_tmp_vbak.
     AUTHORITY-CHECK OBJECT 'V_VBAK_VKO'
        ID 'VKORG' FIELD  wa_tmp_vbak-vkorg
        ID 'VTWEG' FIELD  wa_tmp_vbak-vtweg
        ID 'SPART' FIELD  wa_tmp_vbak-spart
        ID 'ACTVT' FIELD '03'.
   ENDLOOP.
   IF sy-subrc <> 0.
     MESSAGE 'No authorization' TYPE 'E'.
   ENDIF.

 

Hope it will work

MS Office made easy

$
0
0

Some of us have experience with SapScript, SmartForms and PDF based forms. Nevertheless Customers sometime wish to get an MS Office document as soon as it is ‘more familiar’.

We have some options provided by SAP or third party developers. These are:

OLE, DOI both are standard and couple versions of MS Office tools ZWWW as an example or the tool to work with RTF documents.

But let’s compare these technologies:

OLE becomes incredible slow when operating huge data, but you can do everything with your document. But use of OLE makes you hardcode types of documents. So this is a reason why it’s not flexible.

DOI works fine with huge data due to optimization of flushes. For example, you can made OLE document very fast by using queue of OLE commands and common FLUSH. But DOI provides you with this ‘fast option’ from the box. Furthermore you can still operate with OLE objects getting correspondent reference. But where are disadvantages? Well you need to create additional objects to link your GUI-session with document on a frontend such as container. Then you should know how to be with all those interfaces like I_OI_DOCUMENT_PROXY.

ZWWW is a great tool to get almost everything fast and good. You can create a template either at SMW0 or at OAOR transactions. Then you specifies logic of data mapping. This tool works fast.  Isn’t it a dream? I guess no. Because this tool operates with special files with VBA-macroses and runs it without user’s authorization. So it’s a potential harm to user’s computer.

Tool to operate RTF document works also fine but you need to create a whole document in you program. So there’s a huge question how to provide user with possibility to influence the document?

Why not to have a tool which separates design and content parts like does SmartForms or PDF-based forms?

We have documents repository (t-code OAOR) and we have web-repository (t-code SMW0). Both have possibility to store MS Office documents and templates.

We have DOI and OLE tools to manipulate document.

We want to separate development and design stages to make documents flexible.

Desired result is when developer creates a data-extraction report which includes simple call of MS Office document template. This template filled with data extracted by rules described simply and placed into the document. So a functional consultant without developer-key can manipulate design of this document at any time.

Imagine you’ve created a report that gets FI document with its positions. It’s very simple: get the BKPF record and correspondent positions from BSEG. Here are two types of data: structure (BKPF single line) and table type (BSEG positions). Then report calls document via some tool and this FI document is represented with some layout. On the other side a consultant can instantly change any parameter of the document: field’s order of described BKPF structure and their presence, column order of table content and their presence. So, while you have the simple report to extract data you can have different results with possibility to change layout even at production system directly.

Source code listed below will let you use a simple code to fill complex documents. Example of use is:

DATA: BEGIN OF interface,
bkpf  
TYPE bkpf,
bseg_t
TYPE TABLE OF bseg,
END OF interface,
lref_doi
TYPE REF TO i_oi_document_proxy.

*  Some data extraction
lref_doi
= zcl_bas_utilities=>get_doi_doc_from_so( 'FI_DOC_TEMPLATE' ).
zcl_bas_utilities
=>put_data_by_intf_into_names( ir_doi       = lref_doi
is_interface
= interface ).
message 'Save document before press `OK`!' TYPE 'I'.

 

Fields mapping defined by range names (for MS Excel) or bookmarks (for MS Word). For example: ‘BKPF_1’ to output the first field of structure BKPF or ‘BKPF_STBLG’ to output value of field STBLG of structure BKPF. To create column order for BSEG table we should name range like this: ‘BSEG_2_3_BETRG’. This range name will describe filling table with 3 columns of second, third and BETRG fields of table.

  Here is my code to get this tool

 

 

 

Class ZCL_BAS_UTILITIES.

Common part:

 

class ZCL_BAS_UTILITIES definition
public
final
create public .

public section.
*"* public components of class ZCL_BAS_UTILITIES
*"* do not include other source files here!!!
type-pools CNTL .
type-pools SBDST .
type-pools SLIS .

constants TRUE type CHAR01 value 'X'. "#EC NOTEXT
constants FALSE type CHAR01 value ' '. "#EC NOTEXT
constants ON type CHAR01 value '1'. "#EC NOTEXT
constants OFF type CHAR01 value '0'. "#EC NOTEXT

class-methods GET_DOI_DOC_FROM_SO
importing
!IV_DOCUMENT_NAME
type CLIKE
!IV_HIDE
type CHAR01 optional
returning
value(RR_DOI_DOC) type ref to I_OI_DOCUMENT_PROXY .
class-methods INSERT_TABLE_INTO_NAMED_RANGE
importing
!IR_DOCUMENT
type ref to I_OI_DOCUMENT_PROXY
!IT_TABLE
type STANDARD TABLE
!IV_DICTYPE
type CLIKE optional
!IV_RANGENAME
type CLIKE .
class-methods FILL_VALUE_BY_RANGE_NAME
importing
!IV_RANGE_NAME
type CLIKE
!IS_FIELD
type ZHR_NAMEDESCR_WA optional
!IR_DOCUMENT
type ref to I_OI_DOCUMENT_PROXY
!IV_NEW_VALUE
type ANY
!IV_CONCATENATE
type CHAR01 default 'X' .

  class-methods GET_NAMES_FROM_DOI
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IV_STOR_OLE_OBJ
type CHAR01 default FALSE
returning
value(RT_NAMES) type ZHR_NAMEDESCR_ITAB .
class-methods OLE_FLUSH .
class-methods PUT_DATA_BY_INTF_INTO_NAMES
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IS_INTERFACE
type ANY .
class-methods SAVE_DOI
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IV_FILEPATH
type STRING optional
returning
value(RV_FILEPATH) type STRING .
class-methods OPEN_DOCUMENT
importing
!IV_FILEPATH
type STRING .
class-methods GET_PAGES
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
returning
value(RV_RESULT) type INT4 .

 

Private part:

 

private section.
*"* private components of class ZCL_BAS_UTILITIES
*"* do not include other source files here!!!

class-data FIELDS_TO_UPDATE type SOI_FORM_LIST .
class-data SEPARATOR type CHAR04 .
class-data GO_DOC type CNTL_HANDLE .
class-data GO_RANGE type OBJ_RECORD .
class-data GO_BR_CELL type OBJ_RECORD .
class-data GO_LT_CELL type OBJ_RECORD .
class-data GO_APL type OBJ_RECORD .
class-data GO_NAMES type OBJ_RECORD .
class-data GO_ACTIVESHEET type OBJ_RECORD .
class-data GO_SELECTION type OBJ_RECORD .

class-methods ADD_FIELD_VALUE
importing
!IS_FIELD
type ANY
!IV_VALUE
type ANY
!IV_CONCT
type CHAR01 default 'X' .
class-methods INITIALIZE_FIELD_TO_UPDATE .
class-methods UPDATE_FIELDS
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IT_FIELDS
type ZHR_NAMEDESCR_ITAB .
class-methods HIDE_DOI
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY .
class-methods FILL_VALUE_BY_BOOKMARK
importing
!IO_BOOKMARK
type OBJ_RECORD
!IV_NEW_VALUE
type ANY .
class-methods GET_WORD_TABLES
importing
!IO_DOCUMENT
type OBJ_RECORD
returning
value(RT_TABLES) type ZHR_WORDTABLE_ITAB .
class-methods INSERT_TAB_INTO_WORD_TAB
importing
!IT_TABLE
type STANDARD TABLE
!IR_WORD
type ref to I_OI_WORD_PROCESSOR_DOCUMENT
!IV_TAB_INDX
type ANY .
class-methods PUT_STR_FIELD_INT_BKMRK
importing
!IO_BOOKMARK
type OBJ_RECORD
!IT_FIELDS
type STANDARD TABLE
!IS_SOURCE
type ANY .
class-methods PUT_TABLE_INTO_BKMRK
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IT_FIELDS
type STANDARD TABLE
!IT_SOURCE
type STANDARD TABLE
!IV_TAB_INDX
type ANY .
class-methods PUT_THE_STRUCTURE
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IS_FIELD
type ZHR_NAMEDESCR_WA optional
!IT_FIELDS
type STANDARD TABLE
!IS_SOURCE
type ANY
!IV_FULL_NAME
type CLIKE .
class-methods PUT_THE_TABLE
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
!IT_FIELDS
type STANDARD TABLE
!IT_SOURCE
type STANDARD TABLE
!IV_FULL_NAME
type CLIKE .
class-methods GET_FORM_FIELDS
importing
!IR_FORM
type ref to I_OI_FORM
changing
!CT_NAMES
type ZHR_NAMEDESCR_ITAB .
class-methods GET_WORD_BOOKMARKS
importing
!IR_DOI
type ref to I_OI_DOCUMENT_PROXY
changing
!CT_NAMES
type ZHR_NAMEDESCR_ITAB .
class-methods GET_XLS_FIELDS
importing
!IR_XLS
type ref to I_OI_SPREADSHEET
changing
!CT_NAMES
type ZHR_NAMEDESCR_ITAB .

Method’s code:

method GET_DOI_DOC_FROM_SO.
DATA: ls_bds_conn       TYPE bds_conn00,
lr_container_cont
TYPE REF TO i_oi_container_control,
lr_container     
TYPE REF TO cl_gui_custom_container,
lt_content       
TYPE sbdst_content,
lv_size          
TYPE i.

SELECT SINGLE classname classtype log_system object_key
INTO CORRESPONDING FIELDS OF ls_bds_conn
FROM bds_conn06  "Actually here can be any of bds_connNN DB tables
WHERE object_key = iv_document_name.
CHECK ls_bds_conn IS NOT INITIAL.
* Document exists

* Get document's content
cl_bds_document_set
=>get_with_table(
EXPORTING
logical_system
= ls_bds_conn-log_system
classname     
= ls_bds_conn-classname
classtype     
= ls_bds_conn-classtype
object_key    
= ls_bds_conn-object_key
CHANGING
content       
= lt_content ).

* Prepare control
c_oi_container_control_creator
=>get_container_control(
IMPORTING
control = lr_container_cont ).

CHECK lr_container_cont IS BOUND.

* Create GUI- connection
CREATE OBJECT lr_container
EXPORTING
container_name
= 'TECH_CONTAINER'
EXCEPTIONS
others         = 6.

CHECK lr_container IS BOUND.

*Initialize control
lr_container_cont
->init_control(
r3_application_name
= 'SAP'
parent             
= lr_container ).

* Initialize proxy
CALL METHOD lr_container_cont->get_document_proxy
EXPORTING
document_type 
= ''
IMPORTING
document_proxy
= rr_doi_doc.

*Fill document with data
rr_doi_doc
->open_document_from_table(
document_size
= lv_size
document_table
= lt_content ).

CHECK iv_hide is NOT INITIAL.
hide_doi
( rr_doi_doc ).
endmethod.

METHOD insert_table_into_named_range.
* Last change at 23 March 2012 by Guryanov Alexander
* Optimize rows insert to reduce dependence execution
* time from a size of the input table.
*  I've tried to reduce FLUSH commands but here is
*  the minimum.
DATA: lr_doi TYPE REF TO i_oi_document_proxy,
lr_xls
TYPE REF TO i_oi_spreadsheet,
lv_new_range
TYPE char80,
lt_fields
TYPE TABLE OF rfc_fields,
lv_lines 
TYPE i,
lv_address
TYPE char40,
lv_end_row
TYPE char20,
lv_end_column
TYPE char20,
lv_columns
TYPE i,
lv_cur_row
TYPE char20,
lv_cur_column
TYPE char20.
FIELD-SYMBOLS: <line> TYPE any.

CHECK it_table IS NOT INITIAL.

lr_doi
= ir_document.
lr_doi
->get_spreadsheet_interface( IMPORTING
sheet_interface
= lr_xls ).

CHECK lr_xls IS BOUND.
lr_doi
->get_document_handle( "EXPORTING NO_FLUSH = 'X'
IMPORTING handle = go_doc ).
GET PROPERTY OF go_doc-obj 'Application' = go_apl NO FLUSH"Get an Application object
* Calculate position of the named range
GET PROPERTY OF go_apl 'Range' = go_range
NO FLUSH
EXPORTING #1 = iv_rangename.
CALL METHOD OF go_apl 'GoTo' NO FLUSH  "
EXPORTING
#1    
= iv_rangename.
"Clear the range
GET PROPERTY OF go_range 'Cells' = go_names  "Get the first cell
NO FLUSH                                   "of the named range
EXPORTING
#1
= 1
#2
= 1.

GET PROPERTY OF go_names 'Address' = lv_address   "get its address
EXPORTING
#1
= 'True'              "absolute row address
#2
= 'True'              "absolute column address
#3
= -4150.              "RC format
CHECK lv_address IS NOT INITIAL.
SHIFT lv_address."Remove letter 'R'
SPLIT lv_address AT 'C' INTO lv_cur_row lv_cur_column.

* Calculate if some lines should be added
lv_lines
= lines( it_table ) - 1.
IF lv_lines > 0. "If we have some rows to add
*  Add number of table lines without one
lv_lines
= lv_lines + lv_cur_row - 1.

*  Get the right bottom cell of desired region
GET PROPERTY OF go_apl 'Rows' = go_br_cell
NO FLUSH
EXPORTING
#1
= lv_lines.

*  Calculate the left top cell of desired region
GET PROPERTY OF go_apl 'Rows' = go_lt_cell
NO FLUSH
EXPORTING
#1
= lv_cur_row.

CALL METHOD OF go_lt_cell 'Copy' NO FLUSH. "
*  Here is a range between left top and bottom right cells
GET PROPERTY OF go_apl 'Range' = go_range
NO FLUSH
EXPORTING
#1
= go_lt_cell
#2
= go_br_cell.

*  Insert correspondent lines
CALL METHOD OF go_range 'Insert' "
NO FLUSH
EXPORTING
#1      
= -4121
#2      
= '0'.
SET PROPERTY OF go_apl 'CutCopyMode' = 'False' NO FLUSH.
ENDIF.
GET PROPERTY OF go_apl 'Names' = go_names NO FLUSH.
CONCATENATE '=R' lv_cur_row 'C' lv_cur_column INTO lv_address.

GET TIME.
CONCATENATE iv_rangename sy-timlo
INTO lv_new_range.
CALL METHOD OF go_names 'Add'  "Create a new technical named range
NO FLUSH
EXPORTING
#1      
= lv_new_range    "generated name
#2      
= lv_address      "go_range        "For specified range
#3      
= 'False'.         "User will not see this name
*  Remove an "old" named range
GET PROPERTY OF go_names 'Item' = go_names NO FLUSH "Get named range
EXPORTING
#1
= iv_rangename.
CALL METHOD OF go_names 'Delete'. "Remove named range

CALL FUNCTION 'DP_GET_FIELDS_FROM_TABLE'
TABLES
data             = it_table
fields           = lt_fields
EXCEPTIONS
dp_invalid_table
= 1
OTHERS           = 2.

CALL METHOD lr_xls->insert_one_table
EXPORTING
data_table  
= it_table
fields_table
= lt_fields
rangename   
= lv_new_range
wholetable  
= '1'.

FREE OBJECT: go_selection,
go_names
,
go_apl
,
go_doc
-obj,
go_range
,
go_br_cell
,
go_lt_cell
,
go_activesheet
.
ENDMETHOD.

METHOD fill_value_by_range_name.
DATA: lr_doi TYPE REF TO i_oi_document_proxy,
lr_xls
TYPE REF TO i_oi_spreadsheet,
lv_new_range
TYPE char80,
lv_oldval   
TYPE text452,
lv_newval   
TYPE text452.
FIELD-SYMBOLS: <line> TYPE any.

*  IF is_field IS NOT INITIAL.
*    add_field_value( is_field = is_field
*                     iv_value = iv_new_value
*                     iv_conct = iv_concatenate ).
*    RETURN.
*  ENDIF.

lr_doi
= ir_document.
lr_doi
->get_spreadsheet_interface( IMPORTING
sheet_interface
= lr_xls ).

CHECK lr_xls IS BOUND.
lr_doi
->get_document_handle( "EXPORTING NO_FLUSH = 'X'
IMPORTING handle = go_doc ).
GET PROPERTY OF go_doc-obj 'Application' = go_apl NO FLUSH.
GET PROPERTY OF go_apl 'Range' = go_range
NO FLUSH
EXPORTING
#1
= iv_range_name .
IF iv_concatenate = 'X'.
lv_newval
= iv_new_value.
GET PROPERTY OF go_range 'Value' = lv_oldval.
IF lv_oldval IS NOT INITIAL.
CONCATENATE lv_oldval lv_newval
INTO
lv_oldval
SEPARATED BY space.
ELSE.
lv_oldval
= lv_newval.
ENDIF.

SET PROPERTY OF go_range 'Value' = lv_oldval.
ELSE.
SET PROPERTY OF go_range 'Value' = iv_new_value.
ENDIF.

FREE OBJECT:
go_range
,
go_apl
,
go_doc
-obj.
ENDMETHOD.

method GET_NAMES_FROM_DOI.
DATA: lr_form   TYPE REF TO i_oi_form,
lr_xls   
TYPE REF TO i_oi_spreadsheet,
lr_word  
TYPE REF TO I_OI_WORD_PROCESSOR_DOCUMENT.
*        lt_fields TYPE soi_form_list.
FIELD-SYMBOLS: <field> TYPE LINE OF soi_form_list,
<name> 
LIKE LINE OF rt_names.

CHECK ir_doi IS BOUND.
*  Get form interface (common interface)
ir_doi
->get_form_interface( IMPORTING f_interface = lr_form ).
*  Fill names for common interface
get_form_fields
( EXPORTING ir_form = lr_form
CHANGING ct_names = rt_names ).
*  Get spreadsheet interface
ir_doi
->get_spreadsheet_interface( IMPORTING sheet_interface = lr_xls ).
*  Fill names for Excel document
get_xls_fields
( EXPORTING ir_xls   = lr_xls
CHANGING  ct_names = rt_names ).
*  Get wordprocessor interface
*  ir_doi->get_wordprocessor_interface( IMPORTING wp_interface = lr_word ).
get_word_bookmarks
( EXPORTING ir_doi  = ir_doi
CHANGING  ct_names = rt_names ).

endmethod.

method OLE_FLUSH.
CALL FUNCTION 'FLUSH'
EXCEPTIONS
cntl_system_error
= 1
cntl_error       
= 2
OTHERS            = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
endmethod.

METHOD put_data_by_intf_into_names.
DATA: lt_names      TYPE zhr_namedescr_itab,
lr_typedescr 
TYPE REF TO cl_abap_typedescr,
lr_tabledescr
TYPE REF TO cl_abap_tabledescr,
lr_linedescr 
TYPE REF TO cl_abap_typedescr,
lt_fields    
TYPE TABLE OF string,
ls_field     
type LINE OF zhr_namedescr_itab.

FIELD-SYMBOLS: <name>  LIKE LINE OF lt_names,
<field>
TYPE string,
<any1> 
TYPE any,
<any2> 
TYPE any.
lt_names
= get_names_from_doi( ir_doi ).
CHECK lt_names IS NOT INITIAL.
initialize_field_to_update
( ).
LOOP AT lt_names ASSIGNING <name>
WHERE kind <> 'FLD'.
CLEAR lt_fields.
READ TABLE lt_names
with key kind = 'FLD'
name
= <name>-name
INTO
ls_field
.
IF sy-subrc <> 0.
clear ls_field.
ENDIF.
*    Check if such field exists in interface
ASSIGN COMPONENT <name>-name OF STRUCTURE is_interface TO <any1>.
IF sy-subrc = 0.
APPEND INITIAL LINE TO lt_fields ASSIGNING <field>.
<field>
= <name>-name.
ELSE.
*  Get named range's name for ex. TAB1_1_3_SOMEFIELD
*  And split it into table: TAB1/ 1/ 3/ SOMEFIELD
SPLIT <name>-name AT '_' INTO TABLE lt_fields.
ENDIF.
*  So the first line of this table should be a field of the interface is_interface
READ TABLE lt_fields ASSIGNING <field> INDEX 1.
CHECK <field> is ASSIGNED.
ASSIGN COMPONENT <field> OF STRUCTURE is_interface TO <any1>.
CHECK sy-subrc = 0.
lr_typedescr
= cl_abap_typedescr=>describe_by_data( <any1> ).
DELETE lt_fields INDEX 1.      "Remove structure/table/element name
CASE lr_typedescr->kind.
WHEN cl_abap_typedescr=>kind_elem. "Simple field
IF <name>-kind = 'RNGE'. "Excel Range name
fill_value_by_range_name
( iv_range_name = <name>-name
ir_document  
= ir_doi
is_field     
= ls_field
iv_new_value 
= <any1> ).
ELSEIF <name>-kind = 'BKMRK'"Word bookmark
fill_value_by_bookmark
( io_bookmark  = <name>-ole_obj
iv_new_value
= <any1> ).
ENDIF.

WHEN cl_abap_typedescr=>kind_struct.
IF <name>-kind = 'RNGE'. "Excel Range name
put_the_structure
( ir_doi    = ir_doi
it_fields
= lt_fields
is_source
= <any1>
iv_full_name
= <name>-name ).
ELSEIF <name>-kind = 'BKMRK'"Word bookmark
put_str_field_int_bkmrk
( io_bookmark = <name>-ole_obj
it_fields  
= lt_fields
is_source  
= <any1> ).
ENDIF.

WHEN cl_abap_typedescr=>kind_table.
IF <name>-kind = 'RNGE'. "Excel Range name
put_the_table
( ir_doi    = ir_doi
it_fields
= lt_fields
it_source
= <any1>
iv_full_name
= <name>-name ).
ELSEIF <name>-kind = 'WRDTAB'"Word table
put_table_into_bkmrk
( ir_doi      = ir_doi          "Reference to a document proxy
it_fields  
= lt_fields       "Desired fields from table
it_source  
= <any1>          "A table to transfer into a word table
iv_tab_indx
= <name>-value ). "Table index
ENDIF.
WHEN OTHERS.
ENDCASE.
CLEAR lt_fields.
ENDLOOP.

update_fields
( ir_doi    = ir_doi
it_fields
= lt_names ).
ENDMETHOD.

METHOD save_doi.
DATA: lv_filepath TYPE char255,
lv_sapdir  
TYPE string.
CHECK ir_doi IS BOUND.
IF iv_filepath IS NOT INITIAL.
lv_filepath
= iv_filepath.
ELSE.
cl_gui_frontend_services
=>get_sapgui_workdir( CHANGING sapworkdir lv_sapdir
EXCEPTIONS OTHERS = 4 ).
CALL FUNCTION 'FLUSH'
EXCEPTIONS
OTHERS = 0.

*    CHECK sy-subrc = 0.
IF lv_sapdir IS INITIAL OR sy-subrc <> 0.
cl_gui_frontend_services
=>get_desktop_directory(
CHANGING desktop_directory lv_sapdir ).
*      lv_sapdir = 'C:'.
CALL FUNCTION 'FLUSH'
EXCEPTIONS
OTHERS = 0.
ENDIF.
GET TIME.
ir_doi
->get_document_type( IMPORTING document_type = lv_filepath ).
IF lv_filepath(5) = 'Excel'.
lv_filepath
= lv_sapdir && '\' && sy-uname && sy-datum && sy-timlo && '.xls'.
ELSE.
lv_filepath
= lv_sapdir && '\' && sy-uname && sy-datum && sy-timlo && '.doc'.
ENDIF.
ENDIF.
CHECK lv_filepath IS NOT INITIAL.
ir_doi
->save_as( file_name = lv_filepath ).
rv_filepath
= lv_filepath.
CALL FUNCTION 'FLUSH'
EXCEPTIONS
OTHERS = 0.

ENDMETHOD.

METHOD open_document.
CHECK iv_filepath IS NOT INITIAL.
cl_gui_frontend_services
=>execute(
document 
= iv_filepath
maximized
= 'X' ).
ENDMETHOD.

METHOD get_pages.
DATA: lv_hanler TYPE cntl_handle.
ir_doi
->get_document_handle( EXPORTING no_flush = 'X'
IMPORTING handle   = lv_hanler ).
GET PROPERTY OF lv_hanler-obj 'ActiveSheet' = go_activesheet NO FLUSH.
GET PROPERTY OF go_activesheet 'PageSetup' = go_apl NO FLUSH.
GET PROPERTY OF go_apl 'Pages' = go_range NO FLUSH.
GET PROPERTY OF go_range 'Count' = rv_result.
FREE OBJECT: go_range, go_apl, go_activesheet.
ADD 1 TO rv_result.
ENDMETHOD.

 

METHOD add_field_value.
DATA: ls_field TYPE LINE OF soi_form_list,
lv_field
TYPE char200.
FIELD-SYMBOLS: <field> TYPE LINE OF soi_form_list,
<clike>
TYPE c.

MOVE-CORRESPONDING is_field TO ls_field.
ls_field
-type   = 'T'.
ls_field
-number = '1'.
ls_field
-code   = '0'.
IF iv_conct IS INITIAL.
write iv_value to ls_field-value LEFT-JUSTIFIED.
*    ls_field-value = iv_value.
ELSE.
WRITE iv_value to lv_field LEFT-JUSTIFIED.
*    lv_field = iv_value.
CONCATENATE ls_field-value lv_field INTO ls_field-value SEPARATED BY space.
*    TRY .
*        ASSIGN iv_value TO <clike> CASTING.
*        CONCATENATE ls_field-value <clike> INTO ls_field-value SEPARATED BY space.
*      CATCH cx_sy_assign_cast_illegal_cast .
*        WRITE iv_value TO lv_field LEFT-JUSTIFIED.
*        CONDENSE lv_field.
*        CONCATENATE ls_field-value lv_field INTO ls_field-value SEPARATED BY space.
*    ENDTRY.

ENDIF.
APPEND ls_field TO fields_to_update.
*  MODIFY TABLE fields_to_update FROM ls_field.
ENDMETHOD.

METHOD initialize_field_to_update.
CLEAR fields_to_update.
ENDMETHOD.

METHOD update_fields.
DATA: lr_form TYPE REF TO i_oi_form,
lt_fields
TYPE soi_form_list.
FIELD-SYMBOLS: <field>  TYPE LINE OF soi_form_list,
<update>
LIKE LINE OF fields_to_update.
CHECK fields_to_update IS NOT INITIAL.
*  ir_doi->get_form_interface( EXPORTING no_flush = 'X'
*                              IMPORTING f_interface = lr_form ).
*  lr_form->synchronize_fields( no_flush = 'X' ).
*  lr_form->get_data( IMPORTING fields = lt_fields ).
*  LOOP AT lt_fields ASSIGNING <field>.
*    READ TABLE fields_to_update WITH KEY name = <field>-name ASSIGNING <update>.
*    IF sy-subrc <> 0.
*      APPEND INITIAL LINE TO fields_to_update ASSIGNING <update>.
*      MOVE-CORRESPONDING <field> TO <update>.
*      <update>-type   = 'T'.
*      <update>-number = '1'.
*      <update>-code   = '0'.
*    ENDIF.
*  ENDLOOP.

ir_doi
->get_form_interface( EXPORTING no_flush = 'X'
IMPORTING f_interface = lr_form ).
lr_form
->set_data( fields = fields_to_update
CLEAR = ' ' ).
*  lr_form->synchronize_fields( ).
CLEAR fields_to_update.
ENDMETHOD.

METHOD hide_doi.
DATA: lv_hanler TYPE cntl_handle.
ir_doi
->get_document_handle( EXPORTING no_flush = 'X'
IMPORTING handle   = lv_hanler ).
GET PROPERTY OF lv_hanler-obj 'Application' = go_apl NO FLUSH.
SET PROPERTY OF go_apl 'Visible' = 'False' NO FLUSH.
SET PROPERTY OF go_apl 'DisplayAlerts' = 'False'.
FREE OBJECT go_apl.
ENDMETHOD.

METHOD fill_value_by_bookmark.
GET PROPERTY OF io_bookmark 'Range' = go_range NO FLUSH.
SET PROPERTY OF go_range 'Text' = iv_new_value.

FREE OBJECT: go_range.
ENDMETHOD.

METHOD get_word_tables.
DATA: lv_count TYPE i,
lo_table
TYPE obj_record.
FIELD-SYMBOLS: <table> LIKE LINE OF rt_tables.
GET PROPERTY OF io_document 'Tables' = go_activesheet NO FLUSH.
GET PROPERTY OF go_activesheet 'Count' = lv_count.
DO lv_count TIMES.
APPEND INITIAL LINE TO rt_tables ASSIGNING <table>.
<table>
-indx = sy-tabix.
GET PROPERTY OF go_activesheet 'Item' = lo_table
EXPORTING
#1
= sy-index.
CHECK sy-subrc = 0.
<table>
-ole_obj = lo_table.
ENDDO.
FREE OBJECT: lo_table,
go_activesheet
.
ENDMETHOD.

METHOD insert_tab_into_word_tab.
DATA: lr_str_descr  TYPE REF TO cl_abap_structdescr,
lt_str_fields
TYPE ddfields,
lt_columns   
TYPE soi_colnames_table,
lv_doctab_no 
TYPE i.
FIELD-SYMBOLS: <field> TYPE dfies,
<line> 
TYPE any,
<table_line>
TYPE any.
READ TABLE it_table ASSIGNING <table_line> INDEX 1.
CHECK <table_line> IS ASSIGNED.
lr_str_descr ?= cl_abap_structdescr
=>describe_by_data( <table_line> ).
CHECK lr_str_descr IS BOUND.
lt_str_fields
= lr_str_descr->get_ddic_field_list( ). "Here can be dump due to exceptions section omitted
LOOP AT lt_str_fields ASSIGNING <field>.
APPEND INITIAL LINE TO lt_columns ASSIGNING <line>.
<line>
= <field>-fieldname.
ENDLOOP.
lv_doctab_no
= iv_tab_indx.
ir_word
->insert_table2(
data_table
= it_table
info_col_table 
= lt_columns
lowerbound     
= "Whole table
upperbound     
= " whole table
doctable_number
= lv_doctab_no
clearoption    
= "Clear content
startrow       
= "From the first row
varsize        
= 'X' ). "Any rows number
ENDMETHOD.

method PUT_STR_FIELD_INT_BKMRK.
*  This method will put just one field of a structure
*  into the bookmark
FIELD-SYMBOLS: <field>  type any,
<source>
type any.
LOOP AT it_fields ASSIGNING <field>.
ASSIGN COMPONENT <field> OF STRUCTURE is_source to <source>.
IF <source> is ASSIGNED.
exit. "Here we've found soume field from a list of fields at the source structure
ENDIF.
ENDLOOP.
CHECK <source> is ASSIGNED.
fill_value_by_bookmark
( io_bookmark  = io_bookmark
iv_new_value
= <source> ).
endmethod.

METHOD put_table_into_bkmrk.
*  This method should create a local version of the table if some fields specified
*  Otherwise it should put a whole table into the document
DATA: lr_str_descr TYPE REF TO cl_abap_structdescr,
lt_str_fields
TYPE ddfields,
lv_index     
TYPE i,
lt_target_struct
TYPE zhr_typedescr_itab,
ld_target       
TYPE REF TO data,
lr_word         
TYPE REF TO i_oi_word_processor_document.
FIELD-SYMBOLS: <table_line> TYPE any,
<field>     
TYPE any,
<any>       
TYPE any,
<any1>      
TYPE any,
<any_tab>   
TYPE STANDARD TABLE,
<str_field> 
TYPE dfies,
<target_str>
LIKE LINE OF lt_target_struct.

READ TABLE it_source ASSIGNING <table_line> INDEX 1.
CHECK <table_line> IS ASSIGNED. "No sense to continue if no data to put

ir_doi
->get_wordprocessor_interface( IMPORTING wp_interface = lr_word ). "Get word interface
CHECK lr_word IS BOUND. "No sense to continue without the Word

IF it_fields IS INITIAL. "No fields specified
insert_tab_into_word_tab
( it_table = it_source
ir_word 
= lr_word
iv_tab_indx
= iv_tab_indx ).
ELSE.
*  Create fields list
lr_str_descr ?= cl_abap_structdescr
=>describe_by_data( <table_line> ).
CHECK lr_str_descr IS BOUND.
lt_str_fields
= lr_str_descr->get_ddic_field_list( ). "Here can be dump due to exceptions section omitted
LOOP AT it_fields ASSIGNING <field>.
CHECK <field> IS NOT INITIAL.
READ TABLE lt_str_fields WITH KEY fieldname = <field> ASSIGNING <str_field>.
IF sy-subrc <> 0.
TRY.
MOVE <field> TO lv_index.
CATCH cx_sy_conversion_no_number .
CONTINUE.
ENDTRY.
READ TABLE lt_str_fields ASSIGNING <str_field> INDEX lv_index.
CHECK sy-subrc = 0.
ENDIF.
APPEND INITIAL LINE TO lt_target_struct ASSIGNING <target_str>.
<target_str>
-field_name = <str_field>-fieldname.
CONCATENATE <str_field>-tabname '-' <str_field>-fieldname
INTO <target_str>-field_type.

ENDLOOP.
ld_target
= create_dyn_table( lt_target_struct ).
CHECK ld_target IS BOUND.
ASSIGN ld_target->* TO <any_tab>.
CHECK sy-subrc = 0.
LOOP AT it_source ASSIGNING <any>.
APPEND INITIAL LINE TO <any_tab> ASSIGNING <any1>.
MOVE-CORRESPONDING <any> TO <any1>.
ENDLOOP.
insert_tab_into_word_tab
( it_table = <any_tab>
ir_word 
= lr_word
iv_tab_indx
= iv_tab_indx ).
ENDIF.
ENDMETHOD.

method PUT_THE_STRUCTURE.
*  This method will put just one field of a structure
*  into the named range
FIELD-SYMBOLS: <field>  type any,
<source>
type any.
LOOP AT it_fields ASSIGNING <field>.
ASSIGN COMPONENT <field> OF STRUCTURE is_source to <source>.
IF <source> is ASSIGNED.
exit. "Here we've found some field from a list of fields at the source structure
ENDIF.
ENDLOOP.
CHECK <source> is ASSIGNED.
fill_value_by_range_name
( iv_range_name = iv_full_name
ir_document  
= ir_doi
iv_new_value 
= <source> ).
endmethod.

METHOD put_the_table.
*  This method should create a local version of the table if some fields specified
*  Otherwise it should put a whole table into the document
DATA: lr_str_descr TYPE REF TO cl_abap_structdescr,
lt_str_fields
TYPE ddfields,
lv_index     
TYPE i,
lt_target_struct
TYPE zhr_typedescr_itab,
ld_target       
TYPE REF TO data,
lt_fcat         
TYPE lvc_t_fcat.
FIELD-SYMBOLS: <table_line> TYPE any,
<field>     
TYPE any,
<any>       
TYPE any,
<any1>      
TYPE any,
<any_tab>   
TYPE STANDARD TABLE,
<str_field> 
TYPE dfies,
<target_str>
LIKE LINE OF lt_target_struct,
<fline>     
TYPE LINE OF lvc_t_fcat,
<component> 
TYPE abap_compdescr.

READ TABLE it_source ASSIGNING <table_line> INDEX 1.
CHECK <table_line> IS ASSIGNED. "No sense to continue if no data to put

IF it_fields IS INITIAL. "No fields specified
insert_table_into_named_range
( ir_document = ir_doi
it_table   
= it_source
iv_rangename
= iv_full_name ).
ELSE.
*  Create fields list
lr_str_descr ?= cl_abap_structdescr
=>describe_by_data( <table_line> ).
CHECK lr_str_descr IS BOUND.
LOOP AT it_fields ASSIGNING <field>.
CHECK <field> IS NOT INITIAL.
READ TABLE lr_str_descr->components WITH KEY name = <field> ASSIGNING <component>.
IF sy-subrc <> 0.
TRY.
MOVE <field> TO lv_index.
CATCH cx_sy_conversion_no_number .
CONTINUE.
ENDTRY.
READ TABLE lr_str_descr->components ASSIGNING <component> INDEX lv_index.
CHECK sy-subrc = 0.
ENDIF.
APPEND INITIAL LINE TO lt_fcat ASSIGNING <fline>.
<fline>
-fieldname = <component>-name.
<fline>
-datatype  = <component>-type_kind.
<fline>
-inttype   = <component>-type_kind.
<fline>
-intlen    = <component>-length.
<fline>
-decimals  = <component>-decimals.
ENDLOOP.
cl_alv_table_create
=>create_dynamic_table(
EXPORTING
it_fieldcatalog 
= lt_fcat
i_length_in_byte
= 'X'
IMPORTING
ep_table
= ld_target ).
CHECK ld_target IS BOUND.
ASSIGN ld_target->* TO <any_tab>.
CHECK sy-subrc = 0.
LOOP AT it_source ASSIGNING <any>.
APPEND INITIAL LINE TO <any_tab> ASSIGNING <any1>.
MOVE-CORRESPONDING <any> TO <any1>.
ENDLOOP.
insert_table_into_named_range
( ir_document = ir_doi
it_table   
= <any_tab>
iv_rangename
= iv_full_name ).
ENDIF.
ENDMETHOD.

method GET_FORM_FIELDS.
data: lt_fields TYPE soi_form_list.
FIELD-SYMBOLS: <field> type line of SOI_FORM_LIST,
<name> 
like LINE OF ct_names.

CHECK ir_form IS BOUND.
ir_form
->get_form_fields( IMPORTING fields = lt_fields ).
LOOP AT lt_fields ASSIGNING <field>.
APPEND INITIAL LINE TO ct_names ASSIGNING <name>.
MOVE-CORRESPONDING <field> to <name>. "Fill name and value
<name>
-kind = 'FLD'.                  "Domain value could be a reason of dumps if other values ranges determined

ENDLOOP.
endmethod.

METHOD get_word_bookmarks.
* Here's nothing to do actually due to no tools to get bookmarks from a word interface
* A Document ole reference could be used to get this info by Bookmarks collection

DATA: lv_count TYPE i,
lv_name 
TYPE text128,
lt_word_tables
TYPE zhr_wordtable_itab,
lv_cur_indx   
TYPE i.
FIELD-SYMBOLS: <name> LIKE LINE OF ct_names,
<wrdtab>
LIKE LINE OF lt_word_tables.
ir_doi
->get_document_handle( EXPORTING no_flush = 'X'
IMPORTING handle = go_doc ).
GET PROPERTY OF go_doc-obj 'Bookmarks' = go_names NO FLUSH.
GET PROPERTY OF go_names 'Count' = lv_count.
DO lv_count TIMES.
GET PROPERTY OF go_names 'Item' = go_range
NO FLUSH
EXPORTING
#1
= sy-index.
APPEND INITIAL LINE TO ct_names ASSIGNING <name>.
GET PROPERTY OF go_range 'Name' = <name>-name.
<name>
-kind = 'BKMRK'.   "Word bookmark
<name>
-ole_obj = go_range.
ENDDO.
FREE OBJECT: go_selection, go_br_cell, go_lt_cell, go_range, go_names.
CLEAR lv_count.
GET PROPERTY OF go_doc-obj 'Tables' = go_names NO FLUSH.
GET PROPERTY OF go_names 'Count' = lv_count.
DO lv_count TIMES.
*    ActiveDocument.Tables(i).Range.Bookmarks(1) = TableName
lv_cur_indx
= sy-index.
GET PROPERTY OF go_names 'Item' = go_selection
NO FLUSH
EXPORTING
#1
= lv_cur_indx.
GET PROPERTY OF go_selection 'Range' = go_range NO FLUSH.
GET PROPERTY OF go_range 'Bookmarks' = go_br_cell NO FLUSH.
GET PROPERTY OF go_br_cell 'Item' = go_lt_cell
NO FLUSH
EXPORTING
#1
= 1.
GET PROPERTY OF go_lt_cell 'Name' = lv_name.
CHECK sy-subrc = 0"Bookmark for table exists
APPEND INITIAL LINE TO ct_names ASSIGNING <name>.
<name>
-name = lv_name.
<name>
-kind = 'WRDTAB'.   "Word bookmark
<name>
-value = lv_cur_indx.
ENDDO.
*  FREE OBJECT: go_selection, go_br_cell, go_lt_cell, go_range, go_names.
FREE OBJECT: go_selection,
go_names
,
go_apl
,
go_doc
-obj,
go_range
,
go_br_cell
,
go_lt_cell
,
go_activesheet
.
ENDMETHOD.

method GET_XLS_FIELDS.
DATA: lt_ranges TYPE soi_range_list.
FIELD-SYMBOLS: <field> TYPE LINE OF soi_range_list,
<name> 
LIKE LINE OF ct_names.

CHECK ir_xls IS BOUND.
ir_xls
->get_ranges_names( IMPORTING ranges = lt_ranges ).
LOOP AT lt_ranges ASSIGNING <field>.
APPEND INITIAL LINE TO ct_names ASSIGNING <name>.
MOVE-CORRESPONDING <field> TO <name>. "Fill name
<name>
-kind = 'RNGE'.                 "Domain value could be a reason of dumps if other values ranges determined
*   Will not fill object value due to interface bounds
ENDLOOP.
endmethod.

 

Also you’ll need to create types:

ZHR_NAMEDESCR_ITAB (table type of ZHR_NAMEDESCR_WA)
ZHR_NAMEDESCR_WA (structure):
NAME                  CHAR128

KIND                     CHAR6

VALUE                  CHAR255

OLE_OBJ             OBJ_RECORD

ZHR_TYPEDESCR_ITAB (table type of ZHR_TYPEDESCR_WA)

ZHR_TYPEDESCR_WA (structure):

FIELD_NAME                     CHAR40

FIELD_TYPE                       CHAR100

ZHR_WORDTABLE_ITAB (table type of ZHR_WORDTABLE_WA)

ZHR_WORDTABLE_WA (structure):

INDX                     INT4

OLE_OBJ             OBJ_RECORD

Displaying an ALV Grid in Popup Screen with Custom Buttons

$
0
0

In some cases, we might came across a requirement for displaying an ALV Grid in popup screen where we need to select few records and then perform certain function based on selected data. For choosing which function we need to perform, we required custom buttons on the Popup screen. For achieving this requirement, I have created a factory class (ZCL_ALV_POPUP), for using it following things need to be remember:

 

FACTORY Method:

  • It returns the instance of the popup class.
  • For data to be displayed in ALV grid we need to pass an internal table in IT_DATA parameter.
  • For adding the custom buttons we can pass the PF-Status and its program name and whenever custom button is clicked, it raises an event button_click by exporting function code of button and internal table for selected data.
  • For multiple selection of data in ALV, we need to pass IV_MULTI_SELECT as abap_true else abap_false for single selection.

DISPLAY Method:

  • For displaying the popup we need to need to pass the coordinates. 

 

 

CLASS DEFINITION

 

class ZCL_ALV_POPUP definition
  public
  final
  create private .

public section.

  constants MC_FUNC_REFRESH type SALV_DE_FUNCTION value '&REFRS'. "#EC NOTEXT
  constants MC_FUNC_SELECTALL type SALV_DE_FUNCTION value '&SELECT'. "#EC NOTEXT
  constants MC_FUNC_DESELECTALL type SALV_DE_FUNCTION value '&DESELECT'. "#EC NOTEXT

  events BUTTON_CLICK
    exporting
      value(EV_SALV_FUNCTION) type SALV_DE_FUNCTION
      value(ET_SELECTED_DATA) type TABLE .

  type-pools ABAP .


  methods CONSTRUCTOR
    importing
      !IT_DATA type TABLE
      !IV_PROG_NAME type SYREPID optional
      !IV_PF_STATUS type SYPFKEY optional
      !IV_MULTI_SELECT type ABAP_BOOL optional .


  class-methods FACTORY
    importing
      !IT_DATA type TABLE
      !IV_PROG_NAME type SYREPID optional
      !IV_PF_STATUS type SYPFKEY optional
      !IV_MULTI_SELECT type ABAP_BOOL default ABAP_TRUE
    returning
      value(R_ALV_POPUP) type ref to ZCL_ALV_POPUP .


  methods DISPLAY
    importing
      !IV_START_COLUMN type I
      !IV_START_LINE type I
      !IV_END_COLUMN type I optional
      !IV_END_LINE type I optional .


  PROTECTED SECTION.

 

 

 


  PRIVATE SECTION.

 

 

    DATA mr_alv_data TYPE REF TO data .
    DATA mr_table_type TYPE REF TO cl_abap_tabledescr .
    DATA mr_alv TYPE REF TO cl_salv_table .
    DATA mv_multi_select TYPE abap_bool .
    DATA mv_prog_name TYPE syrepid .
    DATA mv_pf_status TYPE sypfkey .

 

    METHODS assign_alv_data
      IMPORTING
        !it_data TYPE table
      EXPORTING
        !er_data TYPE REF TO data
        !er_table_type TYPE REF TO cl_abap_tabledescr .

 


    METHODS get_selected_data
      EXPORTING
        value(et_data) TYPE table .

 


    METHODS select_all
      IMPORTING
        !iv_value TYPE abap_bool DEFAULT abap_true .

 


    METHODS on_link_click
      FOR EVENT link_click OF cl_salv_events_table
      IMPORTING
        !row
        !column .

 


    METHODS on_user_command
      FOR EVENT added_function OF cl_salv_events
      IMPORTING
        !e_salv_function .


ENDCLASS.

 

 

CLASS IMPLEMENTATION

 

   CLASS ZCL_ALV_POPUP IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ASSIGN_ALV_DATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA                        TYPE        TABLE
* | [<---] ER_DATA                        TYPE REF TO DATA
* | [<---] ER_TABLE_TYPE                  TYPE REF TO CL_ABAP_TABLEDESCR
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD assign_alv_data.

    DATA:
      lr_tdata TYPE REF TO data,
      lr_sdata TYPE REF TO data,
      lr_type TYPE REF TO cl_abap_typedescr,
      lr_table TYPE REF TO cl_abap_tabledescr,
      lr_struct TYPE REF TO cl_abap_structdescr,
      lt_field TYPE cl_abap_structdescr=>component_table,
      lt_final TYPE cl_abap_structdescr=>component_table,
      ls_final TYPE LINE OF cl_abap_structdescr=>component_table.

    FIELD-SYMBOLS: <fs> TYPE any,
                   <fs_t_data> TYPE STANDARD TABLE,
                   <fs_s_data> TYPE any.

    CLEAR: er_data, er_table_type.

    ASSIGN it_data TO <fs>.
    GET REFERENCE OF <fs> INTO lr_tdata.

    cl_abap_tabledescr=>describe_by_data_ref(
      EXPORTING
        p_data_ref           = lr_tdata
      RECEIVING
        p_descr_ref          = lr_type
      EXCEPTIONS
        reference_is_initial = 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.

    er_table_type ?= lr_type.
    CHECK er_table_type IS BOUND.

    lr_struct ?= er_table_type->get_table_line_type( ).
    CHECK lr_struct IS BOUND.

    lt_field = lr_struct->get_components( ).

    CLEAR: ls_final, lr_struct, lr_table.
    ls_final-name = 'CHOOSE'.
    ls_final-type ?= cl_abap_datadescr=>describe_by_name( 'XFELD' ).
    APPEND ls_final TO lt_final.
    APPEND LINES OF lt_field TO lt_final.

    lr_struct = cl_abap_structdescr=>create( lt_final ).
    lr_table  = cl_abap_tabledescr=>create( lr_struct ).

    CREATE DATA me->mr_alv_data TYPE HANDLE lr_table.
    CREATE DATA lr_sdata TYPE HANDLE lr_struct.

    ASSIGN me->mr_alv_data->* TO <fs_t_data>.
    ASSIGN lr_sdata->* TO <fs_s_data>.

    LOOP AT it_data ASSIGNING <fs>.
      CLEAR <fs_s_data>.
      MOVE-CORRESPONDING <fs> TO <fs_s_data>.
      APPEND <fs_s_data> TO <fs_t_data>.
    ENDLOOP.

    GET REFERENCE OF <fs_t_data> INTO er_data.

  ENDMETHOD.                    "ASSIGN_ALV_DATA


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_ALV_POPUP->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA                        TYPE        TABLE
* | [--->] IV_PROG_NAME                   TYPE        SYREPID(optional)
* | [--->] IV_PF_STATUS                   TYPE        SYPFKEY(optional)
* | [--->] IV_MULTI_SELECT                TYPE        ABAP_BOOL(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD constructor.

    CLEAR: me->mr_alv,
           me->mr_alv_data,
           me->mr_table_type,
           me->mv_pf_status,
           me->mv_prog_name,
           me->mv_multi_select.

    me->mv_pf_status    = iv_pf_status.
    me->mv_prog_name    = iv_prog_name.
    me->mv_multi_select = iv_multi_select.

    me->assign_alv_data(
      EXPORTING
        it_data       = it_data
      IMPORTING
        er_data       = me->mr_alv_data
        er_table_type = me->mr_table_type
             ).

  ENDMETHOD.                    "constructor


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_ALV_POPUP->DISPLAY
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_START_COLUMN                TYPE        I
* | [--->] IV_START_LINE                  TYPE        I
* | [--->] IV_END_COLUMN                  TYPE        I(optional)
* | [--->] IV_END_LINE                    TYPE        I(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD display.

    DATA:
      lr_functions  TYPE REF TO cl_salv_functions_list,
      lr_columns    TYPE REF TO cl_salv_columns,
      lr_column     TYPE REF TO cl_salv_column_table,
      lr_selections TYPE REF TO cl_salv_selections,
      lr_events     TYPE REF TO cl_salv_events_table.

    FIELD-SYMBOLS <fs_t_data> TYPE STANDARD TABLE.

    ASSIGN me->mr_alv_data->* TO <fs_t_data>.

    TRY.
        cl_salv_table=>factory(
          IMPORTING
            r_salv_table = me->mr_alv
          CHANGING
            t_table      = <fs_t_data> ).
      CATCH cx_salv_msg.                                "#EC NO_HANDLER
    ENDTRY.

    lr_functions = me->mr_alv->get_functions( ).
    lr_functions->set_all( if_salv_c_bool_sap=>true ).

    lr_columns = me->mr_alv->get_columns( ).
    lr_columns->set_optimize( if_salv_c_bool_sap=>true ).

    TRY.
        lr_column ?= lr_columns->get_column( 'CHOOSE' ).
        lr_column->set_cell_type( if_salv_c_cell_type=>checkbox_hotspot ).
        lr_column->set_short_text( 'Choose'(t01) ).
        lr_column->set_medium_text( 'Choose'(t01) ).
        lr_column->set_long_text( 'Choose'(t01) ).
      CATCH cx_salv_not_found.                          "#EC NO_HANDLER
    ENDTRY.

    lr_selections = me->mr_alv->get_selections( ).
    lr_selections->set_selection_mode( if_salv_c_selection_mode=>none ).

    IF me->mv_pf_status IS NOT INITIAL AND me->mv_prog_name IS NOT INITIAL.
      me->mr_alv->set_screen_status(
            pfstatus      = me->mv_pf_status
            report        = me->mv_prog_name
            set_functions = me->mr_alv->c_functions_all ).
    ENDIF.

    lr_events = me->mr_alv->get_event( ).

    SET HANDLER me->on_user_command FOR lr_events.
    SET HANDLER me->on_link_click   FOR lr_events.

    me->mr_alv->set_screen_popup(
      start_column = iv_start_column
      end_column   = iv_end_column
      start_line   = iv_start_line
      end_line     = iv_end_line ).

    me->mr_alv->display( ).

  ENDMETHOD.                    "display_popup


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_ALV_POPUP=>FACTORY
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_DATA                        TYPE        TABLE
* | [--->] IV_PROG_NAME                   TYPE        SYREPID(optional)
* | [--->] IV_PF_STATUS                   TYPE        SYPFKEY(optional)
* | [--->] IV_MULTI_SELECT                TYPE        ABAP_BOOL (default =ABAP_TRUE)
* | [<-()] R_ALV_POPUP                    TYPE REF TO ZCL_ALV_POPUP
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD factory.

    CLEAR r_alv_popup.

    CREATE OBJECT r_alv_popup
      EXPORTING
        it_data         = it_data
        iv_prog_name    = iv_prog_name
        iv_pf_status    = iv_pf_status
        iv_multi_select = iv_multi_select.

  ENDMETHOD.                    "factory


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->GET_SELECTED_DATA
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_DATA                        TYPE        TABLE
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD get_selected_data.

    DATA: lr_t_data TYPE REF TO data,
        lr_s_data TYPE REF TO data,
        lr_struct TYPE REF TO cl_abap_structdescr,
        lv_cnt    TYPE i.

    FIELD-SYMBOLS: <fs_t_tdata> TYPE STANDARD TABLE,
                   <fs_s_tdata> TYPE any,
                   <fs_t_fdata> TYPE STANDARD TABLE,
                   <fs_s_fdata> TYPE any,
                   <fs>         TYPE any,
                   <fs_tdata>   TYPE any,
                   <fs_fdata>   TYPE any.

    CLEAR et_data.

    lr_struct ?= me->mr_table_type->get_table_line_type( ).
    CHECK lr_struct IS BOUND.

    CREATE DATA lr_t_data TYPE HANDLE me->mr_table_type.
    CREATE DATA lr_s_data TYPE HANDLE lr_struct.
    ASSIGN lr_t_data->* TO <fs_t_fdata>.
    ASSIGN lr_s_data->* TO <fs_s_fdata>.
    ASSIGN me->mr_alv_data->* TO <fs_t_tdata>.

    LOOP AT <fs_t_tdata> ASSIGNING <fs_s_tdata>.
      IF <fs_s_tdata> IS ASSIGNED.
        ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_tdata> TO <fs> CASTING TYPE xfeld.
        IF <fs> IS ASSIGNED.
          IF <fs> = abap_true.
            CLEAR <fs_s_fdata>.
            DO.
              lv_cnt = sy-index + 1.

              ASSIGN COMPONENT lv_cnt OF STRUCTURE <fs_s_tdata> TO <fs_tdata>.
              IF sy-subrc <> 0.
                EXIT.
              ENDIF.
              ASSIGN COMPONENT sy-index OF STRUCTURE <fs_s_fdata> TO <fs_fdata>.
              IF <fs_tdata> IS ASSIGNED AND <fs_fdata> IS ASSIGNED.
                <fs_fdata> = <fs_tdata>.
              ENDIF.
            ENDDO.
            APPEND <fs_s_fdata> TO <fs_t_fdata>.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDLOOP.

    et_data = <fs_t_fdata>.

  ENDMETHOD.                    "GET_SELECTED_DATA


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ON_LINK_CLICK
* +-------------------------------------------------------------------------------------------------+
* | [--->] ROW                            LIKE
* | [--->] COLUMN                         LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD on_link_click.

    FIELD-SYMBOLS: <fs_t_data> TYPE STANDARD TABLE,
                   <fs_s_data> TYPE any,
                   <fs> TYPE any.

    CHECK mr_alv IS BOUND.

    ASSIGN me->mr_alv_data->* TO <fs_t_data>.
    READ TABLE <fs_t_data> ASSIGNING <fs_s_data> INDEX row.
    IF <fs_s_data> IS ASSIGNED.
      ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
      IF <fs> IS ASSIGNED.
        IF <fs> = abap_false.
          <fs> = abap_true.
        ELSE.
          <fs> = abap_false.
        ENDIF.
      ENDIF.
    ENDIF.
    IF mv_multi_select = abap_false.
      LOOP AT <fs_t_data> ASSIGNING <fs_s_data>.
        IF <fs_s_data> IS ASSIGNED AND sy-tabix <> row.
          ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
          IF <fs> IS ASSIGNED.
            <fs> = abap_false.
          ENDIF.
        ENDIF.
      ENDLOOP.
    ENDIF.

    mr_alv->refresh( ).

  ENDMETHOD.                    "on_link_click


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->ON_USER_COMMAND
* +-------------------------------------------------------------------------------------------------+
* | [--->] E_SALV_FUNCTION                LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD on_user_command.

    DATA lr_data TYPE REF TO data.
    FIELD-SYMBOLS <fs_data> TYPE STANDARD TABLE.

    CASE e_salv_function.
      WHEN mc_func_refresh OR mc_func_deselectall.
        me->select_all( iv_value = abap_false ).
      WHEN mc_func_selectall.
        me->select_all( iv_value = abap_true ).
      WHEN OTHERS.
        CREATE DATA lr_data TYPE HANDLE me->mr_table_type.
        ASSIGN lr_data->* TO <fs_data>.

        me->get_selected_data(
          IMPORTING
            et_data = <fs_data>
               ).

        RAISE EVENT button_click
              EXPORTING
                ev_salv_function = e_salv_function
                et_selected_data = <fs_data>.
    ENDCASE.

  ENDMETHOD.                    "on_user_command


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_ALV_POPUP->SELECT_ALL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_VALUE                       TYPE        ABAP_BOOL (default =ABAP_TRUE)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD select_all.

    FIELD-SYMBOLS: <fs_t_data> TYPE STANDARD TABLE,
                   <fs_s_data> TYPE any,
                   <fs> TYPE any.

    CHECK mr_alv IS BOUND.

    ASSIGN me->mr_alv_data->* TO <fs_t_data>.

    LOOP AT <fs_t_data> ASSIGNING <fs_s_data>.
      IF <fs_s_data> IS ASSIGNED.
        ASSIGN COMPONENT 'CHOOSE' OF STRUCTURE <fs_s_data> TO <fs> CASTING TYPE xfeld.
        IF <fs> IS ASSIGNED.
          <fs> = iv_value.
        ENDIF.
      ENDIF.
    ENDLOOP.

    mr_alv->refresh( ).

  ENDMETHOD.                    "select_all


ENDCLASS.

 

 

Posting a Goods Movement Document in IS-OIL

$
0
0

This blog illustrates the method to post goods movement in IS-OIL.

 

Almost every one of us have used “BAPI_GOODSMVT_CREATE” to post a material goods movement in SAP. But when we are working in IS-Oil material this BAPI does not work and we end up trying different ways to do the same.

 

Well SAP has another BAPI for this and I will try to post a 311 movement with the same. I hope this helps in other postings as well.

 

The BAPI is BAPI_GOODSMVT_CREATE_OIL.

 

Data Declaration :

 

     DATA : lw_item       TYPE bapioil2017_gm_itm_crte_01,
        lw_item_param
TYPE bapioil2017_gm_itm_crte_param,
        lw_header    
TYPE bapioil2017_gm_head_create,
        lw_doc_no    
TYPE mkpf-mblnr,
        lt_item      
TYPE TABLE OF bapioil2017_gm_itm_crte_01,
        lt_item_param
TYPE TABLE OF bapioil2017_gm_itm_crte_param,
        lt_return    
TYPE TABLE OF bapiret2.

 

Passing the Data.

 

Now most data passing will be similar to our standard way.

 

Material Document Header.

 

    lw_header-pstng_date = sy-datum.
    lw_header
-doc_date   = sy-datum.

 

Material Document Item.

 

  lw_item-material      = lw_g_odet-matnr.
        lw_item
-move_mat      = lw_g_odet-matnr.
        lw_item
-plant         = lw_tankm-plant.
        lw_item
-stge_loc      = lw_tankm-sloc.
        lw_item
-batch         = lw_oijnomi-charg_o.
        lw_item
-val_type      = lc_vatyp.
        lw_item
-move_plant    = lw_tankm-plant.
        lw_item
-move_stloc    = lc_vsloc.
        lw_item
-move_batch    = lw_oijnomi-charg_o.
        lw_item
-move_val_type = lc_vatyp.
        lw_item
-move_type     = '311'.

  lw_item-entry_qnt     = lw_tankm-tag_value.
        lw_item
-entry_uom     = lw_tankm-tag_uom.

 

Posting the Additional Quantities

 

Now this is the major difference between normal goods movement and IS-Oil goods movement.

 

In the declared lt_item_param there are two control parameters for posting items with additional quantities:

§  CALCULATEMISSING

§  USEDEFAULTPARAMETERS

 

There are QCI [Quantity Conversion Interface] parameters which are default specified in configuration if you want to use them you put the USEDEFAULTPARAMETERS parameter value as ‘X’.

 

Extract from SAP FM Documentation for understanding.

 

If the value you enter for the CALCULATEMISSING parameter differs from the default value, the system determines all all necessary units of measure for this posting item and calculates the missing quantities. Otherwise you must ensure that the system can access all quantities in all required units of measure through the interface.

 

We are going to provide values.

 

For some materials the Air Buoyancy indicator is also a parameter for conversion that can be received from MARC.

 

        SELECT SINGLE umrsl abfac FROM marc
                             
INTO (lw_item_param-conversiongroup,
                                   lw_item_param
-airbuoyancyconstant )
                           
WHERE matnr = lw_g_odet-matnr
                              
AND werks = lw_tankm-werks.

       
IF sy-subrc IS INITIAL.
         
IF lw_item_param-airbuoyancyconstant IS NOT INITIAL.
            lw_item_param
-airbuoyancyindicator = 'X'.
         
ENDIF.
       
ENDIF.

        lw_item_param
-calculatemissing        = 'X'.
        lw_item_param
-testtemperature_density = '15.00'.
        lw_item_param
-testtemp_density_uom    = 'CEL'.

 

        lw_item_param-basedensity             = lw_tankm-tag_value.
        lw_item_param
-basedensityuom          = lw_tankm-tag_uom.
        lw_item_param
-testdensity             = lw_tankm-tag_value.
        lw_item_param
-testdensity_uom         = lw_tankm-tag_uom.

        lw_item_param-materialtemperature     = lw_tankm-tag_value.
        lw_item_param
-materialtemperature_uom = lw_tankm-tag_uom.

  

 

 

Another important point

 

 

There is a mapping between the item and item_param that is line_id they should be same for the item for which the parameter is passed.

 

        ADD 1 TO lw_item_count.
    lw_item
-line_id = lw_item_param-line_id = lw_item_count.

 

        APPEND lw_item       TO lt_item.
   
APPEND lw_item_param TO lt_item_param.

 

        CLEAR : lw_item,
           lw_item_param
.


 

 

Calling the BAPI

 

Finally we will call the BAPI to post the Document.

 

CALL FUNCTION 'BAPI_GOODSMVT_CREATE_OIL'
     
EXPORTING
        goodsmvt_header    
= lw_header
        goodsmvt_code      
= '04'
     
IMPORTING
        materialdocument   
= lw_doc_no
     
TABLES
        goodsmvt_item_01   
= lt_item
        goodsmvt_item_param
= lt_item_param
       
return              = lt_return.

   
IF lt_return IS INITIAL
  
AND lw_doc_no IS NOT INITIAL.
     
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' .
     
MESSAGE s110 WITH lw_doc_no.
   
ELSE.

     
CALL FUNCTION 'POPUP_WITH_TABLE_DISPLAY_OK'
       
EXPORTING
          endpos_col  
= 150
          endpos_row  
= 15
          startpos_col
= 5
          startpos_row
= 5
          titletext   
= text-002
       
TABLES
          valuetab    
= lt_return.

   
ENDIF.

Stumbled Upon Checkpoint Groups

$
0
0

I stumbled upon the concept of Checkpoint groups by accident.

 

One day I was debugging a wave release process in EWM box by activating /h debugging and jumping around using F5, F6, F7 keys. It was getting hard to track the flow of logic because of ALV control framework and nervousness around object oriented code. To save time, I placed breakpoint on statement CALL FUNCTION and continued, hoping that I'll reach a main function module soon.

 

 

I came across BREAK-POINT ID statements while still in classes. They seemed to decipher my action and pass control to another class or function module. My first thought about this statement was that SAP has created special breakpoint statements with specific user IDs, and these are used when they respond to OSS messages.

 

It was a mistake not to see keyword documentation of BREAK-POINT ID. This resulted in significant waste of time.

 

Another day I was asked to apply a note, which had manual pre-implement steps. According to those steps, I had to go to SAAB transaction and create or activate a checkpoint group. System allowed me to create Checkpoint group without asking for access key. It then struck me that the concept is not for SAP internal use only.

 

 

If checkpoint group can be activated without access key or transport request, it is as easy as activating the debugger.

I read the documentation, and activated breakpoint in /SCWM/WAVE checkpoint group.

On releasing new wave, debugger popped up at BREAK-POINT ID statement.

 

I found it useful but limited in scope as the person doing debugging needs to know beforehand what checkpoint groups are applicable. Again, it was a mistake to assume.

 

In New ABAP Debugger, I was checking the number of watchpoints set up under Break./Watchpoints > Watchpoints tab. Right next to this tab was Checkpoint Activations. This tab showed list of checkpoints applicable in current process, also the ones used in current stack level.

 

 

After seeing the option activating Checkpoints in New ABAP Debugger, I now try to use it during analysis.

I think having custom checkpoint in every enhancement implementation will make life easy for person doing debugging in support environment.

 

Summary points

  • Checkpoint groups can be activated using Transaction SAAB.
  • Checkpoint groups can be activated in runtime using New ABAP Debugger.
  • Activation can be user specific, server specific or global.
  • Apart from Breakpoints (BREAK-POINT), option of Assertion (ASSERT) and Log point (LOG-POINT) is also there.
  • Logs can be checked in SAAB transaction.
  • SAP Help link
Viewing all 948 articles
Browse latest View live


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