Displaying variables inside message statement in ABAP - abap

How do I display a variable inside a message statement, without using a message class?
IF acct_bal < min_bal.
MESSAGE 'customer balance less than minimum. Balance-->', acct_bal TYPE 'E'.
ENDIF.
My program has a syntax error since the system does not allow acct_bal into the message statement. I don't want to use a message class with placeholders to do this:
Program z_test.
DATA: acct_bal TYPE 'I' value 10,
min_bal TYPE 'I' value 100.
IF acct_bal < min_bal.
MESSAGE 'customer balance less than minimum. Balance-->', acct_bal type 'E'.
ENDIF.

There are lots of possibilities. Here are some of them.
What you want can be achieved using a string template (works as of ABAP 7.02) e.g. |text and { variable }|:
MESSAGE |customer balance less than minimum. Balance-->{ acct_bal }| TYPE 'E'.
Or if you want your message to be translatable via a text symbol:
MESSAGE |{ replace( val = 'customer balance less than minimum. Balance-->&1'(001)
sub = '&1' with = acct_bal ) }| TYPE 'E'.
Or if you want your message be translatable via a message class, create a Message ID via transaction code SE91, with the text customer balance less than minimum. Balance-->&1, for instance the ID 001 in the message class ZMSGCLASS:
MESSAGE e001(zmsgclass) TYPE 'E' WITH acct_bal.
Etc.
More information in ABAP Documentation - MESSAGE.

Related

Date format from 2020.11.20 to 11/2020

I'm trying to change the date format from 2020.11.20 to 11/2020
My objective is to remove the day and leave just month/year.
If I change the type of the field EDATU from vbep-EDATU to string it doesn't work.
Any tips on how to achieve my goal?
DATA: GR_COLUMNS TYPE REF TO CL_SALV_COLUMNS_TABLE,
GR_TABLE TYPE REF TO CL_SALV_TABLE.
TYPES: BEGIN OF IT_STR,
EDATU TYPE VBEP-EDATU,
vbeln type vbep-vbeln,
END OF IT_STR.
DATA: IT_FINAL TYPE STANDARD TABLE OF IT_STR.
FIELD-SYMBOLS: <F_DAT> TYPE IT_STR.
SELECT EDATU vbeln FROM VBEP INTO TABLE IT_FINAL up to 10 rows.
LOOP AT IT_FINAL ASSIGNING <F_DAT>.
<F_DAT>-EDATU = <F_DAT>-EDATU+4(2) && '/' && <F_DAT>-EDATU(4).
ENDLOOP.
TRY.
CALL METHOD CL_SALV_TABLE=>FACTORY
EXPORTING
LIST_DISPLAY = IF_SALV_C_BOOL_SAP=>FALSE
IMPORTING
R_SALV_TABLE = GR_TABLE
CHANGING
T_TABLE = IT_FINAL.
CATCH CX_SALV_MSG .
ENDTRY.
GR_COLUMNS = GR_TABLE->GET_COLUMNS( ).
CALL METHOD GR_TABLE->DISPLAY.
Even though a type D is really just a char based data type of length 8 it has some special behavior when outputting it. If you check in the debugger you will see the data in IT_FINAL is what you want, it's just that the ALV processes this data as a date regardless of the value in it.
So, for example date 20221019 got changed in IT_FINAL-EDATU to '10/2022'. Now, when you display it in the ALV it gets interpreted as a date and gets displayed depending on your user settings, assuming yours are yyyy.mm.dd the output would be: '10/2.02.2'.
You can get around this in two ways:
Add a new field to your table with a char-like type to hold the month value as suggested by Skin, and suppress the display of the EDATU field in the ALV
gr_columns->get_column( columnname = 'EDATU' )->set_technical( abap_true ).
Change the behavior of the EDATU column in the ALV by changing the edit mask with:
gr_columns->get_column( columnname = 'EDATU' )->set_edit_mask('_______').
Option 1 is clearly the better way to avoid unintended mishaps in the future.
I created a new colum type C and changed the loop to
LOOP AT IT_FINAL ASSIGNING <F_DAT>.
data(month) = <F_DAT>-EDATU+4(2).
data(year) = <F_DAT>-EDATU(4).
<f_dat>-char = month && '/' && year.
ENDLOOP.
Thanks for everyone who helped me.

