Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
Ramjee_korada
Active Contributor
8,626

A frequent business requirement involves enabling mass changes to business objects via Excel uploads executed through a custom action popup. Historically, achieving this functionality has necessitated various workarounds, often involving UI5 extensions, third-party solutions, or Object Page manipulations, all of which present specific implementation challenges.

The existing workaround approaches present several drawbacks:

  • Custom UI Extensions: Require specialized UI5 development expertise.

  • Third-Party Solutions: Introduce risks related to licensing compliance and potential security vulnerabilities.

  • Object Page Manipulations: Involve complex, multi-step processes, such as creating a dummy object page, facilitating file upload, temporarily storing the file data in a table field, and requiring a final user action (a button press) to initiate processing. This temporary data storage is often unnecessary, complicating the data model.

However, SAP has recently introduced ABAP / CAP annotations that offer a cloud-ready solution, potentially eliminating approximately 95% of the development effort typically associated with integrating an Excel upload into the backend. This innovation allows developers to prioritize implementing core business logic over developing reusable technical artifacts.

I will now detail the implementation steps.

A business requirement to manage mass processing listings for a library was selected to demonstrate this use case. The implementation requires several steps, with steps 3 through 6 being the special or additional configurations needed, while all others are considered routine.

Ramjee_korada_0-1759618459647.png

Note:

This feature is currently functional on the BTP ABAP Environment. However, an issue appears to exist with metadata generation on S/4HANA 2023 On-Premise deployments, even though the objects are syntactically correct. It is anticipated that this constraint will be addressed in the S/4HANA 2025 release, making the full feature set available on the S/4HANA On-Premise version following a brief waiting period.

Implementation Steps

  1. A database table for the listing entity is created. This involves fields such as Id, Title, Type, and Author.
@EndUserText.label : 'Library Listings'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zrk_lib_listings {

  key client            : abap.clnt not null;
  key listing_uuid      : sysuuid_x16 not null;
  id                    : abap.numc(10);
  title                 : abap.char(40);
  type                  : abap.char(5);
  author                : abap.char(40);
  publisher_studio      : abap.char(40);
  isbn_ean              : abap.char(40);
  language_code         : abap.lang;
  publication_year      : abap.numc(4);
  description           : abap.char(40);
  totalcopies           : abap.int2;
  available_copies      : abap.int2;
  location_shelf_id     : abap.char(40);
  lending_duration_days : abap.int2;
  status                : abap.char(40);
  cover_image_url       : abap.char(100);
  local_created_by      : abp_creation_user;
  local_created_at      : abp_creation_tstmpl;
  local_last_changed_by : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;

}​

2. A RAP Business Object (BO) is generated, followed by the requisite UI artifacts. The specific RAP BO scenario (Managed, Unmanaged, Draft, or Non-Draft) is noted as not influencing the core Excel upload use case. The RAP Generator is used to simplify the demonstration.
Ramjee_korada_0-1759617725687.png

3. A root abstract entity is created for the file to be uploaded. (This entity is highly reusable and can be applied across different RAP BOs).

@EndUserText.label: 'Abs. Entity For Attachment'
define root abstract entity ZRK_D_FILE_STREAM
{
  @Semantics.largeObject.mimeType: 'MimeType'
  @Semantics.largeObject.fileName: 'FileName'
  @Semantics.largeObject.contentDispositionPreference: #INLINE
  @EndUserText.label: 'Select Excel file'
  StreamProperty : abap.rawstring(0);
  
  .hidden: true
  MimeType : abap.char(128);
  
  .hidden: true
  FileName : abap.char(128);   
}

4. The abstract behavior definition for the file entity is implemented.

abstract;
strict(2);
with hierarchy;
define behavior for ZRK_D_FILE_STREAM {
}

5. A second abstract entity is created to serve as an action parameter. This entity includes an association to the file abstract entity (from Step 3).

@EndUserText.label: 'Action Param for Uploading Excel'
define root abstract entity ZRK_D_UPLOAD_EXCEL
{
// Dummy is a dummy field
@UI.hidden: true
dummy : abap_boolean;
     _StreamProperties : association [1] to ZRK_D_FILE_STREAM on 1 = 1;
    
}

6. The abstract behavior definition for the action parameter is implemented, including the association to the earlier entity.

abstract;
strict ( 2 );
with hierarchy;
define behavior for ZRK_D_UPLOAD_EXCEL //alias <alias_name>
{
association _StreamProperties with hierarchy;
}

7. An action is defined on the RAP BO Behavior definition, with the parameter specified in Step 5.

  static action ExcelUpload deep parameter ZRK_D_UPLOAD_EXCEL ;
