We can help. Together we learn....

In very few developments we need Dynamic Where Condition for data base (DB) queries. Meaning; during runtime your program may decide which all fields of the data base table to be used for the DB query. We can very well write our custom code for developing those Dynamic Where Condition. But we know the effort and pain it takes to write such a code or else we can use a Standard SAP function module CRS_CREATE_WHERE_CONDITION to achieve the requirement.


Sample Example:

Lets consider, we have a program which will follow some logic and finally it comes to the conclusion that it will have to do a query on Data Base table MARA based on the fields MATNR (Material Number) and MTART (Material Type). There could be some other possible fields based on which the query can be made and this will be decided at run time. The table fields and their corresponding values can not be know until run time . So we need a Dynamic Where Condition for the Data Base Query. In such a condition you may choose to explore all possible combinations of fields to be used in the where condition and write your custom code to manufacture a Dynamic Where Condition or you can just use a Function Module (FM) which will do the job you.

We will discuss the above situation considering a program, with a selection screen having both the fields MATNR and MTART. (Let us assume these two fields and their corresponding values will be not be available until runtime).


REPORT z_dynamic_where_condition.

* Types
TYPES: BEGIN OF x_mara,
matnr TYPE matnr, "Material Number
mtart TYPE mtart, "Material Type
END OF x_mara.

DATA:
* Internal table
l_i_range TYPE STANDARD TABLE OF crmselstr,
l_i_output TYPE STANDARD TABLE OF mcondition,
l_i_mara TYPE STANDARD TABLE OF x_mara,

* Work area
l_wa_range TYPE crmselstr,

* Variable
v_matnr TYPE mara-matnr,
v_mtart TYPE mara-mtart.


* Selection Screen
SELECT-OPTIONS: s_matnr FOR v_matnr,
s_mtart FOR v_mtart.

* For Select Option 1
LOOP AT s_matnr. "Looping to get multiple (single) values
l_wa_range-table = 'MARA'. "Name of the DB table
l_wa_range-field = 'MATNR'. "Field name the user has selected
l_wa_range-sign = s_matnr-sign. "Sign
l_wa_range-option = s_matnr-option."option
l_wa_range-low = s_matnr-low. "Lower Value
l_wa_range-high = s_matnr-high. "Higher Value
APPEND l_wa_range TO l_i_range.
ENDLOOP..

* For Select Option 2
LOOP AT s_mtart. "Looping to get multiple (single) values
CLEAR l_wa_range.
l_wa_range-table = 'MARA'. "Name of the DB table
l_wa_range-field = 'MTART'. "Field name the user has selected
l_wa_range-sign = s_mtart-sign. "Sign
l_wa_range-option = s_mtart-option. "option
l_wa_range-low = s_mtart-low. "Lower Value
l_wa_range-high = s_mtart-high. "Higher Value
APPEND l_wa_range TO l_i_range.
ENDLOOP.


IF NOT l_i_range[] IS INITIAL.

* Call the FM to create the Dynamic Where condition
CALL FUNCTION 'CRS_CREATE_WHERE_CONDITION'
TABLES
ti_range = l_i_range
to_cond = l_i_output
EXCEPTIONS
invalid_input = 1
OTHERS = 2.

IF sy-subrc = 0.

* Special way to write the query
SELECT matnr "Material Number
mtart "Material Type
FROM mara
INTO TABLE l_i_mara
WHERE (l_i_output).

IF sy-subrc = 0.

ENDIF.

ENDIF. "IF sy-subrc = 0: SELECT matnr mtart

ENDIF. "IF NOT l_i_range[] IS INITIAL.

******************************************************************
** You may need an Dynamic Internal table in such a scenario.
So find here the link for the same **

http://help-sap.blogspot.com/search/label/Internal%20table
******************************************************************

Ever tried it. It is not so simple :)


Method 1
--------------
a) Create a subscreen area in your screen layout where you want to create the select options.
b) In the top include of  your module pool program declare a selection screen as a subscreen e.g.
       SELECTION-SCREEN BEGIN OF SCREEN 100 AS SUBSCREEN.
             select-options s_matnr for mara-matnr.
       SELECTION-SCREEN END OF SCREEN.
