我是ABAP的新手。我有一个问题,我无法理清哪个应该不难实现。
我有一个内部表itab
,其中包含行matnr
的一个组件为空的行。我想查看内部表格的palet
列,并根据matnr
表格中的palet
获取zlldet
,然后更改内部的matnr
列表格为新matnr
值。这是一个总结;
itab
表:
+-------+-------+-----------+
| palet | matnr | something |
+-------+-------+-----------+
| 1234 | null | abc |
| 1235 | null | saa |
| 1236 | null | ssd |
+-------+-------+-----------+
因此,我将检查palet
表中的zlldet
列,并找到该行的matnr
值。新的itab
值应为:
+-------+--------+-----------+
| palet | matnr | something |
+-------+--------+-----------+
| 1234 | 543213 | abc |
| 1235 | 988876 | saa |
| 1236 | 344545 | ssd |
+-------+--------+-----------+
我尝试了什么:
LOOP AT itab.
SELECT SINGLE matnr INTO itab-matnr
FROM zlldet WHERE palet = itab-palet.
ENDIF.
ENDLOOP.
我正在尝试更改第二行中的值。我知道这是错的,我应该使用一些MODIFY
语句,但我不确定如何。
修改:
以下是完整的代码:
REPORT zwps0510 MESSAGE-ID zc LINE-SIZE 255 NO STANDARD PAGE HEADING.
TABLES: zzllog, zzldet, marc, makt.
DATA: BEGIN OF itab OCCURS 0.
INCLUDE STRUCTURE zzllog.
DATA: END OF itab.
DATA: adet TYPE p.
*/ paket numaraları
SELECT-OPTIONS: spalet FOR zzllog-palet. "/paket no
SELECT-OPTIONS: spaleta FOR zzllog-paleta. "/paketnoa
SELECT-OPTIONS: spaletb FOR zzllog-paletb. "/paketnob
SELECTION-SCREEN SKIP 1.
*/ paketle ilgili bilgiler
SELECT-OPTIONS: sdispo FOR marc-dispo.
SELECT-OPTIONS: smatnr FOR zzllog-matnr.
SELECT-OPTIONS: sharkod FOR zzllog-harkod. "/logtaki işlem kodu
*SELECT-OPTIONS: stelf1 FOR zzllog-telf1.
SELECT-OPTIONS: starih FOR zzllog-tarih.
SELECT-OPTIONS: susr FOR zzllog-usr.
SELECT-OPTIONS: saufnr FOR zzllog-aufnr.
SELECTION-SCREEN SKIP 1.
*/ depo adres bilgileri
SELECT-OPTIONS: sflgnum FOR zzllog-flgnum. "/kaynak depo no
SELECT-OPTIONS: sflgtyp FOR zzllog-flgtyp. "/kaynak depo tipi
SELECT-OPTIONS: sflgpla FOR zzllog-flgpla. "/kaynak depo numarası
SELECT-OPTIONS: stlgnum FOR zzllog-tlgnum. "/hedef depo no
SELECT-OPTIONS: stlgtyp FOR zzllog-tlgtyp. "/hedef depo tipi
SELECT-OPTIONS: stlgpla FOR zzllog-tlgpla. "/hedef depo numarası
SELECTION-SCREEN SKIP 1.
*/ Çıktıda gelecek kolonların seçimi
SELECTION-SCREEN BEGIN OF BLOCK uc WITH FRAME TITLE text-001.
PARAMETERS : tarih AS CHECKBOX DEFAULT 'X',
saat AS CHECKBOX DEFAULT 'X',
usr AS CHECKBOX DEFAULT 'X',
palet AS CHECKBOX DEFAULT 'X',
paleta AS CHECKBOX DEFAULT 'X',
paletb AS CHECKBOX DEFAULT 'X',
harkod AS CHECKBOX DEFAULT 'X', "/ hareket kodu
matnr AS CHECKBOX DEFAULT 'X',
menge AS CHECKBOX DEFAULT 'X',
sebep AS CHECKBOX DEFAULT 'X', "/ sipariş/red
aufnr AS CHECKBOX DEFAULT 'X', "/sm.siparişi
ref2 AS CHECKBOX DEFAULT 'X',
paufnr AS CHECKBOX DEFAULT 'X', "/enj.siparişi
flgnum AS CHECKBOX DEFAULT 'X', "/from depo...
flgtyp AS CHECKBOX DEFAULT 'X',
flgpla AS CHECKBOX DEFAULT 'X',
tlgnum AS CHECKBOX DEFAULT 'X', "/ to depo...
tlgtyp AS CHECKBOX DEFAULT 'X',
tlgpla AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK uc.
*
TOP-OF-PAGE.
PERFORM baslik.
*
START-OF-SELECTION.
PERFORM prepare_itab.
PERFORM write_itab.
**
FORM prepare_itab.
*/ Paketle ilgili tüm geçmiş hareketler log tablosundan okunur
SELECT * INTO CORRESPONDING FIELDS OF TABLE itab
FROM zzllog WHERE palet IN spalet
AND paleta IN spaleta
AND paletb IN spaletb
AND matnr IN smatnr
AND harkod IN sharkod
AND tarih IN starih
AND flgnum IN sflgnum
AND flgtyp IN sflgtyp
AND flgpla IN sflgpla
AND tlgnum IN stlgnum
AND tlgtyp IN stlgtyp
AND tlgpla IN stlgpla
AND aufnr IN saufnr
AND usr IN susr.
IF sdispo[] IS NOT INITIAL.
LOOP AT itab.
SELECT SINGLE dispo INTO marc-dispo
FROM marc WHERE matnr = itab-matnr
AND werks = '3001'
AND dispo IN sdispo.
IF sy-subrc <> 0.
DELETE itab.
ENDIF.
ENDLOOP.
ENDIF.
DESCRIBE TABLE itab LINES adet.
*/ tüm hareketler tarih ve saate göre sıralanır
SORT itab BY tarih saat.
WRITE:/ 'ADET: ', adet.
ULINE.
ENDFORM.
所以,我想要做的是:如果sharkod
包含D
,则应检查zzldet
matnr
。
答案 0 :(得分:3)
不使用MODIFY
,而是使用字段符号:
DATA: lt_materials TYPE TABLE OF zzllog.
FIELD-SYMBOLS: <ls_line> TYPE zzllog.
* other code with strange comments :-)
LOOP AT lt_materials ASSIGNING <ls_line> WHERE matnr IS INITIAL.
SELECT SINGLE MATNR
FROM zlldet
INTO <ls_line>-matnr
WHERE palet = <ls_line>-palet.
ENDLOOP.
这只是正确语法的一个示例。在真正的程序中执行此操作并不是一个好主意,因为您有可能在数千个请求中访问数据库,并且可能会获得相当多的性能。最好将没有PALET
的{{1}}数字预先选择到单独的表中,然后使用MATNR
在单个查询中读取所有FOR ALL ENTRIES IN
。< / p>
编辑:添加了类型名称。顺便说一句,你宣布内部表格的方式有点过时......
答案 1 :(得分:1)
当您想要使用修改而不是字段符号时,这将是正确的解决方案:
LOOP AT itab.
SELECT SINGLE matnr INTO itab-matnr
FROM zlldet WHERE palet = itab-palet.
MODIFY itab.
ENDLOOP.
您将itab声明为带有标题行的表(顺便说一下,它已被弃用)。这意味着你有一个表itab和一个结构itab。在哪种情况下使用哪种情况取决于上下文,并且一些命令(如LOOP AT和MODIFY)同时使用两者。这将是具有工作区而不是标题行的代码。它更具可读性。
DATA itab TYPE TABLE OF [something].
DATA wa TYPE [something].
LOOP AT itab INTO wa. " copies each line into wa
SELECT SINGLE matnr INTO wa-matnr
FROM zlldet WHERE palet = itab-palet.
MODIFY itab FROM wa. " writes the changed line back to the table
ENDLOOP.
您还可以使用带有字段符号vwegert的解决方案。字段符号是指向表行的指针。对字段符号的任何更改都将自动写回到表中,因此在这种情况下您不需要修改。它也更快,特别是对于非常宽的表,因为不需要复制数据。
答案 2 :(得分:1)
每次循环内部也可以避免使用select语句。相反,您可以尝试使用Range表,并在循环之前仅使用select语句一次,因为它可以提高性能。
定义用户定义的结构并声明变量
types: begin of ty_p_m,
palet type zlldet-palet,
matnr type zlldet-matnr,
end of ty_p_m.
data: r_palet type range table of zlldet-palet,
r_line_palet like line of r_palet,
i_p_matnr type standard table of ty_p_m,
wa_p_m type ty_p_m.
field-symbols: <fs> type wa_p_m.
在下一步中填写将在选择查询中使用的范围表。
r_line_palet-sign = 'I'.
r_line_palet-option = 'EQ'.
loop at itab into wa.
r_line_palet-low = wa-palet.
append r_line_palet to r_palet.
endloop.
现在通过引用范围表来使用select语句,并在声明的内部表中获取数据。
select palet matnr from zlldet into i_p_matnr
where palet in r_palet.
现在循环声明的内部表。在里面读你的内部表 使用字段符号而不是修改语句,使用传入值并在其中修改表。
loop at i_p_matnr into wa_p_matnr.
read table itab with key palet = wa_p_matnr-palet assigning <fs>.
if sy-subrc = 0.
<fs>-matnr = wa_p_matnr-matnr.
endif.
clear wa_p_matnr.
endloop.