Skip to content

销售交货开票报表

报表主要用于跟踪销售订单后续交货和开票情况,核心是这三者的关联查询。

主程序
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
*&---------------------------------------------------------------------*
*& Report ZSDREPORT
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& 作者 Nefevcore
*& 描述 营销报表
*&---------------------------------------------------------------------*
REPORT zsdreport.

INCLUDE zsdreport_top.
INCLUDE zsdreport_sel.
INCLUDE zsdreport_frm.
INCLUDE zsdreport_alv.

START-OF-SELECTION.
  PERFORM frm_main.
全局参数
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
*&---------------------------------------------------------------------*
*& 包含               ZSDREPORT_TOP
*&---------------------------------------------------------------------*
" 数量和金额
TYPES ty_amount_p16_4 TYPE p LENGTH 16 DECIMALS 4.
TYPES ty_quan_p16_3 TYPE p LENGTH 16 DECIMALS 3.

" 销售
TYPES:
  BEGIN OF ty_va,
    vbeln  TYPE vbap-vbeln, " 销售订单号
    posnr  TYPE vbap-posnr, " 销售订单行号
    vbtyp  TYPE vbak-vbtyp, " 凭证类型
    auart  TYPE vbak-auart, " 销售订单类型
    vkorg  TYPE vbak-vkorg, " 销售组织
    vtweg  TYPE vbak-vtweg, " 分销渠道
    spart  TYPE vbak-spart, " 产品组
    kwmeng TYPE vbap-kwmeng, " 订单数量
    zmeng  TYPE vbap-zmeng, " 目标数量
    meins  TYPE vbap-meins, " 单位
    kzwi1  TYPE vbap-kzwi1, " 销售小计
    waerk  TYPE vbap-waerk, " 货币
    knumv  TYPE vbak-knumv, " 条件号
    kbetr  TYPE prcd_elements-kbetr, " 定价值
    bstkd  TYPE vbkd-bstkd, " 客户参考
  END OF ty_va.

" 交货
TYPES:
  BEGIN OF ty_vl,
    vbeln     TYPE lips-vbeln, " 交货单号
    posnr     TYPE lips-posnr, " 行项目号
    vbtyp     TYPE likp-vbtyp, " 销售和分销凭证类别
    lfart     TYPE likp-lfart, " 交货类型
    wadat_ist TYPE likp-wadat_ist, " 实际交货日期
    uecha     TYPE lips-uecha, " 上层项目批
    wbsta     TYPE lips-wbsta, " 交货状态
    lfimg     TYPE lips-lfimg, " 发货数量
    meins     TYPE lips-meins, " 单位
  END OF ty_vl.

" 发票
TYPES:
  BEGIN OF ty_vf,
    vbeln TYPE vbrp-vbeln, " 发票
    posnr TYPE vbrp-posnr, " 发票行
    vbtyp TYPE vbrk-vbtyp, " 发票凭证类别
    fkdat TYPE vbrk-fkdat, " 开票日期
    fkimg TYPE vbrp-fkimg, " 开票数量
    meins TYPE vbrp-meins, " 单位
    kzwi1 TYPE vbrp-kzwi1, " 发票小计
    waerk TYPE vbrp-waerk, " 货币
  END OF ty_vf.

" 通用
TYPES:
  BEGIN OF ty_general,
    kunnr      TYPE likp-kunnr, " 送达方编码
    kunnr_text TYPE string, " 送达方名称
    kunag      TYPE likp-kunag, " 签署方编码
    kunag_text TYPE string, " 签署方名称
    kunre      TYPE kna1-kunnr, " 开票方编码
    kunre_text TYPE string, " 开票方名称
    kunrg      TYPE kna1-kunnr, " 付款方编码
    kunrg_text TYPE string, " 付款方名称
    matnr      TYPE mara-matnr, " 物料号
    maktx      TYPE makt-maktx,  " 物料描述
    werks      TYPE t001w-werks, " 工厂
    lgort      TYPE t001l-lgort, " 库位
    charg      TYPE mch1-charg, " SAP批次号
    pspnr      TYPE prps-pspnr, " WBS
    posid      TYPE prps-posid, " WBS
  END OF ty_general.

" ALV报表
TYPES:
  BEGIN OF ty_data.
    INCLUDE TYPE ty_va AS va RENAMING WITH SUFFIX _va.
    INCLUDE TYPE ty_vl AS vl RENAMING WITH SUFFIX _vl.
    INCLUDE TYPE ty_vf AS vf RENAMING WITH SUFFIX _vf.
    INCLUDE TYPE ty_general.
TYPES:
    zfactor   TYPE i, " 正负因子
    ztax_rate TYPE ty_amount_p16_4, " 税率

    zamount1  TYPE ty_amount_p16_4, " 销售单价
    zquan2    TYPE ty_quan_p16_3, " 销售数量
    zamount3  TYPE ty_amount_p16_4, " 销售含税总金额

    zamount4  TYPE ty_amount_p16_4, " 发货单价(取销售单价)
    zquan5    TYPE ty_quan_p16_3, " 交货数量
    zamount6  TYPE ty_amount_p16_4, " 发货含税总金额
    zquan7    TYPE ty_quan_p16_3, " 未交货数量
    zamount8  TYPE ty_amount_p16_4, " 未发货含税总金额

    zamount9  TYPE ty_amount_p16_4, " 开票单价
    zquan10   TYPE ty_quan_p16_3, " 开票数量
    zamount11 TYPE ty_amount_p16_4, " 开票含税总金额
    zquan12   TYPE ty_quan_p16_3, " 未开票数量
    zamount13 TYPE ty_amount_p16_4, " 未开票含税总金额

    zsel      TYPE xfeld,
    mtype     TYPE bapi_mtype,
    msg       TYPE bapi_msg,
    t_scol    TYPE lvc_t_scol,
    t_styl    TYPE lvc_t_styl,
  END OF ty_data.
TYPES tt_data TYPE STANDARD TABLE OF ty_data.
DATA gt_data TYPE tt_data.

" 查询优化
" 按正常流程,需要先查询销售或交货,最后到发票
" 如果用户仅在筛选界面输入发票,等同全量查询
" 这样耗时太长,因此可以根据选择界面输入,预先查询
DATA:
  BEGIN OF gs_preload,
    va TYPE xfeld,
    vl TYPE xfeld,
    vf TYPE xfeld,
  END OF gs_preload.

" 键值
TYPES:
  BEGIN OF ty_sdkey,
    vbeln TYPE vbeln,
    posnr TYPE posnr,
  END OF ty_sdkey.
TYPES tt_sdkey TYPE STANDARD TABLE OF ty_sdkey.
DATA gt_sdkey TYPE tt_sdkey.

" 优化,程序写完后,多次出现过滤冲销发票的代码
TYPES:
  BEGIN OF ty_sfakn.
    INCLUDE TYPE ty_sdkey AS va RENAMING WITH SUFFIX _va.
    INCLUDE TYPE ty_sdkey AS vl RENAMING WITH SUFFIX _vl.
    INCLUDE TYPE ty_sdkey AS vf RENAMING WITH SUFFIX _vf.
TYPES:
    sfakn TYPE vbrk-sfakn,
  END OF ty_sfakn.
TYPES tt_sfakn TYPE STANDARD TABLE OF ty_sfakn.
选择屏幕
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
*&---------------------------------------------------------------------*
*& 包含               ZSDREPORT_SEL
*&---------------------------------------------------------------------*
TABLES vbak.
TABLES vbap.
TABLES vbrk.
TABLES likp.
TABLES prps.

PARAMETERS cb1 AS CHECKBOX DEFAULT abap_true.
PARAMETERS cb2 AS CHECKBOX DEFAULT abap_true.

SELECTION-SCREEN ULINE.

" 选择条件
SELECTION-SCREEN BEGIN OF BLOCK b900 WITH FRAME TITLE b900.
  SELECT-OPTIONS s_matnr FOR vbap-matnr.
  SELECT-OPTIONS s_werks FOR vbap-werks.
  SELECT-OPTIONS s_lgort FOR vbap-lgort.
  SELECT-OPTIONS s_charg FOR vbap-charg.
*  SELECT-OPTIONS s_wbs FOR vbap-ps_psp_pnr.
  SELECT-OPTIONS s_wbs FOR prps-posid. " 用外码才能模糊查询
  SELECT-OPTIONS s_vkorg FOR vbak-vkorg.
  SELECT-OPTIONS s_vtweg FOR vbak-vtweg.
  SELECT-OPTIONS s_spart FOR vbak-spart.
  SELECT-OPTIONS s_kunnr FOR vbak-kunnr.
