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

Intelligent Pagination Concept in SAP Jet Forms

$
0
0

This blog presents the concept of intelligent pagination which is used for restricting or controlling the jet form layout based on some criteria.


Jet forms:

Jet forms are used to produce electronic templates that can be issued via emails or printed using several printers. The output can be in any form like .PDF, .HTML etc.


Jet forms only produce the layout (the data in that has to be populated by ABAP print program like scripts). The job of combining the template and data is done by Print Agent which is the component of Jet form central server.


Software: Jet forms are developed using a third party software provided by Adobe. The software is Adobe Output Designer.


Using Output Designer, each electronic template that you create consists of two pieces:

  • The modifiable layout called the template design (.IFD) file.
  • The compiled output template (.MDF) file.


Print Agent:Print Agent, the output component of Adobe Central Output Server (Central), uses intelligent merge technology to enable applications to output data, merged with electronic templates.


Types of Templates: Using output designer, you can develop two types of templates. They are,

  • Static Template
  • Dynamic Template


Example of a template (.IFD file):

1.png


Static Template:

By static template we mean a template that presents the same text, graphics, and field areas to all recipients all the time. Only the user specific data presented in the field areas differs from one recipient to another. The template does not flex to different amounts of data, nor does it eliminate any elements that are irrelevant to an individual user.


Dynamic Templates:

A dynamic template presents text, graphics, and field areas that flex according to the needs of the recipient. In contrast to a static template, a dynamic template presents only those elements and sections of the template that are relevant to the data requested.

“A dynamic template is moreover combination of several sub forms”.

Most commonly, you use dynamic templates when you need to present repeating data that varies in size according to the recipient. Using the example of a purchase order, a dynamic template would show only the number of detail lines pertinent to that order.

The business requirement will dictate whether a template is static or dynamic. When you wish to present the same data to each user, and when the data does not repeat, then a static template is an appropriate choice. Otherwise, a dynamic template provides greater flexibility for presenting data.


Subforms: A subform is an individual section in a template which consists of a group of objects that are relevant to each other.

 

For example, consider the below template. Here all the item details are grouped together into a subform.


2.png


JFPreamble and JFPreamble_1:

The first time you compile a dynamic template, Output Designer creates two custom properties for the template called JFPREAMBLE and JFPREAMBLE_1. These two custom properties, known as DOCVARs (document variables), contain the processing rules for the template. It is JFPREAMBLE that the output Agents look for when the time comes to merge data with template.


Intelligent Pagination:

The output designer gives the flexibility for creating events in the template and making the events active at appropriate time.

Such events can include appropriate page breaking by calculating whether there is adequate space to lay down a subform on the current page or whether to place it at the top of the next page or if there is a need of restricting the pages based on some criteria.

For example, suppose I have 5 pages in my template, but as per the requirement, I have to skip page 1 and print from page 2 to 5 for particular country. This type of requirement can be fulfilled using the Intelligent Pagination concept.


Intelligent Pagination uses several commands to trigger the events and take appropriate action.


We will get a clear picture on Intelligent Pagination concept by understanding the following requirement.


Requirement:Adding a new page after page 1 in already existing layout form and calling the new page instead of page 1 only for specific country. 


Changes to be made in 2 areas:

1) Layout/Template level

2) ABAP Print Program


Template level change:

Template prior to change: Before making the changes, the form template (IFD file) had 3 pages.

3.png

Now adding a new page after page 1.

4.png

5.png

New page inserted as page 2. In this page, copied the page 1 components. We can copy the components from one page to another by CTRL+A and CTRL+C.

6.png

Now, there comes the main task, what command need to be used and where it needs to be written.

JFPreamble, is the document variable where we can make our custom changes.


7.png


8.png

Point to be noticed: While copying the components from page 1 to new page (page2), the names assigned to components in page 2 will be same as in page 1. Hence there will not be any differentiation between page 1 and 2.

As we need to trigger page 2, the idea was basically to change the field name in page 2(new page) and then use intelligent pagination command  !FldUsed on the changed field.


groupname!FldUsed (FieldUsed): This event is triggered whenever the field name mentioned is available with some data.

Hence, we change the name of a global field InvoiceNumber to InvoiceNumber2 in our new page. In page 1, it remains same InvoiceNumber.


9.png

 

Then the box is grouped with group name GInvoice2 as shown below.


10.png

Grouping is required because the group dictionary stores all these events.


The basic Syntax:

^define group:<groupname>!<event>        \action


Then, the event !FLDUSED is added in the JFPreamble, as shown below.

11.png


The flow of the above 2 highlighted lines goes like,

  • ^define group:InvoiceNumber2!FldUsed        \groupGInvoice2\fieldInvoiceNumber2.

         Here, the print agents triggers this event whenever the field mentioned (InvoiceNumber2) has data in it. Once it is triggered, it goes                      to action that is groupGInvoice2.

 

  • ^define group:GInvoice2 \page2.

         When the control comes to group GInvoice2, it triggers this event and performs the action \page2, which means goes to page2.

 

Now here, the changes at template level are done. After making the changes the .IFD file is compiled and .MDF file is generated, which need to be uploaded in the client’s UNIX server.


ABAP Print program changes:


SAP scripts are generally used to produce data stream for jet form layouts. Hence we made changes in the script for restricting the page.


JOB command: This is the first command executed in the script with which the Print Agent is evoked. Hence we made a change for controlling the pages in JOB command as shown below.


“We use certain print agents commands in script level in order to control the printing. The events which we used in template level cannot be used here”.


The below changes are made in JOB command.


If country = specific country.

^JOB &FORM-JOB&_EMAIL -z&template_name &_EMAIL -c001 -aip02  –aspPDF

*Pass the data for InvoiceNumber2.

^GLOBALInvoiceNumber2

&VBDKR-VBELN&

Else.

^JOB &FORM-JOB&_EMAIL -z&template_name &_EMAIL -c001  –aspPDF

*Pass the data for InvoiceNumber.

^GLOBAL InvoiceNumber

&VBDKR-VBELN&

Endif.


Few Print Agent Commands:

-aipn -> used for starting the print from a specific page. Hence we specified here –aip02, which starts the print from page 02.

-c   -> it specifies the number of copies to be printed/emailed.

-asp-> Specifies the type of output to be produced, in this case it is PDF.


There might be a confusion, that why do we need to change again in script level when the changes are made in template level.

It is because, in jet form template the first page is the default page and it will be automatically printed. Hence while start of the print agent itself, we need to make sure that we start the printing with page 2.


After making all these changes, observed the output with the new page and the page 1 was not displayed.


There are lot many other Intelligent Pagination commands, I will be posting soon in my next blog with suitable examples. Thank you for reading.


Using program referenced variables in pricing routines

$
0
0

It shouldn't be a difficult thing to agree that pricing is one of the most tricky items to handle, especially when it comes to debugging scenarios that break so randomly.

 

There was an issue where a custom pricing condition (that calculates the discount based on neighboring items in the order) wasn’t giving expected results. In certain cases it worked, but in some other cases it didn’t. Typical on any custom development right!

 