managed implementation in class ZRK_BP_R_LIB_LISTINGS unique;
strict ( 2 );
with draft;
extensible;
define behavior for ZRK_R_LIB_LISTINGS alias Listings
persistent table ZRK_LIB_LISTINGS
extensible
draft table ZRK_LIB_LSTNGS_D
etag master LocalLastChangedAt
lock master total etag LastChangedAt
authorization master( global )
{
  field ( readonly )
   ListingUUID,
   LocalCreatedBy,
   LocalCreatedAt,
   LocalLastChangedBy,
   LocalLastChangedAt,
   LastChangedAt;

  field ( numbering : managed )
   ListingUUID;


  create;
  update;
  delete;

  draft action Activate optimized;
  draft action Discard;
  draft action Edit;
  draft action Resume;
  draft determine action Prepare;

  static action ExcelUpload deep parameter ZRK_D_UPLOAD_EXCEL ;

  mapping for ZRK_LIB_LISTINGS corresponding extensible
  {
    ListingUUID = listing_uuid;
    ID = id;
    Title = title;
    Type = type;
    Author = author;
    PublisherStudio = publisher_studio;
    IsbnEan = isbn_ean;
    LanguageCode = language_code;
    PublicationYear = publication_year;
    Description = description;
    Totalcopies = totalcopies;
    AvailableCopies = available_copies;
    LocationShelfID = location_shelf_id;
    LendingDurationDays = lending_duration_days;
    Status = status;
    CoverImageUrl = cover_image_url;
    LocalCreatedBy = local_created_by;
    LocalCreatedAt = local_created_at;
    LocalLastChangedBy = local_last_changed_by;
    LocalLastChangedAt = local_last_changed_at;
    LastChangedAt = last_changed_at;
  }

}

8. The business logic is implemented to read the Excel content. A released API, XCO_CP_XLSX , is used for this demonstration.

 METHOD ExcelUpload.
    TYPES : BEGIN OF ty_sheet_data,
              id                  TYPE zrk_r_lib_listings-id,
              title               TYPE zrk_r_lib_listings-title,
              type                TYPE zrk_r_lib_listings-Type,
              author              TYPE zrk_r_lib_listings-author,
              PublisherStudio     TYPE zrk_r_lib_listings-PublisherStudio,
              IsbnEan             TYPE zrk_r_lib_listings-IsbnEan,
              LanguageCode        TYPE zrk_r_lib_listings-LanguageCode,
              PublicationYear     TYPE zrk_r_lib_listings-PublicationYear,
              description         TYPE zrk_r_lib_listings-Description,
              Totalcopies         TYPE zrk_r_lib_listings-Totalcopies,
              AvailableCopies     TYPE zrk_r_lib_listings-AvailableCopies,
              LocationShelfID     TYPE zrk_r_lib_listings-LocationShelfID,
              LendingDurationDays TYPE zrk_r_lib_listings-LendingDurationDays,
              status              TYPE zrk_r_lib_listings-Status,
            END OF ty_sheet_data.

    DATA lv_file_content   TYPE xstring.
    DATA lt_sheet_data     TYPE STANDARD TABLE OF ty_sheet_data.
    DATA lt_listing_create TYPE TABLE FOR CREATE zrk_r_lib_listings.

    lv_file_content = VALUE #( keys[ 1 ]-%param-_streamproperties-StreamProperty OPTIONAL ).

    " Error handling in case file content is initial

    DATA(lo_document) = xco_cp_xlsx=>document->for_file_content( lv_file_content )->read_access( ).

    DATA(lo_worksheet) = lo_document->get_workbook( )->worksheet->at_position( 1 ).

    DATA(o_sel_pattern) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to(
      )->from_column( xco_cp_xlsx=>coordinate->for_alphabetic_value( 'A' )  " Start reading from Column A
      )->to_column( xco_cp_xlsx=>coordinate->for_alphabetic_value( 'N' )   " End reading at Column N
      )->from_row( xco_cp_xlsx=>coordinate->for_numeric_value( 2 )    " *** Start reading from ROW 2 to skip the header ***
      )->get_pattern( ).

    lo_worksheet->select( o_sel_pattern
                                     )->row_stream(
                                     )->operation->write_to( REF #( lt_sheet_data )
                                     )->set_value_transformation(
                                         xco_cp_xlsx_read_access=>value_transformation->string_value
                                     )->execute( ).

    lt_listing_create = CORRESPONDING #( lt_sheet_data ).

    MODIFY ENTITIES OF zrk_r_lib_listings IN LOCAL MODE
           ENTITY Listings
           CREATE AUTO FILL CID FIELDS ( Id Title Type author PublisherStudio IsbnEan LanguageCode PublicationYear description Totalcopies AvailableCopies LocationShelfID LendingDurationDays status )
           WITH lt_listing_create
           " TODO: variable is assigned but never used (ABAP cleaner)
           MAPPED DATA(lt_mapped)
           " TODO: variable is assigned but never used (ABAP cleaner)
           REPORTED DATA(lt_reported)
           " TODO: variable is assigned but never used (ABAP cleaner)
           FAILED DATA(lt_failed).

    " Communicate the messages to UI - not in scope of this demo
    IF lt_failed IS INITIAL.
      APPEND VALUE #( %msg = new_message_with_text( severity = if_abap_behv_message=>severity-success
                                                    text     = 'Listings have been uploaded - please refresh the list!!' ) )
             TO reported-listings.
    ENDIF.
  ENDMETHOD.