SELECTION-SCREEN END OF BLOCK b900.

" 销售信息
SELECTION-SCREEN BEGIN OF BLOCK b910 WITH FRAME TITLE b910.
  SELECT-OPTIONS s_vbnva FOR vbak-vbeln MODIF ID m10.
  SELECT-OPTIONS s_vbtva FOR vbak-vbtyp MODIF ID m10.
  SELECT-OPTIONS s_auart FOR vbak-auart MODIF ID m10.
SELECTION-SCREEN END OF BLOCK b910.

" 交货信息
SELECTION-SCREEN BEGIN OF BLOCK b920 WITH FRAME TITLE b920.
  SELECT-OPTIONS s_vbnvl FOR likp-vbeln MODIF ID m20.
  SELECT-OPTIONS s_vbtvl FOR likp-vbtyp MODIF ID m20.
  SELECT-OPTIONS s_lfart FOR likp-lfart MODIF ID m20.
  SELECT-OPTIONS s_wadat FOR likp-wadat_ist MODIF ID m20.
SELECTION-SCREEN END OF BLOCK b920.

" 发票信息
SELECTION-SCREEN BEGIN OF BLOCK b930 WITH FRAME TITLE b930.
  SELECT-OPTIONS s_vbnvf FOR vbrk-vbeln MODIF ID m30.
  SELECT-OPTIONS s_vbtvf FOR vbrk-vbtyp MODIF ID m30.
  SELECT-OPTIONS s_fkdat FOR vbrk-fkdat MODIF ID m30.
SELECTION-SCREEN END OF BLOCK b930.

*&---------------------------------------------------------------------*
*& INITIALIZATION
*&---------------------------------------------------------------------*
INITIALIZATION.
  PERFORM frm_sel_scr_init.

*&---------------------------------------------------------------------*
*& PBO
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.
  PERFORM frm_sel_scr_pbo.

*&---------------------------------------------------------------------*
*& PAI
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN.
  PERFORM frm_sel_scr_pai.

*&---------------------------------------------------------------------*
*& Form frm_sel_scr_init
*&---------------------------------------------------------------------*
*& 屏幕初始化
*&---------------------------------------------------------------------*
FORM frm_sel_scr_init .

  %_cb1_%_app_%-text = '交货清单'.
  %_cb2_%_app_%-text = '服务开票清单'.

  b900 = '选择条件'.
  %_s_matnr_%_app_%-text = '物料'.
  %_s_werks_%_app_%-text = '工厂'.
  %_s_lgort_%_app_%-text = '库存地点'.
  %_s_charg_%_app_%-text = '批次'.
  %_s_wbs_%_app_%-text = 'WBS'.
  %_s_vkorg_%_app_%-text = '销售组织'.
  %_s_vtweg_%_app_%-text = '分销渠道'.
  %_s_spart_%_app_%-text = '产品组'.
  %_s_kunnr_%_app_%-text = '售达方'.

  b910 = '销售信息'.
  %_s_vbnva_%_app_%-text = '销售订单'.
  %_s_vbtva_%_app_%-text = '销售凭证类别'.
  %_s_auart_%_app_%-text = '销售凭证类型'.

  b920 = '交货信息'.
  %_s_vbnvl_%_app_%-text = '交货订单'.
  %_s_vbtvl_%_app_%-text = '交货凭证类别'.
  %_s_lfart_%_app_%-text = '交货类型'.
  %_s_wadat_%_app_%-text = '交货日期'.

  b930 = '发票信息'.
  %_s_vbnvf_%_app_%-text = '发票凭证'.
  %_s_vbtvf_%_app_%-text = '发票凭证类别'.
  %_s_fkdat_%_app_%-text = '开票日期'.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_sel_scr_pbo
*&---------------------------------------------------------------------*
*& 屏幕PBO
*&---------------------------------------------------------------------*
FORM frm_sel_scr_pbo .

  " 关闭全部分组项目,未分组会展示
  LOOP AT SCREEN.
    IF screen-group1 IS NOT INITIAL.
      screen-input = '0'.
      screen-invisible = '1'.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.

  " 显示分组
  DEFINE _active_grp.
    LOOP AT SCREEN.
      IF screen-group1 = &1.
        screen-input = '1'.
        screen-invisible = '0'.
        MODIFY SCREEN.
      ENDIF.
    ENDLOOP.
  END-OF-DEFINITION.

  " 隐藏分组
  DEFINE _inactive_grp.
    LOOP AT SCREEN.
      IF screen-group1 = &1.
        screen-input = '0'.
        screen-invisible = '1'.
        MODIFY SCREEN.
      ENDIF.
    ENDLOOP.
  END-OF-DEFINITION.

  SET TITLEBAR 'TITLE' WITH '营销报表'.
  _active_grp 'M10'. " 销售信息
  _active_grp 'M20'. " 交货信息
  _active_grp 'M30'. " 发票信息

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_sel_scr_pai
*&---------------------------------------------------------------------*
*& 屏幕PAI
*&---------------------------------------------------------------------*
FORM frm_sel_scr_pai .

ENDFORM.
子例程
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
*&---------------------------------------------------------------------*
*& 包含               ZSDREPORT_FRM
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form frm_main
*&---------------------------------------------------------------------*
*& 程序入口
*&---------------------------------------------------------------------*
FORM frm_main .

  PERFORM frm_get_auth.
  PERFORM frm_get_data.
  PERFORM frm_display TABLES gt_data.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_auth
*&---------------------------------------------------------------------*
*& 权限相关
*&---------------------------------------------------------------------*
FORM frm_get_auth .

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data
*&---------------------------------------------------------------------*
*& 取值相关
*&---------------------------------------------------------------------*
FORM frm_get_data .

  " 销售交货查询,以交货单为中心,查询对应销售凭证和开票凭证
  IF cb1 = abap_true.
    PERFORM frm_get_data_vl.
  ENDIF.
  " 无交货(服务/借贷项等)发票查询,以销售订单为中心,查询对应发票
  IF cb2 = abap_true.
    PERFORM frm_get_data_non_vl.
  ENDIF.

  CHECK gt_data IS NOT INITIAL.

  SORT gt_data BY vbeln_va posnr_va
                  vbeln_vl posnr_vl
                  vbeln_vf posnr_vf.

  DELETE ADJACENT DUPLICATES FROM gt_data COMPARING vbeln_va posnr_va
                                                    vbeln_vl posnr_vl
                                                    vbeln_vf posnr_vf.

  PERFORM frm_fetch_va.
  PERFORM frm_fetch_vl.
  PERFORM frm_fetch_vf.
  PERFORM frm_fetch_vbkd.
  PERFORM frm_fetch_vbpa.
  PERFORM frm_fetch_amount.
  PERFORM frm_fetch_text.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_vl_intersection
*&---------------------------------------------------------------------*
*& 取交集
*&---------------------------------------------------------------------*
FORM frm_intersection
  TABLES et_result TYPE tt_sdkey
  USING VALUE(it_sdkey1) TYPE tt_sdkey
        VALUE(it_sdkey2) TYPE tt_sdkey.

  CLEAR et_result[].

  CHECK it_sdkey1[] IS NOT INITIAL.
  CHECK it_sdkey2[] IS NOT INITIAL.

  DATA ls_sdkey TYPE ty_sdkey.

  IF lines( it_sdkey1 ) < lines( it_sdkey2 ).
    SORT it_sdkey2 BY vbeln posnr.
    LOOP AT it_sdkey1 INTO ls_sdkey.
      READ TABLE it_sdkey2 TRANSPORTING NO FIELDS WITH KEY
      vbeln = ls_sdkey-vbeln
      posnr = ls_sdkey-posnr
      BINARY SEARCH.
      IF sy-subrc = 0.
        INSERT ls_sdkey INTO TABLE et_result.
      ENDIF.
    ENDLOOP.
  ELSE.
    SORT it_sdkey1 BY vbeln posnr.
    LOOP AT it_sdkey2 INTO ls_sdkey.
      READ TABLE it_sdkey1 TRANSPORTING NO FIELDS WITH KEY
      vbeln = ls_sdkey-vbeln
      posnr = ls_sdkey-posnr
      BINARY SEARCH.
      IF sy-subrc = 0.
        INSERT ls_sdkey INTO TABLE et_result.
      ENDIF.
    ENDLOOP.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_filter_cancel_billing
