SAP---ABAP

Monday, October 8, 2007



SQL Tool for ABAP Yes4SQL -- Both Native & Open SQL


REPORT Yes4SQL.

* SQL tool for SAP ABAP Programmers - BOTH OPEN & NATIVE SQLs
* very light - approx. 20KB
*
* Objective - to see JOINS in SAP to confirm or discover relationships
* and to see Data side by Side

* Read "SAP Table and Field search strategies"
* in http://sapabap.iespana.es/sapabap/sap/info/search_fields_tables.htm
* Use SAP_TABLES.exe Document in http://www.sap-img.com
* and many other excellent resources to navigate the cryptic tables & Colums of SAP
*
* SE16 is the best for 1 table inspection & you can open several sessions if
* you have more than 1 table.
* You may "hate joins" and prefer looping matches on Internal Tables.
* However if you wish to see the relationships in DATA VISIBLE format
* NOTHING succeeds like JOINs
* I came in with a Strong Oracle TOAD background and feel comfortable
* in seeing DATA together

* The decision to use JOIN or use iterative Internal Table match with single select
* does not detract from the visibility of tracking relationships

* SQL Must be SELECT
* List of Columns Selected before 1st FROM Must Have
* 1 Column per line in format TABLE~COLUMN if Open SQL
* 1 Column per line in format TABLE.COLUMN if Native SQL

* Naturally tables & Columns must exist
* as this used to dynamically create Internal Table for ALV Grid
*
* Count( * ) is NOT SUPPORTED but you could Use Native COUNT( any NOT NULL NUMERIC COLUMN )

* SUM MIN MAX AVG supported
* SUM( table~COLUMN ) or SUM( table.COLUMN )
* but there must be 1 space as indicated after ( and before ) -- even for native

* If you use NATIVE SQL make sure you have :SY-MANDT filter in WHERE Clause

* You CAN pick 2 COLUMNS having same name - this is important for inspection
* Program creates right aliases as you can see in c:\jnc.ab4
* jnc.ab4 is the generated ABAP program for diagnostics and possible reuse

* JOINs and SUBQUERIES are NOT ALLOWED for
* Pooled Tables, Clustered Tables & Projection Views
* Even AGGREGATE Functions are NOT ALLOWED! -- thse restrictions are inherent in SAP

* So this tool is useful for TRANSPARENT TABLES only!

* Author Jayanta Narayan Choudhuri
* Flat 302
* 395 Jodhpur Park
* Kolkata 700 068
* Email sss@cal.vsnl.net.in
* URL: http://www.geocities.com/ojnc

* TextEdit Control Tool Code Copied from SAP Standard Example saptextedit_demo_3
* This is FREE software with FULL responsibility on USER & anyone changing sourcecode!

DATA:
* reference to wrapper class of control based on OO Framework
g_editor TYPE REF TO cl_gui_textedit,
* reference to custom container: necessary to bind TextEdit Control
g_editor_container TYPE REF TO cl_gui_custom_container,
* other variables
g_ok_code LIKE sy-ucomm, " return code from screen
g_repid LIKE sy-repid.

Data: ROWS type I,
ISOPEN type C,
DELIM type C.

DATA: code Type Table of rssource-line,
prog(8) TYPE c,
msg(120) TYPE c,
lin(3) TYPE c,
wrd(10) TYPE c,
off(3) TYPE c.

Data: OneLineCode like LINE of Code.

Type-Pools : Slis.

DATA : fcat TYPE SLIS_T_FIELDCAT_ALV.
DATA : wcat LIKE LINE OF FCAT.

CONSTANTS: c_line_length TYPE i VALUE 80.

* define table type for data exchange
TYPES: BEGIN OF mytable_line,
line(c_line_length) TYPE c,
END OF mytable_line.

* table to exchange text
DATA g_mytable TYPE TABLE OF mytable_line.

DATA: myLine like LINE of g_mytable.

* necessary to flush the automation queue
CLASS cl_gui_cfw DEFINITION LOAD.

START-OF-SELECTION.
Move 'X' to ISOPEN.
Move 100 to Rows.

CALL SCREEN 100.

************************************************************************
* P B O
************************************************************************
MODULE pbo OUTPUT.

SET PF-STATUS 'MAIN100'.
SET TITLEBAR 'TITLEYES4SQL'.

IF g_editor IS INITIAL.

* initilize local variable with sy-repid, since sy-repid doesn't work
* as parameter directly.
g_repid = sy-repid.

* create control container
CREATE OBJECT g_editor_container
EXPORTING
container_name = 'MYEDIT'
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
create_error = 3
lifetime_error = 4
lifetime_dynpro_dynpro_link = 5.
IF sy-subrc NE 0.
* add your handling
ENDIF.


* create calls constructor, which initializes, creats and links
* a TextEdit Control
CREATE OBJECT g_editor
EXPORTING
parent = g_editor_container
wordwrap_mode = cl_gui_textedit=>wordwrap_at_fixed_position
wordwrap_to_linebreak_mode = cl_gui_textedit=>true
EXCEPTIONS
others = 1.
IF sy-subrc NE 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'Create Object Failed'
txt1 = 'to make TextEditor Control'.
Leave Program.
ENDIF.

ENDIF. " Editor is initial

* remember: there is an automatic flush at the end of PBO!

ENDMODULE. " PBO


************************************************************************
* P A I
************************************************************************
MODULE pai INPUT.

CASE g_ok_code.

WHEN 'EXIT'.
PERFORM exit_program.

WHEN 'EXEC'.
* retrieve table from control
Clear g_mytable.

CALL METHOD g_editor->get_text_as_r3table
IMPORTING
table = g_mytable
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'Get_Text_As_R3Table Failed'
txt1 = 'Unable to Store SQL'.
Leave Program.
ENDIF.

* if you would like to work with the table contents
* perform a explicit flush here allthough the method
* flushes internally (at least up to release 4.6D).
* The reason: don't rely on internal flushes of control
* wrappers. These might vanish in the future leading to a
* malfunction of your transaction. The additional flush here
* does no harm. The autmation queue is empty and NO additional
* roundtrip to the frontend will be triggered.
CALL METHOD cl_gui_cfw=>flush
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'cl_gui_cfw=>flush Failed'
txt1 = 'Exiting Program'.
Leave Program.
ENDIF.

Perform F_RUNSQL.

ENDCASE.

CLEAR g_ok_code.
ENDMODULE. " PAI


************************************************************************
* F O R M S
************************************************************************

*&---------------------------------------------------------------------*
*& Form EXIT_PROGRAM
*&---------------------------------------------------------------------*
FORM exit_program.
* Destroy Control.
IF NOT g_editor IS INITIAL.
CALL METHOD g_editor->free
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'g_editor->free Failed'
txt1 = 'Exiting Program'.
Leave Program.
ENDIF.
* free ABAP object also
FREE g_editor.
ENDIF.


* destroy container
IF NOT g_editor_container IS INITIAL.
CALL METHOD g_editor_container->free
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
* MESSAGE E002 WITH F_RETURN.
ENDIF.
* free ABAP object also
FREE g_editor_container.
ENDIF.


* finally flush
CALL METHOD cl_gui_cfw=>flush
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'cl_gui_cfw=>flush Failed'
txt1 = 'Exiting Program'.
Leave Program.
ENDIF.

LEAVE PROGRAM.

ENDFORM. " EXIT_PROGRAM

*&---------------------------------------------------------------------*
*& Form F_RUNSQL
*&---------------------------------------------------------------------*
FORM F_RUNSQL.

Data: first type I,
numCols type I,
aggfun type I,
Pos Type I,
Off Type I,
Len Type I,
NumRows Type I,
RowNum Type I,
MyString Type String,
MyString2 Type String,
CRows(8) Type C.

data : begin of TBLCOL_TAB occurs 0,
TBL type String,
COL type String.
data : end of TBLCOL_TAB.

If Rows is Initial.
Move 100 to Rows.
EndIf.

Clear Code.

Move 0 to : first, numCols, aggFun.

Loop At g_mytable Into myLine.
Concatenate ' ' myLine ' ' into myLine SEPARATED BY SPACE..

If strlen( myLine ) = 0.
continue.
EndIf.

If first = 0.
Find ' Select ' in myLine Ignoring Case.
If SY-SubRc <> 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'SELECT DMLs Only Please!'
txt1 = 'Correct & Retry'.
Return.
EndIf.
Move 1 to first.
EndIf.

Find ' From ' in MyLine Ignoring case.
If SY-SubRc = 0.
Exit.
EndIf.

If IsOpen = 'X'.
move '~' to delim.
Else.
move '.' to delim.
EndIf.

Find delim in myLine Match Offset off.
If SY-SubRc <> 0.
Continue.
EndIf.

Add 1 to NumCols.

Compute Pos = Off - 1.

Do.
If MyLine+Pos(1) = Space.
Exit.
EndIf.
Subtract 1 from Pos.
EndDo.

Add 1 to Pos.
Compute Len = Off - Pos.
Move MyLine+Pos(Len) to TBLCOL_TAB-TBL.
Move MyLine+Pos(Len) to myString.

Compute Pos = Off + 1.

Do.
If MyLine+Pos(1) = Space OR MyLine+Pos(1) = ','.
Exit.
EndIf.
Add 1 to Pos.
EndDo.

Subtract 1 from Pos.
Compute Len = Pos - Off.
Compute Pos = Off + 1.
Move MyLine+Pos(Len) to TBLCOL_TAB-COL.
Append TBLCOL_TAB.

Concatenate myString delim MyLine+Pos(Len) into myString.

Write numCols to CRows.
Concatenate 'WFLD' CRows Into MyString2.
Condense MyString2 No-Gaps.

Find ')' in myLine.
If Sy-SubRC = 0.
Move 1 to AggFun.
Concatenate ') as' myString2 into myString2 Separated by Space.
Replace ')' in myLine with myString2.
Else.
Concatenate myString 'as' myString2 into myString2 Separated by Space.
Replace myString in myLine with myString2.
EndIf.

Modify g_mytable from MyLine.

EndLoop.

If Lines( TBLCOL_TAB ) = 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'Table~Column Open SQL is MUST'
txt1 = 'Table.Column Native SQL is MUST'.
Return.
EndIf.

Append 'Program SubPool.' to Code.
Append '' to Code.

Append 'data : begin of I_TAB occurs 0,' to Code.

NumRows = Lines( TBLCOL_TAB ).

Move 0 to RowNum.

Loop At TBLCOL_TAB.
Add 1 to RowNum.
Write RowNum to CRows.
Concatenate 'WFLD' CRows Into MyString.
Condense MyString no-gaps.

Concatenate MyString 'Like' TBLCOL_TAB-TBL into MyString SEPARATED BY SPACE.

