Link to presentation on “oDATA  AND SAPGateway”I did earlier this year.


SAPUI5 with Gateway

Link to presentation I did earlier for training my colleagues.


Understanding CSV files and their handling in ABAP

From my blog on SCN


In many ABAP developments, we use CSV files and sometimes there is confusion regarding CSV itself. Is it just a text file with values separated by commas ?

Let’s look at semantics of the various components involved so we have a vocabulary to work with.

Separator: Demarcates between two fields – so it will be a comma ‘,’ for CSVs.

Delimiter: It signifies limits of things, where it begins and ends. e.g. “Test String” has two delimiters, both double quote characters. Many CSVs can have double quotes as delimiters when comma values are to be placed as text.

Terminator : Indicates end of sequence. For CSV, we can think of newline as the terminator.

So if we have confusion about whether commas or double quotes are allowed inside data, looking at the CSV specification:

The de facto standard for CSV is here in case you want to read the full standard.


Definition of the CSV Format

1.  Each record is located on a separate line, delimited by a line break.

2. The last record in the file may or may not have an ending line break.

3.  There maybe an optional header line appearing as the first line of the file with the same format as normal record lines.

4.  Within the header and each record, there may be one or more fields, separated by commas.  Each line should contain the same

number of fields throughout the file.  Spaces are considered part of a field and should not be ignored.  The last field in the

record must not be followed by a comma.

5.  Each field may or may not be enclosed in double quotes (however some programs, such as Microsoft Excel, do not use double quotes

at all).  If fields are not enclosed with double quotes, then double quotes may not appear inside the fields.

6.  Fields containing line breaks (CRLF), double quotes, and commas should be enclosed in double-quotes.

7. If double-quotes are used to enclose fields, then a double-quote appearing inside a field must be escaped by preceding it with

another double quote.

In my experience, point 7 is where we get tripped the most. CSV stands as comma separated values leading to the impression that commas are the separator and given that excel doesn’t put commas, it can start to get confusing.

So looking at some examples

Basic Example:

10, Vikas , Sydney

Data with separator / delimiter inside them.

“11”, “Vikas”, “Sydney, AU”      <– Data containing comma

“12”, “Vikas”, “Sydney, “NSW” AU”   <– Data containing comma and quotes in data

Handling in ABAP:

I’m focusing on reading the files as that’s where we face issues. The file can be uploaded from user’s desktop or read from the application server.

1)  Write your own code:

This can be easiest to start with but can start to get complicated with time.

Get data as a string, split at comma.

   split lv_data at ‘,’ into lw_struct-test1 lw_struct-test2 lw_struct-test3.


a) This won’t work if we have data with separator, terminator or delimiter ( so no commas, double-quotes or newline within data ).

b)  The code will need to be updated if the file format changes – say we need to add another field test4. The code then changes to :

   split lv_data at ‘,’ into lw_struct-test1 lw_struct-test2 lw_struct-test3 lw_struct-test4.

2) Read the file using KCD_CSV_FILE_TO_INTERN_CONVERT



    i_filename      = ‘C:\Temp\Upload.csv’

    i_separator     = ‘,’


    e_intern        = gt_intern


    upload_csv      = 1

    upload_filetype = 2.


a) The file can be read only from presentation server/ desktop.

b) If a CSV file exists with double quotes, the last field is left with double quotes.

c) In case the file is to be read from application server, we need to read the code inside this FM and write some custom logic.

3) Use RTTI and dynamic programming along with FM RSDS_CONVERT_CSV .

It works but has lots of code . You can have a look at the code in this GIST.


In summary the steps are :

– Get structre of destination table using RTTI

– Create field catalog

– Create a dynamic table for field catalog values

– Create dynamic table lines

– Process Raw CSV data

– Store CSV files into dynamic table


a) Relatively long code leading to results especially if you have to program it from scratch.


a) Code is free from the target table format. If a new field is to be added, just update the structure for table typez_data_tty


So the call becomes very straight forward – Instantiate the class with the separator and delimiter values. For a normal CSV, leave them as default .

* Instantiate the CSV object

  call method cl_rsda_csv_converter=>create


*    i_delimiter = C_DEFAULT_DELIMITER

*    i_separator = C_DEFAULT_SEPARATOR


      r_r_conv    = lo_csv

* Process records

  loop at lt_upload_data into lv_data.


    CALL METHOD lo_csv->csv_to_structure


        i_data   = lv_data


        e_s_data = lw_struct.


That’s It !


a) The code is very small – less chances of us making an error compared to the one in 3) above.

b) The code is decoupled with file structure – we get to keep the benefit from the above point .