*&---------------------------------------------------------------------*
*& 排除冲销和被冲销发票
*&---------------------------------------------------------------------*
FORM frm_filter_cancel_billing CHANGING ct_vf TYPE tt_sfakn.

  CHECK ct_vf[] IS NOT INITIAL.

  DATA(lt_cancel) = ct_vf[].
  SORT lt_cancel BY sfakn.
  LOOP AT ct_vf REFERENCE INTO DATA(lr_vf) WHERE sfakn IS INITIAL.
    READ TABLE lt_cancel INTO DATA(ls_cancel) WITH KEY sfakn = lr_vf->vbeln_vf BINARY SEARCH.
    IF sy-subrc = 0.
      lr_vf->sfakn = ls_cancel-vbeln_vf.
    ENDIF.
  ENDLOOP.
  CLEAR lt_cancel.
  DELETE ct_vf WHERE sfakn IS NOT INITIAL.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data_vl
*&---------------------------------------------------------------------*
*& 销售交货查询,以交货单为中心,查询对应销售凭证和开票凭证
*&---------------------------------------------------------------------*
FORM frm_get_data_vl .

  CLEAR gs_preload.
  CLEAR gt_sdkey.

  PERFORM frm_preload_vl_from_vl.
  PERFORM frm_preload_vl_from_va.
  PERFORM frm_preload_vl_from_vf.

  IF gs_preload IS NOT INITIAL.
    " 预查询
    IF gt_sdkey IS NOT INITIAL.
      SELECT
        vbfa~vbelv AS vbeln_va,
        vbfa~posnv AS posnr_va,
        vbfa~vbeln AS vbeln_vl,
        vbfa~posnn AS posnr_vl
        FROM vbfa
        JOIN vbak ON vbfa~vbelv = vbak~vbeln
        JOIN likp ON vbfa~vbeln = likp~vbeln
        FOR ALL ENTRIES IN @gt_sdkey
        WHERE vbfa~vbeln = @gt_sdkey-vbeln
          AND vbfa~posnn = @gt_sdkey-posnr
        INTO TABLE @DATA(lt_vlva).
    ENDIF.
  ELSE.
    " 全量查询
    SELECT
      vbfa~vbelv AS vbeln_va,
      vbfa~posnv AS posnr_va,
      vbfa~vbeln AS vbeln_vl,
      vbfa~posnn AS posnr_vl
      FROM vbfa
      JOIN vbak ON vbfa~vbelv = vbak~vbeln
      JOIN likp ON vbfa~vbeln = likp~vbeln
      INTO TABLE @lt_vlva.
  ENDIF.

  CHECK lt_vlva IS NOT INITIAL.

  " 询报价/合同->销售,需要过滤这部分
  SELECT
    vbfa~vbelv AS vbeln_other,
    vbfa~posnv AS posnr_other,
    vbfa~vbeln AS vbeln_va,
    vbfa~posnn AS posnr_va
    FROM vbfa
    JOIN vbak AS other ON vbfa~vbelv = other~vbeln
    JOIN vbak AS va ON vbfa~vbeln = va~vbeln
    FOR ALL ENTRIES IN @lt_vlva
    WHERE vbfa~vbelv = @lt_vlva-vbeln_va
      AND vbfa~posnv = @lt_vlva-posnr_va
    INTO TABLE @DATA(lt_otherva).

  " 交货-发票
  IF lt_vlva IS NOT INITIAL.
    DATA lt_vlvf TYPE tt_sfakn.
    SELECT
      vbfa~vbelv AS vbeln_vl,
      vbfa~posnv AS posnr_vl,
      vbfa~vbeln AS vbeln_vf,
      vbfa~posnn AS posnr_vf,
      vbrk~sfakn
      FROM vbfa
      JOIN likp ON vbfa~vbelv = likp~vbeln
      JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
      FOR ALL ENTRIES IN @lt_vlva
      WHERE vbfa~vbelv = @lt_vlva-vbeln_vl
        AND vbfa~posnv = @lt_vlva-posnr_vl
      INTO CORRESPONDING FIELDS OF TABLE @lt_vlvf.
    PERFORM frm_filter_cancel_billing CHANGING lt_vlvf. " 排除冲销和被冲销发票
  ENDIF.

  " 销售->发票
  " 对于退货交货,交货单后续无发票,需要根据销售订单查找
  DATA lt_vavf TYPE tt_sfakn.
  SELECT
    vbfa~vbelv AS vbeln_va,
    vbfa~posnv AS posnr_va,
    vbfa~vbeln AS vbeln_vf,
    vbfa~posnn AS posnr_vf,
    vbrk~sfakn " 冲销凭证
    FROM vbfa
    JOIN vbak ON vbfa~vbelv = vbak~vbeln
    JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
    FOR ALL ENTRIES IN @lt_vlva
    WHERE vbfa~vbelv = @lt_vlva-vbeln_va
      AND vbfa~posnv = @lt_vlva-posnr_va
    INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
  PERFORM frm_filter_cancel_billing CHANGING lt_vavf. " 排除冲销和被冲销发票

  SORT lt_otherva BY vbeln_other posnr_other.
  SORT lt_vlvf BY vbeln_vl posnr_vl.
  SORT lt_vavf BY vbeln_va posnr_va.

  LOOP AT lt_vlva INTO DATA(ls_vlva).
    READ TABLE lt_otherva TRANSPORTING NO FIELDS WITH KEY
    vbeln_other = ls_vlva-vbeln_va
    posnr_other = ls_vlva-posnr_va
    BINARY SEARCH.
    IF sy-subrc = 0.
      CONTINUE.
    ENDIF.

    DATA ls_data TYPE ty_data.
    CLEAR ls_data.
    ls_data-vbeln_va = ls_vlva-vbeln_va.
    ls_data-posnr_va = ls_vlva-posnr_va.
    ls_data-vbeln_vl = ls_vlva-vbeln_vl.
    ls_data-posnr_vl = ls_vlva-posnr_vl.

    READ TABLE lt_vlvf INTO DATA(ls_vlvf) WITH KEY
    vbeln_vl = ls_data-vbeln_vl
    posnr_vl = ls_data-posnr_vl
    BINARY SEARCH.
    IF sy-subrc = 0.
      ls_data-vbeln_vf = ls_vlvf-vbeln_vf.
      ls_data-posnr_vf = ls_vlvf-posnr_vf.
    ELSE.
      READ TABLE lt_vavf INTO DATA(ls_vavf) WITH KEY
      vbeln_va = ls_data-vbeln_va
      posnr_va = ls_data-posnr_va
      BINARY SEARCH.
      IF sy-subrc = 0.
        ls_data-vbeln_vf = ls_vavf-vbeln_vf.
        ls_data-posnr_vf = ls_vavf-posnr_vf.
      ENDIF.
    ENDIF.

    INSERT ls_data INTO TABLE gt_data.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_vl_from_vl
