Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member181923
Active Participant
0 Kudos
At a previous engagement, the client wanted a modification to the standard SAP-delivered Report Writer (RW) program invoked by transaction S_ALR_87013542. Unfortunately, the client staff who knew RW were to busy to register a new table in RW and modify the figures/characteristics of the original program. So, we wrote a work-around that is remarkably fast and flexible. The work-around requires only four types of knowledge: 1) how the SAP tables SETNODE and SETLEAF are structured and how they are filled by transactions such as KAHn or GS0n; 2) how to permit selection of a report set on a selection screen; 3) how to "tree-up" a report set into a Dewey Decimal tree that can be read rightward and upward from any given detail line; 4) how to do such "tree-ups" even for report sets in which one or more report subsets contain orphan elements as well as additional (lower) subsets. For those not familiar with (1-4), Sections 1-4 below tell you all you need to know. Section 5 contains the type/data declarations for Sections 2-4. 1. Report Sets, SETNODE, and SETLEAF. Create a dummy report set using any transaction such as GS01 or KAH1. Make sure you create a multi-level report set with three or four levels, and make sure some nodes at various levels contain orphans as well as subsets. (The code presented below uses a cost element report set created via KAH1.) Then go into Data Dictionary and see the result of what you've done in the SAP tables SETNODE and SETLEAF. 2. Selection of a Report Set on a Selection Screen If you examine the following declarations and code snippet, you will see that they were stolen from directly from the front-end of a Report Writer Program. But "mirabile dictu", they work in a plain old custom program. SELECTION-SCREEN BEGIN OF BLOCK COST_SELECTION WITH FRAME TITLE TEXT-003. PARAMETERS: $1KSTAR LIKE RKSB1-KAGRU. SELECT-OPTIONS s_celm FOR cska-kstar. SELECTION-SCREEN END OF BLOCK COST_SELECTION. AT SELECTION-SCREEN ON VALUE-REQUEST FOR $1KSTAR. l_dyname = 'ZRFI_ZCLNTRMB_REPT'. l_dynumb = '1000'. CLEAR l_dynpfields. MOVE '$1KSTAR ' to l_dynpfields-fieldname. APPEND l_dynpfields. CALL FUNCTION 'DYNP_VALUES_READ' EXPORTING dyname = l_dyname dynumb = l_dynumb TABLES dynpfields = l_dynpfields. READ TABLE l_dynpfields WITH KEY fieldname = '$1KSTAR '. CHECK l_dynpfields-FIELDINP = 'X'. CALL FUNCTION 'K_GROUP_SELECT' EXPORTING CLASS = '0102' FIELD_NAME = 'KSTAR ' TABLE = 'CCSS ' IMPORTING SETID = %1KSTAR SET_NAME = $1KSTAR EXCEPTIONS NO_SET_PICKED = 02. CASE SY-SUBRC. WHEN 1. MESSAGE S003. WHEN 2. MESSAGE S004. ENDCASE. 3. Treeing Up Your Selected Report Set. This code takes the report set created in (1) and selected in (2) and trees it up into a Dewey Decimal tree with some extra signals letting us know when a node (vertex) is: a) maximal (no descendant nodes); b) rightmost (no right-sisters); and c) rightmost non-maximal but with a maximal right sister. All variables are declared in Section 5. Also, note that the code is written to handle several different selection-screen possibilities documented at the top of the coee. * ***************************************************** * assume we don't have a complex cost element group, so * just one grand total line v_level_max = 1. * four possibilities regarding cost elements/cost element groups * 1) no cost element(s) selected and no cost element group selected * 2) cost element(s) selected, not a cost element group * 3) simple cost element group selected (root plus just cost elements) * 4) complex cost element group (with subgroups) * if this fails, then no cost element processing need be done IF s_celm-low <> '' or $1KSTAR <> ''. * if this fails, then a cost element group has been selected IF s_celm-low <> ''. * must be a cost element range, so table the elements in the range SELECT kstar FROM cska INTO wa_cost_elmnt-kstar WHERE kstar in s_celm. wa_cost_elmnt-ceg = 'RANGE'. INSERT wa_cost_elmnt INTO TABLE i_cost_elmnt. ENDSELECT. SORT i_cost_elmnt BY kstar. * ok, we must have some type of cost element group at this point ELSE. v_1KSTAR = $1KSTAR. * so check and see if simple (no subgroups) or complex (subgroups) SELECT COUNT(*) FROM SETNODE INTO v_chk_ceg WHERE setname = $1KSTAR. * if no children of root in SETNODE then group is simple IF v_chk_ceg = 0. * OK, we have a simple cost element group, so: * 1) set flag (for use in tree double-click method) indicating * that a SIMPLE Cost Element Group has been selected; * 2) fill i_cost_elmnt. v_ceg_type = 'S'. PERFORM FillCEsFromCEG USING i_cost_elmnt i_sleaf v_1KSTAR. SORT i_cost_elmnt BY kstar. * OK, we have a complex group ELSE. v_ceg_type = 'C'. SELECT COUNT(*) FROM SETNODE INTO v_ch_cnt1 WHERE setname = v_1KSTAR. SELECT subsetname setname seqnr FROM setnode INTO wa_snode WHERE setname = v_1KSTAR. wa_snode-level = 1. IF wa_snode-seqnr = v_ch_cnt1. wa_snode-rightmost = 'Y'. ELSE. wa_snode-rightmost = 'N'. ENDIF. SELECT COUNT(*) FROM SETNODE INTO v_ch_cnt2 WHERE setname = wa_snode-subsetname. IF v_ch_cnt2 = 0. wa_snode-max = 'Y'. ELSE. wa_snode-max = 'N'. ENDIF. v_ch_seqnr = wa_snode-seqnr. SHIFT v_ch_seqnr LEFT DELETING LEADING ' '. CONCATENATE '1' v_ch_seqnr INTO wa_snode-dewdec SEPARATED BY '.'. INSERT wa_snode INTO TABLE i_snode. ENDSELECT. v_level = 1. PERFORM FillOutSNode USING i_snode v_level. SORT i_snode by dewdec. * get max depth from i_snode (not counting root) to use in calculating * node level in grid display v_level_max = 0. LOOP AT i_snode INTO wa_snode. IF wa_snode-level > v_level_max. v_level_max = wa_snode-level. ENDIF. ENDLOOP. v_level_max = v_level_max + 1. * this is a preliminary loop on i_snode (prior to loop that finds * cost elements under node. It determines if sub-groups with * sub-sub-groups also have orphan cost elements LOOP AT i_snode into wa_snode WHERE max = 'N'. SELECT COUNT(*) FROM setleaf INTO v_orph_cnt WHERE setname = wa_snode-subsetname. IF v_orph_cnt > 0. wa_snode-max = 'M'. MODIFY TABLE i_snode FROM wa_snode. ENDIF. ENDLOOP. * this loop processes each MAX node N in i_snode for two purposes: * 1) get the cost elements under N. * 2) get any orphan cost elements under any of N's ancestors * IF N is rightmost. v_ssname_lag = ''. LOOP AT i_snode into wa_snode where max = 'Y'. * just to save typing, get cur node & parent into variables. v_ssname = wa_snode-subsetname. v_ssnm_parnt = wa_snode-setnm. * for debug only IF v_ssname <> v_ssname_lag. v_ssname_lag = v_ssname. ENDIF. PERFORM FillCEsFromCEG USING i_cost_elmnt i_sleaf v_ssname. * IF current node is RIGHTMOST(!): * determine if ANY ANCESTOR of current node is "mixed" * (except the CEG ROOT, which is handled after loop) * For each "mixed" ancestor * get its cost element children as if it were "simple". IF wa_snode-rightmost = 'Y'. PERFORM ReadForMixedAncestor USING v_ssnm_parnt. ENDIF. ENDLOOP. * this checks for children of root cost element group PERFORM FillCEsFromCEG USING i_cost_elmnt i_sleaf v_1KSTAR. * reset * this ends if to check for simple vs complex cost element group ENDIF. * this ends if to check for cost elements vs cost element grou ENDIF. ELSE. * no cost element of any type has been selected v_ceg_type = 'N'. * this ends if to check for cost elements OR cost element group ENDIF. * this creates rightmost indicators in i_cost_elmnt * prime the pump with parent of first element in i_cost_elmnt LOOP AT i_cost_elmnt INTO wa_cost_elmnt. v_ce_cntr = v_ce_cntr + 1. IF v_ce_cntr = 2. EXIT. ENDIF. v_ce_ceg_lag = wa_cost_elmnt-ceg. v_ce_lag = wa_cost_elmnt-kstar. ENDLOOP. * loop on i_cost_elmnt and flag rightmost on change in ceg. * NOTE!: LOOP AT i_cost_elmnt INTO wa_cost_elmnt. READ TABLE i_cost_elmnt INTO wa_cost_elmnt2 WITH TABLE KEY kstar = v_ce_lag. IF wa_cost_elmnt-ceg = v_ce_ceg_lag. wa_cost_elmnt2-rightmost = 'N'. ELSE. wa_cost_elmnt2-rightmost = 'Y'. ENDIF. MODIFY TABLE i_cost_elmnt FROM wa_cost_elmnt2. v_ce_ceg_lag = wa_cost_elmnt-ceg. v_ce_lag = wa_cost_elmnt-kstar. ENDLOOP. * don't forget to set rightmost in LAST row also. READ TABLE i_cost_elmnt INTO wa_cost_elmnt2 WITH TABLE KEY kstar = v_ce_lag. wa_cost_elmnt2-rightmost = 'Y'. MODIFY TABLE i_cost_elmnt FROM wa_cost_elmnt2. *&--------------------------------------------------------* *& Form FillCEsFromCEG *&--------------------------------------------------------* * Form FillCEsFrom CEG fills the cost element table if a * SIMPLE (!) Cost Element Group has been selected FORM FillCEsFromCEG USING fi_cost_elmnt TYPE t_cost_elmnt fi_sleaf TYPE t_sleaf fv_ssname LIKE setnode-subsetname. DATA: fwa_sleaf TYPE LINE OF t_sleaf, fwa_cost_elmnt TYPE LINE OF t_cost_elmnt. CLEAR fi_sleaf. SELECT setname lineid valsign valoption valfrom valto FROM setleaf INTO fwa_sleaf WHERE setclass = '0102' AND subclass = 'USGL' AND setname = fv_ssname. APPEND fwa_sleaf to fi_sleaf. ENDSELECT. SORT fi_sleaf BY setnm lineid. LOOP at fi_sleaf INTO fwa_sleaf. IF fwa_sleaf-vopt = 'EQ'. fwa_cost_elmnt-kstar = fwa_sleaf-vf. fwa_cost_elmnt-ceg = fv_ssname. INSERT fwa_cost_elmnt INTO TABLE fi_cost_elmnt. ELSEIF fwa_sleaf-vopt = 'BT'. SELECT kstar FROM cska INTO fwa_cost_elmnt-kstar WHERE kstar >= fwa_sleaf-vf AND kstar <= fwa_sleaf-vt. fwa_cost_elmnt-ceg = fv_ssname. INSERT fwa_cost_elmnt INTO TABLE fi_cost_elmnt. ENDSELECT. ELSE. * in case there are other relations besides EQ and BT in SETLEAF ENDIF. ENDLOOP. ENDFORM. *&_-------------------------------------------------------* *& Form FillOutSNode *&--------------------------------------------------------* * Form FillOutSNode fills the cost element table if a * COMPLEX (!) Cost Element Group has been selected FORM FillOutSNode USING fi_snode TYPE t_snode fv_level TYPE i. DATA: fwa_snode TYPE LINE OF t_snode, fwa_snode_work TYPE LINE OF t_snode, fv_ch_cnt1 TYPE i, fv_ch_seqnr(22) TYPE c, fv_ch_continue TYPE c, fv_level2 TYPE i. * ********************************************************** * NOTE: !!!! critical code: governs exit from recursive form * DO NOT CHANGE !!!! fv_ch_continue = 'N'. * *********************************************************** LOOP AT fi_snode INTO fwa_snode WHERE level = fv_level. SELECT COUNT(*) FROM SETNODE INTO fv_ch_cnt1 WHERE setname = fwa_snode-subsetname. * ********************************************************** * NOTE: !!!! critical code: governs exit from recursive form * DO NOT CHANGE !!!! IF fv_ch_cnt1 = 0. CONTINUE. ELSE. fv_ch_continue = 'Y'. ENDIF. * *********************************************************** SELECT subsetname setname seqnr FROM setnode INTO fwa_snode_work WHERE setname = fwa_snode-subsetname. fwa_snode_work-level = fv_level + 1. IF fwa_snode_work-seqnr = fv_ch_cnt1. fwa_snode_work-rightmost = 'Y'. ELSE. fwa_snode_work-rightmost = 'N'. ENDIF. SELECT COUNT(*) FROM SETNODE INTO v_ch_cnt2 WHERE setname = fwa_snode_work-subsetname. IF v_ch_cnt2 = 0. fwa_snode_work-max = 'Y'. ELSE. fwa_snode_work-max = 'N'. ENDIF. v_ch_seqnr = fwa_snode_work-seqnr. SHIFT v_ch_seqnr LEFT DELETING LEADING ' '. CONCATENATE fwa_snode-dewdec v_ch_seqnr INTO fwa_snode_work-dewdec SEPARATED BY '.'. INSERT fwa_snode_work INTO TABLE fi_snode. ENDSELECT. ENDLOOP. * *********************************************************** * NOTE: !!!! critical code: if the "if" here fails, then this is the * drop thru to the exit from the recursive * form * DO NOT CHANGE!!!! * ********************************************************** IF fv_ch_continue = 'Y'. fv_level2 = fv_level + 1. PERFORM FillOutSNode USING fi_snode fv_level2. ENDIF. * *********************************************************** ENDFORM. *---------------------------------------------------------* *& Form ReadForMixedAncestor *_--------------------------------------------------------* FORM ReadForMixedAncestor USING fv_setnm LIKE setnode-setname. DATA: fwa_snode TYPE LINE OF t_snode. READ TABLE i_snode INTO fwa_snode WITH TABLE KEY subsetname = fv_setnm. IF fwa_snode-max = 'M'. v_ssnm_parnt = fwa_snode-subsetname. PERFORM FillCEsFromCEG USING i_cost_elmnt i_sleaf v_ssnm_parnt. ENDIF. IF fwa_snode-setnm <> v_1KSTAR AND fwa_snode-rightmost = 'Y'. fv_setnm = fwa_snode-setnm. PERFORM ReadForMixedAncestor USING fv_setnm. ENDIF. ENDFORM. * ********************************************************* 4. Use the tree to subtotal your detail items upward and rightward. Note: The data itabs referenced in this code are declared in Section 5, and their meaning should be clear from the field cat snippet shown in Section 6. IF v_ceg_type = 'N'. LOOP AT i_cost_data INTO wa_cost_data. wa_grnd_totls-ZNRMB_ACTUAL = wa_grnd_totls-ZNRMB_ACTUAL + wa_cost_data-ZNRMB_ACTUAL. wa_grnd_totls-ZNRMB_COMMIT = wa_grnd_totls-ZNRMB_COMMIT + wa_cost_data-ZNRMB_COMMIT. wa_grnd_totls-ZNRMB_TOTAL = wa_grnd_totls-ZNRMB_TOTAL + wa_cost_data-ZNRMB_TOTAL. wa_grnd_totls-ZNRMB_OPEN = wa_grnd_totls-ZNRMB_OPEN + wa_cost_data-ZNRMB_OPEN. wa_grnd_totls-ZNRMB_RLSED = wa_grnd_totls-ZNRMB_RLSED + wa_cost_data-ZNRMB_RLSED. ENDLOOP. wa_grnd_totls-ZNRMB_KSTAR = 'Total'. APPEND wa_grnd_totls TO i_cost_data. * If: * cost element(s) have been selected * OR * a SIMPLE Cost Element Group has been selected * then: * this code will filter the rows in i_cost_data * according to the cost elements that have already been placed * into i_cost_elmnt. ELSEIF s_celm-low <> '' OR v_ceg_type = 'S'. CLEAR i_cost_data_hsh. LOOP AT i_cost_elmnt INTO wa_cost_elmnt. LOOP AT i_cost_data INTO wa_cost_data_hsh. IF wa_cost_data_hsh-ZNRMB_KSTAR = wa_cost_elmnt-kstar. INSERT wa_cost_data_hsh INTO TABLE i_cost_data_hsh. ENDIF. ENDLOOP. ENDLOOP. * since no further cost element group processing required, * move the filtered rows back from temp table to usual grid table. * and total them all up for the single total line CLEAR i_cost_data. LOOP AT i_cost_data_hsh INTO wa_cost_data. wa_grnd_totls-ZNRMB_ACTUAL = wa_grnd_totls-ZNRMB_ACTUAL + wa_cost_data-ZNRMB_ACTUAL. wa_grnd_totls-ZNRMB_COMMIT = wa_grnd_totls-ZNRMB_COMMIT + wa_cost_data-ZNRMB_COMMIT. wa_grnd_totls-ZNRMB_TOTAL = wa_grnd_totls-ZNRMB_TOTAL + wa_cost_data-ZNRMB_TOTAL. wa_grnd_totls-ZNRMB_OPEN = wa_grnd_totls-ZNRMB_OPEN + wa_cost_data-ZNRMB_OPEN. wa_grnd_totls-ZNRMB_RLSED = wa_grnd_totls-ZNRMB_RLSED + wa_cost_data-ZNRMB_RLSED. APPEND wa_cost_data to i_cost_data. ENDLOOP. * append single final total line to i_cost_data IF $1KSTAR <> ''. wa_grnd_totls-ZNRMB_KSTAR = $1KSTAR. wa_grnd_totls-ZNRMB_DESCRIP = v_ceg_ktext. ELSE. wa_grnd_totls-ZNRMB_KSTAR = 'Total'. ENDIF. APPEND wa_grnd_totls TO i_cost_data. * a complex cost group must have been selected. ELSE. v_1KSTAR = $1KSTAR. * create rows of i_ceg_totals from i_snode CLEAR i_ceg_totals. wa_ceg_totals-ZNRMB_KSTAR = v_1KSTAR. INSERT wa_ceg_totals INTO TABLE i_ceg_totals. LOOP AT i_snode INTO wa_snode. wa_ceg_totals-ZNRMB_KSTAR = wa_snode-subsetname. INSERT wa_ceg_totals INTO TABLE i_ceg_totals. ENDLOOP. * filter data by cost elements in selected cost element group and put * in hashed cost data lable for faster look-ups in FilterData form CLEAR i_cost_data_hsh. LOOP AT i_cost_elmnt INTO wa_cost_elmnt. LOOP AT i_cost_data INTO wa_cost_data_hsh. IF wa_cost_data_hsh-ZNRMB_KSTAR = wa_cost_elmnt-kstar. INSERT wa_cost_data_hsh INTO TABLE i_cost_data_hsh. ENDIF. ENDLOOP. ENDLOOP. CLEAR i_cost_data. PERFORM FilterDataThruComplexCEG USING i_snode i_sleaf i_cost_elmnt i_cost_data_hsh i_cost_data i_ceg_totals v_1KSTAR. READ TABLE i_ceg_totals INTO wa_grnd_totls WITH TABLE KEY ZNRMB_KSTAR = v_1KSTAR. wa_grnd_totls-ZNRMB_DESCRIP = v_ceg_ktext. APPEND wa_grnd_totls TO i_cost_data. ENDIF. * 2nd-To-Last loop on i_cost_data to set level numbers in first column * of grid. * but before loop, get v_level_max into work-field. v_level_wrk = v_level_max. v_level_wrk22 = v_level_wrk. SHIFT v_level_wrk22 LEFT DELETING LEADING ' '. v_level_max1 = v_level_wrk22. LOOP AT i_cost_data INTO wa_cost_data. IF s_celm-low = '' AND $1KSTAR = ''. * we have no selected cost elements nor cost element group. v_work5 = wa_cost_data-ZNRMB_KSTAR(5). IF v_work5 = 'Total'. wa_cost_data-ZNRMB_LEVEL = v_level_max1 . wa_cost_data-ZNRMB_COLOR = 'C310'. MODIFY i_cost_data FROM wa_cost_data. ELSE. wa_cost_data-ZNRMB_LEVEL = ''. wa_cost_data-ZNRMB_COLOR = 'C210'. MODIFY i_cost_data FROM wa_cost_data. ENDIF. CONTINUE. ENDIF. READ TABLE i_cost_elmnt INTO wa_cost_elmnt WITH TABLE KEY kstar = wa_cost_data-ZNRMB_KSTAR. * we're on a cost element line, so level field = ' ' in grid. IF sy-subrc = 0. wa_cost_data-ZNRMB_LEVEL = ' ' . wa_cost_data-ZNRMB_COLOR = 'C210'. MODIFY i_cost_data FROM wa_cost_data. CONTINUE. ENDIF. * we're not on a cost element line, so either: * we're on grand total line (if v_ceg_type <> 'C') * or we're on intermediate/grand total line (if v_ceg_type = 'C') IF v_ceg_type <> 'C'. wa_cost_data-ZNRMB_LEVEL = '1'. wa_cost_data-ZNRMB_COLOR = 'C310'. MODIFY i_cost_data FROM wa_cost_data. * note: this EXIT is actually redundant, because if we're not on * a cost element line and we don't have a 'C' cost element group * then we must be on the grand total line. EXIT. ENDIF. * we're not on a cost element line * but we do have a cost element group. READ TABLE i_snode INTO wa_snode WITH TABLE KEY subsetname = wa_cost_data-ZNRMB_KSTAR. IF sy-subrc <> 0. * we don't have a row in i_snode, so we're at the end. wa_cost_data-ZNRMB_LEVEL = v_level_max1. wa_cost_data-ZNRMB_COLOR = 'C310'. MODIFY i_cost_data FROM wa_cost_data. * again, this EXIT is redundant because we must be at the end here. EXIT. ENDIF. * we have a 'C' type group and we're on an intermediate row, so * compute the grid level from v_level_max and the level we're on * in i_snode. v_level_wrk = v_level_max - wa_snode-level. v_level_wrk22 = v_level_wrk. SHIFT v_level_wrk22 LEFT DELETING LEADING ' '. v_level_wrk1 = v_level_wrk22. wa_cost_data-ZNRMB_LEVEL = v_level_wrk1. wa_cost_data-ZNRMB_COLOR = 'C310'. MODIFY i_cost_data FROM wa_cost_data. ENDLOOP. * Last loop on i_cost_data to compute RLESST as * RELEASED - TOTAL LOOP AT i_cost_data INTO wa_cost_data. wa_cost_data-ZNRMB_RLESST = wa_cost_data-ZNRMB_RLSED - wa_cost_data-ZNRMB_TOTAL. MODIFY i_cost_data FROM wa_cost_data. ENDLOOP. *&---------------------------------------------------------------------* *& FilterDataThruComplexCEG *&---------------------------------------------------------------------* FORM FilterDataThruComplexCEG USING fi_snode TYPE t_snode fi_sleaf TYPE t_sleaf fi_cost_elmnt TYPE t_cost_elmnt fi_cost_data_hsh TYPE t_cost_data_hsh fi_cost_data TYPE t_cost_data fi_ceg_totals TYPE t_ceg_totals fv_1KSTAR LIKE setnode-subsetname. DATA: fwa_snode TYPE LINE OF t_snode, fwa_sleaf TYPE LINE OF t_sleaf, fwa_cost_elmnt TYPE LINE OF t_cost_elmnt, fwa_cost_data_hsh TYPE ZCLNTRMB_GRID1, fwa_cost_data TYPE ZCLNTRMB_GRID1, fwa_ceg_totals TYPE ZCLNTRMB_GRID1, fv_el_parent LIKE setnode-subsetname, fv_rmost TYPE c, fv_ce_data TYPE c. * using the cost element table, read the cost element detail data * and roll these detail data up into higher totals; * also, put all detail lines and total lines to grid itab. LOOP AT fi_cost_elmnt INTO fwa_cost_elmnt. * get parent of cost element we're on fv_el_parent = fwa_cost_elmnt-ceg. IF fwa_cost_elmnt-rightmost = 'Y'. fv_rmost = 'E'. ELSE. fv_rmost = 'N'. ENDIF. READ TABLE fi_cost_data_hsh INTO fwa_cost_data WITH TABLE KEY ZNRMB_KSTAR = fwa_cost_elmnt-kstar. * if no detail cost data, then call CreateCEGTotals ONLY IF * we are on a rightmost cost-element (to force subtotal print cascade) IF sy-subrc <> 0. IF fv_rmost = 'E'. fv_ce_data = 'N'. CLEAR fwa_cost_data. PERFORM CreateCEGTotals USING fi_snode fi_cost_elmnt fi_cost_data fi_ceg_totals fv_1KSTAR fv_el_parent fv_rmost fwa_cost_data fwa_cost_elmnt fv_ce_data. ELSE. CONTINUE. ENDIF. ELSE. fv_ce_data = 'Y'. * puts detail lines to the grid itab. APPEND fwa_cost_data TO fi_cost_data. * using parent of cost element to "prime the pump", call * recursive "tree-chase" form to: * 1) create totals for parent AND ALL ancestors * 2) add subtotal/total rows to grid itab as appropriate PERFORM CreateCEGTotals USING fi_snode fi_cost_elmnt fi_cost_data fi_ceg_totals fv_1KSTAR fv_el_parent fv_rmost fwa_cost_data fwa_cost_elmnt fv_ce_data. ENDIF. ENDLOOP. ENDFORM. *&---------------------------------------------------------------------* *& Form CreateCEGTotals *&---------------------------------------------------------------------* FORM CreateCEGTotals USING ffi_snode TYPE t_snode ffi_cost_elmnt TYPE t_cost_elmnt ffi_cost_data TYPE t_cost_data ffi_ceg_totals TYPE t_ceg_totals ffv_1KSTAR LIKE setnode-subsetname ffv_el_parent LIKE setnode-subsetname ffv_rmost TYPE c ffwa_cost_data TYPE ZCLNTRMB_GRID1 ffwa_cost_elmnt TYPE LINE OF t_cost_elmnt ffv_ce_data TYPE c. DATA: ffwa_snode TYPE LINE OF t_snode, ffwa_snode2 TYPE LINE OF t_snode, ffwa_ceg_totals TYPE ZCLNTRMB_GRID1, ffv_key LIKE setnode-subsetname. ffv_key = ffv_el_parent. * accumulate detail data into ancestors ONLY IF some non-zero data * note: 1st time thru, parent will be parent of cost element itself IF ffv_ce_data = 'Y'. READ TABLE ffi_snode INTO ffwa_snode WITH TABLE KEY subsetname = ffv_key. * mark each node in i_snode as having data so that * subtotal print will NOT be suppressed. IF sy-subrc = 0. ffwa_snode-havedata = 'Y'. MODIFY TABLE ffi_snode FROM ffwa_snode. ENDIF. READ TABLE ffi_ceg_totals INTO ffwa_ceg_totals WITH TABLE KEY ZNRMB_KSTAR = ffv_key. ffwa_ceg_totals-ZNRMB_ACTUAL = ffwa_ceg_totals-ZNRMB_ACTUAL + ffwa_cost_data-ZNRMB_ACTUAL. ffwa_ceg_totals-ZNRMB_COMMIT = ffwa_ceg_totals-ZNRMB_COMMIT + ffwa_cost_data-ZNRMB_COMMIT. ffwa_ceg_totals-ZNRMB_TOTAL = ffwa_ceg_totals-ZNRMB_TOTAL + ffwa_cost_data-ZNRMB_TOTAL. * BEGIN OF COMMENT BLOCK - D01K927480/SR-76658 * ffwa_ceg_totals-ZNRMB_PLAN = ffwa_ceg_totals-ZNRMB_PLAN + * ffwa_cost_data-ZNRMB_PLAN. * END OF COMMENT BLOCK - D01K927480/SR-76658 ffwa_ceg_totals-ZNRMB_OPEN = ffwa_ceg_totals-ZNRMB_OPEN + ffwa_cost_data-ZNRMB_OPEN. ffwa_ceg_totals-ZNRMB_RLSED = ffwa_ceg_totals-ZNRMB_RLSED + ffwa_cost_data-ZNRMB_RLSED. * BEGIN OF COMMENT BLOCK - D01K927480/SR-76658 * ffwa_ceg_totals-ZNRMB_ORIG = ffwa_ceg_totals-ZNRMB_ORIG + * ffwa_cost_data-ZNRMB_ORIG. * END OF COMMENT BLOCK - D01K927480/SR-76658 MODIFY TABLE ffi_ceg_totals FROM ffwa_ceg_totals. ELSE. ffwa_ceg_totals-ZNRMB_KSTAR = ffv_key. ENDIF. READ TABLE ffi_snode INTO ffwa_snode WITH TABLE KEY subsetname = ffv_key. * print a subtotal line ONLY IF * we are on a "rightmost" parent * we are not on the root. * we are on an element IF ffv_rmost <> 'N' AND ffv_key <> v_1KSTAR AND ffwa_snode-havedata = 'Y'. * BEGIN OF CODE BLOCK - D01K926214/SR-76658 * since we here because we're not on a cost element with data for it * we must refind the ceg_totals record for the parent of the cost * element READ TABLE ffi_ceg_totals INTO ffwa_ceg_totals WITH TABLE KEY ZNRMB_KSTAR = ffv_key. * END OF CODE BLOCK - D01K926214/SR-76658 SELECT SINGLE descript FROM setheadert INTO ffwa_ceg_totals-ZNRMB_DESCRIP WHERE setname = ffv_key. APPEND ffwa_ceg_totals TO ffi_cost_data. ENDIF. IF ffv_el_parent = ffv_1KSTAR. * because we're at the topmost group (entered on selection screen) EXIT. ELSE. * get parent of node we're on READ TABLE ffi_snode INTO ffwa_snode WITH TABLE KEY subsetname = ffv_key. ffv_el_parent = ffwa_snode-setnm. * get rightmost indicator of node we're on READ TABLE ffi_snode INTO ffwa_snode2 WITH TABLE KEY subsetname = ffv_el_parent. IF sy-subrc <> 0. ffv_rmost = 'R'. ELSE. IF ffwa_snode-rightmost = 'Y' AND ffwa_snode2-max <> 'M' AND ffv_rmost <> 'N'. ffv_rmost = 'G'. ELSE. ffv_rmost = 'N'. ENDIF. * modify havedata flag in parent to 'Y' if 'Y' in current record. IF ffwa_snode-havedata = 'Y'. ffwa_snode2-havedata = 'Y'. MODIFY TABLE ffi_snode FROM ffwa_snode2. ENDIF. ENDIF. PERFORM CreateCEGTotals USING ffi_snode ffi_cost_elmnt ffi_cost_data ffi_ceg_totals ffv_1KSTAR ffv_el_parent ffv_rmost ffwa_cost_data ffwa_cost_elmnt ffv_ce_data. ENDIF. ENDFORM. ***************************************************** Section 5. Data Declarations * to support selection screen processing. DATA: l_dynpfields LIKE dynpread OCCURS 0 WITH HEADER LINE. DATA: l_dyname LIKE d020s-prog, l_dynumb LIKE d020s-dnum, %1KSTAR LIKE RGSBS-SETNR. * types for itabs used in treeing-up cost element report sets TYPES: BEGIN OF t_cost_elmnt_line, kstar LIKE cska-kstar, ceg LIKE setnode-setname, rightmost TYPE c, END OF t_cost_elmnt_line, t_cost_elmnt TYPE HASHED TABLE OF t_cost_elmnt_line WITH UNIQUE KEY kstar INITIAL SIZE 0, BEGIN OF t_sleaf_line, setnm like setleaf-setname, lineid like setleaf-lineid, vsign like setleaf-valsign, vopt like setleaf-valoption, vf like setleaf-valfrom, vt like setleaf-valto, END OF t_sleaf_line, t_sleaf TYPE STANDARD TABLE OF t_sleaf_line INITIAL SIZE 0, BEGIN OF t_snode_line, subsetname like setnode-subsetname, setnm like setnode-setname, seqnr like setnode-seqnr, level type i, max type c, rightmost type c, dewdec(40) type c, havedata type c, END OF t_snode_line, t_snode TYPE HASHED TABLE OF t_snode_line WITH UNIQUE KEY subsetname INITIAL SIZE 0. * itabs and wa's used in treeing up cost element report sets DATA: wa_cost_elmnt TYPE t_cost_elmnt_line, wa_cost_elmnt2 TYPE t_cost_elmnt_line, wa_sleaf TYPE LINE OF t_sleaf, wa_snode TYPE LINE OF t_snode, wa_snode2 TYPE LINE OF t_snode, i_cost_elmnt TYPE t_cost_elmnt, i_sleaf TYPE t_sleaf, i_snode TYPE t_snode. * misc variables for treeing up cost element report sets DATA: v_ch_cnt1 TYPE i, v_ch_cnt2 TYPE i, v_ch_seqnr(22) TYPE c, v_level TYPE i, v_chk_ceg TYPE i, v_1KSTAR LIKE setnode-subsetname, v_ssname LIKE setnode-subsetname, v_ssnm_parnt LIKE setnode-subsetname, v_ssname_lag LIKE setnode-subsetname, v_has_orphans TYPE c, v_orph_cnt TYPE i, v_ceg_type TYPE c, v_ce_cntr TYPE i, v_ce_lag LIKE setnode-subsetname, v_ce_ceg_lag LIKE setnode-subsetname, v_level_max TYPE i, v_level_wrk TYPE i, v_level_wrk22(22) TYPE c, v_level_max1 TYPE c, v_level_wrk1 TYPE c, v_parent(16) TYPE c, v_parent_flag TYPE c. * types for chasing data according to treed-up rept set TYPES: t_cost_data_hsh TYPE HASHED TABLE OF ZCLNTRMB_GRID1 WITH UNIQUE KEY ZNRMB_KSTAR INITIAL SIZE 0, t_cost_data TYPE STANDARD TABLE OF ZCLNTRMB_GRID1 INITIAL SIZE 0, t_ceg_totals TYPE HASHED TABLE OF ZCLNTRMB_GRID1 WITH UNIQUE KEY ZNRMB_KSTAR INITIAL SIZE 0. * itabs/wa's for chasing data according to treed-up rept set DATA: wa_cost_data TYPE ZCLNTRMB_GRID1, wa_cost_data_hsh TYPE ZCLNTRMB_GRID1, wa_costdata_chk TYPE ZCLNTRMB_GRID1, wa_ceg_totals TYPE ZCLNTRMB_GRID1, wa_grnd_totls TYPE ZCLNTRMB_GRID1. i_cost_data TYPE t_cost_data, i_cost_data_hsh TYPE t_cost_data_hsh, i_ceg_totals TYPE t_ceg_totals, * misc variables for chasing data according to treed-up rept set **************************************************** 6. Fieldcat Snippet. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_LEVEL'. i_fieldcat_ln-reptext = 'L'. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_KSTAR'. i_fieldcat_ln-reptext = 'Element/Grp'. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_DESCRIP'. i_fieldcat_ln-reptext = 'Description'. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_ACTUAL'. i_fieldcat_ln-reptext = 'Actual'. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_COMMIT'. i_fieldcat_ln-reptext = 'Commitments'. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_TOTAL'. i_fieldcat_ln-reptext = 'Total'. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_OPEN'. i_fieldcat_ln-reptext = 'Open'. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_RLSED'. i_fieldcat_ln-reptext = 'Authority'. i_fieldcat_ln-tabname = 'ZNASARMB_GRID1'. i_fieldcat_ln-fieldname = 'ZNRMB_RLESST'. i_fieldcat_ln-reptext = 'Difference'. * RLESST = RLSED - TOTAL