9. The action is utilized on the projection behavior and subsequently exposed in the metadata extension.

  use action ExcelUpload;
projection implementation in class ZRK_BP_C_LIB_LISTINGS unique;
strict ( 2 );
extensible;
use draft;
use side effects;
define behavior for ZRK_C_LIB_LISTINGS alias Listings
extensible
use etag
{
  use create;
  use update;
  use delete;

  use action Edit;
  use action Activate;
  use action Discard;
  use action Resume;
  use action Prepare;

  use action ExcelUpload;

}
.lineItem: [{ type:#FOR_ACTION , dataAction: 'ExcelUpload' , label: 'Upload Excel' }]

10. The service binding is published, and the application is then ready for execution.

  • Ramjee_korada_2-1759616768674.pngRamjee_korada_3-1759616871331.pngRamjee_korada_4-1759616921974.pngRamjee_korada_5-1759617464764.png
    Ramjee_korada_6-1759617503382.png

     

 

 

 

23 Comments
Pankaj1
Participant
0 Kudos

Hi Ramjee,

It's a helpful blog but i am bit confused on 4th Step here as you didn't mention the abstract entity definition of reusable entity, it's a copy of 3rd step only. Also, i am working on SAP Cloud ERP Private edition(2023) and as you said, it can give error on metadata but it gives me error while defining abstract entity definition on the 6th Step, looks like you should add abstract entity definition here.

Ramjee_korada
Active Contributor
0 Kudos

Hi Pankaj,

Due to formatting issues, I had to edit the article a few times and made a mistake in step #4 while copying from Eclipse. It's corrected now.

There is no error in the metadata, but the required annotations are not generated in S4/HANA 2023.

Best wishes,
Ramjee Korada

junwu
SAP Champion
SAP Champion
0 Kudos

cool.

but why it requires a deep parameter for the action?

Ramjee_korada
Active Contributor
0 Kudos

@junwu 

as shown in step #5, it’s a nested structure. So, it’s a deep parameter.

junwu
SAP Champion
SAP Champion

that is what I am asking, why? why not just a flat structure.

chandu_reddy751
Discoverer
0 Kudos

Hi Ramjee.

Very good content, can't we achieve this upload without custom table?

Ramjee_korada
Active Contributor

@chandu_reddy751 

As mentioned, Steps #3 -6 are special that you need to implement. The custom table is not required if you have standard tables. 

The custom table is used for the underlying RAP BO to demonstrate a use case and it is not to store any attachments in DB.

Pankaj1
Participant
0 Kudos

@Ramjee_korada : Thanks for help. Can you also help in defining the solution for on-premise as this solution doesnt work there. Can i create abstract entity there with fields like mimetype, content & name and then let UI5 handle it from frontend? Do you have any reference for it?

Ramjee_korada
Active Contributor
0 Kudos

@Pankaj1 we have to wait to use this feature for on premise ( 2025 release ) yet. 
There are other workarounds to be applied meanwhile.

hariyoga21
Explorer
0 Kudos

Hi Ramjee,

Thanks for great blog,  I have the requirements to upload the file and use the file data(trip data) and upload the trip data using PR05  transaction.

Is it still required create the table? earlier i have GUI program where i used  to upload using csv file, i thought creating the same UI5 application using  transaction, however when upload csv file i am getting ole error,  now i am thinking of using RAP, in my selection screen just file upload is only field , it should take the data and upload  PR05, i have sap code to upload PR05, now i just need to know if i can use RAP to just upload file and use the contents to upload to PR05,  request you to advice, thanks in advance.

Hari Yoga 

Mayank_Mittal8
Discoverer
0 Kudos

hi Ramjee, 

Thanks for the informative blog, but can you please address the below points-

1. Why we need to create a deep parameter and 2 abstract hierarchy? Is it not possible with just one abstract hierarchy with semantics.largeObject annotations?

2. Maybe put the Note section( that this feature only applicable om BTP and not on OnPremise 2023) at the beginning of the blog.

3. You mentioned there are some workaround to do this in S4 hana OP 2023, can you describe that workaround/additional annotations?

 

Best Regards

Ramjee_korada
Active Contributor

@Mayank_Mittal8 

One abstractity refers to the attachment and other abstract entity refers to the action parameter.  The relavent documentation can be found here. The fiori elements does not render upload button unless they are annoated as decribed. See below.

Ramjee_korada_0-1760083154807.png

The relavent UI5 annotations are availble in above documentation and they can be implemented in BAS . Also note that the UI5 application needs to deployed/hosted on BTP however the data will be read from S4/HANA OnPremise 2023). 

Below are few workarounds:
https://spreadsheet-importer.com/ ( This provides advanced capabilities).
https://community.sap.com/t5/technology-blog-posts-by-members/upload-excel-using-sap-rap-only/ba-p/1...
https://community.sap.com/t5/technology-blog-posts-by-sap/streams-in-rap-uploading-pdf-excel-and-oth...
https://community.sap.com/t5/technology-blog-posts-by-members/a-step-by-step-guide-to-implementing-a...

 

 

 

younus187
Explorer
0 Kudos

Thanks @Ramjee_korada for sharing this valuable information. I am sure it will save lot of efforts and also ease the challenges wrt mass changes to business objects.

devayani_sharma6
Explorer
0 Kudos

@Ramjee_korada Thank you for writing this great post, I really liked it and it fits perfectly! 🙂

I had a tiny query related to the load and the performance impact as there are deep parameter and 2 abstracts entites being used in this approach, as this is or could be a mass upload where in tens of thousands or thousands of entries would be entered in the excel.

Thanks again! 🙂

Looking forward to your reply.

Ramjee_korada
Active Contributor

@devayani_sharma6 

The deep parameters and abstract entities wont cause performance issue as they are the model to upload an attachment.

If there are thousands of entries, then uploading an excel doesnot create issues but the processing time of business logic. 

In such cases, Application jobs are the best fit and they are cloud ready. 
Once the entries retrived from excel, then you trigger an application job so the user is not waiting on the screen.

I would recommend to have a look at section 3.2 from this blog post.

Best regards,
Ramjee Korada

Srija
Discoverer
0 Kudos

@Ramjee_korada  Thanks for the useful blog.

While trying to implement it following all the steps mentioned in the blog,

Srija_0-1760452315120.png

Srija_1-1760508407220.png

I am not able to enter any file name. Can you please share your thoughts on how this issue happened and what should be done from the BAS level for the upload icon?

patrick_winkler
Product and Topic Expert
Product and Topic Expert
0 Kudos

Hi @Ramjee_korada 
maybe you can add a side effect for the upload action so the table is automatically refreshed.

LuizSouza_L2D
Explorer
0 Kudos

Excelent! Could you please move the note about the S/4HANA 2025 release to the beginning of the blog? Some readers might otherwise miss it.

Ramjee_korada
Active Contributor
0 Kudos

@patrick_winkler I think side effect does not work for static action. I have to give a try.

Ramjee_korada
Active Contributor

@LuizSouza_L2D sure. Note is moved up.

chetan_shah9
Explorer
0 Kudos

@Ramjee_korada  - Hey this was very informative. One question, I tried to replicate this but observed even though i add annotation @Semantics.largeObject.acceptableMimeTypes in step 3 to ensure files are restricted to show only excel files , it shows all files in popup. Even the metadata all annotations except this one in network. Do you know why or what could be the issue ?

 

@EndUserText.label: 'Abstract Entity for File Stream'
define root abstract entity ZA_CHETU_FILE_STREAM

{
  @EndUserText.label: 'Select Excel file'
  @Semantics.largeObject: { mimeType: 'mimeType',
                            fileName: 'fileName',
                            acceptableMimeTypes: [ 'application/vnd.openxmlformats-officedocument.spreadsheetml.*',
                                                   'application/vnd.ms-excel' ],
                            contentDispositionPreference: #INLINE }
  attachment            : /dmo/attachment;

  @UI.hidden: true
  mimeType             : /dmo/mime_type;

  @UI.hidden: true
  fileName             : /dmo/filename;
}

 

venkatesh007
Explorer
0 Kudos

It works on the public cloud as well, right?

venkatesh007
Explorer
0 Kudos

I tried this in my SAP S/4HANA Public Cloud system, but I’m getting an error could you please help me

venkatesh007_0-1762708736444.png