*Get all the schedule details by doingSELECT * INTO TABLE xvbap FROM vbapWHERE vbeln = '7500000028'AND posnr = '000010'.SELECT * INTO TABLE xvbup FROM vbupWHERE vbeln = '7500000028'AND posnr = '000010'.SELECT * INTO TABLE xvbfa FROM vbfaWHERE vbelv = '7500000028'AND posnv = '000010'AND vbtyp_n = 'J'.SELECT * INTO TABLE da_vbep FROM vbepWHERE vbeln = '7500000028'AND posnr = '000010'.CALL FUNCTION 'RV_SCHEDULE_CHECK_DELIVERIES'EXPORTINGfbeleg = '7500000028'fposnr = '000010'* FVERRECHNUNG = ' '* FS073_ALT = ' '* IF_NO_SORT = ' 'TABLESfvbfa = xvbfafvbup = xvbupfxvbep = da_vbep* FVBLB =fvbap = xvbapEXCEPTIONSfehler_bei_lesen_fvbup = 1fehler_bei_lesen_fxvbep = 2OTHERS = 3.
Wednesday, April 22, 2009
Check delivery status
Tuesday, April 14, 2009
Read the domain value ranges
Sometimes we need to display the description based on the key value of a field. And the description is not in a text table but defined as value range in the domain definition. For example the domain XUDATFM lists all the types of dates possible
Using the class CL_ABAP_ELEMDESCR, one can retrieve these values in an internal table of type DDFIXVALUES. Here is an example:
DATA o_rtti_attr TYPE REF TO cl_abap_elemdescr.DATA t_fixed_values TYPE ddfixvalues.TRY.rtti_attr ?= cl_abap_typedescr=>describe_by_name( 'XUDATFM' ).CATCH cx_root. "#EC *
ENDTRY.* get the fixed valuesCALL METHOD rtti_attr->get_ddic_fixed_valuesRECEIVINGp_fixed_values = fixed_valuesEXCEPTIONSno_ddic_type = 1OTHERS = 2.
Thursday, April 09, 2009
Dynamic where conditions in select
I had a problem in work where I would be selecting from tables that are decided on run time and also the where conditions on these tables are to be decided on run time. I found a lot of examples where one could create a dynamic internal table using the RTTS for INTO clause of SELECT. This was only half the solution to my problem. i still have to dynamically create as many where conditions as possible. The syntax of a dynamic select is:
We have four components in the above SQL query that can be given at run time:SELECT (columns) INTO CORRESPONDING FIELDS OF TABLE (Internal Table Name)FROM (Table Name)WHERE (Where String containing conditions)
- Columns. We don’t worry about this as the clause ‘INTO CORRESPONDING FIELDS’ will only pick the fields that are common in the internal table and the database table.
- Internal Table: This is achieved by following the example here.
- Table name: The calling service knows what table to select from.
- Where string containing conditions: This is the problem that is to be solved!
What I intend to do is let the calling program send me any number of ranges and its respective column name. So there will be an internal table (RANGES_TABLE) of the following structure:
Taking the example of table T001:BEGIN OF ranges_tables,tablename TYPE tabname16,fieldname TYPE fieldname,range TYPE REF TO data,END OF ranges_table.
Let’s populate RANGES_TABLE with two criteria, ORT01 and LAND1. We want to get table entries where ORT01 = ‘Walldorf’ and LAND1 = ‘DE’.
RANGES_TABLE now has a list of columns that we need to select from with the conditions respectively. But the user can send one column or two columns or (n) columns. This is will be solved by dynamically creating a structure that will have fields referring to different ranges. The structure will look like this:* 1* Create range for ORT01s_ort01-sign = 'I'.s_ort01-option = 'EQ'.s_ort01-low = 'Walldorf'.APPEND s_ort01 TO r_ort01.* Add entry in the Ranges tables_ranges_table-tablename = 'T001'.s_ranges_table-fieldname = 'ORT01'.CREATE DATA s_ranges_table-range LIKE r_ort01.ASSIGN s_ranges_table-range->* TO <range>.<range> = r_ort01.APPEND s_ranges_table TO t_range_table.* 2* Create range for LAND1s_land1-sign = 'I'.s_land1-option = 'EQ'.s_land1-low = 'DE'.APPEND s_land1 TO r_land1.* Add entry in the Ranges tables_ranges_table-tablename = 'T001'.s_ranges_table-fieldname = 'LAND1'.CREATE DATA s_ranges_table-range LIKE r_land1.ASSIGN s_ranges_table-range->* TO <range>.<range> = r_land1.APPEND s_ranges_table TO t_range_table.
Having creating a structure we create dynamic where conditions. So now the select query will be as follows:BEGIN OF select_strucfield1 TYPE range1..fieldn TYPE rangenEND OF select_struc
Here is the full list of the method that does all this:SELECT * INTO TABLE <l_rows>FROM (s_ranges_table-tablename)WHERE field1 IN select_struc-field1..AND fieldn IN select_struc-fieldn
METHOD select_from_ranges.DATA:l_index TYPE i,l_t_dyn_field TYPE abap_component_tab,l_s_dyn_field LIKE LINE OF l_t_dyn_field,l_str_range_name TYPE string,l_str_sel_option TYPE string,l_o_structdescr TYPE REF TO cl_abap_structdescr,l_d_range_str TYPE REF TO data,l_s_table_range LIKE LINE OF i_t_range.FIELD-SYMBOLS:<l_rows> TYPE ANY TABLE,<l_dyn_range_str> TYPE ANY,<l_range_tbl> TYPE table,<l_range_tbl2> TYPE table.* For all the where conditions sent* create fields in the select strucutureLOOP AT i_t_range INTO l_s_table_range._index = sy-tabix.ASSIGN l_s_table_range-range->* TO <l_range_tbl>.* Create dynamic fieldCLEAR:l_s_dyn_field.l_s_dyn_field-name = l_s_table_range-fieldname.l_s_dyn_field-type ?= cl_abap_datadescr=>describe_by_data( <l_range_tbl> ).APPEND l_s_dyn_field TO l_t_dyn_field.CONCATENATE '<l_dyn_range_str>-' l_s_table_range-fieldname INTO l_str_range_name.* More than one where requires in ANDIF l_index > 1.CONCATENATE l_str_sel_option 'AND'INTO l_str_sel_option SEPARATED BY space.ENDIF.CONCATENATE l_str_sel_option l_s_table_range-fieldname 'in' l_str_range_nameINTO l_str_sel_option SEPARATED BY space.ENDLOOP.* Create dynamic structure with fields pointing to different rangel_o_structdescr = cl_abap_structdescr=>create( p_components = l_t_dyn_field ).CREATE DATA l_d_range_str TYPE HANDLE l_o_structdescr.ASSIGN l_d_range_str->* TO <l_dyn_range_str>.* For all the fields in the structure point them to the range tablesWHILE sy-subrc IS INITIAL.ASSIGN COMPONENT sy-index OF STRUCTURE <l_dyn_range_str> TO <l_range_tbl2>.IF sy-subrc IS NOT INITIAL.EXIT.ENDIF.READ TABLE i_t_range INTO l_s_table_range INDEX sy-index.ASSIGN l_s_table_range-range->* TO <l_range_tbl>.<l_range_tbl2> = <l_range_tbl>.ENDWHILE.ASSIGN c_rows->* TO <l_rows>.* Select from the tableSELECT * INTO TABLE <l_rows>FROM (l_s_table_range-tablename)WHERE (l_str_sel_option).ENDMETHOD.
Friday, April 03, 2009
Date formatter class
One useful class SAP has provided recently is the date formatter class to manage different type of dates that one encounters in the wild. So converting from external to internal formats and vice-versa is better now.
The class in question is CL_ABAP_DATFM. The following date formats are supported at the moment:
1 DD.MM.YYYY
2 MM/DD/YYYY
3 MM-DD-YYYY
4 YYYY.MM.DD
5 YYYY/MM/DD
6 YYYY-MM-DD
7 GYY.MM.DD
8 GYY/MM/DD
9 GYY-MM-DD
A YYYY/MM/DD
B YYYY/MM/DD
C YYYY/MM/DD
One example in which I am using it is converting from say format of DD.MM.YYYY to SAP’s internal format of YYYYMMDD.
TRY.CALL METHOD cl_abap_datfm=>conv_date_ext_to_intEXPORTINGim_datext = '01.01.2009'im_datfmdes = '1' " DD.MM.YYYY
IMPORTINGex_datint = sapdate.CATCH cx_abap_datfm_no_date cx_abap_datfm_invalid_datecx_abap_datfm_format_unknown cx_abap_datfm_ambiguous .* Invalide date formatENDTRY.