c) In the PBO and PAI of the main screen where the select options needs to be created do a call subscreen of the above screen (100).
       CALL SUBCREEN sub_area INCLUDING    
  This call subscreen statement is necessary for transport of values between screen and program.

Note: All validations of the selection screen fields e.g. the s_matnr field created above should be done in selection screen events like AT SELECTION-SCREEN etc and not in PAI. These selection screen validations etc should be done in the top include only.

Method 2
---------------
a) Create 2 separate fields in your screen layout - one for the low value and one for the high value. Insert an icon beside the high value which will call the multiple selections popup screen on user command. Use function module COMPLEX_SELECTIONS_DIALOG to achieve this. 

struc_tab_and_field-fieldname   = con_cust.      " 'KUNNR'
struc_tab_and_field-tablename = con_kna1.     " 'KNA1'.

CALL FUNCTION 'COMPLEX_SELECTIONS_DIALOG'
          EXPORTING
*           TITLE                   = ' '
            text                         = g_titl1                                " 'Customers'
            tab_and_field     = struc_tab_and_field
          TABLES
            RANGE                   = rng_kunnr
          EXCEPTIONS
            NO_RANGE_TAB          = 1
            CANCELLED                    = 2
            INTERNAL_ERROR     = 3
            INVALID_FIELDNAME = 4
            OTHERS                           = 5.

IF NOT rng_kunnr[] IS INITIAL.
*          Read the very first entry of the range table and pass it to
*          dynpro screen field
           READ TABLE rng_kunnr INDEX 1.
           IF sy-subrc = 0.
              g_cust = rng_kunnr-low.
           ENDIF.

You can use the return table rng_kunnr to populate your own internal range table with the values entered by the user. Basically here you are just simulating the work of a select-options parameter by module pool screen elements.

Sometimes we have specific requirements while designing a selection screen. We may have to place more than one Parameter (or Select Option or Radio Button). This can be easily done by using the selection screen BEGIN OF LINE / END OF LINE statements.

The following code extract will help you in designing such a selection screen.

*** Start of Code ***
DATA: l_field TYPE char10,
l_pos TYPE char4.

SELECTION-SCREEN BEGIN OF BLOCK out WITH FRAME TITLE text-s01.
* Line 1
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 5(15) text-010 FOR FIELD p_field1.
PARAMETERS: p_field1 LIKE l_field.
SELECTION-SCREEN COMMENT 45(15) text-011 FOR FIELD p_pos11.
PARAMETERS: p_pos11 LIKE l_pos.
SELECTION-SCREEN COMMENT 75(15) text-012 FOR FIELD p_pos12.
PARAMETERS: p_pos12 LIKE l_pos.
SELECTION-SCREEN END OF LINE.

*** End of Code ***

Output:


Instead of Parameters, you can easily have other elements like Radio Buttons or Select Options. The important thing here is that you need to keep the correct spacing and position or else you can get a selection screen generation error during activating the code, even if your code is syntactically correct.

Value entered in the selection screen, displayed automatically by the function module is nice tabular fashion. Very helpful when the selection screen is huge having a lot of parameters and select options.

 

*----------------------------------------------------------------------*
* T A B L E S *
*----------------------------------------------------------------------*
TABLES: mara.
*----------------------------------------------------------------------*
* S E L E C T I O N S C R E E N *
*----------------------------------------------------------------------*
SELECTION-
SCREENBEGIN OF BLOCK b2 WITH FRAME.
SELECT-OPTIONS: mat FOR mara-matnr NO INTERVALS.
SELECT-OPTIONS: mtype FOR mara-mtart NO INTERVALS.
SELECTION-
SCREENEND OF BLOCK b2.

END-OF-SELECTION.
WRITE:/ 'Thank you'.

TOP-
OF-PAGE.
DATA: i_sel TYPE STANDARD TABLE OF rsparams INITIAL SIZE 0.
  
IF sy-pagno EQ 1.
* Call function for getting selection screen details
    
CALL FUNCTION 'RS_REFRESH_FROM_SELECTOPTIONS'
      
