Sometimes ABAP drives me crazy with really simple tasks such as incrementing an integer within a loop...
Here's my try:
METHOD test.
DATA lv_id TYPE integer.
lv_id = 1.
LOOP AT x ASSIGNING <y>.
lv_id = lv_id+1.
ENDLOOP.
ENDMETHOD.
This results in the error message Field type "I" does not permit subfield access.
You already answered the question yourself, but to make things a bit clearer:
variable + 1
is an arithmetic expression - add 1 to the value of the variable.
variable+1
is an offset operation on a character variable. For example, if variable contains ABC, variable+1 is BC.
This can be especially confusing when dealing with NUMCs. For example, with variable = '4711', variable + 1 is evaluated to 4712, whereas variable+1 is '711' (a character sequence).
The error you saw occurred because it's not possible to perform the index operation on a non-character-like variable.
You mean like:
ADD 1 to lv_id.
By the way, when you loop over an internal table, SY-TABIX has the loop counter.
Uh, I got it.
It's the f****** spaces...
lv_id = lv_id + 1
works...
Simple
DATA : gv_inc type I .
place this statement in loop
gv_inc = gv_inc + 1 .
from SAP NetWeaver Version 7.54 you can also use:
lv_id += 1.
Instead of
lv_id = lv_id + 1.
Happy coding!
If you are going to increment every loop cycle than you can directly get the table size.
describe table x lines data(lv_id). "Out side of the loop.
Related
I am very new to SAS & request help to understand use case of 'Retain' function, below are 2 codes where end goal is cumulative height to be added in new column 'Tot_Height', using 2 different codes, however both give same result, hence confused when would retain function be used and variable be initialised as 0 ?????
Data Set [Data Set][1] : (https://i.stack.imgur.com/nt1j6.png)
Code No 1
```
data class3;
set class2;
retain tot_height 0;
by sex;
if first.sex then tot_height = Height;
else tot_height + Height;
run;
````
Code No 2
````
data class3;
set class2;
if first.sex then tot_height = Height;
else tot_height + Height;
run;
````
Please help understand from above 2 codes as i am confused where would retain help
There is no real difference between those two steps because of the use of the SUM statement in the ELSE clause.
The SUM statement has the form:
variable + expression ;
The result is that the value of EXPRESSION is added to the value of VARIABLE. And that VARIABLE is defined to be RETAINed and if there is no other RETAIN statement with an explicit initial value it is initialized to zero. So adding the explicate RETAIN statement in the first data step that is setting the initial value to zero does not change how the data step will work.
Normally on each iteration of the data step variables that are created by this step (as opposed to variables that are coming from input datasets) will be set to missing. The RETAIN statement says to NOT set them to missing so the value at the start of on iteration is the same as it had at the end of the previous iteration.
Note that for these data steps the initial value is immediately overwritten by the first value of HEIGHT for the first observation since by definition the first observation in the dataset is the first observation of a BY group. So even if you were to change the initial value in the RETAIN statement to something other than zero it will have no real effect since it will be immediately replaced.
Hello Experts
I need a help to count the words of string without using any function in ABAP.
We can only use do loop and if condition.
Please Help
METHODS count_words
IMPORTING
iv_text TYPE string
RETURNING
VALUE(rv_result) TYPE i.
METHOD count_words.
CONSTANTS lc_space TYPE string VALUE ` `.
DATA(lv_remaining_text) = iv_text.
DATA(lv_last_char) = ``.
DO.
IF lv_remaining_text IS INITIAL.
RETURN. " or EXIT if you omit the METHOD around this
ENDIF.
DATA(lv_next_char) = lv_remaining_text(1).
IF lv_next_char <> lc_space AND
( lv_last_char IS INITIAL OR
lv_last_char = lc_space ).
rv_result = rv_result + 1.
ENDIF.
lv_last_char = lv_next_char.
lv_remaining_text = lv_remaining_text+1.
ENDDO.
ENDMETHOD.
Please don't code like this in practice. This sort of low-level character juggling is only for educational purposes.
In real life, please use something like this:
METHOD count_words_cleanly.
rv_result = count( val = iv_text
regex = `(\s\S|^\S)` ).
ENDMETHOD.
You could count the number of spaces between your words.
You need at least STRLEN to determine the string length... without it I dont think this works. CONDENSE might be useful in some cases... give it a try without CONDENSE.
DATA a TYPE string VALUE 'MY NAME IS JOHN'.
DATA c TYPE i.
DATA d TYPE c.
DATA words TYPE i value 1.
DATA e TYPE i VALUE 0.
CONDENSE a.
c = STRLEN( a ).
DO c TIMES.
d = a+e(1).
e = e + 1.
IF d = ' '.
words = words + 1.
ENDIF.
ENDDO.
WRITE words. // just as output ... delete on demand
I'm trying to clean the following empty cells marked in red from this internal table before I display it in an ALV.
If a cell is found to be blank, look for any cells underneath that have value and move up.
I am struggling to figure out what is the best way in code to perform this.
Any help would be great.
It is undoubtedly that something is wrong with your merging logic, however your task is quite interesting and this is one of the possible ways it can be solved.
I took your structure and made an assumption that none of the rows in your table is fully filled, i.e. either first three columns are filled (struct_left) or last three (struct_right). This is how I feel it from your screenshots.
REPORT z_sections.
TYPES:
BEGIN OF struct_left, " left structure
LEFTDAMAGED TYPE c LENGTH 1,
LEFTDAMAGEDDESC TYPE c LENGTH 3,
LEFTDAMAGEDDESCT TYPE c LENGTH 30,
END OF struct_left,
BEGIN OF struct_right, " right structure
RIGHTDAMAGED TYPE c LENGTH 1,
RIGHTDAMAGEDDESC TYPE c LENGTH 3,
RIGHTDAMAGEDDESCT TYPE c LENGTH 30,
END OF STRUCT_right.
TYPES BEGIN OF ty_table.
INCLUDE TYPE struct_left.
INCLUDE TYPE struct_right.
TYPES END OF ty_table.
DATA: lt_current_table TYPE TABLE OF ty_table INITIAL SIZE 100,
ls_current_table LIKE LINE OF lt_current_table,
i TYPE i.
FIELD-SYMBOLS: <fld> TYPE clike.
DATA: r_random TYPE REF TO cl_abap_random_packed,
seed TYPE i.
seed = cl_abap_random=>seed( ).
CALL METHOD cl_abap_random_packed=>create
EXPORTING
seed = seed
min = -999999999999999
max = 999999999999999
RECEIVING
prng = r_random.
DEFINE randomize. " filling row with random data
ASSIGN COMPONENT &1 OF STRUCTURE &2 TO <fld>.
<fld> = r_random->get_next( ).
&1 = &1 + 1.
ASSIGN COMPONENT &1 OF STRUCTURE &2 TO <fld>.
<fld> = r_random->get_next( ).
&1 = &1 + 1.
ASSIGN COMPONENT &1 OF STRUCTURE &2 TO <fld>.
<fld> = r_random->get_next( ).
END-OF-DEFINITION.
START-OF-SELECTION.
* filling table with random stuff
DO 100 TIMES.
CLEAR ls_current_table.
IF sy-index MOD 3 = 0.
i = 1.
randomize i ls_current_table.
ELSE.
i = 4.
randomize i ls_current_table.
ENDIF.
APPEND ls_current_table TO lt_current_table.
ENDDO.
DATA: ls_left TYPE struct_left,
ls_right TYPE struct_right.
DATA lt_new LIKE lt_current_table.
* collapsing table
LOOP AT lt_current_table ASSIGNING FIELD-SYMBOL(<fs_current>) WHERE leftdamaged IS NOT INITIAL.
DELETE lt_current_table WHERE leftdamaged IS INITIAL AND leftdamageddesc IS INITIAL AND leftdamageddesct IS INITIAL AND
rightdamaged IS INITIAL AND rightdamageddesc IS INITIAL AND rightdamageddesct IS INITIAL. " remove empty lines
MOVE-CORRESPONDING <fs_current> TO ls_left.
READ TABLE lt_current_table ASSIGNING FIELD-SYMBOL(<fs_right>) WITH KEY leftdamaged = ''.
IF <fs_right> IS ASSIGNED.
MOVE-CORRESPONDING <fs_right> TO ls_right.
CLEAR: <fs_right>.
ENDIF.
CLEAR: <fs_current>.
IF ls_left IS NOT INITIAL AND ls_right IS NOT INITIAL.
CLEAR: ls_current_table.
MOVE-CORRESPONDING ls_left TO ls_current_table.
MOVE-CORRESPONDING ls_right TO ls_current_table.
APPEND ls_current_table TO lt_new.
CLEAR: ls_left, ls_right.
ENDIF.
ENDLOOP.
You can sort the internal table and store it in a temp internal table, and swap them. For instance:
data: lt_itab_temp like table of lt_itab.
move lt_itab[] to lt_itab_temp[].
clear:lt_itab[],lt_itab.
sort lt_itab_temp descending by rightdamagedesc rightdamagedesct.
move lt_itab_temp[] to lt_itab[].
OR, you can loop through the fieldcatalog, set "no_display" or "no_out" field to 'X'.
Say I have a no. 20101105, I need to compare it with a series of other nos. say 20110105 , 20090105 and find the nearest no. of it.
I don't want to compare it on the whole, I need to compare it each digit wise by parsing thru it and then see which is the closest.
Can someone suggest on how to do this in ABAP language?
In general You should mention some more information. For example, are the numbers really integers ? Then You can put them into an internal table and sorting all of them is the easiest solution to find any "nearest" number relating to an actual scanned. This is just like integers work in sort, they are sorted like numbers, my friend. But If You want it character-wise ( what really makes no sense, if the numbers are integers ) i give You some help with this character-comparison in a do-loop, taking smaller string-length as iterator-counter. I omitted the else, that's Your "homework". :-D
DATA:
lv_length1 TYPE i,
lv_length2 TYPE i,
lv_cnt TYPE i,
lv_teststr1 TYPE string VALUE '123456',
lv_teststr2 TYPE string VALUE '1235'.
lv_length1 = strlen( lv_teststr1 ).
lv_length2 = strlen( lv_teststr2 ).
IF lv_length1 GE lv_length2.
DO lv_length2 TIMES.
IF lv_teststr2+lv_cnt(1) NE lv_teststr1+lv_cnt(1).
BREAK-POINT.
ENDIF.
ADD 1 TO lv_cnt.
ENDDO.
ENDIF.
The counter variable is also the index of, in this case, the first not matching character. This gets the job done.
Coded and tested by me just right now.
I don't know if I understood but maybe this helps.
report znearest.
data lv_value(8) type n.
parameters p_value(8) type n. " ---------> The value
select-options s_values for lv_value. " -> The list
start-of-selection.
data: wa like line of s_values,
lv_dif(8) type n,
lv_nearest(8) type n,
lv_nearest_dif(8) type n,
lv_first type c.
loop at s_values into wa.
lv_dif = abs( p_value - wa-low ). " Calculate the difference
if lv_first is initial.
lv_nearest_dif = lv_dif.
lv_first = 'X'.
endif.
if lv_dif le lv_nearest_dif. " Compare the differences
lv_nearest = wa-low.
lv_nearest_dif = lv_dif.
endif.
endloop.
write: 'The nearest from', p_value, 'is', lv_nearest.
Hope it helps.
Ok so I am trying to reference one variable with another in SQL.
X= a,b,c,d (x is a string variable with a list of things in it)
Y= b ( Y is a string variable that may or may not have a vaue that appears in X)
I tried this:
Case when Y in (X) then 1 else 0 end as aa
But it doesnt work since it looks for exact matches between X and Y
also tried this:
where contains(X,#Y)
but i cant create Y globally since it is a variable that changes in each row of the table.( x also changes)
A solution in SAS would also be useful.
Thanks
Maybe like will help
select
*
from
t
where
X like ('%'+Y+'%')
or
select
case when (X like ('%'+Y+'%')) then 1 else 0 end
from
t
SQLFiddle example
In SAS I would use the INDEX function, either in a data step or proc sql. This returns the position within the string in which it finds the character(s), or zero if there is no match. Therefore a test if the value returned is greater than zero will result in a binary 1:0 output. You need to use the compress function with the variable containing the search characters as SAS pads the value with blanks.
Data step solution :
aa=index(x,compress(y))>0;
Proc Sql solution :
index(x,compress(y))>0 as aa