What is wrong with the following ABAP code - abap

REPORT zbc400_figure157.
TYPES: BEGIN OF t_conn,
cityfrom TYPE spfli-cityfrom,
cityto TYPE spfli-cityto,
carrid TYPE spfli-carrid,
connid TYPE spfli-connid,
END OF t_conn.
DATA:
conn_list LIKE STANDARD TABLE OF t_conn,
startline LIKE sy-tabix,
BEGIN OF wa_travel,
dest TYPE spfli-cityto,
cofl_list LIKE conn_list,
END OF wa_travel,
travel_list LIKE SORTED TABLE OF wa_travel WITH UNIQUE KEY dest.
FIELD-SYMBOLS:
<fs_conn> TYPE t_conn,
<fs_conn_int> TYPE t_conn,
<fs_travel> TYPE wa_travel.
PARAMETERS pa_start TYPE spfli-cityfrom DEFAULT 'FRANKFURT'.
SELECT carrid cityfrom cityto
FROM spfli
INTO CORRESPONDING FIELDS OF TABLE conn_list.
SORT conn_list BY cityfrom cityto ASCENDING AS TEXT.
** build up nested table.
LOOP AT conn_list ASSIGNING <fs_conn> WHERE cityfrom = pa_start.
CLEAR wa_travel.
wa_travel-dest = <fs_conn>-cityto.
READ TABLE conn_list
WITH KEY cityfrom = wa_travel-dest
TRANSPORTING NO FIELDS
BINARY SEARCH.
startline = sy-tabix.
LOOP AT conn_list ASSIGNING <fs_conn_int>
FROM startline.
IF <fs_conn_int>-cityfrom <> wa_travel-dest.
EXIT.
ENDIF.
APPEND <fs_conn_int> TO wa_travel-cofl_list.
ENDLOOP.
SORT wa_travel-cofl_list BY cityto carrid ASCENDING AS TEXT.
INSERT wa_travel INTO TABLE travel_list.
ENDLOOP.
Error: Field "T_CONN" is unknown. It is neither in one of the specified tables nor defined by a "DATA" statement . . . . . . . . . .
We declare an inner table COFL_LIST and an outer table TRAVEL_LIST with corrosponding work areas. An internal table CONN_LIST buffers all of the flight connections and sorts them.
The program uses 3 tables, inner table, outer table and an internal table.
I made the changes in the program as suggested by LPK:
conn_list TYPE STANDARD TABLE OF t_conn,
However, now the problem is in line:
FIELD-SYMBOLS:
<fs_conn> TYPE t_conn,
<fs_conn_int> TYPE t_conn,
<fs_travel> TYPE wa_travel.
Error: The type "WA_TRAVEL" is unknown.
In the program wa_travel variable is already defined in it's BEGIN OF wa_travel and END OF wa_travel block. Why can't the system pick this up?

This line is wrong:
conn_list LIKE STANDARD TABLE OF t_conn,
T_CONN is a type and therefore you have to use TYPE instead of LIKE.
You can find an explanation about the difference here.

The declaration is not correct...
FIELD-SYMBOLS:
TYPE t_conn,
TYPE t_conn,
TYPE wa_travel.
Should be
FIELD-SYMBOLS:
TYPE t_conn,
TYPE t_conn,
LIKE wa_travel.
You need to check with the link provided in the previous answer... or you can use the following from the Help Portal on TYPE & LIKE

Related

Dynamically read an internal table with more than one key field