The calculation was very straightforward and had no chances of breaking. After much debugging it was seen that the RETTKOMV structure was overwriting the values. After ploughing through plenty of SD forms (eg. http://scn.sap.com/thread/236383) which mentioned about this “notorious-yet-popular” structure , I was still clueless on what the issue was.

 

For anyone who has debugged the pricing routines, you can imagine the patience that we develop as a part of this. The number of times the routines get called is pretty much close to being called insane, if you consider the good number of pricing conditions configured per line item.

 

But ABAPers have a way of resolving any issue. Its just a matter of time.

 

It suddenly struck me that to get the details of the line items, we were referencing a structure from SAPMV45A… and this one kept changing focus depending on the various updates to the line items. Bingo.

 

Moral of the story – the pricing condition values getting overwritten because of RETTKOMV is a pretty standard scenario. The framework ensures the dependencies are correctly handled and the prices not distorted because of the umpteen pricing conditions. Care should be taken to make use of the right structures (which again, is dependent on the scenario under consideration) to set the price values. And do not make use of specific item level structures from SAPMV45A as they may change amidst the loops! In the worst case scenario, use the whole table content from SAPMV45A (ensuring performance isn’t significantly impacted) and read the required content based on the item number on which the pricing is to be applied.

 

This was just a tip.. if at all anyone runs into a similar issue.

Archiving a Smartform

$
0
0

I was working on a smartform associated with an output type where it was required to trigger an output with the following requirements.

  1. Archive the output triggered into an external repository, like doculink
  2. Convert the smartform to PDF
  3. Store the PDF on the SAP UNIX directory
  4. Send the PDF as an attachment in an email and archive the same(Transmission Medium = ‘5’)

I was able to fulfill all the above requirements, except archiving of the outputs which led me to do extensive research on this concept and subsequently found a solution for the same.

 

In this blog, I would like to share my knowledge on this as I have seen many threads asking for solution on this.

 

1.       What is archiving?

Archiving is the process of storing data in an external repository which can be reused and viewed as and when needed and which is governed in SAP by the storage mode.

SAP allows outputs to be triggered in three storage modes:

  1. Print only – Printout is issued and no archiving of the output issued
  2. Archive only – The output is only archived
  3. Print and archive – Print out is issued and also output is archived

image1.jpg

 

2.       Why archiving is needed?

Archiving allows us to store the related documents together under one folder with information such as date on which the outputs was triggered.


3.       How to view the archived documents?

Method 1: Transaction code J6NY allows us to see all the archived documents under the required folder for the required output with trigger date.

For example, all vendor POs will be under one folder named Vendor Purchasing Folder. Search the document with PO number.

image2.jpg

 

Method 2: Display Originals in communication method

 

Under messages, select the output successfully processed (Green indicator) , click on "Communication method" then click on "Displ. originals". You will be redirected to where the document is archived.

image3.jpg

image4.jpg


4.       Required settings to archive

To archive the document with the output type, required document type has to be maintained under Storage system in NACE settings.

image5.jpg


5.       Parameters on which archiving of smartforms depends.

    1. CONTROL_PARAMETERS     
    2. OUTPUT_OPTIONS                
    3. ARCHIVE_INDEX
    4. ARCHIVE_PARAMETERS

image6.jpg

 

ABAP approach to archive the outputs:

 

STEP 1:

"Structure for Smartform Control Parameters
 DATA : gst_control_param    TYPE ssfctrlop.
 "Set the GETOTF field to blank            
 gst_control_param-getotf    = ''.


image7.jpg


STEP 2:

"Structure for  Smartform Output Options
 DATA :  gst_output_options           TYPE ssfcompop.   
 "Set the TDARMOD TO 2 ( Archive only) / 3 (Print and Archive)
 gst_output_options-tdarmod = '2'.

                                        OR

 gst_output_options-tdarmod = '3'.

 

image8.jpg


STEP3:

 

Call the smartform with the below parameters


CALL FUNCTION gw_fm_name
 EXPORTING
 archive_index           = toa_dara
 archive_parameters      = arc_params
 control_parameters      = gst_control_param
 output_options          = gst_output


That’s all , call the smartform with these parameters set as required,the output triggered will get archived in the repository. But to convert the smartform output to PDF and attach in the email we need to get the OTF of the smartform called which will be achieved by setting the GETOTF field ‘X’ as below.

 

gst_control_param-getotf    = 'X'. "Get OTF of the smartform

But by doing so it fails to archive the document so to overcome you can call the smartform twice with GETOTF = ‘Blank’ and GETOTF = ‘X’, first one to archive and second one to get otf which can be converted into PDF.

 

Note : Archiving with Transmission medium as External Send (NAST-NACHA = ‘5’)

When output is triggered with transmission medium as external send, the output fails to archive as the GETOTF field is set to ‘X’. So in such case call the smartform twice as explained above.


image9.jpg

 

 

Summary:

  1. To archive, GETOTF = space and TDARMOD = 2 or 3
  2. To get OTF, GETOTF = ‘X’ which can be converted into PDF and can be uploaded onto the SAP UNIX server.

How to Print image over data in smartforms from Include texts.

$
0
0

In Standard Scripts you may find data as such variable logo and variable data(variable in the sense, image and data change as per document) are combined in a include text and printed.where as same include text doesn't get printed in smartforms.

 

Becasue smartforms doesn't have the functionality to execute include texts line by line as we have it in scripts.

In such a case, first you need to separate data using read text(because data may vary according to the document) and print using some internal table.


Identify the logo and upload it in se78 to print it in smartforms using graphics.

In scripts we use protect and end protect to use overlap data with the image.
However in smartform you need to use template and print logo and data in the same row of template, i.e same Output structure

 

Following is the example illustrating the same :

 

data is maintained in text as below :

 

script_data.PNG

below code extracts data and particular image.

 

DATA : lw_flag TYPE c.

REFRESH: gt_tline,gt_tline1.

CLEAR: gw_name, gst_tline,lw_flag.

gw_name = '0084568432'.


CALL FUNCTION 'READ_TEXT'

      EXPORTING
         id                                  = 'ZH20'
         language                      = 'E'
         name                            gw_name
         object                            = 'VBBK'
     TABLES
         lines                               = gt_tline
     EXCEPTIONS
         id                                    = 1
         language                        = 2
         name                              = 3
         not_found                       = 4
         object                              = 5
      reference_check                = 6
      wrong_access_to_archive = 7
      OTHERS                            = 8.

if sy-subrc Eq 0.

   LOOP at gt_tline INTO gst_tline.

     if lw_flag IS INITIAL.

     if gst_tline-tdformat EQ '*'.
       APPEND gst_tline to gt_tline1.
       DELETE gt_tline Index 1.
     else.
       lw_flag = 'X'.
     endif.
     endif.

    if lw_flag = 'X'.
     if gst_tline-tdformat NE '*'.
       if gst_tline-tdline CS 'ZHEX-SQUARE'.
         gw_logo_name = 'Z_SQUARE'.
        endif.
          DELETE gt_tline Index sy-tabix.
      endif.
      endif.
   ENDLOOP.
   CONDENSE gw_logo_name.

endif.

 

Loop at header data is data in GT_TLINE1.

grphic_1.PNG

 

graphic.PNG


and the image looks as below :

 

data.PNG
Please let me know if any queries . thanks

Character formats for Smart form and Adobe form

$
0
0

Hello,

 

This blog entry stem from this question I asked (https://scn.sap.com/thread/3697966) and the response that I got from Jānis B. I think that all the credits should go to him .

 

I am working for a chemical company and there is a use of chemical characteristic in data tables (e.g chemical formula,).

 

For example: H<SB>2</>O boil at 100<SP>0</>

 

This piece of data needs to be printed like this:

screenshot_01.png

We have some old development that use sap script.

Within SAP script form we can define "Character formats" that will intercept the SB,SP tags:

 

We are in 2015 so the current technologies are Smart forms and Adobe forms and we would like to use those:

 

The data definition involve is similar for both technologies , we need to add to our internal table a new "field" , this field is actual a table type tline_tab ,

 

I created a global class (SE24) to put my data type definitions:

 

 

The table values:

 

 

Look into the internal table :

 

 

Smart form implementation:

 

Import parameter:

 

 

Global:(ignore ST_SFLIGHT)

 

screenshot_07.png

 

The table loop:

 

 

The use of dynamic text:

 

We are printing the content of the internal table.

 

 

The last ingredient is a Smart Style: (for demonstration purpose I also use some color)

The SP tag is identical but uses the superscript .

 

To control the height of the table row I use the "Paragraph Format" .

 

 

The Smart Style as used in the form:

 

 

The result:

Adobe form implementation:


(I am a newbie with adobe form and I got a lot of help from a team member Jenya Hondrash )


Data definition:

 

 

Form interface:

 

 

Form context:

 


Form layout:

 

 

 

 

 

Binding:

 

 

The result:

 

 

Phew that was a long one....

 

Regards.

Top 10 ABAP crimes

$
0
0

Unfortunately It is not very rare to see sloppy codes in ABAP especially if you are working as a consultant. In this blog  you can see my  selection of worst ten examples. Some might be debatable but some are definitely not. It would  also be nice to discuss examples, cases you experienced in the comments section.

 

1. Complete program with no modularization blocks

Hundreds sometimes, thousands lines of code with no modularization blocks, no includes. Conditions with hundreds lines of codes. No readability, definitely,  It is my worst nightmare to be asked to correct or change this kind of code. It is not really different having only 2-3 modularization blocks with hundreds line of code.

 

2. Modification/repairs

Not all of them, but if any modification is done without enough investigation might cause big issues in time and I guess everyone would be agree it is not a good approach to modify standard programs without searching  any alternative solution. So I would suggest to think again if you are often doing modifications. And check first if it is possible to make enhancement instead of modifications.

 

3- Not considering performance

Codes with nested loops, one big loop with 30 select single, inside, select *, uncontrolled “read”s. They will decrease the performance more than you can imagine and should be avoided all the time. You can avoid some of them using proper design and  many alternative options are in place only if you search them.

 

4- Development in productive and quality assurance systems

Not very often, but it is not impossible to see such cases, no need to say it may cause big headaches and you are taking big risk if for any reason you are doing this.

 

5- No success and failure checks

I have seen few of these kind of program, probably it is thought that every single statement in the code will run smoothly but it is  not always the case. and If you  can not see any sy-subrc checks in a program this is not a good sign at all.

 

6- Not using exceptions

Very similar to point five, it is nice to consider all possibilities and implementing exceptions as described.

 

7- Copying big templates to every program

Especially for ALV, it is easy to prepare a template with all functionality and copying this template any time where ALV is used.Even it helps to save time, if any function is not needed for the copied programs they should be cleaned, if they are not they will cause issues.

 

8- Too many global definitions

Global definitions should only be used if they are needed by design, and in a good design they should not be needed too much. 

 

9- Lack of comments

Readability is very important, and where a complex logic is coded it is very helpful to put some comments to explain what is exactly done.

 

10-  Too many errors and warnings after SLIN and SCI checks in a recently developed program.

Things might change in time quickly in programming  and easiest way to see if we are on a good track in terms of development quality is  using automated tools like SLIN and SCI. It  is very easy to use, very explanatory and will save us from lots of mistakes. If you are not using this tools you might never know, if something that you have coded is right or wrong. Using these check tools will easily cure most of the mistakes mentioned above. 


It seems ten is not enough I am also adding other points should also have been in this list which are mentioned in comments section


11- Copying standard programs ( From Matthew Billingham)

 

If you copy standard programs, in every upgrade there will be difference between  copy program and new version of the copied standard which is not a good thing. And it will require big efforts to adapt new functionality into copy program.

 

12- Writing code like 1999 ( From Patrick Weber )


Using obsolete statements all the time it is very annoying.

Call two ALV tables in fullscreen

$
0
0

Issue: Create a Report with 2 ALV tables. These should open in full screen and take the maximum amount of space available on the screen. This one is for ABAP beginners.

 

There is a Report by Ruchi Tiwari which do nearly the same, but use a fixed sized custom control.

 

  • Create an empty Dynpro with screen number 2000. Create the PBO (status_2000) and PAI (user_command_2000) within forward navigation. I didn’t change the names. You can use includes but is quiet a god idea for real life use, but in this example I’ll put all code in my program “file”.
  • Add a status, because there will be a point in time, where you wish to leave the program( or not )

1.png

  • Add the PAI code for the exit. Your PBO and PAi should now look like this.2.png

          Now you should be able to call the programm and leave it with the exit button.

  • Add the code to the Programm:



"Data for output
DATA: gr_container TYPE REF TO cl_gui_docking_container.   "The carrier for the split container
DATA: lv_splitter TYPE REF TO cl_gui_splitter_container"The splitter itself
DATA: lv_parent1 TYPE REF TO cl_gui_container.           "parent 1 and 2
DATA: lv_parent2 TYPE REF TO cl_gui_container.

DATA ref_grid1 TYPE REF TO cl_gui_alv_grid.
DATA ref_grid2 TYPE REF TO cl_gui_alv_grid.
DATA: gr_table1 TYPE REF TO cl_salv_table.
DATA: gr_table2 TYPE REF TO cl_salv_table.

"Some data used for DB query
DATA: gt_mara TYPE STANDARD TABLE OF mara.
DATA: gt_mard TYPE STANDARD TABLE OF mard.


START-OF-SELECTION.

SELECT * FROM mara INTO TABLE gt_mara UP TO 200 ROWS.
SELECT * FROM mard INTO TABLE gt_mard UP TO 200 ROWS.

CALL SCREEN 2000.


*&---------------------------------------------------------------------*
*&      Module STATUS_2000  OUTPUT
*&---------------------------------------------------------------------*
MODULE status_2000 OUTPUT.
SET PF-STATUS 'STATUS'.

"Now we create a docking container which will use the hole screen. So the Dynpro 2000 can't be seen anymore.
CREATE OBJECT gr_container
EXPORTING
*     parent                      = g_grid_main
repid                       = sy-repid                                  "needs report id
dynnr                       = sy-dynnr                                  "need dynpro number
side                        = cl_gui_docking_container=>dock_at_bottom  "we want to add the docking on the bottom of the screen 2000
extension                   = cl_gui_docking_container=>ws_maximizebox "The Dockingcontainer should use the hole screen
*     style                       =
*     lifetime                    = lifetime_default
*     caption                     =
*     metric                      = 0
*     ratio                       = 70
*     no_autodef_progid_dynnr     =
*     name                        =
EXCEPTIONS
cntl_error                  = 1
cntl_system_error           = 2
create_error                = 3
lifetime_error              = 4
lifetime_dynpro_dynpro_link = 5
OTHERS                      = 6.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.


**   create splitter container in which we'll place the alv table
CREATE OBJECT lv_splitter
EXPORTING
parent  = gr_container
rows    = 2
columns = 1
align   = 15. " (splitter fills the hole custom container)
**   get part of splitter container for 1st table
CALL METHOD lv_splitter->get_container
EXPORTING
row       = 1
column    = 1
RECEIVING
container = lv_parent1.
**   get part of splitter container for 2nd table
CALL METHOD lv_splitter->get_container
EXPORTING
row       = 2
column    = 1
RECEIVING
container = lv_parent2.

***  Display first ALV
PERFORM set_display.
***  Display second ALV
PERFORM set_display1.

ENDMODULE.                 " STATUS_2000  OUTPUT
*&---------------------------------------------------------------------*
*&      Module USER_COMMAND_2000  INPUT
*&---------------------------------------------------------------------*
MODULE user_command_2000 INPUT.
IF sy-ucomm = 'EXIT'.
LEAVE PROGRAM.
ENDIF.
ENDMODULE.                 " USER_COMMAND_2000  INPUT
*&---------------------------------------------------------------------*
*&      Form SET_DISPLAY
*&---------------------------------------------------------------------*
FORM set_display .
*... Create Instance
CALL METHOD cl_salv_table=>factory
EXPORTING
r_container  = lv_parent1
IMPORTING
r_salv_table = gr_table1
CHANGING
t_table      = gt_mara.

*... Display table
gr_table1->display( ).
ENDFORM. " SET_DISPLAY

FORM set_display1 .
*... Create Instance
CALL METHOD cl_salv_table=>factory
EXPORTING
r_container  = lv_parent2
IMPORTING
r_salv_table = gr_table2
CHANGING
t_table      = gt_mard.

*... Display table
gr_table2->display( ).
ENDFORM.

How to set Page Break/ Page Reset in Smartforms using Events

$
0
0

The events in the smartforms are helpful in the requirements, where we need the following scenarios to be done:

  1. Page break based on the document(sales order number, delivery number, ship-to number)
  2. To print the subtotal of the smartform.
  3. Page number Reset.

 

For printing the sub total of the smartforms, the links are already available.


This blog contains the detailed description about how to set the page break, based on the document number and page number reset.

 

1.1 Steps to be followed in Page Break

 

The below steps are followed and code is applied for the page break:

 

  • Sort the table, in which our loopis present on the basis of the field where the page break is to be applied; in this case, it would be “Ship-to” (KUNNR).

          cap1.png

  • An automatic event would be created named KUNNR.

          Capture.PNG

  • Right click on the event and create a command. This command would be to print the new ship-to party and its corresponding data in the new page.

        cap3.png


The output of the form would be as below:

 

cap4.png


This would be the first page and the next page would have a different ship to number

cap5.png

 


2.    How to Reset Page Number

 

Generally, in smartforms, we would use the system fields for printing the page number. There could be a requirement, wherein the page numbers are to be reset according to the document number. Taking the above given example, in case the page break is in the occurrence of new ship-to number, the page number should reset, rather than the continuous increment of the page number.

 

Say, for instance, there are 2 ship-to numbers; the first ship-to number has 2 pages of data, so, the page number here should be printed as:

      • Page 1 of 2
      • Page 2 of 2

 

The second ship-to number has 1 page, so here the page number would be Page 1 of 1. To achieve the above requirement, events in the smartforms would be used. The flow here for page break logic would always go as below:

 

      • Initialization
      • Header
      • Sort Beginning
      • Sort End
      • Sort Beginning (would go here again for the next new document number)
      • Footer

 

Sort beginning and end areas are created automatically at the time when the sort is applied at the table. We just need to click on sort begin and sort end. Below is the screenshot for the same:

           cap6.png


Following is the code to be executed:

 

In the initialization, we need to count the total number of pages for each new ship-to, the same variable is saved in the final table (used as in loop).

 

DATA: lw_count TYPE i,
      lw_tabix TYPE i,
      lst_lips_kna1 TYPE gty_lips_kna1.

gw_page = 1.
LOOP AT gt_lips_kna1 INTO gst_lips_kna1.
  ADD 1 TO lw_tabix.
  AT NEW kunnr.

    lw_tabix = 1.
  ENDAT.
  IF gw_page IS INITIAL.
    lw_count = 31.   "  It is set 31 here for the number of line items, the value would differ according to the line items one needs to print in a page

  ELSE.
   lw_count = ( gw_page * 30 ) + 1."All the line items would be in the multiple of 30 + 1. For eg : 60 + 1, 90 + 1 etc.
  ENDIF.
  IF lw_tabix >= lw_count.
    ADD 1 TO gw_page.
  ENDIF.
  CLEAR gw_page_total.
  AT END OF kunnr.
   
gw_page_total = gw_page.
    gw_page = 1.
  ENDAT.
  IF gw_page_total IS NOT INITIAL.
    gst_lips_kna1-page_total = gw_page_total.
    MODIFY gt_lips_kna1 FROM gst_lips_kna1
    INDEX sy-tabix TRANSPORTING page_total.
    READ TABLE gt_lips_kna1 INTO lst_lips_kna1
    WITH KEY kunnr = gst_lips_kna1-kunnr.
    IF sy-subrc EQ 0.
      lst_lips_kna1-page_total = gw_page_total.
      MODIFY gt_lips_kna1 FROM lst_lips_kna1
      INDEX sy-tabix TRANSPORTING page_total.
    ENDIF.
  ENDIF.

ENDLOOP.
CLEAR gw_page.

 

lw_count is taken as the counter for the number of line items that would fit in one page.

gw_page_total is the variable to print the total number of pages in one ship-to.

gw_page will store the value for the current page to be printed.

 


The header portion will have the following code:

 

      IF gw_new_sort EQ 'X'.
        CLEAR gw_new_sort.
      ELSE.
        ADD 1 TO gw_page.
      ENDIF.

 


This code sets in the flag, which is used later in the footer part.

 

Sort begin would have this code to set the current page of the ship-to:

 

CLEAR gw_count1.
IF gw_count <= 1." This is done to avoid setting the flag as ‘X’ at the first run of the loop

ELSE.
  gw_new_sort = 'X'. " This flag is set to identify the beginning of a new page
ENDIF.

READ TABLE gt_lips_kna1 INTO lst_lips_kna1
      WITH KEY kunnr = gst_lips_kna1-kunnr.
IF sy-subrc EQ 0.
  IF sy-tabix = 1 .
  ELSE.
  lw_tabix = sy-tabix - 1. “ This marks begin of next document so to fetch the total pages for current ship-to number, subtracted 1 to get last record of current.
    READ TABLE gt_lips_kna1 INTO lst_lips_kna1 INDEX lw_tabix.
  ENDIF.
  gw_page_total = lst_lips_kna1-page_total.
ENDIF.


cap8.png


Sort End:

 

To fetch the total number of pages of the current document, as per the logic coded in initialization. 


cap9.png

 

 

 

READ TABLE gt_lips_kna1 INTO lst_lips_kna1
      WITH KEY kunnr = gst_lips_kna1-kunnr.
IF sy-subrc EQ 0.
  gw_page_total = lst_lips_kna1-page_total.
ENDIF.

 

 

The footer would be the area where the page number needs to be printed. After placing the text with the fields of the current page and page total, the code is to be placed in order to reset the page values.



cap10.png

 

IF gw_new_sort EQ 'X'.
  gw_page = 1.
  READ TABLE gt_lips_kna1 INTO lst_lips_kna1_n
      WITH KEY kunnr = gst_lips_kna1-kunnr.
  IF sy-subrc EQ 0.
    gw_page_total = lst_lips_kna1_n-page_total.
  ENDIF.
ENDIF.





Currency CURR type with more than 2 decimals - ALV output

$
0
0

I just realized how to use CURR type with more than 2 decimals.

 

I created a DOMAIN with Data Type CURR and 8 decimal places. Look at what happens at SE16N Details:

Capture.PNG


Value on right (Value Unconverted) is the real values on table with 8 decimals, and values on LEFT are showing on any ALV Output (SE16, SE16N or any ALV report). There is NO Conversion Routine at the Domain, only standard CURR type.

 

 

I could set DECIMALS on SALV using CL_SALV_COLUMN->SET_DECIMALS( '8' ), but it will only add ZEROS

 

Ex for first line in table, TOTFRDOC will show 11,006,361.60000000 instead of 11.00636160.

 

 

 

Yes, you may use CURR type with more than 2 decimals, knowing that this output conversion will happens.


So when use it?? If you want your CURR value converted to percentage (as a rate) usually using 4 decimals. Example:


Value unconverted: 0.6160

Output will show as percentage 61.60


Out of curiosity...

there are 57 standard domains type CURR with more than 2 decimals in my SAP system, 109 standard tables using that without any conversion...but most of them are rates with 4 decimals, so when converting to 2 decimals it shows value multiplied by 100, as in the example above.


I could fix my domain using DataType DEC instead. My ALV outputs are now showing right values with 8 decimals.

The Zen of Python in ABAP

$
0
0

After reading  Gungor Ozcelebi's blog, Top 10 ABAP crimes, I though I would share some Wisdom from "The Zen of Python" written by Tim Peters. This is valid for any programming language or developer, especially ABAP . Also check out  Python's PEP - 8 guideline which lays out strict coding formats and standards but the language does not enforce these. This would be a good idea for the ABAP elders to create some general consensuses or rules for programming guidelines.

 

Copied from https://www.python.org/dev/peps/pep-0020/

 

The Zen of Python by Tim Peters

 

    Beautiful is better than ugly.

    Explicit is better than implicit.

    Simple is better than complex.

    Complex is better than complicated.

    Flat is better than nested.

    Sparse is better than dense.

    Readability counts.

    Special cases aren't special enough to break the rules.

    Although practicality beats purity.

    Errors should never pass silently.

    Unless explicitly silenced.

    In the face of ambiguity, refuse the temptation to guess.

    There should be one-- and preferably only one --obvious way to do it.

    Although that way may not be obvious at first unless you're Dutch.

    Now is better than never.

    Although never is often better than *right* now.

    If the implementation is hard to explain, it's a bad idea.

    If the implementation is easy to explain, it may be a good idea.

    Namespaces are one honking great idea -- let's do more of those!



I would also like to point out that we should not be so quick to blame the fellow developers in ABAP but the rather the language. ABAP may be open source but it is proprietary. Many people in ABAP may have never worked with another language and often learn from outdated materials, bad examples, or over priced books. Another consequence of ABAP's proprietary status is the lack of appreciation for the work, especially for contract developers. How many people do you know who develop in ABAP as a hobby or learned it just to make something cool? This may or may not even be some of the reasons SAP is offering an alternative JAVA instance (as if JAVA is a better alternative to anything). I think it is a good idea for any developer in any language to learn other technical skills/languages to get a broader appreciation for development. In any case, ABAP certainly has it's advantages as well.

Difference in Valuation Data in MM03 from MBEW

$
0
0

The accounting tab of MM03 transaction displays all the valuation data of the material. All this data is fetched from MBEW table. For some materials there will be difference in the values displayed in MM03 and MBEW depending on sales area. Moving Average Price (VERPR), Standard Price (STPRS), Moving Average price of previous year (VJVER), Moving Average Price of previous period (VMVER ), Standard price of Previous period (VMSTP) and previous year (VJSTP ) are the fields for which we could find the difference in database values and MM03.

 

Any currency field in MBEW have the potential to generate the issue. Their values in database will be different from the values in MM03. This is because of the currency conversion which takes place before the values are displayed to the user. The currency conversion will takes place based on the values in MM03. The possible decimals places for each currency will be configured in TCRUX table.

 

TCURX is a standard SAP table that is used to support translation of currency values from/to internal (e.g. stored in a table) to/from external (e.g. displayed in user screen) values.  Standard SAP stores all values with two digits to the right of the decimal (looking like cents) so the table helps SAP to interpret the values when moving between internal and external processing.

 

The valuation data is converted from internal to external based on the configuration maintained in TCRUX table. SAP data associated with the referenced material is retrieved from SAP tables and displayed. This data is update to the database while creating an new material and below function modules are triggered in this process.

 

1) BAPI_MATERIAL_SAVEDATA:

          This funciton module is triggered to save the material data to the database. Function module CURRENCY_AMOUNT_BAPI_TO_SAP is called in the           subroutine Save_MBEW_DATA for currency conversions.

 

2)CURRENCY_AMOUNT_BAPI_TO_SAP:

          This function module is called to convert valuation fields data from the screen to SAP tables. For example the table value is 12.34 CLP, have a value of           1234 CLP or 12.34 CLP in the screen.