If RowNum = NumRows.
Concatenate MyString '-' TBLCOL_TAB-COL '.' into MyString.
Else.
Concatenate MyString '-' TBLCOL_TAB-COL ',' into MyString.
EndIf.
Append MyString to Code.
EndLoop.
Append 'data : end of I_TAB.' to Code.
Append '' to Code.
Append 'DATA : R_TAB LIKE LINE OF I_TAB,' to Code.
Append ' L_KOUNT type I.' to Code.
Append '' to Code.

Append 'DATA : MyString type STRING.' to Code.
Append 'DATA : MyTitle type LVC_TITLE.' to Code.
Append '' to Code.

Append 'Data: ROWS type I.' to Code.
Append '' to Code.

Append 'Form DoSQL.' to Code.
Append '' to Code.
Write Rows to CRows.
Replace all Occurrences of ',' in Crows With ''.
Concatenate 'Move' Crows 'to ROWS.' into MyString SEPARATED BY SPACE.
Append MyString to Code.
Append '' to Code.

Move 0 to RowNum.
Loop At TBLCOL_TAB.
Add 1 to RowNum.
If RowNum = 1.
Concatenate ' Move ''' TBLCOL_TAB-COL ''' to MyString.' into MyString.
Append MyString to Code.
Else.
Concatenate ' Concatenate MyString '','' '''
TBLCOL_TAB-COL ''' Into MyString.' into MyString.
Append MyString to Code.
EndIf.
Append ' Move MyString to MyTitle.' to Code.
Append '' to Code.
EndLoop.

Append '' to Code.
Append 'Try.' to Code.
Append '' to Code.

If IsOpen <> 'X'.
Append 'Move 0 to L_KOUNT.' to Code.
Append 'EXEC SQL.' to Code.
Append ' open c1 for ' to Code.
EndIf.

Move 0 to first.
Loop At g_mytable into MyLine.
If IsOpen = 'X' and first = 0.
Find ' From ' in myLine ignoring case.
If SY-SubRC = 0.
Append 'Into Table I_TAB' to Code.
If aggFun = 0.
Append 'Up To ROWS rows' to Code.
EndIf.
move 1 to first.
EndIf.
EndIf.
Append MyLine to Code.
EndLoop.

If IsOpen = 'X'.
If first = 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'Open SQL Without a FROM'
txt1 = 'Correct & retry'.
Return.
EndIf.
Append '.' to Code.
Else.
Append 'ENDEXEC.' to Code.
Append '' to Code.
Append 'DO.' to Code.
Append ' EXEC SQL.' to Code.
Append ' fetch next c1 INTO :R_TAB ' to Code.
Append ' ENDEXEC.' to Code.
Append ' IF sy-subrc <> 0.' to Code.
Append ' EXIT.' to Code.
Append ' ENDIF.' to Code.
Append ' Append R_TAB to I_TAB.' to Code.
Append ' Add 1 to L_KOUNT.' to Code.
Append ' If L_KOUNT >= ROWS.' to Code.
Append ' Exit.' to Code.
Append ' EndIf.' to Code.
Append 'ENDDO.' to Code.
Append '' to Code.
Append 'EXEC SQL.' to Code.
Append ' close c1' to Code.
Append 'ENDEXEC.' to Code.
Append '' to Code.
EndIf.

Append '' to Code.
Append 'PERFORM zjnc_dump_list USING ''I_TAB[]'' ''I_TAB'' MyTitle.' to Code.
Append '' to Code.
Append 'Catch CX_ROOT.' to Code.
If IsOpen <> 'X'.
Append 'EXEC SQL.' to Code.
Append ' close c1' to Code.
Append 'ENDEXEC.' to Code.
EndIf.
Append 'CALL FUNCTION ''POPUP_TO_INFORM''' to Code.
Append ' EXPORTING' to Code.
Append ' titel = ''jncDynamicSub''' to Code.
Append ' txt2 = ''Generate SUBROUTINE POOL Succeeded BUT SQL failed''' to Code.
Append ' txt1 = ''Possible Wrong SQL - see c:\jnc.ab4''.' to Code.
Append 'EndTry.' to Code.
Append 'EndForm. "DoSQL.' to Code.

Append '' to Code.
Append
'*&--------------------------------------------------------------------*' to Code.
Append '*& Form ZJNC_DUMP_LIST Our Good Old ALV list - RECOMMENDED!' to Code.
Append
'*&--------------------------------------------------------------------*' to Code.
Append 'FORM zjnc_dump_list USING value(p_it_name) TYPE c' to Code.
Append ' value(p_wa_name) TYPE c' to Code.
Append ' value(p_heading) TYPE c.' to Code.
Append '' to Code.
Append ' TYPE-POOLS: slis.' to Code.
Append '' to Code.
Append ' DATA:' to Code.
Append ' stru_ref TYPE REF TO cl_abap_structdescr,' to Code.
Append ' comp_tab TYPE abap_compdescr_tab,' to Code.
Append ' one_comp TYPE abap_compdescr,' to Code.
Append ' one_name TYPE string,' to Code.
Append ' type_ref TYPE REF TO cl_abap_typedescr,' to Code.
Append ' is_ddic TYPE abap_bool,' to Code.
Append ' lt_ddic TYPE dd_x031l_table,' to Code.
Append ' wa_ddic TYPE x031l,' to Code.
Append ' lt_fcat TYPE slis_t_fieldcat_alv,' to Code.
Append ' wa_fcat TYPE slis_fieldcat_alv,' to Code.
Append ' ls_layo TYPE slis_layout_alv,' to Code.
Append ' l_alv TYPE REF TO cl_gui_alv_grid.' to Code.
Append '' to Code.
Append ' FIELD-SYMBOLS: TYPE ANY,' to Code.
Append ' TYPE STANDARD TABLE,' to Code.
Append ' TYPE ANY.' to Code.
Append '' to Code.
Append ' ASSIGN (p_it_name) TO .' to Code.
Append '' to Code.
Append ' ASSIGN (p_wa_name) TO .' to Code.
Append '' to Code.
Append ' ls_layo-colwidth_optimize = ''X''.' to Code.
Append ' ls_layo-zebra = ''X''.' to Code.
Append ' ls_layo-window_titlebar = p_heading.' to Code.
Append ' ls_layo-box_tabname = p_it_name.' to Code.
Append '' to Code.
Append ' stru_ref ?= cl_abap_structdescr=>describe_by_data( ).' to Code.
Append '' to Code.
Append ' comp_tab = stru_ref->components.' to Code.
Append '' to Code.
Append ' LOOP AT comp_tab INTO one_comp.' to Code.
Append ' CLEAR wa_fcat.' to Code.
Append ' wa_fcat-tabname = p_it_name.' to Code.
Append ' wa_fcat-fieldname = one_comp-name.' to Code.
Append '' to Code.
Append ' CONCATENATE p_wa_name ''-'' one_comp-name INTO one_name.' to Code.
Append '' to Code.
Append ' ASSIGN (one_name) TO .' to Code.
Append '' to Code.
Append ' type_ref ?= cl_abap_typedescr=>describe_by_data( ).' to Code.
Append '' to Code.
Append ' is_ddic = type_ref->is_ddic_type( ).' to Code.
Append '' to Code.
Append ' IF is_ddic = abap_true.' to Code.
Append ' lt_ddic = type_ref->get_ddic_object( ).' to Code.
Append '' to Code.
Append ' LOOP AT lt_ddic INTO wa_ddic.' to Code.
Append ' CLEAR wa_ddic-tabname.' to Code.
Append ' SELECT SINGLE' to Code.
Append ' dd03l~tabname' to Code.
Append ' INTO wa_ddic-tabname' to Code.
Append ' FROM dd03l' to Code.
Append ' WHERE dd03l~fieldname = wa_ddic-fieldname' to Code.
Append ' AND dd03l~tabname NOT LIKE ''/%''. " only normal namespace' to Code.
Append '' to Code.
Append '' to Code.
Append ' wa_fcat-ref_tabname = wa_ddic-tabname.' to Code.
Append ' wa_fcat-ref_fieldname = wa_ddic-fieldname.' to Code.
Append '' to Code.
Append ' SELECT SINGLE' to Code.
Append ' dd04t~scrtext_s' to Code.
Append ' dd04t~scrtext_m' to Code.
Append ' dd04t~scrtext_l' to Code.
Append ' INTO (wa_fcat-seltext_s, wa_fcat-seltext_m, wa_fcat-seltext_l)' to Code.
Append ' FROM dd04t' to Code.
Append ' WHERE dd04t~rollname = wa_ddic-fieldname' to Code.
Append ' AND dd04t~ddlanguage = sy-langu.' to Code.
Append '' to Code.
Append ' ENDLOOP.' to Code.
Append ' ELSE.' to Code.
Append ' MOVE one_comp-name TO: wa_fcat-seltext_s, wa_fcat-seltext_m,' to Code.
Append ' wa_fcat-seltext_l.' to Code.
Append ' ENDIF.' to Code.
Append '' to Code.
Append ' APPEND wa_fcat TO lt_fcat.' to Code.
Append '' to Code.
Append ' ENDLOOP.' to Code.
Append '' to Code.
Append ' CALL FUNCTION ''REUSE_ALV_GRID_DISPLAY''' to Code.
Append ' EXPORTING' to Code.
Append ' is_layout = ls_layo' to Code.
Append ' it_fieldcat = lt_fcat' to Code.
Append ' TABLES' to Code.
Append ' t_outtab = .' to Code.
Append '' to Code.
Append 'ENDFORM. "ZJNC_DUMP_LIST' to Code.

CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
FILENAME = 'c:\jnc.ab4'
TABLES
DATA_TAB = CODE.


IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.


GENERATE SUBROUTINE POOL code NAME prog
MESSAGE msg
LINE lin
WORD wrd
OFFSET off.

IF sy-subrc <> 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'Generate SUBROUTINE POOL Failed'
txt1 = 'Possible Nonconformant SQL - see c:\jnc.ab4'.
ELSE.
PERFORM DoSQL IN PROGRAM (prog).
IF sy-subrc <> 0.
CALL FUNCTION 'POPUP_TO_INFORM'
EXPORTING
titel = g_repid
txt2 = 'Generate SUBROUTINE POOL Succeeded BUT Call failed'
txt1 = 'Possible Wrong SQL - see c:\jnc.ab4'.
ENDIF.
ENDIF.

ENDFORM. "F_RUNSQL
=================================================================================
Few Sample SQLs
===============

1) Open
Select
Mard~matnr
Makt~maktx
From Makt
Inner Join Mard
on Makt~matnr = Mard~matnr
Where Makt~Spras = SY-LANGU

2) Native Oracle
SELECT Mard.matnr,
Makt.maktx
From Makt, Mard
Where Makt.mandt = Mard.mandt
And Makt.matnr = Mard.matnr
And Makt.mandt = :SY-MANDT
And Makt.spras = :SY-LANGU

