‎2020 Apr 05 6:01 PM
Hi, im new to abap and currently learning badi.
I inserted simple logic in Z Badi Interface in Method
IV_MATNR Importing Type MARA-MATNR
LS_MARA Changing Type MARA
GT_MARA Changing Type MARA
select matnr mtart INTO gt_mara FROM mara
WHERE matnr eq iv_matnr.
if sy-subrc <> 0.
clear gt_mara.
ELSE.
write: / , / ls_mara-matnr, ls_mara-mtart.
endif.
ENDSELECT.
Im trying to call classic badi in program. Once selected material in parameter and execute, the output is empty.
Please correct me if there are any mistakes, thanks
Program code:
DATA o_badi TYPE REF TO ZIF_EX_ABAP_BADI. ""Classic BADi interface name
DATA: gt_mara TYPE zmara_ttyp WITH HEADER LINE.
DATA: gs_mara LIKE LINE OF gt_mara.
PARAMETERS: p_matnr like gs_mara-matnr.
START-OF-SELECTION.
CALL METHOD CL_EXITHANDLER=>GET_INSTANCE ""call this method create instance for Classic BADI definition
EXPORTING
EXIT_NAME = 'ZABAP_BADI' ""classic BADi definition
* NULL_INSTANCE_ACCEPTED = SEEX_FALSE
* IMPORTING
* ACT_IMP_EXISTING =
CHANGING
INSTANCE = o_badi
* EXCEPTIONS
* NO_REFERENCE = 1
* NO_INTERFACE_REFERENCE = 2
* NO_EXIT_INTERFACE = 3
* CLASS_NOT_IMPLEMENT_INTERFACE = 4
* SINGLE_EXIT_MULTIPLY_ACTIVE = 5
* CAST_ERROR = 6
* EXIT_NOT_EXISTING = 7
* DATA_INCONS_IN_EXIT_MANAGEM = 8
* OTHERS = 9
.
*IF SY-SUBRC <> 0.
** Implement suitable error handling here
*ENDIF.
CALL METHOD O_BADI->MAT_DETAILS
EXPORTING
IV_MATNR = p_matnr
CHANGING
LS_MARA = gs_mara
GT_MARA = gt_mara .
LOOP AT gt_mara INTO gs_mara.
WRITE: gs_mara-matnr,
gs_mara-mtart.
ENDLOOP.
‎2020 Apr 06 4:35 AM
I see several ways to 'improve' your coding, but the main problem is the content of your badi-implementation and how you deal with tables that have a header line. For a better solution, see the end of the answer. First, here is what 'went' wrong
1. You use SELECT...ENDSELECT, which will only fetch one record at a time and write the record into a structure (and not a table, see ABAP documentation on ENDSELECT😞
SELECT matnr mtart INTO gt_mara FROM mara WHERE matnr EQ iv_matnr.
...
ENDSELECT.This way, the table of the variable GT_MARA[] never gets filled, but the structure of the variable GT_MARA gets filled. In most cases, ABAP will choose the right 'part' (either table or structure) of a table with header line depending on the context. And in some cases this can be 'wrong' or not possible. For more infos see ABAP documentation on Internal Tables with Header Line.
2. When a Record is found, you use the WRITE (to screen output) statement on an empty variable:
WRITE: / , / ls_mara-matnr, ls_mara-mtart.
The variable LS_MARA has never been set, neither by your report, nor by the badi method. But you are still trying to read from it. And even worse, you are trying to write to the screen output, which in most cases of a Badi would not be ok, unless you were just trying to test your coding.
3. You are trying to obviously handle an unsuccessful call within the SELECT...ENDSELECT statement, instead of afterwards.
SELECT ... .
IF sy-subrc <> 0.
clear: gt_mara.
ENDIF.
ENDSELECT.This coding for the IF-clause will never be reached, because the inside of a SELECT...ENDSELECT is only processed for each record found (sy-subrc = 0), and if there is no record found, the sy-subrc will be <> 0 and the coding will continue after the ENDSELECT (see the setting of sy-subrc in ABAP documentation about SELECT.
UPDATE: 4. You define GT_MARA as TABLE with HEADER LINE in your report, but the BADI only uses the header line structure of GT_MARA in the CHANGING parameter. The table of GT_MARA never gets set.
CALL METHOD O_BADI->MAT_DETAILS
EXPORTING
IV_MATNR = p_matnr
CHANGING
LS_MARA = gs_mara
GT_MARA = gt_mara. " -> this obviously a just using the structure
APPEND gt_mara. " -> this is how you would make your following coding workSolution [A] with SELECT...INTO <structure>...ENDSELECT:
UPDATE: Since GT_MARA is a CHANGING parameter and the type is defined as a structure, your changing parameters ls_mara and gt_mara are of the same type and you do not add any functionality to your coding by having both. The following coding has been updated to work for your coding though:
CLEAR: gt_mara, ls_mara.
SELECT matnr mtart INTO gt_mara FROM mara WHERE matnr EQ iv_matnr.
ls_mara = gt_mara.
ENDSELECT.
IF sy-subrc <> 0.
" ...
ENDIF.Solution [B] with SELECT...INTO TABLE <table>:
UPDATE: Can only be used if the interface parameter GT_MARA is a TABLES parameter and not a CHANGING parameter. As a TABLES parameter it is a TABLE TYPE with HEADER LINE. As a CHANGING parameter it is either or, but not both, and it depends on the given TYPE. And obviously the given TYPE is a structure and not a table.
SELECT matnr mtart INTO TABLE gt_mara[] FROM mara WHERE matnr EQ iv_matnr.
IF sy-subrc <> 0.
" ...
ENDIF.UPDATE: Solution [C] with SELECT SINGLE...INTO <fields>:
SELECT SINGLE matnr mtart INTO (ls_mara-matnr, ls_mara-mtart) FROM mara WHERE matnr EQ iv_matnr.
IF sy-subrc = 0.
gt_mara = ls_mara.
ELSE
clear: gt_mara, ls_mara.
ENDIF.UPDATE: I would make the following changes to your BADI and Report coding:
‎2020 Apr 06 11:09 AM
Hi, thanks for your reply. When I used solution A, it is showing me this error:
"GT_MARA" is not an internal table. "OCCURS n" specification is missing.
When i tried to remove endselect in solution B, it says "incorrect Nesting, Select must be closed by Endselect", which is why i put endselect.at the statement
When i changed the following from
if sy-subrc <> 0.
clear gt_mara.
ELSE.
write: / , / ls_mara-matnr, ls_mara-mtart.
endif.
To:
if sy-subrc <> 0.
clear gt_mara.
ELSE.
write: / , / gt_mara-matnr, gt_mara-mtart.
endif.
It is only showing one field - mtart in the output
‎2020 Apr 06 4:24 PM
arnold92, see my "UPDATES:" in the original answer.
As a first start, try Solution [C] as of right now.
If you continue having your issue with "It is only showing one field - mtart in the output", can you provide a screenshot of that.
Also, can you provide the defintion of your structure type zmara_ttyp.
‎2020 Apr 08 11:10 AM
Hi Michael thanks for your answer, it works. For zmara_ttyp it's a table type where i inserted mara.
I have another question about calling new badi, it prompts error "No value was passed to the mandatory parameter "IV_ACT". I have marked parameters as "pass in value" yet problem persists
Report:
DATA: w_badi type REF TO ZABAP03_BADI_ENHANCEMENT.
DATA: ev_percentage TYPE p.
PARAMETERS: iv_act TYPE i.
PARAMETERS: iv_max TYPE i.
TRY.
GET BADI w_badi.
call BADI w_badi->cal_perc.
ENDTRY.
The badi is calling a method from a superclass

‎2020 Apr 08 11:47 AM
A S, I have answered your question and you say that it works, so please mark as answered, vote up, like or close this question and especially dont answer more question in this thread that are unrelated to the original question, especially when you already have an open question that deals with the same issue (which I have answered by the way just now for you as well).
PS: Why do you use two accounts to post same and similar questions at the same time gheing.sheng.sao?
‎2020 Apr 06 11:06 AM
Just a tip since you are learning: Kernel BAdI's are the new (and faster) way to have BAdI's on code, put that on you list.
"HEADER LINE" is a obsolete instruction because it causes troubles exactly like you passed and michael.piesche detailed (TABLE with HEADER LINE is both a structure and a internal table). You should cross it from your study.
‎2020 Apr 06 12:31 PM
When I removed With Header Line, it is showing error ïnternal tables/structures not compatible (between the methods and the program) even though i changed several times
‎2020 May 13 3:54 PM
gheing.sheng.sao, please follow up on your open question.