c) It can be used for both application server / presentation server files – of course file reading will need to be done before the call.

d) The developer has documented the examples exhaustively in method CSV_TO_STRUCTURE . Big thank to him/her !

e) It’s part of package RSDA which is present in ABAP trial environments as well such as NSP .

If you feel lazy to type the full program, here is the whole source code:



Installation and version management of mobile applications without any MDM solution

From my SCN blog post:


While testing applications, we used the below strategies and it took us some time to work these out. So I sum these up as reference – I trust people will find it useful. These are based on my experience in dealing with iOS apps.

Problem 1: I was working on an enterprise mobile application project but we couldn’t use the organisation’s pre-existing mobile device management ( MDM ) solution. This can happen due to any number of factors – in our case, the app was simply too big to be supported by the current version of MDM solution (it’s not a SAP MDM solution ).

Solution :

We used the below alternatives and they can be employed to work.

1. DropBox. A simple html page can be created in DropBox which points to the app’s plist file ( property list file ) and the plist file in turn will point to the relative location of the .app file. I kept the app in the Public folder of dropbox.

Let me draw a picture to make it clearer.

Screen Shot 2014-08-23 at 11.07.08 pm.png

2. TestFlight: I wasn’t aware of this site when we were first working on testing release I but found it extremely useful for subsequent releases. You can set up a project team, assign users to test and check the devices registered.

See the sample screenshot below.

Screen Shot 2014-08-23 at 6.png

3. Through a public site. You’ll need infrastructure team to create a publicly accessible domain ( if you want them to access via normal internet ).

Add the below MIME types to your web server ( for IIS ).

Mime type for plist -> application/xml

Mimet type for ipa -> application/octet-stream

4. The most obvious one : If the users can come to your desk, of course just use Xcode to install by making the device a developer device.

Hints on creating the HTML page:

a) Create the HTML page – this page will point to the plist file.


<a href=”itms-services://?action=download-manifest&url=http://dl.dropbox.com/u/xxxxxxxxx/app_live.plist“>Download App</a>

This will create a quick and dirty page for users to install the app.

Screen Shot 2014-08-23 at 5.58.09 pm.png

Of course, you can make it better by adding icons etc.

b) The plist file will in turn point to the .ipa file. You’ll need to edit it manually from the one generated by Xcode.

<?xml version=”1.0″ encoding=”UTF-8″?>

<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd“>

<plist version=”1.0″>























   <string>Name Of Application</string>






Problem 2: While testing we realised that sometimes the user’s app version was outdated and they’ll report issues or have inconsistencies due to a lower version. This can cause a lot of confusion.

Solution :


– Store the supported version of the app on a text file in an external URL .

– Get the version of the app and compare the version from an external URL.

– If the version in the app is lower than the supported version , display a message asking the user to upgrade and quit.

The supported version may not be the current version of the app – for minor UI tweaks, we may not change the supported version but if there are changes to the underlying object structure, the supported version will need to be changed.

Sample Objective-C code:  We can put it in the Main View Controller.

Main view controller :

    [self checkifObsoleteAppVersion];


