Thursday, December 28, 2017

Touching Feet - Update

It has been a few days since my first sincere attempt at touching feet.
After practice of about 4 days (5-10mins per day), I am now able to touch and grab all toe fingers using hands. It was made possible by tips from internet and from my sister who is a yoga athlete. As it turns out, inhale and exhale play a significant role in inching forward.

Virus-free. www.avast.com

Table Comprehension Example Like Nested Loop

DATA lt TYPE TABLE OF i.
DO 10 TIMES.
APPEND sy-index TO lt.
ENDDO.
"loop at itab into wa. fill wa2 using wa and append lt2, all this using
DATA lt2 TYPE TABLE OF i.
lt2 = VALUE #( FOR lv IN lt ( lv * lv ) ).
"nested loop of lt and lt2 to create lines of lt3
DATA lt3 TYPE TABLE OF i.
lt3 = VALUE #( FOR lv IN lt FOR lv2 IN lt2 ( lv + lv2 ) ).
cl_demo_output=>display( lt3 ).


Virus-free. www.avast.com

Table Comprehension Example

Below snippet is populating itab lt2 whose every line is related to that of itab lt.

DATA lt TYPE TABLE OF i.
DO 10 TIMES.
APPEND sy-index TO lt.
ENDDO.
"loop at itab into wa. fill wa2 using wa and append lt2, all this using table expression
DATA lt2 TYPE TABLE OF i.
lt2 = VALUE #( FOR lv IN lt ( lv * lv ) ).
cl_demo_output=>display( lt2 ).


Virus-free. www.avast.com

Explore More Loop Group

I skimmed through below blogs and it is now clear that my previous posts on loop groups are just scratching the surface.

https://blogs.sap.com/2016/06/23/group-by-for-internal-tables-step-by-stepc/

https://blogs.sap.com/2014/10/02/abap-news-for-740-sp08-grouping-internal-tables/


Virus-free. www.avast.com

Rewriting DEMO_LOOP_AT_GROUP_SYNTAX For Practice

I memorized the demo program, and tried write everything from scratch. Custom code is saved as ZDEMO_LOOP_AT_GROUP_SYNTAX on my local computer.

Idea was to:
  1. Define an itab of different structure, content and see how behavior changes when itab rows sort order is changed and when grouping is done with/without ASCENDING.
  2. Learn instantiation, sections and method chaining of class cl_demo_output
  3. Get familiar with the syntax variations.
  4. Truly understand the difference between representative binding and group key binding of group loop with member loop. I could see that group key had different runtime structure than itab row.

NOTE: The group loop output was one of these: ls, <ls>, ls->*. Respective name used in member LOOP AT GROUP was: ls, <ls>, ls. This is not what I expected when INTO REFERENCE was used. I first wrote LOOP AT GROUP ls->* and this gave syntax error.



Virus-free. www.avast.com

Friday, December 22, 2017

Touching Feet

Today I made a sincere effort to touch my own feet (yogasana) and failed. An article on internet was discussing the benefits of being flexible. It may reduce the impact of fall or injury because the muscles would need to bend/stretch more before tearing. The strategy of touching feet is to actually try touching it regularly and also some other exercises that focus of parts of it. All in all, it involves calf, hamstring, lower back etc. I hope that blogging about this would help not forget the goal.

This is one small fitness step just like numerous other failed attempts before. In case things get rolling, I would move on to other asanas.

For every such move, I would first be able to do it for fraction of second, then comes reps and last comes holds.

Grouping Internal Tables Rows In Loop

Demo program DEMO_LOOP_AT_GROUP_SYNTAX and respective documentation show 6 syntaxes in which grouping is done.

https://help.sap.com/doc/abapdocu_740_index_htm/7.40/en-US/abenloop_at_group_abexa.htm

First three group loops have representative binding and next three group loops have group key binding which is more explicit in nature.

While looping, result can be put into data, field-symbol or data reference. All are covered in example.

Tuesday, December 19, 2017

Incorrect Hyperlink in SAP Keyword Documentation

While sifting through keyword documentation, I came across this mistake.

https://help.sap.com/doc/abapdocu_740_index_htm/7.40/en-US/abennews-740_sp08.htm

Two hyperlinks are present with text "Internal Tables in Release 7.40, SP08". First one directs are "AMDP in Release 7.40, SP08" whereas second one directs to correct link.

Table Expression Default Value

Demo program DEMO_TAB_EXP_DEFAULT is good enough to understand the usage of DEFAULT and OPTIONAL additions while using table expression to read line.

