ABAP: pass some variables, but the program is giving error - why? - abap

**********the data that i am using************
DATA: BEGIN OF morada,
gpart LIKE fkkvkp-gpart,
vkont LIKE fkkvkp-vkont,
vertrag LIKE ever-vertrag,
name1 TYPE c LENGTH 100,
full_address TYPE c LENGTH 255,
address_1_1 TYPE c LENGTH 60,
address_1_2 TYPE c LENGTH 60,
address_1_3 TYPE c LENGTH 60,
postal_code_1 TYPE c LENGTH 60,
local_1 TYPE c LENGTH 60.
DATA END OF morada.
DATA: BEGIN OF istab, "OCCURS 0,
*aninhamos as tabelas.
color(4) TYPE c,
gpart TYPE fkkvkp-gpart,
vkont TYPE fkkvkp-vkont,
vertrag TYPE ever-vertrag,
vkonto TYPE ever-vkonto.
DATA END OF istab.
DATA: itab LIKE TABLE OF istab WITH HEADER LINE,
p_istab LIKE TABLE OF istab WITH HEADER LINE,
p_morada LIKE TABLE OF morada WITH HEADER LINE.
then in other include.
PERFORM map_data
USING itab
CHANGING p_morada.
FORM map_data USING pt_istab TYPE itab
CHANGING pt_morada TYPE morada.
Endform
in form, he will not going to recognize the 'type itab' neither 'type morada'... why

You are using the DATA statement to declare variables named itab and morada. Then you try to use the USING … TYPE … addition to refer to data types of the same name. This won’t work. Try looking up the keyword documentation for TYPE and use that instead of DATA.

I would vote up vwegert answer but do not have the reputation to do so.
Type code below, along with data and form changes necessary to use the types. You're naming conventions could also use some work but i will leave that to you!
TYPES: BEGIN OF morada,
gpart LIKE fkkvkp-gpart,
vkont LIKE fkkvkp-vkont,
vertrag LIKE ever-vertrag,
name1 TYPE c LENGTH 100,
full_address TYPE c LENGTH 255,
address_1_1 TYPE c LENGTH 60,
address_1_2 TYPE c LENGTH 60,
address_1_3 TYPE c LENGTH 60,
postal_code_1 TYPE c LENGTH 60,
local_1 TYPE c LENGTH 60,
END OF morada.
TYPES: BEGIN OF istab,
color(4) TYPE c,
gpart TYPE fkkvkp-gpart,
vkont TYPE fkkvkp-vkont,
vertrag TYPE ever-vertrag,
vkonto TYPE ever-vkonto,
END OF istab.
DATA: itab TYPE TABLE OF istab,
p_istab TYPE TABLE OF istab,
p_morada TYPE TABLE OF morada.
PERFORM map_data
USING itab
CHANGING p_morada.
FORM map_data USING pt_itab
CHANGING pt_morada.
ENDFORM .

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.

Looping through a dynamic internal table