3)CURRENCY_AMOUNT_SAP_TO_BAPI:

          This function module can be called to convert the screen values to table values, i.e., with this the screen values and the SAP table values will be same.           However this can cause some inconsistency if the same material is part of multiple sales areas, which may use different currencies.

Creating internal table at runtime and display it (dynamic design) - beginners

$
0
0

Hi at all! I am relatively new to ABAP and I am just sitting in on creating some templates for often used topics.

The problem I have is that a lot of posts are not explained very well, hence it is often hard to understand what the person who blogged something about a topic is really doing within the code. Therefore I provide now – in my eyes – an important topic regarding the creation of internal tables at runtime.This gives you more flexibility and this class can also be reused.
I try to describe this topic as clear as possible to you.

Moreover i have decided to not use the plain text editor because this is pretty impractical reagarding copying.

If you have any questions or suggestions please let me now!!!

There is also a picture of the report attached

 

Regards Patrick.

 

 

Below you can see the class zcl_dynamic_db_query which handles the dynamic creation of an internal table.


CLASS zcl_dynamic_db_query DEFINITION

   PUBLIC

   FINAL

   CREATE PUBLIC .

 

PUBLIC SECTION.

*  public static method 'main' receives 3 input parameters from the calling program ->

*  the name of the DB-Table, the Columns which are needed and the where clause

   CLASS-METHODS main

     IMPORTING

       !dbtab TYPE csequence

       !cols   TYPE csequence

       !where TYPE csequence.

 

