Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

How to change line of a hashed table using a method call?

Former Member
0 Kudos

Hello everyone,

writing a custom program, I try to execute the following code:

LOOP AT it_vttk REFERENCE INTO dref_vttk.

...

  me->set_shipment_status( EXPORTING im_status = 2 CHANGING ch_shpmnt = dref_vttk->* ).

...

ENDLOOP.

This throws a runtime error calling me that I am not allowed to write to field "???" (tried a little and in fact I am not allowed to write to dref_vttk->*). it_vttk is defined as HASHED TABLE OF vttk WITH UNIQUE KEY tknum. it_vttk is a (private) attribute of the class containing the above coding in a (public) method.

It is clear to me that I am not allowed to change the key field tknum within loop processing, but I don't do this in method set_shipment_status.

So - what is the proper way of changing fields in a line of a hashed table using a method call? I can't specify the fields in the method call because the method decides which fields are changed.

12 REPLIES 12

Former Member
0 Kudos

Can you share the code ?

0 Kudos

I could, but maybe a minimal working example suffices:


REPORT zzms_test_loop.

DATA: it_vttk TYPE HASHED TABLE OF vttk WITH UNIQUE KEY tknum,

       dref_vttk TYPE REF TO vttk,

       wa_vttk TYPE vttk.

SELECT * FROM vttk INTO TABLE it_vttk WHERE tplst ='4017'.

LOOP AT it_vttk REFERENCE INTO dref_vttk.

   dref_vttk->streg = 'X'.

   wa_vttk = dref_vttk->*.

   wa_vttk-streg = 'X'.

   dref_vttk->* = wa_vttk.

ENDLOOP.

The first instruction in the loop works flawlessly. Then I try to achieve the same result assigning the table line to a work area (or passing it to a method as a CHANGING parameter, think this makes no difference), changing the field there and writing the result back. This leads to a dump.

If it is generally not allowed to assign anything to dref_xxx->* in a loop (which I would find weird anyway), I wonder why this gives a runtime and not a syntax error...

matt
Active Contributor
0 Kudos

The contents of the memory location that hold wa_vttk-tknum are copied to the memory location dref-vttk->tknum which is protected, as tknum is a key field.

0 Kudos

why not use wa_vttk then before equating it to dref_vttk->*.

me->set_shipment_status( EXPORTING im_status = 2 CHANGING ch_shpmnt = wa_vttk ).

dref_vttk->* = wa_vttk.

Former Member
0 Kudos

I know, but can't ABAP simply check whether both contents are identical and then be happy? As far as I know, there is no construction like "Write all fields except for X", so changing many fields of the structure would be quite difficult then...

matt
Active Contributor
0 Kudos

Michael Seifert wrote:

I know, but can't ABAP simply check whether both contents are identical and then be happy? .

I'm sure it could. But it doesn't so we'll have to live with it.

You could use:

LOOP AT it_vttk ASSIGNING <vttk>.

...

  me->set_shipment_status( EXPORTING im_status = 2 CHANGING ch_shpmnt = <vttk> ).

...

ENDLOOP.


Then within your set_shipment_status, use

ASSIGN COMPONENT fieldname OF STRUCTURE ch_shpmnt TO <status>.

<status> = im_status.

0 Kudos

Michael Seifert wrote:

I know, but can't ABAP simply check whether both contents are identical and then be happy? As far as I know, there is no construction like "Write all fields except for X", so changing many fields of the structure would be quite difficult then...

I not sure if other programming languages are capable of doing this, but afaik the ABAP kernel is not too smart enough to do this. I checked recent ABAP documentation on MOVE-CORRESPONDING but still no luck.

Until SAP builds this functionality into the ABAP Kernel you have to live using this workaround involving field symbols.

  • DATA flights_tab TYPE HASHED TABLE OF sflight WITH UNIQUE KEY carrid connid fldate.
  • SELECT * FROM sflight INTO TABLE flights_tab UP TO 10 ROWS.
  • LOOP AT flights_tab REFERENCE INTO DATA(dref_flight).
  •   DATA(flight) = dref_flight->*.
  •   flight-currency = 'EUR'.
  •   WHILE sy-subrc = 0.
  •     ASSIGN COMPONENT sy-index OF STRUCTURE:
  •         dref_flight->* TO FIELD-SYMBOL(<val1>),
  •         flights_tab    TO FIELD-SYMBOL(<val2>).
  •     CHECK sy-subrc = 0.
  •     IF <val1> <> <val2>.
  •       <val1> = <val2>.
  •     ENDIF.
  •   ENDWHILE.
  • ENDLOOP.