I am trying to split internal table to smaller chunks.
In below example the internal table big_table is split into small tables.
My question is how do we get the actual data from lt_small_tables for further processing.
TYPES: BEGIN OF lty_line,
column1 TYPE i,
column2 TYPE c LENGTH 4,
END OF lty_line.
CONSTANTS: lc_test_data_amount TYPE i VALUE 44,
lc_split_at_amount TYPE i VALUE 7,
DATA: lt_big_table TYPE STANDARD TABLE OF lty_line,
lv_string TYPE string,
lt_small_tables TYPE STANDARD TABLE OF REF TO data,
lr_small_table TYPE REF TO data.
FIELD-SYMBOLS: <lg_target> TYPE STANDARD TABLE.
" Generate test data
DO lc_test_data_amount TIMES.
CALL FUNCTION 'GENERAL_GET_RANDOM_STRING'
EXPORTING number_chars = 4 " Specifies the number of generated chars
IMPORTING random_string = lv_string. " Generated string
APPEND VALUE #( column1 = sy-index
column2 = CONV #( lv_string ) ) TO lt_big_table.
ENDDO.
" Split
DATA(lo_descr) = CAST cl_abap_tabledescr(
cl_abap_typedescr=>describe_by_data( lt_big_table ) ).
LOOP AT lt_big_table ASSIGNING FIELD-SYMBOL(<ls_line>).
IF ( sy-tabix - 1 ) MOD lc_split_at_amount = 0.
CREATE DATA lr_small_table TYPE HANDLE lo_descr.
ASSERT lr_small_table IS BOUND.
APPEND lr_small_table TO lt_small_tables.
ASSIGN lr_small_table->* TO <lg_target>.
ASSERT <lg_target> IS ASSIGNED.
ENDIF.
APPEND <ls_line> TO <lg_target>.
ENDLOOP.
Thanks,
Kris
There are at least a couple of ways
Solution 1: cast internal table reference into a known type, so that you can directly access its fields.
FIELD-SYMBOLS: <fs_table> like lt_big_table.
LOOP AT lt_small_tables into lr_small_table.
ASSIGN lr_small_table->* TO <fs_table>.
ASSERT <fs_table> IS ASSIGNED.
LOOP AT <fs_table> into data(ls_line).
" do something with line
write: / ls_line-column1, ls_line-column2.
ENDLOOP.
ENDLOOP.
Solution 2: dynamic access to the tables fields
FIELD-SYMBOLS: <generic_fs_table> TYPE ANY TABLE.
LOOP AT lt_small_tables into lr_small_table.
ASSIGN lr_small_table->* TO <generic_fs_table>.
ASSERT sy-subrc = 0.
LOOP AT <generic_fs_table> ASSIGNING FIELD-SYMBOL(<generic_fs_line>).
" dinamically access to line fields
ASSIGN COMPONENT 'COLUMN1' of STRUCTURE <generic_fs_line> to FIELD-SYMBOL(<generic_fs_field1>).
ASSERT sy-subrc = 0.
ASSIGN COMPONENT 'COLUMN2' of STRUCTURE <generic_fs_line> to FIELD-SYMBOL(<generic_fs_field2>).
ASSERT sy-subrc = 0.
" do something with component2
write: / <generic_fs_field1>, <generic_fs_field2>.
ENDLOOP.
ENDLOOP.

SQL query does not return data

I am developing a SAP program to obtain information about a reference from the material table (MARA).
First I take certain references and then using a loop I need to make other query for every iteration:
SELECT
MARA~BISMT
FROM mara
WHERE mara~matnr = #ref
INTO #var.
I know that the problem is that the types conflict (mara~matnr is characters and ref is string), how can I convert both to the same type and see the results?
You can also use ABAP string templates instead of conversion exits suggested by mkysoft:
DATA: ref TYPE string VALUE '2'.
ref = |{ CONV matnr( ref ) ALPHA = in }|.
SELECT SINGLE bismt
FROM mara
WHERE matnr = #ref
INTO #DATA(var).
You can use field symbol for dynamic type and CONVERSION_EXIT_ALPHA_INPUT function module for formatting value for db.
TABLES: mara.
DATA: ref TYPE string,
var TYPE string.
FIELD-SYMBOLS: <fs_ref> TYPE any.
ref = '11'.
ASSIGN ('mara-matnr') TO <fs_ref>.
CHECK sy-subrc IS INITIAL.
<fs_ref> = ref.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = <fs_ref>
IMPORTING
output = <fs_ref>.
SELECT SINGLE mara~bismt
FROM mara
INTO #var
WHERE mara~matnr = #<fs_ref>.

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.

Creating a range for a field from internal table using RTTS