Using OPTIONAL, we can get similar behavior as read table. Still there would be one difference. The work area of read table remains unchanged if record is not found. When table expression is used, work area will be cleared or filled with found row. So, OPTIONAL helps you to prevent the expression from throwing exception of line not found. Value is always passes, be it initial row type or the one specified in DEFAULT addition.

Monday, December 18, 2017

Short Form for Structured Row Types

When internal table is constructed using constructor expression like VALUE and the row type is of structured type, a short form can be used to specify line_spec.

It is useful when most columns of lines to be inserted are same and only some differ.

DATA lt_vbeln TYPE RANGE OF vbeln.

"normal form

lt_vbeln = VALUE #( ( sign = 'I' option = 'EQ' low = '11' )

                    ( sign = 'I' option = 'EQ' low = '22' )

                    ( sign = 'I' option = 'EQ' low = '33' ) ).

"short form

lt_vbeln = VALUE #( BASE lt_vbeln

                    sign = 'I' option = 'EQ' ( low = '44' )

                                             ( low = '55' )

                                             ( low = '66' ) ).

Friday, December 15, 2017

VALUE Internal Table "LINES OF" Line_spec

Example code is from documentation.

TYPES t_itab TYPE TABLE OF i WITH EMPTY KEY. 

DATA(jtab) = VALUE t_itab( ( 10 ) ( 20 ) ( 30 ) ). 

DATA(itab) = VALUE t_itab( ( ) ( 1 ) ( 2 ) ( LINES OF jtab ) ). 

cl_demo_output=>display( itab ).



Some things are to be noted here.

Blank parenthesis will insert initial line.

Internal table key is empty. It means primary key will not have any key field. Commonly used way to declare internal table (data lt_vbap type standard table of vbap) results in non-unique default key. Default key means all non-numeric fields of line type. If internal table has unstructured line type, table_line would be the default key. Surprisingly, lt_vbap would mostly be read using vbeln posnr but default key would have more than 200 fields. Why maintain huge key when it is never utilized. So empty key or vbeln+posnr would be better than the default. An obvious advantage of using proper keys is that the read with table key will be preferred over sort read binary search.

Till now, I have used VALUE expression to fill empty table. Using LINES OF, we can essentially append lines without using append statement. LINES OF can also have additions like FROM TO and USING KEY.

Thursday, December 14, 2017

Using BASE In VALUE, NEW & CORRESPONDING

Constructor expression create a new variable from scratch. Components have initial value unless passed explicity using expression argument. A template value or start can be applied using BASE, before actual construction takes place. Valid since ABAP 740 SP08.

Below are some basic example codes of BASE being applied in VALUE, NEW and CORRESPONDING.

TYPES: BEGIN OF ts, a, b, c, END OF ts.

"VALUE with BASE

DATA(base1) = VALUE ts( a = 'a' b = 'b' c = 'c' ).

DATA(ls1) = VALUE #( BASE base1 a = '.' ).

cl_demo_output=>write( base1 ).

cl_demo_output=>write( ls1 ).

"NEW with BASE

DATA(ldr1) = NEW #( BASE base1 b = '.' ).

cl_demo_output=>write( ldr1->* ).

"CORRESPONDING with BASE

TYPES: BEGIN OF ts2, b, c, END OF ts2.

DATA(ls2) = CORRESPONDING ts( BASE ( base1 ) VALUE ts2( b = '.' ) ).

cl_demo_output=>write( ls2 ).

"display all

cl_demo_output=>display( ).

Wednesday, December 13, 2017

REDUCE Operator Example

This is my first practice code of REDUCE operator.

"sum of squares of 1 to 4 using reduction operator

DATA(lv_result) = REDUCE i( INIT ii TYPE i

                            FOR k = 1 THEN k + 1 UNTIL k > 4

                            LET kk = k * k IN

                            NEXT ii = ii + kk ).

cl_demo_output=>display( lv_result ).

"traditional way to achieve same result

DATA ii2 TYPE i.

DATA(k2) = 1.

DO.

  DATA(kk2) = k2 * k2.

  ii2 = ii2 + kk2.



  k2 = k2 + 1.

  IF k2 > 4.

    EXIT.

  ENDIF.

ENDDO.

lv_result = ii2.

cl_demo_output=>display( lv_result ).

Tuesday, December 12, 2017

Incorrect Sample Code In BOOLX Documentation

Boolx is an inbuilt function which returns a byte chain of type xstring.

Below example shows how individual bits are being set. Bitwise OR operations are able to give final result which has bit string 01010101 or hex value 55.