EXPORTING
        curr_report     = sy-cprog
      
TABLES
        selection_table = i_sel
      
EXCEPTIONS
        not_found       = 
1
        no_report       = 
2
        
OTHERS          = 3.
    
IF sy-subrc <> 0.
      
WRITE:/ 'Fails to get the selection screen details'(201).
    
ENDIF.

* Displaying selection screen details
    
CALL FUNCTION 'RS_LIST_SELECTION_TABLE'
      
EXPORTING
        
report        = sy-cprog
        seltext       = 
'X'
        screennr      = 
' '
      
TABLES
        sel_tab       = i_sel
      
EXCEPTIONS
        sel_tab_empty = 
1
        
OTHERS        = 2.
    
IF sy-subrc <> 0.
      
WRITE:/ 'Fails to display the selection screen details'(202).
    
ENDIF.
  
ENDIF.




Restricting range entry for select-option.

by Voice | Thursday, November 06, 2008 in | comments (2)

Sometime it is required to restrict range input for a select option.  SAP provides an extension which is generally used for this is NO INTERVALS.

 Code:SELECT-OPTIONS: mat FOR mara-matnr NO INTERVALS.

 Apparently it seem that requirement is met but if someone presses multiple selection tab, a pop screen will open and there user can enter the range. This can also be restricted by using a function module SELECT_OPTIONS_RESTRICT.

 Example code:

**********************************************************************
* TYPE-POOLS:
**********************************************************************
TYPE-POOLS: sscr.
*----------------------------------------------------------------------*
* T A B L E S *
*----------------------------------------------------------------------*
TABLES: mara.
*----------------------------------------------------------------------*
* S E L E C T I O N S C R E E N *
*----------------------------------------------------------------------*
SELECTION-
SCREENBEGIN OF BLOCK b2 WITH FRAME.
SELECT-OPTIONS: mat FOR mara-matnr NO INTERVALS.
SELECT-OPTIONS: mtype FOR mara-mtart NO INTERVALS.
SELECTION-
SCREENEND OF BLOCK b2.

*---------------------------------------------------------------------*
* Initialization Event
*---------------------------------------------------------------------*
INITIALIZATION.

  
CONSTANTS: lc_opt_list TYPE rsrest_opl VALUE 'OPT_LIST',
             lc_s        
TYPE rsscr_kind VALUE 'S',
             lc_mat      
TYPE blockname  VALUE 'MAT',
             lc_inc      
TYPE c          VALUE 'I'.

  
DATA: lw_opt_list TYPE sscr_opt_list,
         lw_restrict 
TYPE sscr_restrict,
         lw_ass      
TYPE sscr_ass.

  lw_opt_list-name       = lc_opt_list.
  lw_opt_list-options-bt = space.
  lw_opt_list-options-
eq = 'X'.
  
APPEND lw_opt_list TO lw_restrict-opt_list_tab.

  lw_ass-kind    = lc_s.
  lw_ass-name    = lc_mat.
  lw_ass-sg_main = lc_inc.
  lw_ass-op_main = lc_opt_list.
  
APPEND lw_ass TO lw_restrict-ass_tab.

  
CALL FUNCTION 'SELECT_OPTIONS_RESTRICT'
    
EXPORTING
      restriction            = lw_restrict
    
EXCEPTIONS
      too_late               = 
1
      repeated               = 
2
      selopt_without_options = 
3
      selopt_without_signs   = 
4
      invalid_sign           = 
5
      empty_option_list      = 
6
      invalid_kind           = 
7
      repeated_kind_a        = 
8
      
OTHERS                 = 9.




   With NO INTERVALS command. After pressing multiple selection tab you can enter range value.









After restricting with the function module you can not enter range value now.

There are other option available in this function module. Explore and enjoy :)

Dynamic selection screen

by Voice | Thursday, November 06, 2008 in | comments (0)

Selection screen is the first thing which user can see when he/she executes a program or transaction. For basic need, we can create a selection screen only by using ABAP commands and we do not have to go for a module pool programming.

 

There are some extensions which can be used with select option to meet the requirement.