*&---------------------------------------------------------------------*
*& 直接按交货单查询
*&---------------------------------------------------------------------*
FORM frm_preload_vl_from_vl .

  IF s_vbnvl[] IS NOT INITIAL
  OR s_vbtvl[] IS NOT INITIAL
  OR s_lfart[] IS NOT INITIAL
  OR s_wadat[] IS NOT INITIAL
  OR s_matnr[] IS NOT INITIAL
  OR s_werks[] IS NOT INITIAL
  OR s_lgort[] IS NOT INITIAL
  OR s_charg[] IS NOT INITIAL
  OR s_wbs[]   IS NOT INITIAL
  OR s_kunnr[] IS NOT INITIAL
    .

    SELECT
      lips~vbeln,
      lips~posnr
      FROM likp
      JOIN lips ON likp~vbeln = lips~vbeln
      LEFT JOIN prps ON lips~ps_psp_pnr = prps~pspnr
      WHERE lips~vbeln IN @s_vbnvl
        AND likp~vbtyp IN @s_vbtvl
        AND likp~lfart IN @s_lfart
        AND likp~wadat IN @s_wadat
        AND likp~kunnr IN @s_kunnr
        AND lips~matnr IN @s_matnr
        AND lips~werks IN @s_werks
        AND lips~lgort IN @s_lgort
        AND lips~charg IN @s_charg
        AND prps~posid IN @s_wbs
      INTO TABLE @gt_sdkey.

    gs_preload-vl = abap_true. " 表示已执行预加载

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_vl_from_va
*&---------------------------------------------------------------------*
*& 根据销售订单查找交货单
*&---------------------------------------------------------------------*
FORM frm_preload_vl_from_va .

  IF s_vbnva[] IS NOT INITIAL
  OR s_vbtva[] IS NOT INITIAL
  OR s_auart[] IS NOT INITIAL
  .

    DATA lt_sdkey TYPE tt_sdkey.
    SELECT
      vbfa~vbeln AS vbeln,
      vbfa~posnn AS posnr
      FROM vbfa
      JOIN vbak ON vbfa~vbelv = vbak~vbeln
      JOIN likp ON vbfa~vbeln = likp~vbeln
      WHERE vbak~vbeln IN @s_vbnva
        AND vbak~vbtyp IN @s_vbtva
        AND vbak~auart IN @s_auart
      INTO TABLE @lt_sdkey.

    " 将当前查询结果和之前的查询结果取交集
    IF gs_preload IS INITIAL.
      gt_sdkey = lt_sdkey.
    ELSE.
      PERFORM frm_intersection TABLES gt_sdkey USING gt_sdkey lt_sdkey.
    ENDIF.
    gs_preload-va = abap_true. " 表示已执行预加载

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_vl_from_vf
*&---------------------------------------------------------------------*
*& 根据发票查找交货单
*&---------------------------------------------------------------------*
FORM frm_preload_vl_from_vf .

  IF s_vbnvf[] IS NOT INITIAL
  OR s_vbtvf[] IS NOT INITIAL
  OR s_fkdat[] IS NOT INITIAL
  .

    DATA lt_sdkey TYPE tt_sdkey.

    " 对于发票,先查找发票对应销售单,再根据销售单查找交货单
    " 这样一个流程,可以兼容退货的情况(对于退货,交货订单后续是物料凭证)
    DATA lt_vavf TYPE tt_sfakn.
    SELECT
      vbfa~vbelv AS vbeln_va,
      vbfa~posnv AS posnr_va,
      vbfa~vbeln AS vbeln_vf,
      vbfa~posnn AS posnr_vf,
      vbrk~sfakn " 冲销凭证
      FROM vbfa
      JOIN vbak ON vbfa~vbelv = vbak~vbeln
      JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
      WHERE vbrk~vbeln IN @s_vbnvf
        AND vbrk~vbtyp IN @s_vbtvf
        AND vbrk~fkdat IN @s_fkdat
      INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
    PERFORM frm_filter_cancel_billing CHANGING lt_vavf. " 排除冲销和被冲销发票

    IF lt_vavf IS NOT INITIAL.
      SELECT
        vbfa~vbeln AS vbeln,
        vbfa~posnn AS posnr
        FROM vbfa
        JOIN vbak ON vbfa~vbelv = vbak~vbeln
        JOIN likp ON vbfa~vbeln = likp~vbeln
        FOR ALL ENTRIES IN @lt_vavf
        WHERE vbfa~vbelv = @lt_vavf-vbeln_va
          AND vbfa~posnv = @lt_vavf-posnr_va
        INTO TABLE @lt_sdkey.
    ENDIF.

    " 将当前查询结果和之前的查询结果取交集
    IF gs_preload IS INITIAL.
      gt_sdkey = lt_sdkey.
    ELSE.
      PERFORM frm_intersection TABLES gt_sdkey USING gt_sdkey lt_sdkey.
    ENDIF.
    gs_preload-vf = abap_true. " 表示有执行优化
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data_non_vl
*&---------------------------------------------------------------------*
*& 无交货(服务/借贷项等)发票查询,以销售订单为中心,查询对应发票
*&---------------------------------------------------------------------*
FORM frm_get_data_non_vl .

  CLEAR gs_preload.
  CLEAR gt_sdkey.

  PERFORM frm_preload_va_from_va.
  PERFORM frm_preload_va_from_vl.
  PERFORM frm_preload_va_from_vf.

  DATA lt_vavf TYPE tt_sfakn.

  IF gs_preload IS NOT INITIAL.
    " 预查询
    IF gt_sdkey IS NOT INITIAL.
      SELECT
        vbfa~vbelv AS vbeln_va,
        vbfa~posnv AS posnr_va,
        vbfa~vbeln AS vbeln_vf,
        vbfa~posnn AS posnr_vf,
        vbrk~sfakn " 冲销凭证
        FROM vbfa
        JOIN vbak ON vbfa~vbelv = vbak~vbeln
        JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
        FOR ALL ENTRIES IN @gt_sdkey
        WHERE vbfa~vbelv = @gt_sdkey-vbeln
          AND vbfa~posnv = @gt_sdkey-posnr
        INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
    ENDIF.
  ELSE.
    " 全量查询
    SELECT
      vbfa~vbelv AS vbeln_va,
      vbfa~posnv AS posnr_va,
      vbfa~vbeln AS vbeln_vf,
      vbfa~posnn AS posnr_vf,
      vbrk~sfakn " 冲销凭证
      FROM vbfa
      JOIN vbak ON vbfa~vbelv = vbak~vbeln
      JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
      INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
  ENDIF.
  PERFORM frm_filter_cancel_billing CHANGING lt_vavf. " 排除冲销和被冲销发票

  " 无交货判断
  IF lt_vavf IS NOT INITIAL.
    SELECT
      vbfa~vbelv AS vbeln_va,
      vbfa~posnv AS posnr_va,
      vbfa~vbeln AS vbeln_vl,
      vbfa~posnn AS posnr_vl
      FROM vbfa
      JOIN vbak ON vbfa~vbelv = vbak~vbeln
      JOIN likp ON vbfa~vbeln = likp~vbeln
      FOR ALL ENTRIES IN @lt_vavf
      WHERE vbfa~vbelv = @lt_vavf-vbeln_va
        AND vbfa~posnv = @lt_vavf-posnr_va
      INTO TABLE @DATA(lt_vavl).
  ENDIF.

  SORT lt_vavl BY vbeln_va posnr_va.

  LOOP AT lt_vavf INTO DATA(ls_vavf).
    READ TABLE lt_vavl TRANSPORTING NO FIELDS WITH KEY
    vbeln_va = ls_vavf-vbeln_va
    posnr_va = ls_vavf-posnr_va
    BINARY SEARCH.
    IF sy-subrc <> 0.
      INSERT CORRESPONDING #( ls_vavf ) INTO TABLE gt_data.
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_vl_from_vl
*&---------------------------------------------------------------------*
*& 直接按交货单查询
*&---------------------------------------------------------------------*
FORM frm_preload_va_from_va.

  IF s_vbnva[] IS NOT INITIAL
  OR s_vbtva[] IS NOT INITIAL
  OR s_auart[] IS NOT INITIAL
  OR s_matnr[] IS NOT INITIAL
  OR s_werks[] IS NOT INITIAL
  OR s_lgort[] IS NOT INITIAL
  OR s_charg[] IS NOT INITIAL
  OR s_wbs[]   IS NOT INITIAL
  OR s_vkorg[] IS NOT INITIAL
  OR s_vtweg[] IS NOT INITIAL
  OR s_spart[] IS NOT INITIAL
  OR s_kunnr[] IS NOT INITIAL
    .

    SELECT
      vbap~vbeln,
      vbap~posnr
      FROM vbak
      JOIN vbap ON vbak~vbeln = vbap~vbeln
      LEFT JOIN prps ON vbap~ps_psp_pnr = prps~pspnr
      WHERE vbak~vbeln IN @s_vbnva
        AND vbak~vbtyp IN @s_vbtva
        AND vbak~auart IN @s_auart
        AND vbak~vkorg IN @s_vkorg
        AND vbak~vtweg IN @s_vtweg
        AND vbak~kunnr IN @s_kunnr
        AND vbap~spart IN @s_spart
        AND vbap~matnr IN @s_matnr
        AND vbap~werks IN @s_werks
        AND vbap~lgort IN @s_lgort
        AND vbap~charg IN @s_charg
        AND prps~posid IN @s_wbs
      INTO TABLE @gt_sdkey.

    gs_preload-va = abap_true. " 表示已执行预加载

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_va_from_vl
*&---------------------------------------------------------------------*
*& 不存在这种情况,但假设屏幕有输入交货相关
*&---------------------------------------------------------------------*
FORM frm_preload_va_from_vl .

  IF s_vbnvl[] IS NOT INITIAL
  OR s_vbtvl[] IS NOT INITIAL
  OR s_lfart[] IS NOT INITIAL
  .

    CLEAR gt_sdkey.
    gs_preload-vl = abap_true. " 表示已执行预加载

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_preload_va_from_vf
*&---------------------------------------------------------------------*
*& 根据通过发票找销售订单
*&---------------------------------------------------------------------*
FORM frm_preload_va_from_vf.

  IF s_vbnvf[] IS NOT INITIAL
  OR s_vbtvf[] IS NOT INITIAL
  OR s_fkdat[] IS NOT INITIAL
  .

    DATA lt_vavf TYPE tt_sfakn.
    SELECT
      vbfa~vbelv AS vbeln_va,
      vbfa~posnv AS posnr_va,
      vbfa~vbeln AS vbeln_vf,
      vbfa~posnn AS posnr_vf,
      vbrk~sfakn " 冲销凭证
      FROM vbfa
      JOIN vbak ON vbfa~vbelv = vbak~vbeln
      JOIN vbrk ON vbfa~vbeln = vbrk~vbeln
      WHERE vbrk~vbeln IN @s_vbnvf
        AND vbrk~vbtyp IN @s_vbtvf
        AND vbrk~fkdat IN @s_fkdat
      INTO CORRESPONDING FIELDS OF TABLE @lt_vavf.
    PERFORM frm_filter_cancel_billing CHANGING lt_vavf." 排除冲销和被冲销发票

    " 无交货判断
    IF lt_vavf IS NOT INITIAL.
      SELECT
        vbfa~vbelv AS vbeln_va,
        vbfa~posnv AS posnr_va,
        vbfa~vbeln AS vbeln_vl,
        vbfa~posnn AS posnr_vl
        FROM vbfa
        JOIN vbak ON vbfa~vbelv = vbak~vbeln
        JOIN likp ON vbfa~vbeln = likp~vbeln
        FOR ALL ENTRIES IN @lt_vavf
        WHERE vbfa~vbeln = @lt_vavf-vbeln_va
          AND vbfa~posnn = @lt_vavf-posnr_va
        INTO TABLE @DATA(lt_vavl).
    ENDIF.

    SORT lt_vavl BY vbeln_va posnr_va.

    DATA lt_sdkey TYPE tt_sdkey.
    DATA ls_sdkey TYPE ty_sdkey.
    LOOP AT lt_vavf INTO DATA(ls_vavf).
      READ TABLE lt_vavl TRANSPORTING NO FIELDS WITH KEY
      vbeln_va = ls_vavf-vbeln_va
      posnr_va = ls_vavf-posnr_va
      BINARY SEARCH.
      IF sy-subrc <> 0.
        CLEAR ls_sdkey.
        ls_sdkey-vbeln = ls_vavf-vbeln_va.
        ls_sdkey-posnr = ls_vavf-posnr_va.
        INSERT ls_sdkey INTO TABLE lt_sdkey.
      ENDIF.
    ENDLOOP.

    " 将当前查询结果和之前的查询结果取交集
    IF gs_preload IS INITIAL.
      gt_sdkey = lt_sdkey.
    ELSE.
      PERFORM frm_intersection TABLES gt_sdkey USING gt_sdkey lt_sdkey.
    ENDIF.
    gs_preload-vf = abap_true. " 表示有执行优化

  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_va