PROTECTED SECTION.

 

 

PRIVATE SECTION.

*  private static method 'display'; is used to give out the table header and

*  the result of the SELECT Statement executed in static method 'main'

   CLASS-METHODS display

     IMPORTING

       VALUE(result) TYPE STANDARD TABLE

       !struct_header TYPE REF TO cl_abap_structdescr .

 

 

ENDCLASS.          "end of definition

 

 

CLASS zcl_dynamic_db_query IMPLEMENTATION.

 

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Static Public Method ZCL_DYNAMIC_DB_QUERY=>MAIN

* +-------------------------------------------------------------------------------------------------+

* | [--->] DBTAB                         TYPE        CSEQUENCE

* | [--->] COLS                           TYPE        CSEQUENCE

* | [--->] WHERE                        TYPE        CSEQUENCE

* +--------------------------------------------------------------------------------------</SIGNATURE>

 

 

  METHOD main.

 

*     here we make use of the ABAP RTTS (Run Time Type Services) and

*     RTTI (Run Time Type Information) Classes which help us to find out

*    the structure of a table at runtime and also the types of its columns

    DATA: type_descr   TYPE REF TO cl_abap_typedescr,

               struct_descr TYPE REF TO cl_abap_structdescr,

               table_descr  TYPE REF TO cl_abap_tabledescr,

               table_ref    TYPE REF TO data,

              components   TYPE cl_abap_structdescr=>component_table,

              component    LIKE LINE OF components,

              error        TYPE REF TO cx_root.

 

*   field symbols are place holder for existing data objects and parts of existing data objects.

*  we need them to create the table to fill in the input of the query

    FIELD-SYMBOLS: <table>      TYPE ANY TABLE.

 

*   this creates a bunch of type descriptions of the table 'dbtab' and

*   saves the typeinformation into the variable 'type_descr'

    cl_abap_typedescr=>describe_by_name(

                       EXPORTING  p_name = dbtab

                       RECEIVING  p_descr_ref = type_descr

                       EXCEPTIONS type_not_found = 4 ).

    IF sy-subrc = 4.

      MESSAGE 'Type not found error' TYPE 'I' DISPLAY LIKE 'E'.

      RETURN.

    ENDIF.

 

    TRY.

*     now we use a down cast. the downcast is used when the static type of the

*     source variable is 'data' and the static type of the target variable

*     is completely typed. if not the exception cx_sy_move_cast_error is raised

      struct_descr ?= type_descr.

 

      CATCH cx_sy_move_cast_error INTO error.

        MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.

      RETURN.

    ENDTRY.

 

*   get components saves all components(== columns) of the table into the variable 'components'

    components = struct_descr->get_components( ).

 

 

*   If all columns are selected all components of the structure remain in the components variable

    IF cols = '*'.

*   else sort out those who are not needed

 

 

    ELSE.

      LOOP AT components INTO component.

        CONCATENATE '\b' component-name '\b' INTO component-name.

 

*     search for  all components which are inside of 'cols' and sort

*     out those columns inside the' components ' variable which are not needed

        FIND REGEX component-name IN cols.

 

 

        IF sy-subrc <> 0.

          DELETE components INDEX sy-tabix.

        ENDIF.

 

 

      ENDLOOP.

 

 

    ENDIF.

 

 

    TRY.

*     now we overwrite the existing structure with a new structure which

*     holds only those columns which are needed

      struct_descr = cl_abap_structdescr=>create( components ).

 

 

*     now we 'create' the description of the table which  will be needed in the end

      table_descr  = cl_abap_tabledescr=>create( struct_descr ).

 

      CATCH cx_sy_struct_creation cx_sy_table_creation INTO error.

        MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.

        RETURN.

    ENDTRY.

    TRY.

*     with 'TYPE HANDLE' we are able to reference a typed object of RTTS

*     the information was gathered with the aid of RTTI and now

*     the information is saved into the variable table_ref. This is necessary

*     because we cannot assign  with a RTTS object --> we need a data variable to do so

      CREATE DATA table_ref TYPE HANDLE table_descr.

 

 

*     now assign the structure of the table to the field symbol

      ASSIGN table_ref->* TO <table>.

 

      CATCH cx_sy_create_data_error INTO error.

        MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.

        RETURN.

     ENDTRY.

 

 

*     now we have to query the needed data from the table and save it into our table

     TRY.

     SELECT (cols)

      FROM (dbtab)

      INTO CORRESPONDING FIELDS OF TABLE <table>

      WHERE (where).

 

 

      CATCH cx_sy_sql_error INTO error.

        MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.

        RETURN.

 

 

     ENDTRY.

 

*     now we call the display function exporting the table with our information

*     and the structure of the table (which is needed for the header line)

      display(

            EXPORTING result = <table>

                      struct_header = struct_descr

                       ).

 

  ENDMETHOD.                    "main

 

 

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Static Private Method ZCL_DYNAMIC_DB_QUERY=>DISPLAY

* +------------------------------------      -------------------------------------------------------------+

* | [--->] RESULT                             TYPE        STANDARD TABLE

* | [--->] STRUCT_HEADER          TYPE REF TO CL_ABAP_STRUCTDESCR

* +--------------------------------------------------------------------------------------</SIGNATURE>

 

 

METHOD display.

    FIELD-SYMBOLS: <wa>              TYPE any,

                                <component>  TYPE any,

                                <wa_header>   LIKE LINE OF struct_header->components.

 

 

*      reading and displaying the header of the dynamically created table

       LOOP AT struct_header->components ASSIGNING <wa_header>.

         WRITE <wa_header>-name.

       ENDLOOP.

 

