No domain values in CL_SALV_TABLE column. Why? - abap

I have 2 rows shown in the ALV list, one of this column has domain values.
If I click on the search help right it doesn't show any values at all.
Do I have to activate something in the class to see the values of any domain?

Automatic search help (aka domain values) will be showed only when creating ALV via Dictionary structure, and that's why it is impossible with cl_salv_table, because it accepts only internal table.
However, it have special method set_ddic_reference for assigning F4 values.
DATA: lr_column TYPE REF TO cl_salv_column_table,
lr_columns TYPE REF TO cl_salv_columns_table.
DATA: ls_ddic type salv_s_ddic_reference.
lr_columns = o_alv->get_columns( ).
lr_column ?= lr_columns->get_column( columnname = 'MANDT' ).
ls_ddic-table = 'T001'.
ls_ddic-field = 'MANDT'.
lr_column->set_ddic_reference( ls_ddic ).
lr_column->set_f4( abap_true ).
This code should be called after the factory constructor and before the display() method.

Related

How to expose the return type of a global class method?

I've written an ABAP Method, which returns me some analyses in a custom table.
Now I want to call this Method from an RFC module.
So far so good - the method works fine, but I'm curious of how to return this table?
Do I have to create a table / structure ... in SE11 to make it work because otherwise I can't refer to this table type or is there an easier way?
I'm quite new to ABAP so I don't know the best practices.
m_analyses = new zcl_manalyses( ).
data(lt_m_analyses) = m_analyses->analyse_m_data(
budat_from = budat_from
budat_to = budat_to
).
The TYPES statement can not only occur inside a method's body, but also inside the class definition, in which case it can be accessed from other places with class_name=>type_name (if it's public):
CLASS cl_user_registry DEFINITION PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF user,
firstname TYPE string,
lastname TYPE string,
END OF user,
users TYPE STANDARD TABLE OF user.
METHODS:
get_current_users
RETURNING users.
ENDCLASS.
DATA current_users TYPE cl_user_registry=>users.
current_users = cl_user_registry=>get_current_users( ).
You first have to create a structure in ABAP Dictionary (SE11), then you create a table type in SE11 as well.
You then reference the structure in the line type of the table type.
Try using the new global table type, it should work. (with typing 'TYPE')

cl_salv_bs_runtime_info=>get_data_ref() returns no data

I have this code, which works very nice for a lot of reports:
if IV_SELECTION_SET_VARIANT is INITIAL.
SUBMIT (IV_REPORT_NAME)
WITH SELECTION-TABLE selection_table
AND RETURN.
ELSE.
SUBMIT (IV_REPORT_NAME)
WITH SELECTION-TABLE selection_table
USING SELECTION-SET IV_SELECTION_SET_VARIANT
AND RETURN.
endif.
FIELD-SYMBOLS <lt_data> TYPE ANY TABLE.
FIELD-SYMBOLS <lt_data_line> TYPE ANY TABLE.
DATA lr_data TYPE REF TO data.
DATA lr_data_line TYPE REF TO data.
DATA lr_data_descr TYPE REF TO cl_abap_datadescr.
DATA lr_data_line_descr TYPE REF TO cl_abap_datadescr.
cl_salv_bs_runtime_info=>get_data_ref(
IMPORTING r_data_descr = lr_data_descr
r_data_line_descr = lr_data_line_descr ).
IF lr_data_descr IS NOT BOUND.
ev_result_json = '[]'.
EXIT.
ENDIF.
But for AdHoc Queries the line IF lr_data_descr IS NOT BOUND. is true and ev_result_json is empty.
What could be the reason for this?
The name of the report is AQZZZMM=========ZME80FN=======.
The method cl_salv_bs_runtime_info=>get_data_ref provides data only if in your precedent SUBMIT call an ALV grid control had been called, and the writing of the data has been requested before (internally by the submitted report, or explicitly, by calling the method cl_salv_bs_runtime_info=>set beforehand).
There are reports which don't call an ALV grid at all: for these, the method won't provide any result data.
There are reports (like ABAP queries) where the user himself can determine how to display the data - with an ALV grid control, or as ALV list, or as classical list or even in some other way. If the user chose some other display method than "ALV grid", the method cl_salv_bs_runtime_info=>get_data_ref will give you no data.
It may happen that a report which basically should display an ALV grid, doesn't display the grid if it did not select any result data. In these cases, the method cl_salv_bs_runtime_info=>get_data_ref will give you no data.
There are reports which display not one but several ALV grid controls at once, with different data. In this case, the method cl_salv_bs_runtime_info=>get_data_ref will retrieve the data from the last displayed ALV grid control (the last grid for which the method SET_TABLE_FOR_FIRST_DISPLAY has been called).

Сlass for wrapping generic table crashes