3) KONV is Cluster - BAD LUCK!
Select VBRK~VBELN
VBRP~POSNR
KONV~KSCHL
KONV~KWERT
From ( VBRK Inner Join VBRP
On VBRK~VBELN = VBRP~VBELN )
Inner Join KONV
On VBRK~KNUMV = KONV~KNUMV
And VBRP~POSNR = KONV~KPOSN

4) KONV is Cluster - BAD LUCK!
Select KONV~KNUMV
KONV~KPOSN
KONV~KSCHL
KONV~KWERT
From KONV
Where KONV~KNUMV in (
Select VBRK~KNUMV
From VBRK Inner Join VBRP
On VBRK~VBELN = VBRP~VBELN
Where VBRK~KNUMV = KONV~KNUMV
And VBRP~POSNR = KONV~KPOSN
)

5) Open
Select VBRP~MATNR
Sum( VBRP~NETWR )
From VBRP
Group By VBRP~MATNR

6) Native Oracle
Select VBRP.MATNR ,
Sum( VBRP.NETWR )
From VBRP
Where mandt = :sy-mandt
Group By VBRP.MATNR

7) Native Oracle
Select VBRP.MATNR ,
Count( VBRP.NETWR ),
Sum( VBRP.NETWR )
From VBRP
Where mandt = :sy-mandt
Group By VBRP.MATNR

8) Open
Select VBRP~MATNR
makt~maktx
Sum( VBRP~NETWR )
From VBRP inner Join MAKT
On VBRP~MATNR = MAKT~MATNR
Where MAKT~SPRAS = SY-LANGU
Group By VBRP~MATNR makt~maktx

9) Native Oracle
Select VBRP.MANDT,
VBRP.MATNR,
MAKT.MAKTX,
Sum( VBRP.NETWR )
From VBRP , MAKT
Where VBRP.MANDT = MAKT.MANDT
And VBRP.MATNR = MAKT.MATNR
And MAKT.SPRAS = :SY-LANGU
Group By VBRP.MANDT, VBRP.MATNR, MAKT.MAKTX

10) Open
SELECT EKET~EBELN
EKET~EINDT
EKET~WAMNG
EKET~WEMNG
From ( ekko INNER JOIN ekpo
ON ekko~mandt = ekpo~mandt
AND ekko~ebeln = ekpo~ebeln
)
INNER JOIN eket
ON ekpo~mandt = eket~mandt
AND ekpo~ebeln = eket~ebeln
AND ekpo~ebelp = eket~ebelp
AND EKET~WAMNG > 0
AND EKET~WAMNG <> EKET~WEMNG
Where EKPO~MATNR = 'NB220'
And EKPO~WERKS In ('P001', 'P004', 'L004')
And EKKO~BSTYP = 'F'
And EKKO~BSART = 'UB'
And EKPO~ELIKZ <> 'X'
And EKKO~LOEKZ <> 'X'

11) Native Oracle
SELECT EKET.EBELN,
EKET.EINDT,
EKET.WAMNG,
EKET.WEMNG
FROM ( ekko INNER JOIN ekpo
ON ekko.mandt = ekpo.mandt
AND ekko.ebeln = ekpo.ebeln
)
INNER JOIN eket
ON ekpo.mandt = eket.mandt
AND ekpo.ebeln = eket.ebeln
AND ekpo.ebelp = eket.ebelp
AND EKET.WAMNG > 0
AND EKET.WAMNG <> EKET.WEMNG
Where EKPO.MATNR = 'NB220'
And EKPO.WERKS In ('P001', 'P004', 'L004')
And EKKO.BSTYP = 'F'
And EKKO.BSART = 'UB'
And EKPO.ELIKZ <> 'X'
And EKKO.LOEKZ <> 'X'


Different Types of Selection Screens

What is:

1. at selection-screen on field
2. at selection-screen output
3. at selection-screen block
4. at selection-screen on value-request
5. at selection-screen on help-request and their difference?


For knowing Selection-screens:

First you must have right understanding of Events.
- Events are introduced by Event Keyword. They end when again next processs begins.


Selection-screens are special screen defined in ABAP.
- This ABAP at run time only controls the flow logic of Selection-screens. The PBO and PAI triggers the num of. selection-screens.


The basic form of the selection screen events is the AT SELECTION-SCREEN event. This event occurs after the runtime environment has passed all input data from the selection screen to the ABAP program. The other selection screen events allow programmers to modify the selection screen before it is sent and specifically check user input.


At Selection-screen OUTPUT is trigerred in PBO of selection-screen.

- This allows you to modify the Selection-screen, before it is displayed.


At Selection-screen On Field is triggered in PAI of selection-screens.

- The input fields can b checked,in the corresponding event block. If an error message occurs within this event block, the corresponding field is made ready for input again on the selection screen.


At Selection-screen On Block is trigerred in PAI event.

- You define a block by enclosing the declarations of the elements in the block between the statements SELECTION-SCREEN BEGIN OF BLOCK block - END OF BLOCK block. You can use this event block to check the consistency of the input fields in the block.


At Selection-screen On value request.

- This event is trigerred for F4 help.


At Selection-screen On help request .
- This event is triggered when the user clicks F1 for help on fileds.



Difference Between Select-Options & Ranges


What are the difference between SELECT-OPTIONS & RANGES?


Here both SELECT-OPTIONS & RANGES works for the same purpose. They both are used for the range selection from selection screen. The main diff. between them is, while we use SELECT-OPTIONS system implicitly creates the select options internal table which contains the fields of SIGN,OPTION,LOW & HIGH. But in case of RANGES, this internal table should be defined explicitly.

Eg. to SELECT-OPTIONS :
-----------------------------------------

REPORT YARSELECT.
TABLES YTXLFA1.
SELECT-OPTIONS : VENDOR FOR YTXLFA1-LIFNR.
INITIALIZATION.
VENDOR-LOW = 1000. " It specifies the range starting value.
VENDOR-HIGH = 2000. " It specifies the range ending value.
VENDOR-OPTION = 'BT'. " specifies ranges value is in between.
VENDOR-SIGN = 'I'. "specifies both inclussive.

APPEND VENDOR.

- - - -
- - - -
SELECT LIFNR LAND1 NAME1 FROM LFA1 INTO TABLE ITAB
WHERE LIFNR IN VENDOR.

Eg. to RANGES:
-------------------------

REPORT YARRANGE.
TABLES YTXLFA1.
RANGES: VENDOR FOR YTXFLA1-LIFNR.

- - - -
- - - --
- - - -

SELECT LIFNR LAND1 NAME1 FROM LFA1 INTO TABLE ITAB
WHERE LIFNR IN VENDOR.

Here with RANGES user has to design an internal table with fields -
SIGN,OPTION,LOW and HIGH EXPLICITLY.

--------------------------------------------------------------------------------------------------------->


Example:

select-options: bukrs for zstock-bukrs.

Should the user fill in 'ABFI' in BUKRS on the selection screen, BUKRS will look like this:

IEQABFI

This is because BUKRS is set as a table as follows:

begin of bukrs occurs 0,
SIGN(1) type c,
OPTION(2) type c,
LOW like bukrs,
HIGH like bukrs,
end of bukrs.

Now, when you create the following range, it will have the exact same fields set inside its table:

Ranges: bukrs for zstock-bukrs.

The difference is, because ranges doesn't show on the selection screen, you will have to fill it yourself, meaning you will have to fill bukrs-sign, bukrs-option, bukrs-low & bukrs-high all manually.

Some tips:
Sign is always I (for Include) or E (for Exclude)
Option can be a whole range, which includes:
EQ (Equal)
BT (Between))
CP (Contain Pattern)
So let's say you want to have the range check for all company codes not starting with AB, you will set your code as follow:

ranges: bukrs for zstock-bukrs.

bukrs-sign = 'E'. "Exclude
bukrs-option = 'CP'. "Pattern
bukrs-low = 'AB*'. "Low Value
bukrs-high = ''. "High Value
append bukrs.

Always remember to APPEND your range when you fill it, as the WHERE clause checks against the lines of the range table, not against the header line.

Hope this explains it well enough.

--------------------------------------------------------------------------------------------------------->


What does SIGN "I" & "E" mean?

The "I" stands for Include, and the "E" for Exclude.

The easiest way to learn how the range selections work is, create the following dummy program:

report dummy.
tables: mara.
select-options: matnr for mara-matnr.
start-of-selection.
loop at matnr.
write: / matnr-sign,
matnr-option,
matnr-low,
matnr-high.
endloop.

Run this program, and fill in a lot of junk into MATNR. Fill in some includes, some excludes, some ranges, etc., and you will soon realise how the system builds ranges (select-options). Once you know that, you can fill your own ranges quickly and efficiently.



Inner Join to retrieve the Material Valuation Class

*
* Inner Join to retrieve the Material Valuation Class pointing to
* which General Ledger.
*
* Based on transaction OBYC - Inventory Posting - BSX
*
* If you use inner join to read data from several logically
* connected tables instead of nested Select statements.
* It will reduce your network load.
*
* Written by : SAP Basis, ABAP Programming and Other IMG Stuff
*
*
REPORT ZVALGL.

TABLES: MARA, "General Material Data
MAKT, "Material Descriptions
MBEW, "Material Valuation
SKAT, "G/L Account Master Record
T025T, "Valuation Class Descriptions
T030. "Standard Accounts Table

DATA: BEGIN OF WA,
BKLAS TYPE MBEW-BKLAS,
BKBEZ TYPE T025T-BKBEZ,
MTART TYPE MARA-MTART,
MATNR TYPE MARA-MATNR,
MAKTX TYPE MAKT-MAKTX,
END OF WA,
ITAB LIKE SORTED TABLE OF WA
WITH NON-UNIQUE KEY BKLAS MATNR.

SELECT-OPTIONS: PLANT FOR MBEW-BWKEY MEMORY ID PLT,
MATLTYPE FOR MARA-MTART MEMORY ID TYP,
MATERIAL FOR MBEW-MATNR MEMORY ID MAT,
CHARTACC FOR T030-KTOPL MEMORY ID KTO.

SELECT P~BKLAS
F~MATNR F~MTART
G~MAKTX
T~BKBEZ
INTO CORRESPONDING FIELDS OF TABLE ITAB
FROM ( ( ( ( MBEW AS P
INNER JOIN MARA AS F ON P~MATNR = F~MATNR )
INNER JOIN MAKT AS G ON P~MATNR = G~MATNR )
INNER JOIN T025T AS T ON P~BKLAS = T~BKLAS ) )
WHERE P~BWKEY IN PLANT
AND F~MTART IN MATLTYPE
AND P~MATNR IN MATERIAL
AND G~SPRAS = 'E'.