– (void) checkifObsoleteAppVersion{


//Get version from external site

    NSString *versionURLString = @”http://URL/version.txt;  //<<– Version information stored in a simple text file

    NSURL *versionURL = [NSURL URLWithString:[versionURLStringstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    NSString *versionOnExternalSite = [[NSString stringWithContentsOfURL:versionURLencoding:NSUTF8StringEncoding error:nilsubstringToIndex:6];


//Get version from App

    NSString *versionFromApp = [self.syncManager.appVersion substringToIndex:6];


//Format the versions to numbers

    NSNumberFormatter *versionFromAppNo = [[[NSNumberFormatter alloc]init]autorelease];

    NSNumber *appNo = [ versionFromAppNo numberFromString:versionFromApp];


    NSNumberFormatter *versionFromAppNoExt = [[[NSNumberFormatter alloc]init]autorelease];

    NSNumber *appNoExt = [ versionFromAppNoExt numberFromString:versionOnExternalSite];


//App version shouldn’t be lower than the one maintained in version file


    if ([appNo floatValue] < [appNoExt floatValue] )



// Show a message

        UIAlertView *appObsoleteView = [[[UIAlertView alloc]initWithTitle:@”App version obsolete”message:@”A new version of App has been released and this version is obsolete.Please upgrade App to the new version.” delegate:self cancelButtonTitle:@”Exit” otherButtonTitles:nil, nil]autorelease];

        appObsoleteView.tag = 666;

        [appObsoleteView show];








Problem 3: Just putting as a reference to consolidate the information in a single place. Users were required to be manually registered and there were issues caused sometimes due to wrong information being set up due to manual process.



I created a solution using SUP’s Java APIs and shared the experience in an earlier blog.




Retain selection screen values on program restart for transactions with chosen selections

From my blog on SCN


I had an interesting last week and what looked easy at the outset did my head in for quite a while. I tried various methods and the below approach was able to give me a satisfactory solution.

Let’s have a look at the high level requirement.

– Copy a standard SAP transaction and customise it . Below picture describes the requirement

Screen Shot 2014-08-16 at 7.28.17 pm.png

The transaction is started with only few fields of the complete selection screen as the selection screen has too many fields and may confuse the users.


The users need to navigate back and forth between different modes of output screen. At the first display of output screen ( let’s call them as levels – so the output screen is at level 0 when initially displayed and if called again goes to level 1 and so on . Similarly when the user comes back from a higher level of screen, the level will decrease : from 1 to 0 ). And of course when the program navigates back from level 0 of selection screen, it should display the selection screen.

I prototyped using a simple program using flight model.

– Selection Screen : Contains all fields.

All fields.PNG

However, the transaction is always run with a variant which hides the last field.

Selection Screen.PNG

– Let’s test with some data.

Selection Test.PNG

We get the level 0 output screen.

Level 0.PNG

Now click on filter ( search icon on top right )


and we get level 1 screen.

Level 1.PNG

Looks good so far. Now, let’s try going back – going back to level 0 gives the screen as anticipated. However, when we go back and see that the selection screen parameters have gone back. The selection screen has gone blank !

Selection Screen.PNG

Let’s see what’s going on.

As we need to keep track of different levels of screen, if the level of screen is greater than 0.


ELSEIF syucomm = ‘EXIT’.

    IF gv_list_level > 0.

      gv_list_level = gv_list_level 1.

      gt_flight[] = gt_master_flight[].

      CALL SCREEN 100.


When we want to go back to selection screen from screen at level 0, we use below:

SUBMIT zsubmit_flight

            WITH report EQ ‘ZTESTFLIGHT’

            WITH variant = ‘ZFLIGHT_VAR’

            WITH SELECTION-TABLE gt_seltab .

zsubmit_flight is a standard SAP report used by the report and can’t be changed by us.



                    VIA SELECTION-SCREEN


1) Store selected values by call of RS_REFRESH_FROM_SELECTOPTIONS 

2) Export the selection table before doing a program restart.

EXPORT gt_seltab TO MEMORY ID gc_sel_mem.

3)  Retrieve the selection table AT SELECTION-SCREEN OUTPUT.

RS_VARIANT_CONTENTS gives the parameters and select-options actually visible in the variant.

IMPORT gt_seltab FROM MEMORY ID gc_sel_mem.

  IF NOT gt_seltab[] IS INITIAL.



        report              = ‘ZTESTFLIGHT’

        variant              = ‘ZFLIGHT_VAR’


        l_params            = lt_params

        l_selop              = lt_selops

        valutab              = lt_value


        variant_non_existent = 1

        variant_obsolete    = 2

        OTHERS              = 3.

    IF sysubrc <> 0.

clear: lt_value,




* Update parameters values

    LOOP AT lt_params INTO lw_param.

      READ TABLE gt_seltab REFERENCE INTO lo_values WITH KEY selname = lw_paramname.

      IF sysubrc = 0.

        lv_attr = lo_values->selname.

        TRANSLATE lv_attr TO UPPER CASE.

        ASSIGN (lv_attr) TO <fs_attr_val>.

        <fs_attr_val> = lo_values->low.



* Update select-option values

    LOOP AT lt_selops INTO lw_param.

      READ TABLE gt_seltab REFERENCE INTO lo_values WITH KEY selname = lw_paramname.

      IF sysubrc = 0.

        CONCATENATE lo_values->selname ‘SIGN’ INTO lv_attr SEPARATED BY ‘-‘.

        TRANSLATE lv_attr TO UPPER CASE.

        ASSIGN (lv_attr) TO <fs_attr_sign>.

        <fs_attr_sign> = lo_values->sign.

        CONCATENATE lo_values->selname ‘OPTION’ INTO lv_attr SEPARATED BY ‘-‘.

        TRANSLATE lv_attr TO UPPER CASE.

        ASSIGN (lv_attr) TO <fs_attr_option>.

        <fs_attr_option> = lo_values->option.

        CONCATENATE lo_values->selname ‘LOW’ INTO lv_attr SEPARATED BY ‘-‘.

        TRANSLATE lv_attr TO UPPER CASE.

        ASSIGN (lv_attr) TO <fs_attr_low>.

        <fs_attr_low> = lo_values->low.

        CONCATENATE lo_values->selname ‘HIGH’ INTO lv_attr SEPARATED BY ‘-‘.

        TRANSLATE lv_attr TO UPPER CASE.

        ASSIGN (lv_attr) TO <fs_attr_high>.

        <fs_attr_high> = lo_values->high.

        lv_attr = lo_values->selname.

        TRANSLATE lv_attr TO UPPER CASE.

        ASSIGN (lv_attr) TO <fs_attr_main>.

        CONCATENATE lv_attr ‘[]’ INTO lv_attr_tab.

        ASSIGN (lv_attr_tab) TO <fs_attr_tab>.

        IF lo_values->low IS NOT INITIAL OR lo_values->high IS NOT INITIAL.

          REFRESH <fs_attr_tab>.

          APPEND <fs_attr_main> TO <fs_attr_tab>.





– Create a transaction ‘ZFLIGHT’ with program ZTESTFLIGHT , variant ZFLIGHT_VAR.

The code can be referred here:

The code can be referred here:



Program ZTESTFLIGHT with issues:


Program  ZTESTFLIGHT with corrections:

ABAP_Demo/ZTESTFLIGHT_2 at master · viksingh/ABAP_Demo · GitHub

The key here is function module RS_VARIANT_CONTENTS and the dynamic update of selection screen after restart of a transaction.



Program ZTESTFLIGHT with issues:


Program  ZTESTFLIGHT with corrections:

ABAP_Demo/ZTESTFLIGHT_2 at master · viksingh/ABAP_Demo · GitHub

The key here is function module RS_VARIANT_CONTENTS and the dynamic update of selection screen after restart of a transaction.

ABAP dynamic internal table sort saves the day

Requirement to refresh the ALV to display only display unique fields. Thankfully the sort fields of an itab can be specified dynamically now.


SORT gt_output BY (lt_sorttab).
CATCH cx_sy_dyn_table_ill_comp_val.
gt_output[] = lt_output[].

Understanding and updating MIGO defaults in ABAP

Posted on SCN at http://scn.sap.com/community/abap/blog/2014/07/28/understanding-and-modifying-migos-defaults-programmatically.

Recently I had a situation where I needed to update MIGOs defaults programatically. I tried to search for a solution but couldn’t see it mentioned anywhere and hence decided to write it down . I hope that it’ll be useful for anyone in a similar situation.



MIGO is a multi-purpose transaction which can be used for various activities in material management – performing goods movements, receipt of purchase order etc. It replaces many older transactions . There are others as well but to list down a few:


  • Post a goods receipt to a known purchase order (transaction MB01)
  • Change a material document from goods receipts (transaction MB02)
  • Display a material document from goods receipts (transaction MB03)
  • Cancel a material document from goods receipts (transaction MBST)


To understand why we may need to ever need to modify MIGO defaults, consider the below situation.


– A file arrives for processing in SAP ( say as a batch job ) .


– Initial goods movement is tried using a BAPI. If the processing fails , a user SM35 BDC session is created for processing which can be reprocessed by users ( the users are familiar with MIGO ). A custom transaction for reprocessing is created as the users couldn’t be given access to SM35. SM35 allows you to display and potentially reprocess all sessions which can be tricky if the authorisations are a bit leaky.





The failed sessions can then be processed by a custom transaction – the SM35 sessions are persisted to a temporary table to be used by reprocessing transaction.




Everything looks good in theory : all automatic postings are done in background and any errors can be handled by the custom transaction. However, while the user is performing the reprocessing the MIGO session, something interesting happens – if the user opens a parallel MIGO session and performs some other processing in parallel, the subsequent sessions start to fail in the custom transaction. Users could be processing multiple sessions sequentially and might go away and do some other movements in parallel in MIGO.



Why does this happen ?


MIGO stores user’s defaults trying to optimise the usage so that the user doesn’t have to set the selections – this causes the defaults to be always set whenever you use the transaction. The parallel session which the user opened has overridden the defaults and as a result, subsequent failed sessions have different default values set in the screen even though the BDC recording used in SM35 session was set correctly. User defaults is overriding BDC set values .



Looking at the below image, the BDC session has set values A07 and R10 for action and sub-selection within action.



However, if the user choses something else in a parallel session ( say A05 and a sub-selection ) , it overrides the action default and subsequent SM35 sessions start failing as then MIGO will start with A05 / sub-selection.




MIGO stores user’s defaults in table ESDUS and these defaults correspond to MIGO_FIRSTLINE action. Seeing the below table entries, the settings for the user are:


Default is action = A07

and sub-selection for A07 is R10.


Hence, A07 / R10 will appear for ACTION and sub-selection ( as shown in above image ) .



Show Me The Code:


Now, we know where they’re stored, how to update them ?


Class CL_MMIM_USERDEFAULTS can be used to  read and update the parameters. It’s a singleton and hence there should be only instance at a given time. Consequently, if we’re using it we have to ensure the instance is destroyed . This is achieved by FLUSH_ALL method of the class. Above methods are self explanatory and the constructor requires ACTION value.




So I did the following:

– Instantiate the class using ACTION as “MIGO_FIRSTLINE” and set the instance values.

– Set the values:


                                         ( i_element = ‘ACTION’
= lv_action      ).


– Flush the value to dB and destroy the instance

o_migo_defaults->flush( ). “Save values to dB
->flush_all( ). “Destroy this instance as others instance will start producing errors

The table has other values used in MIGO defaults ( e.g. default movement type for an action ) and can be similarly updated.

Integration Gateway in SAP Mobile Platform 3.0

Main features of SMP 3.0 :

– SUP, Agentry and Mobiliser combined. This itself is a pretty big as each of the platforms had an integration framework and it had to be harmonised . It’s simplified to just use SMP with services exposed in oData format.

– Through SMP 3.0, services from ABAP backend ( using SAP Gateway ) and non SAP backends can be easily consumed. This is pretty powerful as data could be spread out over multiple kinds of data sources. It allows for data consumption from JPA, JDBC , SOAP  etc.

– Eclipse GWPA has been enhanced for new features – to consume services from different backend types.

– A big drawback I see is that it doesn’t seem to talk about MBO based replication. My first iOS mobility project involved creating an iOS ( iPAD app ) using SUP which was based on MBOs and it’s sad to see them go. Support for offline capabilities is planned from later releases of SMP 3.0.

– A big positive is the ability to schedule different data based on speed ( or other requirements ) – the ability to assign priorities in scheduling is a big one – our users were extremely frustrated that they can’t control the information they wanted and had to wait for sync of everything from past before relevant data for today could be synced.

 Comparisons between SAP Gateway and SAP Integration Gateway:

– ABAP based vs Lean Java server ( Java, OSGI ).

– Supports SAP vs Supports both SAP and non-SAP data sources.

– Available as a standalone solution vs embedded inside SMP 3.0 .

– On premse vs On premise / Cloud.


SAP HANA CDS ( Core Data Services )

With SAP HANA platform, there has been a major shift in the way database is looked at. Traditionally, ABAP developers brought most of the data back to application server and manipulated based forming the core logic of the application.With HANA, the emphasis has been to do more in the databse ( akka code pushdown ).

However, there are some major drawbacks:

– It relies on development in two areas : HANA views / procedures which are then consumed in ABAP.

– Two separate mechanisms for ALM with ABAP and HANA transports.

With SAP NW 7.4 SP5, ABAP open SQL has been enhanced and views can be created using DDL. This is known as CDS ( Core Data Services ) .

Looking at an example: Create a basic view.

And the view can be consumed in ABAP – Need to add @ annotation .




These can be extended so that if DDIC additions are made, the view gets them automatically.


And the views can be made more complex.



and even more complex.




This to me looks like a step in the right direction as:

– it’s open SQL and hence is dB agnostic. Hence, it can be supported for other vendors databases in future.

– No separate development done in HANA reducing complexity of application development

ABAP SP5 on HANA is out

Cloud Appliiance Library has been updated with SP5. This is a big release as it has lot of “code push down” features.

Performance Worklist Tool: The SQL Performance Worklist (Transaction: SWLT) allows you to correlate SQL runtime data with ABAP code analysis to plan optimizations using results from the new SQLMonitor and CodeInspector.

CDS Viewbuilding: CDS Viewbuilding is drastically improving the existing viewbuilding mechanisms in ABAP.

Extended OpenSQL: Open SQL has been enhanced with new features, especially a lot of limitations have been removed, the JOIN functionality has been enhances as have been arithmetical and string expressions.

ABAP managed Database Procedures (AMDP): AMDPs enables you to create database procedures directly in ABAP using e.g. SQL Script and to seamlessly integrate it in modern ABAP development. An AMDP can be implemented using an ABAP method. 

And then there are additions to ABAP.

– MOVE-CORRESPONDING for Internal Tables : No longer RTTI required for such activities.

and some more:

Expressions and Functions

Table Comprehensions


Open SQL additions

Links :



Two more enhancements with the solution from CAL ( Cloud Appliance Library ) :

– Front End provided  , installation of eclipse and HANA studio no longer mandatory e.g. if you have a mac.

– BW is present in the same system.