*&---------------------------------------------------------------------*
*& 读取销售信息
*&---------------------------------------------------------------------*
FORM frm_fetch_va .
  CHECK gt_data IS NOT INITIAL.

  SELECT
    vbap~vbeln,
    vbap~posnr,
    vbak~vbtyp, " 凭证类型
    vbak~auart, " 销售订单类型
    vbak~vkorg, " 销售组织
    vbak~vtweg, " 分销渠道
    vbak~spart, " 产品组
    vbap~waerk, " 货币
    vbap~kzwi1, " 销售小计
    vbap~kwmeng, " 订单数量
    vbap~zmeng, " 目标数量
    vbak~knumv, " 条件号
    vbap~meins, " 单位
    vbap~matnr, " 物料
    vbap~werks, " 工厂
    vbap~lgort, " 库存地点
    prps~pspnr, " WBS
    prps~posid, " WBS
    vbap~charg " 批次
    FROM vbak
    JOIN vbap ON vbak~vbeln = vbap~vbeln
    LEFT JOIN prps ON vbap~ps_psp_pnr = prps~pspnr
    FOR ALL ENTRIES IN @gt_data
    WHERE vbak~vbeln = @gt_data-vbeln_va
    INTO TABLE @DATA(lt_va).
  SORT lt_va BY vbeln posnr.

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
    READ TABLE lt_va INTO DATA(ls_va) WITH KEY
    vbeln = lr_data->vbeln_va
    posnr = lr_data->posnr_va
    BINARY SEARCH.
    IF sy-subrc = 0.
      lr_data->va = CORRESPONDING #( ls_va ).
      lr_data->matnr = ls_va-matnr.
      lr_data->werks = ls_va-werks.
      lr_data->lgort = ls_va-lgort.
      lr_data->pspnr = ls_va-pspnr.
      lr_data->posid = ls_va-posid.
      lr_data->charg = ls_va-charg.
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_va
*&---------------------------------------------------------------------*
*& 读取交货单信息
*&---------------------------------------------------------------------*
FORM frm_fetch_vl .
  CHECK gt_data IS NOT INITIAL.

  SELECT
    lips~vbeln, " 交货订单
    lips~posnr, " 行项目
    likp~vbtyp, " 凭证类型
    likp~lfart, " 交货类型
    likp~wadat_ist, " 实际交货日期
    lips~uecha, " 上层行(判断行项目是否为拆分行)
    lips~wbsta, " 处理状态
    lips~lfimg, " 交货数量
    lips~meins, " 单位
    lips~matnr, " 物料
    lips~werks, " 工厂
    lips~lgort, " 库存地点
    prps~pspnr, " WBS
    prps~posid, " WBS
    lips~charg " 批次
    FROM likp
    JOIN lips ON likp~vbeln = lips~vbeln
    LEFT JOIN prps ON lips~ps_psp_pnr = prps~pspnr
    FOR ALL ENTRIES IN @gt_data
    WHERE likp~vbeln = @gt_data-vbeln_vl
    INTO TABLE @DATA(lt_vl).
  SORT lt_vl BY vbeln posnr.

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
    READ TABLE lt_vl INTO DATA(ls_vl) WITH KEY
    vbeln = lr_data->vbeln_vl
    posnr = lr_data->posnr_vl
    BINARY SEARCH.
    IF sy-subrc = 0.
      lr_data->vl = CORRESPONDING #( ls_vl ).
      lr_data->matnr = ls_vl-matnr.
      lr_data->werks = ls_vl-werks.
      lr_data->lgort = ls_vl-lgort.
      lr_data->pspnr = ls_vl-pspnr.
      lr_data->posid = ls_vl-posid.
      lr_data->charg = ls_vl-charg.
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_vf
*&---------------------------------------------------------------------*
*& 读取发票信息
*&---------------------------------------------------------------------*
FORM frm_fetch_vf .
  CHECK gt_data IS NOT INITIAL.

  SELECT
    vbrp~vbeln, " 发票
    vbrp~posnr, " 发票行
    vbrk~vbtyp, " 发票凭证类别
    vbrk~fkdat, " 开票日期
    vbrp~fkimg, " 开票数量
    vbrp~meins, " 单位
    vbrp~kzwi1, " 发票小计
    vbrp~waerk " 货币
    FROM vbrk
    JOIN vbrp ON vbrk~vbeln = vbrp~vbeln
    FOR ALL ENTRIES IN @gt_data
    WHERE vbrk~vbeln = @gt_data-vbeln_vf
    INTO TABLE @DATA(lt_vf).
  SORT lt_vf BY vbeln posnr.

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
    READ TABLE lt_vf INTO DATA(ls_vf) WITH KEY
    vbeln = lr_data->vbeln_vf
    posnr = lr_data->posnr_vf
    BINARY SEARCH.
    IF sy-subrc = 0.
      lr_data->vf = CORRESPONDING #( ls_vf ).
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_vbkd
*&---------------------------------------------------------------------*
*& 读取VBKD
*&---------------------------------------------------------------------*
FORM frm_fetch_vbkd .
  CHECK gt_data IS NOT INITIAL.

  SELECT
    vbeln,
    posnr,
    bstkd
    FROM vbkd
    FOR ALL ENTRIES IN @gt_data
    WHERE vbeln = @gt_data-vbeln_va
    INTO TABLE @DATA(lt_vbkd).
  SORT lt_vbkd BY vbeln posnr.

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
    READ TABLE lt_vbkd INTO DATA(ls_vbkd) WITH KEY
    vbeln = lr_data->vbeln_va
    BINARY SEARCH.
    IF sy-subrc = 0.
      lr_data->bstkd_va = ls_vbkd-bstkd.
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_vbpa
*&---------------------------------------------------------------------*
*& 销售业务货币
*&---------------------------------------------------------------------*
FORM frm_fetch_vbpa .
  CHECK gt_data IS NOT INITIAL.

  SELECT
    vbeln,
    parvw,
    kunnr
    FROM vbpa
    FOR ALL ENTRIES IN @gt_data
    WHERE vbeln = @gt_data-vbeln_va
      AND posnr = '' " 取抬头业务伙伴
    INTO TABLE @DATA(lt_vbpa).

  SORT lt_vbpa BY vbeln parvw.

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).

    " 重复代码
    DATA ls_vbpa LIKE LINE OF lt_vbpa.
    DEFINE _get_partner.
      CLEAR ls_vbpa.
      READ TABLE lt_vbpa INTO ls_vbpa WITH KEY
      vbeln = lr_data->vbeln_va
      parvw = &1
      BINARY SEARCH.
      IF sy-subrc = 0.
        &2 = ls_vbpa-kunnr.
      ENDIF.
    END-OF-DEFINITION.

    _get_partner 'AG' lr_data->kunag.
    _get_partner 'RE' lr_data->kunre.
    _get_partner 'RG' lr_data->kunrg.

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_amount
*&---------------------------------------------------------------------*
*& 数量与金额处理
*&---------------------------------------------------------------------*
FORM frm_fetch_amount .
  CHECK gt_data IS NOT INITIAL.

  SELECT
    knumv,
    kposn,
    stunr,
    zaehk,
    kschl,
    waers,
    kbetr,
    kpein
    FROM prcd_elements
    FOR ALL ENTRIES IN @gt_data
    WHERE knumv = @gt_data-knumv_va
      AND kinak = '' " 排除未激活的定价
    INTO TABLE @DATA(lt_prcd_elements).

  " 对于多个价格,取最新的
  SORT lt_prcd_elements BY knumv kposn kschl
                           zaehk DESCENDING .
  DELETE ADJACENT DUPLICATES FROM lt_prcd_elements COMPARING knumv kposn kschl.

  " 对于下面类型,数量金额按负数处理
  DATA lt_vbtyp_neg_opt TYPE RANGE OF vbtyp.
  lt_vbtyp_neg_opt = VALUE #( sign = 'I' option = 'EQ'
    ( low = 'H' ) " 退货
    ( low = 'T' ) " 订单的退货交货
    ( low = 'K' ) " 贷项凭证申请
    ( low = 'O' ) " 贷项凭证
  ).

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
    " 重复代码
    DATA ls_prcd_elements LIKE LINE OF lt_prcd_elements.
    DEFINE _get_prcd_elements.
      READ TABLE lt_prcd_elements INTO ls_prcd_elements WITH KEY
      knumv = lr_data->knumv_va
      kposn = lr_data->posnr_va
      kschl = &1
      BINARY SEARCH.
      IF sy-subrc <> 0.
        CLEAR ls_prcd_elements.
      ENDIF.
    END-OF-DEFINITION.

    " 判断是否为退货之类
    IF lr_data->vbtyp_va IN lt_vbtyp_neg_opt
    OR lr_data->vbtyp_vl IN lt_vbtyp_neg_opt
    OR lr_data->vbtyp_vf IN lt_vbtyp_neg_opt.
      lr_data->zfactor = -1.
    ELSE.
      lr_data->zfactor = 1.
    ENDIF.

    " 数量金额方向校准
    lr_data->kwmeng_va *= lr_data->zfactor.
    lr_data->zmeng_va *= lr_data->zfactor.
    lr_data->kzwi1_va *= lr_data->zfactor.
    lr_data->lfimg_vl *= lr_data->zfactor.
    lr_data->fkimg_vf *= lr_data->zfactor.
    lr_data->kzwi1_vf *= lr_data->zfactor.

    " 税率
    _get_prcd_elements 'MWSI'.
    lr_data->ztax_rate = ls_prcd_elements-kbetr / 100. " 底表记录13,转换为0.13

    " 销售数量,对于订单,取订单数量,对于和同或服务框架之类的,取目标数量
    IF lr_data->kwmeng_va <> 0.
      lr_data->zquan2 = lr_data->kwmeng_va.
    ELSEIF lr_data->zmeng_va <> 0.
      lr_data->zquan2 = lr_data->zmeng_va.
    ENDIF.
    " 销售单价 = 数量(订单数量或目标数量) / 小计
    " 看项目实际需求,可能会取定价值,这边简单取小计值即可
    IF lr_data->zquan2 <> 0.
      lr_data->zamount1 = lr_data->kzwi1_va / lr_data->zquan2.
    ENDIF.
    " 销售含税总金额 = 小计
    lr_data->zamount3 = lr_data->kzwi1_va.

    IF lr_data->vbeln_vl IS NOT INITIAL.
      lr_data->zamount4 = lr_data->zamount1. " 交货单价 = 销售单价
      " 根据行项目过账状态判断交货数量,不会有中间状态
      IF lr_data->wbsta_vl = 'C'. " 完全交货
        lr_data->zquan5 = lr_data->lfimg_vl. " 交货数量
      ENDIF.
      lr_data->zamount6 = lr_data->zquan5 * lr_data->zamount4. " 交货含税总金额 = 交货数量 * 交货单价
      lr_data->zquan7 = lr_data->zquan2 - lr_data->zquan5. " 未交货数量 = 销售数量 - 交货数量
      lr_data->zamount8 = lr_data->zquan7 * lr_data->zamount4. " 未交货含税总金额 = 未交货数量 * 交货单价
    ENDIF.

    " 开票单价 = 数量 / 小计
    IF lr_data->fkimg_vf <> 0.
      lr_data->zamount9 = lr_data->kzwi1_vf / lr_data->fkimg_vf.
    ENDIF.
    lr_data->zquan10 = lr_data->lfimg_vl. " 开票数量
    lr_data->zamount11 = lr_data->zquan10 * lr_data->zamount9. " 开票含税总金额 = 开票数量 * 开票单价
    IF lr_data->vbeln_vl IS NOT INITIAL.
      lr_data->zquan12 = lr_data->zquan5 - lr_data->lfimg_vl. " 未开票数量 = 交货数量 - 开票数量
    ELSE.
      lr_data->zquan12 = lr_data->zquan2 - lr_data->lfimg_vl. " 未开票数量 = 销售数量 - 开票数量
    ENDIF.
    lr_data->zamount13 = lr_data->zquan12 * lr_data->zamount11. " 未交货含税总金额 = 未交货数量 * 交货单价
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_fetch_text
*&---------------------------------------------------------------------*
*& 读取文本
*&---------------------------------------------------------------------*
FORM frm_fetch_text .
  CHECK gt_data IS NOT INITIAL.