DATA(result) = boolx( bool = 2 > 1 bit = 8 )

        BIT-OR boolx( bool = 2 < 1 bit = 7 )

        BIT-OR boolx( bool = 2 > 1 bit = 6 )

        BIT-OR boolx( bool = 2 < 1 bit = 5 )

        BIT-OR boolx( bool = 2 > 1 bit = 4 )

        BIT-OR boolx( bool = 2 < 1 bit = 3 )

        BIT-OR boolx( bool = 2 > 1 bit = 2 )

        BIT-OR boolx( bool = 2 < 1 bit = 1 ).

Documentation says this function allows efficient saving of truth values. Not sure how much performace will be gained when the space is littered with inefficient code. Bit position 1 is leftmost and 8 is rightmost. A byte has only 8 bits.

There is also a fancy code that I don't understand but it does same as above using REDUCE table expression.

DATA(result) = 

  REDUCE xstring( INIT x TYPE xstring 

                  FOR j = 4 THEN j - 1 UNTIL j < 1 

                  LET b1 = 2 * j b2 = 2 * j - 2 IN 

                  NEXT x = x BIT-OR boolx( bool = 2 > 1  bit = b1 ) 

                             BIT-OR boolx( bool = 2 < 1  bit = b2 ) ). 

Still if I had to explain without understanding, I would go like this:

1. x variable of type xstring is declared.

2. A loop counter j value starts with 4 and in every pass it is decremented till it becomes 1. Value zero is the exit condition. Total 4 passes.

3. 2 more variables are declared, b1 and b2. b1 = 2 * j. b2 = 2 * j - 2. So in loop passes, (b1,b2) values go like this (8,6) (6,4) (4,2) (2,0).

4. Bitwise OR is done on x, boolx using b1 and boolx using b2.



But since the number sequence 86644220 does not look like 87654321, it looks like the code is incorrect in documentation. However, the end result is correct because we just need to set the bit positions 8, 6, 4 and 2. Odd bit positions are anyways in initial state.

Correct code would be this:

DATA(result) =

  REDUCE xstring( INIT x TYPE xstring

                  FOR j = 4 THEN j - 1 UNTIL j < 1

                  LET b1 = 2 * j b2 = 2 * j - 1 IN

                  NEXT x = x BIT-OR boolx( bool = 2 > 1  bit = b1 )

                             BIT-OR boolx( bool = 2 < 1  bit = b2 ) ).

Above code would be setting bit positions 87654321.

Boolean Data Type in XML JSON ABAP

XML and JSON have boolean data type.

In case of XML, xsd:boolean is the data type. The xml nodes would have case sensitive values like true and false. 1 and 0 are also allowed.

Coming to JSON, same true and false values are used. Example { "sale":true }. On the other hand, { "sale":"true" } would correspond to string type.

However in case of ABAP, there has not been a dedicated boolean data type. Even if abap_bool or xsdboolean are the closest match, they can store any char1 value.

The difference is visible when serialization is done to generate xml or json.

Below code is copied from the keyword documentation. XSDBOOL function is available since ABAP 740 SP08.

NOTE:The result would be very different if boolc were used instead of xsdbool. Firstly, the transformations would have a different result (since the values "X" and " " are not transformed to true or false); secondly, the logical expression gui_flag = abap_false would always be false (since abap_false loses its blank when converted to the type string). 



DATA(gui_flag) = xsdbool( cl_demo_sap_gui=>check( ) ). 

CALL TRANSFORMATION id SOURCE gui_flag = gui_flag 

                       RESULT XML DATA(xml). 

DATA(writer) = 

  cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). 

CALL TRANSFORMATION id SOURCE gui_flag = gui_flag 

                       RESULT XML writer. 

DATA(json) = writer->get_output( ). 

cl_demo_output=>write_xml( xml ). 

cl_demo_output=>write_json( json ). 

IF gui_flag = abap_false. 

  cl_demo_output=>get( ). 

ELSE. 

  cl_demo_output=>display( ). 

ENDIF. 

XSDBOOL BOOLC SPACE & INITIAL

Below code snippet shows the difference between a string of initial state and a string of length 1 with blank value masquerading as abap_false boolean value.

As of ABAP release 740 SP08, xsdbool function can be used to get rid of such ambiguity.



DATA(lv_cstring_false) = boolc( 1 LT 0 ).

IF lv_cstring_false EQ abap_false.

  BREAK-POINT. "not called

ENDIF.

DATA(lv_xsdbool_false) = xsdbool( 1 LT 0 ).

IF lv_xsdbool_false EQ abap_false.

  BREAK-POINT.  "called

ENDIF.

IF lv_cstring_false IS INITIAL.

  BREAK-POINT.  "called

ENDIF.



Inbuilt functions help the developer to write more compact code and get rid of helper variables.