LOOP AT ITAB INTO WA.
CLEAR: T030, SKAT.
SELECT SINGLE * FROM T030 WHERE BKLAS = WA-BKLAS
AND KTOSL = 'BSX'.
SELECT SINGLE * FROM SKAT WHERE SAKNR = T030-KONTS
AND SPRAS = 'E'.
WRITE: / WA, T030-KONTS, SKAT-TXT20.
ENDLOOP.



How to used 3 tables for inner joins?


Inner joins using 3 tables


Try this :-

SELECT stpo~stlnr stpo~idnrk mast~matnr mara~mtart stpo~menge
INTO CORRESPONDING FIELDS OF TABLE zmat1 FROM mast
JOIN stpo ON stpo~stlnr = mast~stlnr
JOIN mara ON mara~matnr = mast~matnr
WHERE stpo~stlty = 'M' "AND stpo~idnrk IN s_matnr
AND mast~werks = 1000.

Here s_matnr is a select-options on the selection-screen.

Or this.


Code:


Select single Vbrk~Bukrs Vbrk~Kunrg Vbrk~Vbeln
Vbrk~Fkdat Vbrk~Bstnk_Vf Vbrk~Zterm
Tvzbt~Vtext
Vbak~Vbeln Vbak~Bstdk
Likp~Vbeln Likp~lfdat Likp~Lfuhr
into w_vbrk
from vbrk
inner join Tvzbt on Tvzbt~Zterm = Vbrk~Zterm and
Tvzbt~Spras = sy-langu
Inner join Vbfa as SalesLnk
on SalesLnk~vbeln = pu_vbeln and
SalesLnk~vbtyp_v = c_order
inner join Vbak on Vbak~Vbeln = SalesLnk~Vbelv
Inner join Vbfa as DeliveryLnk
on DeliveryLnk~vbeln = pu_vbeln and
DeliveryLnk~vbtyp_v = c_Delivery
inner join Likp on Likp~Vbeln = DeliveryLnk~Vbelv
where vbrk~vbeln = pu_Vbeln.


This code locates sales, delivery and payment terms info from a billing document number.

or

Here, this one also works fine :

select zfpcd~cadivi zfpcd~proforma zfpcd~factura zfpcd~aniofactura
zfpcd~montousd zfpcd~montoap zfpcd~ebeln zfpcd~inco1
zfpcd~lifnr lfa1~name1 zcdvs~status zfpcd~conint
into it_lista
from zfpcd inner join zcdvs
on zfpcd~ebeln = zcdvs~ebeln
and zfpcd~proforma = zcdvs~proforma
and zfpcd~lifnr = zcdvs~lifnr
inner join lfa1
on zfpcd~lifnr = lfa1~lifnr
where zcdvs~status = '04'.




Protect Selection/Parameters


An easy way of making a standard reports selection/parameters to be read-only/protected. (like an option NO-INPUT).

You can add a "Module Protect Output." module with code to the program, where it sets the screen-input = 0 as required, and add the line "Module Protect Output." to the PBO, and it works fine, until you re-generate the code and
this line is removed (the PBO PAI in SE51 screen 1000) as known, this code is also re-generated and any changes made will be ineffective.

If you tried using one of the PBO generated module names, it will says its does not exist, so if you generate it with the code, and run the program it will tell you "Module PBO_REPORT is already defined as a OUTPUT module".

The purpose: To calculate and set up the parameters in INITIALIZATION. You want to show them to the user, and use them in SELECTs, use them as Headings, but you want to stop the user from changing some of them.


The solution is as follows :


AT SELECTION-SCREEN OUTPUT.
PERFORM protect.
.
.
.
FORM protect.
LOOP at SCREEN
CASE screen-name.
WHEN 'UNAME' OR 'UNUMB' OR 'DESCR'. screen-input = 0.
WHEN 'XNAME' OR 'XNUMB' OR 'DESCX'. screen-input = 0.
ENDCASE.
ENDLOOP.
ENDFORM.


Difference Between Select Single and Select UpTo One Rows


According to SAP Performance course the SELECT UP TO 1 ROWS is faster than SELECT SINGLE because you are not using all the primary key fields.


select single is a construct designed to read database records with primary key. In the absence of the primary key, it might end up doing a sequential search, whereas the select up to 1 rows may assume that there is no primary key supplied and will try to find most suitable index.

The best way to find out is through sql trace or runtime analysis.


Use "select up to 1 rows" only if you are sure that all the records returned will have the same value for the field(s) you are interested in. If not, you will be reading only the first record which matches the criteria, but may be the second or the third record has the value you are looking for.


The System test result showed that the variant Single * takes less time than Up to 1 rows as there is an additional level for COUNT STOP KEY for SELECT ENDSELECT UP TO 1 ROWS.


The 'SELECT SINGLE' statement selects the first row in the database that it finds that fulfils the 'WHERE' clause If this results in multiple records then only the first one will be returned and therefore may not be unique.


Mainly: to read data from


The 'SELECT .... UP TO 1 ROWS' statement is subtly different. The database selects all of the relevant records that are defined by the WHERE clause, applies any aggregate, ordering or grouping functions to them and then returns the first record of the result set.


Mainly: to check if entries exist.



Select statement with inner join is taking forever

Following is the select stmt which is taking forever.

SELECT MKPF~BUDAT MKPF~CPUTM
MSEG~MATNR MSEG~WERKS MSEG~EBELN
MSEG~EBELP MSEG~ERFMG
INTO CORRESPONDING FIELDS OF TABLE
W_DTL_INVOICE
FROM MKPF INNER JOIN MSEG
ON MKPF~MBLNR = MSEG~MBLNR
AND MKPF~MJAHR = MSEG~MJAHR
WHERE MKPF~BUDAT > '20040721' AND
MSEG~BWART = '101' AND
MSEG~BUKRS = '1733'.

It does not have much records.
Can somebody let me know how to fine tune this statement.


I have gone through the same problem last year. This is the solution I made. My program spended more than an hour to select 5000 records from mkpf inner mseg(From a range of 100000 records) . Now it needs less than 15 seconds to perform the same task.

Try this changes

** in global data add these two hashed tables

data: begin of wa_mkpfmseg,
mblnr like mkpf-mblnr,
mjahr like mkpf-mjahr,
zeile like mseg-zeile,
bukrs like mseg-bukrs
bwart like mseg-bwart,
budat like mkpf-budat,
cputm like mkpf-cputm,
matnr like mseg-matnr,
werks like mseg-werks,
ebeln like mseg-ebeln,
ebelp like mseg-ebelp,
erfmg like mseg-erfmg,
end of wa_mkpfmseg.

data ht_mkpfmseg like hashed table of wa_mkpfmseg
with unique key mblnr mjahr zeile
with header line.

data: begin of wa_mkpfmsegSel,
budat like mkpf-budat,
cputm like mkpf-cputm,
matnr like mseg-matnr,
werks like mseg-werks,
ebeln like mseg-ebeln,
ebelp like mseg-ebelp,
erfmg like mseg-erfmg,
end of wa_mkpfmseg.


data ht_mkpfmsegSel like hashed table of wa_mkpfmsegSel
with unique key budat cputm matnr werks ebeln ebelp
with header line.

** change your select sentence to look like this:
select mkpf~mblnr
mkpf~mjahr
mseg~zeile
mseg~bukrs
mseg~bwart
MKPF~BUDAT MKPF~CPUTM
MSEG~MATNR MSEG~WERKS MSEG~EBELN
MSEG~EBELP MSEG~ERFMG
INTO TABLE ht_mkpfmseg
FROM MKPF INNER JOIN MSEG
ON mkpf~mandt = mseg~mandt
AND MKPF~MBLNR = MSEG~MBLNR
AND MKPF~MJAHR = MSEG~MJAHR
where mkpf~budat > '20040721'.

loop at ht_mkpfmseg.
check ht_mkpfmseg-bukrs = '1733' and ht_mkpfmseg-bwart = '101'
read table ht_mkpfmsegsel with table key
budat = ht_mkpfmseg-budat
cputm = ht_mkpfmseg-cputm

matnr = ht_mkpfmseg-matnr
werks = ht_mkpfmseg-werks

ebeln = ht_mkpfmseg-ebeln
ebelp = ht_mkpfmseg-ebelp
transporting erfmg.
if sy-subrc <> 0.
move-corresponding ht_mkpfmseg to ht_mkpfmsegsel.
insert table ht_mkpfmsegsel.
else.
ht_mkpfmsegSel-budat = ht_mkpfmseg-budat.
ht_mkpfmsegSel-cputm = ht_mkpfmseg-cputm.
ht_mkpfmsegSel-matnr = ht_mkpfmseg-matnr,
ht_mkpfmsegSel-werks = ht_mkpfmseg-werks.
ht_mkpfmsegSel-ebeln = ht_mkpfmseg-ebeln.
ht_mkpfmsegSel-ebelp = ht_mkpfmseg-ebelp.
add ht_mkpfmseg-erfmg to ht_mkpfmsegSel-erfmg.
modify table ht_mkpfmsegSel transporting erfmg.
endif.
endloop.
" at this point ht_mkpfmsegSel has the data collected that you want.
loop at ht_mkpfmsegSel.
.... Here put the code between your select ... endselect.
endloop.


This should run faster because of the next reasons:


1. you're not distracting the sql optimizer when it analizes the sql where clause. It makes use of the first index declared on mkpf (budat-mblnr)-


2. the data is selected into a hashed table which are the faster access tables provided by SAP from 4.0 up to 4.6c (I don't know about 4.7)


3. As the select isn't restricting bukrs and bwart (but there is a good reason on this: it's faster to read 100000 records into a hashed table and then filter the 80000 unwanted than to select the 20000 records via non index fields in the where clause. I tested it in my own programs).




How can we give dynamic table name in select statement?


Dynamic Select Statement

check this code...

*-----

For dynamic table name....

REPORT demo_select_dynamic_database .

DATA wa TYPE scarr.
DATA name(10) TYPE c VALUE 'SCARR'.

SELECT *
INTO wa
FROM (name) CLIENT SPECIFIED
WHERE mandt = '000'.
WRITE: / wa-carrid, wa-carrname.
ENDSELECT.

*-----

For dynamic field list

REPORT demo_select_dynamic_columns .

DATA: itab TYPE STANDARD TABLE OF spfli,
wa LIKE LINE OF itab.
DATA: line(72) TYPE c,

list LIKE TABLE OF line(72).

line = ' CITYFROM CITYTO '.

APPEND line TO list.

SELECT DISTINCT (list)
INTO CORRESPONDING FIELDS OF TABLE itab
FROM spfli.

IF sy-subrc EQ 0.

LOOP AT itab INTO wa.
WRITE: / wa-cityfrom, wa-cityto.
ENDLOOP.

