Code: Alles auswählen.
Erkennen von belegten Intervallen innerhalb eines Nummernkreises
DATA:
matnr(18) type n,
nrk_von like matnr,
nrk_bis like matnr,
nrk_first like matnr value 100000,
nrk_last like matnr value 999999,
xmara like mara-matnr occurs 2000.
select matnr from mara
into table xmara
where matnr between nrk_von and nrk_last
order by matnr.
append nrk_last to xmara.
write: / 'Anzahl Einträge:', sy-dbcnt.
nrk_von = nrk_first.
loop at xmara into matnr from 2.
if nrk_von = matnr.
nrk_von = matnr + 1.
else.
nrk_bis = matnr - 1.
Write: / nrk_von no-zero.
if nrk_von <> nrk_bis.
write: '-', nrk_bis no-zero.
endif.
nrk_von = matnr + 1.
clear nrk_bis.
endif.
write: at 50 '==',matnr no-zero.
new-line.
endloop.
Code: Alles auswählen.
---------------------------------------------------------
Ausgabe bei
1,2,4,5,8,9,11,12,13,14,15,17,18,19,20,101,103,109:
---------------------------------------------------------
1 == 2
3 == 4
== 5
6 - 7 == 8
== 9
10 == 11
== 12
== 13
== 14
== 15
16 == 17
== 18
== 19
== 20
21 - 100 == 101
102 == 103
104 - 108 == 109
110 . 999998 == 999999
Code: Alles auswählen.
REPORT make_range_tab.
PARAMETERS:
p_zeile TYPE char256 OBLIGATORY DEFAULT 'C1,C2,C3,C4,C7,C8,C9,C11'.
TYPES:
gt_element TYPE string, "Grundlegender Typ, anpassbar je nach Bedarf
gt_elementrange TYPE RANGE OF gt_element.
START-OF-SELECTION.
PERFORM s_o_s USING p_zeile.
*&---------------------------------------------------------------------*
*& Form s_o_s
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM s_o_s USING value(i_zeile) TYPE csequence.
DATA:
ltab_range TYPE gt_elementrange.
FIELD-SYMBOLS:
<ls_rangeline> TYPE LINE OF gt_elementrange.
* eigentlicher Aufruf
PERFORM my_collect USING i_zeile CHANGING ltab_range[].
* Demoausgabe
WRITE:
/ i_zeile.
LOOP AT ltab_range[] ASSIGNING <ls_rangeline>.
WRITE:
/ <ls_rangeline>-sign, <ls_rangeline>-option,
<ls_rangeline>-low, <ls_rangeline>-high.
ENDLOOP.
ENDFORM. "s_o_s
*&---------------------------------------------------------------------*
*& Form my_collect
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->VALUE(I_ZEILE) text
* -->OTAB_RANGE text
*----------------------------------------------------------------------*
FORM my_collect USING value(i_zeile) TYPE csequence
CHANGING otab_range TYPE gt_elementrange.
DATA:
lv_compare TYPE gt_element,
lv_low TYPE gt_element,
lv_high TYPE gt_element,
ltab_elements TYPE STANDARD TABLE OF gt_element
WITH DEFAULT KEY INITIAL SIZE 0,
lv_subrc TYPE syst-subrc.
FIELD-SYMBOLS:
<ls_element> TYPE gt_element.
CLEAR:
otab_range[].
* Aufteilen in interne Tabelle
SPLIT i_zeile AT ',' INTO TABLE ltab_elements[].
* Jedes Element wird mit dem vorherigen verglichen.
LOOP AT ltab_elements[] ASSIGNING <ls_element>.
IF lv_compare IS INITIAL.
* Noch kein Vergleichselement vorhanden
lv_low = lv_compare = <ls_element>.
ELSE.
* Vergleichslogik ausgelagert - an Elementtyp anpassbar
PERFORM naechstes_element
USING lv_compare <ls_element> CHANGING lv_subrc.
IF NOT lv_subrc = 0.
* keine Folge, Eintrag speichern
PERFORM insert_entry USING lv_low lv_high CHANGING otab_range[].
* aktueller Eintrag als Vergleichselement speichern
lv_low = lv_compare = <ls_element>.
ELSE.
* Vergleichselement anpassen
lv_high = lv_compare = <ls_element>.
ENDIF.
ENDIF.
AT LAST.
* Letzten Eintrag nicht vergessen
PERFORM insert_entry USING lv_low lv_high CHANGING otab_range[].
ENDAT.
ENDLOOP.
ENDFORM. " my_collect
*&---------------------------------------------------------------------*
*& Form naechstes_element
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_LV_ELEMENT text
* -->P_<LS_ELEMENT> text
* <--P_LV_SUBRC text
*----------------------------------------------------------------------*
FORM naechstes_element USING value(i_compare) TYPE gt_element
value(i_current) TYPE gt_element
CHANGING o_subrc TYPE syst-subrc.
DATA:
lv_flag TYPE xfeld,
lv_comp TYPE char1,
lv_curr TYPE char1,
lv_icomp TYPE i,
lv_icurr TYPE i.
CLEAR:
o_subrc.
* ist (altes) Vergleichselement größer oder gleich, dann kein Nachfolger
IF i_compare >= i_current.
o_subrc = 1.
ELSE." i_compare < i_current.
lv_flag = space.
TRY.
* alle gleichen Zeichen(die keine Ziffer sind)
* von vorne her entfernen
WHILE lv_flag = space.
lv_comp = i_compare+0(1).
lv_curr = i_current+0(1).
IF lv_comp = lv_curr
AND lv_comp CN '0123456789'.
i_compare = i_compare+1.
i_current = i_current+1.
ELSE.
lv_flag = 'X'.
ENDIF.
ENDWHILE.
CATCH cx_sy_range_out_of_bounds.
lv_flag = 'X'.
ENDTRY.
* nur wenn der Rest nur aus Ziffern besteht kann verglichen werden
IF i_compare CN '0123456789'
OR i_current CN '0123456789'.
o_subrc = 2.
ELSE.
* Wandlung in Zahlen
lv_icomp = i_compare.
lv_icurr = i_current.
lv_icomp = lv_icurr - lv_icomp.
IF lv_icomp = 1.
CLEAR o_subrc.
ELSE.
o_subrc = 3.
ENDIF.
ENDIF.
ENDIF.
ENDFORM. " naechstes_element
*&---------------------------------------------------------------------*
*& Form insert_entry
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->VALUE(I_LOW) text
* -->VALUE(I_HIGH) text
* -->C_RANGE text
*----------------------------------------------------------------------*
FORM insert_entry USING value(i_low) TYPE gt_element
value(i_high) TYPE gt_element
CHANGING c_range TYPE gt_elementrange.
DATA:
lv_rangeline TYPE LINE OF gt_elementrange.
IF i_high IS INITIAL.
lv_rangeline-sign = 'I'.
lv_rangeline-option = 'EQ'.
lv_rangeline-low = i_low.
INSERT lv_rangeline INTO TABLE c_range[].
ELSE.
lv_rangeline-sign = 'I'.
lv_rangeline-option = 'BT'.
lv_rangeline-low = i_low.
lv_rangeline-high = i_high.
INSERT lv_rangeline INTO TABLE c_range[].
ENDIF.
ENDFORM. "insert_entry