Example taken from keyword documentation. Instead of declaring a boolean variable and using IF-ELSE-ENDIF block to fill it based on contents of sy-batch, inbuilt function can be used.

PARAMETERS word TYPE c length 30. 

DATA result_tab TYPE cl_abap_docu=>search_results. 

cl_abap_docu=>start( 

  EXPORTING word           = word 

            no_dialog      = boolc( sy-batch IS NOT INITIAL ) 

  IMPORTING search_results = result_tab ). 

  

  

If specific methods are expecting values like Y,N instead of X,space, translate function can be used inline.

DATA lv TYPE string.

lv = boolc( 1 GT 2 ).

DATA(lv_flag) = translate( val = lv from = ' X' to = 'NY' ).

WRITE / lv_flag.

lv = boolc( 1 LT 2 ).

lv_flag = translate( val = lv from = ' X' to = 'NY' ).

WRITE / lv_flag.



NOTE: abap_false loses its blank when converted to the type string. This is heavy.

Monday, December 11, 2017

Removed Malware From Intex Aqua

The smart phones I have used never had any adware issue. (Micromax and Lava). On the other hand, my mother's phone is an Intex Aqua which is loaded with shitty bloatware.

Although my mother adjusts a lot, using the phone was royal PITA because it showed fullscreen ads all the time, every if there is an incoming call. How irritating would that be if a person is getting an incoming call and he is unable to do anything about it.

A google search directed me to a personal blog of a guy who documented the steps he took to clean up his Intex mobile. I followed same steps but they did not work as my phone was infected in a different way than his.

Anyways the idea was to run malwarebytes app to know which apps are naughty, all of them being system apps so malwarebytes won't be able to uninstall them. I was even not given an option to disable such apps like System Update, Software Update, ImageEdit, Beauty something.

Here is the sequence of events.

1. Installing / using latest version of kingroot from official site. Failed 3 times.

2. Using Kingroot's Purify to free up some space.

3. Installing / using lower version of kingroot from xda developers site. Failed 3 times.

4. Installing / using lastest version of kingoroot from some site. Failed 3 times and then root successful.

5. Ran older version of kingroot to remove apps, but it try to take over root and in the process somehow unrooted the phone.

6. Kingoroot failed root attempt 5 times.

7. Using latest version of kingroot and root successful.

8. Removing offending apps from kingroot.

9. Unchecked the checkbox which allowed installing apps from unknown sources.

10. Did not remove kingoroot and malwarebytes as I suspect they may be needed again if Intex pushed something.

Chained Methods and Method Chaining

Method chaining has been available for last few ABAP releases. This is applicable only for functional method calls. e.g. meth1( )->meth2( )->meth3( ).

Chained statement using colon operator is also available since long long time. e.g. data: a , b , c.

The programming guideline states some incorrect ways of chaining which pass syntax check but do not increase readability.

Recently I came across a standard code that was chaining method calls to make code readable just like macros.

Example:

meth1( p1 = 'A' p2 = :

'This' ) ,

'Is' ) ,

'It' ).

Such creativity is applicable only when last actual parameter differs and rest of the method call remains unchanged.

Friday, December 8, 2017

Sales Order Item Billing Plan Change

A while ago I wrote a code that used BAPI_CUSTOMERCONTRACT_CHANGE to fill acceptance date in contract data tab of sales order item.

The challenge was that once BAPI_SALESORDER_CHANGE is found to not support contract data changes, one would be tempted to use any suggestion given by web search. For e.g calling update FM which is almost like updating the db table itself.

Question is how one to come to use BAPI_CUSTOMERCONTRACT_CHANGE by old fashion investigation instead of web search. Since VEDA table has acceptance date with data element VADAT_VEDA, a where used search for BAPI* structure gave a hit. Next where used showed FMs, more importantly the ones starting with BAPI* that may do what I needed. Since system was configured to create billing plan with start date same as contract acceptance date, I was indirectly able to create billing plan of sales order item.

Today I had to fill end date of existing billing plans. No rule was configured that would transfer the date from contract data tab to billing plan tab. Since BAPI_CUSTOMERCONTRACT_CHANGE was ruled out and where-used searched did not return a BAPI* FM, web search led me to copy code of standard report SDFPLA02. I feel this approach is better than using FM BILLING_SCHEDULE_SAVE.

Reference: https://archive.sap.com/discussions/thread/188338

Thursday, November 30, 2017

The Loop Is Pulling Me Back

This blog was rebooted so that it could help me come out of the loop on a one mini blog per day basis.
Last few days have gone by without blogging. I would like to attribute it to inertia, workload spike and some traveling for family functions.
I sure do hope that this activity would  remind me that the loop is doing its thing and I must stay on track.

