[SAP ABAP] Import and Export document Part 1
Client-side file processing
In a NetWeaver environment, we always need to remember the differences between the application server layer and the presentation layer. The application server layer is, as you may already know, a runtime environment for ABAP code. At a lower technical level, the application server is a remote server on which the NetWeaver platform is installed. The presentation layer instead can be understood as your local PC.
This difference is very important in the case of reading and writing files because SAP provides separate sets of tools in each case—one for processing files on the presentation layer and a second for processing files on the application server. Both are commonly used in SAP projects and will be fully covered in this chapter.
Imagine a situation where a client asks you to develop an ABAP program that reads the content of files stored on the end user's local PC. This section will tell you exactly how to deal with such a situation.
The following steps show how to develop ABAP program that reads the content of files:
- Go to the ABAP Workbench (transaction
SE80
) and create a new report from the local class-based report template (look at Appendix A, Assessments for help). You can give it any name, but I suggest sticking to the name given in this book (ZMSA_R_CHAPTER4_1
). The code will look like this:
REPORT ZMSA_R_CHAPTER4_1.
CLASS lcl_demo DEFINITION.
PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.
CLASS lcl_demo IMPLEMENTATION.
METHOD main.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_demo=>main( ).
- We will put the entire code in the
main
method. Create two variables—one to store the filename and file path on our local system and one to store the contents of our file. The code will look as follows:
DATA: lv_filepath TYPE string VALUE 'C:\temp\testfile4_1.txt'.
DATA: lt_data TYPE TABLE OF string.
- We will assume just for now that our filename and file path will always be the same (
C:\temp\testfile4_1.txt
). Later, we will change it and allow the user to choose what he or she needs. Create a text file inC:\temp
with the nametestfile4_1.txt
and insert the following content:
This is first line of testfile4_1.txt.
This is second line of testfile4_1.txt.
This is third line of testfile4_1.txt.
- The best way to read a file from the local PC is to use the
gui_upload
static method from the standard SAP classcl_gui_frontend_services
. Some people will use the old function modulegui_upload
, but a better approach is to use thegui_upload
method. It's an object-oriented wrapper forgui_upload
function which means the only purpose of this method is to call another function module. To save yourself a bit of time, you can always choosePattern
from theABAP Workbench
menu bar:
- In the popup that appears, choose
ABAP Objects Patterns
and click on the green checkmark:
- Another popup will appear. Fill it in as follows and click the green check mark again:
- Thanks to this, the method call pattern will be pasted into the source code of your program. You should see something similar to the following:
CALL METHOD cl_gui_frontend_services=>gui_upload
* EXPORTING
* filename = SPACE
* filetype = 'ASC'
* has_field_separator = SPACE
* header_length = 0
* read_by_line = 'X'
* dat_mode = SPACE
* codepage = SPACE
* ignore_cerr = ABAP_TRUE
* replacement = '#'
* virus_scan_profile =
* IMPORTING
* filelength =
* header =
CHANGING
data_tab =
* isscanperformed = SPACE
* EXCEPTIONS
* [...]
We need to provide variables for the
filename
and data_tab
parameters. It's important to notice that the filename
parameter also includes a path. In our case, it's a full path so it's an absolute address. It can accept relative addressing and the default root directory is c:\Users\%USER%\Documents\SAP\SAP GUI\
(in a Windows environment). The parameter filename
is commented out by default, so you have to remove the asterisk from the parameter name and from the EXPORTING
section.
If you look closely at the
gui_upload
method call pattern, you will see that there are a bunch of additional parameters that can help you archive specific business requirements. There is the filetype
parameter, which can take one of three values: ASC
(if data will be transferred as ASCII text), BIN
(if data should be transferred unconverted in binary format), and DAT
(if data should be transported unconverted as an ASCII text table, where the different columns are separated by a tabulator). You can also define code-page if you have different character encodingbycodepage
parameters, the date format using dat_mode
, or even run a virus scan by filling virus_scan_profile
. For more information, you can read the class documentation.
For displaying the results, we can use the
display_data
method from the cl_demo_output
class. It's a very simple way to display something using just a single line of code. Please put the following method call at the end of the main method:cl_demo_output=>display_data( lt_data ).
Now you can execute your program. Most likely, a SAP GUI security popup will appear. You need to click the
Allow
button to make this example work. This is standard SAP protection for unauthorized access to your local files. You can also mark the Remember My Decision
checkbox to avoid being noticed next time you execute this program. You can always change these settings in the SAP GUI
| Options
| Security
| Security Settings
menu:
If everything went well, you should see a popup with the following content:
This code is far from perfect. First of all, the user has the possibility to choose a file he or she desires and not get a hardcoded one all the time. Let's be realistic; two user environments are never the same, so the hardcoded approach will never work in real life. To set up a dynamic file location, we need to use the method
file_open_dialog
from cl_gui_frontend_services
. But first, we need to declare two additional variables—one to store the filename and file path and another to get user operation return code. Your new code should look like this:DATA: lt_filetable TYPE filetable.
DATA: lt_filetable TYPE file_table.
DATA: lv_rc TYPE i.
Generate the method call pattern using the
Pattern
button for file_open_dialog
, exactly like we did for the gui_upload
method. This time it will produce the following code:CALL METHOD cl_gui_frontend_services=>file_open_dialog
* EXPORTING
* window_title =
* default_extension =
* default_filename =
* file_filter =
* with_encoding =
* initial_directory =
* multiselection =
CHANGING
file_table =
rc =
* user_action =
* file_encoding =
* EXCEPTIONS
* file_open_dialog_failed = 1
* cntl_error = 2
* error_no_gui = 3
* not_supported_by_gui = 4
* others = 5
.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
Provide variables for
file_table
and rc
parameters. It should be noted that the parameter file_table
is of table
type and can include more entries. This can be useful if you want to read multiple files, but can be also annoying if you have only one file in every scenario, because you have to implement additional logic to read the first (and only) file path in the table. The parameter rc
gives you information on how many files were selected. It will be set to -1
if something went wrong. Use the READ TABLE
keyword to read the first file path:READ TABLE lt_filetable INTO lv_filepath INDEX 1.
Now if you run your program, you will get an additional popup where you can choose the desired file:
There are many additional useful parameters in the
file_open_dialog
method. You can block multiple file selection options (but you will still have to read the first entry from lt_filetable
). You can also make your dialog more business oriented and suitable by choosing the default directory path, default filetype, default extension, and additional filters. If you want to improve the user experience, you can make this popup a bit prettier by choosing the text for the title.
There is still one last part missing. We wrote down a nice piece of code but we didn't handle an expected situation we may come across. What will happen when the user does not choose any file at all? What will happen if the file can't be accessed? As a good programmer, you should always take care of such situations. Murphy's law is applicable in computer science more than anywhere else, so if something can go wrong, certainly sooner or later it will. The most obvious way is to tell the user what went wrong, put understandable information on the screen, and terminate processing. You can solve this in the following way (place it just after the
file_open_dialog
call):IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
RETURN.
ELSEIF lv_rc < 1.
MESSAGE 'No File choosen' TYPE 'W'.
RETURN.
ENDIF.
Something similar can be also applied to the
gui_upload
call:IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty
NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
RETURN.
ENDIF.
Make sure you have uncommented all the exceptions in the method call, otherwise catching an exception will not work and you will end up with a short dump.
Now let's imagine the situation that the client needs a report which will generate a result in the form of a text file saved on the user's local computer. This chapter will expand your skills with this knowledge. It's very similar to the previous example; the only difference is that we write the file to the PC and not read from the PC. To save files and choose a suitable file path, we will be using new methods from the previously used class,
cl_gui_frontend_services
.
First, create new report,
ZMSA_R_CHAPTER4_2
, and include a report template from Appendix A, Assessments. We need to declare variables. We need three of them to make the method file_save_dialog
work. lv_filename
is the name of the file, lv_path
is for the path-to-file directory where the file will be saved, and lv_fullpath
is the path plus the filename. The code equivalent to this step looks like this: DATA: lv_filename TYPE string.
DATA: lv_path TYPE string.
DATA: lv_fullpath TYPE string.
We will not hardcode the path in this example and will go straight into the method
file_save_dialog
. This is an analogous method to file_open_dialog
but for choosing a path for where to store the file. Use the pattern
option on the file_save_dialog
method to produce a call (if you don't know how, please go back to the Reading files from the local PC using gui_upload section). If you did everything according to the instructions, you should see something like this:CALL METHOD cl_gui_frontend_services=>file_save_dialog
* EXPORTING
* window_title =
* default_extension =
* default_file_name =
* with_encoding =
* file_filter =
* initial_directory =
* prompt_on_overwrite = 'X'
CHANGING
filename =
path =
fullpath =
* user_action =
* file_encoding =
* EXCEPTIONS
* cntl_error = 1
* error_no_gui = 2
* not_supported_by_gui = 3
* invalid_default_file_name = 4
* others = 5
.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
Now, use the
code pattern
tool to insert the gui_download
method call structure: CALL METHOD cl_gui_frontend_services=>gui_download
EXPORTING
* bin_filesize =
filename =
* filetype = 'ASC'
* append = SPACE
* write_field_separator = SPACE
* header = '00'
* trunc_trailing_blanks = SPACE
* write_lf = 'X'
* col_select = SPACE
* col_select_mask = SPACE
* dat_mode = SPACE
* confirm_overwrite = SPACE
* no_auth_check = SPACE
* codepage = SPACE
* ignore_cerr = ABAP_TRUE
* replacement = '#'
* write_bom = SPACE
* trunc_trailing_blanks_eol = 'X'
* wk1_n_format = SPACE
* wk1_n_size = SPACE
* wk1_t_format = SPACE
* wk1_t_size = SPACE
* show_transfer_status = 'X'
* fieldnames =
* write_lf_after_last_line = 'X'
* virus_scan_profile = '/SCET/GUI_DOWNLOAD'
* IMPORTING
* filelength =
changing
data_tab =
* EXCEPTIONS
* file_write_error = 1
* no_batch = 2
* gui_refuse_filetransfer = 3
* invalid_type = 4
* no_authority = 5
* unknown_error = 6
* header_not_allowed = 7
* separator_not_allowed = 8
* filesize_not_allowed = 9
* header_too_long = 10
* dp_error_create = 11
* dp_error_send = 12
* dp_error_write = 13
* unknown_dp_error = 14
* access_denied = 15
* dp_out_of_memory = 16
* disk_full = 17
* dp_timeout = 18
* file_not_found = 19
* dataprovider_exception = 20
* control_flush_error = 21
* not_supported_by_gui = 22
* error_no_gui = 23
* others = 24
.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
Two parameters are obligatory—one to tell the method where to store the file and another that contains actual data to be stored. For the first parameter, we will use the
lv_fullpath
variable. For the second parameter, we need to declare a new variable: DATA: lt_data_tab TYPE TABLE OF string.
In real life, some business data can be stored in a local file. In this example, we will just add a few dummy lines:
APPEND '1st dummy line' TO lt_data_tab.
APPEND '2nd dummy line' TO lt_data_tab.
APPEND '3rd dummy line' TO lt_data_tab.
If you execute your program, you will see save the file dialog:
You can choose whatever directory or filename you want, but you have to remember to be consistent in other parts of this example—we will refer to this value. If a file already exists, you will be asked to confirm overwriting:
After clicking
Yes
, go to the chosen path and open your file:Note
Remember to use the mechanisms from the previous example to handle errors and inform the user what went wrong.
I highly recommend playing around with all the other parameters of the
gui_download
method. It allows you to overwrite files without prompt popups and manipulate file content by using separators or date modifier options. You can also define the writing mode (data may be overwritten or appended at the end of the file).
Also, it's really worthwhile to check other methods from the
cl_gui_frontend_services
class as it can give you a variety of different possibilities. You can copy and delete a file or even read a file's attributes. This gives you a full spectrum of functionalities for working with directories. Apart from operations on files and folders, this class also offers a vast amount of other possibilities, such as the manipulation of registers and the reading of environment variables or other information about the user's system.Server-side file processing
In this section, we will cover the basic transactions related to server-side files and writing and reading files to an application server. Those examples used in the loop and in the background job may be used for mass import and mass export.
Before we start going into the ABAP code, we need to get familiar with a few useful transactions. In local environments and common operating systems, every user knows how to explore folders and view file contents. But in the case of server-side files, things are different. Of course, we talk here about a typical situation where the programmer does not have access to the server from the level of the operating system and can view files only by using the SAP GUI. The first transaction,
AL11
, is very important and useful. It's a SAP equivalent to Windows Explorer. Run AL11
from the Command Field
in the SAP GUI. This will open the following:
In
AL11
, you can display server-side SAP directories, files, and file contents. We will use transaction AL11
to check if the files from the following example are really uploaded on the server. The full directory structure depends on the server operating system, but some of them are generic and should be quite similar in every SAP installation.
We will not discuss every single item in this list, but you should definitely know the most useful ones:
DIR_PROFILE
is a central configuration directory of a SAP system. An instance is configured using a profile file stored in theDIR_PROFILE
directory.DIR_SAPUSERS
is a default catalog for user files.DIR_TRANS
is a transport request directory. Basically, every released transport request is stored here as a file. You can copy such files and move into another system. It may be a good idea to back up your work for future use.DIR_TEMP
is a directory for temporary data.
Another two applications need to be mentioned before we jump into ABAP. The first one,
CG3Z
, is used to upload files to the server. The second, CG3Y
, is to read files from the server. We will go through a simple example for each transaction, just for better visualization of how this really works. Run CG3Z
first and fill everything in as follows:
Now you can verify the whole process by going to
AL11
and exploring the used directory. If the path is not specified, the default folder will be DIR_SAPUSERS
. For easy searching of the file, you can use a filter option on the menu bar:
Just put your filename in the popup:
This will remove all other files from the listing:
When you have located your file, you can open it by double-clicking it:
The second transaction,
CG3Y
, is used to download files from SAP server directories. Open CG3Y
(it looks almost the same as CG3Z
) and fill it in as follows:
Write the source file path and filename into the
Source file on application server
field (analogously to the previous example in the CG3Z
), and then choose to save your file anywhere you want by filling the Target file on front end
field. Go to a temp
directory to verify the new testfile4_2_from_server.txt
file. It should have the same content as the original testfile4_2.txt
:
In both transactions, we have two options we haven't covered yet. The
Overwrite file
option will overwrite the file if it exists in the destination directory and the Transfer format to data
option that defines the method of file transfer as BIN
for binary transfer and ASC
for ASCII-like transfer. During both operations, a popup with an authorization permission question can appear. To make these examples work, you have to allow for read and write access.
Working with a file on a local PC gives you many capabilities; however, it has important limitations. For example, files are only available to us and if we close the current transaction, data will be lost. This means we can't use this data in a job or later in another transaction. The solution for these two problems can be storing files on the application server. We can't use
cl_gui_frontend_services
for that because it works only with the frontend layer. For application server-based file operations, we have a special keyword, OPEN DATASET
.
Let's check how exactly this works. Please create a new report,
ZMSA_R_CHAPTER4_3
, from Appendix A, Assessments report template and declare the following variables in the main
method:DATA: lv_file TYPE string VALUE 'testfile4_3.txt'.
To open a file, you need to use the following syntax:
OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE ENCODING DEFAULT.
This actually opens something that may be considered stream to file. To write data into the file, you have to use the
TRANSFER
keyword:TRANSFER '1st line on application server' TO lv_file.
TRANSFER '2nd line on application server' TO lv_file.
TRANSFER '3rd line on application server' TO lv_file.
After this operation, we have to close the file. To do so, we need to use the
CLOSE DATASET
statement:CLOSE DATASET lv_file.
CLOSE DATASET
will also save the current buffer to the file if there is some buffer on the operating system. An opened file that was not explicitly closed will be automatically closed when the program is exited. We can check our new file in an AL11
transaction. Keep in mind that we didn't provide a directory, so the file will be saved in the default root folder, DIR_SAPUSERS
.
Reading files from the application server is very easy; even easier than writing a file. But to be sure that this example works, we first need to store something in the application server. Copy a report pattern from Appendix A, Assessments into the newly created
ZMSA_R_CHAPTER4_4
. We need an additional variable to store file content lt_data
and lv_line
to temporarily store each line of a file. The variable lv_file
is used to store the filename: DATA: lv_file TYPE string VALUE 'testfile4_3.txt'.
DATA: lv_line TYPE string.
DATA: lt_data TYPE TABLE OF string.
The first statement is almost the same as in the last exercise; we just need to change direction from
OUTPUT
to INPUT
:OPEN DATASET lv_file FOR INPUT IN TEXT MODE ENCODING DEFAULT.
Now, to read file content, we have to loop through every single line and put line content to our table variable
lt_data
: DO.
READ DATASET lv_file INTO lv_line.
IF sy-subrc = 0.
APPEND lv_line TO lt_data.
ELSE.
EXIT.
ENDIF.
ENDDO.
If a
READ DATASET
statement encounters the end of the file, sy-subrc
will return a value of 4
and the DO
loop will be stopped. Of course, you have to close the file: CLOSE DATASET lv_file.
To check the results, we will use the
display
_data
method from the cl_demo_output
class again:cl_demo_output=>display_data( lt_data ).
If you did everything right after the execution of
ZMSA_R_CHAPTER4_4
, you should see the following:
Now you know how to do two basic operations with files on the application server. To learn more, you should check the SAP documentation for the
OPEN DATASET
statement. The last thing worth mentioning is two function modules, archivfile_client_to_server
and eps2_get_directory_listing
. The first function allows you to connect two operations—read a file from the client and upload it to the server. You can achieve this by mixing examples from this chapter, but this function can save you some time. The second function allows you to list all files and folders on the application server.
Comments
Post a Comment