This is the second part of the ‘How to setup file upload planning sequence from SAPUI5’ blog series. You can read the first part of the blog here: How to setup file upload planning sequence from SAPUI5 – Part 1
In the first part, we successfully sent the file upload data to the OData gateway service and I also mentioned how we can call a planning sequence from a UI5 app. The next step is to create a custom Planning Function type so we can execute our own logic to do a CSV file upload into BW-Integrated Planning
The file uploader for planning sequence only works with CSV files for now. It also expects that the order of the columns in the CSV file is the same as we have in the aggregation level. The sample working CSV format can be seen here.
Planning Function Type Creation
Before creating a new planning function type, we need to create a new ABAP class where we can implement the logic for the planning function type.
To create a new ABAP class, go to tcode SE24. Enter class name ‘ZPF_FILE_UPLOAD’ and click create. Select the object type as class. Activate the newly created class.
After activation, go to the Interfaces tab and enter IF_RSPLFA_SRVTYPE_IMP_EXEC entry. Save and activate the class.
Until now, we have a custom ABAP class which we can use in our planning function type.
Go to transaction ‘RSPLF1’ and enter the function type name ‘ZPF_FILE_UPLOAD’ and description and click on Create.
In the properties tab, enter the name of our custom ABAP class and activate the planning function type.
Implementing the EXECUTE method
Go to transaction SE24 again and display the ‘ZPF_FILE_UPLOAD’ class which we created earlier. Go to the Methods tab and click on the EXECUTE method.
We will write the logic to read the data from the uploaded file from SAPUI5 here. The following code reads the data from a CSV file which was converted to xstring in the gateway service and can be accessed globally from the memory id ‘z_upload_data’.
method IF_RSPLFA_SRVTYPE_IMP_EXEC~EXECUTE. DATA: l_data TYPE string, l_file_content TYPE xstring, l_t_column TYPE string, l_r_converter TYPE REF TO cl_abap_conv_in_ce, l_r_output_line TYPE REF TO data, l_t_data TYPE TABLE OF string, l_t_header TYPE TABLE OF string, l_t_line TYPE TABLE OF string. DATA: BEGIN OF crlf, cr TYPE c, lf TYPE c, END OF crlf, l_s_data TYPE string. FIELD-SYMBOLS: <l_s_data> TYPE any, <l_s_output> TYPE any, <l_field> TYPE any, <l_tab_data> TYPE any. * Read xstring containing file content import base64_xstring to l_file_content from memory id 'z_upload_data'. * Convert file content to string TRY. CALL METHOD cl_abap_conv_in_ce=>create EXPORTING input = l_file_content encoding = 'DEFAULT' replacement = '#' ignore_cerr = abap_false RECEIVING conv = l_r_converter. CALL METHOD l_r_converter->read IMPORTING data = l_data. CATCH cx_root. EXIT. ENDTRY. crlf = cl_abap_char_utilities=>cr_lf. * Convert CRLF to LF REPLACE ALL OCCURRENCES OF crlf IN l_data WITH crlf-lf. * Convert CR to LF TRANSLATE l_data USING crlf. * Split into table lines SPLIT l_data AT crlf-lf INTO TABLE l_t_data. * Make copy of data create data l_r_output_line LIKE LINE OF c_th_data. ASSIGN l_r_output_line->* to <l_s_output>. * Read first line of table READ TABLE l_t_data INTO l_s_data INDEX 1. * Split the first line (header) of the table SPLIT l_s_data AT ',' INTO TABLE l_t_header. * Loop remaining lines except the file header LOOP AT l_t_data assigning <l_s_data> FROM 2. "split current line SPLIT <l_s_data> AT ',' INTO TABLE l_t_line. "loop over the header split LOOP AT l_t_header assigning <l_tab_data>. read table l_t_line index SY-tabix into l_t_column. ASSIGN COMPONENT <l_tab_data> of structure <l_s_output> to <l_field>. <l_field> = l_t_column. ENDLOOP. * Modify c_th_data from internal structure MODIFY table c_th_data from <l_s_output>. ENDLOOP. endmethod.
The complete code for the class can be found on this link.
The next step is to do the following things:
- Create an aggregation level for InfoCube
- Create filter on InfoObjects
- Create a planning function
- Select function type as ZPF_FILE_UPLOAD (custom function type that we created)
- Create a planning sequence and select the aggregation level, filter and planning function created above.
Executing the planning sequence from SAPUI5
Until now, we have an implementation of a custom planning function which is now being used in the planning sequence we created. We will now call the planning sequence from the gateway service and execute the planning sequence. The following code executes the planning sequence and returns the messages/errors in the lt_bapiret table.
We will format the returned messages from the ‘RSPLSSE_PLSEQ_EXECUTE’ function and then return them to SAPUI5 and save the data to our InfoCube.
The complete code can be found here.
After executing a planning sequence, the returned messages will look like this on the SAPUI5 frontend.
You can find the code in the consetto github repository: https://github.com/consetto/ui5-file-upload-planning
Further improvements/features can be added in the current solution for file upload. Some of them are:
- Adding support for file upload from other file formats like excel, text file, etc.
- Preview the file data before saving it in the InfoCube
- Adding validations for correct order of columns in CSV file, InfoObject validations, correct file format/encoding, etc.
In this series of blogs, we looked at how to call a planning sequence in general and execute the underlying planning function from SAPUI5. I also explained how to do a CSV file upload into BW-Integrated Planning from SAPUI5 frontend. I hope it will help a lot of people who are looking for a solution to connect the SAPUI5 file upload for the plan data in BW-IP or BPC. I am looking forward to your feedback.