Access shadowed variable from subroutine? - abap

How to call a shadowed variable from subroutine?
Below is code sample, where I do want to print shadowed variable value:
data i type i value 13.
perform _form.
form _form.
data i like i.
i = 17.
" write shadowed i value here
endform.

There is a possibility to do it dynamically with ASSIGN ('(PROGRAMM)VARIABLE') TO FIELD-SYMBOL(<lv_fs>).
Here's an example.
REPORT zz_test.
DATA i TYPE i VALUE 13.
PERFORM _form.
FORM _form.
FIELD-SYMBOLS <lv_shadow> TYPE i.
DATA i LIKE i.
i = 17.
" write shadowed i value here
ASSIGN ('(ZZ_TEST)I') TO <lv_shadow> CASTING.
IF <lv_shadow> IS ASSIGNED.
WRITE <lv_shadow>.
ENDIF.
ENDFORM.

Related

No data returned from class method to PBO

I want to return record of table from abap method, which is field of class
but nothing is returned to the variable in PBO
definition in class
data MS_ZORK_JG_SETTING type ZORK_JG_SETTING .
methods GET_MS_ZORK_JG_SETTING
returning
value(MS_ZORK_JG_SETTING) type ZORK_JG_SETTING .
MS_ZORK_JG_SETTING is a data type which contains data from ZORK_JG_SETTING transparent table, filled properly using other method, so there is a correct data in this variable
in pbo of the screen i wanted to assign returned value to variable of the same type as returned
MODULE pbo_0102 OUTPUT.
DATA: wa_jg_setting TYPE zork_jg_setting.
wa_jg_setting = go_bukrs_conf->get_ms_zork_jg_setting( ).
MOVE-CORRESPONDING wa_jg_setting TO zork_jg_setting.
ENDMODULE.
But wa_jg_setting is empty. Tell me why and how to repair that?
Place of invoking screen
DATA: go_bukrs_conf TYPE REF TO zork_cl_scr_bukrs_conf.
CREATE OBJECT go_bukrs_conf
EXPORTING
pa_bukrs = '3020'.
CALL SCREEN 102.
And get_ms_zork_jg_settings method. I am assigning a value of field to a formal parameter
method GET_MS_ZORK_JG_SETTING.
ms_zork_jg_setting = ms_zork_jg_setting."zwracana wartosc to pole/ atrybut
endmethod.
The line
ms_zork_jg_setting = ms_zork_jg_setting.
is useless, as you assign the value of the return parameter to itself.
Generally speaking, var = var is always non-sense.
Probably you want to do:
ms_zork_jg_setting = me->ms_zork_jg_setting.

Convert dynamic REF TO DATA structure to static