Why do I get runtime error DBSQL_DBSL_LENGTH_ERROR?

I have the following code:
DATA: lt_matnr TYPE TABLE OF mara,
ls_matnr TYPE mara,
lv_werk TYPE werks_d VALUE 'WERK',
lt_stoc_int TYPE TABLE OF zmm_s_stock_list,
lt_stoc TYPE TABLE OF zsd_stock_list,
ls_stoc TYPE zsd_stock_list.
SELECT matnr
FROM mara
INTO CORRESPONDING FIELDS OF TABLE lt_matnr.
LOOP AT lt_matnr INTO ls_matnr.
CALL FUNCTION 'Z_MM_LIST_STOC_MATERIAL_WERKS'
EXPORTING
IP_MATNR = ls_matnr-matnr
IP_WERKS = lv_werk
IMPORTING
ET_STOCK_EXP = lt_stoc_int.
LOOP AT lt_stoc_int ASSIGNING FIELD-SYMBOL(<ls_stoc_int>).
MOVE-CORRESPONDING <ls_stoc_int> TO ls_stoc.
* + other data processing ...
APPEND ls_stoc TO lt_stoc.
ENDLOOP.
ENDLOOP.
INSERT zsd_stock_list FROM TABLE lt_stoc.
Everything works fine until the INSERT statement where I get the following short-dump:
Runtime error: DBSQL_DBSL_LENGTH_ERROR
Exception: CX_SY_OPEN_SQL_DB
Error analysis:
An exception has occurred which is explained in more detail below. The
exception, which is assigned to class 'CX_SY_OPEN_SQL_DB' was not caught an
therefore caused a runtime error. The reason for the exception is:
While accessing a database, the length of a field in ABAP does not
match the size of the corresponding database field.
This can happen for example if a string is bound to a database field
that is shorter than the current string.
It makes little sense because lt_stoc is TYPE TABLE OF zsd_stock_list, how can the field length not match ?

Check if message id exists

I am using the MESSAGE function and I want to know how I can find out if the message id exists or not.
For example:
I defined a message with the id "001" in my message class "test_message".
Then I call it like this: MESSAGE e001(test_messages) WITH 'Test'.
I retrieve it in another function from sy
When I do MESSAGE e000(test_messages) WITH 'Test'.
the values in sy are the same (except for the id of course). But in that case I want to change my process because I never created a message with the id 000.
I don't know where else to check if the id actually exists or not.
You can do a SELECT versus the table T100. If you can find your message, it exists :P
Something like
SELECT "just anything that fits your needs, with or without SINGLE
"UP TO 1 ROWS if you will not use the table's PK
FROM T100
INTO "field or fieldlist that fits your needs
WHERE ARBGB = "your ID
AND MSGNR = "your number.
"ENDSELECT. if you use UP TO 1 ROWS
IF sy-subrc = 0. "it exists
VXLozano's answer is appropriate but could be improved in performance by providing also the language field and retrieving only the TEXT field. Doing so allows you to add the "SINGLE" option and speed-up your message look-up.
SELECT SINGLE TEXT
FROM T100
INTO dummyfield
WHERE SPRSL = SY-LANGU
AND ARBGB = "Your ID"
AND MSGNR = "your Number".
IF sy-subrc = 0.
"the requested message in the message class exists for your current language
ENDIF.

How to check if there is initial value and duplicate entry?