Please check F1 for the extensions and their effects.

Some it is required to populate a default value in the selection screen. There is an ABAP command which can be used for this.

Eg. SELECT-OPTIONS: matn FOR mara-matnr DEFAULT 'AA'.

 

# Sometime the default value needs to be calculated at run-time. Use Initialization Event or At Selection-screen output Event.

 

Dynamic Selection Screen: You can active a field or can disable input to a certain field depending on some criteria at your will. The following code may help you to make a dynamic screen. There are several other option in SCREEN structure. Explore and you can impress some user by producing a flashy selection screen. Remember selection screen is the first impression of your program.

 

TABLES: mara.

*----------------------------------------------------------------------*
* S E L E C T I O N S C R E E N *
*----------------------------------------------------------------------
SELECTION-
SCREENBEGIN OF BLOCK b1 WITH FRAME.
PARAMETERS : mat RADIOBUTTON GROUP opt1 DEFAULT 'X' USER-COMMAND aa.
PARAMETERS : mtype RADIOBUTTON GROUP opt1.
SELECTION-
SCREENEND OF BLOCK b1.
SELECTION-
SCREENBEGIN OF BLOCK b2.
SELECT-OPTIONS: matn FOR mara-matnr DEFAULT 'AA'
                MODIF 
ID a.
SELECT-OPTIONS: mtypen FOR mara-mtart MODIF ID b.
SELECTION-
SCREENEND OF BLOCK b2.
*----------------------------------------------------------------------*
* AT S E L E C T I O N S C R E E N O U T P U T *
*----------------------------------------------------------------------
AT SELECTION-SCREEN OUTPUT.
  
LOOP AT SCREEN.
    
IF mat = 'X'.
      
IF screen-group1 = 'B'.
        
screen-input = 0.
      
ENDIF.
    
ELSE.
      
IF screen-group1 = 'A'.
        
screen-active = 0.
      
ENDIF.
    
ENDIF.
    
MODIFY SCREEN.
  
ENDLOOP.

Transport ABAP Report Variants

Some times it is required to transport the selection variants (created for a report program) from one environment to another. We will discuss this requirement with a sample scenario.


Steps to be followed.

Step 1) Execute transaction SE38 and give the name of the program as:


Step 2) In the same screen check the radio button “Variants” and click on Display
pushbutton or follow menu path Goto -> Variants as:


Step 3) In the next screen thus appears; follow the menu path Utilities -> Transport
request.. as:


Step 4) Execute (F8) the program thus appears in the next screen as:


Step 5) Up on execution a pop up would appear asking for selecting the variants
(saved against that report program) to be transported as:

(We can select the variants we need and exclude the others)


Step 6) Up on pressing Continue, a next pop up appears; asking for the transport
details as:

Here we can choose our own transport to move the selection
variants for the report program from one environment to another.

ABAP CRM Tips

by Biswa | Tuesday, November 04, 2008 in , | comments (3)

Tip 1: Opening CRM Order in a new window

When there is a requirement to open a CRM Order (Customer Order. Service Order. etc.) from a program, the normal process is to populate the Business Object Parameter (CRM_OBJECT_ID) with the Transaction Number (OBJECT_ID) and then doing a CALL TRANSACTION to CRMD_ORDER. But this method does not seem to work.

SET PARAMETER ID 'CRM_OBJECT_ID' FIELD .
CALL TRANSACTION 'CRMD_ORDER' AND SKIP FIRST SCREEN.

It will not get into the transaction (CRM Order) , but stop at the search screen

The way around could be using the BAPI BAPI_BUSPROCESSND_DISPLAY to display the CRM Order. You can use it to display the CRM Order screen directly. Just pass your Order Header GUID ID to the business process and the CRMD_ORDER screen will be displayed.

CALL FUNCTION 'BAPI_BUSPROCESSND_DISPLAY'
EXPORTING
business_process = <order_header_guid>

Tip 2: Inserting or Deleting Standard / Custom messages in CRM GUI.

If possible, you can follow the following steps.

a) First delete message, for example


* Deleting the messages from stack

