Amount Field Length Extension: Code Adaptations (2 decimals / 3 decimals) - abap

While preparing for the conversion to S/4HANA, our custom code check produces following error message:
Old Arithmetic type conflict (Type DMBTR, Note: 0002610650) P(13,3)
I have recreated the problem in a simple demo program.
DATA: punit TYPE dmbtr, "curr(23,2)
two TYPE dmbtr VALUE '12.55', "curr(23,2)
three TYPE menge_d VALUE '5.123'. "quan(13,3)
CATCH SYSTEM-EXCEPTIONS arithmetic_errors = 4.
punit = two / three.
ENDCATCH.
WRITE (26) punit.
The error is in the line punit = two / three.
I've already checked the SAP Note 2610650 but can not find any useful information in it. Hope you can help me.

With the new data type dmbtr_cs it worked fine. (see SAP Note 2628040)
DATA: punit TYPE dmbtr_cs,
two TYPE dmbtr_cs VALUE '12.55',
three TYPE menge_d VALUE '5.123'.
CATCH SYSTEM-EXCEPTIONS arithmetic_errors = 4.
punit = two / three.
ENDCATCH.
WRITE (26) punit.

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 ?

Converting MATNR via conversion exit fails for custom table

I'm trying to select the latest date of a material movement from MSEG, but the material needs to be in stock and that is sourced from a bespoke table which uses unconverted Material names.
I've tried using the CALL FUNCTION 'CONVERSION_EXIT_MATN1_OUTPUT' (and INPUT) but I'm not sure how to properly utilize it in a select statement.
IF MSEG-BWART = '101'.
CALL FUNCTION 'CONVERSION_EXIT_MATN1_OUTPUT'
EXPORTING
INPUT = ZBJSTOCK-ZMAT10
IMPORTING
OUTPUT = WA2-MATNR.
SELECT MAX( BUDAT_MKPF )
FROM MSEG
INTO GRDT
WHERE MATNR = WA2-MATNR.
ENDIF.
Currently, WA2-MATNR seems to come out as blank and therefore is not pulling the data from MSEG.
You shouldn't use conversion exit here. Material number in SAP tables lays in internal (INPUT) format and you are converting it into readable format (OUTPUT) in order to query table. It is obvious you will not find anything.
Sample:
MATNR internal format (for OUT exits)
000000000000025567
MATNR external format (for IN exits)
25567
Conversions cases:
000000000000025567 -> CONVERSION_EXIT_MATN1_OUTPUT -> 25567 ✔️
25567 -> CONVERSION_EXIT_MATN1_OUTPUT -> 25567 ❌ nothing changes
25567 -> CONVERSION_EXIT_MATN1_INPUT -> 000000000000025567 ✔️
000000000000025567 -> CONVERSION_EXIT_MATN1_INPUT -> 000000000000025567 ❌ nng changes
Most likely, your bespoke table contains faulty material number so exit doesn't return anything. Or material number in format that exit doesn't expect, e.g. 19 characters instead of 18 and so on.
P.S.
Just for you info, you can use templates for conversion. It is the same as calling conversion FMs
SELECT SINGLE matnr FROM mara INTO #DATA(l_matnr) WHERE EXISTS ( SELECT * FROM mseg WHERE matnr = mara~matnr ).
l_matnr = | { l_matnr ALPHA = OUT } |. <<-- templating
SELECT SINGLE matnr, budat_mkpf
FROM mseg
INTO #DATA(l_mkpf)
WHERE matnr = #l_matnr.
In the above sample SELECT will not return anything, but if you comment out the template line it will.
Unless you’ve added code into the user exits in that function, it’s not going to do what you want. The standard purpose of that function is to format the material number for display on the screen.
The quickest way to do what you want is to select from your custom table to do the lookup.
That said, there is a user exit in that function where you can code the select to do the lookup. The extra benefit of doing that is that your users will be able to type in the legacy material number and the system will switch it with the new one.

Convert work area to the line of type internal table

I am getting this syntax error:
"WA_1" cannot be converted to the line type of "IT_1"
I'm trying to display contents from internal table as follows:
REPORT ZSAM.
DATA: ITable Type ZMUAZ_STRUCTURE OCCURS 10,
IT_1 Type ZSTRUCT1 OCCURS 10,
IT_2 Type ZSTRUCT2 OCCURS 10,
WA_1 like IT_1,
WA_2 like IT_2,
WA_3 like ITable.
WRITE: 'vbeln', 'vtweg', 'posnr', 'matnrr','vrkme'.
select vbeln audat netwr waerk vkorg vtweg from VBAK into corresponding fields of Table IT_1.
LOOP AT IT_1 INTO WA_1.
write: / WA_1-vbeln, WA_1-audat, WA_1-netwr, WA_1-waerk, WA_1-vkorg, WA_1-vtweg.
endloop.
Any idea how to resolve this error?
wa_1 is declared as internal table (not as work area). The simplest solution is to complete the declaration with LINE OF:
... wa_1 LIKE LINE OF it_1,
However declaring internal tables and work areas like you did with OCCURS is obsolete, its modern equivalent is STANDARD TABLE OF :
DATA: it_1 TYPE STANDARD TABLE OF zstruct1,
wa_1 TYPE zstruct1.

SSIS Derived Column Calcuation Issue

I am having an issue with a derived column calculation in SSIS not returning the correct values. To give some background, I had to change the format of my calculation due to an overflow issue (resolved), see here - SSIS - Derived Column Calculation Error
Now, the old and new calculations return different values in SSIS, even though they are both mathematically the same and return the same value when executed in .net, excel and SQL.
In .Net -
decimal test1 = Convert.ToDecimal((415 * 415 * 415) * 0.000000030940000);
decimal test2 = Convert.ToDecimal((0.000000030940000 * 415 * 415 * 415));
both return 2.2113862225
In SSIS -
test1 = ((415 * 415 * 415) * 0.000000030940000)
test2 = (0.000000030940000 * 415 * 415 * 415)
return different values (test1 = 2.2113862225 and test2 = 2.211535)
Interestingly, SSIS sees test1 as a numeric (38,6) and test2 as a numeric (27,15)....
Has anyone encountered this issue before?
I don't really want to have to re-factor the whole package to use .net calculations, however that will be my last resort solution.
In case anyone else has this problem - I didn't find the solution but did implement a workaround -
Instead of doing the calculation in a derived column -
Use the derived column component to reate the variable and set it as 0
Add a data conversion and switch it to the required data type (float in this case)
Add an OLE DB Command to call a stored procedure to do the calculation, with an output parameter filling the variable created at point 1.