*      reading out the content of the internal table

       NEW-LINE.

       LOOP AT result ASSIGNING <wa>.

         DO.

          ASSIGN COMPONENT sy-index OF STRUCTURE <wa>

          TO <component>.

          IF sy-subrc <> 0.

            EXIT. "no more components

         ENDIF.

        WRITE: <component>.

      ENDDO.

      NEW-LINE.

      ENDLOOP.


 

   ENDMETHOD. " end of method 'display'


ENDCLASS. "end of class implementation




Now the report with a call of the class.


*&---------------------------------------------------------------------*
*& Report  ZLP_DYN_DB
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT ZLP_DYN_DB.

parameters:
  p_dbtab Type c length 132,
  p_cols  Type c length 132,
  p_where Type c length 132.


START-OF-SELECTION.

zcl_dynamic_db_query=>main(
        EXPORTING dbtab = p_dbtab
                  cols  = p_cols
                  where = p_where ).

Creating a Smartform and Access it via ABAP Program

$
0
0

Hi at all!

 

The next topic I want to cover is a short introduction on how to create a Smartform and call it from a program. For this you have to have an understanding of Smartforms in general.

 

However lets go through the steps starting at creating the smartform up to calling it from your program.


Have fun and if you have any question please feel free to ask!!

 

Regards Patrick.


1.) Call Transaction SMARTFORMS and create a new Form. Prepare it in order to get your data into the form.

 

As you can see on the Screenshot I have already prepared a Smartform named "ZSF_CAR_BOOKING".

 

02_Smartform.PNG

 

The first important step is to prepare data elements in the Form attribute. Therefore in the Tree View an the right side of the window select Form Interface. There we have several tabs, but to keep this simple we just focus on the Import Tab. There you specify the data you need in your form.

In this case we have some different fields of tables which are needed in the form (marked yellow in the screenshot below).

 

03_Smartform_input.PNG

 

As soon as this step is finished we can continue to create so called Windows were we place the data later on. Therefore we make a right click on

%PAGE1 New Page and Create a new Window. In this case I created 3 Windows and one Graphic element for the Company Logo.


As soon as this is finished you can see the finished components in the left tree view. The screenshot below shows how this now looks like. Moreover you can see that %WINDOW1 contains no text but a Address Component. This is a very simple way of adding a company address to your Smartform. The Main Window component also contains 1 Element, namely a Text Element.


04_Smartform_components.PNG


Now comes the point where the "MAGIC" happens. As already mentioned we create some text elements in the corresponding windows (alternatively also tables and loops can be created, but that is not the context of this blog).  The screenshot below shows how to turn on the Field List. With the aid of this field list we can now add our variables to the corresponding text elements.

 

The yellow button (outlined red on the top left of the picture) is the Field List Button and opens the Field List Window in the lower left. The second highlighted button is to insert the variables into the Text element. It is important that you use this button to add variables, otherwise it will not work!

The field list displays all possible variables which can be used in your form. Moreover there are the System Fields which enable you to insert fields like page number, date etc.

 

 

The next thing you have to look for is that you insert the variables enclosed in &. An example is shown in the picture below. As it can be seen the button Insert Field opens a new dialog where you can enter the desired variables you want to display in this form.

 

 

Now you can save your Smartform and activate it. When it is activated, a function module is automatically generated.





2.) Now the Form should be called in your program right? Now this step shows the code with the explanation of how this is done (in the most easiest way). And don't worry about were the data is coming from this is just a snippet of code.

No formatting of the code is used in order to make copying easier for you.                  



*&---------------------------------------------------------------------*
*& Report  ZLP_CALL_SMARTFORM
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT ZLP_CALL_SMARTFORM.

DATA:
*     we need that parameter to get the name of the function module
*     created when the Smartform is activated       
      fm_name TYPE rs38l_fnam,
     
*     those are the structures where the different information is stored    
      ls_cars         TYPE ZCARS,
      ls_customers    TYPE ZCUSTOMERS,
      ls_reservations TYPE ZRESERVATIONS,
      days            TYPE I,
      costs           TYPE I,
      mess            TYPE CHAR200.

*     here I calculate how long the car has been rent and moreover the costs
*     are then calculated depending on the category of the car.
      days = ls_reservations-date_to - ls_reservations-date_from.

      IF ls_cars-category = 'A'.
          costs = days * 300.
      ELSEIF ls_cars-category = 'B'.
          costs = days * 200.
      ELSEIF ls_cars-category = 'C'.
          costs = days * 115.
      ENDIF.

*      ----------------------------------------------------------------------
*     This function module call is used to retrieve the name of the Function
*     module generated when the SMARTFORM is activated
*     the export parameter 'formname' needs to be provided with the name of your
*     desired smartform
      CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
         EXPORTING
           formname                 = 'ZSF_CAR_BOOKING'
*          VARIANT                  = ' '
*          DIRECT_CALL              = ' '
        IMPORTING
          fm_name                  = fm_name
        EXCEPTIONS
          no_form                  = 1
          no_function_module       = 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.

*      now this function module is called and all the parameters
*      which you want to have in your smartform have to be provided
*      here. Error handling for parameters which are not provided is
*      usually done in the Smartform itself with an alternative or some other
*      processing logic.
        CALL FUNCTION fm_name
         EXPORTING
            mandt                 = sy-mandt
            name                 = ls_customers-name
            car                     = ls_cars-car
            category             = ls_cars-category
            license_plate        = ls_cars-license_plate
            reservation_number   = ls_reservations-reservation_id
            date_from            = ls_reservations-date_from
            date_to              = ls_reservations-date_to
            costsrate            = costs
            days_rental          = days
         EXCEPTIONS
           formatting_error           = 1
           internal_error             = 2
           send_error                 = 3
           user_canceled              = 4
           OTHERS                     = 5.

        IF sy-subrc <> 0.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
        ENDIF.

Test Driving the ABAP Test Double Framework - Eclipse Tools

$
0
0

This is a follow-up to the Test Driving the ABAP Test Double Framework


That blog contains screen shots of ABAP Unit tools in SAPGUI.

I've since re-installed my Eclipse. Below are the equivalent ABAP Unit Tools in Eclipse.

 

The ABAP Unit Runner ( CTRL+SHIFT+F10 ) displays the test methods and shows which tests have failed.

 

ABAP Unit Runner.GIF

 

 

The ABAP Coverage View ( CTRL+SHIFT+F11 ) displays the statistics on how much of the code have been covered by the tests.

 

ABAP Coverage.GIF

 

Navigating to the code from the ABAP Coverage View displays which piece of code has not been tested.

 

 

Code Coverage.GIF

Adding fields to table BKPF and updating in posting transactions.

$
0
0

 

I research about it and i want to share my solution.

 

This post is just to share knowledge and to receive your opinions.

 

First i went to dictionary ABAP and selected the BKPF table, then clicked in append structure.

 

 

after that this pop up dynpro is showed and you need to select the "Create Append" button

 

 

put the name in the box and then create, here you need to create the structure as any other, finally active.

 

Note: the field name must start with ZZ or YY. more information in Methods for Modifying Dictionary Tables - Contributor Corner - SCN Wiki

 

Until here we just have the fields to use, the next step is creating an BTE (bussines Transaction Event), if you don't know what is BTE or how it works see the doc FI Enhancement Technique - How-To-Guide on the Usage of Business Transaction Events (BTE)

 

Just to abstract.

"Business Transaction Events (BTE) allows attaching additional components, in the form of a function module to the R/3 system. Business transaction events function in the same manner as customer exits"- Jelena Perfiljeva in doc Business Transaction events(BTE) - Code Gallery - SCN Wiki

I used the BTE process Interface '00001120' - DOCUMENT POSTING:  Field substitution header/items, the sample function module is "SAMPLE_PROCESS_00001120", in FIBF transaction you can see more documentation.

 

Sample function.

FUNCTION SAMPLE_PROCESS_00001120.
 *"----------------------------------------------------------------------
 *"*"Lokale Schnittstelle:
 *"  IMPORTING
 *"     VALUE(I_BKDF) TYPE  BKDF OPTIONAL
 *"  TABLES
 *"      T_BKPF STRUCTURE  BKPF
 *"      T_BSEG STRUCTURE  BSEG
 *"      T_BKPFSUB STRUCTURE  BKPF_SUBST
 *"      T_BSEGSUB STRUCTURE  BSEG_SUBST
 *"      T_BSEC STRUCTURE  BSEC OPTIONAL
 *"  CHANGING
 *"     REFERENCE(I_BKDFSUB) TYPE  BKDF_SUBST OPTIONAL
 *"----------------------------------------------------------------------
 ENDFUNCTION.

The main purpose of this process is update head or line fields using the tables T_BKPFSUB and T_BSEGSUB, we going to use the T_BKPFSUB because the change was in the head of FI document, by logic the custom fields isn't in the Substitutable fields table, so, we need to appending it too with our fields.

 

Note: you need to copy the SAMPLE functions, never do changes in these, then you copy that go to the FIBF transaction to update the tables control.

 

Finally i didn't want to change the screen of every FI posting screens, for allow to the user to write in that fields, i just use the function  POPUP_GET_VALUES_USER_HELP

 

DATA: BEGIN OF FIELDS OCCURS 2.      INCLUDE STRUCTURE SVAL.   DATA: END OF FIELDS.   CLEAR FIELDS.   FIELDS-TABNAME = 'BKPF'.   FIELDS-FIELDNAME = 'ZZXBLNR_2'.   FIELDS-FIELD_OBL = 'X'.   APPEND FIELDS   CALL FUNCTION 'POPUP_GET_VALUES_USER_HELP'      EXPORTING         POPUP_TITLE = POPUP_TITLE      IMPORTING         RETURNCODE = RETURNCODE      TABLES         FIELDS = FIELDS   EXCEPTIONS        ERROR_IN_FIELDS                 = 1        OTHERS                          = 2               .   CHECK SY-SUBRC = 0.   LOOP AT FIELDS .      IF FIELDS-FIELDNAME = 'ZZFIELD1'.        t_bkpf-ZZFIELD1 = FIELDS-VALUE.        T_BKPFSUB-ZZFIELD1 = FIELDS-VALUE.      ENDIF.   ENDLOOP.  MODIFY T_BKPF INDEX 1 TRANSPORTING ZZFIELD1.  MODIFY T_BKPFSUB INDEX 1 TRANSPORTING ZZFIELD1.

