naimesh.patel

9 Posts
Today, we will explore about the Single Responsibility Principle. 


Definition: 
According to Robert C. Martin, Single Responsibility Principle (SRP) by definition is: There would not be more than one reason to change the class. Class would always represent only one responsibility. Here responsibility is the reason tot change the class.

We must not create a single class which has more than one responsibility. If the class has more than one responsibility, than that would be more than one reason to change that class. Classes with more than one responsibility would have a tendency to break more easily than the classes with less responsibility. Whenever, we do the changes in multi responsibility classes, we have to make sure we don’t break the other responsibility of that class - more responsibilities leads to more testing.


Example:
image
We have to develop a simple report to select the data and than display this data as an ALV. If we design only one single class ZCL_REPORT to achieve this requirement, than we are giving more than one responsibility to this class: 1) Data Selection, 2) Output of DATA (ALV). Clearly, there are two reasons which lead to change this class: Change in Data selection (e.g. changing the formula to calculate the net price) and change in ALV processing (e.g. adding a provision to display default variant). There is no clear distinction between the attributes which belong to which responsibility and we might change them accidentally. So, we need to test the entire class and make sure we haven’t broken this functionality.

We can avoid this risk by segregating both responsibilities in separate classes: class for data selection ZCL_DATA_SELECT & class for ALV ZCL_OUTPUT_ALV. Since we have different classes, we don’t have to worry about making accidental update in the other classes’ attributes. We can still create a class ZCL_REPORT which uses both data selection ZCL_DATA_SELECT and ALV ZCL_OUTPUT_ALV classes.
image


Dilemma: 
SRP seems to be the simplest principle but it is one of the hardest to get right. Segregating the responsibilities would depend always on the developer. One could still find more than one responsibility in the data selection class ZCL_DATA_SELECT: data selection from DB ZCL_DATA_DB & Data manipulation ZCL_DATA_PROCESS. Class Data selection from DB ZCL_DATA_DB would be still segregated in to more than one responsibility: data selection for each individual sub objects like Class to select material data ZCL_MATERIAL, class to select Customer data ZCL_CUSTOMER etc. We need to find the optimal segregation of the responsibilities between our classes.

In the previous post of the series Object Oriented Design Principles, we have seen:
1) Object Oriented Design Principles (OODP): Open-Closed Principle(OCP)
2) Object Oriented Design Principles (OODP): OCP with Business Scenario

 

Definition:
By Definition, Dependency Inversion Principle (DIP) is: Depend upon Abstractions. Do not depend upon concretions.

 

Problem with the Procedural design:
Procedural designs exhibit always particular type of dependency. In the procedural programming, there would be always some code blocks which are repetitive. Like in the example, we have a program which has different set of the interfaces like interface to create Sales Order (as shown in the blog post: Object Oriented Design Principles (OODP): OCP with Business Scenario), Purchase Order etc. Program structure have some CONCRETE code blocks which makes it very RIGID. As shown in this diagram, we can’t use the Validation of the sub objects in more than one interface because it is wrapped in the concrete code block or FM.

image

 

Concrete classes are rigid, where as using interfaces make the design flexible. So, if we follow the object oriented design using proper abstraction we can remove the rigidity of the code and make our code blocks more reusable. Moreover, we can extend the abstract classes or interfaces to have new functionality and we can achieve the Open Closed Principle (OCP).

 

 

Achieving DIP:
Every dependency should depend on the Interface or Abstraction class. There should be no dependency targeted on the concrete classes. For example, we would try to work on the object reference created with reference to abstract class or interface. We should try to define the method parameters, attributes with reference to abstract class or interface. There should not be direct reference of the concrete class.

We will try to explore the same example, as we have seen in the previous post Object Oriented Design Principles (OODP): OCP with Business Scenario. Method VALIDATE_KEYS of the class LCL_SO is not reusable. We can’t use that method in another object to achieve the same functionality, unless we instantiate the SO object and call the method. This makes the design little bit rigid. Let’s see how we can overcome this problem by following DIP.

Let's check the UML diagram for this design:

image

 