I created structure with three components, one of which is type ref to data and a table type of this structure. The problem is, how do I add data to this table?
It always has three components, but only one of them is discovered during processing, I always know two of them. Thus I always use the entire table type ref to data and then determine the type of this structure and create the table on it.
The issue here is that by doing this, even though I know two of the components, the whole itab will be dynamic, so I must use it in methods exporting/importing a type ref to data, which is inconvenient.
The method below will always return a table type ref to data, which is completely dynamic (type ref to data), but the structure of the table will always be like this:
component 1 -> type pc261.
component 2 -> type pay99_international.
compoment 3 -> well this is always a mistery hehe
methods get_payroll
importing it_rgdir type hrpy_tt_rgdir
returning value(rt_value) type ref to data.
method get_payroll.
field-symbols: <lt_payroll> type standard table.
create data rt_value type standard table of (mv_py_struct_type).
assign rt_value->* to <lt_payroll>.
...
endmethod.
My intention was to have the returning value with another type, a known type, with which I can use the two known components more easily. The idea I had was to create a type with only the unknown field as ref to data, than have a table of it.
This way, I would be able to use it inside methods without having to work so "dynamicaly", which altough works perfectly, is kind of difficult to understand only by reading the code.
types begin of gty_s_generic_payroll.
types evp type pc261.
types inter type pay99_international.
types nat type ref to data.
types end of gty_s_generic_payroll.
types gty_t_generic_payroll type table of gty_s_generic_payroll.
The problem is, how to use an itab of type gty_t_generic_payroll as declared above?
I must somehow create the component 3, but I have no idea how to do it...
At the end, I have a generic field-symbol, that is type table, that has the two known components + the third one that was discovered during processing time.
So how can I pass the content of this field symbol to a table type gty_t_generic_payroll?
data lt_payroll type ref to data.
field-symbols <lt_payroll> type any table.
lt_payroll = mo_payroll->get_payroll( lt_rgdir ). "this will return type ref to data
assign lt_payroll->* to <lt_payroll>.
After executing this code <lt_payroll> has all the values, but it is a dynamic table where I cannot use components <lt_payroll>[1]-inter.
So how to pass to gty_t_generic_payroll-typed variable, so that I can access components without much dynamics?
Given your target structure and table like this:
TYPES:
BEGIN OF payroll_row_type,
known_first_component TYPE something_we_know,
known_second_component TYPE something_else_we_know,
discovered_component TYPE REF TO data,
END OF payroll_row_type.
TYPES payroll_table_type TYPE STANDARD TABLE OF payroll_row WITH EMPTY KEY.
If you now have another table, whose type at runtime is:
TYPES:
BEGIN OF discovered_row_type,
known_first_component TYPE something_we_know,
known_second_component TYPE something_else_we_know,
known_third_component TYPE some_data_type,
END OF discovered_row_type.
TYPES discovered_table_type TYPE STANDARD TABLE OF discovered_row WITH EMPTY KEY.
You can move one to the other with
DATA source TYPE discovered_table_type.
DATA target TYPE payroll_table_type.
DATA resolved_component TYPE REF TO DATA.
DATA(descriptor) =
cl_abap_elemdescr=>describe_by_data( source_row-known_third_component ).
LOOP AT source INTO DATA(source_row).
DATA(target_row) =
VALUE payroll_row_type(
known_first_component = source_row-known_first_component
known_second_component = source_row-known_second_component ).
CREATE DATA target_row-discovered_component TYPE descriptor.
ASSIGN source_row-known_third_component TO FIELD-SYMBOL(<source_component>).
ASSIGN target_row-discovered_component TO FIELD-SYMBOL(<target_component>).
<target_component> = <source_component>.
INSERT target_row INTO TABLE target.
ENDLOOP.
The question and answers may look confusing for future visitors (what is the actual question?), so here is my two cents.
Summary of the question :
You call an external code (1) which gives you an internal table generated dynamically, but you know that all the components are always the same except one which varies but is at the same position, so you'd like to refer to its components statically, except for the one which varies.
(1) so, you can't adapt it.
Your workaround is to define an equivalent internal table statically and the component which varies will be defined as a data reference type (pointer to any data object), then to initialize it by copying the data from the dynamic internal table.
You ask for another better solution because yours consumes extra memory (two internal tables) and decreases the performance (copy process).
Answer :
No better solution
It looks like I was able to pass the values from the fully generic table (type ref to data) to another table that is 1/3 generic (type gty_t_generic_payroll):
methods get_payroll
importing it_rgdir type hrpy_tt_rgdir
returning value(rt_value) type gty_t_generic_payroll.
method get_payroll.
data lt_payroll type gty_t_generic_payroll.
data lt_payroll_aux type ref to data.
field-symbols: <lt_payroll_aux> type standard table.
create data lt_payroll_aux type standard table of (mv_py_struct_type).
assign lt_payroll_aux->* to <lt_payroll_aux> .
call function ' '.
call function ' '
exporting
= mv_relid
= mv_pernr
= xsdbool( gs_parm-use_natio <> abap_true )
tables
= it_rgdir
= <lt_payroll_aux> "table with the values I need
exceptions
= 0.
if sy-subrc <> 0.
return.
endif.
loop at <lt_payroll_aux> assigning field-symbol(<ls_payroll_aux>).
assign component 1 of structure <ls_payroll_aux> to field-symbol(<evp>).
assign component 2 of structure <ls_payroll_aux> to field-symbol(<inter>).
assign component 3 of structure <ls_payroll_aux> to field-symbol(<nat>).
data(ls_value) = value gty_s_generic_payroll(
evp = <evp>
inter = <inter>
).
get reference of <nat> into ls_value-nat.
append ls_value to rt_value. "returning table, with values I need and
"now with 2/3 known types
endloop.
endmethod.
At the end of the day, I acomplished what I needed, but unfortunately I do loose a lot of performance, since I must loop twice in the results now.
to populate the not-so-dynamic-table
to do the actual process of the report (at least it gets pretier lol)
This is the only way because I can't simply use insert lines of dynamic_itab to not_so_dynamic_itab, since the third component is reference .

Pass a read-only variable to a CHANGING parameter