Let us say I have the following code:
iob_typedescr ?= cl_abap_typedescr=>describe_by_name( 'HOUSES' ).
iob_structdescr_table ?= iob_typedescr.
it_ddic_all = iob_structdescr_table->get_ddic_field_list( ).
LOOP AT it_ddic_all INTO is_ddic WHERE keyflag EQ 'X'.
APPEND is_ddic TO it_keyfields.
ENDLOOP.
So basically, in the above code I know all of the key fields in the table HOUSES and they are in the table it_keyfields. Now if I had an internal table which had the same structure as HOUSES and wanted to select data from it how would I be able to do this dynamically? If I knew I had only one key then I could do a READ TABLE as follows:
READ TABLE it_internal_table WITH KEY (key_name) = provided_value TRANSPORTING NO FIELDS.
But in this case I may have more than one key in it_keyfields so I am not sure how I could write the READ TABLE statement for this.
You could create a dynamic where condition and use it with LOOP WHERE.
Here is a snippet using table SPFLI as an example.
" variable that contains dynamic where condition later
DATA lv_where TYPE string.
" field-symbol that can contain any data
FIELD-SYMBOLS: <f_field_value> TYPE any.
" define it_internal_table (can be dynamic)
DATA it_internal_table TYPE TABLE OF spfli.
it_internal_table = VALUE #(
( mandt = '001' carrid = '002' connid = '0003' cityfrom = 'PARIS' )
( mandt = '001' carrid = '004' connid = '0005' cityfrom = 'BERLIN' )
).
" define provided values that need to be searched in it_internal_table
DATA(ls_provided_entry) = VALUE spfli( mandt = '001' carrid = '002' connid = '0003' cityfrom = 'PARIS' ).
" create dynamic where condition
LOOP AT it_keyfields ASSIGNING FIELD-SYMBOL(<f_key>).
ASSIGN COMPONENT <f_key>-fieldname OF STRUCTURE ls_provided_entry TO <f_field_value>.
IF sy-subrc = 0.
IF lv_where IS INITIAL.
lv_where = |{ <f_key>-fieldname } = `{ <f_field_value> }`|.
ELSE.
DATA(lv_where_and) = |AND { <f_key>-fieldname } = `{ <f_field_value> }`|.
CONCATENATE lv_where lv_where_and INTO lv_where SEPARATED BY space.
ENDIF.
ENDIF.
ENDLOOP.
" now check with LOOP WHERE if the provided entry exists in it_internal_table
LOOP AT it_internal_table ASSIGNING FIELD-SYMBOL(<f_internal_table_line>) WHERE (lv_where).
" if this point is reached, the entry exists;
" <f_internal_table_line> contains the complete line
WRITE 'The entry exists'.
EXIT.
ENDLOOP.
If you want to handle different numbers of key fields dynamically at runtime then you won't be able to do that with a READ command. However, you can now also read data from an internal table using SELECT and there you can dynamically create a WHERE condition that selects on fields only known during runtime.
From the documentation: Use of SELECT to access an internal table using as an alternative to the statement READ TABLE. Unlike READ TABLE, the statement SELECT offers a (dynamic) WHERE condition and evaluates the field list for the inline declaration. The statement is executed on the AS ABAP and the data in the internal table is not transported to the database.

The field "str_mara" is unknown, but there is a field with the similar name "it_mara"

I want to display the content of Mara table.
types : begin of str_mara,
matnr type mara-matnr,
ernam type mara-ernam,
end of str_mara.
data it_mara type table of str_mara .
select matnr ernam from mara into TABLE it_mara .
loop at it_mara into str_mara.
write:/ str_mara-matnr , str_mara-ernam.
endloop.
Well, there is no variable named str_mara. There is just a type named str_mara.
Just loop using a field symbol as it should be done anyway.
LOOP AT it_mara ASSIGNING FIELD-SYMBOL(<str_mara>).
WRITE: /, <str_mara>-matnr, <str_mara>-ernam.
ENDLOOP.
Type is just a static definition, no memory is allocated, therefore cannot be used on its own.
You can either create a variable with that type or use a inline declaration to create a variable like that.
option 1: data ls_mara type str_mara.
option 2: loop at lt_mara into data(ls_mara).
Or go with Umar's answer :)
BTW, be sure to check your where condition on the access to mara table.
You can also use inline declaration to display content of mara table with fewer line of ABAP code.
SELECT matnr, ernam FROM mara INTO TABLE #DATA(lt_mara) .
LOOP AT lt_mara ASSIGNING FIELD-SYMBOL(<fs_mara>).
WRITE: /, <fs_mara>-matnr, <fs_mara>-ernam.
ENDLOOP.

How to dynamically call Field Symbols

Lets say I have a standard structure assigned to a field symbol. Is there a way to pass a variable to the field symbol for dynamic calls?
Eg:
DATA: lt_mara TYPE STANDARD TABLE OF mara WITH HEADER LINE,
parameter_name(10) TYPE c.
parameter_name = 'MATNR'.
LOOP AT lt_mara ASSIGNING FIELD-SYMBOL(<fs_lt_mara>).
WRITE: <fs_lt_mara>-(parameter_name).
ENDLOOP.
Where the parameter_name contains a column name that is available in the mara structure.
It is possible with ASSIGN instruction.
Below is an example:
DATA: lt_mara TYPE STANDARD TABLE OF mara WITH HEADER LINE,
parameter_name(10) TYPE c.
parameter_name = 'MATNR'.
FIELD-SYMBOLS: <fs_lt_mara> TYPE mara,
<fs_value> TYPE any.
SELECT * FROM mara UP TO 10 ROWS INTO TABLE lt_mara.
LOOP AT lt_mara ASSIGNING <fs_lt_mara>.
ASSIGN COMPONENT parameter_name OF STRUCTURE <fs_lt_mara> TO <fs_value>.
IF sy-subrc = 0.
WRITE: / <fs_value>.
ENDIF.
ENDLOOP.
I provide another example of ASSIGN. You do ASSIGN once and do a LOOP INTO.
DATA: lt_mara TYPE STANDARD TABLE OF mara,
ls_mara TYPE mara,
lc_matnr TYPE char5 VALUE 'MATNR'.
FIELD-SYMBOLS: <ls_mara> TYPE mara,
<lv_value> TYPE any.
SELECT * FROM mara UP TO 10 ROWS INTO TABLE lt_mara.
ASSIGN COMPONENT lc_matnr OF STRUCTURE ls_mara TO <lv_value>.
CHECK <lv_value> IS ASSIGNED.
LOOP AT lt_mara INTO ls_mara.
WRITE: / <lv_value>.
ENDLOOP.

