Simplest way to delete a row - abap

Is there any simplest/fastest way for below code:
DATA: lv_knuma_ag LIKE STANDARD TABLE OF zta_fg_hdr WITH HEADER LINE.
RANGES: lr_knuma_ag FOR zta_fg_hdr-knuma_ag.
"Select `knuma_ag` and save it to internal table `lv_knuma_ag`
LOOP AT li_promo.
SELECT dest~knuma_ag
FROM zta_fg_dest AS dest
INNER JOIN zta_s_d_xkunnr AS xkunnr ON xkunnr~zcd_dest EQ dest~zcd_dest
APPENDING CORRESPONDING FIELDS OF TABLE lv_knuma_ag
WHERE dest~knuma_ag EQ li_promo-knuma_ag
AND xkunnr~xkunnr EQ gi_vl-vkbur.
ENDLOOP.
"Insert `lv_knuma_ag` onto ranges table `lr_knuma_ag`
LOOP AT lv_knuma_ag.
lr_knuma_ag-sign = 'I'.
lr_knuma_ag-option = 'EQ'.
lr_knuma_ag-low = lv_knuma_ag-knuma_ag.
lr_knuma_ag-high = space.
APPEND lr_knuma_ag.
ENDLOOP.
"Delete row in `li_promo` where `knuma_ag` is in ranges table `lr_knuma_ag`
IF NOT lr_knuma_ag IS INITIAL.
DELETE li_promo WHERE knuma_ag IN lr_knuma_ag.
ENDIF.
As you see on the code, it contains twice loop to only fill the ranges table. I would like to make it only one, is it possible? Thanks.

Yes, it should be possible to achieve this without flooding your DBMS with possibly thousands of queries:
DATA: lt_knuma_ag_hash TYPE HASHED TABLE OF insert_type_of_knuma_ag_here WITH UNIQUE KEY TABLE_table_line.
IF li_promo[] IS NOT INITIAL.
SELECT DISTINCT knuma_ag
FROM zta_fg_dest
INTO TABLE lt_knuma_ag_hash
FOR ALL ENTRIES IN li_promo
WHERE knuma_ag = li_promo-knuma_ag.
ENDIF.
LOOP AT li_promo ASSIGNING <li_promo>.
READ TABLE lt_knuma_ag_hash TRANSPORTING NO FIELDS WITH TABLE KEY table_line = <li_promo>-knuma_ag.
IF sy-subrc = 0.
DELETE li_promo.
ENDIF.
ENDLOOP.

Related

Counting Duplicate Row in internal table

I need to count the number of duplicate rows in an internal table base on one field.
I have tried to create a work area and counting the duplicate data but the problem is it counts all duplicate data. My purpose is to count duplicate data by the same date.
DATA: gv_line TYPE i.
gv_line = 0.
LOOP AT i_sect_proe.
IF wa_sect_proe IS INITIAL.
wa_sect_proe = i_sect_proe.
CONTINUE.
ENDIF.
IF wa_sect_proe-/smr/wondat EQ i_final_f-/smr/wondat.
gv_line = gv_line + 1.
ENDIF.
i_sect_proe-/smr/line = gv_line.
ENDLOOP.
The code I've tried displays the number off all duplicate data.
DATA: BEGIN OF lt_result OCCURS 0,               date TYPE datum,               count TYPE i,           END OF lt_result.
SORT yourTable BY dateField.
LOOP AT yourTable.
    lt_result-date   = yourTable-dateField.
    lt_result-count = 1.
    COLLECT lt_result INTO lt_result.
ENDLOOP.
Result in lt_result[].

read from internal table with loop and no results