And that's all, if you want to make a validation after posting the document about this fields you can try with the BTE P/S Interface '00001030 - POST DOCUMENT:Posting of standard data.' for FI transactions and '00001050 - POST DOCUMENT: Accounting interface' to interface like MIRO, PCP0, etc.

 

Finally remember in BTE's do a SY-TCODE or SY-REPID or document class types validation because it affect to many transactions.

 

Hope you find it helpful.

 

Thank you to take the time to read.

 

Francisco Romero.


Additional Fields on the Material Master

$
0
0

This article has its original at my blog http://oprsteny.com

 

If you need to extend your Material Master view tabs then this article will show how you can do it in few simple steps.

Let's have an example where we'd like to add some Plant-specific fields to the Material Master and we'd also like these fields to be visible and editable in MM transactions MM01 / MM02 / MM03.

In the example we will add new field Process Code (ZZ_PROCCODE) to the MM View named General Plant Data / Storage 1

Extending the master table

  1. Go to TCode SE11 and display table for plant-specific fields (MARC)
  2. Extend an existing or create new custom Append for MARC table- it will be a normal structure (will be editable in SE11) which will be appended at the end of the table

    New MARC Append structure
  3. Add your fields to the Append-structure - In our example we will add field for storing a process code called ZZ_PROCCODE of type ZZ_DTEL_PROCCODE built on domain ZZ_DOM_PROCCODE.

    New data element for MARC Append structure

    Data element Domain definition
  4. Activate the append structure -> this will trigger the MARC table
    (and all depending tables/structures) adjustments - this can be quite
    time consuming so take care when doing such change in production
    environment

    Updated MARC table with new Append structure

Create/Extend own sub-screen

  1. Create new function group (you can skip this step if you already
    have a FUGR created for this purpose) where you define new sub-screens
    which will contain your custom fields.

    !!! STOP !!!

    Do not create the FUGR manually but go through customizing for the MM views in
    SPRO IMG -> Logistics General -> Material Master ->
    Configuring the Material Master -> Create Programs for Customized
    Subscreens


    SAP IMG for Material Master Customizing

    Let's call our new FUGR ZSALES_MASTER.
  2. In SE80 display FUGR MGD1 and select the screen (MM View
    sub-screen) you want to enhance with your own fields - in our case it
    will be screen 2701 (Storage data: general data)
  3. Copy the selected screen from MGD1 to your FUGR (keep its current number)

    Copy standard screen to your FUGR
  4. Using Screen Painter edit the new screen in your FUGR (in our case
    screen 2701) and rename the group to some custom text describing the
    group of fields you're going to put inside. Then delete all fields from
    the screen and put there only your custom fields.

    ...the original layout will be changed from this

    Original screen layout

    ... to the following

    New screen layout
  5. Save and activate your new screen
  6. In SE80 open the screen (in our case 2701) and go to tab Flow logic
  7. In the code displayed remove (or comment out) all lines manipulating
    with fields that no longer exist in the screen and replace them with
    commands that will manipulate with your own custom fields. Be careful -
    don't remove (comment out) module calls MODULE GET_DATEN_SUB and MODULE SET_DATEN_SUB - these are responsible for reading data from database and putting them back once you change them in the MM views.

    Changed Flow logic of your new screen
  8. Activate all changes in the custom FUGR (added screen, its layout and flow logic)

Add the new subscreen to the standard MM Views

  1. Go to customizing for the MM views in SPRO IMG -> Logistics
    General -> Material Master -> Configuring the Material Master
    -> Define Structure of Data Screens for Each Screen Sequence
    (Tcode OMT3)

  2. Now you can either create your own screen sequence (by copying some
    of the existing ones) or just modify one of the already prepared ones -
    we will go to update already existing one (21 - Standard Industry: Tab
    pages)

    SAP IMG - MM Screens Sequence Customizing
  3. select the line and double-click on Data Screens

    SAP IMP Screens Sequence Customizing - Data Screens
  4. Now select the line with Screen Desription General Plant Data / Storage 1 and double-click on Subscreens

    SAP IMG Screens Sequence Customizing - Sub Screens
  5. Here you can preview the whole screen with its all sub-screens by pushing the button View Data Screen
  6. You can see your custom sub-screen is not visible ... yet :-)
  7. Go back and select the first line where  PROGRAM = SAPLMGD1 and SCREEN=0001 (screen 0001 is a dummy/empty screen), click on the Add new Entries button and replace the program name with SAPLZSALES_MASTER (main program of your FUGR) and put your own screen number (2701)
  8. Press SAVE button (you will be asked for a transport number) and voila ...YOU ARE DONE 8-)

To test your new screen go to MM01 or MM02

New material creation

Check in the General Plant Data / Storage 1 tab, that your new field (ZZ_PROCCODE) in your new sub-screen (2161) is visible. Change its value, enter all other required fields and save changes.

New material details

Check in SE16 that data has been saved correctly in the MARC table

New material details in MARC table

Modification of new fields data in PAI

In case you need to process or modify data of your new fields (or

also data of standard fields) during PAI in MM01/MM02/MM03) you have to

implement Customer-Exit EXIT_SAPLMGMU_001.

This user exit is called every time PAI is triggered.

If you need to do some error-checking during the SAVE action only, then you can surround your code with something like

  1. IF sy-ucomm = 'BU'. "this code executed only during SAVE
  2. * your code
  3. ENDIF.

Insufficient Data for an Image error with Adobe Reader

$
0
0

Hi guys, recently I got into trouble with some SAP 4.7 developments, I have SAP 4.7 release 620 at level 0063. I don't really know what the basis team upgraded but some reports begun to generate wrong PDF files. In SAP preview there was no problem but when you downloaded or sent them by email and then opened with Adobe Reader a message was shown: "Insufficient Data for an Image" / "Datos insuficientes para una imagen" (I have Adobe in Spanish version).

 

Basically the problem happened with the FMs 'CONVERT_OTFSPOOLJOB_2_PDF' and 'CONVERT_ABAPSPOOLJOB_2_PDF' when trying to flat compress images and font types to attach PDF binaries to an email. To solve it you need to check if one of these options meets your case:

 

A. Using report  RSTXPDF3:

 

This report is used to maintain the OTF-PDF conversion parameters in SAP. The parameter FLATE_COMPR_OFF (Do not use flat compression) must be set to ON, this way you disable flat compression and the PDF are generated correctly. To do it follow the next sequence:

 

 

1. Go to SE38 and run report RSTXPDF3.

1.png

2. Select 'List settings' check box and execute it.

2.png

3. Check if the value of parameter FLATE_COMPR_OFF is set to ON.

3.png

4. Go back and select 'Change Settings' check box, in the field Name enter the parameter you want to change and execute it.

4.png

5. Click on 'ON' button.

5.png

6. The parameter's value is changed, now you can test your PDF generation again.

6.png

 

 

B. Implementing SAP Notes:

 

NumberDescription
0000924752PDF converter: Logging OTF data
0001029572Prerequisite for Note 1499987
0001112170Error in SAPconnect OTF documents with format=TXT
0001125846CONVERT_OTF: Adobe Reader does not display any creation date 
0001151257Converting document content    
0001278061CONVERT_OTF: Overriding "Author" field in the PDF
0001320163Incorrect PDF data after Unicode conversion   
0001324547Sending a spool request as PDF via e-mail

 

Go to transaction SNOTE to implement the notes.

7.png

 

Hope these help you if you experience this problem.

SAP Praxishandbuch ABAP - Book Review

$
0
0

The author has collected the most important recurring solutions for ABAP development in this book. Therefore he could restrict the book to a manageable size. Nevertheless the solutions are explained by using practical examples. Furthermore the book contains many screenshots with detailed explanations that make it easier to understand.


The first part of the compendium explains an example from real life – the examples are showing that he was working at public utilities. It shows how specific development and enhancement of SAP standard can solve the requirements.


The foundation for any development, the SAP Data Dictionary, is explained in great depth. It covers the most important features of the Data Dictionary for developers: table properties, indexes, foreign keys, append structures, expansion categories, conversion routines in domains, table maintenance generator and modification adjustments, lock objects, database utility, search helps.


The next chapter on debugging is the chapter that I like most because for good development you must discover your program errors fast. This chapter explains the new debugger in more detail than the old debugger, because it has a cleaner Look & Feel and has an increased functionality. The author shows the core functionality so that almost all debugging cases during programming are covered. Additionally he gives hints in which cases a debugging instruction should be used. Furthermore some special debug mechanisms are explained, such as debugging pop-up-screens and background programs.


The chapter on professional ABAP development shows how you can use a basic structure for your ABAP programs. He starts with the mostly underrated topic documentation because ABAP programs are not scripts for a short-term event. So if you must maintain an old program it would be nice to have a good documentation inside the program. Also a kind of documentation is the user-friendly error handling that comes next. Here you can see that the author limits himself to the essential error-handling. After some lines about version management he turns to the SAP Control Framework. The book is covering only the ALV Grid Control, but this very extensively. The author is right that this control is the most used among all the controls of this framework but some lines on the Tree Control would have been nice. Nevertheless the author explains the ALV Grid lists for reporting and interactive programming in great detail. Furthermore data transfer and sending mail are explained with simple examples. Some minor topics like the use of “dirty assign” complete the book.


The book is suitable for developers with at least some previous knowledge and also as a reference book for advanced developers. In the moment it is only available  in German, but I hope that an English translation will be available soon. If you want to know more Google Playprovides themost comprehensive free sample I have seen.

NAMING STANDARDS IN ABAP CODING

$
0
0

1 Introduction

This document describes the development standards for SAP R/3, Workbench objects. These standards define the approach to be followed by all developers during development and maintenance activities.

These guidelines ensure that:

  • Objects are implemented in a consistent manner
  • Efficient development and maintenance.

 

2 General Naming Standards

2.1 ABAP Programs

 

2.1.1 ABAP Program Naming Standards

The maximum length for an ABAP program name is 30 characters. This format will help identify programs within a functional subsystem within an application area.

Format:      Z_BBCC_..._E---E

Where:                    Z          =             “Z” represents custom programs.
                           _ =    Underscore

                          BB     =     Functional area ex: FI, SD etc.           

                          CC    =    Functional subsystem within the functional area –.

                             _ =    Underscore

                             ... =     <open – descriptive of the program function, abbreviated as required>