ENDIF.



Several nested INNER JOIN statements can be inefficient


"Using several nested INNER JOIN statements can be inefficient and cause time out if the tables become too big in the future."


Joins here (in ABAP) are not those Native SQL Joins. If you are talking about the Core RDBMS, which mean Oracle or SQL Server, then Undoubtedly Joins are the best.


In ABAP, these joins are first split by the ABAP processor and then sent to the database, with the increase in DATA in production system, these joins tend to give way if your database keeps growing larger and larger.


You should rather used "FOR ALL ENTRIES IN" (Tabular conditions), which is a much effecient way as far as performance is concerned.


For example :


DATA: BEGIN OF LINE,
CARRID TYPE SPFLI-CARRID,
CONNID TYPE SPFLI-CONNID,
CITYFROM TYPE SPFLI-CITYFROM,
CITYTO TYPE SPFLI-CITYTO,
END OF LINE,
ITAB LIKE TABLE OF LINE.

LINE-CITYFROM = 'FRANKFURT'.
LINE-CITYTO = 'BERLIN'.
APPEND LINE TO ITAB.

LINE-CITYFROM = 'NEW YORK'.
LINE-CITYTO = 'SAN FRANCISCO'.
APPEND LINE TO ITAB.

SELECT CARRID CONNID CITYFROM CITYTO
INTO CORRESPONDING FIELDS OF LINE
FROM SPFLI
FOR ALL ENTRIES IN ITAB
WHERE CITYFROM = ITAB-CITYFROM AND CITYTO = ITAB-CITYTO.

WRITE: / LINE-CARRID, LINE-CONNID, LINE-CITYFROM, LINE-CITYTO.

ENDSELECT.




Performance tuning for Data Selection Statement

For all entries

The for all entries creates a where clause, where all the entries in the driver table are combined with OR. If the number of
entries in the driver table is larger than rsdb/max_blocking_factor, several similar SQL statements are executed to limit the
length of the WHERE clause.


The plus

  • Large amount of data
  • Mixing processing and reading of data
  • Fast internal reprocessing of data
  • Fast

The Minus
  • Difficult to program/understand
  • Memory could be critical (use FREE or PACKAGE size)

Some steps that might make FOR ALL ENTRIES more efficient:
  • Removing duplicates from the the driver table
  • Sorting the driver table
    If possible, convert the data in the driver table to ranges so a BETWEEN statement is used instead of and OR statement:
    FOR ALL ENTRIES IN i_tab
    WHERE mykey >= i_tab-low and
    mykey <= i_tab-high.


Nested selects


The plus:
  • Small amount of data
  • Mixing processing and reading of data
  • Easy to code - and understand

The minus:
  • Large amount of data
  • when mixed processing isn’t needed
  • Performance killer no. 1


Select using JOINS


The plus
  • Very large amount of data
  • Similar to Nested selects - when the accesses are planned by the programmer
  • In some cases the fastest
  • Not so memory critical

The minus
  • Very difficult to program/understand
  • Mixing processing and reading of data not possible


Use the selection criteria

SELECT * FROM SBOOK.                  
CHECK: SBOOK-CARRID = 'LH' AND
SBOOK-CONNID = '0400'.
ENDSELECT.
SELECT * FROM SBOOK                    
WHERE CARRID = 'LH' AND
CONNID = '0400'.
ENDSELECT.


Use the aggregated functions

C4A = '000'.             
SELECT * FROM T100
WHERE SPRSL = 'D' AND
ARBGB = '00'.
CHECK: T100-MSGNR > C4A.
C4A = T100-MSGNR.
ENDSELECT.

SELECT MAX( MSGNR ) FROM T100 INTO C4A
WHERE SPRSL = 'D' AND
ARBGB = '00'.


Select with view

SELECT * FROM DD01L                   
WHERE DOMNAME LIKE 'CHAR%'
AND AS4LOCAL = 'A'.
SELECT SINGLE * FROM DD01T
WHERE DOMNAME = DD01L-DOMNAME
AND AS4LOCAL = 'A'
AND AS4VERS = DD01L-AS4VERS
AND DDLANGUAGE = SY-LANGU.
ENDSELECT.

SELECT * FROM DD01V
WHERE DOMNAME LIKE 'CHAR%'
AND DDLANGUAGE = SY-LANGU.
ENDSELECT.


Select with index support

SELECT * FROM T100           
WHERE ARBGB = '00'
AND MSGNR = '999'.
ENDSELECT.

SELECT * FROM T002.
SELECT * FROM T100
WHERE SPRSL = T002-SPRAS
AND ARBGB = '00'
AND MSGNR = '999'.
ENDSELECT.
ENDSELECT.


Select … Into table

REFRESH X006.                
SELECT * FROM T006 INTO X006.
APPEND X006.
ENDSELECT

SELECT * FROM T006 INTO TABLE X006.

Select with selection list

SELECT * FROM DD01L             
WHERE DOMNAME LIKE 'CHAR%'
AND AS4LOCAL = 'A'.
ENDSELECT

SELECT DOMNAME FROM DD01L
INTO DD01L-DOMNAME
WHERE DOMNAME LIKE 'CHAR%'
AND AS4LOCAL = 'A'.
ENDSELECT


Key access to multiple lines

LOOP AT TAB.         
CHECK TAB-K = KVAL.
" ...
ENDLOOP.

LOOP AT TAB WHERE K = KVAL.
" ...
ENDLOOP.


Copying internal tables

REFRESH TAB_DEST.             
LOOP AT TAB_SRC INTO TAB_DEST.
APPEND TAB_DEST.
ENDLOOP.

TAB_DEST[] = TAB_SRC[].


Modifying a set of lines

LOOP AT TAB.            
IF TAB-FLAG IS INITIAL.
TAB-FLAG = 'X'.
ENDIF.
MODIFY TAB.
ENDLOOP.

TAB-FLAG = 'X'.
MODIFY TAB TRANSPORTING FLAG
WHERE FLAG IS INITIAL.


Deleting a sequence of lines

DO 101 TIMES.              
DELETE TAB_DEST INDEX 450.
ENDDO.

DELETE TAB_DEST FROM 450 TO 550.

Linear search vs. binary

READ TABLE TAB WITH KEY K = 'X'.

READ TABLE TAB WITH KEY K = 'X' BINARY SEARCH.


Comparison of internal tables

DESCRIBE TABLE: TAB1 LINES L1,     
TAB2 LINES L2.

IF L1 <> L2.
TAB_DIFFERENT = 'X'.
ELSE.
TAB_DIFFERENT = SPACE.
LOOP AT TAB1.
READ TABLE TAB2 INDEX SY-TABIX.
IF TAB1 <> TAB2.
TAB_DIFFERENT = 'X'. EXIT.
ENDIF.
ENDLOOP.
ENDIF.

IF TAB_DIFFERENT = SPACE.
" ...
ENDIF.

IF TAB1[] = TAB2[].
" ...
ENDIF.


Modify selected components

LOOP AT TAB.          
TAB-DATE = SY-DATUM.
MODIFY TAB.
ENDLOOP.

WA-DATE = SY-DATUM.
LOOP AT TAB.
MODIFY TAB FROM WA TRANSPORTING DATE.
ENDLOOP.


Appending two internal tables

LOOP AT TAB_SRC.             
APPEND TAB_SRC TO TAB_DEST.
ENDLOOP

APPEND LINES OF TAB_SRC TO TAB_DEST.


Deleting a set of lines

LOOP AT TAB_DEST WHERE K = KVAL.
DELETE TAB_DEST.
ENDLOOP

DELETE TAB_DEST WHERE K = KVAL.

Tools available in SAP to pin-point a performance problem

    The runtime analysis (SE30)
    SQL Trace (ST05)
    Tips and Tricks tool 
    The performance database


Optimizing the load of the database


Using table buffering

Using buffered tables improves the performance considerably. Note that in some cases a stament can not be used with a buffered table, so when using these staments the buffer will be bypassed. These staments are:
  • Select DISTINCT
  • ORDER BY / GROUP BY / HAVING clause
  • Any WHERE clasuse that contains a subquery or IS NULL expression
  • JOIN s
  • A SELECT... FOR UPDATE
If you wnat to explicitly bypass the bufer, use the BYPASS BUFFER addition to the SELECT clause.


Use the ABAP SORT Clause Instead of ORDER BY

The ORDER BY clause is executed on the database server while the ABAP SORT statement is executed on the application server. The datbase server will usually be the bottleneck, so sometimes it is better to move thje sort from the datsbase server to the application server.

If you are not sorting by the primary key ( E.g. using the ORDER BY PRIMARY key statement) but are sorting by another key, it could be better to use the ABAP SORT stament to sort the data in an internal table. Note however that for very large result sets it might not be a feasible solution and you would want to let the datbase server sort it.


Avoid ther SELECT DISTINCT Statement

As with the ORDER BY clause it could be better to avoid using SELECT DISTINCT, if some of the fields are not part of an index. Instead use ABAP SORT + DELETE ADJACENT DUPLICATES on an internal table, to delete duplciate rows.



What's the purpose of using PACKAGE SIZE in select statement?

Package size can be used if you for example only want to finish processing a limited amount of data at a time due to lack of memory.


The example below read 50 records at a time from VBAK into an internal table, and selects the corresponding entries from vbap into an internal table. Then the two internal tables can be processed, and the next 50 records from VBAk can be read. Remember to reinitialize tha tables before the next read.

REPORT z_test.

TYPES:
BEGIN OF t_vbak,
vbeln LIKE vbak-vbeln,
erdat LIKE vbak-erdat,
END OF t_vbak,

BEGIN OF t_vbap,
posnr LIKE vbap-posnr,
matnr LIKE vbap-matnr,
meins LIKE vbap-meins,
END OF t_vbap,

BEGIN OF t_report,
vbeln LIKE vbak-vbeln,
erdat LIKE vbak-erdat,
posnr LIKE vbap-posnr,
matnr LIKE vbap-matnr,
meins LIKE vbap-meins,
END OF t_report.

DATA:
li_vbak TYPE t_vbak OCCURS 0,
l_vbak TYPE t_vbak,
li_vbap TYPE t_vbap OCCURS 0,
l_vbap TYPE t_vbap,
li_report TYPE t_report OCCURS 0,
l_report TYPE t_report.

START-OF-SELECTION.
SELECT vbeln erdat
FROM vbak
INTO TABLE li_vbak PACKAGE SIZE 50.
SELECT posnr matnr meins
FROM vbap
INTO TABLE li_vbap
FOR ALL ENTRIES IN li_vbak
WHERE vbeln = li_vbak-vbeln.
IF sy-subrc = 0.
* Now you have the two internal tables li_vbak and li_vbap filled
* with data.
* Do something with the data - remember to reinitialize internal
* tables
ENDIF.
ENDSELECT.

