How can I retrieve Customer Master Data from a report and print it?
I have the Customer Number but I don't know what is the best approach to retreive other details such as:
Name
Street Address
Communication
(in the future also Contact Persons)
In my research I've found as options:
Doing a query on KNA1 and other Customer Master Data Tables
BAPI_CUSTOMER_GETLIST
BAPI_CUSTOMER_GETDETAIL2
I need a snippet of code that can print Customer master in a report.
You could try function module BAPI_CUSTOMER_GETDETAIL2, it returns CUSTOMERADDRESS.
More importantly, I found this in less than a minute by
Starting transaction BAPI
Clicking on the 'Alphabetical' tab
Find Customer (good guess on my part, but not too hard a guess)
Stare at the methods and see that only GETDETAIL, GETDETAIL1 & GETDETAIL2 are likely
Double click on GETDETAIL2 (number at the end means the version)
Notice the name of the Function Module in the right hand Detail Pane.
My shoulder surfing fellow coder tells me that you could also simply have queried BAPI_CUSTOMER_* since the BAPI's you found clearly follow a pattern.
As to the snippet, you should at least try and let us know where you fail.
DATA : wa_address TYPE bapicustomer_04.
PARAMETERS p_kunnr TYPE kunnr.
CALL FUNCTION 'BAPI_CUSTOMER_GETDETAIL2'
EXPORTING
customerno = p_kunnr
IMPORTING
customeraddress = wa_address.
WRITE: wa_address-name , wa_address-name_2 , wa_address-city , wa_address-country.
I would use a query, try this:
report ZKNA1.
tables: kna1.
type-pools slis.
data gt_fieldcat type slis_t_fieldcat_alv with header line.
data: gs_layout type slis_layout_alv,
g_repid type sy-repid.
types: begin of st_output,
kunnr type kna1-kunnr,
name1 type kna1-name1,
city1 type adrc-city1,
city2 type adrc-city2,
street type adrc-street,
tel_number type adrc-tel_number, " If you need more fields add them here and in the field catalog
end of st_output,
gt_tbl_data type standard table of st_output.
data gt_output type standard table of st_output.
data g_count type i.
data t_heading type slis_t_listheader.
selection-screen: begin of block b2 with frame title text-t01.
select-options s_kunnr for kna1-kunnr.
select-options s_name1 for kna1-name1.
selection-screen: end of block b2.
initialization.
g_repid = sy-repid.
start-of-selection.
perform get_data.
perform build_alv.
form init_layout.
gs_layout-zebra = 'X'.
gs_layout-detail_popup = 'X'.
endform. "init_layout
form get_data.
field-symbols <wa_gt_output> type st_output.
data zlen type i.
select
kna1~kunnr
kna1~name1
adrc~city1
adrc~city2
adrc~street
adrc~tel_number
from kna1
left join adrc on adrc~addrnumber = kna1~adrnr
into corresponding fields of table gt_output
where
kna1~kunnr in s_kunnr and
kna1~name1 in s_name1
order by
kna1~kunnr
.
g_count = sy-dbcnt.
endform. " GET DATA
form build_alv.
* ALV required data objects.
data: w_title type lvc_title,
w_comm type slis_formname,
w_status type slis_formname,
x_layout type slis_layout_alv,
t_event type slis_t_event,
t_fieldcat type slis_t_fieldcat_alv,
t_sort type slis_t_sortinfo_alv.
refresh t_fieldcat.
refresh t_event.
refresh t_sort.
clear x_layout.
clear w_title.
* Layout
perform init_layout.
* Field Catalog
perform set_fieldcat using:
1 'KUNNR' 'KUNNR' 'KNA1' 25 space space space space space space space space space space space t_fieldcat,
2 'NAME1' 'NAME1' 'KNA1' 25 space space space space space space space space space space space t_fieldcat,
3 'CITY1' 'CITY1' 'ADRC' 25 space space space space space space space space space space space t_fieldcat,
4 'CITY2' 'CITY2' 'ADRC' 25 space space space space space space space space space space space t_fieldcat,
5 'STREET' 'STREET' 'ADRC' 25 space space space space space space space space space space space t_fieldcat,
6 'TEL_NUMBER' 'TEL_NUMBER' 'ADRC' 25 space space space space space space space space space space space t_fieldcat.
* Top of page heading
perform set_top_page_heading using t_heading[] t_event.
* Events
perform set_events using t_event.
* GUI Status
w_status = ''.
g_repid = sy-repid.
* User commands
w_comm = 'USER_COMMAND'.
* Order
* Example
* PERFORM set_order USING '<field>' 'IT_DATA' 'X' space space t_sort.
call function 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = g_repid
is_layout = gs_layout
it_fieldcat = t_fieldcat
it_sort = t_sort
i_callback_pf_status_set = w_status
i_callback_user_command = w_comm
i_save = 'X'
it_events = t_event
i_grid_title = w_title
TABLES
t_outtab = gt_output
EXCEPTIONS
program_error = 1
others = 2.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
endif.
endform. " build_alv
form set_top_page_heading using t_heading type slis_t_listheader
t_events type slis_t_event.
data: x_heading type slis_listheader,
x_event type line of slis_t_event.
clear x_heading.
x_heading-typ = 'S'.
x_heading-key = 'Count: '.
x_heading-info = g_count.
append x_heading to t_heading.
* Top of page event
x_event-name = slis_ev_top_of_page.
x_event-form = 'TOP_OF_PAGE'.
append x_event to t_events.
endform. "set_top_page_heading
form set_events using t_events type slis_t_event.
data: x_event type line of slis_t_event.
**
* Example
* -------
* clear x_event.
* x_event-name = .
* x_event-form = .
* append x_event to t_event.
**
endform. "set_events
form set_order using p_fieldname p_tabname p_up p_down p_subtot
t_sort type slis_t_sortinfo_alv.
data: x_sort type slis_sortinfo_alv.
clear x_sort.
x_sort-fieldname = p_fieldname.
x_sort-tabname = p_tabname.
x_sort-up = p_up.
x_sort-down = p_down.
x_sort-subtot = p_subtot.
append x_sort to t_sort.
endform. "set_order
form set_fieldcat using
p_colpos "Column position.
p_fieldname "Field of internal table
p_ref_fieldname "(Optional) Table field / data element
p_ref_tabname "(Optional) Table which holds the field referenced
p_outputlen "(Optional) Column width
p_noout "(Optional) If set to 'X', states that the field is not showed initially
p_seltext_m "(Optional) Medium label
p_seltext_l "(Optional) Long label
p_seltext_s "(Optional) Small label
p_reptext_ddic "(Optional) Extra small (heading) label
p_ddictxt "(Optional) Set to 'L', 'M', 'S' or 'R'
p_hotspot "(Optional) If set to 'X', this field will be used as a hotspot area for cursor
p_showasicon "(Optional) If set to 'X', this field will be shown as an icon
p_checkbox "(Optional) If set to 'X', this field will be shown as a checkbox
p_edit "(Optional) If set to 'X', this field will be editable.
p_dosum "(Optional) If set to 'X', this field will be summed (aggregation function)
t_fieldcat type slis_t_fieldcat_alv. "Table which contains the whole fieldcat.
data: wa_fieldcat type slis_fieldcat_alv.
clear wa_fieldcat.
* General settings
wa_fieldcat-fieldname = p_fieldname.
wa_fieldcat-col_pos = p_colpos.
wa_fieldcat-no_out = p_noout.
wa_fieldcat-hotspot = p_hotspot.
wa_fieldcat-checkbox = p_checkbox.
wa_fieldcat-icon = p_showasicon.
wa_fieldcat-do_sum = p_dosum.
if p_ref_tabname is initial.
wa_fieldcat-rollname = p_ref_fieldname.
else.
wa_fieldcat-ref_tabname = p_ref_tabname.
if p_ref_fieldname eq space.
wa_fieldcat-ref_fieldname = wa_fieldcat-fieldname.
else.
wa_fieldcat-ref_fieldname = p_ref_fieldname.
endif.
endif.
* Set output length.
if not p_outputlen is initial.
wa_fieldcat-outputlen = p_outputlen.
endif.
* Set text headers.
if not p_seltext_m is initial.
wa_fieldcat-seltext_m = p_seltext_m.
endif.
if not p_seltext_l is initial.
wa_fieldcat-seltext_l = p_seltext_l.
endif.
if not p_seltext_s is initial.
wa_fieldcat-seltext_s = p_seltext_s.
endif.
if not p_reptext_ddic is initial.
wa_fieldcat-reptext_ddic = p_reptext_ddic.
endif.
if not p_ddictxt is initial.
wa_fieldcat-ddictxt = p_ddictxt.
endif.
* Set as editable or not.
if not p_edit is initial.
wa_fieldcat-input = 'X'.
wa_fieldcat-edit = 'X'.
endif.
append wa_fieldcat to t_fieldcat.
endform. "set_fieldcat2
form top_of_page.
call function 'REUSE_ALV_COMMENTARY_WRITE'
exporting
* i_logo = <<If you want to set a logo, please,
* uncomment and edit this line>>
it_list_commentary = t_heading.
endform. " alv_top_of_page
form user_command using r_ucomm like sy-ucomm
rs_selfield type slis_selfield.
* Executes a command considering the sy-ucomm.
case r_ucomm.
when '&IC1'.
if rs_selfield-fieldname eq 'KUNNR'.
set parameter id 'KUN' field rs_selfield-value.
call transaction 'XD03' and skip first screen. " Call transaction
else.
message 'Wrong column' type 'I'.
endif.
endcase.
endform. "user_command
Check that you could double click in client code and the program sends you transaction 'XD03'.
Related
I have a dynpro screen with two input fields:
The sales order n°
The sales order line n° (in a dropdown list)
My problem is that the sales order line isn't refreshed after a different sales order n° is input. However the other output fields relating to the sales order line are properly refreshed with the expected data.
Program behavior:
"Document vente" is "Sales order". "Poste" is "Line number".
From this screen, If I request sales order number 1, the order line 10 remains active and shows up in the dropdown list, despite order number 1 not having a line number 10. The other output fields are updated with the data of line 20. If I pick line orders 20, 30 or 70, the value 10 disappears from the list.
The dynpro screen fields are named as their corresponding fields from the VBAK and VBAP tables, so that their values are copied automatically from one to another.
The code followed by the comment "Set order line to first one in the order" doesn't seem to work. I expect it to replace the value of the line number field with the first line number in the new order.
The code:
MODULE REFRESH_ALL_FIELDS INPUT.
DATA temp_vbeln TYPE VBAK-VBELN.
temp_vbeln = VBAK-VBELN.
CLEAR: VBAK, VBAP.
SELECT VBELN KUNNR BSTNK NETWR WAERK
FROM VBAK
INTO CORRESPONDING FIELDS OF VBAK
WHERE VBAK~VBELN = temp_vbeln.
ENDSELECT.
" Fill dropdown list with order line numbers.
TYPE-POOLS VRM.
DATA it_posnr TYPE VRM_VALUES.
REFRESH it_posnr.
SELECT POSNR
FROM VBAP
INTO TABLE it_posnr
WHERE VBAP~VBELN = VBAK-VBELN.
CALL FUNCTION 'VRM_SET_VALUES'
EXPORTING
ID = 'VBAP-POSNR'
VALUES = it_posnr
* EXCEPTIONS
* ID_ILLEGAL_NAME = 1
* OTHERS = 2
.
IF SY-SUBRC <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
" Set order line number as first in the order.
SELECT SINGLE POSNR
FROM VBAP
INTO VBAP-POSNR
WHERE VBAP~VBELN = VBAK-VBELN.
PERFORM REFRESH_ITEM_FIELDS.
ENDMODULE. " REFRESH_ALL_FIELDS INPUT
MODULE REFRESH_ITEM_FIELDS INPUT.
PERFORM REFRESH_ITEM_FIELDS.
ENDMODULE. " REFRESH_ITEM_FIELDS INPUT
FORM REFRESH_ITEM_FIELDS .
SELECT SINGLE MATNR ARKTX KWMENG
FROM VBAP
INTO CORRESPONDING FIELDS OF VBAP
WHERE VBAP~VBELN = VBAK-VBELN
AND VBAP~POSNR = VBAP-POSNR.
ENDFORM. " REFRESH_ITEM_FIELDS
Flow logic:
PROCESS BEFORE OUTPUT.
PROCESS AFTER INPUT.
FIELD VBAK-VBELN MODULE REFRESH_ALL_FIELDS ON REQUEST.
FIELD VBAP-POSNR MODULE REFRESH_ITEM_FIELDS ON REQUEST.
How can I fix this ?
The dynpro flow logic statement FIELD vbak-vbeln MODULE ... ON REQUEST permits only to change "easily" the value of the screen field VBAK-VBELN, i.e. the value of the global variable VBAK-VBELN will be "transported" in both directions, from the screen to the ABAP program, and vice versa.
If you want to change another screen field, like VBAP-POSNR, you must call the function module DYNP_VALUES_UPDATE:
TYPES tt_dynpread TYPE STANDARD TABLE OF dynpread WITH DEFAULT KEY.
DATA(dynpfields) = VALUE ty_dynpread_s(
( fieldname = 'VBAP-POSNR'
fieldvalue = vbap-posnr ) ).
CALL FUNCTION 'DYNP_VALUES_UPDATE'
EXPORTING
dyname = sy-repid
dynumb = sy-dynnr
TABLES
dynpfields = dynpfields
EXCEPTIONS
OTHERS = 8.
Another solution is to declare a "chain" of fields, you may then change those fields directly inside the module without calling DYNP_VALUES_UPDATE:
CHAIN.
FIELD: vbak-vbeln, vbap-posnr.
MODULE ... ON REQUEST.
ENDCHAIN.
But that would require to execute the same code for both fields.
Here is the way how you can do it without creating a dynpro, just with pure selection screen:
TYPES: BEGIN OF ty_order,
vbeln TYPE vbak-vbeln,
erdat TYPE vbak-erdat,
netwr TYPE vbak-netwr,
kunnr TYPE vbak-kunnr,
END OF ty_order,
BEGIN OF ty_pos,
vbeln TYPE vbap-vbeln,
posnr TYPE vbap-posnr,
matnr TYPE vbap-matnr,
arktx TYPE vbap-arktx,
kwmeng TYPE vbap-kwmeng,
END OF ty_pos.
DATA: i_order TYPE TABLE OF ty_order WITH EMPTY KEY,
i_pos TYPE TABLE OF ty_pos WITH EMPTY KEY,
i_aux TYPE TABLE OF ty_pos WITH EMPTY KEY,
list TYPE vrm_values.
PARAMETERS: order TYPE vbak-vbeln AS LISTBOX VISIBLE LENGTH 80 USER-COMMAND ord,
position TYPE vbap-posnr AS LISTBOX VISIBLE LENGTH 80 USER-COMMAND art.
INITIALIZATION.
SELECT vbeln erdat netwr kunnr
FROM vbak AS ak
INTO TABLE i_order
WHERE vbeln = ANY ( SELECT vbeln FROM vbap WHERE vbeln = ak~vbeln GROUP BY vbeln HAVING COUNT( * ) > 1 ).
IF i_order IS NOT INITIAL.
SELECT vbeln posnr matnr arktx kwmeng
FROM vbap
INTO TABLE i_pos
FOR ALL ENTRIES IN i_order
WHERE vbeln = i_order-vbeln.
ENDIF.
LOOP AT i_order INTO DATA(wa).
APPEND VALUE vrm_value( key = |{ wa-vbeln ALPHA = OUT }| text = |{ wa-erdat DATE = USER }| ) TO list.
ENDLOOP.
CALL FUNCTION 'VRM_SET_VALUES'
EXPORTING
id = 'order'
values = list.
CLEAR list.
AT SELECTION-SCREEN.
CHECK sy-ucomm = 'ORD'.
CLEAR position.
CALL FUNCTION 'VRM_SET_VALUES'
EXPORTING
id = 'position'
values = list.
CLEAR list.
AT SELECTION-SCREEN ON order.
CHECK sy-ucomm = 'ORD' AND order IS NOT INITIAL.
i_aux = VALUE #( FOR pos IN i_pos WHERE ( vbeln = |{ order ALPHA = IN }| ) ( pos ) ).
LOOP AT i_aux INTO DATA(aux).
APPEND VALUE vrm_value( key = |{ aux-posnr ALPHA = OUT }| text = |{ aux-matnr ALPHA = OUT }| ) TO list.
ENDLOOP.
CALL FUNCTION 'VRM_SET_VALUES'
EXPORTING
id = 'position'
values = list.
After each selection in order dropdown all the order-related data will be collected to i_aux table which you can use for populating output fields.
The closest solution was to update a working area in the PAI, and update the actual screen fields in the PBO, from the values of the WA.
I want to create a function/custom class method that takes in 2 parameters:
1) IM_ITAB type ANY TABLE
2) IM_COMPONENT type STRING
and returns 1 parameter:
1) EX_RANGE type PIQ_SELOPT_T
So, algorithm is like this:
First of all, we check if the column with a component name at all exists
Then, we check that internal table is not empty.
Then, we loop through internal table assigning component and filling range table. Code is below.
METHODS compose_range_from_itab
IMPORTING
IM_ITAB type ANY TABLE
IM_COMPONENT type STRING
EXPORTING
EX_RANGE type PIQ_SELOPT_T.
...
METHOD compose_range_from_itab.
DATA: lo_obj TYPE REF TO cl_abap_tabledescr,
wa_range TYPE selopt,
lt_range TYPE piq_selopt_t.
FIELD-SYMBOLS: <fs_line> TYPE ANY,
<fs_component> TYPE ANY.
lo_obj ?= cl_abap_typedescr=>describe_by_data( p_data = im_itab ).
READ TABLE lo_obj->key TRANSPORTING NO FIELDS WITH KEY name = im_component.
IF sy-subrc IS INITIAL.
IF LINES( im_itab ) GT 0.
LOOP AT im_itab ASSIGNING <fs_line>.
ASSIGN COMPONENT im_component OF STRUCTURE <fs_line> TO <fs_component>.
wa_range-sign = 'I'.
wa_range-option = 'EQ'.
wa_range-low = <fs_component>.
APPEND wa_range TO lt_range.
ENDLOOP.
SORT lt_range BY low.
DELETE ADJACENT DUPLICATES FROM lt_range COMPARING low.
ex_range[] = lt_range[].
ENDIF.
ENDIF.
ENDMETHOD.
But I want to improve the method further. If the imported internal table has, let's say, 255 columns, then it will take longer to loop through such table. But I need only one column to compose the range.
So I want to get components of internal table, then choose only one component, create a new line type containing only that component, then create internal table with that line type and copy.
Here is the pseudo code corresponding to what I want to achieve:
append corresponding fields of im_itab into new_line_type_internal_table.
How can I "cut out" one component and create a new line type using RTTS?
You are overcomplicating everything, you don't need RTTS for that.
DEFINE make_range.
ex_range = VALUE #( BASE ex_range ( sign = 'I' option = 'EQ' low = &1 ) ).
END-OF-DEFINITION.
LOOP AT im_itab ASSIGNING FIELD-SYMBOL(<fs_line>).
ASSIGN COMPONENT im_component OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_field>).
CHECK sy-subrc = 0 AND <fs_field> IS NOT INITIAL.
make_range <fs_field>.
ENDLOOP.
And yes, as Sandra said, you won't gain any performance with RTTS, just the opposite.
Surprisingly, this variant turned out to be faster:
CLASS-METHODS make_range_variant_2
IMPORTING
sample TYPE table_type
column TYPE string
RETURNING
VALUE(result) TYPE range_type.
METHOD make_range_variant_2.
TYPES:
BEGIN OF narrow_structure_type,
content TYPE char32,
END OF narrow_structure_type.
TYPES narrow_table_type TYPE STANDARD TABLE OF narrow_structure_type WITH EMPTY KEY.
DATA narrow_table TYPE narrow_table_type.
DATA(mapping) =
VALUE cl_abap_corresponding=>mapping_table_value(
( kind = cl_abap_corresponding=>mapping_component srcname = column dstname = 'CONTENT' ) ).
DATA(mover) =
cl_abap_corresponding=>create_with_value(
source = sample
destination = narrow_table
mapping = mapping ).
mover->execute(
EXPORTING
source = sample
CHANGING
destination = narrow_table ).
LOOP AT narrow_table ASSIGNING FIELD-SYMBOL(<row>).
INSERT VALUE #(
sign = 'I'
option = 'EQ'
low = <row>-content )
INTO TABLE result.
ENDLOOP.
ENDMETHOD.
CL_ABAP_CORRESPONDING delegates to a kernel function for the structure-to-structure move, which apparently is faster than the ABAP-native ASSIGN COMPONENT [...] OF STRUCTURE [...] TO FIELD-SYMBOL [...]. The actual loop then seems to be faster because it uses fixed-name assignments.
Maybe somebody could verify.
I would not go for a Macro.
Data:
lr_data type ref to data.
FIELD-SYMBOLS:
<lv_component> TYPE any,
<ls_data> TYPE any.
CREATE DATA lr_data LIKE LINE OF im_itab.
ASSIGN lr_data->* TO <ls_data>.
"Check whether im_component exists
ASSIGN COMPONENT im_component OF STRUCTURE <ls_data> TO <lv_component>.
CHECK sy-subrc EQ 0.
LOOP AT im_itab INTO <ls_data>.
APPEND VALUE #( sign = 'I' option = 'EQ' low = <lv_component> ) TO ex_range.
ENDLOOP.
I have requirement to provider customer search help for user and data to be retrieved from application server directory.
Following is the detail of directory and File type.
Application Server Directory: /usr/sap/tmp/
File type extension .txt should only be available in search help.
Custom Search help should display Directory Name and File having extension .txt.
Users should not be able to select files from any other directory.
Example of Search help output:
Directory Name File Name
-------------- --------------
/usr/sap/tmp/ file_name1.txt
/usr/sap/tmp/ file_name2.txt
/usr/sap/tmp/ file_name3.txt
Following links are helpful but my requirement is not fulfilled.
https://archive.sap.com/discussions/thread/285999
F4_FILENAME
cl_gui_frontend_services=>directory_browse
/SAPDMC/LSM_F4_SERVER_FILE
https://archive.sap.com/discussions/thread/715635
F4_DXFILENAME_TOPRECURSION
is there any one who has better solution?
regards,
Umar Abdullah
Doesn't function module /SAPDMC/LSM_F4_SERVER_FILE fullfil your requirement?
Edit:
In order for users to not be able to select anything from different directories, you can write a wrapper around the function call to make sure the right directory is selected.
Probably not the ideal solution, but one that requires no development effort.
CONSTANTS:
lco_directory TYPE char30 VALUE '/usr/sap/tmp/',
lco_filemask TYPE char5 VALUE '*'.
DATA:
lv_filename TYPE rlgrap-filename,
lv_path TYPE string.
WHILE 1 NE 2.
CLEAR: lv_filename, lv_path.
CALL FUNCTION '/SAPDMC/LSM_F4_SERVER_FILE'
EXPORTING
directory = lco_directory
filemask = lco_filemask
IMPORTING
serverfile = lv_filename
EXCEPTIONS
canceled_by_user = 1
OTHERS = 2.
IF sy-subrc = 0 AND sy-ucomm NE 'CANC' AND lv_filename IS NOT INITIAL.
CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH'
EXPORTING
full_name = lv_filename
IMPORTING
file_path = lv_path
EXCEPTIONS
x_error = 1
OTHERS = 2 .
IF sy-subrc = 0 AND lv_path NE lco_directory.
* Wrong directory was chosen
MESSAGE 'Invalid directory' TYPE 'S' DISPLAY LIKE 'W'.
ELSE.
* Directory is ok
EXIT.
ENDIF.
ELSE.
* Action cancelled
CLEAR: lv_filename, lv_path.
EXIT.
ENDIF.
ENDWHILE.
I have created custom logic for the requirement. I would like to share.
REPORT YUA_LIST_DIRECTORY.
CLASS ff_intf DEFINITION.
PUBLIC SECTION.
METHODS: listdirectory IMPORTING iv_dir TYPE c
EXPORTING ev_ldir TYPE c ev_file TYPE c ,
get_file_list IMPORTING iv_ldir TYPE c iv_today TYPE c.
TYPES: BEGIN OF t_directory,
log_name TYPE dirprofilenames,
phys_path TYPE dirname_al11,
END OF t_directory.
DATA: lt_int_list TYPE TABLE OF abaplist,
lt_string_list TYPE list_string_table,
lt_directories TYPE TABLE OF t_directory,
ls_directory TYPE t_directory.
DATA: BEGIN OF gs_file,
directory(500) TYPE c, " name of directory.
name(75) TYPE c, " name of entry." (possibly truncated.)
type(10) TYPE c, " type of entry: directory, file
len(16) TYPE p, " length in bytes
owner(8) TYPE c, " owner of the entry
mtime(6) TYPE p, " last modification date, " seconds since 1970
mode(9) TYPE c, " like "rwx-r-x--x":" protection mode
errno(3) TYPE c,
errmsg(40) TYPE c,
mod_date TYPE d,
mod_time(8) TYPE c, " hh:mm:ss
subrc LIKE sy-subrc,
END OF gs_file.
DATA:
ls_file LIKE gs_file,
pt_file LIKE TABLE OF gs_file.
CLASS-METHODS: p6_to_date_time_tz IMPORTING iv_time TYPE p EXPORTING ev_time TYPE c ev_date TYPE d.
ENDCLASS. "ff_intf DEFINITION
*----------------------------------------------------------------------*
* CLASS ff_intf IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS ff_intf IMPLEMENTATION.
METHOD listdirectory.
FIELD-SYMBOLS: <l_line> TYPE string.
CONCATENATE 'FF' sy-datum '.txt' INTO ev_file. " file name
SUBMIT rswatch0 EXPORTING LIST TO MEMORY AND RETURN.
CALL FUNCTION 'LIST_FROM_MEMORY'
TABLES
listobject = lt_int_list.
CALL FUNCTION 'LIST_TO_ASCI'
EXPORTING
with_line_break = 'X' "abap_true
IMPORTING
list_string_ascii = lt_string_list
TABLES
listobject = lt_int_list.
* remove the separators and the two header lines
DELETE lt_string_list WHERE table_line CO '-'.
DELETE lt_string_list INDEX 1.
DELETE lt_string_list INDEX 1.
* parse the individual lines
LOOP AT lt_string_list ASSIGNING <l_line>.
* If you're on a newer system, you can do this in a more elegant way using regular expressions
CONDENSE <l_line>.
SHIFT <l_line> LEFT DELETING LEADING '|'.
SHIFT <l_line> RIGHT DELETING TRAILING '|'.
SPLIT <l_line>+1 AT '|' INTO ls_directory-log_name ls_directory-phys_path.
APPEND ls_directory TO lt_directories.
ENDLOOP.
READ TABLE lt_directories INTO ls_directory WITH KEY log_name = iv_dir .
IF sy-subrc EQ 0.
ev_ldir = ls_directory-phys_path.
ENDIF.
ENDMETHOD. "listdirectory
METHOD get_file_list.
DATA:
l_counter TYPE i,
l_counter_package TYPE i,
l_char10(10),
l_text(100),
l_subrc LIKE sy-subrc,
lv_cmptoday TYPE c LENGTH 11.
*-----------------------------------*
DATA lv_compstr TYPE c LENGTH 5.
lv_compstr = '*.TXT'.
CONCATENATE '*' sy-datum+0(4) sy-datum+4(2) sy-datum+6(2) '*' INTO lv_cmptoday. " YYYYMMDD
CALL 'C_DIR_READ_FINISH'
ID 'ERRNO' FIELD ls_file-errno
ID 'ERRMSG' FIELD ls_file-errmsg.
CALL 'C_DIR_READ_START'
ID 'DIR' FIELD iv_ldir " logical directory
ID 'FILE' FIELD '*'
ID 'ERRNO' FIELD ls_file-errno
ID 'ERRMSG' FIELD ls_file-errmsg.
IF sy-subrc <> 0.
IF NOT ls_file-errmsg IS INITIAL.
MESSAGE i034(/sapdmc/lsmw_obj_060) WITH ls_file-errmsg.
ENDIF.
EXIT.
ENDIF.
DO .
CLEAR ls_file.
CALL 'C_DIR_READ_NEXT'
ID 'TYPE' FIELD ls_file-type
ID 'NAME' FIELD ls_file-name
ID 'LEN' FIELD ls_file-len
ID 'OWNER' FIELD ls_file-owner
ID 'MTIME' FIELD ls_file-mtime
ID 'MODE' FIELD ls_file-mode
ID 'ERRNO' FIELD ls_file-errno
ID 'ERRMSG' FIELD ls_file-errmsg.
l_subrc = sy-subrc.
ls_file-subrc = sy-subrc.
IF l_subrc = 1.
EXIT.
ELSEIF l_subrc = 5.
ls_file-type = '???'.
ls_file-owner = '???'.
ls_file-mode = '???'.
ENDIF.
ls_file-directory = iv_ldir.
ADD 1 TO l_counter.
ADD 1 TO l_counter_package.
IF l_counter_package = 100.
l_text = '& Enteries Read'.
l_char10 = l_counter.
REPLACE '&' WITH l_char10 INTO l_text.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
text = l_text.
l_counter_package = 0.
ENDIF.
* Machine time into date/time of day convert
IF iv_today EQ 'X'. " only files of current date
CALL METHOD ff_intf=>p6_to_date_time_tz( EXPORTING iv_time = ls_file-mtime
IMPORTING ev_time = ls_file-mod_time ev_date = ls_file-mod_date ).
IF ls_file-mod_date EQ sy-datum.
* Only the files, which fit the sample(mask)
CASE ls_file-type(1).
WHEN 'F' OR 'f'. " File
IF ( ls_file-name CP lv_compstr ) AND ls_file-name+0(2) = 'FF' AND ls_file-name CP lv_cmptoday. " Only Text File to compare
APPEND ls_file TO pt_file.
ENDIF.
* WHEN OTHERS.
* APPEND ls_file TO pt_file.
ENDCASE.
ENDIF.
ELSE. " ALL files in directory
* Only the files, which fit the sample(mask)
CASE ls_file-type(1).
WHEN 'F' OR 'f'. " File
IF ( ls_file-name CP lv_compstr ) AND ls_file-name+0(2) = 'FF'. " Only Text File to compare and PODEL & Today
APPEND ls_file TO pt_file.
ENDIF.
ENDCASE.
ENDIF.
ENDDO.
SORT pt_file BY type DESCENDING name DESCENDING.
CALL 'C_DIR_READ_FINISH'
ID 'ERRNO' FIELD ls_file-errno
ID 'ERRMSG' FIELD ls_file-errmsg.
ENDMETHOD. "get_file_list
METHOD p6_to_date_time_tz.
DATA: opcode TYPE x,
unique, not_found,
timestamp TYPE i,
date TYPE d,
time TYPE t,
tz LIKE sy-zonlo,
timestring(10),
abapstamp(14),
abaptstamp TYPE timestamp.
timestamp = iv_time.
IF sy-zonlo = space.
* Der Benutzer hat keine Zeitzone gepflegt: nehme lokale des App. Srv.
CALL FUNCTION 'TZON_GET_OS_TIMEZONE'
IMPORTING
ef_timezone = tz
ef_not_unique = unique
ef_not_found = not_found.
IF unique = 'X' OR not_found = 'X'. .
tz = sy-tzone.
CONCATENATE 'UTC+' tz INTO tz.
ENDIF.
ELSE.
tz = sy-zonlo.
ENDIF.
* wandle den Timestamp in ABAP Format um und lass den ABAP konvertieren
opcode = 3.
CALL 'RstrDateConv'
ID 'OPCODE' FIELD opcode
ID 'TIMESTAMP' FIELD timestamp
ID 'ABAPSTAMP' FIELD abapstamp.
abaptstamp = abapstamp.
CONVERT TIME STAMP abaptstamp TIME ZONE tz INTO DATE date
TIME time.
IF sy-subrc <> 0.
date = abapstamp(8).
time = abapstamp+8.
ENDIF.
WRITE: time(2) TO timestring(2),
':' TO timestring+2(1),
time+2(2) TO timestring+3(2),
':' TO timestring+5(1),
time+4(2) TO timestring+6(2).
MOVE timestring TO ev_time.
MOVE date TO ev_date.
ENDMETHOD. "P6_TO_DATE_TIME_TZ
ENDCLASS.
DATA lo_pi TYPE REF TO ff_intf.
DATA ls_pt LIKE LINE OF lo_pi->pt_file.
DATA v_csv TYPE c LENGTH 1 VALUE space.
DATA v_separator TYPE c LENGTH 2.
DATA: lt_file TYPE ztt_file,
ls_file LIKE LINE OF lt_file,
ls_ptfile LIKE LINE OF lo_pi->pt_file.
SELECTION-SCREEN: BEGIN OF BLOCK a WITH FRAME TITLE text-001.
PARAMETERS p_dir TYPE c LENGTH 50 DEFAULT '/usr/sap/tmp/'.
PARAMETERS: p_sfile LIKE rlgrap-filename.
SELECTION-SCREEN: END OF BLOCK a.
AT SELECTION-SCREEN OUTPUT.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_sfile.
REFRESH lo_pi->pt_file.
CALL METHOD lo_pi->get_file_list( EXPORTING iv_ldir = p_dir iv_today = '' ). " Directory logical name.
REFRESH lt_file.
LOOP AT lo_pi->pt_file INTO ls_ptfile.
MOVE ls_ptfile-directory TO ls_file-directory.
MOVE ls_ptfile-name TO ls_file-fname.
APPEND ls_file TO lt_file.
ENDLOOP.
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
retfield = 'FNAME'
dynpprog = sy-repid
dynpnr = sy-dynnr
dynprofield = 'so_tmpl-low'
value_org = 'S'
TABLES
value_tab = lt_file
EXCEPTIONS
parameter_error = 1
no_values_found = 2
OTHERS = 3.
CASE sy-subrc.
WHEN 1.
MESSAGE 'Parameter Error' TYPE 'I' DISPLAY LIKE 'W'.
WHEN 2.
MESSAGE 'No values found' TYPE 'I' DISPLAY LIKE 'W'.
WHEN 3.
MESSAGE 'Error Processing help' TYPE 'I' DISPLAY LIKE 'W'.
ENDCASE.
********************************* INITIALIZATION. ************************************
INITIALIZATION.
CREATE OBJECT lo_pi.
********************************* START-OF-SELECTION ************************************
START-OF-SELECTION.
********************************* END-OF-SELECTION ************************************
END-OF-SELECTION.
I have a serie of entry parameters where there a match code, I need that this field (matchcode) will be dependent of a text parameter. For example, something like that :
SELECTION-SCREEN BEGIN OF BLOCK block02 WITH FRAME TITLE text-002.
PARAMETERS:
p_mona TYPE ZTIPOSOL GROUP rad1 MATCHCODE OBJECT ZFIMC002,
p_fcomp TYPE SY-DATUM MODIF ID A OBLIGATORY.
SELECTION-SCREEN END OF BLOCK block02
ABAP Development
No, you cannot. However, you can populate search help values dynamically in AT SELECTION-SCREEN ON VALUE-REQUEST event:
DATA: LT_VBAK TYPE STANDARD TABLE OF VBAK.
PARAMETER P_VBELN TYPE VBELN.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_VBELN.
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
RETFIELD = 'VBELN'
DYNPPROG = SY-REPID
DYNPNR = SY-DYNNR
DYNPROFIELD = 'P_VBELN'
VALUE_ORG = 'S'
TABLES
VALUE_TAB = LT_VBAK
EXCEPTIONS
PARAMETER_ERROR = 1
NO_VALUES_FOUND = 2
OTHERS = 3.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
where LT_VBAK is a internal table you need to populate with values.
If your values are dependent on another selection screen parameter, use DYNP_VALUES_READ FM to read them from screen.
Another approach is not to dynamically fill values but to create a single Search Help in DDIC and create Search Help exit which will control SHELP behavior depending on some conditions.
I'm trying to use the function module REUSE_ALV_FIELDCATALOG_MERGE to pass the field label in ddic to display in the column header of the alv report.
But, that didn't work.
If I comment the I_STRUCTURE_NAME = 'TY_YNAH_CUS_OBJ_REQ' line, it give me runtime error state
The ABAP program lines are wider than the internal table.
But if I uncomment it ,the program still did not work
REPORT YALV_TEST.
tables sscrfields.
type-pools : slis.
"CREATE STRUCTURE -1
TYPES: BEGIN OF TY_YNAH_CUS_OBJ_REQ,
REQID TYPE YNAH_REQ_ID,
REQUESTOR TYPE YNAH_REQUESTOR,
BUSINESS_OWNER TYPE YNAH_BUS_OWN,
FUNCTIONAL_OWNER TYPE YNAH_FUNC_OWN,
REQNUM TYPE YNAH_SERVICE_REQ_NUM,
PROJECT_ID TYPE YNAH_PRO_ID,
SYSTEM_ID TYPE YNAH_SYS_ID,
FUNCTIONAL_AREA TYPE YNAH_FUNC_AREA,
REQUEST_DATE TYPE YNAH_REQ_DATE,
REQUEST_TIME TYPE YNAH_REQ_TIME,
END OF TY_YNAH_CUS_OBJ_REQ.
"defining internal table -2
DATA: IT_YNAH_CUS_OBJ_REQ type TABLE OF TY_YNAH_CUS_OBJ_REQ
* WA_YNAH_CUS_OBJ_REQ type TY_YNAH_CUS_OBJ_REQ.
DATA: it_fcat TYPE slis_t_fieldcat_alv ,
wa_fcat TYPE slis_fieldcat_alv,
gd_layout TYPE slis_layout_alv.
SELECTION-SCREEN BEGIN OF BLOCK menu WITH FRAME TITLE text-001.
SELECT-OPTIONS: s_proid FOR IT_YNAH_CUS_OBJ_REQ-PROJECT_ID.
PARAMETER p_sysid type TY_YNAH_CUS_OBJ_REQ-SYSTEM_ID.
SELECTION-SCREEN: BEGIN OF LINE,
pushbutton 33(8) BUT user-command search.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK menu.
initialization.
BUT = 'SEARCH'. END-OF-SELECTION.
"execute search function when user click search button
at selection-screen. "after processing user input
case SSCRFIELDS.
when 'SEARCH'.
SSCRFIELDS-UCOMM = 'ONLI'.
endcase.
"fetch data using select-4 START-OF-SELECTION.
SELECT *
FROM YNAH_CUS_OBJ_REQ "Database
INTO CORRESPONDING FIELDS OF TABLE IT_YNAH_CUS_OBJ_REQ "Into internal table
WHERE
PROJECT_ID in s_proid and
SYSTEM_ID eq p_sysid.
CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
EXPORTING
I_PROGRAM_NAME = sy-repid
I_INTERNAL_TABNAME ='TY_YNAH_CUS_OBJ_REQ'
* I_STRUCTURE_NAME = 'TY_YNAH_CUS_OBJ_REQ'
* I_CLIENT_NEVER_DISPLAY = 'X'
I_INCLNAME = sy-repid
* I_BYPASSING_BUFFER = 'X'
* I_BUFFER_ACTIVE = CHANGING CT_FIELDCAT = it_fcat.
* EXCEPTIONS
* INCONSISTENT_INTERFACE = 1
* PROGRAM_ERROR = 2
* OTHERS = 3
* .
IF SY-SUBRC <> 0.
** Implement suitable error handling here
ENDIF.
The REUSE_*ALV* function modules are unsupported. I'd suggest switching to the CL_SALV_* classes. The documentation is better, there are more sample programs (DEMO_SALV_*) and you get support.
You need a dictionary structure if you want to get dictionary-based field descriptions (duh). If you assemble a structure type on the ABAP level using TYPE ... BEGIN OF ... END OF ..., as far as I know, the dictionary types for the individual fields are converted to ABAP types first and only then assembled into a structure type. Anyway, the dictionary reference of the original fields is lost. Instead of defining the structure of the output table in your code, use a dictionary structure.
You have some mistakes you might have not known (SAP is very confusing sometimes
and not transparent with error-messages). I got for you a working example of mine, have a look on it, especially on the comments.
First, data definition:
TYPE-POOLS slis. "import you need for REUSE_ALV_FIELDCATALOG_MERGE
DATA:
lt_fieldcat TYPE slis_t_fieldcat_alv,
BEGIN OF G_IT_MATERIAL occurs 0,
MATNR LIKE MARA-MATNR,
MTART LIKE MARA-MTART,
MAKTX_DE LIKE MAKT-MAKTX,
MAKTX_FR LIKE MAKT-MAKTX,
MAKTX_IT LIKE MAKT-MAKTX,
ERNAM LIKE MARA-ERNAM,
ERSDA LIKE MARA-ERSDA,
LAEDA LIKE MARA-LAEDA,
END OF G_IT_MATERIAL.
It is absolutely necessary that you define your local structure directly with LIKE, otherwise the parser from REUSE_ALV_FIELDCATALOG_MERGE will not find it.
Select your stuff:
SELECT ma~matnr ma~mtart ma~ernam ma~ersda ma~laeda
de~maktx as maktx_de fr~maktx as maktx_fr it~maktx as maktx_it
FROM mara as ma
LEFT JOIN MAKT as de ON de~matnr = ma~matnr AND de~spras = 'DE'
LEFT JOIN MAKT as fr ON fr~matnr = ma~matnr AND fr~spras = 'FR'
LEFT JOIN MAKT as it ON it~matnr = ma~matnr AND it~spras = 'IT'
INTO CORRESPONDING FIELDS OF TABLE g_it_material
WHERE ...
Create a field catalog dynamically:
CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
EXPORTING
I_PROGRAM_NAME = sy-repid
I_INTERNAL_TABNAME = 'G_IT_MATERIAL'
I_INCLNAME = sy-repid
CHANGING
ct_fieldcat = lt_fieldcat
EXCEPTIONS
inconsistent_interface = 1
program_error = 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 display the ALV grid:
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
it_fieldcat = lt_fieldcat "you could also give a structure
"i_structure_name = 'ZMM_SMATERIAL' "here instead of the fieldcat
TABLES
t_outtab = g_it_material
EXCEPTIONS
program_error = 1
OTHERS = 2.
Note that the parser also needs a max linesize of 72 chars.
There are several different text components provided by structure slis_fieldcat_alv that are used as column labels. The chosen text depends on the current column width (which itself usually depends on the length of the data displayed). Make sure that you change them all accordingly!
The usual technique is: By passing the I_STRUCTURE_NAME, you get a field catalog corresponding to this DDIC structure (the changing parameter ct_fieldcat). You then modify this internal table according to your needs and pass that modified table to the REUSE_ALV_GRID_DISPLAY.
In cases where I don't distinguish the different-sized text versions, I use the following macros to set all the text fields to the same value. The macros require a local work area ls_fieldcat (with the linetype of ct_fieldcat) and a local string variablelv_text` in order to work.
define set_field.
* Feld &1 für Anzeigefeld &2 den Wert &3 zuweisen
ls_fieldcat-&1 = &3.
modify ct_fieldcat from ls_fieldcat
transporting &1
where fieldname cp '&2'.
end-of-definition.
define set_text_direct.
lv_text = &2.
set_field seltext_s &1 lv_text.
lv_text = &2.
set_field seltext_m &1 lv_text.
lv_text = &2.
set_field seltext_l &1 lv_text.
end-of-definition.