_     =    Underscore

                         E---E =     a word or abbreviation describing the type of program – 

EXAMPLE:Z_SDSALES_RPT(REPORT PROGRAM)

                   Z_SDCUST_BDC(BDC PROGRAM)

Example: Z_FIAP_POSPAY_OUT or Z_HRPA_ROLL_OUT ( Out bound interfaces )

                 Z_FIAP_RETURN_CHECK_RPT ( report program )

 

 

2.1.2 Names of modified SAP program objects

If security is required at the program or application level, obtain the appropriate security object from the SAP security team.

  • Make a custom copy of the object according to the rules in the following sub-sections.
  • Make the necessary modifications in the custom copy.
  • Place a “Z”, to represent custom development, in front of the SAP report name (as the first character).

    - This standard does NOT apply to any module pool or function object.
  • Place a “Z”, to represent custom development, in front of the module pool, e.g. SAPMA03B would become ZSAPMA03B and its INCLUDE module MA03BTOP would become MZA03BTOP, etc.
  • Decide whether your change will be at risk if there is a support pack change to any of the INCLUDE modules, and if so then make sure to copy ALL INCLUDES to a NewellRubbermaid name even if you have no change to make in them.
  • IF you need to ADD new sub-routines, then create an entirely NEW include module called MZMA03BX…X– where “X…X” is any suitable acronym that may be extended to suit your need.

2.1.2.1 Names of modified SAP reports, sub-routine pools and report include modules.

2.1.2.2 Names of modified SAP module pools and their include modules

2.2 Transaction Codes

2.2.1 Transaction Codes Naming Standards

The maximum length for a transaction code name is 20 characters. Please make the names meaningful and at the same time keep it short.

Format:   ZBBCC_...X

Where:                     Z          = “Z” represents custom programs.
BB           =  Functional area ex: FI, PP etc. refer Appendix A           
CC           =  Functional subsystem within the application area – refer Appendix A.

                           _       = Underscore

            =  Meaningful abbreviation for the transaction

                            X        = optional alphanumeric identifier.

1 for create

2 for change

3 for display

6 for Delete

9 for List processing

Example:             ZFIAR_GLIST1, ZFIAP_GLIST1

 

2.2.2 Transaction Codes Design Standards

  • Follow SAPGUI standards to maintain the SAP look and feel; e.g. always provide 3 ways to reach each option – menu, button and function key.
  • Use the screen painter and the menu painter to maintain consistency – use 1000 as the first main screen, then increments of a thousand for separate functionality, or increments of a hundred for sub-screens. Don’t use multiples of ten or one unless going to sub-sub-screens, or to distinguish some tiny refinement for a special case.
  • Follow SAP standards for naming module pools, i.e. SAPMZ… for the main program, MZ… for the include modules.

 

2.3 Menus or PF Status

2.3.1 Menus or PF Status Naming Standards

The maximum length for a menu name is 20 characters. The NewellRubbermaid standard for custom menu names will be six characters, with the following format:

Format:   Z…

Where:   Z           =             “Z” represents custom programs.
…         =             Open

Example:             ZMAIN

 

2.4 Function Groups

2.4.1 Function Groups Naming Standards

The maximum length for a function group name is 26 characters. Please make the names meaningful and at the same time keep it short.

Format:                Z_BBCC_

Where:     Z  =     “Z” represents custom programs.
                                     _       = Underscore

                                       BB =           Application area or functional area .

                                        CC  =  Functional subsystem within the application area .

                 _  =   Underscore , Constant.
… =         Open – try and use short  meaningful abbreviations.

Example:   Z_HRPD_DATEF = Human Resources Date Functions,
Z_FIAP_DATE (theoretical case that matches naming convention)

Note: The creation of a function group results in the creation of a main program for the function group called SAPLxxxx, where xxxx is the name of the function group – no matter how long it is, hence the request for short names; e.g. SAPLZPDF, with include modules named LxxxxTOP (Global definitions), LZxxxxUXX (all includes for the individual functions), LZxxxxUnn (include module containing an individual function; “nn” is program assigned code starting at “01” and incrementing as new functions are built in the group), LxxxxF01 (Forms), LxxxxO01 (PBO modules), LxxxxI01 (PAI modules).

2.4.2 Function Groups Design Standards

All logically related function modules should be assigned to the same function group.

Do not attempt to place a new NewellRubbermaid function in an SAP function group – even if it is related!

Do NOT place unrelated functions into the same function group just to avoid creating a new group - it is much cleaner to create a new function group if there is no suitable one available. In fact it may be a great deal more efficient at run time as there is not much point in dragging 20 functions, for example, into memory if only one is required.

It is recommended that if you are building a complex function group that you place related sub-routines in separate include modules LxxxxFnn rather than build one huge include module.

It is imperative for the sake of efficiency that you pass information from the function to the sub-routines via properly typed parameters (including tables – use a type-pool to ensure that you can define the table appropriately in the function parameters) and NOT via global fields.

Global fields should be reserved strictly for items that are used throughout the group such as constants and type-pools. Values stored globally will be retained for the entire run of the calling program – this can be a negative property just as often as it is a positive idea; use with care.

Use locally defined “STATICS” for values that need to be retained for use in a particular function or sub-routine – not a global field. Because a “static” field is locally defined there is no danger of changing it accidentally in another part of the program.

Rely on local variables (except “STATICS” of course) to be “clean” at every new entry to a sub-routine; it is a waste of time to clear them before use. This is one of their great advantages over global variables.

2.5 Function Modules

2.5.1 Function Modules Naming Standards

The maximum length of a function module name is 30 characters. The NewellRubbermaid standard for custom function modules will allow up to 30 characters with the following format:

Format: Z_BBCC_...

Where:                     Z  =     “Z” represents custom programs.
_   =        constant underscore;

             BB   =   Functional Area – refer Appendix A

             CC   =   Functional subsystem within the application area –.

                _   =        constant underscore;
…   =         <up to 25 characters – descriptive of function’s use with abbreviations as required>.

 

Example: Z_FIAP_CHECKWRITE

