File
Downloads an editable table as a CSV file built in plain ABAP, and the same CSV together with a text note packed into one ZIP archive with cl_abap_zip.
Z2UI5_CL_SMP_APP_542
Learn
File
UI5 1.71
frontend action
The facts
- Repository
- abap2UI5/samples
- Class
Z2UI5_CL_SMP_APP_542- Source file
z2ui5_cl_smp_app_542.clas.abap↗- Category
- File
- Learning path
- Reach outside the view
- Minimum UI5
- 1.71 — the floor abap2UI5 holds its samples to
- In the playground
- runs in the browser, with no system and nothing installed
- Marked
(A)— Performs a frontend action: client->follow_up_action( ), or drag and drop
Keywords: zip, cl_abap_zip, csv, export, download_b64_file, base64, xstring, utf-8, itab
Controls it builds
- sap.m.Button
- sap.m.Column
- sap.m.ColumnListItem
- sap.m.Input
- sap.m.Label
- sap.m.MessageStrip
- sap.m.OverflowToolbar
- sap.m.Page
- sap.m.Shell
- sap.m.Table
- sap.m.Text
- sap.m.TextArea
- sap.m.Title
- sap.m.ToolbarSpacer
- sap.m.VBox
- sap.ui.core.mvc.View
Read out of the builder chain by the abap2UI5 linter, not from the category this sample is filed under — which is what makes “which samples build one of these” a question the catalogue can answer at all.
Libraries
Run it here
The sample running, in this page — the app on its own, with no editor over it.
Switch to Playground with this code
Nothing is installed and nothing is sent anywhere: the ABAP is compiled to JavaScript in this browser and runs against abap2UI5 itself.
The ABAP
z2ui5_cl_smp_app_542.clas.abap — 302 lines
Click a number to link to a line — shift-click for a range.
Read it on GitHub ↗
" @keywords zip cl_abap_zip csv export download_b64_file base64 xstring utf-8 itab
" @summary Downloads an editable table as a CSV file built in plain ABAP, and the same CSV together with a text note packed into one ZIP archive with cl_abap_zip.
CLASS z2ui5_cl_smp_app_542 DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
TYPES:
BEGIN OF ty_s_product,
id TYPE string,
name TYPE string,
quantity TYPE i,
price TYPE p LENGTH 9 DECIMALS 2,
END OF ty_s_product.
DATA t_products TYPE STANDARD TABLE OF ty_s_product WITH EMPTY KEY.
DATA note TYPE string.
PROTECTED SECTION.
DATA client TYPE REF TO z2ui5_if_client.
METHODS on_init.
METHODS on_event.
METHODS view_display.
METHODS csv_build
RETURNING
VALUE(result) TYPE string.
METHODS csv_field
IMPORTING
val TYPE string
RETURNING
VALUE(result) TYPE string.
METHODS file_download
IMPORTING
name TYPE string
mime TYPE string
content TYPE xstring.
" Both wrap a pair of classes that do the same job under different names:
" the first is the ABAP Cloud one, the second the classic on-premise one.
" Called dynamically so the class that is missing on a system is a caught
" runtime error instead of a syntax error at activation.
METHODS base64_encode
IMPORTING
val TYPE xstring
RETURNING
VALUE(result) TYPE string.
METHODS string_to_xstring
IMPORTING
val TYPE string
RETURNING
VALUE(result) TYPE xstring.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_smp_app_542 IMPLEMENTATION.
METHOD z2ui5_if_app~main.
me->client = client.
IF client->check_on_init( ).
on_init( ).
ELSEIF client->check_on_navigated( ).
view_display( ).
ELSEIF client->check_on_event( ).
on_event( ).
ENDIF.
ENDMETHOD.
METHOD on_init.
" the second and third name hold the separator and quotes on purpose -
" the CSV has to escape them
t_products = VALUE #(
( id = `P-001` name = `Notebook Basic 15` quantity = 3 price = `956.00` )
( id = `P-002` name = `Cable "USB-C"; 2 m` quantity = 25 price = `9.90` )
( id = `P-003` name = `Monitor 27"` quantity = 4 price = `289.00` )
( id = `P-004` name = `Wireless Mouse` quantity = 12 price = `24.50` ) ).
note = `Stock list exported from abap2UI5.`.
view_display( ).
ENDMETHOD.
METHOD on_event.
TRY.
IF client->check_on_event( `DOWNLOAD_CSV` ).
file_download( name = `products.csv` mime = `text/csv` content = string_to_xstring( csv_build( ) ) ).
ELSEIF client->check_on_event( `DOWNLOAD_ZIP` ).
DATA(zip) = NEW cl_abap_zip( ).
zip->add( name = `products.csv` content = string_to_xstring( csv_build( ) ) ).
zip->add( name = `note.txt` content = string_to_xstring( note ) ).
file_download( name = `export.zip` mime = `application/zip` content = zip->save( ) ).
ENDIF.
CATCH cx_root INTO DATA(error).
client->message_box_display( text = error->get_text( ) type = `error` ).
ENDTRY.
ENDMETHOD.
METHOD csv_build.
" a header line, then one line per row - separator ;, lines end in CRLF
result = |ID;Name;Quantity;Price\r\n|.
LOOP AT t_products INTO DATA(product).
result = result && |{ csv_field( product-id ) };{ csv_field( product-name ) };| &&
|{ csv_field( |{ product-quantity }| ) };{ csv_field( |{ product-price }| ) }\r\n|.
ENDLOOP.
ENDMETHOD.
METHOD csv_field.
" RFC 4180: a value holding the separator, a quote or a line break is
" enclosed in quotes, and every quote inside it is doubled
result = val.
IF result CA |;"\r\n|.
result = |"{ replace( val = result sub = `"` with = `""` occ = 0 ) }"|.
ENDIF.
ENDMETHOD.
METHOD file_download.
" download_b64_file takes a base64 data URL and the name the browser
" saves it under
client->follow_up_action(
val = client->cs_event-download_b64_file
t_arg = VALUE #( ( |data:{ mime };base64,{ base64_encode( content ) }| ) ( name ) ) ).
ENDMETHOD.
METHOD base64_encode.
DATA lv_class TYPE string.
TRY.
lv_class = `CL_WEB_HTTP_UTILITY`.
CALL METHOD (lv_class)=>(`ENCODE_X_BASE64`)
EXPORTING
unencoded = val
RECEIVING
encoded = result.
CATCH cx_root.
lv_class = `CL_HTTP_UTILITY`.
CALL METHOD (lv_class)=>(`ENCODE_X_BASE64`)
EXPORTING
unencoded = val
RECEIVING
encoded = result.
ENDTRY.
ENDMETHOD.
METHOD string_to_xstring.
DATA lo_conv TYPE REF TO object.
DATA lv_class TYPE string.
TRY.
lv_class = `CL_ABAP_CONV_CODEPAGE`.
CALL METHOD (lv_class)=>create_out
RECEIVING
instance = lo_conv.
CALL METHOD lo_conv->(`IF_ABAP_CONV_OUT~CONVERT`)
EXPORTING
source = val
RECEIVING
result = result.
CATCH cx_root.
lv_class = `CL_ABAP_CONV_OUT_CE`.
CALL METHOD (lv_class)=>create
EXPORTING
encoding = `UTF-8`
RECEIVING
conv = lo_conv.
CALL METHOD lo_conv->(`CONVERT`)
EXPORTING
data = val
IMPORTING
buffer = result.
ENDTRY.
ENDMETHOD.
METHOD view_display.
DATA(view) = z2ui5_cl_ui5_view_builder=>factory(
)->ele( n = `View` ns = `mvc`
)->a( n = `displayBlock` v = `true`
)->a( n = `height` v = `100%`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:mvc` v = `sap.ui.core.mvc` ).
DATA(page) = view->ele( `Shell`
)->ele( `Page`
)->a( n = `title` v = `abap2UI5 - File - ZIP and CSV Download with cl_abap_zip`
)->a( n = `showNavButton` b = client->check_app_prev_stack( )
)->a( n = `navButtonPress` v = client->_event_nav_app_leave( ) ).
page->tag( `MessageStrip`
)->a( n = `text` v = `Download CSV turns the table into a CSV file in plain ABAP - separator ;, values with a ` &&
`separator or a quote enclosed in quotes, CRLF line ends - encoded as UTF-8. Download ZIP packs that CSV ` &&
`and the note as note.txt into one archive with cl_abap_zip. Both reach the browser via download_b64_file.`
)->a( n = `type` v = `Information`
)->a( n = `showIcon` b = abap_true
)->a( n = `class` v = `sapUiSmallMargin` ).
DATA(table) = page->ele( `Table`
)->a( n = `items` v = client->_bind( t_products )
)->a( n = `class` v = `sapUiSmallMargin` ).
table->ele( `headerToolbar`
)->ele( `OverflowToolbar`
)->tag( `Title`
)->a( n = `text` v = `Products - edit a cell, then download` ).
table->ele( `columns`
)->ele( `Column`
)->tag( `Text`
)->a( n = `text` v = `ID`
)->end(
)->ele( `Column`
)->tag( `Text`
)->a( n = `text` v = `Name`
)->end(
)->ele( `Column`
)->tag( `Text`
)->a( n = `text` v = `Quantity`
)->end(
)->ele( `Column`
)->tag( `Text`
)->a( n = `text` v = `Price` ).
table->ele( `items`
)->ele( `ColumnListItem`
)->ele( `cells`
)->tag( `Input`
)->a( n = `value` v = `{ID}`
)->tag( `Input`
)->a( n = `value` v = `{NAME}`
)->tag( `Input`
)->a( n = `value` v = `{QUANTITY}`
)->tag( `Input`
)->a( n = `value` v = `{PRICE}` ).
page->ele( `VBox`
)->a( n = `class` v = `sapUiSmallMargin`
)->tag( `Label`
)->a( n = `text` v = `Note (note.txt in the ZIP)`
)->a( n = `labelFor` v = `note`
)->tag( `TextArea`
)->a( n = `id` v = `note`
)->a( n = `value` v = client->_bind( note )
)->a( n = `rows` v = `3`
)->a( n = `width` v = `100%` ).
page->ele( `footer`
)->ele( `OverflowToolbar`
)->tag( `ToolbarSpacer`
)->tag( `Button`
)->a( n = `text` v = `Download CSV`
)->a( n = `icon` v = `sap-icon://download`
)->a( n = `press` v = client->_event( `DOWNLOAD_CSV` )
)->tag( `Button`
)->a( n = `text` v = `Download ZIP`
)->a( n = `icon` v = `sap-icon://attachment-zip-file`
)->a( n = `type` v = `Emphasized`
)->a( n = `press` v = client->_event( `DOWNLOAD_ZIP` ) ).
client->view_display( view->stringify( ) ).
ENDMETHOD.
ENDCLASS.
More in File
On this page