mirror of
https://github.com/abap2xlsx/abap2xlsx.git
synced 2025-05-05 08:06:15 +08:00

* Options to skip hidden rows and columns for CSV format Add options to skip hidden rows and columns when saving the data in CSV format. This is especially useful, when converting an ALV to an Excel object and saving it as CSV file. ALV layouts often display only selected columns. * Adding missing data definition Adding missing data definition for lo_autofilter. * Fix dates not converterted to external format Method get_default_excel_date_format of class zcl_excel_worksheet uses language "E" (English) to determine the date format from domain XUDATFM. Method create_csv of class zcl_excel_writer_csv has a logic to determine the field type from the number format. For this also the values from domain XUDATFM are used. But here they are read with sy-langu. Due to this, fields are not correctly identified as "date" when the user language is not English. Solution: Additionally read domain values with language "E". * Trigger filter area validation Trigger filter area validation * Fix date identification logic for newer AS ABAP versions The texts of domain XUDATFM changed in newer systems: NW 7.40: DD.MM.YYYY NW 7.52: DD.MM.YYYY (Gregorian Date) This breaks the date identification logic. New logic copied from get_date_format_des of class cl_abap_datfm, which is called in method get_default_excel_date_format of class zcl_excel_worksheet to get the users default date pattern. * Performance improvement for skip hidden rows Performance improvement for skip hidden rows --------- Co-authored-by: Domi Bigl <dominik.bigl@cadaxo.com> Co-authored-by: sandraros <34005250+sandraros@users.noreply.github.com>
378 lines
12 KiB
ABAP
378 lines
12 KiB
ABAP
CLASS zcl_excel_writer_csv DEFINITION
|
|
PUBLIC
|
|
FINAL
|
|
CREATE PUBLIC .
|
|
|
|
*"* public components of class ZCL_EXCEL_WRITER_CSV
|
|
*"* do not include other source files here!!!
|
|
PUBLIC SECTION.
|
|
|
|
INTERFACES zif_excel_writer .
|
|
|
|
"! Default value for initial dates e.g. user's format (DD.MM.YYYY, MM.DD.YYYY, etc.)
|
|
CONSTANTS c_default TYPE c LENGTH 10 VALUE 'DEFAULT' ##NO_TEXT.
|
|
|
|
CLASS-METHODS set_delimiter
|
|
IMPORTING
|
|
VALUE(ip_value) TYPE c DEFAULT ';' .
|
|
CLASS-METHODS set_enclosure
|
|
IMPORTING
|
|
VALUE(ip_value) TYPE c DEFAULT '"' .
|
|
CLASS-METHODS set_endofline
|
|
IMPORTING
|
|
VALUE(ip_value) TYPE any DEFAULT cl_abap_char_utilities=>cr_lf .
|
|
CLASS-METHODS set_active_sheet_index
|
|
IMPORTING
|
|
!i_active_worksheet TYPE zexcel_active_worksheet .
|
|
CLASS-METHODS set_active_sheet_index_by_name
|
|
IMPORTING
|
|
!i_worksheet_name TYPE zexcel_worksheets_name .
|
|
CLASS-METHODS set_initial_ext_date
|
|
IMPORTING
|
|
!ip_value TYPE char10 DEFAULT c_default .
|
|
CLASS-METHODS set_skip_hidden_rows
|
|
IMPORTING
|
|
!ip_value TYPE abap_bool.
|
|
CLASS-METHODS set_skip_hidden_columns
|
|
IMPORTING
|
|
!ip_value TYPE abap_bool.
|
|
*"* protected components of class ZCL_EXCEL_WRITER_CSV
|
|
*"* do not include other source files here!!!
|
|
PROTECTED SECTION.
|
|
*"* private components of class ZCL_EXCEL_WRITER_CSV
|
|
*"* do not include other source files here!!!
|
|
PRIVATE SECTION.
|
|
|
|
DATA excel TYPE REF TO zcl_excel .
|
|
CLASS-DATA delimiter TYPE c VALUE ';' ##NO_TEXT.
|
|
CLASS-DATA enclosure TYPE c VALUE '"' ##NO_TEXT.
|
|
CLASS-DATA:
|
|
eol TYPE c LENGTH 2 VALUE cl_abap_char_utilities=>cr_lf ##NO_TEXT.
|
|
CLASS-DATA worksheet_name TYPE zexcel_worksheets_name .
|
|
CLASS-DATA worksheet_index TYPE zexcel_active_worksheet .
|
|
CLASS-DATA initial_ext_date TYPE char10 VALUE c_default.
|
|
CLASS-DATA skip_hidden_rows TYPE abap_bool.
|
|
CLASS-DATA skip_hidden_columns TYPE abap_bool.
|
|
|
|
METHODS create
|
|
RETURNING
|
|
VALUE(ep_excel) TYPE xstring
|
|
RAISING
|
|
zcx_excel.
|
|
METHODS create_csv
|
|
RETURNING
|
|
VALUE(ep_content) TYPE xstring
|
|
RAISING
|
|
zcx_excel .
|
|
ENDCLASS.
|
|
|
|
|
|
|
|
CLASS ZCL_EXCEL_WRITER_CSV IMPLEMENTATION.
|
|
|
|
|
|
METHOD create.
|
|
|
|
* .csv format with ; delimiter
|
|
|
|
* Start of insertion # issue 1134 - Dateretention of cellstyles(issue #139)
|
|
me->excel->add_static_styles( ).
|
|
* End of insertion # issue 1134 - Dateretention of cellstyles(issue #139)
|
|
|
|
ep_excel = me->create_csv( ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD create_csv.
|
|
|
|
TYPES: BEGIN OF lty_format,
|
|
cmpname TYPE seocmpname,
|
|
attvalue TYPE seovalue,
|
|
END OF lty_format.
|
|
DATA: lt_format TYPE STANDARD TABLE OF lty_format,
|
|
ls_format LIKE LINE OF lt_format,
|
|
lv_date TYPE d,
|
|
lv_tmp TYPE string,
|
|
lv_time TYPE c LENGTH 8.
|
|
|
|
DATA: lo_iterator TYPE REF TO zcl_excel_collection_iterator,
|
|
lo_worksheet TYPE REF TO zcl_excel_worksheet.
|
|
|
|
DATA: lo_autofilter TYPE REF TO zcl_excel_autofilter.
|
|
DATA: lv_row_hidden TYPE abap_bool.
|
|
|
|
DATA: lt_cell_data TYPE zexcel_t_cell_data_unsorted,
|
|
lv_row TYPE i,
|
|
lv_col TYPE i,
|
|
lv_string TYPE string,
|
|
lc_value TYPE string,
|
|
lv_attrname TYPE seocmpname.
|
|
|
|
DATA: ls_numfmt TYPE zexcel_s_style_numfmt,
|
|
lo_style TYPE REF TO zcl_excel_style.
|
|
|
|
FIELD-SYMBOLS: <fs_sheet_content> TYPE zexcel_s_cell_data.
|
|
|
|
* --- Retrieve supported cell format
|
|
SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_format
|
|
FROM seocompodf
|
|
WHERE clsname = 'ZCL_EXCEL_STYLE_NUMBER_FORMAT'
|
|
AND typtype = 1
|
|
AND type = 'ZEXCEL_NUMBER_FORMAT'.
|
|
|
|
* --- Retrieve SAP date format
|
|
CLEAR ls_format.
|
|
SELECT ddtext INTO ls_format-attvalue FROM dd07t WHERE domname = 'XUDATFM'
|
|
AND ( ddlanguage = sy-langu OR ddlanguage = 'E' ).
|
|
ls_format-cmpname = 'DATE'.
|
|
ls_format-attvalue = ls_format-attvalue(10). " Ignore description, only use pattern
|
|
CONDENSE ls_format-attvalue.
|
|
CONCATENATE '''' ls_format-attvalue '''' INTO ls_format-attvalue.
|
|
APPEND ls_format TO lt_format.
|
|
ENDSELECT.
|
|
|
|
|
|
LOOP AT lt_format INTO ls_format.
|
|
TRANSLATE ls_format-attvalue TO UPPER CASE.
|
|
MODIFY lt_format FROM ls_format.
|
|
ENDLOOP.
|
|
|
|
|
|
* STEP 1: Collect strings from the first worksheet
|
|
lo_iterator = excel->get_worksheets_iterator( ).
|
|
DATA: current_worksheet_title TYPE zexcel_sheet_title.
|
|
|
|
WHILE lo_iterator->has_next( ) EQ abap_true.
|
|
lo_worksheet ?= lo_iterator->get_next( ).
|
|
|
|
IF worksheet_name IS NOT INITIAL.
|
|
current_worksheet_title = lo_worksheet->get_title( ).
|
|
CHECK current_worksheet_title = worksheet_name.
|
|
ELSE.
|
|
IF worksheet_index IS INITIAL.
|
|
worksheet_index = 1.
|
|
ENDIF.
|
|
CHECK worksheet_index = sy-index.
|
|
ENDIF.
|
|
APPEND LINES OF lo_worksheet->sheet_content TO lt_cell_data.
|
|
EXIT. " Take first worksheet only
|
|
ENDWHILE.
|
|
|
|
DELETE lt_cell_data WHERE cell_formula IS NOT INITIAL. " delete formula content
|
|
|
|
SORT lt_cell_data BY cell_row
|
|
cell_column.
|
|
|
|
IF skip_hidden_rows = abap_true.
|
|
* --- Retrieve autofilters (to identify hidden rows)
|
|
lo_autofilter = excel->get_autofilters_reference( )->get( io_worksheet = lo_worksheet ).
|
|
IF lo_autofilter IS NOT INITIAL.
|
|
lo_autofilter->get_filter_area( ). " trigger filter area validation
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
lv_row = 1.
|
|
lv_col = 1.
|
|
CLEAR lv_string.
|
|
LOOP AT lt_cell_data ASSIGNING <fs_sheet_content>.
|
|
|
|
* --- Check, if row is hidden
|
|
AT NEW cell_row.
|
|
IF lo_autofilter IS NOT INITIAL.
|
|
lv_row_hidden = lo_autofilter->is_row_hidden( iv_row = <fs_sheet_content>-cell_row ).
|
|
ENDIF.
|
|
ENDAT.
|
|
|
|
* --- Add empty rows
|
|
WHILE lv_row < <fs_sheet_content>-cell_row.
|
|
CONCATENATE lv_string zcl_excel_writer_csv=>eol INTO lv_string.
|
|
lv_row = lv_row + 1.
|
|
lv_col = 1.
|
|
ENDWHILE.
|
|
|
|
* --- Skip hidden rows
|
|
IF lv_row_hidden = abap_true.
|
|
lv_row = <fs_sheet_content>-cell_row + 1.
|
|
lv_col = 1.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
* --- Add empty columns
|
|
WHILE lv_col < <fs_sheet_content>-cell_column.
|
|
CONCATENATE lv_string zcl_excel_writer_csv=>delimiter INTO lv_string.
|
|
lv_col = lv_col + 1.
|
|
ENDWHILE.
|
|
|
|
* --- Skip hidden columns
|
|
IF skip_hidden_columns = abap_true AND
|
|
lo_worksheet->get_column( ip_column = <fs_sheet_content>-cell_column )->get_visible( ) = abap_false.
|
|
lv_col = <fs_sheet_content>-cell_column + 1.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
* --- Retrieve Cell Style format and data type
|
|
CLEAR ls_numfmt.
|
|
IF <fs_sheet_content>-data_type IS INITIAL AND <fs_sheet_content>-cell_style IS NOT INITIAL.
|
|
lo_iterator = excel->get_styles_iterator( ).
|
|
WHILE lo_iterator->has_next( ) EQ abap_true.
|
|
lo_style ?= lo_iterator->get_next( ).
|
|
CHECK lo_style->get_guid( ) = <fs_sheet_content>-cell_style.
|
|
ls_numfmt = lo_style->number_format->get_structure( ).
|
|
EXIT.
|
|
ENDWHILE.
|
|
ENDIF.
|
|
IF <fs_sheet_content>-data_type IS INITIAL AND ls_numfmt IS NOT INITIAL.
|
|
" determine data-type
|
|
CLEAR lv_attrname.
|
|
CONCATENATE '''' ls_numfmt-numfmt '''' INTO ls_numfmt-numfmt.
|
|
TRANSLATE ls_numfmt-numfmt TO UPPER CASE.
|
|
READ TABLE lt_format INTO ls_format WITH KEY attvalue = ls_numfmt-numfmt.
|
|
IF sy-subrc = 0.
|
|
lv_attrname = ls_format-cmpname.
|
|
ENDIF.
|
|
|
|
IF lv_attrname IS NOT INITIAL.
|
|
FIND FIRST OCCURRENCE OF 'DATETIME' IN lv_attrname.
|
|
IF sy-subrc = 0.
|
|
<fs_sheet_content>-data_type = 'd'.
|
|
ELSE.
|
|
FIND FIRST OCCURRENCE OF 'TIME' IN lv_attrname.
|
|
IF sy-subrc = 0.
|
|
<fs_sheet_content>-data_type = 't'.
|
|
ELSE.
|
|
FIND FIRST OCCURRENCE OF 'DATE' IN lv_attrname.
|
|
IF sy-subrc = 0.
|
|
<fs_sheet_content>-data_type = 'd'.
|
|
ELSE.
|
|
FIND FIRST OCCURRENCE OF 'CURRENCY' IN lv_attrname.
|
|
IF sy-subrc = 0.
|
|
<fs_sheet_content>-data_type = 'n'.
|
|
ELSE.
|
|
FIND FIRST OCCURRENCE OF 'NUMBER' IN lv_attrname.
|
|
IF sy-subrc = 0.
|
|
<fs_sheet_content>-data_type = 'n'.
|
|
ELSE.
|
|
FIND FIRST OCCURRENCE OF 'PERCENTAGE' IN lv_attrname.
|
|
IF sy-subrc = 0.
|
|
<fs_sheet_content>-data_type = 'n'.
|
|
ENDIF. " Purcentage
|
|
ENDIF. " Number
|
|
ENDIF. " Currency
|
|
ENDIF. " Date
|
|
ENDIF. " TIME
|
|
ENDIF. " DATETIME
|
|
ENDIF. " lv_attrname IS NOT INITIAL.
|
|
ENDIF. " <fs_sheet_content>-data_type IS INITIAL AND ls_numfmt IS NOT INITIAL.
|
|
|
|
* ----- Use format to determine the data type and display format.
|
|
CASE <fs_sheet_content>-data_type.
|
|
|
|
WHEN 'd' OR 'D'.
|
|
IF <fs_sheet_content>-cell_value IS INITIAL AND initial_ext_date <> c_default.
|
|
lc_value = initial_ext_date.
|
|
ELSE.
|
|
lc_value = zcl_excel_common=>excel_string_to_date( ip_value = <fs_sheet_content>-cell_value ).
|
|
TRY.
|
|
lv_date = lc_value.
|
|
CALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL'
|
|
EXPORTING
|
|
date_internal = lv_date
|
|
IMPORTING
|
|
date_external = lv_tmp
|
|
EXCEPTIONS
|
|
date_internal_is_invalid = 1
|
|
OTHERS = 2.
|
|
IF sy-subrc = 0.
|
|
lc_value = lv_tmp.
|
|
ENDIF.
|
|
|
|
CATCH cx_sy_conversion_no_number.
|
|
|
|
ENDTRY.
|
|
ENDIF.
|
|
|
|
WHEN 't' OR 'T'.
|
|
lc_value = zcl_excel_common=>excel_string_to_time( ip_value = <fs_sheet_content>-cell_value ).
|
|
WRITE lc_value TO lv_time USING EDIT MASK '__:__:__'.
|
|
lc_value = lv_time.
|
|
WHEN OTHERS.
|
|
lc_value = <fs_sheet_content>-cell_value.
|
|
|
|
ENDCASE.
|
|
|
|
CONCATENATE zcl_excel_writer_csv=>enclosure zcl_excel_writer_csv=>enclosure INTO lv_tmp.
|
|
CONDENSE lv_tmp.
|
|
REPLACE ALL OCCURRENCES OF zcl_excel_writer_csv=>enclosure IN lc_value WITH lv_tmp.
|
|
|
|
FIND FIRST OCCURRENCE OF zcl_excel_writer_csv=>delimiter IN lc_value.
|
|
IF sy-subrc = 0.
|
|
CONCATENATE lv_string zcl_excel_writer_csv=>enclosure lc_value zcl_excel_writer_csv=>enclosure INTO lv_string.
|
|
ELSE.
|
|
CONCATENATE lv_string lc_value INTO lv_string.
|
|
ENDIF.
|
|
|
|
ENDLOOP.
|
|
|
|
CLEAR ep_content.
|
|
|
|
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
|
|
EXPORTING
|
|
text = lv_string
|
|
IMPORTING
|
|
buffer = ep_content
|
|
EXCEPTIONS
|
|
failed = 1
|
|
OTHERS = 2.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_active_sheet_index.
|
|
CLEAR worksheet_name.
|
|
worksheet_index = i_active_worksheet.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_active_sheet_index_by_name.
|
|
CLEAR worksheet_index.
|
|
worksheet_name = i_worksheet_name.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_delimiter.
|
|
delimiter = ip_value.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_enclosure.
|
|
zcl_excel_writer_csv=>enclosure = ip_value.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_endofline.
|
|
zcl_excel_writer_csv=>eol = ip_value.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_initial_ext_date.
|
|
initial_ext_date = ip_value.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_skip_hidden_rows.
|
|
skip_hidden_rows = ip_value.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_skip_hidden_columns.
|
|
skip_hidden_columns = ip_value.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD zif_excel_writer~write_file.
|
|
me->excel = io_excel.
|
|
ep_file = me->create( ).
|
|
ENDMETHOD.
|
|
ENDCLASS.
|