*  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
*    lr_data->kunag_text = zcl_text=>auto( lr_data->kunag ).
*    lr_data->kunnr_text = zcl_text=>auto( lr_data->kunnr ).
*    lr_data->kunre_text = zcl_text=>auto( lr_data->kunre ).
*    lr_data->kunrg_text = zcl_text=>auto( lr_data->kunrg ).
*    lr_data->maktx = zcl_text=>auto( lr_data->matnr ).
*  ENDLOOP.

ENDFORM.
ALV
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
*&---------------------------------------------------------------------*
*& 包含               ZSDREPORT_ALV
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form frm_display
*&---------------------------------------------------------------------*
*& 报表展示
*&---------------------------------------------------------------------*
FORM frm_display TABLES ct_data TYPE STANDARD TABLE.

  DATA ls_layout TYPE lvc_s_layo.
  DATA lt_fieldcat TYPE STANDARD TABLE OF lvc_s_fcat.

  PERFORM frm_set_layout CHANGING ls_layout.
  PERFORM frm_set_fieldcat TABLES lt_fieldcat.
  PERFORM frm_set_style.
  PERFORM frm_set_color.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program      = sy-repid
*     i_callback_pf_status_set = 'FRM_PF_STATUS'
      i_callback_user_command = 'FRM_USER_COMMAND'
      is_layout_lvc           = ls_layout
      it_fieldcat_lvc         = lt_fieldcat
      i_default               = abap_true
      i_save                  = 'A'
    TABLES
      t_outtab                = ct_data[]
    EXCEPTIONS
      program_error           = 1
      OTHERS                  = 2.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_layout