CALL FUNCTION 'CRM_MESSAGES_DELETE'
EXPORTING
iv_caller_name = gc_object_name-order
iv_ref_object = iv_item
it_r_msgidno = lt_idno
EXCEPTIONS
OTHERS = 1.


b) Check for corresponding message text already exists or not, for example


CALL FUNCTION 'CRM_TEXT_READ_API'
EXPORTING
it_guid = lt_object_guids
iv_object_kind = gc_object_kind-orderadm_i
IMPORTING
et_text = lt_text.

OR,

Search the corresponding messages, for example,

ls_idno-sign = 'I'.
ls_idno-option = 'EQ'.
ls_idno-low-msgid = 'Z_ZZZ_CA_MESSAGES'.
ls_idno-low-msgno = '126'.

APPEND ls_idno TO lt_idno.

CALL FUNCTION 'CRM_MESSAGES_SEARCH'
EXPORTING
it_r_msgidno = lt_idno
iv_ref_object = iv_header_guid
iv_ref_kind = gc_object_kind-orderadm_h
iv_only_errors_on_object = true
IMPORTING
et_msg_info = lt_msg_info
EXCEPTIONS
appl_log_error = 1
error_occurred = 2
OTHERS = 3.


c) If message does not exist .Then raise message. for example


CALL FUNCTION 'CRM_MESSAGE_COLLECT'
EXPORTING
iv_caller_name = gc_object_name-order
iv_ref_object = iv_item
iv_ref_kind = gc_object_kind-orderadm_i
iv_logical_key = 'MAINTAIN'
iv_msgno = lv_msgno
iv_msgid = 'CRM_ORDERADM_I'
iv_msgty = lv_msgty
EXCEPTIONS
not_found = 1
appl_log_error = 2
OTHERS = 3.


Sending Inbound IDocs from a SAP Program

by Biswa | Tuesday, November 04, 2008 in , | comments (3)

In most cases, the inbound IDoc to SAP is generated by an external system (say XI) and passed on to SAP. The inbound IDoc is then processed using the process code / corresponding function module. But in certain cases, due to the client requirements, the interface program needs to be designed in such a way that the Inbound IDoc originates from within the same SAP system i.e. both the sending and receiving system are the same.

Now mostly in such requirements, we generally generate the IDoc after reading data from a flat file. The file is passed to the application server by a middleware (say XI). The SAP interface program reads the file from the application server and then starts processing the data. To create the inbound IDoc, we need to use the Function Module ‘IDOC_INBOUND_WRITE_TO_DB’. This creates and saves the IDoc to the database.

The control record information for the inbound IDoc is passed to pc_control_record (Similar to EDIDC – IDoc control record). In the control records, all relevant information like status (53); receiver port, receiver partner no.; sender port; sender partner no etc are populated. All the IDoc data is passed to internal table t_data_records (Similar to EDIDD – IDoc control record). The IDoc data is read from the incoming file and processed and then populated to internal table itab_data_records_db with segment name etc.

The inbound process data is passed to the function module.

CALL FUNCTION 'IDOC_INBOUND_WRITE_TO_DB'
exporting
pi_do_handle_error = 'X'
pi_return_data_flag = ' '

importing
pe_idoc_number = control_record_db_in-docnum
pe_inbound_process_data = wa_inbound_process_data_in

tables
t_data_records = itab_data_records_db
changing
pc_control_record = control_record_db_in
exceptions
idoc_not_saved = 1
others = 2.


Now if the inbound IDoc has been successfully created and we want to process the same, the function module ‘IDOC_START_INBOUND’ can be used. Here we pass the inbound process data containing the IDoc process code and event code to wa_inbound_process_data_in. The status and release are added to the control records internal table i_control_records.

CALL FUNCTION 'IDOC_START_INBOUND'
exporting
pi_inbound_process_data = wa_inbound_process_data_in
pi_called_online = 'X'
succ_show_flag = 'X'

tables
t_control_records = i_control_records
exceptions
others = 1.

If we have no exception, then the IDoc will be successfully processed and have status ‘53’.


Link to this post on our new blog : http://www.sapyard.com/sending-inbound-idocs-from-a-sap-program/

Categories