Reading Excel Files
Comprehensive guide to reading and parsing existing Excel files with abap2xlsx.
Basic File Reading
Loading an Excel File
The primary class for reading Excel files is zcl_excel_reader_2007
, which handles Excel 2007+ (.xlsx) format files .
abap
" Basic Excel file reading
REPORT zread_excel_basic.
DATA: lo_reader TYPE REF TO zif_excel_reader,
lo_excel TYPE REF TO zcl_excel,
lo_worksheet TYPE REF TO zcl_excel_worksheet,
lv_file_data TYPE xstring.
START-OF-SELECTION.
" Load Excel file data (from upload, file system, etc.)
" lv_file_data = ... your file loading logic
" Create reader instance
CREATE OBJECT lo_reader TYPE zcl_excel_reader_2007.
" Load the Excel file
TRY.
lo_excel = lo_reader->load_file( lv_file_data ).
MESSAGE 'Excel file loaded successfully' TYPE 'S'.
CATCH zcx_excel INTO DATA(lx_excel).
MESSAGE |Error loading Excel file: { lx_excel->get_text( ) }| TYPE 'E'.
ENDTRY.
Accessing Worksheets
abap
" Get worksheets from loaded Excel file
DATA: lo_worksheets TYPE REF TO zcl_excel_worksheets,
lv_worksheet_count TYPE i.
" Get all worksheets
lo_worksheets = lo_excel->get_worksheets( ).
lv_worksheet_count = lo_worksheets->size( ).
WRITE: / |Excel file contains { lv_worksheet_count } worksheets|.
" Get active worksheet
lo_worksheet = lo_excel->get_active_worksheet( ).
WRITE: / 'Active worksheet:', lo_worksheet->get_title( ).
" Get worksheet by index (1-based)
lo_worksheet = lo_excel->get_worksheet_by_index( 1 ).
" Get worksheet by name
lo_worksheet = lo_excel->get_worksheet_by_name( 'Sheet1' ).
Reading Cell Data
Individual Cell Access
abap
" Read individual cells
DATA: lv_cell_value TYPE string,
lv_cell_formula TYPE string.
" Read cell value
lv_cell_value = lo_worksheet->get_cell( ip_column = 'A' ip_row = 1 ).
WRITE: / 'Cell A1:', lv_cell_value.
" Read cell formula
lv_cell_formula = lo_worksheet->get_cell_formula( ip_column = 'B' ip_row = 1 ).
IF lv_cell_formula IS NOT INITIAL.
WRITE: / 'Cell B1 formula:', lv_cell_formula.
ENDIF.
" Check if cell exists and has content
IF lo_worksheet->get_cell( ip_column = 'C' ip_row = 1 ) IS NOT INITIAL.
WRITE: / 'Cell C1 has content'.
ENDIF.
Reading Cell Ranges
abap
" Get worksheet dimensions
DATA: lv_highest_row TYPE i,
lv_highest_col TYPE i,
lv_highest_col_alpha TYPE string.
lv_highest_row = lo_worksheet->get_highest_row( ).
lv_highest_col = lo_worksheet->get_highest_column( ).
lv_highest_col_alpha = zcl_excel_common=>convert_column2alpha( lv_highest_col ).
WRITE: / |Data range: A1:{ lv_highest_col_alpha }{ lv_highest_row }|.
" Read all data in a range
DATA: lv_row TYPE i,
lv_col TYPE i,
lv_col_alpha TYPE string.
DO lv_highest_row TIMES.
lv_row = sy-index.
DO lv_highest_col TIMES.
lv_col = sy-index.
lv_col_alpha = zcl_excel_common=>convert_column2alpha( lv_col ).
lv_cell_value = lo_worksheet->get_cell(
ip_column = lv_col_alpha
ip_row = lv_row
).
IF lv_cell_value IS NOT INITIAL.
WRITE: / |{ lv_col_alpha }{ lv_row }: { lv_cell_value }|.
ENDIF.
ENDDO.
ENDDO.
Converting Excel Data to Internal Tables
Automatic Table Conversion
abap
" Define target structure
TYPES: BEGIN OF ty_employee,
emp_id TYPE i,
name TYPE string,
department TYPE string,
salary TYPE p DECIMALS 2,
hire_date TYPE d,
END OF ty_employee.
DATA: lt_employees TYPE TABLE OF ty_employee,
ls_employee TYPE ty_employee.
" Read data starting from row 2 (assuming row 1 has headers)
DATA: lv_data_row TYPE i VALUE 2.
DO lv_highest_row - 1 TIMES. " Skip header row
CLEAR ls_employee.
" Map Excel columns to structure fields
ls_employee-emp_id = lo_worksheet->get_cell( ip_column = 'A' ip_row = lv_data_row ).
ls_employee-name = lo_worksheet->get_cell( ip_column = 'B' ip_row = lv_data_row ).
ls_employee-department = lo_worksheet->get_cell( ip_column = 'C' ip_row = lv_data_row ).
ls_employee-salary = lo_worksheet->get_cell( ip_column = 'D' ip_row = lv_data_row ).
ls_employee-hire_date = lo_worksheet->get_cell( ip_column = 'E' ip_row = lv_data_row ).
" Only add if row has data
IF ls_employee-emp_id IS NOT INITIAL.
APPEND ls_employee TO lt_employees.
ENDIF.
ADD 1 TO lv_data_row.
ENDDO.
WRITE: / |Imported { lines( lt_employees ) } employee records|.
Dynamic Field Mapping
abap
" Read headers dynamically
DATA: lt_headers TYPE TABLE OF string,
lv_header TYPE string.
" Read header row
DO lv_highest_col TIMES.
lv_col_alpha = zcl_excel_common=>convert_column2alpha( sy-index ).
lv_header = lo_worksheet->get_cell( ip_column = lv_col_alpha ip_row = 1 ).
IF lv_header IS NOT INITIAL.
APPEND lv_header TO lt_headers.
ENDIF.
ENDDO.
" Display headers
LOOP AT lt_headers INTO lv_header.
WRITE: / |Column { sy-tabix }: { lv_header }|.
ENDLOOP.
Handling Different Data Types
Data Type Conversion
abap
" Handle different Excel data types
METHOD convert_excel_cell_value.
DATA: lv_raw_value TYPE string,
lv_date_value TYPE d,
lv_number_value TYPE p DECIMALS 2,
lv_integer_value TYPE i.
lv_raw_value = lo_worksheet->get_cell( ip_column = ip_column ip_row = ip_row ).
" Convert based on expected data type
CASE ip_data_type.
WHEN 'DATE'.
" Excel dates are stored as numbers (days since 1900-01-01)
lv_date_value = zcl_excel_common=>excel_string_to_date( lv_raw_value ).
rv_converted_value = lv_date_value.
WHEN 'NUMBER'.
lv_number_value = lv_raw_value.
rv_converted_value = lv_number_value.
WHEN 'INTEGER'.
lv_integer_value = lv_raw_value.
rv_converted_value = lv_integer_value.
WHEN OTHERS.
" Keep as string
rv_converted_value = lv_raw_value.
ENDCASE.
ENDMETHOD.
Handling Formulas and Calculated Values
abap
" Read both formula and calculated value
DATA: lv_formula TYPE string,
lv_calculated_value TYPE string.
lv_formula = lo_worksheet->get_cell_formula( ip_column = 'F' ip_row = 10 ).
lv_calculated_value = lo_worksheet->get_cell( ip_column = 'F' ip_row = 10 ).
IF lv_formula IS NOT INITIAL.
WRITE: / |Cell F10 formula: { lv_formula }|.
WRITE: / |Calculated value: { lv_calculated_value }|.
ELSE.
WRITE: / |Cell F10 value: { lv_calculated_value }|.
ENDIF.
Reading Worksheet Properties
Worksheet Metadata
abap
" Get worksheet properties
DATA: lv_sheet_title TYPE string,
lv_sheet_state TYPE string,
lo_sheet_setup TYPE REF TO zcl_excel_sheet_setup.
lv_sheet_title = lo_worksheet->get_title( ).
WRITE: / 'Worksheet title:', lv_sheet_title.
" Get print setup information
lo_sheet_setup = lo_worksheet->get_sheet_setup( ).
IF lo_sheet_setup IS BOUND.
DATA(lv_orientation) = lo_sheet_setup->get_orientation( ).
DATA(lv_paper_size) = lo_sheet_setup->get_paper_size( ).
WRITE: / 'Print orientation:', lv_orientation.
WRITE: / 'Paper size:', lv_paper_size.
ENDIF.
Reading Comments and Annotations
abap
" Read cell comments
DATA: lo_comments TYPE REF TO zcl_excel_comments,
lo_comment TYPE REF TO zcl_excel_comment.
lo_comments = lo_worksheet->get_comments( ).
" Check if specific cell has a comment
lo_comment = lo_comments->get_comment( ip_column = 'A' ip_row = 1 ).
IF lo_comment IS BOUND.
DATA(lv_comment_text) = lo_comment->get_text( ).
WRITE: / 'Comment on A1:', lv_comment_text.
ENDIF.
Advanced Reading Features
Reading Merged Cells
abap
" Detect merged cell ranges
DATA: lo_ranges TYPE REF TO zcl_excel_ranges,
lo_range TYPE REF TO zcl_excel_range.
lo_ranges = lo_worksheet->get_merge( ).
" Iterate through merged ranges
DATA: lv_range_count TYPE i.
lv_range_count = lo_ranges->size( ).
DO lv_range_count TIMES.
lo_range = lo_ranges->get( sy-index ).
DATA(lv_range_value) = lo_range->get_value( ).
WRITE: / |Merged range { sy-index }: { lv_range_value }|.
ENDDO.
Reading Conditional Formatting
abap
" Read conditional formatting rules
DATA: lo_cond_formats TYPE REF TO zcl_excel_styles_cond,
lo_cond_format TYPE REF TO zcl_excel_style_cond.
lo_cond_formats = lo_worksheet->get_styles_cond( ).
" Process conditional formatting rules
DATA: lv_cond_count TYPE i.
lv_cond_count = lo_cond_formats->size( ).
WRITE: / |Worksheet has { lv_cond_count } conditional formatting rules|.
Error Handling and Validation
Robust File Reading
abap
" Comprehensive error handling for file reading
METHOD read_excel_file_safely.
DATA: lo_reader TYPE REF TO zif_excel_reader,
lo_excel TYPE REF TO zcl_excel.
TRY.
" Validate file format
IF xstrlen( iv_file_data ) < 100.
RAISE EXCEPTION TYPE zcx_excel
EXPORTING error = 'File too small or empty'.
ENDIF.
" Check file signature (ZIP format for .xlsx)
DATA(lv_header) = iv_file_data(4).
IF lv_header <> '504B0304'. " ZIP file signature
RAISE EXCEPTION TYPE zcx_excel
EXPORTING error = 'Invalid Excel file format'.
ENDIF.
" Create reader and load file
CREATE OBJECT lo_reader TYPE zcl_excel_reader_2007.
lo_excel = lo_reader->load_file( iv_file_data ).
" Validate loaded content
IF lo_excel->get_worksheets( )->size( ) = 0.
RAISE EXCEPTION TYPE zcx_excel
EXPORTING error = 'No worksheets found in file'.
ENDIF.
rv_excel = lo_excel.
CATCH zcx_excel INTO DATA(lx_excel).
MESSAGE |Excel reading error: { lx_excel->get_text( ) }| TYPE 'E'.
CATCH cx_root INTO DATA(lx_root).
MESSAGE |Unexpected error: { lx_root->get_text( ) }| TYPE 'E'.
ENDTRY.
ENDMETHOD.
Performance Considerations
Efficient Reading Strategies
abap
" Read only necessary data
METHOD read_excel_efficiently.
" 1. Check worksheet dimensions first
DATA(lv_max_row) = lo_worksheet->get_highest_row( ).
DATA(lv_max_col) = lo_worksheet->get_highest_column( ).
" 2. Skip empty rows/columns
DATA: lv_row TYPE i VALUE 1,
lv_empty_rows TYPE i VALUE 0.
DO lv_max_row TIMES.
" Check if entire row is empty
DATA(lv_row_empty) = abap_true.
DO lv_max_col TIMES.
DATA(lv_col_alpha) = zcl_excel_common=>convert_column2alpha( sy-index ).
IF lo_worksheet->get_cell( ip_column = lv_col_alpha ip_row = lv_row ) IS NOT INITIAL.
lv_row_empty = abap_false.
EXIT.
ENDIF.
ENDDO.
IF lv_row_empty = abap_true.
ADD 1 TO lv_empty_rows.
ELSE.
" Process non-empty row
" Your row processing logic here
ENDIF.
ADD 1 TO lv_row.
ENDDO.
WRITE: / |Skipped { lv_empty_rows } empty rows|.
ENDMETHOD.
Next Steps
After mastering Excel file reading:
- Working with Worksheets - Navigate between multiple sheets
- Cell Formatting - Understand and preserve formatting
- Data Conversion - Converting Excel data to ABAP structures
- Performance Optimization - Efficient reading strategies for large files
Common Reading Patterns
Complete File Processing Example
abap
" Complete example: Read Excel file and process data
METHOD process_excel_upload.
DATA: lo_reader TYPE REF TO zif_excel_reader,
lo_excel TYPE REF TO zcl_excel,
lo_worksheet TYPE REF TO zcl_excel_worksheet,
lt_processed_data TYPE TABLE OF your_structure.
TRY.
" Load and validate file
CREATE OBJECT lo_reader TYPE zcl_excel_reader_2007.
lo_excel = lo_reader->load_file( iv_file_data ).
" Get first worksheet
lo_worksheet = lo_excel->get_active_worksheet( ).
" Convert to internal table
lt_processed_data = convert_worksheet_to_table( lo_worksheet ).
" Process the data
LOOP AT lt_processed_data INTO DATA(ls_data).
" Your business logic here
ENDLOOP.
CATCH zcx_excel INTO DATA(lx_excel).
MESSAGE |File processing error: { lx_excel->get_text( ) }| TYPE 'E'.
ENDTRY.
ENDMETHOD.
This guide covers the essential techniques for reading Excel files with abap2xlsx. The reader classes provide comprehensive support for extracting data, formulas, and formatting from Excel files.