I want to create a function/custom class method that takes in 2 parameters:
1) IM_ITAB type ANY TABLE
2) IM_COMPONENT type STRING
and returns 1 parameter:
1) EX_RANGE type PIQ_SELOPT_T
So, algorithm is like this:
First of all, we check if the column with a component name at all exists
Then, we check that internal table is not empty.
Then, we loop through internal table assigning component and filling range table. Code is below.
METHODS compose_range_from_itab
IMPORTING
IM_ITAB type ANY TABLE
IM_COMPONENT type STRING
EXPORTING
EX_RANGE type PIQ_SELOPT_T.
...
METHOD compose_range_from_itab.
DATA: lo_obj TYPE REF TO cl_abap_tabledescr,
wa_range TYPE selopt,
lt_range TYPE piq_selopt_t.
FIELD-SYMBOLS: <fs_line> TYPE ANY,
<fs_component> TYPE ANY.
lo_obj ?= cl_abap_typedescr=>describe_by_data( p_data = im_itab ).
READ TABLE lo_obj->key TRANSPORTING NO FIELDS WITH KEY name = im_component.
IF sy-subrc IS INITIAL.
IF LINES( im_itab ) GT 0.
LOOP AT im_itab ASSIGNING <fs_line>.
ASSIGN COMPONENT im_component OF STRUCTURE <fs_line> TO <fs_component>.
wa_range-sign = 'I'.
wa_range-option = 'EQ'.
wa_range-low = <fs_component>.
APPEND wa_range TO lt_range.
ENDLOOP.
SORT lt_range BY low.
DELETE ADJACENT DUPLICATES FROM lt_range COMPARING low.
ex_range[] = lt_range[].
ENDIF.
ENDIF.
ENDMETHOD.
But I want to improve the method further. If the imported internal table has, let's say, 255 columns, then it will take longer to loop through such table. But I need only one column to compose the range.
So I want to get components of internal table, then choose only one component, create a new line type containing only that component, then create internal table with that line type and copy.
Here is the pseudo code corresponding to what I want to achieve:
append corresponding fields of im_itab into new_line_type_internal_table.
How can I "cut out" one component and create a new line type using RTTS?
You are overcomplicating everything, you don't need RTTS for that.
DEFINE make_range.
ex_range = VALUE #( BASE ex_range ( sign = 'I' option = 'EQ' low = &1 ) ).
END-OF-DEFINITION.
LOOP AT im_itab ASSIGNING FIELD-SYMBOL(<fs_line>).
ASSIGN COMPONENT im_component OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_field>).
CHECK sy-subrc = 0 AND <fs_field> IS NOT INITIAL.
make_range <fs_field>.
ENDLOOP.
And yes, as Sandra said, you won't gain any performance with RTTS, just the opposite.
Surprisingly, this variant turned out to be faster:
CLASS-METHODS make_range_variant_2
IMPORTING
sample TYPE table_type
column TYPE string
RETURNING
VALUE(result) TYPE range_type.
METHOD make_range_variant_2.
TYPES:
BEGIN OF narrow_structure_type,
content TYPE char32,
END OF narrow_structure_type.
TYPES narrow_table_type TYPE STANDARD TABLE OF narrow_structure_type WITH EMPTY KEY.
DATA narrow_table TYPE narrow_table_type.
DATA(mapping) =
VALUE cl_abap_corresponding=>mapping_table_value(
( kind = cl_abap_corresponding=>mapping_component srcname = column dstname = 'CONTENT' ) ).
DATA(mover) =
cl_abap_corresponding=>create_with_value(
source = sample
destination = narrow_table
mapping = mapping ).
mover->execute(
EXPORTING
source = sample
CHANGING
destination = narrow_table ).
LOOP AT narrow_table ASSIGNING FIELD-SYMBOL(<row>).
INSERT VALUE #(
sign = 'I'
option = 'EQ'
low = <row>-content )
INTO TABLE result.
ENDLOOP.
ENDMETHOD.
CL_ABAP_CORRESPONDING delegates to a kernel function for the structure-to-structure move, which apparently is faster than the ABAP-native ASSIGN COMPONENT [...] OF STRUCTURE [...] TO FIELD-SYMBOL [...]. The actual loop then seems to be faster because it uses fixed-name assignments.
Maybe somebody could verify.
I would not go for a Macro.
Data:
lr_data type ref to data.
FIELD-SYMBOLS:
<lv_component> TYPE any,
<ls_data> TYPE any.
CREATE DATA lr_data LIKE LINE OF im_itab.
ASSIGN lr_data->* TO <ls_data>.
"Check whether im_component exists
ASSIGN COMPONENT im_component OF STRUCTURE <ls_data> TO <lv_component>.
CHECK sy-subrc EQ 0.
LOOP AT im_itab INTO <ls_data>.
APPEND VALUE #( sign = 'I' option = 'EQ' low = <lv_component> ) TO ex_range.
ENDLOOP.