*&---------------------------------------------------------------------*
*& 报表布局设置
*&---------------------------------------------------------------------*
FORM frm_set_layout CHANGING cs_layout TYPE lvc_s_layo.

  CLEAR cs_layout.
  cs_layout-zebra = abap_true. " 斑马线
  cs_layout-cwidth_opt = abap_true. " 自动调整ALVL列宽
  cs_layout-sel_mode = 'A'. " 选择模式
  cs_layout-ctab_fname = 'T_SCOL'. " 单元格颜色设置
  cs_layout-stylefname = 'T_STYL'. " 单元格控制

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_fieldcat
*&---------------------------------------------------------------------*
*& 字段目录设置
*&---------------------------------------------------------------------*
FORM frm_set_fieldcat TABLES ct_fieldcat TYPE lvc_t_fcat.

  DATA ls_fieldcat TYPE lvc_s_fcat.

  DEFINE _init_fieldcat.
    CLEAR ls_fieldcat.
    ls_fieldcat-fieldname = &1.
    ls_fieldcat-tooltip =
    ls_fieldcat-coltext =
    ls_fieldcat-seltext =
    ls_fieldcat-scrtext_l =
    ls_fieldcat-scrtext_m =
    ls_fieldcat-scrtext_s = &2.
    ls_fieldcat-ref_table = &3.
    ls_fieldcat-ref_field = &4.
    INSERT ls_fieldcat INTO TABLE ct_fieldcat.
  END-OF-DEFINITION.


  _init_fieldcat 'VBELN_VA' '销售订单' 'VBAP' 'VBELN'.
  _init_fieldcat 'POSNR_VA' '销售行项目' 'VBAP' 'POSNR'.
  _init_fieldcat 'VBTYP_VA ' '凭证类型' 'VBAK' 'VBTYP'.
  _init_fieldcat 'AUART_VA ' '销售订单类型' 'VBAK' 'AUART'.
  _init_fieldcat 'VKORG_VA ' '销售组织' 'VBAK' 'VKORG'.
  _init_fieldcat 'VTWEG_VA ' '分销渠道' 'VBAK' 'VTWEG'.
  _init_fieldcat 'SPART_VA ' '产品组' 'VBAK' 'SPART'.
*  _init_fieldcat 'KWMENG_VA' '订单数量' 'VBAP' 'KWMENG'.
*  _init_fieldcat 'ZMENG_VA ' '目标数量' 'VBAP' 'ZMENG'.
  _init_fieldcat 'MEINS_VA ' '单位' 'VBAP' 'MEINS'.
*  _init_fieldcat 'KZWI1_VA ' '销售小计' 'VBAP' 'KZWI1'.
  _init_fieldcat 'WAERK_VA ' '货币' 'VBAP' 'WAERK'.
  _init_fieldcat 'KNUMV_VA ' '条件号' 'VBAK' 'KNUMV'.
*  _init_fieldcat 'KBETR_VA ' '定价值' 'PRCD_ELEMENTS' 'KBETR'.
  _init_fieldcat 'BSTKD_VA ' '客户参考' 'VBKD' 'BSTKD'.

  _init_fieldcat 'KUNAG     ' '签署方编码' 'KNA1' 'KUNNR'.
  _init_fieldcat 'KUNAG_TEXT' '签署方名称' '' ''.
  _init_fieldcat 'KUNNR     ' '送达方编码' 'KNA1' 'KUNNR'.
  _init_fieldcat 'KUNNR_TEXT' '送达方名称' '' ''.
  _init_fieldcat 'KUNRE     ' '开票方编码' 'KNA1' 'KUNNR'.
  _init_fieldcat 'KUNRE_TEXT' '开票方名称' '' ''.
  _init_fieldcat 'KUNRG     ' '付款方编码' 'KNA1' 'KUNNR'.
  _init_fieldcat 'KUNRG_TEXT' '付款方名称' '' ''.

  _init_fieldcat 'MATNR' '物料号' 'MARA' 'MATNR'.
  _init_fieldcat 'MAKTX' '物料描述' 'MAKT' 'MAKTX'.
  _init_fieldcat 'WERKS' '工厂' 'T001W' 'WERKS'.
  _init_fieldcat 'LGORT' '库位' 'T001L' 'LGORT'.
  _init_fieldcat 'POSID' 'WBS' 'PRPS' 'POSID'.
  _init_fieldcat 'CHARG' '批次' 'MCH1' 'CHARG'.

  _init_fieldcat 'VBELN_VL' '交货订单' 'LIPS' 'VBELN'.
  _init_fieldcat 'POSNR_VL' '交货行项目' 'LIPS' 'POSNR'.
  _init_fieldcat 'VBTYP_VL' '销售和分销凭证类别' 'LIKP' 'VBTYP'.
  _init_fieldcat 'LFART_VL' '交货类型' 'LIKP' 'LFART'.
  _init_fieldcat 'WADAT_IST_VL' '实际交货日期' 'LIKP' 'WADAT_IST'.
  _init_fieldcat 'UECHA_VL' '上层项目批' 'LIPS' 'UECHA'.
  _init_fieldcat 'WBSTA_VL' '交货状态' 'LIPS' 'WBSTA'.
*  _INIT_FIELDCAT 'LFIMG_VL' '交货数量' 'LIPS' 'LFIMG'.
  _init_fieldcat 'MEINS_VL' '单位' 'LIPS' 'MEINS'.

  _init_fieldcat 'VBELN_VF' '开票凭证' 'VBRP' 'VBELN'.
  _init_fieldcat 'POSNR_VF' '开票行项目' 'VBRP' 'POSNR'.
  _init_fieldcat 'VBTYP_VF' '发票凭证类别' 'VBRK' 'VBTYP'.
  _init_fieldcat 'FKDAT_VF' '开票日期' 'VBRK' 'FKDAT'.
*  _INIT_FIELDCAT 'FKIMG_VF' '开票数量' 'VBRP' 'FKIMG'.
  _init_fieldcat 'MEINS_VF' '单位' 'VBRP' 'MEINS'.
*  _INIT_FIELDCAT 'KZWI1_VF' '发票小计' 'VBRP' 'KZWI1'.
  _init_fieldcat 'WAERK_VF' '货币' 'VBRP' 'WAERK'.

  _init_fieldcat 'ZTAX_RATE' '税率' '' ''.

  _init_fieldcat 'ZAMOUNT1 ' '销售单价' '' ''.
  _init_fieldcat 'ZQUAN2   ' '销售数量' '' ''.
  _init_fieldcat 'ZAMOUNT3 ' '销售含税总金额' '' ''.

  _init_fieldcat 'ZAMOUNT4 ' '发货单价' '' ''.
  _init_fieldcat 'ZQUAN5   ' '交货数量' '' ''.
  _init_fieldcat 'ZAMOUNT6 ' '发货含税总金额' '' ''.
  _init_fieldcat 'ZQUAN7   ' '未交货数量' '' ''.
  _init_fieldcat 'ZAMOUNT8 ' '未交货含税总金额' '' ''.

  _init_fieldcat 'ZAMOUNT9 ' '开票单价' '' ''.
  _init_fieldcat 'ZQUAN10  ' '开票数量' '' ''.
  _init_fieldcat 'ZAMOUNT11' '开票含税总金额' '' ''.
  _init_fieldcat 'ZQUAN12  ' '未开票数量' '' ''.
  _init_fieldcat 'ZAMOUNT13' '未开票含税总金额' '' ''.

  " 个性化自己输出数据格式
  LOOP AT ct_fieldcat REFERENCE INTO DATA(lr_fieldcat).
    IF lr_fieldcat->fieldname = 'ZSEL'.
      lr_fieldcat->checkbox = abap_true.
    ENDIF.

    " 销售参考
    IF lr_fieldcat->fieldname = 'KWMENG_VA' " 订单数量
    OR lr_fieldcat->fieldname = 'ZMENG_VA' " 目标数量
    OR lr_fieldcat->fieldname = 'ZQUAN2' " 销售数量
    .
      lr_fieldcat->qfieldname = 'MEINS_VA'.
    ENDIF.

    IF lr_fieldcat->fieldname = 'KZWI1_VA' " 小计
    OR lr_fieldcat->fieldname = 'KBETR_VA' " 定价值
    OR lr_fieldcat->fieldname = 'ZAMOUNT1' " 销售单价
    OR lr_fieldcat->fieldname = 'ZAMOUNT3' " 销售含税总金额
    .
      lr_fieldcat->qfieldname = 'WAERK_VA'.
    ENDIF.

    " 交货参考
    IF lr_fieldcat->fieldname = 'LFIMG_VL' " 交货数量
    OR lr_fieldcat->fieldname = 'ZQUAN5' " 交货数量
    OR lr_fieldcat->fieldname = 'ZQUAN7' " 未交货数量
    .
*      lr_fieldcat->qfieldname = 'MEINS_VL'.
      lr_fieldcat->qfieldname = 'MEINS_VA'.
    ENDIF.

    IF lr_fieldcat->fieldname = 'ZAMOUNT4' " 交货单价
    OR lr_fieldcat->fieldname = 'ZAMOUNT6' " 发货含税总金额
    OR lr_fieldcat->fieldname = 'ZAMOUNT7' " 未发货含税总金额
    .