To achieve the DIP in the same example, we can create an abstract class ZCL_AB_ORDER which contains all the common functionality e.g. VALIDATE method & common attributes e.g. table for sub-objects T_SUBOBJ. Based on this abstract class, we can inherit all main classes e.g. class for sales order ZCL_SALES_ORDER, class for purchase order ZCL_PURCHASE_ORDER etc. The attribute T_SUBOBJ will hold the object reference of the sub-objects like Material, Customer, Vendor etc.

Subclasses of the abstract class ZCL_AB_ORDER 

image

 

For the sub-objects, we can create an interface ZIF_SUBOBJ which contains method definitions for common methods for the sub-objects like method VALIDATE_KEY. Use this interface in all the sub-objects like Material ZCL_MATERIAL, customer ZCL_CUSTOMER, Vendor ZCL_VENDOR etc. We can implement object specific validation in the inherited method from the ZIF_SUBOBJ e.g. material number validation against material master (table MARA) etc.

Subclasses of subobject interface ZIF_SUBOBJ:

image

 

We can create a utility class ZCL_UTILITIES which has some generic methods e.g. VALIDATION. This method can accept any object inherited from the abstract class ZCL_AB_ORDER. We can check all the sub-objects’ method VALIDATE_KEY to call the object specific validation.

Implementation of Method VALIDATION:

image

 

We call this method VALIDATION from the method VALIDATE of the abstract class ZCL_AB_ORDER. Since the parameter of the VALIDATION method depend on the abstract class ZCL_AB_ORDER, we can use this method with any object reference which is inherited from the abstract class ZCL_AB_ORDER. As a input of the method ZCL_UTILITES=>VALIDATION we are passing the current object (ME).

image

You can find the class design, implementation and test report in WIKI Object-Oriented Design Principle - Dependency Inversion Principle Example

 

Conclusion:
* Abstraction would help us to create more reusable methods like VALIDATE in class ZCL_AB_ORDER and VALIDATION in class ZCL_UTILITIES.
* Code would lose the rigidity and become more flexible, which would lead to easy maintenance.
* We achieved DIP - Removed the dependency on the actual concrete class.

 

Credits:
Robert C. Martin

In the previous post Object Oriented Design Principles (OODP): Open-Closed Principle(OCP) of the series OODP, we have seen how we can achieve the OCP using Shape object like Square, Circle. In this blog post, we will see how we can use the Open-Closed Principle in business scenario.

As noted in the previous post thumb rule for OCP is: We can add new features in the module without changing the existing code (CLOSED) but by adding new code (OPEN).

 

Requirement:
There is a need for a data upload program to create a sales order. Flat file would be the source of the data for this program. We are getting some fields in the flat file like Customer number, Material number, Plant etc. Obviously, it is required to validate the input before calling the BAPI to create the sales order. For this example, we would concentrate on the validation part. We will use the polymorphism to achieve the OCP for this requirement.

 

UML diagram would look like this:

image

 

To realize this requirement, we would create an interface LIF_SUBOBJ for common methods which we can use in different classes like Customer LCL_KUNNR, Material LCL_MATNR, etc. Definition of the interface and interface impelementing classes:

 

Method IS_VALID in the customer class LCL_KUNNR validates the customer number against the customer master KNA1. Method IS_VALID in the material class LCL_MATNR validates the material number against the material master MARA.
Implementation for these classes LCL_KUNNR, LCL_MATNR:

 

Public attribute LT_OBJ of class LCL_SO is an internal table which holds the reference of different objects like Customer LCL_KUNNR, Material Number LCL_MATNR etc. Method VALIDATE_KEYS of the class LCL_SO calls the method IS_VALID of each object reference of the table LT_OBJ attribute. We will use down cast from the object reference in LT_OBJ to object reference of LIF_SUBOBJ. Definition and Implementation of the sales order class LCL_SO is:

 

Full code sinppet of the program could be found here. For completion purpose, I have included local class based exception in this coding.

 

Change in Requirement:
After successful validation of the object, it required to set some attributes of the each object. E.g. set the customer name attribute of the object customer. We will achieve this added requirement without any modification of the method VALIDATE_KEYS.

