2015 Mar 03 10:15 PM
Hi,
I'm originally a C++ developer trying to learn ABAP.
I want to append values to a select-option from a table if another select-option is specified. I wrote some code that I believe will work but looks very inefficient to me. Any advice on how to streamline this process would appreciated.
The following is pseudo code and I left out some tweaks for simplicity and understanding but the basic idea is there. I want to add selection criteria to a select-option based upon a second select option (that may or may not be provided) table lookup.
Example:
DATA: groups TYPE table3.
SELECT-OPTIONS:
s_accountNo FOR table1-accountNo,
s_accountGroupNo FOR table2-accountGroupNo.
**** get the Account Groups that meet the selection criteria.
START-OF-SELECTION
SELECT * INTO TABLE groups
FROM table3
WHERE accountGroupNo IN s_accountGroupNo.
**** Remove duplicate accounts from the Account Groups
SORT groups BY accountNo.
DELETE ADJACENT DUPLICATES FROM groups COMPARING accountNo.
**** Append the account #'s onto the s_accountNo range/select-option
LOOP AT groups.
APPEND groups-accountNo TO s_accountNo.
ENDLOOP.
**** manually edit the s_accountNo to have the correct option/sign for use in further select statements.
LOOP AT s_accountNo.
s_accountNo-sign = 'I'.
s_accountNo-option = 'EQ'.
MODIFY s_accountNo.
ENDLOOP.
Thanks much,
-Chris
2015 Mar 04 2:38 AM
AT SELECTION-SCREEN OUTPUT. is to be used when you need to populate selection option based on the other.
After this statement u can have an IF condition based on which you will populate the values again.
2015 Mar 04 5:16 AM
Hi Chris -
If you are just interested in appending select option s_accountno in your example, please check the below code I modified
DATA: groups TYPE table3.
SELECT-OPTIONS:
s_accountNo FOR table1-accountNo,
s_accountGroupNo FOR table2-accountGroupNo.
**** get the Account Groups that meet the selection criteria.
START-OF-SELECTION
SELECT * INTO TABLE groups
FROM table3
WHERE accountGroupNo IN s_accountGroupNo.
**** Remove duplicate accounts from the Account Groups
SORT groups BY accountNo.
DELETE ADJACENT DUPLICATES FROM groups COMPARING accountNo.
**** Append the account #'s onto the s_accountNo range/select-option
LOOP AT groups.
s_accountNo-low = groups-accountNo
s_accountNo-sign = 'I'.
s_accountNo-option = 'EQ'.
APPEND s_accountNo.
ENDLOOP.
Let us know, if it works.
2015 Mar 04 5:58 AM
1. Only SELECT the field you need - if you select 100 fields using * and only need one this is a performance hit. Likewise the table you're selecting into needs only one field
2. Use SELECT DISTINCT - that way you get just one entry and don't need to remove duplicates
3. Use a work area - tables with header lines are obsolete
4.
LOOP AT groups.
APPEND groups-accountNo TO s_accountNo.
ENDLOOP.
The second line won't work, since s_accountNo is a structure (sign, option, low, high). Should be s_accountNo-low.
5.
You don't need 4) and the following loop. Instead combine them.
s_accountNo_line-sign = 'I'.
s_accountNo-line-option = 'EQ'.
LOOP AT groups INTO group.
s_accountNo-low = group.
INSERT s_accountNo_line INTO TABLE s_accountNo.
ENDLOOP.
2015 Mar 04 2:21 PM
Thank you greatly for the input, I paired it down to the following.
:
Data: groups TYPE table3,
s_accountNo_line LIKE LINE OF s_accountNo.
SELECT-OPTIONS:
s_accountNo FOR table1-accountNo.
s_accountGroupNo FOR table2-accountGroupNo
START-OF-SELECTION
SELECT DISTINCT accountNo
FROM table3
INTO CORRESPONDING FIELDS OF TABLE groups
WHERE accountGroupNo IN s_accountGroupNo.
s_accountNo_line-sign = 'I'.
s_accountNo_line-option = 'EQ'.
LOOP AT groups
s_accountNo_line-low = groups-accountNo
INSERT s_accountNo_line INTO TABLE s_accountNo.
ENDLOOP.
This is more efficient and concise by a longshot. I have tried googling and looking up work area vs internal table and I'm not grasping the concept well. I'll continue looking into it, but if you have any more input in that area I'd appreciate it.
-Chris
2015 Mar 04 3:53 PM
There is no "work area vs internal table". But these concepts are widely documented, so do no bear repeating here. Your best bet is to run in debug and watch how data moves around.
2015 Mar 05 10:37 PM
I'm really confused why do you have SELECT-OPTION and then change it in START-OF-SELECTION event. This doesn't seem to make a lot of sense... Select options are meant for users to enter their, well, selection criteria. If someone enters one thing and then the program plays "switcheroo" on them wouldn't that be confusing?
If you need to pre-fill some values for the users (i.e. defaults) then it needs to be done in INITIALIZATION. Or if you just need to build a range to use in SELECT somewhere then take a look at Help article for 'range'. Or maybe you don't even need anything and could just use SELECT ... JOIN. This example looks very confusing to be honest.
And if you're selecting just one field then you don't need INTO CORRESPONDING FIELDS.
Internal tables are similar to arrays in other languages. Not exactly the same but close enough.
I'm also not sure why would anyone want to learn ABAP at this point since it's clearly a dying breed but that's another story.
2015 Mar 06 9:39 AM
Jelena Perfiljeva wrote:
I'm also not sure why would anyone want to learn ABAP at this point since it's clearly a dying breed but that's another story.
Rumours of ABAP's demise have been circulating for at least fifteen years. And yet, still here we are!
2015 Mar 06 2:07 PM
The goal is that rather than having to key in sometimes large quantities of account numbers in the account select-option the user has the option to enter an account group which will then add all the account numbers associated with that group to the account number selection criteria. (if that makes sense).
As far as learning ABAP, I look at it as a chance to get better with database manipulation as much as anything
Thanks for the into corresponding fields tip.
2015 Mar 06 8:48 PM
Chris - but wouldn't this relationship be stored somewhere in SAP? I just feel you don't need to manipulate select options at all, although I'm not sure what data you'll be getting exactly. You might want to post what tables you're planning to read - if those are standard ones (those that don't start with Y or Z) then we would know them too, it's not a secret.
For example, for table KNA1 (customer master) we could have the selection options for account number (KUNNR) and country (LAND1). The users could fill in either one of them or both or none.
Then there would be a SELECT statement like this (just a very simple example):
SELECT KUNNR NAME1
INTO TABLE itab_customers
FROM KNA1
WHERE KUNNR IN SO_KUNNR
AND LAND1 IN SO_LAND1.
If, for example, the users only select 'US' for the country (LAND1), the program does not need to go and fill in SO_KUNNR with the customer numbers that fit that criteria. SELECT statement takes care of that. If both selection options are left blank then SELECT would just read the whole KNA1 table (blank select option translates to "include all", not to "equals blank" - this part can be confusing for beginners).
Again, not sure what you're doing exactly further in the program but I feel you might be just misunderstanding how selection options work.
2015 Mar 06 8:56 PM
Chris Bosler wrote:
... sometimes large quantities of account numbers in the account select-option.. .
Another consideration will be the size of the SQL statement that is generated by ABAP and sent to the database. If you end up with too many " OR AccountNo = 'XXXXXXXX'" options, you may get a dump.
Rob
2015 Mar 06 9:05 PM
Are you referring to a select-option with doing the multiple selections, i.e.
sign 'I', option 'EQ', low 'value'
meaning this will be turned into an SQL statement with OR AccountNo = 'XXXXXX' and a ton of these could cause an error?
as opposed to doing a range
sign 'I' option 'BT' or whatever between is?
2015 Mar 06 9:12 PM
Yes.
Another option would be to use a sub-query to pass the account numbers from the Account Group table.
Rob
2015 Mar 06 9:28 PM
The actual selection is fairly complicated from my point of view. I wrote the accountNo example to make things less confusing for me as much as anyone else, not to hide anything. I also didn't expect this amount of feedback, though it is appreciated.
The eventual select statement that is done is the following:
SELECT DISTINCT vttp~zseq_num
likp~vbeln
likp~lprio
likp~vstel
lips~werks
likp~lgnum
lips~posnr
lips~lgort
lips~vgbel
lips~vgpos
lips~sobkz
lips~lfimg
lips~vrkme
lips~matnr
lips~volum
mara~raube
vttk~dplbg
vttp~tknum
vttp~tpnum
likp~berot
likp~vkorg
likp~lfart
INTO TABLE temp_deliveries
FROM vttk
INNER JOIN vttp
ON vttk~tknum = vttp~tknum
INNER JOIN likpuk AS likp
ON vttp~vbeln = likp~vbeln
INNER JOIN lipsup AS lips
ON likp~vbeln = lips~vbeln
INNER JOIN mara
ON lips~matnr = mara~matnr
WHERE likp~vstel = p_vstel
AND lips~werks = p_werks
AND likp~lgnum IN s_lgnum
AND likp~vbeln IN s_vbeln
AND lips~vgbel IN s_vgbel
AND vttk~dplbg IN s_dplbg
AND vttk~tknum IN s_tknum
AND mara~raube = p_raube
AND likp~lfart IN ('ZLF', 'NL')
AND lips~kosta <> 'C'
AND lips~kosta <> ''
AND likp~kostk <> 'C'
AND likp~vbtyp = outbound.
and the structure it is put into is the following:
TYPES: BEGIN OF type_deliveries,
zseq_num TYPE vttp-zseq_num,
vbeln TYPE likp-vbeln,
lprio TYPE likp-lprio,
vstel TYPE likp-vstel,
werks TYPE likp-werks,
lgnum TYPE likp-lgnum,
posnr TYPE lips-posnr,
lgort TYPE lips-lgort,
vgbel TYPE lips-vgbel,
vgpos TYPE lips-vgpos,
sobkz TYPE lips-sobkz,
lfimg TYPE lips-lfimg,
vrkme TYPE lips-vrkme,
matnr TYPE lips-matnr,
volum TYPE lips-volum,
raube TYPE mara-raube,
dplbg TYPE vttk-dplbg,
tknum TYPE vttk-tknum,
tpnum TYPE vttp-tpnum,
berot TYPE likp-berot,
vkorg TYPE likp-vkorg,
lfart TYPE likp-lfart,
sdabw type likp-sdabw,
orig_lgort TYPE lips-zzorig_lgort,
selected TYPE flag,
counter(15) TYPE n,
END OF type_deliveries.
Currently there is a select option for tknum and I am attempting (successfully with my change shown above, though as many have pointed out I may be misusing the intended functionality) to add another select-option for s_pickno which is a field of a custom table that has pickno as one of it's unique keys and tknum as another of it's fields. The idea is to be able to take a pickno and use it to find all the tknum's associated and then use them in the select statement above as well as any tknum's provided as initial input by the user. If there is a better method than modifying the s_tknum selection I'm open to feedback.
Apologies that my initial example did not portray this, but being new I was a little overwhelmed myself and want something I can wrap my head around better. There's my wall of text
2015 Mar 10 1:48 PM
This is the "answer" I went with. A sub-query worked perfectly for the situation. Thanks for the reply.
2015 Mar 06 8:20 PM
2015 Mar 06 9:29 PM