Set parameter name as an internal table name

I wanted to know if it is possible to make the input parameter name as an internal table.
Please have a look in the snippet of the code. In this report I am trying to take p_dbtab as a table name then make an internal table i_temp of the type p_dbtab.
REPORT ZPRACTICDYNAMIC.
SELECTION-SCREEN BEGIN OF BLOCK 1.
PARAMETERS:
p_dbtab TYPE tabname DEFAULT 'FARR_D_FULFILLMT' OBLIGATORY.
SELECTION-SCREEN END OF BLOCK 1.
DATA: it_tab TYPE STANDARD TABLE OF p_dbtab.
this will work:
data: rt_data type REF TO data.
PARAMETERS: p_dbtab TYPE tabname DEFAULT 'FARR_D_FULFILLMT' OBLIGATORY.
FIELD-SYMBOLS: <t_data> type any TABLE.
CREATE DATA rt_data type STANDARD TABLE OF (p_dbtab).
assign rt_data->* to <t_data>.

Add line to dynamic internal table

I want to add a dynamic table line to a dynamic internal table.
DATA: lo_structdescr TYPE REF TO cl_abap_structdescr,
lo_tabledescr TYPE REF TO cl_abap_tabledescr,
lt_components TYPE abap_component_tab,
ls_component TYPE LINE OF abap_component_tab,
lt_keys TYPE abap_keydescr_tab,
lt_table TYPE REF TO data,
ls_table TYPE REF TO data.
FIELD-SYMBOLS: <ls_table> TYPE any,
<lt_table> TYPE ANY TABLE,
<lv_value> TYPE any.
MOVE 'COMP1' TO ls_component-name.
ls_component-type ?= cl_abap_elemdescr=>get_string( ).
INSERT ls_component INTO TABLE lt_components.
MOVE 'COMP2' TO ls_component-name.
ls_component-type ?= cl_abap_elemdescr=>get_i( ).
INSERT ls_component INTO TABLE lt_components.
lo_structdescr ?= cl_abap_structdescr=>create( lt_components ).
CREATE DATA ls_table TYPE HANDLE lo_structdescr.
ASSIGN ls_table->* TO <ls_table>.
lo_tabledescr ?= cl_abap_tabledescr=>create( p_line_type = lo_structdescr
p_table_kind = cl_abap_tabledescr=>tablekind_hashed
p_unique = abap_true
p_key = lt_keys
p_key_kind = cl_abap_tabledescr=>keydefkind_default ).
CREATE DATA lt_table TYPE HANDLE lo_tabledescr.
ASSIGN lt_table->* TO <lt_table>.
ASSIGN COMPONENT 'COMP1' OF STRUCTURE <ls_table> TO <lv_value>.
<lv_value> = 'test'.
APPEND <ls_table> TO <lt_table>.
The last line is the problem. I get this syntax error:
You cannot use explicit or implicit index operations on tables with
types "HASHED TABLE" or "ANY TABLE". "<LT_TABLE>" has the type "ANY
TABLE". It is possible that the "TABLE" addition was not specified
before "<LT_TABLE>".
How am I supposed to add a line to the table?
Using INSERT <ls_table> INTO TABLE <lt_table>. is correct but the reason for the syntax errors is that you defined your field symbol as:
<lt_table> TYPE ANY TABLE,
since your program is hard coded to use a hashed table you should rather define your field symbols as
<lt_table> TYPE HASHED TABLE,
By doing this the syntax checker can give you better syntax checks since it knows the basic type of the table.
What the syntax error is telling you is that using append will only work with tables that are accessible via an index (standard and sorted) and since ANY TABLE could possibly be hash table (only accessible by key) you cannot append to it.
Use the INSERT operation:
INSERT <ls_table> INTO TABLE <lt_table>.
I hope you know what you're doing. With all that generic data handling, I doubt anyone will be able to understand what problem you're trying to solve at all.