Thursday, November 23, 2017

Grouping Internal Tables

ABAP release 740 SP08 onwards.

In my previous post I mentioned using FOR table iteration expression for the first time ever.

When I tried to look at what else can be done using FOR in keyword documentation, it was all about grouping internal tables.

Grouping internal tables can be done using LOOP GROUP BY as well, but I hadn't used that either as that feature is also valid since 740 SP08.

So, I'll do some reading on LOOP GROUP BY first and then graduate to using FOR GROUP BY.

FOR Table Iteration

Today I used simplest form of table iteration using FOR keyword.

My use case was that I have list of values in an unstructured internal table, say integers 1, 2 and 3. I need to build a range table of those values so that IN operator of SELECT query can be used.

If I were building a range table using fixed variable values or hard coded literals, it would have been something like this. VALUE operator is something I know how to use in simple cases.

DATA range TYPE RANGE OF i.

range = VALUE #(

    ( sign = 'I' option = 'EQ' low = '1' )

    ( sign = 'I' option = 'EQ' low = '2' )

    ( sign = 'I' option = 'EQ' low = '3' )

  ).


Since I am having the values in internal tables, I would need to loop through it.

DATA integers TYPE TABLE OF i.

integers = VALUE #( ( 1 ) ( 2 ) ( 3 ) ).

range = VALUE #( FOR integer IN integers ( sign = 'I' option = 'EQ' low = integer ) ).



Before knowing FOR keyword, I would have done it like this.

DATA range TYPE RANGE OF i.

DATA integers TYPE TABLE OF i.

integers = VALUE #( ( 1 ) ( 2 ) ( 3 ) ).

LOOP AT integers INTO DATA(integer).

  APPEND INITIAL LINE TO range ASSIGNING FIELD-SYMBOL(<range_line>).

  <range_line> = VALUE #( sign = 'I' option = 'EQ' low = integer ).

ENDLOOP.



End result is identical.

Friday, November 17, 2017

Predicates In ABAP

Expression is something that has a result.

Relational expression is an expression whose result is truth value (true or false).

Other expressions are declaration, logical, constructor, table and calculation.

Relational expression can have comparison expression and predicates.

Comparison expression has joins operands using comparison operator.

Predicate qualifies an operand. Predicate operator is "IS".

This is implementing in ABAP using predicate expression, predicate function and predicate method calls.

Predicate expression examples:

1. variable IS NOT INITIAL

2. methodcall( ) IS NOT INITIAL

3. methodcall( ) IS INITIAL

As of ABAP 740 SP08, point 2 above can be written in short form.

IF methodcall( ).

<logic>

ENDIF.

Thursday, November 16, 2017

Simple Transformation to Serialize ABAP Deep Internal Table

Today I worked on an ABAP program to export batch classes, classifications and values to a cXML format file required by Ariba.

Serialization is ABAP to XML. Deserialization is the opposite.

Although I prefer XSLT over ST (both transformations are possible in SAP), I ended up using ST as I don't know XSLT properly yet.

A single internal table with deep structure was prepared which had all the data returned by relevant BAPIs.

The internal table was structured like this:

ROOT (itab)

  line

    class name

    class description

    characteristics (itab)

      line

        characteristic name

        characteristic description

    characteristic values (itab)

      line

        characteristic name

        characteristic value

        characteristic value description



Logic to traverse the internal table was written inside the transformation using tt:value tt:loop tt:cond+check tt:attribute commands.

To achieve proper node nesting, I needed an equivalent of LOOP WHERE in ST. This was possible by using tt:loop+name and tt:cond+check command.

Command tt:cond+check also allowed me to do something like "if var1 eq 'E'" and "if var2 eq var3".

DOCTYPE node could not be added using ST. So it was added by string manipulating the xml in ABAP code post transformation.



So, use of tt:cond and tt:loop+name qualifies this activity has something new (never done before) for me.

Wednesday, November 15, 2017

Optional Interface Methods

ABAP release 740 SP08 onwards.

Interface method definition has an addition DEFAULT FAIL/IGNORE that allows you to skip explicit method implementation in a class that implements the interface.

When this addition is not used, syntax check forces you to implement the method.

When addition is used, syntax check would pass.

At runtime, DEFAULT FAIL will raise exception during method call.

At runtime, DEFAULT IGNORE will call implicit blank method implementation.

More info here:

https://help.sap.com/doc/abapdocu_740_index_htm/7.40/en-US/abapmethods_default.htm

Stuck in a loop

I have been stuck in a loop for long time.

I will try to find or do new stuff and document it here.

Most of the stuff will be related to ABAP programming.