On many occasions, users need to upload an excel file from the local system and extract the content from the excel file to send to backend SAP. There are multiple ways to achieve the extraction of data from excel file and send the content to SAP system. In this article I am going to explain how one can download the content of an SAP table as a form off an excel file. We will also discuss in detail about how one can upload an excel file filled with table content and send the extracted data to back-end SAP. Finally, we will see how to convert the encoded data in back-end SAP. In this article we are going to use SAP gateway stream methods to extract SAP data and upload presentation server data to SAP.
DATA: lo_property TYPE REF TO /iwbep/if_mgw_odata_property,
lo_entity_type TYPE REF TO /iwbep/if_mgw_odata_entity_typ.
super->define( ).
lo_entity_type = model->get_entity_type( iv_entity_name = 'TableStructure' ).
IF lo_entity_type IS BOUND.
lo_property = lo_entity_type->get_property('MimeType').
lo_property->set_as_content_type( ).
ENDIF.
DATA: ls_stream TYPE ty_s_media_resource,
lv_data_string TYPE string,
lv_xstring TYPE xstring,
ls_header TYPE ihttpnvp,
lt_fields TYPE STANDARD TABLE OF dfies.
* Get Tablename passed from frontend
DATA(ls_key_tab) = VALUE #( it_key_tab[ name = 'TableName' ] OPTIONAL ).
* Get Column Lists from Table name
IF ls_key_tab-value IS NOT INITIAL.
CALL FUNCTION 'DDIF_FIELDINFO_GET'
EXPORTING
tabname = CONV ddobjname( ls_key_tab-value )
TABLES
dfies_tab = lt_fields
EXCEPTIONS
not_found = 1
internal_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
"Handle Suitable Error Here
ELSE.
* Build String with table coulmn names
LOOP AT lt_fields INTO DATA(lt_fields_line).
IF sy-tabix = 1.
lv_data_string = |{ lt_fields_line-fieldname }|.
ELSE.
lv_data_string = |{ lv_data_string }\t{ lt_fields_line-fieldname }|.
ENDIF.
CLEAR: lt_fields_line.
ENDLOOP.
* Convert String to xstring
CALL FUNCTION 'HR_KR_STRING_TO_XSTRING'
EXPORTING
unicode_string = lv_data_string
IMPORTING
xstring_stream = lv_xstring
EXCEPTIONS
invalid_codepage = 1
invalid_string = 2
OTHERS = 3.
* Pass back stream values
ls_stream-value = lv_xstring.
ls_stream-mime_type = 'application/msexcel'.
* Set Header for Response
DATA(lv_filename) = |{ ls_key_tab-value }-{ sy-datum }-{ sy-uzeit }.xls|.
lv_filename = escape( val = lv_filename format = cl_abap_format=>e_url ).
ls_header-name = 'Content-Disposition'.
ls_header-value = |outline; filename="{ lv_filename }"|.
me->set_header( ls_header ).
copy_data_to_ref(
EXPORTING is_data = ls_stream
CHANGING cr_data = er_stream ).
ENDIF.
ENDIF.
<ObjectPageSubSection id="customTableSel">
<blocks>
<layout:VerticalLayout>
<m:Input id="tableInput" width="100%" type="Text" placeholder="Enter Table Name ..." showSuggestion="true" suggestionItems="{/TableListSet}"
showValueHelp="true" valueHelpRequest="onValueHelpRequest" suggest="onSuggest" liveChange="onLiveChange">
<m:suggestionItems>
<core:Item text="{NameOfTable}"/>
</m:suggestionItems>
</m:Input>
<m:Button text="Download Template" press="onDownTempPressed" enabled="true"></m:Button>
</layout:VerticalLayout>
</blocks>
</ObjectPageSubSection>
onDownTempPressed: function (oEvent) {
var inputTableName = this.getView().byId("tableInput").getValue();
var mainUri = this.getOwnerComponent().getManifestEntry("/sap.app/dataSources/mainService").uri;
// Check whether table name field is not initial
if (inputTableName === "") {
this.getView().byId("tableInput").setValueState("Error");
MessageToast.show("Please Provide a Table Name");
} else {
//Reset the value state for input field in case it was error
this.getView().byId("tableInput").setValueState("None");
var wStream = window.open(mainUri + "TableStructureSet('" + inputTableName + "')/$value");
if (wStream === null) {
MessageToast.show("Error generating template");
} else {
MessageToast.show("Template Downloaded Successfully");
}
}
},
<ObjectPageSection id="sectionBrowseDataFile" title="Upload Data" importance="Medium" titleUppercase="true">
<subSections>
<ObjectPageSubSection id="browseDataFile" title="Browse Data File">
<blocks>
<u:FileUploader id="fileUploader" name="myFileUpload" tooltip="" fileType="xls" uploadOnChange="false" typeMissmatch="handleTypeMissmatch"
change="onChange"/>
</blocks>
</ObjectPageSubSection>
</subSections>
</ObjectPageSection>
<ObjectPageSection id="executeUpload" title="Execute Upload" importance="Medium" titleUppercase="true">
<subSections>
<ObjectPageSubSection id="executeUploadSubSection" title="">
<blocks>
<layout:VerticalLayout>
<m:RadioButtonGroup id="radioButtonGroup">
<m:buttons>
<m:RadioButton id="radioButton1" text="Insert"/>
<m:RadioButton id="radioButton2" text="Modify"/>
<m:RadioButton id="radioButton3" text="Delete"/>
</m:buttons>
</m:RadioButtonGroup>
<m:Button text="Execute Upload" press="onExecuteUpload" type="Emphasized" enabled="true"></m:Button>
</layout:VerticalLayout>
</blocks>
</ObjectPageSubSection>
</subSections>
</ObjectPageSection>
onExecuteUpload: function (oEvent) {
var oFileUploader = this.byId("fileUploader");
var xlsDomRef = oFileUploader.getFocusDomRef();
var xlsFile = xlsDomRef.files[0];
var that = this;
this.fileName = xlsFile.name;
this.fileType = xlsFile.type;
//Get selected Radio Button
for (var j = 0; j < this.getView().byId("radioButtonGroup").getButtons().length; j++) {
if (this.getView().byId("radioButtonGroup").getButtons()[j].getSelected()) {
this.operation = this.getView().byId("radioButtonGroup").getButtons()[j].getText();
}
}
var oReader = new FileReader();
oReader.onload = function (oReadStream) {
//Get the number of columns present in the file uploaded & convert the regex unformatted stream
//to array. This will be parsed at the backend SAP
var noOfcolumn = oReadStream.currentTarget.result.match(/[^\r\n]+/g)[0].split("\t").length;
var binContent = oReadStream.currentTarget.result.match(/[^\r\n\t]+/g);
//Provide the binary content as payload. This will be received as an XSTRING in
//SAP under the CREATE_STREAM method of media resource structure
var payload = {
"Content": binContent
};
//Provide additional details through header. Column No, Filename + File Type + TableName + Operation
var header = {
"slug": noOfcolumn + "," + that.fileName + "," + that.fileType + "," + that.operation
};
//Call a CREATE_STREAM activity
that.getModel().create("/TableStructureSet", payload, {
headers: header,
success: function (oData, oResponse) {
MessageToast.show("Data Uploaded Successfully!");
},
error: function (oError) {
MessageToast.show("Data Uploaded Failed!");
}
});
};
// Read the file as a binary String. Do not read URI, you have to encode before sending
oReader.readAsBinaryString(xlsFile);
},
* Data Declarations
DATA: lv_xstring TYPE xstring,
lv_string TYPE string,
lv_length TYPE i,
lv_strcomp_counter TYPE i,
li_bin_tab TYPE STANDARD TABLE OF x255,
lt_dref TYPE REF TO data,
ls_dref TYPE REF TO data.
FIELD-SYMBOLS: <lfs_dyntab> TYPE STANDARD TABLE,
<lfs_dyntab_line> TYPE any.
* Get the column count and table name for upload
SPLIT iv_slug AT ',' INTO TABLE DATA(li_slug_data).
DATA(lv_colcount) = VALUE #( li_slug_data[ 1 ] OPTIONAL ).
DATA(lv_operation) = VALUE #( li_slug_data[ 4 ] OPTIONAL ).
DATA(lv_fileName) = CONV string( VALUE #( li_slug_data[ 2 ] OPTIONAL ) ).
SPLIT lv_fileName AT '-' INTO TABLE DATA(li_fileName).
DATA(lv_tableName) = VALUE tabname16( li_fileName[ 1 ] OPTIONAL ).
* Read the stream information
lv_xstring = is_media_resource-value.
* XString to Binary Conversion
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_xstring
IMPORTING
output_length = lv_length
TABLES
binary_tab = li_bin_tab.
* Binary to String Conversion
CALL FUNCTION 'SCMS_BINARY_TO_STRING'
EXPORTING
input_length = lv_length
IMPORTING
text_buffer = lv_string
TABLES
binary_tab = li_bin_tab
EXCEPTIONS
failed = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
* Format String to Readable format to Parse in Table
REPLACE ALL OCCURRENCES OF '{' IN lv_string WITH ''.
REPLACE ALL OCCURRENCES OF '}' IN lv_string WITH ''.
REPLACE ALL OCCURRENCES OF ':' IN lv_string WITH ''.
REPLACE ALL OCCURRENCES OF '[' IN lv_string WITH ''.
REPLACE ALL OCCURRENCES OF ']' IN lv_string WITH ''.
REPLACE ALL OCCURRENCES OF '"' IN lv_string WITH ''.
REPLACE ALL OCCURRENCES OF 'Content' IN lv_string WITH ''.
SPLIT lv_string AT ',' INTO TABLE DATA(li_values).
CREATE DATA lt_dref TYPE TABLE OF (lv_tableName).
CREATE DATA ls_dref TYPE (lv_tableName).
* Assign field symbol with table type of DDIC
ASSIGN lt_dref->* TO <lfs_dyntab>.
* Assign field symbol with Structure type of DDIC
ASSIGN ls_dref->* TO <lfs_dyntab_line>.
* Initialize Counter
lv_strcomp_counter = 1.
* Dynamically read the values and build internal table
LOOP AT li_values ASSIGNING FIELD-SYMBOL(<lfs_values>).
ASSIGN COMPONENT lv_strcomp_counter OF STRUCTURE <lfs_dyntab_line> TO FIELD-SYMBOL(<lfs_tgt_data>).
<lfs_tgt_data> = <lfs_values>.
lv_strcomp_counter = lv_strcomp_counter + 1.
* LineBreak Counter for checking column count
DATA(lv_linebrk_counter) = sy-tabix MOD ( lv_colcount ).
IF lv_linebrk_counter EQ 0.
lv_strcomp_counter = 1.
APPEND <lfs_dyntab_line> TO <lfs_dyntab>.
CLEAR: <lfs_dyntab_line>.
ENDIF.
ENDLOOP.
* Delete the header row of the table
DELETE <lfs_dyntab> INDEX 1.
* Create Entry to Actual Table
MODIFY (lv_tableName) FROM TABLE <lfs_dyntab>.
IF sy-subrc <> 0.
ENDIF.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
6 | |
4 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 | |
3 | |
3 |