Grid Table
Subtotals as a hierarchy in a sap.ui.table.TreeTable - a grand total per currency, a node per region and country carrying its sum, the sales as leaves - collapsible in the browser.
- Class
z2ui5_cl_smp_app_545- Repository
- abap2UI5/samples
- UI5 libraries
- sap.m, sap.ui.core, sap.ui.table
- Lowest UI5 release
- 1.71
- In the browser
- Runs in the playground
- Controls it builds
- sap.m.Button, sap.m.Label, sap.m.MessageStrip, sap.m.OverflowToolbar, sap.m.Page, sap.m.Shell, sap.m.Text, sap.m.Title, sap.m.ToolbarSpacer, sap.ui.core.mvc.View, sap.ui.table.Column, sap.ui.table.RowSettings, sap.ui.table.TreeTable
The class
" @keywords tree table treetable subtotal grand total group sum currency hierarchy collapse expand arraynames expandtolevel collapseall control_by_id rowsettings
" @summary Subtotals as a hierarchy in a sap.ui.table.TreeTable - a grand total per currency, a node per region and country carrying its sum, the sales as leaves - collapsible in the browser.
CLASS z2ui5_cl_smp_app_545 DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
TYPES:
BEGIN OF ty_s_sale,
region TYPE string,
country TYPE string,
product TYPE string,
quantity TYPE i,
amount TYPE p LENGTH 15 DECIMALS 2,
currency TYPE string,
END OF ty_s_sale.
TYPES ty_t_sales TYPE STANDARD TABLE OF ty_s_sale WITH EMPTY KEY.
TYPES:
BEGIN OF ty_s_node,
name TYPE string,
quantity TYPE i,
amount TYPE p LENGTH 15 DECIMALS 2,
currency TYPE string,
"! what the node is: a sale (empty), a subtotal or a grand total, see cs_kind
kind TYPE string,
END OF ty_s_node.
TYPES BEGIN OF ty_s_country.
INCLUDE TYPE ty_s_node.
TYPES:
nodes TYPE STANDARD TABLE OF ty_s_node WITH EMPTY KEY,
END OF ty_s_country.
TYPES BEGIN OF ty_s_region.
INCLUDE TYPE ty_s_node.
TYPES:
nodes TYPE STANDARD TABLE OF ty_s_country WITH EMPTY KEY,
END OF ty_s_region.
TYPES BEGIN OF ty_s_total.
INCLUDE TYPE ty_s_node.
TYPES:
nodes TYPE STANDARD TABLE OF ty_s_region WITH EMPTY KEY,
END OF ty_s_total.
TYPES ty_t_tree TYPE STANDARD TABLE OF ty_s_total WITH EMPTY KEY.
CONSTANTS:
BEGIN OF cs_kind,
subtotal TYPE string VALUE `S`,
total TYPE string VALUE `T`,
END OF cs_kind.
DATA t_tree TYPE ty_t_tree.
DATA visible_rows TYPE i.
"! Builds the hierarchy grand total - region - country - sale. Amounts
"! only add up within one currency, so the root is one grand total per
"! currency: a region that sells in two currencies sits under both. Every
"! node carries the sums of the sales below it; regions, countries and
"! sales keep the order of their first sale within a currency.
"! @parameter t_sales | the sales, in any order
"! @parameter result | one grand total node per currency, in alphabetical order
METHODS tree_build
IMPORTING
t_sales TYPE ty_t_sales
RETURNING
VALUE(result) TYPE ty_t_tree.
PROTECTED SECTION.
DATA client TYPE REF TO z2ui5_if_client.
METHODS on_init.
METHODS view_display.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_smp_app_545 IMPLEMENTATION.
METHOD z2ui5_if_app~main.
me->client = client.
IF client->check_on_init( ).
on_init( ).
ELSEIF client->check_on_navigated( ).
view_display( ).
ELSEIF client->check_on_event( `EXPAND` ).
" three levels below the grand totals: regions, countries, sales
client->follow_up_action( val = client->cs_event-control_by_id
t_arg = VALUE #( ( `tree` ) ( `expandToLevel` ) ( `3` ) ) ).
ELSEIF client->check_on_event( `COLLAPSE` ).
client->follow_up_action( val = client->cs_event-control_by_id
t_arg = VALUE #( ( `tree` ) ( `collapseAll` ) ) ).
ENDIF.
ENDMETHOD.
METHOD on_init.
DATA(t_sales) = VALUE ty_t_sales(
( region = `EMEA` country = `Germany` product = `Notebook` quantity = 10 amount = `12000.00` currency = `EUR` )
( region = `APAC` country = `Japan` product = `Antivirus` quantity = 50 amount = `2500.00` currency = `USD` )
( region = `EMEA` country = `Switzerland` product = `Monitor` quantity = 8 amount = `2400.00` currency = `CHF` )
( region = `Americas` country = `USA` product = `Server` quantity = 2 amount = `18000.00` currency = `USD` )
( region = `EMEA` country = `Germany` product = `Office Suite` quantity = 25 amount = `4500.00` currency = `EUR` )
( region = `Americas` country = `Canada` product = `Monitor` quantity = 5 amount = `1500.00` currency = `CAD` )
( region = `EMEA` country = `France` product = `Notebook` quantity = 6 amount = `7200.00` currency = `EUR` )
( region = `APAC` country = `Australia` product = `Training` quantity = 2 amount = `3000.00` currency = `USD` )
( region = `EMEA` country = `Switzerland` product = `Installation` quantity = 3 amount = `1350.00` currency = `CHF` )
( region = `Americas` country = `USA` product = `Support Contract` quantity = 12 amount = `6000.00` currency = `USD` )
( region = `APAC` country = `Japan` product = `Notebook` quantity = 4 amount = `4800.00` currency = `USD` )
( region = `Americas` country = `Canada` product = `Office Suite` quantity = 40 amount = `7600.00` currency = `CAD` ) ).
t_tree = tree_build( t_sales ).
" room for every node, so expanding all scrolls nothing out of sight
visible_rows = lines( t_sales ).
LOOP AT t_tree INTO DATA(s_total).
visible_rows = visible_rows + 1.
LOOP AT s_total-nodes INTO DATA(s_region).
visible_rows = visible_rows + 1 + lines( s_region-nodes ).
ENDLOOP.
ENDLOOP.
view_display( ).
ENDMETHOD.
METHOD tree_build.
DATA t_sorted TYPE ty_t_sales.
FIELD-SYMBOLS <total> TYPE ty_s_total.
FIELD-SYMBOLS <region> TYPE ty_s_region.
FIELD-SYMBOLS <country> TYPE ty_s_country.
t_sorted = t_sales.
SORT t_sorted STABLE BY currency.
LOOP AT t_sorted INTO DATA(s_sale).
READ TABLE result ASSIGNING <total> WITH KEY currency = s_sale-currency.
IF sy-subrc <> 0.
APPEND VALUE #( name = `Grand Total` currency = s_sale-currency kind = cs_kind-total ) TO result ASSIGNING <total>.
ENDIF.
<total>-quantity = <total>-quantity + s_sale-quantity.
<total>-amount = <total>-amount + s_sale-amount.
READ TABLE <total>-nodes ASSIGNING <region> WITH KEY name = s_sale-region.
IF sy-subrc <> 0.
APPEND VALUE #( name = s_sale-region currency = s_sale-currency kind = cs_kind-subtotal ) TO <total>-nodes ASSIGNING <region>.
ENDIF.
<region>-quantity = <region>-quantity + s_sale-quantity.
<region>-amount = <region>-amount + s_sale-amount.
READ TABLE <region>-nodes ASSIGNING <country> WITH KEY name = s_sale-country.
IF sy-subrc <> 0.
APPEND VALUE #( name = s_sale-country currency = s_sale-currency kind = cs_kind-subtotal ) TO <region>-nodes ASSIGNING <country>.
ENDIF.
<country>-quantity = <country>-quantity + s_sale-quantity.
<country>-amount = <country>-amount + s_sale-amount.
APPEND VALUE #( name = s_sale-product
quantity = s_sale-quantity
amount = s_sale-amount
currency = s_sale-currency
kind = `` ) TO <country>-nodes.
ENDLOOP.
ENDMETHOD.
METHOD view_display.
DATA(view) = z2ui5_cl_ui5_view_builder=>factory(
)->ele( n = `View` ns = `mvc`
)->a( n = `displayBlock` v = `true`
)->a( n = `height` v = `100%`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`
)->a( n = `xmlns:table` v = `sap.ui.table` ).
DATA(page) = view->ele( `Shell`
)->ele( `Page`
)->a( n = `title` v = `abap2UI5 - Grid Table - Collapsible Subtotals in a TreeTable`
)->a( n = `showNavButton` b = client->check_app_prev_stack( )
)->a( n = `navButtonPress` v = client->_event_nav_app_leave( ) ).
page->tag( `MessageStrip`
)->a( n = `text` v = `The backend nests the sales into a hierarchy - a grand total per currency, then region, ` &&
`country and the sale - and every node carries the sums below it. The TreeTable reads the children ` &&
`from the NODES arrays and expands and collapses them in the browser; the two buttons call ` &&
`expandToLevel and collapseAll on it by ID.`
)->a( n = `type` v = `Information`
)->a( n = `showIcon` b = abap_true
)->a( n = `class` v = `sapUiSmallMargin` ).
" arrayNames tells the JSON model which component holds the children;
" the first level - the grand totals - starts expanded
DATA(table) = page->ele( n = `TreeTable` ns = `table`
)->a( n = `id` v = `tree`
)->a( n = `rows` v = |\{ path: '{ client->_bind( val = t_tree path = abap_true ) }', | &&
|parameters: \{ arrayNames: ['NODES'], numberOfExpandedLevels: 1 \} \}|
)->a( n = `selectionMode` v = `None`
)->a( n = `visibleRowCount` v = client->_bind( visible_rows )
)->a( n = `class` v = `sapUiSmallMarginBeginEnd` ).
table->ele( n = `extension` ns = `table`
)->ele( `OverflowToolbar`
)->tag( `Title`
)->a( n = `text` v = `Sales`
)->tag( `ToolbarSpacer`
)->tag( `Button`
)->a( n = `text` v = `Expand All`
)->a( n = `icon` v = `sap-icon://expand-group`
)->a( n = `press` v = client->_event( `EXPAND` )
)->tag( `Button`
)->a( n = `text` v = `Collapse All`
)->a( n = `icon` v = `sap-icon://collapse-group`
)->a( n = `press` v = client->_event( `COLLAPSE` ) ).
" the bar at the start of the row tells the totals from the sales
table->ele( n = `rowSettingsTemplate` ns = `table`
)->tag( n = `RowSettings` ns = `table`
)->a( n = `highlight` v = |\{= $\{KIND\} === '{ cs_kind-total }' ? 'Warning' : $\{KIND\} === '{ cs_kind-subtotal }' ? 'Information' : 'None' \}| ).
" no sortProperty and no filterProperty: the sums belong to the tree as
" the backend built it
DATA(columns) = table->ele( n = `columns` ns = `table` ).
columns->ele( n = `Column` ns = `table`
)->a( n = `width` v = `18rem`
)->tag( `Label`
)->a( n = `text` v = `Region / Country / Product`
)->ele( n = `template` ns = `table`
)->tag( `Text`
)->a( n = `text` v = `{NAME}`
)->a( n = `wrapping` b = abap_false ).
columns->ele( n = `Column` ns = `table`
)->a( n = `width` v = `8rem`
)->a( n = `hAlign` v = `End`
)->tag( `Label`
)->a( n = `text` v = `Quantity`
)->ele( n = `template` ns = `table`
)->tag( `Text`
)->a( n = `text` v = `{QUANTITY}` ).
columns->ele( n = `Column` ns = `table`
)->a( n = `width` v = `10rem`
)->a( n = `hAlign` v = `End`
)->tag( `Label`
)->a( n = `text` v = `Amount`
)->ele( n = `template` ns = `table`
)->tag( `Text`
)->a( n = `text` v = `{ parts: ['AMOUNT', 'CURRENCY'], type: 'sap.ui.model.type.Currency', formatOptions: { showMeasure: false } }` ).
columns->ele( n = `Column` ns = `table`
)->a( n = `width` v = `6rem`
)->tag( `Label`
)->a( n = `text` v = `Currency`
)->ele( n = `template` ns = `table`
)->tag( `Text`
)->a( n = `text` v = `{CURRENCY}` ).
client->view_display( view->stringify( ) ).
ENDMETHOD.
ENDCLASS.