I'd like to display a table from a class instance using CL_SALV_TABLE. However, my table is read-only and it's to be passed to a CHANGING parameter, I'm not allowed to do so.
How can I copy my dynamic reference to something that I can pass? The data type of the attribute can by any table.
Call of method FACTORY of the class CL_SALV_TABLE has failed; the
actual parameter for T_TABLE is write-protected.
DATA(lv_attribute) = 'mt_attribute'. "Dynamic name of class attribute
ASSIGN lr_appclass->(lv_attribute) TO FIELD-SYMBOL(<lt_table>).
cl_salv_table=>factory(
IMPORTING r_salv_table = DATA(lr_salv_table)
CHANGING t_table = <lt_table> ).
You can use RTTS to generate dynamic variables.
To generate a dynamic internal table with same type of original:
DATA: lo_table_desc TYPE REF TO cl_abap_tabledescr, " RTTS table descriptor
lrt_copy TYPE REF TO DATA. " temp data ref
FIELD-SYMBOLS:
<lt_copy> TYPE ANY TABLE.
" original type determination
lo_table_desc ?= cl_abap_tabledescr=>describe_by_data( {HERE_GOES_THE_MEMBER_TABLE} ).
" dynamic allocation
CREATE DATA lrt_copy TYPE HANDLE lo_table_desc.
ASSIGN lrt_copy->* TO <lt_copy>.
" {NOW_USE_<lt_copy>}
Without runtime typing:
ASSIGN lr_appclass->('MT_ATTRIBUTE') TO FIELD-SYMBOL(<member>).
DATA(copied_member) = copy( <member> ).
ASSIGN copied_member->* TO FIELD-SYMBOL(<table>).
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(lr_salv_table)
CHANGING
t_table = <table> ).
with
METHODS copy
IMPORTING
data TYPE any
RETURNING
VALUE(result) TYPE REF TO data.
METHOD copy.
CREATE DATA result LIKE data.
ASSIGN result->* TO FIELD-SYMBOL(<result>).
<result> = data.
ENDMETHOD.
I added the method copy to clarify what's happening. Its code can also be added to the main function.

Refresh ALV grid after deleting a row

So after I deleted a specific row in a database Table, it isn't removed on my screen. I have to end the programm and start it again to see the changes.
I've used alv->refresh( ). but this does not work for me. Is there a way to refresh the screen properly?
the refresh method has to have an importing parameter called is_stable. This structure has two fields (rwo and col) set both to 'X':
alv->refresh( is_stable = 'XX' ).
If the answer above doesn't work, you can use this method, it gets current ALV from global memory.
METHOD refresh_alv.
DATA: ref_grid TYPE REF TO cl_gui_alv_grid, valid TYPE c.
IF ref_grid IS INITIAL.
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = ref_grid.
ENDIF.
IF NOT ref_grid IS INITIAL.
ref_grid->check_changed_data(
IMPORTING
e_valid = valid ).
ENDIF.
IF valid IS NOT INITIAL.
ref_grid->refresh_table_display( ) .
ENDIF.
ENDMETHOD.

Single-line method calls with untyped parameters

Can I define an ABAP method where the RETURNING parameter and any IMPORTING parameters have a generic type but that can still be called in a single line as a functional method?
In other words I'd like to replace this:
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = lv_external_value
IMPORTING
output = lv_internal_value.
With:
lv_internal_value= zcl_conversion=>alpha_input( lv_external_value ).
Unfortunately the fact that Class Methods can't have an untyped returning parameter is preventing me from declaring the functional method's return value as type ANY or CLIKE. The accepted standard of creating generic method parameters seems to be to define them as TYPE REF TO DATA and dereference/assign them. But as far as I know that prevents me from calling the method in a single statement as I have to first assign the importing parameter and then dereference the returning parameter, resulting in the same or more lines of code than a simple FM call.
Is there a way around this?
Unfortunately, there is no other way to dereference data than to use the dereference operator, either in the form ->* for the full value segment, or in the form ->comp, if the data object is structured and has a component named comp (and, even worse, there are a lot of places in ABAP code where you would like to use a value from a derefenced data object but can't do it for internal reasons / syntax restrictions).
However, you could simply keep the data reference object retrieved by your method in a variable of the calling code and work with that variable (instead of using a field symbol or a variable for the derefenced value segment itself). Either generically, as a ref to data variable, or typed, using the CAST operator (new ABAP syntax).
Most things that can be done with a field-symbol, can also be done directly with a data reference as well.
Example: Working with a variable result of the expected return type:
data(result) = cast t000( cl=>m( ) ).
write result->mandt.
See here the full example:
report zz_new_syntax.
class cl definition.
public section.
class-methods m returning value(s) type ref to data.
endclass.
start-of-selection.
data(result) = cast t000( cl=>m( ) ).
write: / result->mandt. " Writes '123'.
class cl implementation.
method m.
s = new t000( mandt = '123' ).
endmethod.
endclass.
On ABAP NW Stack 7.4 you could just use parameters type STRING and then use the new CONV Operator to convert your actual input in string. Little ugly but should work.
lv_internal_value = CONV #(zcl_conversion=>alpha_input( CONV #(lv_external_value) )).