*-- End of Program




Usage of 'for all entries' in Select Statement


FORM data_retrieval.

DATA: ld_color(1) TYPE c.

DATA: BEGIN OF T_VBAP OCCURS 0,
VBELN LIKE VBAP-VBELN,
MATNR LIKE VBAP-MATNR,
POSNR LIKE VBAP-POSNR,
END OF T_VBAP.

DATA: BEGIN OF T_VBFA OCCURS 0,
VBELV LIKE VBFA-VBELV,
VBELN LIKE VBFA-VBELN,
VBTYP_N LIKE VBFA-VBTYP_N,

END OF T_VBFA.

DATA: BEGIN OF T_VBAK OCCURS 0,
VBELN LIKE VBAK-VBELN,
IHREZ LIKE VBAK-IHREZ,
END OF T_VBAK.

DATA: BEGIN OF T_KNA1 OCCURS 0,
KUNNR LIKE KNA1-KUNNR,
NAME1 LIKE KNA1-NAME1,
END OF T_KNA1.

DATA: BEGIN OF T_MAKT OCCURS 0,
MATNR LIKE MAKT-MATNR,
MAKTX LIKE MAKT-MAKTX,
END OF T_MAKT.

SELECT likp~vbeln likp~lifex likp~bldat likp~wadat likp~wadat_ist likp~kodat likp~lfart
likp~kunnr likp~vstel lips~posnv lips~lfimg lips~vrkme lips~lgmng lips~meins
lips~werks lips~lgort lips~charg lips~vbelv lips~posnr lips~matnr
lips~vbeln LIPS~VGBEL LIPS~VGPOS vbup~kosta vbup~wbsta vbup~posnr vbup~vbeln
* VBAK~IHREZ VBAK~VBELN VBAP~VBELN
INTO CORRESPONDING FIELDS OF TABLE it_itab
FROM ( likp
INNER JOIN lips
ON lips~vbeln = likp~vbeln
INNER JOIN vbup
ON vbup~posnr = lips~posnr
and VBUP~VBELN = LIPS~VBELN )
* left outer join VBAK
* on VBAK~VBELN = LIPS~VGBEL
* inner join VBAP
* on VBAP~VBELN = VBAK~VBELN )
WHERE likp~vbeln IN so_vbeln
AND likp~lifex IN so_lifex
AND likp~lfart IN so_lfart
AND likp~kunnr IN so_kunnr
AND likp~vstel IN so_vstel
AND likp~bldat IN so_bldat
AND likp~wadat_ist IN so_wadat
AND vbup~kosta IN so_kosta
AND vbup~wbsta IN so_wbsta
AND LIPS~LFIMG NE 0.

SELECT VBELN IHREZ INTO TABLE T_VBAK
FROM VBAK
FOR ALL ENTRIES IN IT_ITAB
WHERE VBELN = IT_ITAB-VGBEL.
* APPEND T_VBAK.
* ENDSELECT.

SELECT VBELN MATNR POSNR INTO TABLE T_VBAP
FROM VBAP
FOR ALL ENTRIES IN IT_ITAB
WHERE VBELN = IT_ITAB-VGBEL AND
MATNR = IT_ITAB-MATNR AND
POSNR = IT_ITAB-VGPOS.
* APPEND T_VBAP.
* ENDSELECT.

SELECT VBELV VBELN VBTYP_N INTO TABLE T_VBFA
FROM VBFA
FOR ALL ENTRIES IN IT_ITAB
WHERE VBELV = IT_ITAB-VBELN AND
VBTYP_N = 'M' .

SELECT KUNNR NAME1 INTO TABLE T_KNA1
FROM KNA1
FOR ALL ENTRIES IN IT_ITAB
WHERE KUNNR = IT_ITAB-KUNNR.
* APPEND T_KNA1.
* ENDSELECT.

SELECT MATNR MAKTX INTO TABLE T_MAKT
FROM MAKT
FOR ALL ENTRIES IN IT_ITAB
WHERE MATNR = IT_ITAB-MATNR.
* APPEND T_MAKT.
* ENDSELECT.


*Populate field with color attributes

LOOP AT it_itab INTO wa_ITAB.

* Populate color variable with colour properties

* Char 1 = C (This is a color property)

* Char 2 = 3 (Color codes: 1 - 7)

* Char 3 = Intensified on/off ( 1 or 0 )

* Char 4 = Inverse display on/off ( 1 or 0 )

* i.e. wa_ekko-line_color = 'C410'
REFRESH color.
colourize 'VBELN' 0. " .
WA_ITAB-farbe = color[].


ld_color = ld_color + 1.

* Only 7 colours so need to reset color value

IF ld_color = 3. "8

ld_color = 1.

ENDIF.

CONCATENATE 'C' ld_color '10' INTO wa_ITAB-line_color.
WA_ITAB-NAME1 = ''.
WA_ITAB-MAKTX = ''.
WA_ITAB-IHREZ = ''.
WA_ITAB-VBELV = ''.
READ TABLE T_KNA1 WITH KEY KUNNR = WA_ITAB-KUNNR.
IF SY-SUBRC = 0.
WA_ITAB-NAME1 = T_KNA1-NAME1.
ENDIF.
READ TABLE T_MAKT WITH KEY MATNR = WA_ITAB-MATNR.
IF SY-SUBRC = 0.
WA_ITAB-MAKTX = T_MAKT-MAKTX.
ENDIF.
READ TABLE T_VBAK WITH KEY VBELN = WA_ITAB-VGBEL.
IF SY-SUBRC = 0.
WA_ITAB-IHREZ = T_VBAK-IHREZ.
ENDIF.
READ TABLE T_VBFA WITH KEY VBELV = WA_ITAB-VBELN.
IF SY-SUBRC = 0.
WA_ITAB-VBELVA = T_VBFA-VBELN.
ENDIF.
* READ TABLE T_VBAP WITH KEY VBELN = WA_ITAB-VGBEL
* POSNR = WA_ITAB-VGPOS
* MATNR = WA_ITAB-MATNR.
* IF SY-SUBRC = 0.
* WA_ITAB-IHREZ = T_VBAK-IHREZ.
* ENDIF.



* wa_ekko-line_color = 'C410'.

MODIFY it_itab FROM wa_itab.

ENDLOOP.

ENDFORM. " data_retrieval

Sunday, October 7, 2007



Making a Java Editor in ABAP and compiling it


It have two reports:

zjavacreate
zjavamodify

ZJAVACREATE:

REPORT zjavacreate message-id zmsgnew.

*************************Creation of Internal table*******************
DATA: BEGIN OF ti_record OCCURS 200,
Line(250),
END OF ti_record.
DATA: BEGIN OF ti_rec OCCURS 200,
Line(250),
END OF ti_rec.

******************************Selection screen*************************
selection-screen begin of block b1 with frame .
Parameters create radiobutton group g1.
PARAMETERS: JavaName(30) lower case.
parameters modify radiobutton group g1.
selection-screen end of block b1.

*******************Calling the java program creation page***************
at selection-screen.
if CREATE = 'X'.
if javaname is not initial.
refresh ti_record[].
concatenate 'public class' javaname into ti_record-line separated by space.

concatenate ti_record-line '{' into ti_record-line separated by space.
Append ti_record.
ti_record-line = 'public static void main(String []args){'.
Append ti_record.
ti_record-line ='//enter ur code here'.
append ti_record.
ti_record-line ='}'.
Append ti_record.
ti_record-line ='}'.
Append ti_record.

EDITOR-CALL FOR ti_record .
else.
Message e001.

endif.
***************************Saving the java program*********************
data tfile type string.

concatenate 'D:\Programs\' javaname '.java' into tfile.
CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
FILENAME = tfile
FILETYPE = 'ASC'
TABLES
DATA_TAB = ti_record.
endif.
data new(15).
if MODIFY = 'X'.
new = 'ZJAVAMODIFY1'.
CALL TRANSACTION NEW.
endif.
************************************************************************
ZJAVAMODIFY:

REPORT zjavamodify.
***********************selection screen.*********************
selection-screen begin of block b1 with frame .
Parameters compile radiobutton group g1.
Parameters modify radiobutton group g1.
Parameters execute radiobutton group g1.
PARAMETER : FILE(100) lower case.
selection-screen end of block b1.
DATA: BEGIN OF TI_RECORD OCCURS 1,
LINE(200),
END OF TI_RECORD.
data: st1(30),st2(30).

AT SELECTION-SCREEN ON VALUE-REQUEST FOR FILE.
CALL FUNCTION 'WS_FILENAME_GET'
EXPORTING
* DEF_FILENAME = ' '
DEF_PATH = '*.*'
* MASK = ' '
* MODE = ' '
* TITLE = ' '
IMPORTING
FILENAME = FILE
* RC =
.

End-of-selection.

********************************************************************
*****************************MODIFY*********************************
if modify = 'X'.
data: TXT_FILE1 TYPE STRING .
txt_file1 = file.
**************FM GUI_UPLOAD

CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
FILENAME = txt_file1
TABLES
DATA_TAB = ti_recORD[].
**********End FM GUI_UPLOAD
EDITOR-CALL FOR ti_record .
**************FM GUI_UPLOAD

CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
FILENAME = txt_file1
FILETYPE = 'ASC'
TABLES
DATA_TAB = ti_record.
**********End FM GUI_UPLOAD
endif.

********************end of modify********************

*******************BAT file for compilation n
execution.****************
if compile = 'X'.
DATA: begin of itab_bat_create occurs 0,
row(500) type c,
end of itab_bat_create.

data:comp_join1(250).
concatenate 'java' 'jCompiler' file into comp_join1
separated
by space.
itab_bat_create-row = 'c:'.
append itab_bat_create.
itab_bat_create-row = 'cd Documents and Settings\127740'.
append itab_bat_create.
itab_bat_create-row = comp_join1.
append itab_bat_create.

********FM GUI_DOWNLOAD
data: st type string.
st = 'C:\Documents and Settings\127740\compile_java.bat'.
call function 'GUI_DOWNLOAD'
EXPORTING
filename = st
filetype = 'ASC'
TABLES
data_tab = itab_bat_create[]
EXCEPTIONS
file_open_error = 1
file_write_error = 2
others = 3.
********end FM GUI_DOWNLOAD
*****FM dvsvas_doc_ws_execute_50
CALL FUNCTION 'DSVAS_DOC_WS_EXECUTE_50'
EXPORTING
PROGRAM = 'C:\Documents and Settings\127740\compile_java.bat'.
*****end FM dvsvas_doc_ws_execute_50
endif.
************************end of compile********************************