BR,

Suhas

0 Kudos

Suhas,

The post not mine, but i have a question... When you make reference into dref_flight, this does not need to be declared (eg. DATA dref_flight TYPE REF TO data)? Or this is declared when you pass DATA(dref_flight) (creating the same data type how i show above) ?


Thanks for clearing my doubt

0 Kudos

Those are inline declarations for ABAP 740 - ABAP Keyword Documentation.

There are quite a few blogs by Horst Keller about the new features of ABAP 740. You can find those in the ABAP forums, should read those!

BR,

Suhas

0 Kudos

Thanks Suhas, I'll read for sure !

0 Kudos

I don't get your idea right, I think... If I have to use a workarea anyway, why not use LOOP ... INTO instead of REFERENCE INTO? And if I want to change just a single component of dref_flight->*, I could change the component directly. Maybe I should give you indeed an example using methods, so you understand what I am trying to do 🙂

This one works, but only because main and test are methods of the same class which has dref_vttk as an attribute:


REPORT zzms_test_loop.

CLASS test DEFINITION.

   PUBLIC SECTION.

     CLASS-DATA:

       it_vttk TYPE HASHED TABLE OF vttk WITH UNIQUE KEY tknum,

       dref_vttk TYPE REF TO vttk.

     CLASS-METHODS:

       test IMPORTING flag TYPE c,

       main.

ENDCLASS.                    "test DEFINITION

CLASS test IMPLEMENTATION.

   METHOD test.

     IF flag = 'X'.

       dref_vttk->streg = 'X'.

     ENDIF.

   ENDMETHOD.                    "test


   METHOD main.

     SELECT * FROM vttk INTO TABLE it_vttk WHERE tplst ='4017'.

     LOOP AT it_vttk REFERENCE INTO dref_vttk.

       test=>test( EXPORTING flag = '').

     ENDLOOP.

   ENDMETHOD.

ENDCLASS.

This one does not work (runtime error), because I am not allowed to pass dref_vttk->* as CHANGING parameter:


REPORT zzms_test_loop.

CLASS test DEFINITION.

   PUBLIC SECTION.

     CLASS-DATA:

       it_vttk TYPE HASHED TABLE OF vttk WITH UNIQUE KEY tknum.

     CLASS-METHODS:

       test IMPORTING flag TYPE c CHANGING shpmnt TYPE vttk,

       main.

ENDCLASS.                    "test DEFINITION

START-OF-SELECTION.

test=>main( ).

CLASS test IMPLEMENTATION.

   METHOD test.

     IF flag = 'X'.

       shpmnt-streg = 'X'.

     ENDIF.

   ENDMETHOD.                    "test

   METHOD main.

     DATA dref_vttk TYPE REF TO vttk.

     SELECT * FROM vttk INTO TABLE it_vttk WHERE tplst ='4017'.

     LOOP AT it_vttk REFERENCE INTO dref_vttk.

       test=>test( EXPORTING flag = 'X' CHANGING shpmnt = dref_vttk->* ).

     ENDLOOP.

ENDMETHOD.                    "main

ENDCLASS.

But this is (as far as I can see) the only way to do it if main and test are not methods of the same class. I simply don't understand a) why the pure assignment of dref_vttk->* as a CHANGING parameter leads to an error (because at that time it is unclear what will happen to this parameter) and b) why this is a runtime and not a syntax error.

rosenberg_eitan
Active Contributor
0 Kudos

Hi,

Maybe I am missing something but why not use field symbols .

Regards.

Code:

REPORT  y_r_eitan_test_30_07.

START-OF-SELECTION .
   PERFORM at_start_of_selection .


*----------------------------------------------------------------------*
FORM at_start_of_selection .
   PERFORM test05 .
ENDFORM .                    "at_start_of_selection

*----------------------------------------------------------------------*
FORM test05 .

   DATA: it_sbook TYPE HASHED TABLE OF sbook WITH UNIQUE KEY bookid .

   SELECT * INTO TABLE it_sbook FROM sbook UP TO 10 ROWS .

   FIELD-SYMBOLS: <st_sbook> LIKE LINE OF it_sbook .

   LOOP AT it_sbook ASSIGNING <st_sbook> .

     PERFORM recalc CHANGING <st_sbook> .

   ENDLOOP.

ENDFORM.                                                    " TEST05
*----------------------------------------------------------------------*
FORM recalc
   CHANGING st_sbook TYPE sbook .

   st_sbook-forcuram = 1 .

ENDFORM.                    " RECALC