I'd like to build a container ABAP class that wraps an arbitrary internal table.
My initial approach was to define a member variable of TYPE REF TO DATA and pass a reference into the constructor.
The problem is that due to the pointer the instance is still dependent on the original itab. So if the original table is freed from memory you cannot access the data anymore. I'd need to have a real copy of the table data stored within the object, so I would be able to pass the object outside the original scope of the itab.
Is there any way of achieving this in ABAP?
Sample code with references that crashes in the scenario defined in the end:
CLASS lcl_test_itab_wrapper DEFINITION LOCAL FINAL
CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS: access_outside_itab_scope.
METHODS: constructor IMPORTING itab TYPE table,
access_itab_data.
PRIVATE SECTION.
CLASS-METHODS: sample_itab_setup RETURNING VALUE(result) TYPE REF TO lcl_test_itab_wrapper.
DATA: table_ref TYPE REF TO data.
ENDCLASS.
CLASS lcl_test_itab_wrapper IMPLEMENTATION.
METHOD access_itab_data.
FIELD-SYMBOLS <table> TYPE table.
ASSIGN me->table_ref->* TO <table>.
WRITE:/ lines( <table> ).
ENDMETHOD.
METHOD constructor.
me->table_ref = REF #( itab ).
ENDMETHOD.
METHOD sample_itab_setup.
DATA: dummy_itab TYPE TABLE OF string.
APPEND 'test_record' TO dummy_itab.
CREATE OBJECT result EXPORTING itab = dummy_itab.
ENDMETHOD.
METHOD access_outside_itab_scope.
DATA(o_instance) = sample_itab_setup( ).
" Here it crashes as the referenced itab was freed already.
" I'd need to have a real itab copy stored in the instance
o_instance->access_itab_data( ).
ENDMETHOD.
Update: Solution based on #vwegert answer
Replace constructor reference assignment by:
CREATE DATA me->table_ref LIKE itab.
FIELD-SYMBOLS <table> TYPE table.
ASSIGN me->table_ref->* TO <table>.
<table> = itab.
You need to create a data object dynamically instead of (ab)using a statically defined one. Check the documentation of the CREATE DATA statement.
Check out the "GET REFERENCE of xx into xx" statement as well, you can save three lines of your code.

Getting an ABAP object's identity number

when inspecting an object-instance in the debugger, it will be printed like this:
{O:9*CLASS=CL_SOMETHING}
Is it possible to retrieve that class' identity-number 9 from a given object reference?
I want to distinguish multiple instances of the same class and print their instance-number.
I found no way using the RTTI to get that information, any advice?
As far as I know, you can't access that internal object identifier. The debugger uses some private kernel interface to do so that is not accessible to the ordinary user. You could try something like this:
CLASS lcl_object_id_map DEFINITION.
PUBLIC SECTION.
METHODS get_id
IMPORTING ir_object TYPE REF TO object
RETURNING value(r_id) TYPE sysuuid_c.
PRIVATE SECTION.
TYPES: BEGIN OF t_object_id,
object TYPE REF TO object,
id TYPE sysuuid_c,
END OF t_object_id,
tt_object_id_map TYPE HASHED TABLE OF t_object_id
WITH UNIQUE KEY object.
DATA gt_object_id_map TYPE tt_object_id_map.
ENDCLASS. "lcl_object_id_map DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_object_id_map IMPLEMENTATION.
METHOD get_id.
DATA: ls_entry TYPE t_object_id.
FIELD-SYMBOLS: <ls_entry> TYPE t_object_id.
READ TABLE gt_object_id_map
ASSIGNING <ls_entry>
WITH KEY object = ir_object.
IF sy-subrc <> 0.
ls_entry-object = ir_object.
ls_entry-id = cl_system_uuid=>create_uuid_c32_static( ).
INSERT ls_entry INTO TABLE gt_object_id_map ASSIGNING <ls_entry>.
ENDIF.
r_id = ls_entry-id.
ENDMETHOD. "get_id
ENDCLASS. "lcl_object_id_map IMPLEMENTATION
I actually found an (internal) way to get the object's internal ID in the Object Services CL_OS_CA_COMMON=>OS_GET_INTERNAL_OID_BY_REF:
CALL 'OBJMGR_GET_INFO' ID 'OPNAME' FIELD 'GET_OBJID'
ID 'OBJID' FIELD integer_oid
ID 'OBJ' FIELD ref_to_object.
Yes, this is internal stuff... Use at own risk.

Correct way of using TYPE REF TO data?

I've declared a type with the type of ref to data. so it looks like this
my_type type ref to data.
Then I declare an internal table, which I want to assign to my_type.
Data:
ref_data type my_type.
itable type it_table.
ref_data = itable.
Why can't I assign itable to ref_data, isn't a ref to data is a generic data type and can be assigned to anything?
This is very similar to other programming languages, and it's not a problem of typing the variables or references. You're trying to assign a value to a pointer variable - that won't work anywhere. You need to use GET REFERENCE OF itable INTO ref_data.
That's not quite how a data reference works. A data reference has to be typed, but you type it at run time.
data: ref_data type ref to data.
data: itable type it_table.
"you access the data in a data reference via a field symbol
field-symbols: <dref> type any.
create data ref_data type it_table.
assign ref_data->* to <dref>.
<dref> = itable.
I now have a copy of itable in my dynamically typed variable ref_data, accessed by the field symbol .