*********************************************************************
*************************************** output***********************
if execute = 'X'.
data: TXT_FILE3 TYPE STRING .
split File AT '.java' into: st1 st2 .
concatenate st1 'error.txt' into TXT_FILE3.
**************FM GUI_UPLOAD
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
FILENAME = txt_file3
TABLES
DATA_TAB = ti_recORD[].
**********End FM GUI_UPLOAD
if not ti_record[] is initial.
loop at ti_record.
write:/ ti_record.
endloop.
else.
data: TXT_FILE4 TYPE STRING .
split File AT '.java' into: st1 st2 .
concatenate st1 'output.txt' into TXT_FILE4.
**************FM GUI_UPLOAD
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
FILENAME = TXT_FILE4
TABLES
DATA_TAB = ti_recORD[].
**********End FM GUI_UPLOAD
loop at ti_record.
write:/ ti_record.
endloop.
endif.
endif.
************************end of
output****************************************

In ZJAVACREATE we have used the transaction new which is nothing but the transaction code for zjavamodify.


Program to Test Line Selection & Scrolling within Document


I have generated a list containing say 20 lines, I need to display a checkbox on each line. Based on the user selection on the checkbox I need to capture the lines choosed by the user. How to do this?

*Program to Test Line Selection & Scrolling within Document:Rajiv
* Creating Text file of selected data
* carton selection
*-----------------------------------------------------------
REPORT ZRJ001
LINE-SIZE 120 LINE-COUNT 60 NO STANDARD PAGE HEADING.
*------------------------------------------------
* Defining Tables
*-----------------------------------------------
TABLES : ZPACK,ZTRN.

*------------------------------------------------
* Defining Internal Tables
*-----------------------------------------------
*DATA : IZPACK LIKE ZPACK OCCURS 0 WITH HEADER LINE.
DATA : BEGIN OF IZPACK OCCURS 0,
ZPKSLIP_NO LIKE ZPACK-ZPKSLIP_NO,
ZBATCH_NO LIKE ZPACK-ZBATCH_NO,
ZCARTON_NO LIKE ZPACK-ZCARTON_NO,
ZDATE LIKE ZPACK-ZDATE,
ZMATNR LIKE ZPACK-ZMATNR,
ZGROSS_WT LIKE ZPACK-ZGROSS_WT,
ZTARE_WT LIKE ZPACK-ZTARE_WT,
ZNET_WT LIKE ZPACK-ZNET_WT,
ZGRADE LIKE ZPACK-ZGRADE,
ZTRNTYP LIKE ZPACK-ZTRN_TYP,
END OF IZPACK.
*For Screen Command
DATA : BEGIN OF SCR1_OK_CODE OCCURS 0,
OK_CODE LIKE SY-UCOMM,
END OF SCR1_OK_CODE.

DATA : BEGIN OF SCR2_OK_CODE OCCURS 0,
OK_CODE LIKE SY-UCOMM,
END OF SCR2_OK_CODE.
*For Text file data
DATA : BEGIN OF ISEL OCCURS 0,
ZBATCH_NO LIKE ZPACK-ZBATCH_NO,
ZCARTON_NO LIKE ZPACK-ZCARTON_NO,
ZDATE LIKE ZPACK-ZDATE,
ZMATNR LIKE ZPACK-ZMATNR,
ZGROSS_WT LIKE ZPACK-ZGROSS_WT,
ZTARE_WT LIKE ZPACK-ZTARE_WT,
ZNET_WT LIKE ZPACK-ZNET_WT,
END OF ISEL.


*------------------------------------------------
* variables / constants
*-----------------------------------------------
DATA: MHD1 LIKE SY-TITLE,
MHD2 LIKE SY-TITLE,
MHD3 LIKE SY-TITLE,
CH(1) TYPE C VALUE '|',
CHK_BOX,
CHK_BOX_VAL,
LINE_NO LIKE SY-LINNO,
PAGE_NO LIKE SY-PAGNO,
SEL_CART TYPE I,
IZPACK_LINE TYPE I,
NEW_SCREEN,
SRNO TYPE I.
SELECTION-SCREEN BEGIN OF BLOCK B1 WITH FRAME TITLE TEXT-001.
SELECT-OPTIONS: ZSHIP_PT FOR ZPACK-ZSHIP_PT NO-EXTENSION NO INTERVALS
OBLIGATORY DEFAULT '5102'.
* ZMERGE FOR ZPACK-ZMERGE_NO. "Merge No.
SELECTION-SCREEN END OF BLOCK B1.

AT SELECTION-SCREEN.
IF SY-UCOMM NE '1'. "Multiple Selection
IF ZSHIP_PT IS INITIAL.
MESSAGE E055(00).
ENDIF.
* IF ZMERGE IS INITIAL.
SELECT * FROM ZPACK INTO CORRESPONDING FIELDS OF TABLE IZPACK
WHERE ZSHIP_PT IN ZSHIP_PT.
* ELSE.
* SELECT * FROM ZPACK INTO CORRESPONDING FIELDS OF TABLE IZPACK
* WHERE ZSHIP_PT IN ZSHIP_PT AND ZMERGE_NO IN ZMERGE.
* ENDIF.
IF SY-SUBRC NE 0.
MESSAGE E058(00) WITH ZSHIP_PT.
ENDIF.
ENDIF.
*At Line Selection
*-----------------
AT LINE-SELECTION.
PERFORM SELECT_CURRENT_LINE.

*Top of Page Operation
*---------------------
TOP-OF-PAGE.
MHD1 = 'WELSPUN SYNTEX LIMITED'.
MHD2 = 'Data Selection from Displayed Document.'.
MHD3 = 'Select Challan to Make selected List'.
PERFORM DATA_HEADER.
SET LEFT SCROLL-BOUNDARY COLUMN 15.

*User Command Choosen
*---------------------
AT USER-COMMAND.
CASE SY-UCOMM.
WHEN 'LEFT'.
SCROLL LIST LEFT.
WHEN 'RIGH'.
SCROLL LIST RIGHT.
WHEN 'TOP'.
SCROLL LIST TO FIRST PAGE.
WHEN 'BOTT'.
SCROLL LIST TO LAST PAGE.
WHEN 'PREV'.
SCROLL LIST BACKWARD.
WHEN 'NEXT'.
SCROLL LIST FORWARD.
WHEN 'SELA'.
PERFORM SELECT_DESELECT_ALL USING 'X'.
WHEN 'SELD'.
PERFORM SELECT_DESELECT_ALL USING 'SPACE'.
WHEN 'SELC'.
PERFORM SELECT_CURRENT_LINE.
WHEN 'CONT'.
PERFORM GENERATE_INSPECTION_LIST USING 'X'.
WHEN 'LIST'.
PERFORM GENERATE_INSPECTION_LIST USING SPACE.
WHEN 'FILE'.
PERFORM GENERATE_INSPECTION_LIST USING 'Y'.
ENDCASE.

* SCROLL LIST TO PAGE pag.
* SCROLL LIST TO COLUMN col.

START-OF-SELECTION.
PERFORM LIST_OK_CODE.
SET PF-STATUS 'CARTLIST' EXCLUDING SCR2_OK_CODE.
PERFORM SELECT_DATA.
PERFORM LIST_DATA.

END-OF-SELECTION.

*&---------------------------------------------------------------------*
*& Form LIST_OK_CODE
*&---------------------------------------------------------------------*
FORM LIST_OK_CODE. " Only for EXCLUDING OPTION
APPEND 'LIST' TO SCR1_OK_CODE.
APPEND 'SELA' TO SCR1_OK_CODE.
APPEND 'SELD' TO SCR1_OK_CODE.
APPEND 'SELC' TO SCR1_OK_CODE.
APPEND 'CONT' TO SCR1_OK_CODE.
APPEND 'FILE' TO SCR1_OK_CODE.
APPEND 'LEFT' TO SCR2_OK_CODE.
APPEND 'RIGH' TO SCR2_OK_CODE.
APPEND 'TOP' TO SCR2_OK_CODE.
APPEND 'BOTT' TO SCR2_OK_CODE.
APPEND 'PREV' TO SCR2_OK_CODE.
APPEND 'NEXT' TO SCR2_OK_CODE.
ENDFORM. " LIST_OK_CODE

*&---------------------------------------------------------------------*
*& Form SELECT_DATA
*&---------------------------------------------------------------------*
FORM SELECT_DATA.
*Data already selected when checking.
ENDFORM. " SELECT_DATA

*&---------------------------------------------------------------------*
*& Form LIST_DATA
*&---------------------------------------------------------------------*
FORM LIST_DATA.
SORT IZPACK BY ZPKSLIP_NO ZBATCH_NO.
LOOP AT IZPACK.
* AT NEW ZPKSLIP_NO.
* FORMAT COLOR 5 INVERSE.
* WRITE: /02 CHK_BOX AS CHECKBOX, 'Challan No :' COLOR 6
* INTENSIFIED, IZPACK-ZPKSLIP_NO hotspot on.
* FORMAT RESET.
* ENDAT.
FORMAT COLOR 1 INVERSE.
WRITE:/ CHK_BOX AS CHECKBOX.
WRITE: CH NO-GAP ,(13) IZPACK-ZCARTON_NO UNDER 'Carton No.' NO-GAP.
WRITE: CH NO-GAP ,(10) IZPACK-ZDATE UNDER 'Packing Date' NO-GAP.
WRITE: CH NO-GAP ,(10) IZPACK-ZGROSS_WT UNDER 'Gross Qty.' NO-GAP.
WRITE: CH NO-GAP ,(10) IZPACK-ZTARE_WT UNDER 'Tare Qty.' NO-GAP.
WRITE: CH NO-GAP ,(10) IZPACK-ZNET_WT UNDER 'Net Qty.' NO-GAP.
WRITE: CH NO-GAP ,(18) IZPACK-ZMATNR UNDER 'Material No.' NO-GAP.
WRITE: CH NO-GAP ,(12) IZPACK-ZBATCH_NO UNDER 'Lot No.' NO-GAP.
WRITE: CH NO-GAP ,(5) IZPACK-ZGRADE UNDER 'Grade' NO-GAP.
WRITE: CH NO-GAP ,(5) IZPACK-ZTRNTYP UNDER 'Type' NO-GAP.
WRITE: '|'.
FORMAT RESET.

ENDLOOP.
ENDFORM. " LIST_DATA

*&---------------------------------------------------------------------*
*& Form DATA_HEADER
*&---------------------------------------------------------------------*
FORM DATA_HEADER.
FORMAT COLOR COL_GROUP.
CALL FUNCTION 'Z_YHEAD_PRINT'
EXPORTING
TITLE1 = MHD1
TITLE2 = MHD2
TITLE3 = MHD3
COLOR = 'X'
EXCEPTIONS
OTHERS = 1.
FORMAT RESET.
FORMAT COLOR COL_HEADING.
WRITE :/02 'Carton No.',
17 'Packing Date',
30 'Gross Qty.',
45 'Tare Qty.',
60 'Net Qty.',
75 'Material No.',
95 'Lot No.',
105 'Grade',
112 'Type'.
ULINE.
FORMAT RESET.
ENDFORM. " DATA_HEADER