In the below code, I read data from database table with SELECT into the internal table dresult.
Reading the first line of the internal table displays the expected result, but using the LOOP displays nothing.
What's the issue?
Note: I tried to remove ENDSELECT and it worked. Why?
REPORT ZTEST02.
"Detail Informaion
TYPES : BEGIN OF details,
d1 type arktx, " description
d2 type lfimg, "quantity
END OF details.
DATA : dresult TYPE TABLE OF details WITH HEADER LINE,
t_dresult TYPE details,
sdno TYPE vbeln.
PARAMETERS packo TYPE vbeln OBLIGATORY MATCHCODE OBJECT f4_likp.
START-OF-SELECTION.
SELECT arktx,lfimg
INTO #dresult
FROM lips as detail
LEFT JOIN marm as material
ON detail~matnr = material~matnr
LEFT OUTER JOIN vbak
ON detail~vgbel = vbak~vbeln
WHERE detail~vbeln = #packo.
ENDSELECT.
READ TABLE dresult into t_dresult INDEX 1.
write: t_dresult-d1,t_dresult-d2.
LOOP AT dresult INTO t_dresult.
write: t_dresult-d1,t_dresult-d2.
ENDLOOP.
With SELECT ... ENDSELECT you select the data into a work area (INTO #dresult - which is actually the header line of the internal table with the same name). As result the internal table dresult does not contain any data, so the LOOP and the READ TABLE won't work.
I would declare the internal table without HEADER LINE and remove ENDSELECT:
DATA: dresult type STANDARD TABLE OF details,
...
SELECT ...
INTO TABLE #dresult
Moreover, after READ TABLE, it is always good to check if an entry was found:
READ TABLE ...
IF sy-subrc EQ 0.
...
ENDIF.

Change table row by index

How can I give a field a value with a specific index.
Or if the field is not initial I wanna change the value on this index
Example:
TYPES : BEGIN OF itab,
number1 type n,
endof itab.
lv_tabix = sy-tabix.
itab-number1 index lv-tabix = '1'.
Just use table expressions for this, if you are on the recent ABAP releases:
TRY.
itab[ lv-tabix ]-number1 = '1'.
CATCH cx_sy_itab_line_not_found INTO DATA(exc).
cl_demo_output=>display( exc->get_text( ) ).
ENDTRY.
You should read table by index and assign target line to filed symbol first:
READ TABLE {your itab} INDEX lv_tabix ASSIGNING FIELD-SYMBOL(<fs>).
<fs>-number1 = '1'.
Depending on your server version, seperate field symbol declaration may be needed:
FIELD-SYMBOLS <fs> TYPE {your table line type}
Check READ TABLE online help https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abapread_table_outdesc.htm#!ABAP_ALTERNATIVE_2#2#
Check the help of the sentence MODIFY (itab):
https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abapmodify_itab_single.htm
DATA: workarea TYPE your_type.
workarea-field = value.
"modifying for an index
MODIFY your_table INDEX your_index FROM workarea TRANSPORTING field.
"modifying for a condition
MODIFY your_table FROM workarea TRANSPORTING field WHERE your_condition.
Or you can use FIELD-SYMBOLS, as has been pointed before me by Anton.
This?
TYPES: begin OF ty_itab,
number1 TYPE n,
END OF ty_itab.
DATA: itab TYPE TABLE OF ty_itab,
wa_itab like line of itab,
lv_tabix TYPE sy-tabix.
APPEND wa_itab TO itab.
lv_tabix = sy-tabix.
READ TABLE itab INTO wa_itab INDEX lv_tabix.
wa_itab-number1 = '1'.
MODIFY itab FROM wa_itab INDEX lv_tabix.
BREAK-POINT.

how can I get values from the table

I concatenated values of select-options and a parameter. The condition of that query is based on the concatenated data. I can get all the data i need.
here's my code:
TABLES: bkpf.
SELECT-OPTIONS: s_belnr FOR bkpf-belnr NO-EXTENSION OBLIGATORY .
PARAMETERS: p_ghjahr LIKE bkpf-gjahr DEFAULT sy-datum(4) OBLIGATORY. "Fiscal
DATA: it_con TYPE TABLE OF BKPF,
ls_con TYPE bkpf-AWKEY,
lv_belnr LIKE bkpf-belnr,
IT TYPE STANDARD TABLE OF BKPF,
WA TYPE BKPF.
IF s_belnr-high IS INITIAL.
CONCATENATE s_belnr-low p_ghjahr INTO ls_con.
APPEND ls_con TO it_con.
ELSE.
lv_belnr = s_belnr-low.
WHILE lv_belnr LE s_belnr-high.
CONCATENATE lv_belnr p_ghjahr INTO ls_con.
APPEND ls_con TO it_con.
ADD 1 TO lv_belnr.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = lv_belnr
IMPORTING
output = lv_belnr.
ENDWHILE.
ENDIF.
LOOP AT it_concats INTO ls_concats.
SELECT BELNR
FROM BKPF
INTO CORRESPONDING FIELDS OF TABLE IT
FOR ALL ENTRIES IN IT_CONCATS
WHERE AWKEY EQ IT_CONCATS-AWKEY.
ENDLOOP.
LOOP AT IT INTO WA.
WRITE: / WA-BELNR.
ENDLOOP.
Ignoring (because your question is too vague), the type of document you are looking for, I'll suggest something like
(WARNING, I do NOT provide full answers, just code snipets who you must tune to make it work; if someone wants to improve my answer, feel free to do it, and I'll gladly will vote the new one as the good one... if it is)
data: awkey_range type range of bkpf-awkey,
awkey_line like line of awkey_range.
* Fill the awkey_range with something like
awkey_line-sign = 'I'.
awkey_line-option = 'EQ'.
* loop at bkpf_table into bkpf_line.
* concatenate bkpf_line-belnr bkpf_line-ghjahr into awkey_line-low.
* append awkey_line to awkey_range.
* endloop.
* And then a single SQL
select *
from bkpf
into table IT "Ouch, what a name
where awkey in awkey_range.
And it should work, if I'm not missing something.

Disable Column in VA01

I have a requirement where I need to disable the full column in Sales Order Line item. Fields are VBAP-ARKTX and VBAP-KDMAT.
I've found the way to disable columns with data in them, but not the whole column.
I used USEREXIT_FIELD_MODIFICATION to achieve this using the following code;
IF sy-TCODE = 'VA02'.
IF screen-name = 'VBAP-KDMAT' .
screen-INPUT = 0.
modify screen.
ENDIF.
ENDIF.
Is there a way to disable the whole column?
Adjusting table control which contains items is the easiest and the most recommended way. It can be done for single user or for group of users.
Otherwise, try to create a screen variant in SHD0. It allows easily hide any column of any table and any field on the screen.
The specific problem I faced was how to disable two fields, but let standard mapped data to be displayed in them.
To cater this requirement I used the following;
Include: MV45AFZZ
User Exit Name: USEREXIT_FIELD_MODIFICATION
Enhancement Name: -Any name you want-
I created an Enhancement and wrote the following code;
"Specify the condition
IF VBAK-VKORG = '1234' AND ( sy-TCODE = 'VA02' OR sy-TCODE = 'VA01' ) AND ( screen-name = 'VBAP-KDMAT' OR screen-name = 'VBAP-ARKTX' ).
screen-input = 0."disable input
MODIFY SCREEN.
DATA: i_tab_mara TYPE TABLE OF MARA WITH HEADER LINE.
DATA: l_maktx TYPE MAKT-MAKTX.
DATA: WA_MARA LIKE LINE OF i_tab_mara.
DATA: i_tab_vbap TYPE TABLE OF VBAP WITH HEADER LINE.
DATA: wa_vbap LIKE LINE OF i_tab_vbap.
IF sy-TCODE = 'VA01' .
SELECT SINGLE * from MARA INTO WA_MARA WHERE MATNR eq VBAP-MATNR.
SELECT MAKTX FROM MAKT INTO l_maktx WHERE MATNR eq VBAP-MATNR.
ENDSELECT.
VBAP-KDMAT = WA_MARA-KDMAT.
VBAP-ARKTX = l_maktx.
MODIFY SCREEN.
ELSEIF sy-TCODE = 'VA02' .
SELECT SINGLE * FROM VBAP INTO WA_VBAP WHERE VBELN eq VBAK-VBELN AND POSNR eq VBAP-POSNR.
IF WA_VBAP-ARKTX eq ''." Check if the fileds are empty, otherwise old data is overwritten
SELECT MAKTX FROM MAKT INTO l_maktx WHERE MATNR eq VBAP-MATNR.
ENDSELECT.
VBAP-ARKTX = l_maktx.
MODIFY SCREEN.
ENDIF.
IF WA_VBAP-KDMAT eq ''." Check if the fileds are empty, otherwise old data is overwritten
SELECT SINGLE * from MARA INTO WA_MARA WHERE MATNR eq VBAP-MATNR.
VBAP-KDMAT = WA_MARA-KDMAT.
MODIFY SCREEN.
ENDIF.
ENDIF.
ENDIF.
There is one thing, that You can do in the dynpro-designer. There You can modify the sap-standard-dynpro as a dynpro-modification.
Nevertheless, this might be overwritten with the next release. Is this also an option for You ?