Aligning numeric values on left with WRITE - abap

I'm creating a calculation table and want to align the numbers on the left under the '+'.
But somehow the first number in each column from the counter has some space before it.
How can I eliminate that space and align my table so that the left side is all in one row?
Code:
DATA: counter TYPE i,
counter2 TYPE i.
ULINE /(159).
WRITE: /1 sy-vline , '+', sy-vline.
DO 11 TIMES.
counter = sy-index - 1 .
WRITE: counter, sy-vline.
ENDDO.
ULINE /(159).
DO 11 TIMES.
counter = sy-index - 1 .
WRITE: /1 sy-vline , counter , sy-vline.
ULINE /(159).
ENDDO.

The spaces in front of the number are there because of the data type. Type i is an elementary data type and can have numbers from -2147483648 to 2147483647, which means it can be 11 characters long. Some data types have an output length that is variable, but that is not the case for i. You can see that if you click on it in your output, it should have a red outline 11 characters long.
But if you would rather have the spaces at the end of the number, then you can use 'CONVERSION_EXIT_ALPHA_OUTPUT'. But the "table outline" will still have to be just as big, since the number can have 11 characters.
DATA: counterc TYPE c LENGTH 11.
...
MOVE counter TO counterc.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
EXPORTING
input = counterc
IMPORTING
output = counterc.
...
WRITE: ... counterc ...
Alternatively, the output of a table looks way better if you use SALV. Look here for example, to see how to output a table using SALV.

Related

How to do typecasting without loosing a comma?

Task: I have data col(30) TYPE c VALUE '-1111,45'. and I need to check if this value is negative, if negative - do typecasting. But on the output I get 5 though I have to get 1111,45 without a minus and again do typecasting to the previous type (с).
REPORT Z_CAST.
data col(30) TYPE c VALUE '-1111,45'.
data numc type n.
numc = col.
if numc < 0.
numc = -1 * numc.
endif.
col = numc.
WRITE col. "Output: 5
REPORT Z_CAST.
data col(30) TYPE c VALUE '-1111,45'.
if col+0(1) EQ '-'.
WRITE col+1. "1111,45
endif.
This is the minimum character processing way to do this:
col = replace( val = col
sub = '-'
with = ' ' ).
You don't have to find the - first to replace it.
And this is the clean numeric way that ABAPers will usually choose:
DATA n TYPE p LENGTH 12 DECIMALS 2.
n = col.
n = abs( n ).
Note that this does not work with your example '-1111,45' though: ABAP expects a point . as decimal separator, but your number uses a localized format with comma ,, so you would have to normalize the number first.

Cleaning empty cells in internal table

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'.

How to convert Character Numerals into Numeric format?

I am trying to convert some String of Characters into Numeric form and then further incrementing it.
For Example : XX1-XXXXX.01.01.01.01 should be incremented to XX1-XXXXX.01.01.01.02 and if it reaches to XX1-XXXXX.01.01.01.99 then next increment should be XX1-XXXXX.01.01.02.00 and it continues for next node also.
XX1-XXXXX.01.01.01.01 is in Character Format.
Any Possible Solution?
This one is not compatible down to ABAP 700 like szakos but I want to bring in another solution:
FORM increment
CHANGING
fcw_out TYPE string.
DATA lw_as_n TYPE n LENGTH 8.
SPLIT fcw_out AT '.' INTO DATA(lw_start) DATA(lw_rest).
REPLACE ALL OCCURRENCES OF '.' IN lw_rest WITH ''.
lw_as_n = lw_rest + 1.
fcw_out = |{ lw_start }.{ lw_as_n(2) }.{ lw_as_n+2(2) }.{ lw_as_n+4(2) }.{ lw_as_n+6(2) }|.
ENDFORM.
" ------------------------------------------------
" Test run
" ------------------------------------------------
DATA(w_str) = `XX1-XXXXX.01.01.01.99`.
PERFORM increment CHANGING w_str. " ==> XX1-XXXXX.01.01.02.00
You can achieve this by converting the numerical parts of the node to a number and write it back after increasing. Simple example code:
DATA: l_node TYPE c LENGTH 21,
l_node_new TYPE c LENGTH 21,
l_help TYPE c LENGTH 11,
l_num TYPE n LENGTH 8,
l_node_pos TYPE int4,
l_num_pos TYPE int4.
l_node_new = l_node = 'XX1-XXXXX.01.01.01.01'.
l_help = l_node+10(*).
REPLACE ALL OCCURRENCES OF '.' IN l_help WITH ''.
CONDENSE l_help.
l_num = l_help.
DO 100 TIMES.
ADD 1 TO l_num.
ENDDO.
DO 4 TIMES.
l_node_pos = 10 + ( sy-index - 1 ) * 3.
l_num_pos = 0 + ( sy-index - 1 ) * 2.
l_node_new+l_node_pos(2) = l_num+l_num_pos(2).
ENDDO.
WRITE / l_node.
WRITE / l_node_new.
The output is:
The ABAP version was 700 so this is the "old" syntax, but should work on newer versions.