By adding a new method SET_ATTRIBUTES in the interface LIF_SUBOBJ, it will be available in all implementing classes like LCL_KUNNR, LCL_MATNR. Call this method inside the LOOP of objects after key validation in the method VALIDATE_KEYS. Updated UML will look like this:

image

And updated code snippet can be found here.

 

Conclusion:
Method VALIDATE_KEYS is closed for any modification:
* Achieve the same functionality (e.g. validating the object key) by creating a new class implementing LIF_SUBOBJ (e.g. LCL_WERKS for Plant validation)
* Add a new common functionality (e.g. saving data into Ztable) by creating a new method in the interface (e.g. method SAVE_DATA_TO_ZTAB in class LIF_SUBOBJ)

We need to follow the Design principle while developing the software to reduce the TCO (Total Cost of Ownership), Reduce the Cost of maintenance and for robust design.

 

Definition:
The name itself sounds like contradicting – OPEN & CLOSE, but by definition, A module should be OPEN for extension but CLOSED for modification. The Open-Closed Principle (OCP) is one of the most important Design Principle. OCP originated from the work of by the Bertrand Meyer.

 

In simple words: We can add new features in the module without changing the existing code (CLOSED) but by adding new code (OPEN).  By following this principle, we can make sure that by changing the code in the method we are not going to break existing functionality. Let us try to see it using the example.

 

Example:
First of all we would see the code which doesn’t follow this principle. Consider we have a class which prints the shape information of different shapes based on the input.
image

Code snippet which violates this principle.

 

Now the problem with this code is, when ever we need to add a new type of Shape, we need to change the code in the CREATE_SHAPE, WRITE_SHAPE method, which is clear violation of the OCP. According to OCP, we should only change the method to add new functionality. Here we are not adding a new functionality. Creation of the Shape Object and writing the information of the different Shape is not a new functionality. So, we must re-design our class and methods to be able to follow the Open Closed Principle.

 

We can use the dynamic polymorphism to achieve Open-Closed design. Check the UML for the new design.

image

Now we would create an interface LIF_SHAPE which we will use to create different shapes like circle using LCL_CIRCLE, square using LCL_SQUARE and so on.

 

Implementation of the class LCL_CIRCLE and LCL_SQUARE implements the method

 

Design of the report class is also changed. LCL_REPORT would now accept the class name instead of the simple type to instantiate required object as the parameter of the method CREATE_SHAPE.

 

Implementation of the class LCL_REPORT needs to be changed. CREATE_SHPAE would create the object and WRITE_SHAPE would call the method WRITE_SHAPE from the object O_SHAPE.

 

Full code Snippet which shows how to achieve OCP design.

 

Now, if we want to add a new shape, say TRIANGLE. We can easily add a new shape without changing any existing code.
1. Create a new class LCL_TRIANGLE which implements the interface LIF_SHAPE
2. Implement the method LIF_SHAPE~WRITE_SHAPE in this class.

 

Conclusion:
By using the polymorphism, now both methods CREATE_SHAPE & WRITE_SHAPE of the class LCL_REPORT are CLOSED for any modification and we have successfully achieved OCP design.


Credits:
Bertrand Meyer
Robert C. Martin

 

Preface:

 

 

Today’s blog

The specified item was not found.