2.5.1.1       Modifying SAP function groups

  • Copy the function GROUP to a name which has a “Z”, to represent custom development, in front of the original function group name. When prompted to copy the functions you want, uncheck the ones you do NOT want and check the ones to copy and add “Z” at the front of each name you need to use. This will automatically create the appropriate programs with the proper names. Remove the last vowel if the original name was too long to add the “Z” for custom development.

    e.g. To copy the function RP_SALARY_GENERIC_CALC, look up its group (= PARA) and start by copying that to “ZPARA”; you will be prompted immediately to select the functions that you need; SAPLPARA will become SAPLZPARA and the includes will become LZPARA… (e.g. LZPARATOP).
  • Make the necessary changes
  • IF you need to ADD new sub-routines then create an entirely new include module called LZPARAF9N– where “N” is a digit from 0 to 9 or a character from A to Z; this gives you scope for 36 new include modules!

    IF you need new PBO or PAI modules then create new include modules named, e.g. LZPARAO9N or LZPARAI9N.
  • When you are sure that you have finished, use the extended program check to remove unused code. If you did not copy all the routines in the group then is possible that some global data fields and some entire sub-routines will no longer be needed.
  • Always edit and activate a function or function group via Transaction SE80 (or SE37 if you must).
  • After changing or creating a function module, perform an extended syntax check to confirm the changes.
  • All function parameters of all varieties (IMPORT, EXPORT, CHANGED and TABLES) must be typed with data dictionary fields elements or types defined in a type-pool.
  • All data being used in subroutines within the function group MUST be passed to and from the form using properly typed parameters – NOT BY MOVING IT TO A GLOBAL FIELD. This latter habit – much used by SAP :-( is very inefficient, especially for tables and in an extreme case (large record size and large number of lines) can make an hour or more difference to the processing time.
  • The command “IF <outbound parameter, table parameter or change parameter> IS REQUESTED” should be used to avoid the work of calculating outbound values that the caller does not want, e.g. refer to the function ZPDF_GET_P0041_DATES.

    Remember that this command works ONLY in the function module itself and not in any of the include modules of the function group.
  • Remember too that ALL outbound parameters are optional.
  • Use STATICS to retain useful values from one call to the next within a program run rather than a global field that should not be used by any other function in the group.
  • Identify all possible errors that would require the function to hand control back to the caller for a decision and create a suitably named exception.

    When an error occurs, always issue a suitable message with “… RAISING <exception name>” on the end so that the message goes back to the caller for them to decide if they want to use it or not.

    Remember that when you raise an exception you automatically clear all return parameters.
  • If you are providing an input parameter for a field that will normally have a standard value, e.g. Company Code is most likely to be “NewellRubbermaid” = ‘001’, then provide a default value to avoid unnecessary use. On the other hand – make sure you provide a parameter even if the chance of SEATTLE’S BEST COFFEE using it is slim; e.g. see ZSRF_REPORT_HEADER.
  • When you call your function you MUST AT LEAST include the “EXCEPTION OTHERS = <any numeric value>” in the parameter list. You should only need to declare individual exceptions if you have different processing for them.
  • A “flower box” with details of the original author and a history of changes should appear in all modules and includes that make up the function group (e.g. LZxxxTOP, LZxxxF01, LZxxxU01, etc.), except the LZxxxUXX include module which is maintained exclusively by the system.
  • Follow all the guidelines for coding any standard ABAP program.
  • Calls to BAPI should be placed in their own sub-routines in an ABAP program that calls them, and their error return and message fields should be tested immediately after the call.
  • BAPI, like regular functions, should NOT issue messages directly – BUT neither should they raise exceptions. Instead they should set up an error code and a message and hand control back to the caller without having taken any other action.
  • This section will be enlarged in the future, in the meantime – please look at an SAP example and follow the same principles.

2.5.2 Function Module Design Standards

2.5.2.1       Messages, exceptions & a return code – BAPI

 

2.6 Message Classes

Before creating a new message class, check the list of valid message classes in SE91. If you can not find an appropriate class in this list, use the naming standards below to create one.


Description

Message class

Application Link Enabling

ZALE

Electronic Data Interchange

ZEDI

Workflow

ZWKF

Cross Functional

ZXX

Financials (All Modules)

ZFIN

Sales and Distribution

ZSD

Materials Management

ZMM

 

2.6.1 Message Class Naming Standards

See Previous section for message class names used.

2.6.2 Message Design Standards

Always create descriptive, parameterized messages.

No message can have more than 4 parameters; just use an ampersand without any other addition.

To use a parameter in the long text use &V1&, &V2&, &V3& or &V4& to get the corresponding value – the 1, 2, 3, 4 refer to the order the parameters were passed into the message and are not names of the parameters. In the standard SYST fields these values will be found in SY-MSGV1, SY-MSGV2, etc.

  1. N.B.       The long text must be defined

    OR

    the flag labeled “Self-explanatory” on the SE91 screen must be set to say that you do not want a long text.

BEWARE:      If you add a new message to an SAP message group, use numbers GREATER THAN or equal to 900 for the new messages, else SAP may use your number in their next release.

 

2.7 Development Classes or Packages

Development classes have been predefined based on a logical grouping of functional subsystems.

Development Classes or Packages Naming Standards

The maximum length for a development class name is 26 characters.

Format:   ZBB…

Where:      Z        =             “Z” represents custom programs.
BB        =             Functional sub system; see Appendix A..
          =             Free form.

Note: although the above define naming standards for Packages. All names have been predefined in Appendix A.

2.8 Authorization Objects

The SAP security teams will create all custom authorization objects.

Use YZ to represent custom development.


Description

Authorization Objects

Application Link Enabling

YZALE

Electronic Data Interchange

YZEDI

Workflow

YZWKF

Cross Functional

YZXX

Financials (All Modules)

YZFIN

Sales and Distribution

YZSD

Material Master

YZMM

 

2.9 Layout Sets (SAPSCRIPTS)

2.9.1 Layout Sets (SAPSCRIPTS) Naming Standards

The maximum length of a layout set name is 16 characters.

Format:   Z_BBCC_

Where:     Z  =     “Z” represents custom programs.
_   =        constant underscore;

             BB   = Functional Area – refer Appendix A

             CC   =   Functional subsystem within the application area .

                _   =        constant underscore;
…   =         <up to 25 characters – descriptive of function’s use with abbreviations as required>.

Example: Z_FIAP_CHKWRITE

 

2.9.2 Layout Sets (SAPSCRIPTS) Design Standards

Standard SAP layout sets: If there is a need to modify a SAP layout set, and the SAP provided customer enhancement /option is not available, do the following:

Make a custom copy of the layout set by placing a “Z” in front of the SAP layout set (as the first character).

Make the necessary modifications in the custom copy.

 
 

 

2.10 Customer Enhancements (Including user exits)

A SAP repair key is required for modification of a workbench object. To create a custom enhancement:

Use transactions CMOD and SMOD.

Follow SAP standards.

2.10.1 Example of CMOD use

Project: ZHIFTMOD
Components of ZHIFTMOD:    PBAS0001        PA: Personnel Administration/Recruitment; default values and checks.

Function exits:     EXIT_SAPFP50M_001           PBO Module, all code in include zxpadu01
EXIT_SAPFP50M_002           PAI Module, all code in include zxpadu02.

2.10.2 Example of SMOD use

An enhancement includes one or more components (function exits, menu enhancements, screen enhancements). It can have 8 characters. For enhancements, you are recommended to observe the following naming convention:

  • Application:

    1 letter (e.g.  S = Basis)
  • Work area:

    2 digits
  • Sub work area:

    1 letter

You can use any characters for the remaining places. It may be that conventions are established within each department.

Example: ZFPASMOD

2.11 Screens

2.11.1 Screens Naming Standards

A Screen Painter screen name consists of the name of the ABAP program the screen is attached to plus a four-digit screen number. The number range for the screen number depends on whether the ABAP program is a customer-developed screen attached to an SAP program or a customer-developed screen attached to a customer-developed program. The two cases are discussed below.

Format:   A…ABBBB

Where: A…A       =             Program name of the ABAP program (refer to the appropriate section for the naming rules of the program) the screen is attached to.

BBBB     =             Screen number

See below for details

Customer-developed Screens Attached to a Customer-developed Program:

Screen numbers must be between 0001 and 8999. It is recommended that the first screen for a program be numbered 0100 and each additional screen with that program be numbered an increment of 10 above the previous screen; for example, 0100, 0110, 0120.

Customer-developed Screens Attached to a Customer-developed Program:

Screen numbers must be between 0001 and 8999. It is recommended that the first screen for a program be numbered 1000 and each additional screen with that program be numbered an increments of 100 if they are small variations on the first screen, or 1000 if they are quite different; sub-screen numbers should use increments of 10 from the parent screen. Unit intervals will be used as sub-screens of sub-screens – or if you get stuck for a number!

2.12 Data Definitions

2.12.1 Internal Program Data Variables Naming Standards

Data variable names can be up to 32 characters long, with the exception of selection-screen parameters and select-options which can only be 8 characters long. Variable names should be descriptive.

Variables should be named as follows:

Format:   V_...

Where:   V          =             Variable prefix
…          =             <Open>

Prefix

Represents

P_

Parameters for selection screens & sub-routines (within the form – anything goes in the call statement).

S_

Selection screen SELECT-OPTIONS

PR_

Radio button

 

Type of field

Global prefix

Local prefix

Parameter prefix

Constant

C_

LC_

Not applicable

Range

R_

LR_

PR_ (or PT_)

Internal Table

T_

LT_

PT_

Structure (String)

X_

LX_

PX_

Variable

V_

L_

P_

 

2.12.2 Tables and Fields Naming Standards

Table definitions should be formatted as follows. Only one table shall be listed on any one line of the program, and the table description should be added as the end of line comment.

Example:

TABLES:      MARA,   “MATERIAL MASTER DATA

T001,   “Company codes
T100,               “Messages
TDCT,              “Dialog Modules
TAPLT.            “Program application descriptions

Within a table name or within a field name, use an underscore (e.g. CUST_NO or T_LIKP). This will avoid confusion when connecting the table name and field name together with the required hyphen (e.g. T_LIKP-CUST_NO). In general, hyphens should be avoided except in the specific case of connecting a table name to a field name.

Comment work fields and fields in work records, especially those used for interfacing. Define a type first and then use it as appropriate in tables or parameters. Especially when defining internal fields that are to hold values from databases, use “TYPE” and the corresponding Data Dictionary data element name in preference to just the generic type and length to make sure that the variables have identical characteristics.

N.B. “TYPE” is preferred over “LIKE” because it is more efficient (one less look up in the data dictionary) and is the new SAP standard being introduced as part of the drive toward object oriented code. The exception is in a selection screen parameter definition where LIKE will pick up check table values for the input and “TYPE” will not.

Example:

TYPES: BEGIN OF partner_name,
REC_TYPE            TYPE CHAR01,    "interface type ind.
PERNR                  TYPE P_PERNR, "partner number
NAME                   TYPE EMNAM,   "formatted name
END OF partner_name.
DATA:   X_PNAME_REC TYPE partner_name,
T_PNAME TYPE STANDARD TABLE OF partner_name.

For each field, include a comment after the field describing the use – unless the name is unambiguously obvious.

Example:

DATA:                   V_LIFNR TYPE LIFNR.      “Vendor a/c number

  • Use TYPE-POOLS for data structures that will be used in more than one ABAP program or are required for function parameters.
  • Fully declare each field unless TYPE or LIKE is used. Do not let the data type or the length default. For fields that are whole numbers, it is not necessary to define them with zero decimal places.

 

2.12.3 Text Elements Design Standards

Do not use hard-coded literals. Use Text Elements to handle literal text that is printed on a report; e.g.

WRITE: / ‘Write some sort of message or heading on this line’(XYZ).

The advantage of using Text Elements is easier maintainability and speed of the program. The labels are alphanumeric.

* Do NOT use Text Elements for constants - constants should be defined in a “CONSTANTS” statement.

Literal text MUST BE defined as in the example above.

After the first use of a text (as above) the successive uses of the same text must say “WRITE: / TEXT-XYZ” – it does not matter where in the code the various uses of the text are; e.g. the definition may be on line 55 and the reuse on line 42.

DO NOT TYPE THE TEXT INTO THE TEXT ELEMENT FILE – LET THE SYSTEM DO THAT FOR YOU. When you have finished typing the program with all its texts defined as above then, from within the program, go to the menu option “GOTO, TEXT ELEMENTS, TEXT SYMBOLS” then “UTILITIES, ADJUST, TEXT SYMBOLS” and the system will create or adjust the text elements for you. Easier than entering the text yourself AND it documents the code automatically without you having to place a comment on the line!

Selection Texts:Ensure that all the selection-options and parameters have a corresponding text in the selection texts. Also ensure that there are no additional selection texts .

abapOpenChecks - Open source checks SAP Code Inspector / ATC

$
0
0

Over the last 6 months I've been working on a set of custom checks for code inspector, the project is available on github.

 

Currently it contains the following general purpose checks, some complex and some simple.

 

CHECK_01 - IF in IF

CHECK_02 - EXIT outside of loop

CHECK_03 - TRY without CATCH

CHECK_04 - Line length

CHECK_05 - 7 bit ASCII

CHECK_06 - Check for use of pretty printer

CHECK_07 - Functional writing style for CALL METHOD

CHECK_08 - Obsolete statement

CHECK_09 - Tab instead of spaces

CHECK_10 - Use icon_ constants

CHECK_11 - Max one statement per line

CHECK_12 - Specify SORT order

CHECK_13 - Sequential blank lines

CHECK_14 - Commented code

CHECK_17 - Definitions in top of routine

CHECK_18 - Empty branch

CHECK_19 - Use LINE OF

CHECK_20 - Bad indentation

CHECK_21 - Unused FORM parameter

CHECK_22 - Conditions contain identical code

CHECK_23 - CHECK outside of loop

CHECK_24 - Identical code blocks

CHECK_25 - Selection screen data not referenced statically

CHECK_26 - No direct changes to standard tables

 

You can configure code inspector or ATC to use these checks in your default variant.

checks.png

 

The checks are provided "AS IS", some might not fit your development requirement, and some might be slow or not even work.

This is a box of chocolates; take the ones you like . Some of the checks contains settings so it is possible to change to fit your requirements.

 

Feel free to submit pull requests or open issues. More checks will be added over time.

 

https://github.com/larshp/abapOpenChecks

Viewing all 948 articles
Browse latest View live


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