*&---------------------------------------------------------------------*
*& Form SELECT_CURRENT_LINE
*&---------------------------------------------------------------------*
FORM SELECT_CURRENT_LINE.
READ CURRENT LINE FIELD VALUE CHK_BOX INTO CHK_BOX_VAL.
IF CHK_BOX_VAL IS INITIAL.
CHK_BOX_VAL = 'X'.
ELSE.
CHK_BOX_VAL = SPACE.
ENDIF.
MODIFY CURRENT LINE FIELD VALUE CHK_BOX FROM CHK_BOX_VAL.

ENDFORM. " SELECT_CURRENT_LINE

*&---------------------------------------------------------------------*
*& Form SELECT_DESELECT_ALL
*&---------------------------------------------------------------------*
* -->P_0245 text
*----------------------------------------------------------------------*
*FORM SELECT_DESELECT_ALL USING VALUE(P_0245).
FORM SELECT_DESELECT_ALL USING P_VALUE.
LINE_NO = 8.
PAGE_NO = 1.
DO.
IF LINE_NO GT SY-LINCT.
LINE_NO = 8.
ADD 1 TO PAGE_NO.
ENDIF.
READ LINE LINE_NO OF PAGE PAGE_NO.
MODIFY LINE LINE_NO OF PAGE PAGE_NO
FIELD VALUE CHK_BOX FROM P_VALUE.
IF SY-SUBRC NE 0.
EXIT.
ENDIF.
ADD 1 TO LINE_NO.
ENDDO.

ENDFORM. " SELECT_DESELECT_ALL

*&---------------------------------------------------------------------*
*& Form GENERATE_INSPECTION_LIST
*&---------------------------------------------------------------------*
FORM GENERATE_INSPECTION_LIST USING P_CHECK.
LINE_NO = 8.
PAGE_NO = 1.
CLEAR:NEW_SCREEN,SRNO,SEL_CART.
DO.
IF LINE_NO GT SY-LINCT.
LINE_NO = 8.
ADD 1 TO PAGE_NO.
ENDIF.
READ LINE LINE_NO OF PAGE PAGE_NO FIELD
VALUE CHK_BOX INTO CHK_BOX_VAL.
IF SY-SUBRC EQ 0.
IF CHK_BOX_VAL = 'X'.
ADD 1 TO SEL_CART.
IF P_CHECK EQ ' '. " Only Checking
PERFORM CREATE_LIST.
ENDIF.
IF P_CHECK = 'Y'. "Replace data to table ISEL for text file
MOVE : IZPACK-ZBATCH_NO TO ISEL-ZBATCH_NO,
IZPACK-ZMATNR TO ISEL-ZMATNR,
IZPACK-ZCARTON_NO TO ISEL-ZCARTON_NO,
IZPACK-ZDATE TO ISEL-ZDATE,
IZPACK-ZGROSS_WT TO ISEL-ZGROSS_WT,
IZPACK-ZTARE_WT TO ISEL-ZTARE_WT,
IZPACK-ZNET_WT TO ISEL-ZNET_WT.
APPEND ISEL.
ENDIF.
ENDIF.
CHK_BOX_VAL = SPACE.
ELSE.
EXIT.
ENDIF.
ADD 1 TO LINE_NO.
ENDDO.
IF SEL_CART = 0.
MESSAGE S398(00) WITH 'Please Select the Carton first'.
ELSE.
MESSAGE S398(00) WITH SEL_CART 'Cartons were selected'.
IF P_CHECK = 'Y'.
PERFORM CREATE_FILE. "To Created Text file of Selected Cartons
ENDIF.
ENDIF.
ENDFORM. " GENERATE_INSPECTION_LIST

*&---------------------------------------------------------------------*
*& Form CREATE_LIST
*&---------------------------------------------------------------------*
FORM CREATE_LIST.
IF NEW_SCREEN IS INITIAL.
NEW_SCREEN = 'X'.
SET TITLEBAR 'INSP_LIST'.
SET PF-STATUS 'CARTLIST' EXCLUDING SCR1_OK_CODE.
MHD1 = 'WELSPUN SYNTEX LIMITED'.
MHD2 = 'ZPACK Data For Scroll Test.'.
MHD3 = 'List of Selected Cartons'.
PERFORM DATA_HEADER.
ENDIF.
IF SY-LINNO = 1.
* PERFORM HEADER2.
ENDIF.

IZPACK_LINE = LINE_NO - 7.
READ TABLE IZPACK INDEX IZPACK_LINE.
ADD 1 TO SRNO.
FORMAT COLOR 6 INVERSE.
WRITE:/ CH NO-GAP ,(13) IZPACK-ZCARTON_NO UNDER 'Carton No.' NO-GAP.
WRITE: CH NO-GAP ,(10) IZPACK-ZDATE UNDER 'Packing Date' NO-GAP.
WRITE: CH NO-GAP ,(10) IZPACK-ZGROSS_WT UNDER 'Gross Qty.' NO-GAP.
WRITE: CH NO-GAP ,(10) IZPACK-ZTARE_WT UNDER 'Tare Qty.' NO-GAP.
WRITE: CH NO-GAP ,(10) IZPACK-ZNET_WT UNDER 'Net Qty.' NO-GAP.
WRITE: CH NO-GAP ,(18) IZPACK-ZMATNR UNDER 'Material No.' NO-GAP.
WRITE: CH NO-GAP ,(12) IZPACK-ZBATCH_NO UNDER 'Lot No.' NO-GAP.
WRITE: CH NO-GAP ,(5) IZPACK-ZGRADE UNDER 'Grade' NO-GAP.
WRITE: CH NO-GAP ,(5) IZPACK-ZTRNTYP UNDER 'Type' NO-GAP.
WRITE: '|'.
WRITE:/ SY-ULINE(110).
FORMAT RESET.
*WRITE :/ SY-PFKEY.
ENDFORM. " CREATE_LIST

*&---------------------------------------------------------------------*
*& Form CREATE_FILE
*&---------------------------------------------------------------------*
FORM CREATE_FILE.
DATA: BEGIN OF ITAB_FIELDS OCCURS 0,
IFIELD_NAME(15) TYPE C,
END OF ITAB_FIELDS.

DATA: MNAME(4) TYPE C,
G_ROW TYPE I,
G_FILENAME LIKE RLGRAP-FILENAME. "Defining Filename.

LOOP AT ISEL.
G_ROW = G_ROW + 1.
ENDLOOP.
CONCATENATE 'C:\CHAL' SY-DATUM+6(2) SY-DATUM+4(2) '.DAT' INTO
G_FILENAME.
MESSAGE S899(MM) WITH 'Created file' G_FILENAME.
* APPEND FIELD NAME
MOVE G_ROW TO ITAB_FIELDS-IFIELD_NAME.
APPEND ITAB_FIELDS.
CLEAR ITAB_FIELDS.

* START DOWNLOAD
CALL FUNCTION 'WS_DOWNLOAD'
EXPORTING
FILENAME = G_FILENAME
FILETYPE = 'DAT'
COL_SELECT = ' '
COL_SELECTMASK = ';'
TABLES
DATA_TAB = ISEL
FIELDNAMES = ITAB_FIELDS
EXCEPTIONS
FILE_OPEN_ERROR = 1
FILE_WRITE_ERROR = 2
INVALID_FILESIZE = 3
INVALID_TYPE = 4
NO_BATCH = 5
UNKNOWN_ERROR = 6
INVALID_TABLE_WIDTH = 7
GUI_REFUSE_FILETRANSFER = 8
CUSTOMER_ERROR = 9
OTHERS = 10
.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.

* END OF DOWNLOAD
MESSAGE S899(MM) WITH 'Created file' G_FILENAME.

ENDFORM. " CREATE_FILE


Creating new program via ABAP

*
* Creating new program via ABAP

*
REPORT ZCREATE_NEW_PROGRAM_VIA_ABAP.

* Type of an editor line: rssource-line
DATA: code TYPE TABLE OF rssource-line.

* Report Name
APPEND 'REPORT ZTESTING.'
TO code.

* Report Code
APPEND 'WRITE / ''Program created via ABAP!''.'
TO code.

* Report Name in SE38
INSERT REPORT 'ZTESTING' FROM code.

WRITE: / 'Report created (old report with same name overwritten).'.
WRITE: / 'Please check via transaction SE38'.

*-- End of Program



Mass update the User Parameter Value


When you need to mass maintain the User parameters to another value. This program will come in handy as you do not need to maintain the parameters for each user manually.

*
* Mass Update User parameters collectively.
*
* Written by : SAP Basis, ABAP Programming and Other IMG Stuff
*
*
REPORT ZUSERPARAM.

PARAMETERS: P_PARID(3), "Parameter ID
P_PARVA(18), "Parameter Value
P_USER(18). "User Name

TABLES: USR02, USR05.

DATA BEGIN OF IUSR02 OCCURS 5.
INCLUDE STRUCTURE USR02.
DATA END OF IUSR02.

ULINE.
WRITE: /, 'Report Selection criteria:'.
WRITE: /10 'Parameter ID:', P_PARID.
WRITE: /10 ' Parm Value:', P_PARVA.
WRITE: /10 'User Name:', P_USER.
ULINE.

SELECT * FROM USR02 INTO TABLE IUSR02 WHERE BNAME = P_USER.

LOOP AT IUSR02. "Loop thru all users
SELECT SINGLE * FROM USR05
WHERE BNAME = IUSR02-BNAME
AND PARID = P_PARID.

IF SY-SUBRC = 0.
UPDATE USR05
SET PARVA = P_PARVA
WHERE BNAME = IUSR02-BNAME
AND PARID = P_PARID.

IF SY-SUBRC = 0.
WRITE: /5 USR05-BNAME, USR05-PARID, 'Old =', USR05-PARVA,
'New =', P_PARVA.
ELSE.
WRITE: /5 'Update rc=', SY-SUBRC, USR05-BNAME.
EXIT.
ENDIF.
ELSE.
CLEAR USR05.
USR05-BNAME = IUSR02-BNAME.
USR05-PARID = P_PARID.
USR05-PARVA = P_PARVA.
INSERT USR05.
IF SY-SUBRC = 0.
WRITE: /5 'Insert ok:', USR05-BNAME, P_PARID, P_PARVA.
ELSE.
WRITE: /5 'Bad Insert, rc=', SY-SUBRC, USR05-BNAME.
EXIT.
ENDIF.
ENDIF.
ENDLOOP.

*** The end of program