from Alvaro Tejada  (https://wiki.sdn.sap.com/wiki/x/nDk) has reminded me that we can also use the XML to create formatted, fancy Excel files using ABAP and XML.

 

The advantages of the XML technique over the OLE:

    • Using XML we can send the fancy generated file as an Email Attachment.

    • We can create formatted excel file using the XML technique from the Web applications generated using Web Dynpro or BSP.

    • It’s faster compared OLE technique

 

We can use the CALL TRANSFORMATION  (http://help.sap.com/saphelp_nw04s/helpdata/en/e3/7d4719ca581441b6841f1054ff1326/frameset.htm) to convert our internal table data to the formatted Excel. As release 6.10, ABAP run time environment contains the XSLT processor for executing the transformation. Alternativly, we can use CONCATENATE syntax to XML string using the XML tags and the data, but it would be as clean as CALL TRANSFORMATION.

 

 

 

Code to Generate sample Excel

 

 

*&----


*

*& Report  ZTEST_NP_EXCEL_XML

*&

*& Download the formatted excel file using XML

*&----


*

 

REPORT  ztest_np_excel_xml.

 

TYPES: BEGIN OF ty_mara,

       matnr TYPE matnr,

       maktx TYPE char30,

       END   OF ty_mara.

 

DATA: itab TYPE STANDARD TABLE OF ty_mara,

      la_tab LIKE LINE OF itab,

      xmlstr TYPE string.

 

START-OF-SELECTION.

 

*----


  • Test table

*----


  la_tab-matnr = 'TEST1'.

  la_tab-maktx = 'Test description'.

  APPEND la_tab TO itab.

 

  la_tab-matnr = 'TEST2'.

  la_tab-maktx = 'Test description 2'.

  APPEND la_tab TO itab.

 

*----


  • Get the XML data excel

*----


  CALL TRANSFORMATION ztest_np_xls

    SOURCE table = itab

    RESULT XML xmlstr.

 

*----


  • Download the file

*----


 

 

  • Fill the table

  DATA: xml_table TYPE STANDARD TABLE OF string.

 

  APPEND xmlstr TO xml_table.

 

  DATA: window_title TYPE string,

        fullpath TYPE string,

        path TYPE string,

        user_action TYPE i,

        default_extension TYPE string,

        default_file_name TYPE string,

        file_filter TYPE  string,

        filename TYPE string,

        initialpath TYPE string.

 

  • File selection

  MOVE '.XLS' TO default_extension.

  MOVE 'XLS files (.XLS)|.XLS' TO file_filter.

 

  CALL METHOD cl_gui_frontend_services=>file_save_dialog

    EXPORTING

      default_extension = default_extension

      default_file_name = default_file_name

      file_filter       = file_filter

      initial_directory = initialpath

    CHANGING

      filename          = filename

      path              = path

      fullpath          = fullpath

      user_action       = user_action

    EXCEPTIONS

      cntl_error        = 1

      error_no_gui      = 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.

 

  • download file

  CALL FUNCTION 'GUI_DOWNLOAD'

    EXPORTING

      filename                = fullpath

      filetype                = 'ASC'

    TABLES

      data_tab                = xml_table

    EXCEPTIONS

      file_write_error        = 1

      no_batch                = 2

      gui_refuse_filetransfer = 3

      invalid_type            = 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.

 

 

 

 

XML transformation</p><p><textarea cols="60" rows="20"><?sap.transform simple?>

<?mso-application progid="Excel.Sheet"?>

<tt:transform xmlns:tt="http://www.sap.com/transformation-templates">

 

  <tt:root name="table"/>

 

  <tt:template>

    <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html=

"http://www.w3.org/TR/REC-html40">

      <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">

        <Author>npatel</Author>

        <LastAuthor>npatel</LastAuthor>

        <Created>2009-01-01T22:27:09Z</Created>

        <Company></Company>

        <Version>11.8132</Version>

      </DocumentProperties>

      <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">

        <WindowHeight>12660</WindowHeight>

        <WindowWidth>19980</WindowWidth>

        <WindowTopX>480</WindowTopX>

        <WindowTopY>120</WindowTopY>

        <ProtectStructure>False</ProtectStructure>

        <ProtectWindows>False</ProtectWindows>

      </ExcelWorkbook>

      <Styles>

        <Style ss:ID="Default" ss:Name="Normal">

          <Alignment ss:Vertical="Bottom"></Alignment>

          <Borders></Borders>

          <Font></Font>

          <Interior></Interior>

          <NumberFormat/>

          <Protection></Protection>

        </Style>

        <Style ss:ID="s23">

          <Font ss:Bold="1" ss:Size="26" x:Family="Swiss"></Font>

          <Interior ss:Color="#FFFF99" ss:Pattern="Solid"></Interior>

        </Style>

      </Styles>

 

      <Worksheet ss:Name="Sheet1">

        <Table ss:ExpandedColumnCount="3" ss:ExpandedRowCount="25" x:FullColumns="1" x:FullRows="1">

          <Column ss:Width="152.25"/>

          <Column ss:Width="180"/>

          <Column ss:Width="117"/>

          <Row>

            <Cell ss:StyleID="s23">

              <Data ss:Type="String">Material No</Data>

            </Cell>

            <Cell ss:StyleID="s23">

              <Data ss:Type="String">Material Desc</Data>

            </Cell>

          </Row>

          <tt:loop ref=".table">

            <Row>

              <Cell>

                <Data ss:Type="String">

                  <tt:value ref="MATNR"/>

                </Data>

              </Cell>

              <Cell>

                <Data ss:Type="String">

                  <tt:value ref="MAKTX"/>

                </Data>

              </Cell>

            </Row>

          </tt:loop>

        </Table>

        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">

          <Selected/>

          <Panes>

            <Pane>

              <Number>3</Number>

              <ActiveRow>4</ActiveRow>

              <ActiveCol>1</ActiveCol>

            </Pane>

          </Panes>

          <ProtectObjects>False</ProtectObjects>

          <ProtectScenarios>False</ProtectScenarios>

        </WorksheetOptions>

      </Worksheet>

      <Worksheet ss:Name="Sheet2">

        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">

          <ProtectObjects>False</ProtectObjects>

          <ProtectScenarios>False</ProtectScenarios>

        </WorksheetOptions>

      </Worksheet>

      <Worksheet ss:Name="Sheet3">

        <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">

          <ProtectObjects>False</ProtectObjects>

          <ProtectScenarios>False</ProtectScenarios>

        </WorksheetOptions>

      </Worksheet>

    </Workbook>

 

  </tt:template>

 

</tt:transform>

</textarea> </p><p>Output:<br />This test program will generate the formatted excel like this:

image

 

 

 

How to get the proper STYLE tag definition for particular formatting:

 

1. Create an test excel file in the MS Excel with the required formatting

2. Save the file as the XML file.

3. Open the file using the Notepad to know the Style

For example: Font-size 26, Background Color yellow will get us this Style

image

4. Change the XML transformation accordingly

Like:

!https://weblogs.sdn.sap.com/weblogs/images/47199/2_xml_style.png|height=284|alt=image|width=477|src=https://weblogs.sdn.sap.com/weblogs/images/47199/2_xml_style.png|border=1!</body>

We all know that ABAP Object is very powerful over the classical ABAP. Here I want to share one of my best experiments with the ABAP objects to overcome the restrictions of SALV mdoel.

 

Background
I was reading the help on the CL_SALV_TABLE to get more insight of how to use this new SALV model effectively. When I came across the section Recommendation and Restriction, I was amazed by reading "Tables displayed with ALV are not ready for input".

image

It was very hard for me to understand this restriction because: The new SALV model is unified object oriented model which has kind of wrapper classes which are ultimately calling the FM REUSE_ALV_GRID_DISPLAY or REUSE_ALV_LIST_DISPLAY; class GL_GUI_ALV_GRID and so on. So, if the ALV created with the CL_GUI_ALV_GRID can be ready for input, why can’t the ALV created with the SALV model be the "Ready for input"? This propelled me to analyze how we can make the ALV Full-screen as "Set ready for Input".

 

Journey to find the solution
By putting breakpoints and debugging, I came to know that when I tried to generate the fullscreen ALV, it calls the FM REUSE_ALV_GRID_DISPLAY and this FM in turn uses the class CL_GUI_ALV_GRID to generate the ALV.

Before couple of months, I came across a very powerful function module GET_GLOBALS_FROM_SLVC_FULLSCR which gives us the object of type GL_GUI_ALV_GRID which was created to generate the fullscreen ALV. I have used this FM in couple of programs to achieve some functionality which is not possible using the FM REUSE_ALV_GRID_DISPLAY. Some of them:

Basically, to achieve this type of not achievable functionality of the Fullscreen ALV, I get the object using the FM GET_GLOBALS_FROM_SLVC_FULLSCR and use the methods available in the CL_GUI_GRID_DISPLAY followed by the refresh method to refresh the ALV.

 

Based on the assumption - if I get the ALV object from the SALV model than I can make the SALV model ALV to "Set Ready for input" -  I have started searching the ALV object in the SALV model. At the very top node of the SALV model CL_SALV_MODEL, I got the methods (GET_GRID) which can provide me the ALV grid object.

UML diagram contains the SALV hierarchy and visibility of the R_CONTROLLER:

image

Class CL_SALV_MODEL has a protected attribute R_CONTROLLER which has everything I need to get to GRID object. So, I tried to access that attribute directly, but obviously I didn’t work as I didn’t have the object reference for the CL_SALV_MODEL. By this point of time, I have tried all the normal ways to get the access the R_CONTROLLER - like Feild-symbol to access the object from memory but that didn't work either. 

 

Solution
I knew that I have to think in a different way, and I tried to inherite the class from the class CL_SALV_MODEL_LIST, passed the ALV model to the class and tried to access the R_CONTROLLER and BINGO - I am able to access the R_CONTROLLER in my inherited class.

UML Diagram shows the iherited class along with the existing SALV model:

image

 

Steps to follow:
1. Inherited a local class LCL_SALV_MODEL from the CL_SALV_MODEL_LIST
2. Generate SALV model to generate the ALV object
3. Used narrow casting to get the CL_SALV_MODEL object from the ALV object
4. Passed this CL_SALV_MODEL object to the inherited class LCL_SALV_MODEL. Since LCL_SALV_MODEL is inherited from the CL_SALV_MODEL_LIST, it allows me to access the R_CONTROLLER of the CL_SALV_MODEL.
5. Get the GRID object from the object MODEL -> Controller -> Adapter -> Grid.
6. Set the Layout for EDIT and Refresh the ALV.

 

When we run the report, ALV will not come directly in the input mode:
image

As soon as we press the "My Function" button, ALV will change into editable ALV. This ALV will have its separate GUI Status which contains all the required buttons for the Editable ALV.
image

 

Code Snippet
UML diagram for code snippet:

image

 

Here is the code, which I used to get the access of the GRID object from the SALV model and to make ALV editable. Here I have used the PF-STATUS avaliable in the report program SALV_DEMO_TABLE_EVENTS for easy installation of this demo report.


 

Example 2: Background Wallpaper in ALV created using SALV model
When we pass the parameter I_BACKGROUND_ID in the function module REUSE_ALV_GRID_DISPLAY, we will get the background wallpaper in the top of page section of the ALV.

SALV model uses the class CL_SALV_FORM_DYDOS to generate the TOP-OF-PAGE header from the SALV Form object (CL_SALV_FORM). CL_SALV_FORM is used to generate the Header in the SALV model.

When SALV model creates an object for the CL_SALV_FORM_DYDOS, it doesn’t pass the Wallpaper picture. Thus, we are not able to get the header background wallpaper in the SALV model.

To get the wallpaper in the header, we can use the same solution which we have used to make Editable ALV.

ALV header without wallpaper using the SALV model:

image

ALV header with the wallpaper using the SALV model:

image

 

Code snippet to get the header with the wallpaper:

Get the Header in the SALV:

Set the background wallpaper by accessing the GRID and TOP-of-LIST object

Naimesh Patel

LSMW with RFBIBL00

Posted by Naimesh Patel Aug 14, 2008

In the ABAP Forum, there are couple of questions unanswered related to LSMW using standard program RFBIBL00 to post the FI documents. That inspried me to write this Blog.

Step 1: Maintain Object Attributes
For creating the FI document with the RFBIBL00 using LSMW, we have to select the object 0100, method 0000 and program RFBIBL00.

image

Step 2: Maintain Source Structures
We will create total two structures: One for header and another for item. We could have at least two line items in the FI document. So, we need to upload at least 2 records per document. To upload 2 records, we should able to pass those two records in the mapping as well as in the conversion.

Create a structure with name ZFI_HEAD for the Header (BKPF).

image

Under the ZFI_HEAD, create another structure ZFI_ITEM for items (BSEG). Put cursor on the ZFI_HEAD and press the create button to create lower level structure ZFI_ITEM.

image

Step 3: Maintain Source Fields
We need to have one link field which will link the Header record with the Item record which system will use later to link the records from both different files.

These are the fields for the ZFI_HEAD structure:

image

These are the fields for the ZFI_ITEM structure:

image

Step 4: Maintain Structure Relations
Here we will define the structure relationship between source structure (BGR00, BBKPF, BBSEG, etc) and target structure (ZFI_HEAD, ZFI_ITEM, etc).

image

Step 5: Maintain Field Mapping and Conversion Rules
Assign all the fields from the ZFI_HEAD to respective fields from BBKPF and ZFI_ITEM to respective fields from BBSEG. Don't assign the CNT field to any of the field.
Make sure we pass correct formatted date (YYYMMDD) to the BBKPF.

image

Step 6: Maintain Fixed Values, Translations, User-Defined Routines
We don't to maintain anything in field.

Step 7: Specify Files
Create 2 files: 1 for header, 1 for Item. Sequence of the fields in the Structure must be same as the fields in the file. You can download my test files: Header and Item.

Create a header file.

image

Create another file for the Items in the same fashion.

You can change the names of the Read and Conversion files.

image

Step 8: Assign Files
Assign the files to the structures.

 

image

Step 9: Read data
Read the files specified in the Step 7

Step 10: Display read data
Displaying read data

Step 11: Convert Data
Run the convert data report to convert the input data to .conv file

Step 12: Display Converted Data

Step 13: Run program
Run program RFBIBL00 to create a session.

image

 

Use BBTAX:

  • To use the BBTAX structure also in the RFBIBL00, we need to create another structure (e.g. FI_TAX) under the ZFI_HEADER and same level of ZFI_ITEM.
  • As ZFI_ITEM (BBSEG) and FI_TAX (BBTAX) are at the same level so, we can use the same CNT field to link them.
  • Create a Separate file as we have created for the header and item.

Use BWITH:

  • BWITH is the subitem level data for the FI document. With-holding tax data is attached to the line item. So, we need to create a child structure under the ZFI_ITEM.
  • Since we have created the structure at child level, we need another field to link the item data to the withholding tax data.
  • Create a separate field as we have created for the header and item.

 

I'm on Google+. Follow me on Google+ .

Naimesh Patel

Watermark in SAPScript

Posted by Naimesh Patel May 22, 2008


On the other day, I was reading through SCN and this question came up. There wasn’t any suitable answer, which can get the watermark in SAPScript. So, I decided to give a try. I have tried couple of times with different techniques like calling the subroutine which SmartForm uses for background processing from SAPScript, putting the graphics in various windows and call them from driver program, etc. But today, I got a good solution, which I thought would be useful to everybody.

How it looks with Watermark?
image

There are couples of hurdles in the way to get it working:

First is the Graphics:
Watermark Graphics should have some specific property. This kind of graphics should not have the “Reserve Height Automatically” as ON in their attributes.
image

Whenever we import any .bmp file as the graphics in the SE78, system by default sets the indicator “Reserve Height Automatically” as ON. So, when we include this graphics in our SAPScript, system will reserve predefined space on the page which will prevent the next line to print in that space.

The Graphics with the “Reserve Height Automatically” as ON generates output like this:
image


Second is how to get the watermark on each page:
To get the graphics on every page we have couple of options:
Option 1: Create a GRAPHICS window on the center of the page and include the watermark.
This option is not working because: System starts the processing of the windows in the sequence maintained on the page window of SAPScript. So, Main window will be executed before Graphics window. This will overlap the content of the main window by the Graphics (which is not our purpose).
image


Option 2: Call a Graphics inside the MAIN window.
This option seems to work with little logic to print the watermark on each page.

I have attached my SAPScript, Little driver program code and the test watermark image for your reference.

SAPScript:
You can save this block as .txt file and use report RSTXSCRP to import into your system. You need to save this SAPScript with name ZTEST_WATERMARK.

Code:
Here is the simple driver program.

Watermark Image:
I have used this image for my testing:
image

Note: I have tried this on ECC 5.0. I am not sure about other systems.

Naimesh Patel

Marbles Game in ABAP

Posted by Naimesh Patel May 7, 2008
Marbles Game, a fun and simple variation of the famous Chinese Checkers Game!

Try to remove all but one marble from the board. You can remove a marble by skipping over it to an empty spot. Select a marble by clicking on it and move it by selecting the spot that you want to move to. (Caution: highly addictive...)

How it looks? 

image

And the ABAP code is here.

Hope you will enjoy it..!!