Converting ABAP 740 syntax to 700 - VALUE & LOOP AT ... GROUP BY - abap

I found a demo program for the tree salv online that I wanted to use, but since it uses 740 syntax, I have to convert it first. Which is also a good opportunity to learn more about the new syntax.
I already did almost all of it, but am having trouble with VALUE. Reading this wiki entry, among others, couldn't help me.
Original code in 740:
" Treenodes einfügen
LOOP AT it_spfli ASSIGNING FIELD-SYMBOL(<c>) GROUP BY <c>-carrid.
DATA(it_cp) = VALUE ty_it_spfli( FOR <cp> IN GROUP <c> ( <cp> ) ).
DATA(o_parent) = o_tree->get_nodes( )->add_node( related_node = ''
relationship = cl_gui_column_tree=>relat_last_child
collapsed_icon = CONV #( icon_closed_folder )
expanded_icon = CONV #( icon_open_folder )
row_style = if_salv_c_tree_style=>intensified
text = CONV #( <c>-carrid ) ).
IF lines( it_cp ) > 1.
o_parent->get_item( 'CARRID' )->set_type( if_salv_c_item_type=>button ).
o_parent->get_item( 'CARRID' )->set_value( 'all' ).
ENDIF.
LOOP AT GROUP <c> ASSIGNING FIELD-SYMBOL(<f>).
DATA(o_carrid) = o_tree->get_nodes( )->add_node( related_node = o_parent->get_key( )
relationship = cl_gui_column_tree=>relat_last_child
data_row = <f>
row_style = if_salv_c_tree_style=>intensified
text = CONV #( <f>-connid ) ).
o_carrid->get_item( 'CARRID' )->set_type( if_salv_c_item_type=>checkbox ).
o_carrid->get_item( 'CARRID' )->set_editable( abap_true ).
ENDLOOP.
ENDLOOP.
New code in 700, except for line with VALUE:
" new variables added to convert code to 700
DATA: o_nodes TYPE REF TO cl_salv_nodes,
o_parent TYPE REF TO cl_salv_node,
o_carrid TYPE REF TO cl_salv_node,
o_item TYPE REF TO cl_salv_item,
o_key TYPE lvc_nkey.
DATA: h_collapsed_icon TYPE salv_de_tree_image VALUE 'icon_closed_folder',
h_expanded_icon TYPE salv_de_tree_image VALUE 'icon_open_folder',
h_text_carrid TYPE lvc_value.
DATA: it_cp TYPE STANDARD TABLE OF ty_it_spfli.
SORT it_spfli BY carrid.
" Treenodes einfügen
LOOP AT it_spfli ASSIGNING <c>.
AT NEW carrid.
it_cp = value TY_IT_SPFLI( for <CP> in GROUP <c> ( <CP> ) ). <--- Here
o_nodes = o_tree->get_nodes( ).
h_text_carrid = <c>-carrid.
o_parent = o_nodes->add_node( related_node = ''
relationship = cl_gui_column_tree=>relat_last_child
collapsed_icon = h_collapsed_icon
expanded_icon = h_expanded_icon
row_style = if_salv_c_tree_style=>intensified
text = h_text_carrid ).
IF LINES( it_cp ) > 1.
o_item = o_parent->get_item( 'CARRID' ).
o_item->set_type( if_salv_c_item_type=>button ).
o_item->set_value( 'all' ).
ENDIF.
ENDAT.
o_key = o_parent->get_key( ).
o_carrid = o_nodes->add_node( related_node = o_key
relationship = cl_gui_column_tree=>relat_last_child
data_row = <c>
row_style = if_salv_c_tree_style=>intensified
text = h_text_carrid ).
o_item = o_parent->get_item( 'CARRID' ).
o_item->set_type( if_salv_c_item_type=>checkbox ).
o_item->set_editable( abap_true ).
ENDLOOP.
My questions are now:
Did I convert the LOOP AT ... GROUP BY correctly by using AT NEW?
How do I convert the line with VALUE?
Thank you in advance for your help.

You can't do the conversion the way you did. The outer loop of the original code grouping by the CARRID is not exactly like AT NEW, because it generates a temporary group table which then you can use everywhere. Without it, you should generate the group in advance.
I didn't verify the code, but to simulate the GROUP BY and then make the rest of the conversion easy without having to rewrite too much, I would create a nested table for each CARRID from the original:
DATA: BEGIN OF ls_spfli_carrid_group,
carrid TYPE carrid,
flights TYPE ty_it_spfli,
END OF ls_spfli_carrid_group,
lt_spfli_carrid_group LIKE STANDARD TABLE OF ls_spfli_carrid_group.
SORT it_spfli BY carrid.
LOOP AT it_spfli INTO ls_spfli.
AT NEW carrid.
it_spfli
ls_spfli_carrid_group-carrid = ls_spfli-carrid.
REFRESH ls_spfli_carrid_group-flights.
APPEND ls_spfli_carrid_group TO lt_spfli_carrid_group.
ENDAT.
APPEND ls_spfli TO ls_spfli_carrid_group-flights.
ENDLOOP.
LOOP AT lt_spfli_carrid_group INTO ls_spfli_carrid_group.
it_cp = ls_spfli_carrid_group-flights.
...
LOOP AT ls_spfli_carrid_group-flights INTO ls_flight. "Should be like the LOOP AT GROUP
ENDLOOP.
ENDLOOP.

In fact, you are asking what means the line with "FOR ... IN GROUP":
TYPES: ty_it_spfli TYPE STANDARD TABLE OF spfli WITH DEFAULT KEY.
DATA it_spfli TYPE ty_it_spfli.
LOOP AT it_spfli ASSIGNING FIELD-SYMBOL(<c>) GROUP BY <c>-carrid.
DATA(it_cp) = VALUE ty_it_spfli( FOR <cp> IN GROUP <c> ( <cp> ) ).
...
ENDLOOP.
First of all, the outer loop with "GROUP BY" iterates on the distinct values of CARRID component. For example, the internal table it_spfli may have 100 lines, but there are only 10 distinct CARRID values, so it will iterate 10 times.
The inner "value construction" FOR <cp> IN GROUP <c> does a loop at the "members" of the "group" of lines <c>, where the "members" are the lines of it_spfli which correspond to the current group (those lines which correspond to the value of CARRID of the current group), and at each iteration the line ( <cp> ) is appended to the variable it_cp.
This line:
DATA(it_cp) = VALUE ty_it_spfli( FOR <cp> IN GROUP <c> ( <cp> ) ).
is equivalent to the following syntax with LOOP AT GROUP, which is valid only from 7.40 too, but it should be more clear to you, and you can convert it in 7.0 more intuitively:
DATA(it_cp) = VALUE ty_it_spfli( ). " initialization (empty internal table)
LOOP AT GROUP <c> ASSIGNING FIELD-SYMBOL(<cp>).
INSERT <cp> INTO TABLE it_cp.
ENDLOOP.

Thank you Sandra and RaTiO for your help.
Now that I understood what is supposed to happen, I have the following two solutions (one of them being the one from RaTiO).
(What is supposed to happen: The VALUE command was supposed to fill another itab with those lines of the looping table, which contain the current CARRID. Then depending on the amount of lines, you could see if the node will have children and thus need to be an expanding button.)
So the solution I thought of myself was to fill a copy of the table inside the LOOP and delete those entries that do not contain the current CARRID.
DATA: it_copy_spfli TYPE ty_it_spfli.
...
SORT it_spfli BY carrid.
LOOP AT it_spfli ASSIGNING <c>.
AT NEW carrid.
REFRESH it_copy_spfli.
it_copy_spfli = it_spfli.
DELETE it_copy_spfli WHERE carrid <> <c>-carrid.
...
IF LINES( it_copy_spfli ) > 1.
...
ENDIF.
ENDAT.
...
ENDLOOP.
Then there's RaTiO's solution, creating a nested table to LOOP over instead.
DATA: it_copy_spfli TYPE ty_it_spfli.
DATA: BEGIN OF ls_spfli_carrid_group,
carrid TYPE s_carr_id,
flights TYPE ty_it_spfli,
END OF ls_spfli_carrid_group.
DATA: ls_spfli TYPE spfli,
ls_flight TYPE spfli,
lt_spfli_carrid_group LIKE STANDARD TABLE OF ls_spfli_carrid_group.
SORT it_spfli BY carrid.
LOOP AT it_spfli INTO ls_spfli.
APPEND ls_spfli TO ls_spfli_carrid_group-flights.
AT END OF carrid.
ls_spfli_carrid_group-carrid = ls_spfli-carrid.
APPEND ls_spfli_carrid_group TO lt_spfli_carrid_group.
REFRESH ls_spfli_carrid_group-flights.
ENDAT.
ENDLOOP.
LOOP AT lt_spfli_carrid_group INTO ls_spfli_carrid_group.
REFRESH it_copy_spfli.
it_copy_spfli = ls_spfli_carrid_group-flights.
...
h_text_carrid = ls_spfli_carrid_group-carrid.
...
IF LINES( it_copy_spfli ) > 1.
...
ENDIF.
LOOP AT ls_spfli_carrid_group-flights INTO ls_flight.
...
o_carrid = o_nodes->add_node( ...
data_row = ls_flight
... ).
...
ENDLOOP.
ENDLOOP.
Then I adapted it to use FIELD-SYMBOLS instead.
DATA: it_copy_spfli TYPE ty_it_spfli.
TYPES: BEGIN OF ty_spfli_carrid_group,
carrid TYPE s_carr_id,
flights TYPE ty_it_spfli,
END OF ty_spfli_carrid_group.
DATA: lt_spfli_carrid_group TYPE STANDARD TABLE OF ty_spfli_carrid_group.
FIELD-SYMBOLS: <spfli> TYPE spfli,
<flight> TYPE spfli,
<spfli_carrid_group> TYPE ty_spfli_carrid_group.
SORT it_spfli BY carrid.
LOOP AT it_spfli ASSIGNING <spfli>.
AT NEW carrid.
APPEND INITIAL LINE TO lt_spfli_carrid_group ASSIGNING <spfli_carrid_group>.
ENDAT.
APPEND <spfli> TO <spfli_carrid_group>-flights.
AT END OF carrid.
<spfli_carrid_group>-carrid = <spfli>-carrid.
ENDAT.
ENDLOOP.
LOOP AT lt_spfli_carrid_group ASSIGNING <spfli_carrid_group>.
...
LOOP AT <spfli_carrid_group>-flights ASSIGNING <flight>.
...
ENDLOOP.
ENDLOOP.
All the solutions worked as expected. Comparing the runtime, the last one was the fastest, but they were very very close. So I decided to use mine, since it is only a couple lines, while RaTiO's requires another LOOP.
Thank you again =)

Related

Is there anyway in power bi to assign value to distinct count against value

I want to ask that i have a column of claims in which a claim no have different occurances but i want to assign value of 1 when claim no is distinct and it occurred first time then i assign 0 when it is repeated , so is there any method for creating calculated column for this problem
You can use Power Query to achieve your goal: Below I created some datasets, and achieved a result:
Let's say you have such data set:
Then here is all steps involved in Power Query to achieve your goal. Just Paste the code into Advanced Editor in which you can find in Home tab and Query Group:
If you clicked the Advanced Editor, You can see the full code, like this:
The Full M-Code:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMjMwNDFS0lEyVIrVAfNMzYA8IxgPTc4UWQ6s0hBFpSmKnAmKnBGKKcboZsYCAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Claim No" = _t, Occurances = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Claim No", Int64.Type}, {"Occurances", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"Claim No"}, {{"Order", each _, type table [Claim No=nullable number, Occurances=nullable number]}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Custom", each Table.AddIndexColumn([Order],"SNo",1)),
Custom1 = Table.Combine(#"Added Custom"[Custom]),
#"Added Custom1" = Table.AddColumn(Custom1, "Distinct_Number", each if [SNo] = 1 then 1 else 0),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom1",{"SNo"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Removed Columns",{{"Distinct_Number", Int64.Type}})
in
#"Changed Type1"
If we test it, It returns:

Delete or ignore rows that have empty tables when using Table.ExpandTableColumn | Power Query

I need to expand a table column but some of the table contents are empty and return ""
when I run the query it stops at the first table where the content is empty.
I need to ignore these rows when using the Table.ExpandTableColumn or delete them beforehand.
#"Função Personalizada Invocada" = Table.AddColumn(#"Tipo Alterado", "generation_24hrs", each get_generation_24([user.data.id])),
#"generation_24hrs Expandido" = Table.ExpandTableColumn(#"Função Personalizada Invocada", "generation_24hrs", {"entry.value.id", "entry.value.kwh_ger", "entry.value.kwh_con"}, {"entry.value.id", "entry.value.kwh_ger", "entry.value.kwh_con"})
Before
After:
try
#"Função Personalizada Invocada" = Table.AddColumn(#"Tipo Alterado", "generation_24hrs", each get_generation_24([user.data.id])),
#"Added Custom" = Table.AddColumn(#"Função Personalizada Invocada", "RowCount", each Table.RowCount([generation_24hrs])),
#"Filtered Rows" = Table.SelectRows(#"Added Custom", each ([RowCount] <> "0")),
#"generation_24hrs Expandido" = Table.ExpandTableColumn(#"Filtered Rows", "generation_24hrs", {"entry.value.id", "entry.value.kwh_ger", "entry.value.kwh_con"}, {"entry.value.id", "entry.value.kwh_ger", "entry.value.kwh_con"})

CX_SY_READ_SRC_LINE_TOO_LONG error while calling REUSE_ALV_FIELDCATALOG_MERGE

I want to using 'reuse_alv_fieldcatalog_merge' fill the table and press the screen . But it gives such an error:
"The ABAP program lines are wider than the internal table."
I checked the settings and Downwards-Comp. There was no sign in the line lentgh (72) section. So the problem is not caused by this. I leave my code down. I would be glad if you could help.
TYPE-POOLS slis .
TABLES : vbrk, vbrp.
DATA : BEGIN OF gt_table OCCURS 0,
vbeln LIKE vbrk-vbeln,
waerk LIKE vbrk-waerk,
kunag LIKE vbrk-kunag,
fkart LIKE vbrk-fkart,
fktyp LIKE vbrk-fktyp,
vbtyp LIKE vbrk-vbtyp,
vkorg LIKE vbrk-vkorg,
vtweg LIKE vbrk-vtweg,
fkdat LIKE vbrk-fkdat,
posnr LIKE vbrp-posnr,
vrkme LIKE vbrp-vrkme,
matnr LIKE vbrp-matnr,
werks LIKE vbrp-werks,
fkimg LIKE vbrp-fkimg,
ntgew LIKE vbrp-ntgew,
brgew LIKE vbrp-brgew,
gewei LIKE vbrp-gewei,
brtwr LIKE vbrp-brtwr,
name1 LIKE kna1-name1,
END OF gt_table.
SELECT-OPTIONS : so_vbeln FOR vbrk-vbeln,
so_fkart FOR vbrk-fkart,
so_fktyp FOR vbrk-fktyp,
so_vbtyp FOR vbrk-vbtyp,
so_vkorg FOR vbrk-vkorg,
so_vtweg FOR vbrk-vtweg,
so_fkdat FOR vbrk-fkdat,
so_vrkme FOR vbrp-vrkme,
so_matnr FOR vbrp-matnr,
so_werks FOR vbrp-werks.
DATA : i_fcat TYPE slis_t_fieldcat_alv .
DATA : wa_fcat LIKE LINE OF i_fcat .
START-OF-SELECTION .
PERFORM get_data .
PERFORM create_fcat_merge .
END-OF-SELECTION .
PERFORM disp_alv .
FORM get_data .
SELECT a~vbeln a~waerk a~kunag a~fkart a~fktyp a~vbtyp a~vkorg a~vtweg a~fkdat b~posnr b~vrkme
b~matnr b~werks b~fkimg b~ntgew b~brgew b~gewei b~brtwr c~name1
INTO TABLE gt_table
FROM vbrk AS a INNER JOIN vbrp AS b ON a~vbeln = b~vbeln
INNER JOIN kna1 AS c ON c~kunnr = a~kunag
WHERE a~vbeln IN so_vbeln AND
a~fkart IN so_fkart AND
a~fktyp IN so_fktyp AND
a~vbtyp IN so_vbtyp AND
a~vkorg IN so_vkorg AND
a~vtweg IN so_vtweg AND
a~fkdat IN so_fkdat AND
b~vrkme IN so_vrkme AND
b~matnr IN so_matnr AND
b~werks IN so_werks.
ENDFORM.
FORM disp_alv .
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = sy-repid
it_fieldcat = i_fcat
TABLES
t_outtab = gt_table.
ENDFORM.
FORM create_fcat_merge .
CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
EXPORTING
i_program_name = sy-repid
i_internal_tabname = 'gt_table'
i_inclname = sy-repid
CHANGING
ct_fieldcat = i_fcat.
ENDFORM.
Your SELECT line is wider than 72 characters:
SELECT a~vbeln a~waerk a~kunag a~fkart a~fktyp a~vbtyp a~vkorg a~vtweg a~fkdat b~posnr b~vrkme
Break it into two lines:
SELECT a~vbeln a~waerk a~kunag a~fkart a~fktyp a~vbtyp a~vkorg a~vtweg
a~fkdat b~posnr b~vrkme
There is another issue:
CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
EXPORTING
i_program_name = sy-repid
i_internal_tabname = 'gt_table'
The 'gt_table' has to be in capitals (just to prevent the next dump):
i_internal_tabname = 'GT_TABLE'
PS.: I guess you are just playing around, there are more up to date tools to create an ALV list.

Odoo add records to one2many field using onchange event twice

As code below , I could add record to the one2many field 'f_12m' when the other field 'onte' was changed .
But the problem is that when I change the 'note' value again , it delete all the records of 'f_12m' field , then add a new record .
How can i keep the old records and add new one , without saving the whold model ?
f_12m = fields.One2many( 'x_app.other_model', 'oid', string= 'FieldName' )
#api.onchange( 'note' )
def _onchange_note( self ) :
dic_value = {}
list_f_12m = []
list_f_12m.append( ( 0 , 0 , {'note':self.note} ) )
dic_value.update( f_12m = list_f_12m )
return {'value': dic_value }
Please try below code
f_12m = fields.One2many( 'x_app.other_model', 'oid', string= 'FieldName' )
#api.onchange( 'note' )
def _onchange_note( self ) :
dic_value = {}
list_f_12m = self.f_12m.ids
f_12m_new = self.env['x_app.other_model'].create({'note':self.note, 'oid':self.id})
list_f.12m.append(f_12m_new.id)
self.f_12m = [(6,0,list_f_12m)]
Hope this helps!

How to sort result by field?

I have a simple example:
result = db.command({
'findandmodify' : 'Task',
'remove' : True
})
print result
How to get first inserted element ? ( order by _id )
The find_one method in pymongo should return the first document in the collection: http://api.mongodb.org/python/current/tutorial.html#getting-a-single-document-with-find-one