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.
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 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.
How to update Z fields with BAPI_OUTB_DELIVERY_CHANGE using EXTENSION2?
I tried to update some Z fields in LIKP table using the BAPI to update deliveries but after call it any changes wasn't made.
Any suggestions?
I found the BAdI - SMOD_V50B0001. I made an enhancement implementaction and in the method EXIT_SAPLV50I_010 (User Exit BAPI for Changes to Outbound Delivery) set the follow code.
METHOD if_ex_smod_v50b0001~exit_saplv50i_010.
CONSTANTS: lc_vbkok TYPE char5 VALUE 'VBKOK', "Enhance the structure for more z fields in LIKP
lc_vbpok TYPE char5 VALUE 'VBPOK', "Enhance the structure for more z fields in LIPS
lc_cs_vbkok TYPE char8 VALUE 'CS_VBKOK'.
DATA: lv_item TYPE posnr_vl.
FIELD-SYMBOLS: <lfs_fieldname> TYPE any.
LOOP AT extension2 INTO DATA(lw_extension2).
CASE lw_extension2-param.
"As a structure in row 0
WHEN lc_vbkok. "Fields for LIKP
ASSIGN (lc_cs_vbkok) TO FIELD-SYMBOL(<lfs_vbkok>).
IF <lfs_vbkok> IS ASSIGNED.
ASSIGN COMPONENT lw_extension2-field OF STRUCTURE <lfs_vbkok> TO <lfs_fieldname>.
IF <lfs_fieldname> IS ASSIGNED.
<lfs_fieldname> = lw_extension2-value.
ENDIF.
ENDIF.
"As a table from row 1 to n
WHEN lc_vbpok. "Fields for LIPS
MOVE lw_extension2-row TO lv_item.
READ TABLE ct_vbpok ASSIGNING FIELD-SYMBOL(<lfs_vbpok>) WITH KEY posnr_vl = lv_item.
IF sy-subrc = 0.
ASSIGN COMPONENT lw_extension2-field OF STRUCTURE <lfs_vbpok> TO <lfs_fieldname>.
IF <lfs_fieldname> IS ASSIGNED.
<lfs_fieldname> = lw_extension2-value.
ENDIF.
ENDIF.
ENDCASE.
ENDLOOP.
ENDMETHOD.
Enhace the structures VBKOK as well LIKP with appen structures to add new z fields and enhance the structure VBPOK as well LIPS for the same purpose.
Also take a look to the program LV50LF01 and would need to implement an additional enhancement point to keep the values.
After this a think that I got it.
METHOD m_update_delivery.
DATA: lw_header_data TYPE bapiobdlvhdrchg,
lw_header_control TYPE bapiobdlvhdrctrlchg,
lw_extension2 TYPE bapiext.
DATA: li_extension2 TYPE TABLE OF bapiext,
li_return TYPE TABLE OF bapiret2.
DATA: lv_delivery TYPE bapiobdlvhdrchg-deliv_numb.
lw_header_data-deliv_numb = p_w_output-delivery.
lw_header_control-deliv_numb = p_w_output-delivery.
lv_delivery = p_w_output-delivery.
lw_extension2-param = 'VBKOK'.
lw_extension2-field = 'ZZEXIDV'.
lw_extension2-value = p_w_output-value.
APPEND lw_extension2 TO li_extension2.
" Call BAPI to update delivery
CALL FUNCTION 'BAPI_OUTB_DELIVERY_CHANGE'
EXPORTING
header_data = lw_header_data
header_control = lw_header_control
delivery = lv_delivery
TABLES
extension2 = li_extension2
return = li_return.
READ TABLE li_return INTO DATA(lw_return)
WITH KEY type = c_e.
IF sy-subrc <> 0.
COMMIT WORK AND WAIT.
ENDIF.
ENDMETHOD.
You need to add BAPI_COMMIT after your BAPI function module.
I have a selection screen with select-options where I want to enter several information about materials, for example: material number etc.
The user is also able to enter a language which the output should be in.
If the user chooses english the program shall display an internal table with material number, language, material name in english. If the user enters spanish, I want the output to be in spanish.
What do I have to do in order to define a dynamic structure / table which shows the respective columns dependent on the chosen language?
Thanks for your help
It's highly-dependent on the data structure you are going to show to user, but usually you don't need dynamic structure for this, but rather need to populate data dynamically, i.e. depending on current user language.
For example, material texts are stored in MAKT text table, where texts are stored along with language keys by which they are usually retrieved:
SELECT
a~matnr
a~werks
b~maktx FROM ekpo AS a
INNER JOIN makt AS b
ON b~matnr = a~matnr
AND b~spras = sy-langu
INTO CORRESPONDING FIELDS OF TABLE int_out
WHERE
a~matnr IN s_matnr and
a~werks IN s_werks.
Other descriptions in SAP are usually stored in text tables as well.
More about sy-langu and other system fields is here.
UPDATE: If you really want a dynamic structure with all the languages, see this sample:
DATA: lang TYPE SPRAS.
* language selection
SELECT-OPTIONS: s_lang FOR lang.
SELECT a~matnr, a~werks, b~maktx, b~spras UP TO 5000 ROWS
FROM ekpo AS a
JOIN makt AS b
ON b~matnr = a~matnr
INTO TABLE #DATA(int_out)
WHERE a~werks LIKE '3%'
AND a~matnr LIKE '1%'
AND b~spras IN #s_lang.
*finding unique languages
DATA lt_langs TYPE TABLE OF spras.
lt_langs = VALUE #( ( '' ) ).
LOOP AT int_out ASSIGNING FIELD-SYMBOL(<fs_out>)
GROUP BY ( lang = to_upper( val = <fs_out>-spras ) ) ASCENDING
WITHOUT MEMBERS
ASSIGNING FIELD-SYMBOL(<ls_lang>).
APPEND <ls_lang>-lang TO lt_langs.
ENDLOOP.
DATA :
ls_component TYPE cl_abap_structdescr=>component,
gt_components TYPE cl_abap_structdescr=>component_table.
*adding MATNR column
ls_component-name = 'MATNR'.
ls_component-type ?= cl_abap_datadescr=>describe_by_name( 'matnr' ).
APPEND ls_component TO gt_components.
*Creating dynamic structure with column for every lang
LOOP AT lt_langs ASSIGNING FIELD-SYMBOL(<fs_lang>).
CONDENSE <fs_lang>.
IF <fs_lang> IS NOT INITIAL.
ls_component-name = 'makt_' && <fs_lang>.
ls_component-type ?= cl_abap_datadescr=>describe_by_name( 'maktx' ).
APPEND ls_component TO gt_components.
ENDIF.
ENDLOOP.
* constructing dynamic structure
DATA: gr_struct_typ TYPE REF TO cl_abap_datadescr.
gr_struct_typ ?= cl_abap_structdescr=>create( p_components = gt_components ).
* constructing table from structure
DATA: gr_dyntable_typ TYPE REF TO cl_abap_tabledescr.
gr_dyntable_typ = cl_abap_tabledescr=>create( p_line_type = gr_struct_typ ).
DATA: gt_dyn_table TYPE REF TO data,
gw_dyn_line TYPE REF TO data.
FIELD-SYMBOLS: <gfs_line>,<gfs_line1>,<fs1>,
<gfs_dyn_table> TYPE STANDARD TABLE.
CREATE DATA: gt_dyn_table TYPE HANDLE gr_dyntable_typ,
gt_dyn_table TYPE HANDLE gr_dyntable_typ,
gw_dyn_line TYPE HANDLE gr_struct_typ.
ASSIGN gt_dyn_table->* TO <gfs_dyn_table>.
ASSIGN gw_dyn_line->* TO <gfs_line>.
LOOP AT int_out ASSIGNING <fs_out>.
* checking for duplicated
READ TABLE <gfs_dyn_table> ASSIGNING <gfs_line1> WITH KEY ('MATNR') = <fs_out>-matnr.
IF sy-subrc = 0.
CONTINUE.
ENDIF.
* assigning material number
LOOP AT gt_components ASSIGNING FIELD-SYMBOL(<fs_component>).
IF <fs_component>-name = 'MATNR'.
ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <gfs_line> TO <fs1>.
IF <fs1> IS ASSIGNED.
<fs1> = <fs_out>-matnr.
UNASSIGN <fs1>.
ENDIF.
ENDIF.
* assigning languge-dependent names
READ TABLE int_out WITH KEY matnr = <fs_out>-matnr
spras = <fs_component>-name+5
ASSIGNING FIELD-SYMBOL(<fs_spras>).
IF sy-subrc = 0.
ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <gfs_line> TO <fs1>.
IF <fs1> IS ASSIGNED.
<fs1> = <fs_spras>-maktx.
UNASSIGN <fs1>.
ENDIF.
ENDIF.
ENDLOOP.
APPEND <gfs_line> TO <gfs_dyn_table>.
CLEAR: <gfs_line>.
ENDLOOP.
DATA: l_lang TYPE spras VALUE 'E'.
* showing values in proper language depending on user input
LOOP AT <gfs_dyn_table> ASSIGNING <gfs_line>.
ASSIGN COMPONENT 'makt_' && l_lang OF STRUCTURE <gfs_line> TO <fs1>.
IF <fs1> IS ASSIGNED.
WRITE / <fs1>.
UNASSIGN <fs1>.
ENDIF.
ENDLOOP.
I am pasting this program for example but i will never know the type of the table (here vbap and vbak).
My goals is to display my field symbol without knowing the types.
Is it possible ?
Here is my code :
REPORT ZTEST_FME_FOL.
type-pools slis .
FIELD-SYMBOLS : <mytable> TYPE ANY TABLE.
DATA : lv_alv_table TYPE REF TO cl_salv_table,
lv_funct TYPE REF TO cl_salv_functions,
lv_columns TYPE REF TO cl_salv_columns_table,
lv_column TYPE REF TO CL_SALV_COLUMN_table.
SELECT * from vbap INNER JOIN VBAK ON vbap~vbeln = vbak~vbeln UP TO 10 ROWS INTO TABLE <mytable>.
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = lv_alv_table
CHANGING
t_table = <mytable> ).
CATCH cx_salv_msg .
ENDTRY.
lv_funct = lv_alv_table->get_functions( ).
lv_funct->set_all( Abap_True ).
lv_columns = lv_alv_table->get_columns( ).
lv_alv_table->display( ).
Thanks in advance !
Depending on what you 're trying to do there's going to be more validation required than what I've done, but in essence this is what you need.
Using (dynamic) joins may be particularly tricky.
report zevw_test_dynamic_alv.
parameters: p_table type string obligatory.
field-symbols: <gt_table> type standard table.
data: gt_data type ref to data.
start-of-selection.
create data gt_data type table of (p_table).
assign gt_data->* to <gt_table>.
select * from (p_table) up to 10 rows
into table <gt_table>.
perform display_results using <gt_table>. "Your ALV stuff will be in here
You may even have to build the fieldcat manually and then use
call method cl_alv_table_create=>create_dynamic_table
exporting
it_fieldcatalog = gt_fieldcat[]
importing
ep_table = gt_data.
to get the data reference