Remove variables by character pattern in variable name (SAS)

I'd like to drop all variables with a certain character segment in the name. Example below:
var1 var2 var3 o_var1 o_var2 o_var3
1 1 1 3 2 5
7 3 4 . -1 5
I'd like to only keep those without the "o_" in front. I could sort positionally and keep the first x number of variables, but with 100s of variables with this pattern, I wanted to seek an alternative.
Just use the colon wildcard operator.
data want;
set have (drop=o_:); /* drops all variables beginning with o_ */
run;

How to write number with sign on the left and thousands separator point

I am holding the number in character format in abap. Because I have to take the minus from right to left. So I have to put the number to character and shift or using function 'CLOI_PUT_SIGN_IN_FRONT' I'm moving minus character to left.
But after assigning number to character it doesn't hold the points. I mean my number is;
1.432- (as integer)
-1432 (as character)
I want;
-1.432 (as character)
is there a shortcut for this or should I append some string operations.
Edit:
Here is what I'm doing now.
data: mustbak_t(10) TYPE c,
mustbak like zsomething-menge.
select single menge from zsomething into mustbak where something eq something.
mustbak_t = mustbak.
CALL FUNCTION 'CLOI_PUT_SIGN_IN_FRONT'
CHANGING
VALUE = mustbak_t.
write: mustbak_t.
If you're on a recent release, you could use string templates - you'll have to add some black magic to use a country that confoirms to your decimal settings, though:
DATA: l_country TYPE t005x-land,
l_text TYPE c LENGTH 15,
l_num TYPE p LENGTH 6.
SELECT SINGLE land
INTO l_country
FROM t005x
WHERE xdezp = space.
l_num = '-123456'.
l_text = |{ l_num COUNTRY = l_country }|.
WRITE: / l_text.
In this case, you need a country code to pass to the COUNTRY parameter as described in the format options. The values of the individual fields, namely T005X-XDEZP are described in detail in the country-specific formats.
tl;dr = Find any country where they use "." as a thousands separator and "," as a decimal separator and use that country settings to format the number.
You could also use classic formatting templates, but they are hard to handle unless you have a fixed-length output value:
DATA: l_text TYPE c LENGTH 15,
l_num TYPE p LENGTH 6 DECIMALS 2.
l_num = '-1234.56'.
WRITE l_num TO l_text USING EDIT MASK 'RRV________.__'.
CONDENSE l_text NO-GAPS.
WRITE: / l_text.
Here's another way, which i finally got working:
DATA: characters(18) TYPE c,
ints TYPE i VALUE -222333444.
WRITE ints TO characters. "This is it... nothing more to say.
CALL FUNCTION 'CLOI_PUT_SIGN_IN_FRONT'
CHANGING
value = characters.
WRITE characters.
Since integers are automatically printed with the thousands separator, you can simply output them to a char data object directly using WRITE TO with no aditions..... lol
DATA: currency TYPE cdcurr,
characters(18) TYPE c,
ints TYPE i VALUE -200000.
currency = ints.
WRITE currency TO characters CURRENCY 'USD' DECIMALS 0.
CALL FUNCTION 'CLOI_PUT_SIGN_IN_FRONT'
CHANGING
value = characters.
.
WRITE: / 'example',characters.
This prints your integer as specified. Must be apparently converted to a currency during the process.