I have an ABAP program to add records into the database. I would like to check if there is the same identification number in the database and if so raise an error message. The second thing, if user passes the id field as empty I would like to raise an error message.
MY METHOD TO ADD RECORDS INTO DATABASE
METHOD add.
DATA: IT_E TYPE TABLE OF ZE.
DATA:WA_E TYPE ZE.
IF sy-subrc EQ 0.
WA_E-ID = C_ID.
WA_E-NAME = C_NAME.
APPEND wa_e TO it_e.
INSERT ZE FROM TABLE it_e.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'Message2'
TEXTLINE1 = 'Record Added Successfully.'.
IF sy-subrc <> 0.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'Message2'
TEXTLINE1 = 'YOu cant use this id no'.
ENDIF.
DATA : ref_obj TYPE REF TO LCL_E.
MAIN PART
START-OF-SELECTION.
IF ra_add EQ 'X'.
IF pa_id eq space.
CALL FUNCTION 'POPUP_TO_DISPLAY_TEXT'
EXPORTING
TITEL = 'Message2'
TEXTLINE1 = 'You cant pass id field empty'.
else.
CREATE OBJECT ref_obj
EXPORTING
im_id = pa_id
im_name = pa_name
CALL METHOD ref_obj->add.
endif.
For the first issue I would recommend to make a SELECT with the key before the INSERT to ensure that record exists in table, if it does display the message else make the INSERT. For the second issue you should use "IF lv_data IS INITIAL".
1)You can make the field mandatory using the keyword OBLIGATORY.
PARAMETERS : pa_id type c OBLIGATORY.
2) Try to retrieve the record from database using the id.if the sy-subrc <> 0 then insert the record ,else raise the error message.

Why INSERT into internal table fails?

I have a Problem with ABAP. I have the following code from a book:
METHOD make_reservation.
DATA: license_plate TYPE zcars-license_plate,
reservation_wa LIKE LINE OF reservation_tab,
reservation_num TYPE i,
mess TYPE string.
reservation_num = lines( reservation_tab ).
SELECT license_plate FROM zcars INTO (license_plate) WHERE category = category.
LOOP AT reservation_tab
TRANSPORTING NO FIELDS
WHERE license_plate = license_plate
AND NOT ( date_from > date_to OR date_to < date_from ).
ENDLOOP.
IF sy-subrc <> 0.
reservation_wa-reservation_id = reservation_num + 1.
reservation_wa-customer_id = customer.
reservation_wa-license_plate = license_plate.
reservation_wa-date_from = date_from.
reservation_wa-date_to = date_to.
INSERT reservation_wa INTO TABLE reservation_tab.
IF sy-subrc <> 0.
CONCATENATE license_plate ' reserved!' INTO mess.
MESSAGE mess TYPE 'I'.
ELSE.
MESSAGE 'internal error!' TYPE 'I' DISPLAY LIKE 'E'.
LEAVE PROGRAM.
ENDIF.
RETURN.
ENDIF.
ENDSELECT.
RAISE EXCEPTION TYPE zcx_no_car_available.
ENDMETHOD.
the problem is the line INSERT reservation_wa INTO TABLE reservation_tab. which does not run correctly and I always get sy-subrc <> 0. This results to the message "internal error!"
now my question: I tired to debug it, but I cant find the reason why this statement does not insert the data. How can I find out a detailed error message what went wrong with this SQL statement?
This snipplet tests for not equal 0:
INSERT reservation_wa INTO TABLE reservation_tab.
IF sy-subrc <> 0.
CONCATENATE license_plate ' reserved!' INTO mess.
MESSAGE mess TYPE 'I'.
ELSE.
MESSAGE 'internal error!' TYPE 'I' DISPLAY LIKE 'E'.
LEAVE PROGRAM.
ENDIF.
I always prefer to test for equality (that's easier to read). The similar coding for your code:
INSERT reservation_wa INTO TABLE reservation_tab.
IF sy-subrc = 0.
MESSAGE 'internal error!' TYPE 'I' DISPLAY LIKE 'E'.
LEAVE PROGRAM.
ELSE.
CONCATENATE license_plate ' reserved!' INTO mess.
MESSAGE mess TYPE 'I'.
ENDIF
In plain text: If the insert is successful (return code == 0), then report an error. If the insert is not successful, then inform about the correct reservation.
I don't know your exact requirement, but it seems you mix up the if/else branch in your code.
In ABAP, sy-subrc == 0 always means success. Your code seems to have a problem since the success is associated with any other value.
If you put a breakpoint in your code just before the insert, you'll be able to check that the insertion was a success.
You can check the possible return values of an instruction by putting the cursor on it and using the F1 key. this will launch the help/documentation.
Regards