I want to show text on input field in the screen, which is value from work area, respectivetly name, age and city, as you can see. When I declare znew_fdkey01 and znew_fdkey02 (which are transparent tables) with using TABLES keyword like this:
TABLES: znew_fdkey01, znew_fdkey02.
it works perfectly. But when I want to obtain the same effect without using this keyword, and when I declare variables like this:
DATA: znew_fdkey01 TYPE znew_fdkey01,
znew_fdkey02 TYPE znew_fdkey02.
it does not show me text in the input field.
Why?
NB: here is the code to initialize the screen fields (the same in both cases):
LOOP AT SCREEN INTO screen_wa.
IF screen_wa-name = 'ZNEW_FDKEY01-NAME'.
znew_fdkey01-name = lr_znewfdkey3-name.
ENDIF.
IF screen_wa-name = 'ZNEW_FDKEY01-AGE'.
znew_fdkey01-age = lr_znewfdkey3-age.
ENDIF.
IF screen_wa-name = 'ZNEW_FDKEY02-CITY'.
znew_fdkey02-city = lr_znewfdkey3-city.
ENDIF.
MODIFY SCREEN FROM screen_wa.
ENDLOOP.
This is correct, TABLES defines work areas and at the same time it is necessary to ensure the automatic communication between the screen (dynpro) and the ABAP program, as documented in the ABAP Help:
Table work areas declared using TABLES are interface work areas...
The statement TABLES is required for exchanging data between dynpro fields and the ABAP program, if the fields were defined in a dynpro in the program by being taken from ABAP Dictionary, . In the dynpro event PBO, the content of the table work area is passed to identically named dynpro fields. In PAI, the system takes the data from identically named dynpro fields.
(Otherwise don't use TABLES to declare work areas, that is obsolete)
You must use TABLES only if you define your screen input/output field as a "DDIC" field (Data/ABAP Dictionary). This is a checkbox defined in the Screen Painter for each screen field.
There are two possibilities:
Either you name your screen I/O field like according to an existing DDIC structure field (as you did, ZNEW_FDKEY01-NAME) and you define it as a "DDIC" field (it's a field attribute in the Screen Painter) and you must use TABLES to transfer values.
Or you don't define your screen input field as a "DDIC" field, and you define the field name as a global variable in your program, using TABLES is completely optional. But in that case, you lose some features in the screen that are unique to the DDIC, like the reuse of DDIC labels (any change impacts all screens), the Value Help/F4 like the search help implying multiple fields (but you can still code it in ABAP from scratch), etc.
Example:
Create this program:
TABLES spfli. " Mandatory as screen field SPFLI-CARRID is connected to the "DDIC"
DATA scarr TYPE scarr. " or TABLES scarr if you wish
spfli-carrid = 'LH'.
scarr-carrname = 'Name of company'.
CALL SCREEN 100.
MODULE screen_0100_pai INPUT.
LEAVE TO SCREEN 0.
ENDMODULE.
Create the dynpro 0100 with these fields (pay attention to "Dict.field")
Name Type Line Col. Def Vis Format Inp Out Dict.field
SPFLI-CARRID I/O 1 18 3 3 CHAR X X X
SCARR-CARRNAME I/O 2 18 20 20 CHAR X X
and this flow logic:
PROCESS BEFORE OUTPUT.
PROCESS AFTER INPUT.
MODULE SCREEN_0100_PAI.
Activate and run the program.
Result as expected:
Related
In our current project we are using SAPNCO3 with RFC calls. The requirement is to create material with the function "BAPI_MATERIAL_SAVEDATA" and some custom fields (via EXTENSIONIN). The problem now is how to extend the needed structures "BAPI_TE_MARA/X" so that they can carry the custom fields? I cannot found any function for this.
Please have a look at the Code snippet at the bottom.
Thank you!
Tobias
var BAPI_TE_MARA = repo.GetStructureMetadata("BAPI_TE_MARA");
IRfcStructure structure = BAPI_TE_MARA.CreateStructure();
structure.SetValue("MATERIAL", material.Number);
//structure.SetValue("ZMM_JOB_REFERENCE", "f");
BAPI_MATERIAL_SAVEDATA has two table parameters EXTENSIONIN and EXTENSIONINX to which you pass lines with the values of your custom fields.
These table parameters have to indicate what extension structures you want to use and their values.
As these custom fields may extend different tables of the material, you have to indicate different extension structures depending on which table these fields belong to:
For the table MARA, the extension structures are BAPI_TE_MARA and BAPI_TE_MARAX.
For the table MARC, the extension structures are BAPI_TE_MARC and BAPI_TE_MARCX.
These extension structures should preferably have character-like fields to simplify the programming (and to support IDocs, as rule-of-thumb).
For instance, if you have the custom fields ZZCNAME (7 characters) and ZZCTEXT (50 characters) in the table MARA, they will also be defined in BAPI_TE_MARA and have the same names and types. In BAPI_TE_MARAX, you also have two fields with the same names, but always of length 1 character and their values must be 'X' to indicate that a value is passed in BAPI_TE_MARA (useful in case a blank value is passed that must not be ignored). The X extension structures are essential especially in "change" BAPIs.
If you want to pass values to the BAPI, you must first initialize these structures:
BAPI_TE_MARA:
MATERIAL ZZCNAME ZZCTEXT
------------ ------- -------
000000012661 NAME TEXT
BAPI_TE_MARAX:
MATERIAL ZZCNAME ZZCTEXT
------------ ------- -------
000000012661 X X
Then, you must initialize the two parameters of the BAPI:
EXTENSIONIN (notice that there are 3 spaces in NAME TEXT because the technical length of ZZCNAME is 7 characters and its value "NAME" occupies only 4 characters):
STRUCTURE VALUEPART1 (240 Char) VALUEPART2 (240) VALUEPART3 (240) VALUEPART4 (240)
------------ ----------------------- ---------------- ---------------- ----------------
BAPI_TE_MARA 000000012661NAME TEXT
EXTENSIONINX:
STRUCTURE VALUEPART1 (240 Char) VALUEPART2 (240) VALUEPART3 (240) VALUEPART4 (240)
------------- --------------------- ---------------- ---------------- ----------------
BAPI_TE_MARAX 000000012661XX
Consequently, your program must:
concatenate all BAPI_TE_MARA fields together and copy the resulting string into fields VALUEPART1 to VALUEPART4 of EXTENSIONIN as if it was a 960 characters field
concatenate all BAPI_TE_MARAX fields together and copy the resulting string into fields VALUEPART1 to VALUEPART4 of EXTENSIONINX
I guess you may use ToString() to get one concatenated string of characters of all fields of a structure, and to set the value of VALUEPART1, VALUEPART2, etc., you'll probably need to initialize them individually from the string of characters with Substring.
My comment was half by half correct and incorrect, I wasn't aware of the extension technique in this BAPI, so I wasn't aware of this structure is really used in this BAPI.
You asked
The problem now is how to extend the needed structures "BAPI_TE_MARA/X" so that they can carry the custom fields?`
and what I said is indeed stays valid: you cant extend the interface from NCo, only on backend.
You writes:
At this If I load BAPI_TE_MARA there aren't any custom fields but the material
and this get me to the idea that your ABAP developers made only half of the work. The things to be done on the SAP backend:
Extend MARA table with custom Z fields (in SAP it is called Append structure)
Extend interface structure BAPI_TE_MARA with the fields which should exactly correspond to the MARA fields
This is how it must look like on backend
If you don't see any custom fields in BAPI_TE_MARA except MATERIAL probably step 2 is missing on SAP side. As what I got from your comments, they created structure ZMM_S_MATMAS_ADDITION but appended it only to MARA, but not to BAPI_TE_MARA.
What is missing from Sandra excellent holistic answer is step 3: for all this construction to work some customizing need to be done.
T130F table must contain your custom fields. To maintain the entry for T130F go to transaction SPRO or directly to maintenance view V_130F.
SPRO way: go to SPRO -> Logistics-General -> Material Master -> Field Selection -> Assign fields to field Selection Groups and maintain the entry in the table
Sample ABAP code that does the thing:
DATA: ls_headdata TYPE bapimathead,
lt_extensionin TYPE STANDARD TABLE OF bapiparex,
ls_extensionin LIKE LINE OF lt_extensionin,
lt_extensioninx TYPE STANDARD TABLE OF bapiparexx,
ls_extensioninx LIKE LINE OF lt_extensioninx,
lt_messages TYPE bapiret2_t,
ls_bapi_te_mara TYPE bapi_te_mara,
ls_bapi_te_marax TYPE bapi_te_marax.
ls_headdata-material = |{ ls_headdata-material ALPHA = IN }|.
ls_headdata-basic_view = 'X'.
ls_bapi_te_mara-material = ls_headdata-material.
ls_bapi_te_mara-zztest1 = '322223'.
ls_bapi_te_marax-material = ls_headdata-material.
ls_bapi_te_marax-zztest1 = 'X'.
ls_extensionin-structure = 'BAPI_TE_MARA'.
ls_extensionin-valuepart1 = ls_bapi_te_mara
APPEND ls_extensionin TO lt_extensionin.
ls_extensioninx-structure = 'BAPI_TE_MARAX'.
ls_extensioninx-valuepart1 = ls_bapi_te_marax-zztest1.
APPEND ls_extensioninx TO lt_extensioninx.
CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
EXPORTING
headdata = ls_headdata
TABLES
returnmessages = lt_messages
extensionin = lt_extensionin
extensioninx = lt_extensioninx.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = 'X'.
Based on this you can model your .Net code for BAPI calling.
P.S. Pay attention to the first line with ALPHA = IN. The input to the material number field must be in fully qualified 18-char format with leading zeroes, e.g. 000000000000323, otherwise the update will fail.
Always extend structure EMARA and not MARA, BAPI_TE_MARA, ... directly.
In a SAP database there are values formatted as PxDTyH where x is the number of days and y is the number of hours. A value like P2DT0H is 2 days + 0 hours. I can see that via SE16:
Unfortunately, this is exactly displayed like that to the user, "3" corresponds to the index in the database (not seen in the screenshot above).
I'd like to see it displayed
without the index (changing the options "show keys within drop-down lists" did not have an effect)
instead of the technical name P2DT0H I'd like to see "2 days and 0 hours" (or similar)
Is there a way to process the data before it gets displayed in the combo box? The developers can't change the format in the database because it would change the API.
FYI: I'm just a tester, I don't know how to code in ABAP, but from knowledge of other programming languages, I'd say that the data can be converted before it's displayed. I don't need a fully-fledged answer, just a pointer to a SAP hook or event which enables writing a conversion function.
Probably, conversion routines can be an option for you. What you should do is to:
Take your domain (which is used for PxDTyH values) or create new one specially for this.
Create FM with name CONVERSION_EXIT_%NAME%_OUTPUT, and put conversion logic in there. Mandatory parameters INPUT and OUTPUT should exist.
Enter the %NAME% into Convers.routine field in domain properties.
Enable Check conversion exits checkbox in user parameters.
More info is here.
I have just started writing a program using ABAP, I have a screen (named 9007) that contains an Input/Output field and I want to fill it with a variable from my database.
The beginning looks like this :
PROGRAM ZMCQ.
MODULE USER_COMMAND_9007 INPUT.
SELECT SINGLE FIELD1
FROM ZTABLE_NAME INTO ??? *it doesn't work to put the field name there *
WHERE FIELD2 EQ 3.
ENDMODULE.
I am stuck here and I don't know how should I do that .. help please x)
You have to declare a global variable in your Report. Than got to your to Dynpro Settings to the Tab "Elementlist" an put the variable name in line of your I/O field.
After this you have the connection between your Dynpro-Field and a variable.
I am new to ABAP.
I have a requirement in abap.In my presentation server ,there is header text file, which I want to upload data from that text file to Header table. But the custom table is having different structure from text file.
It includes extra 4 fields- PO_CREATED_DATE, PO_CREATED_BY, PO_CHANGED_DATE, PO_CHANGED_BY.
These fields have to populate from our report program using sy-datum and sy-uname.
In this scenario,we have to check,If the data is existing then populate
PO_CHANGED_DATE, PO_CHANGED_BY and if the data is not there,then populate PO_CREATED_DATE, PO_CREATED_BY.
Please let me know the logic...
first load the file into an internal table with only 1 very long field (long enough to contain at least the longest possible line in the file). Then loop over that itab and split the individual lines using the separator that is used in the file. You split the contents into a work area that contains all your fields, including the 4 extra fields that may or may not be included in the file. Make sure to clear the work area before splitting the line into the WA. Append the work area to an itab with the same structure as the wa, then continue with the next line.
After that, loop over that second itab and check for lines where your 4 extra fields are initial. Those are the lines where you need to add the data by code. After that, do whatever you need to do with the data in the itab.
I uploaded text file header data to it_input1 using gui_upload.But the it_input1 is not having extra 4 fields.I declared another itable it_header which is having the same structure as Header custom table.Now i wnt to check whether the data in the it_input 1 is alredy existing or not.If existing ,populate it_header-po_changed_date and it_header-po_changed_by or else, it_header-po_created_date and it_header-po_created_by.
Take a look to the "Pattern" Button on top. Select ABAP Objects an press enter.
Now you can supply the class and methdo you want to call.
CL_GUI_FRONTEND_SERVICES=>GUI_UPLOAD
GUI_UPLOAD is a static method. If you are new that is the easiest way to see which parameters must be supplied. With the forward navigation (double-click) you can check the signature for typing the parameter variables.
Then you just need to convert your data (e.g. SPLIT). I can only recommend to use the F1-Help.
Kind regards!
Is there any way of programmatically getting the value of a Text Symbol at runtime?
The scenario is that I have a simple report that calls a function module. I receive an exported parameter in variable LV_MSG of type CHAR1. This indicates a certain status message created in the program, for instance F (Fail), X (Match) or E (Error). I currently use a CASE statement to switch on LV_MSG and fill another variable with a short description of the message. These descriptions are maintained as text symbols that I retrieve at compile time with text-MS# where # is the same as the possible returns of LV_MSG, for instance text-MSX has the value "Exact Match Found".
Now it seems to me that the entire CASE statement is unnecessary as I could just assign to my description variable the value of the text symbol with ID 'MS' + LV_MSG (pseudocode, would use CONCATENATE). Now my issue is how I can find a text symbol based on the String representation of its ID at runtime. Is this even possible?
If it is, my code would look cleaner and I wouldn't have to update my actual code when new messages are added in the function module, as I would simply have to add a new text symbol. But would this approach be any faster or would it in fact degrade the report's performance?
Personally, I would probably define a domain and use the fixed values of the domain to represent the values. This way, you would even get around the string concatenation. You can use the function module DD_DOMVALUE_TEXT_GET to easily access the language-dependent text of a domain value.
To access the text elements of a program, use a function module like READ_TEXT_ELEMENTS.
Be aware that generic programming like this will definitely slow down your program. Whether it would make your code look cleaner is in the eye of the beholder - if the values change rarely, I don't see why a simple CASE statement should be inferior to some generic text access.
Hope I understand you correctly but here goes. This is possible with a little trickery, all the text symbols in a report are defined as variables in the program (with the name text-abc where abc is the text ID). So you can use the following:
data: lt_all_text type standard table of textpool with default key,
lsr_text type ref to textpool.
"Load texts - you will only want to do this once
read textpool sy-repid into lt_all_text language sy-langu.
sort lt_all_Text by entry.
"Find a text, the field KEY is the text ID without TEXT-
read table lt_all_text with key entry = i_wanted_text
reference into lsr_text binary search.
If you want the address you can add:
field-symbols: <l_text> type any.
data l_name type string.
data lr_address type ref to data.
concatenate 'TEXT-' lsr_text->key into l_name.
assign (l_name) to <l_text>.
if sy-subrc = 0.
get reference of <l_text> into lr_address.
endif.
As vwegert pointed out this is probably not the best solution, for error handling rather use message classes or exception objects. This is useful in other cases though so now you know how.