*      lr_fieldcat->qfieldname = 'WAERK_VL'.
      lr_fieldcat->qfieldname = 'WAERK_VA'.
    ENDIF.

    " 开票参考
    IF lr_fieldcat->fieldname = 'FKIMG_VF' " 开票数量
    OR lr_fieldcat->fieldname = 'ZQUAN10' " 开票数量
    OR lr_fieldcat->fieldname = 'ZQUAN12' " 未开票数量
    .
      lr_fieldcat->qfieldname = 'MEINS_VF'.
    ENDIF.

    IF lr_fieldcat->fieldname = 'KZWI1_VF' " 开票小计
    OR lr_fieldcat->fieldname = 'ZAMOUNT9' " 开票单价
    OR lr_fieldcat->fieldname = 'ZAMOUNT11' " 开票含税总金额
    OR lr_fieldcat->fieldname = 'ZAMOUNT13' " 未开票含税总金额
    .
      lr_fieldcat->qfieldname = 'WAERK_VF'.
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_style
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
FORM frm_set_style.

  DATA ls_styl TYPE lvc_s_styl.

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
    CLEAR lr_data->t_styl.

    " 设置ALV字段或行的状态
    " 常用有禁止编辑CL_GUI_ALV_GRID=>MC_STYLE_DISABLED
    " 禁止删除行CL_GUI_ALV_GRID=>MC_STYLE_NO_DELETE_ROW

  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_set_color
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
FORM frm_set_color.

  STATICS:
    BEGIN OF color,
      r_light     TYPE char04,
      r_highlight TYPE char04,
      r_success   TYPE char04,
      r_error     TYPE char04,
      light       TYPE lvc_s_scol-color,
      highlight   TYPE lvc_s_scol-color,
      success     TYPE lvc_s_scol-color,
      error       TYPE lvc_s_scol-color,
    END OF color.
  IF color IS INITIAL.
    color-r_light = 'C300'.
    color-r_highlight = 'C310'.
    color-r_success = 'C500'.
    color-r_error = 'C600'.
    color-light = VALUE #( col = 3 ).
    color-highlight = VALUE #( col = 3 int = 1 ).
    color-success = VALUE #( col = 5 ).
    color-error = VALUE #( col = 6 ).
  ENDIF.

  DATA ls_scol TYPE lvc_s_scol.

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
    CLEAR lr_data->t_scol.

    " 关键信息高亮显示
    lr_data->t_scol = VALUE #( BASE lr_data->t_scol color = color-light " highlight
      ( fname = 'VBELN_VA    ' ) " 销售订单号
      ( fname = 'VBELN_VF    ' ) " 开票凭证
      ( fname = 'VBELN_VL    ' ) " 交货单号
    ).

    " 关键信息高亮显示
    lr_data->t_scol = VALUE #( BASE lr_data->t_scol color = color-light
      ( fname = 'KUNAG' ) " 签署方编码
      ( fname = 'KUNNR' ) " 送达方编码
      ( fname = 'KUNRE' ) " 开票方编码
      ( fname = 'KUNRG' ) " 付款方编码

      ( fname = 'MATNR' ) " 物料号
      ( fname = 'WERKS' ) " 工厂
      ( fname = 'LGORT' ) " 库位
      ( fname = 'PSPNR' ) " WBS
      ( fname = 'POSID' ) " WBS
      ( fname = 'CHARG' ) " SAP批次号

      ( fname = 'MEINS_VA' ) " 单位
      ( fname = 'MEINS_VL' ) " 单位
      ( fname = 'MEINS_VF' ) " 单位
      ( fname = 'WAERK_VA' ) " 货币
      ( fname = 'WAERK_VL' ) " 货币
      ( fname = 'WAERK_VF' ) " 货币

      ( fname = 'KWMENG_VA' ) " 订单数量
      ( fname = 'ZMENG_VA' ) " 目标数量
      ( fname = 'KZWI1_VA' ) " 销售小计
      ( fname = 'LFIMG_VL' ) " 发货数量
      ( fname = 'FKIMG_VF' ) " 开票数量
      ( fname = 'KZWI1_VF' ) " 发票小计

      ( fname = 'ZAMOUNT1 ' ) " 销售单价
      ( fname = 'ZQUAN2   ' ) " 销售数量
      ( fname = 'ZAMOUNT3 ' ) " 销售含税总金额

      ( fname = 'ZAMOUNT4 ' ) " 发货单价
      ( fname = 'ZQUAN5   ' ) " 交货数量
      ( fname = 'ZAMOUNT6 ' ) " 发货含税总金额
      ( fname = 'ZQUAN7   ' ) " 未交货数量
      ( fname = 'ZAMOUNT8 ' ) " 未交货含税总金额

      ( fname = 'ZAMOUNT9 ' ) " 开票单价
      ( fname = 'ZQUAN10  ' ) " 开票数量
      ( fname = 'ZAMOUNT11' ) " 开票含税总金额
      ( fname = 'ZQUAN12  ' ) " 未开票数量
      ( fname = 'ZAMOUNT13' ) " 未开票含税总金额
    ).

    IF lr_data->mtype = 'E'.
      lr_data->t_scol = VALUE #( BASE lr_data->t_scol color = color-error
        ( fname = 'MTYPE' )
        ( fname = 'MSG' )
      ).
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_pf_status
*&---------------------------------------------------------------------*
*& 设置GUI状态
*&---------------------------------------------------------------------*
FORM frm_pf_status USING ct_extab TYPE slis_t_extab.

  DATA lt_excluding TYPE STANDARD TABLE OF sy-ucomm.
  SET PF-STATUS 'STATUS' EXCLUDING lt_excluding.

  DATA l_title TYPE string.
  SET TITLEBAR 'TITLE' WITH l_title.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_user_command
*&---------------------------------------------------------------------*
*& 功能响应
*&---------------------------------------------------------------------*
FORM frm_user_command USING cv_ucomm LIKE sy-ucomm
                            cs_selfield TYPE slis_selfield.

  " 刷新屏幕数据到内表
  DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_grid.
  CALL METHOD lo_grid->check_changed_data.

  PERFORM frm_get_data_selection.

  " 按钮功能实现
  CASE cv_ucomm.
    WHEN '&IC1'. " 双击
      CASE cs_selfield-fieldname.
        WHEN 'MATNR'.
          SET PARAMETER ID 'MXX' FIELD 'K'.
          SET PARAMETER ID 'MAT' FIELD cs_selfield-value.
          CALL TRANSACTION 'MM03' AND SKIP FIRST SCREEN.

        WHEN 'VBELN_VA'.
          SET PARAMETER ID 'AUN' FIELD cs_selfield-value.
          CALL TRANSACTION 'VA03' AND SKIP FIRST SCREEN.

        WHEN 'VBELN_VL'.
          SET PARAMETER ID 'VL' FIELD cs_selfield-value.
          CALL TRANSACTION 'VL03N' AND SKIP FIRST SCREEN.

        WHEN 'VBELN_VF'.
          SET PARAMETER ID 'VF' FIELD cs_selfield-value.
          CALL TRANSACTION 'VF03' AND SKIP FIRST SCREEN.

      ENDCASE.

    WHEN OTHERS.
  ENDCASE.

  " 刷新ALV 显示值
  cs_selfield-refresh = abap_true .
  cs_selfield-row_stable = abap_true .
  cs_selfield-col_stable = abap_true .

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data_selection
*&---------------------------------------------------------------------*
*& 传递侧边栏选择到ZSEL字段
*&---------------------------------------------------------------------*
FORM frm_get_data_selection.

  " 刷新屏幕数据到内表
  DATA: lo_grid TYPE REF TO cl_gui_alv_grid.
  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_grid.

  " 获取ALV选取行
  DATA lt_rows TYPE lvc_t_row.
  CALL METHOD lo_grid->get_selected_rows
    IMPORTING
      et_index_rows = lt_rows.

  LOOP AT lt_rows INTO DATA(ls_row).
    READ TABLE gt_data REFERENCE INTO DATA(lr_data) INDEX ls_row-index.
    IF sy-subrc = 0.
      lr_data->zsel = abap_true.
    ENDIF.
  ENDLOOP.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_reset_data_selection
*&---------------------------------------------------------------------*
*& 取消全部勾选
*&---------------------------------------------------------------------*
FORM frm_reset_data_selection.

  LOOP AT gt_data REFERENCE INTO DATA(lr_data).
    CLEAR lr_data->zsel.
  ENDLOOP.

ENDFORM.