mirror of
https://github.com/abap2xlsx/abap2xlsx.git
synced 2025-05-04 17:56:10 +08:00
extract font width logic to new class (#882)
* extract font width logic to new class * rename importing parameters * fixes * Update src/zcl_excel_font.clas.abap Co-authored-by: sandraros <34005250+sandraros@users.noreply.github.com> * Update src/zcl_excel_font.clas.abap Co-authored-by: sandraros <34005250+sandraros@users.noreply.github.com> * Update src/zcl_excel_worksheet.clas.abap Co-authored-by: sandraros <34005250+sandraros@users.noreply.github.com> * Update src/zcl_excel_font.clas.testclasses.abap Co-authored-by: sandraros <34005250+sandraros@users.noreply.github.com> * Update src/zcl_excel_font.clas.abap Co-authored-by: sandraros <34005250+sandraros@users.noreply.github.com> * fix syntax * Update src/zcl_excel_font.clas.abap Co-authored-by: sandraros <34005250+sandraros@users.noreply.github.com> Co-authored-by: sandraros <34005250+sandraros@users.noreply.github.com>
This commit is contained in:
parent
ea40b6860e
commit
fd83cbc112
183
src/zcl_excel_font.clas.abap
Normal file
183
src/zcl_excel_font.clas.abap
Normal file
|
@ -0,0 +1,183 @@
|
|||
CLASS zcl_excel_font DEFINITION
|
||||
PUBLIC
|
||||
FINAL
|
||||
CREATE PUBLIC .
|
||||
|
||||
PUBLIC SECTION.
|
||||
|
||||
TYPES:
|
||||
BEGIN OF mty_s_font_metric,
|
||||
char TYPE c LENGTH 1,
|
||||
char_width TYPE tdcwidths,
|
||||
END OF mty_s_font_metric .
|
||||
TYPES:
|
||||
mty_th_font_metrics
|
||||
TYPE HASHED TABLE OF mty_s_font_metric
|
||||
WITH UNIQUE KEY char .
|
||||
TYPES:
|
||||
BEGIN OF mty_s_font_cache,
|
||||
font_name TYPE zexcel_style_font_name,
|
||||
font_height TYPE tdfontsize,
|
||||
flag_bold TYPE abap_bool,
|
||||
flag_italic TYPE abap_bool,
|
||||
th_font_metrics TYPE mty_th_font_metrics,
|
||||
END OF mty_s_font_cache .
|
||||
TYPES:
|
||||
mty_th_font_cache
|
||||
TYPE HASHED TABLE OF mty_s_font_cache
|
||||
WITH UNIQUE KEY font_name font_height flag_bold flag_italic .
|
||||
|
||||
CONSTANTS lc_default_font_height TYPE tdfontsize VALUE '110' ##NO_TEXT.
|
||||
CONSTANTS lc_default_font_name TYPE zexcel_style_font_name VALUE 'Calibri' ##NO_TEXT.
|
||||
CLASS-DATA mth_font_cache TYPE mty_th_font_cache .
|
||||
|
||||
CLASS-METHODS calculate_text_width
|
||||
IMPORTING
|
||||
!iv_font_name TYPE zexcel_style_font_name
|
||||
!iv_font_height TYPE tdfontsize
|
||||
!iv_flag_bold TYPE abap_bool
|
||||
!iv_flag_italic TYPE abap_bool
|
||||
!iv_cell_value TYPE zexcel_cell_value
|
||||
RETURNING
|
||||
VALUE(rv_width) TYPE float .
|
||||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
|
||||
CLASS ZCL_EXCEL_FONT IMPLEMENTATION.
|
||||
|
||||
|
||||
METHOD calculate_text_width.
|
||||
|
||||
CONSTANTS lc_excel_cell_padding TYPE float VALUE '0.75'.
|
||||
|
||||
DATA: ld_current_character TYPE c LENGTH 1,
|
||||
lt_itcfc TYPE STANDARD TABLE OF itcfc,
|
||||
ld_offset TYPE i,
|
||||
ld_length TYPE i,
|
||||
ld_uccp TYPE i,
|
||||
ls_font_metric TYPE mty_s_font_metric,
|
||||
ld_width_from_font_metrics TYPE i,
|
||||
ld_font_family TYPE itcfh-tdfamily,
|
||||
lt_font_families LIKE STANDARD TABLE OF ld_font_family,
|
||||
ls_font_cache TYPE mty_s_font_cache.
|
||||
|
||||
FIELD-SYMBOLS: <ls_font_cache> TYPE mty_s_font_cache,
|
||||
<ls_font_metric> TYPE mty_s_font_metric,
|
||||
<ls_itcfc> TYPE itcfc.
|
||||
|
||||
" Check if the same font (font name and font attributes) was already
|
||||
" used before
|
||||
READ TABLE mth_font_cache
|
||||
WITH TABLE KEY
|
||||
font_name = iv_font_name
|
||||
font_height = iv_font_height
|
||||
flag_bold = iv_flag_bold
|
||||
flag_italic = iv_flag_italic
|
||||
ASSIGNING <ls_font_cache>.
|
||||
|
||||
IF sy-subrc <> 0.
|
||||
" Font is used for the first time
|
||||
" Add the font to our local font cache
|
||||
ls_font_cache-font_name = iv_font_name.
|
||||
ls_font_cache-font_height = iv_font_height.
|
||||
ls_font_cache-flag_bold = iv_flag_bold.
|
||||
ls_font_cache-flag_italic = iv_flag_italic.
|
||||
INSERT ls_font_cache INTO TABLE mth_font_cache
|
||||
ASSIGNING <ls_font_cache>.
|
||||
|
||||
" Determine the SAPscript font family name from the Excel
|
||||
" font name
|
||||
SELECT tdfamily
|
||||
FROM tfo01
|
||||
INTO TABLE lt_font_families
|
||||
UP TO 1 ROWS
|
||||
WHERE tdtext = iv_font_name
|
||||
ORDER BY PRIMARY KEY.
|
||||
|
||||
" Check if a matching font family was found
|
||||
" Fonts can be uploaded from TTF files using transaction SE73
|
||||
IF lines( lt_font_families ) > 0.
|
||||
READ TABLE lt_font_families INDEX 1 INTO ld_font_family.
|
||||
|
||||
" Load font metrics (returns a table with the size of each letter
|
||||
" in the font)
|
||||
CALL FUNCTION 'LOAD_FONT'
|
||||
EXPORTING
|
||||
family = ld_font_family
|
||||
height = iv_font_height
|
||||
printer = 'SWIN'
|
||||
bold = iv_flag_bold
|
||||
italic = iv_flag_italic
|
||||
TABLES
|
||||
metric = lt_itcfc
|
||||
EXCEPTIONS
|
||||
font_family = 1
|
||||
codepage = 2
|
||||
device_type = 3
|
||||
OTHERS = 4.
|
||||
IF sy-subrc <> 0.
|
||||
CLEAR lt_itcfc.
|
||||
ENDIF.
|
||||
|
||||
" For faster access, convert each character number to the actual
|
||||
" character, and store the characters and their sizes in a hash
|
||||
" table
|
||||
LOOP AT lt_itcfc ASSIGNING <ls_itcfc>.
|
||||
ld_uccp = <ls_itcfc>-cpcharno.
|
||||
ls_font_metric-char =
|
||||
cl_abap_conv_in_ce=>uccpi( ld_uccp ).
|
||||
ls_font_metric-char_width = <ls_itcfc>-tdcwidths.
|
||||
INSERT ls_font_metric
|
||||
INTO TABLE <ls_font_cache>-th_font_metrics.
|
||||
ENDLOOP.
|
||||
|
||||
ENDIF.
|
||||
ENDIF.
|
||||
|
||||
" Calculate the cell width
|
||||
" If available, use font metrics
|
||||
IF lines( <ls_font_cache>-th_font_metrics ) = 0.
|
||||
" Font metrics are not available
|
||||
" -> Calculate the cell width using only the font size
|
||||
ld_length = strlen( iv_cell_value ).
|
||||
rv_width = ld_length * iv_font_height / lc_default_font_height + lc_excel_cell_padding.
|
||||
|
||||
ELSE.
|
||||
" Font metrics are available
|
||||
|
||||
" Calculate the size of the text by adding the sizes of each
|
||||
" letter
|
||||
ld_length = strlen( iv_cell_value ).
|
||||
DO ld_length TIMES.
|
||||
" Subtract 1, because the first character is at offset 0
|
||||
ld_offset = sy-index - 1.
|
||||
|
||||
" Read the current character from the cell value
|
||||
ld_current_character = iv_cell_value+ld_offset(1).
|
||||
|
||||
" Look up the size of the current letter
|
||||
READ TABLE <ls_font_cache>-th_font_metrics
|
||||
WITH TABLE KEY char = ld_current_character
|
||||
ASSIGNING <ls_font_metric>.
|
||||
IF sy-subrc = 0.
|
||||
" The size of the letter is known
|
||||
" -> Add the actual size of the letter
|
||||
ADD <ls_font_metric>-char_width TO ld_width_from_font_metrics.
|
||||
ELSE.
|
||||
" The size of the letter is unknown
|
||||
" -> Add the font height as the default letter size
|
||||
ADD iv_font_height TO ld_width_from_font_metrics.
|
||||
ENDIF.
|
||||
ENDDO.
|
||||
|
||||
" Add cell padding (Excel makes columns a bit wider than the space
|
||||
" that is needed for the text itself) and convert unit
|
||||
" (division by 100)
|
||||
rv_width = ld_width_from_font_metrics / 100 + lc_excel_cell_padding.
|
||||
ENDIF.
|
||||
|
||||
ENDMETHOD.
|
||||
ENDCLASS.
|
27
src/zcl_excel_font.clas.testclasses.abap
Normal file
27
src/zcl_excel_font.clas.testclasses.abap
Normal file
|
@ -0,0 +1,27 @@
|
|||
CLASS ltcl_Test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
|
||||
|
||||
PRIVATE SECTION.
|
||||
METHODS calculate FOR TESTING RAISING cx_static_check.
|
||||
ENDCLASS.
|
||||
|
||||
|
||||
CLASS ltcl_Test IMPLEMENTATION.
|
||||
|
||||
METHOD calculate.
|
||||
|
||||
DATA lv_width TYPE f.
|
||||
|
||||
lv_width = zcl_excel_font=>calculate_text_width(
|
||||
iv_font_name = 'foobar'
|
||||
iv_font_height = 20
|
||||
iv_flag_bold = abap_false
|
||||
iv_flag_italic = abap_false
|
||||
iv_cell_value = 'hello world' ).
|
||||
|
||||
cl_abap_unit_assert=>assert_equals(
|
||||
act = lv_width
|
||||
exp = '2.75' ).
|
||||
|
||||
ENDMETHOD.
|
||||
|
||||
ENDCLASS.
|
17
src/zcl_excel_font.clas.xml
Normal file
17
src/zcl_excel_font.clas.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
|
||||
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
|
||||
<asx:values>
|
||||
<VSEOCLASS>
|
||||
<CLSNAME>ZCL_EXCEL_FONT</CLSNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>abap2xlsx - Font Logic</DESCRIPT>
|
||||
<STATE>1</STATE>
|
||||
<CLSCCINCL>X</CLSCCINCL>
|
||||
<FIXPT>X</FIXPT>
|
||||
<UNICODE>X</UNICODE>
|
||||
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
|
||||
</VSEOCLASS>
|
||||
</asx:values>
|
||||
</asx:abap>
|
||||
</abapGit>
|
|
@ -620,30 +620,6 @@ CLASS zcl_excel_worksheet DEFINITION
|
|||
PROTECTED SECTION.
|
||||
PRIVATE SECTION.
|
||||
|
||||
TYPES:
|
||||
BEGIN OF mty_s_font_metric,
|
||||
char TYPE c LENGTH 1,
|
||||
char_width TYPE tdcwidths,
|
||||
END OF mty_s_font_metric .
|
||||
TYPES:
|
||||
mty_th_font_metrics
|
||||
TYPE HASHED TABLE OF mty_s_font_metric
|
||||
WITH UNIQUE KEY char .
|
||||
TYPES:
|
||||
BEGIN OF mty_s_font_cache,
|
||||
font_name TYPE zexcel_style_font_name,
|
||||
font_height TYPE tdfontsize,
|
||||
flag_bold TYPE abap_bool,
|
||||
flag_italic TYPE abap_bool,
|
||||
th_font_metrics TYPE mty_th_font_metrics,
|
||||
END OF mty_s_font_cache .
|
||||
TYPES:
|
||||
mty_th_font_cache
|
||||
TYPE HASHED TABLE OF mty_s_font_cache
|
||||
WITH UNIQUE KEY font_name font_height flag_bold flag_italic .
|
||||
* types:
|
||||
* mty_ts_row_dimension TYPE SORTED TABLE OF zexcel_s_worksheet_rowdimensio WITH UNIQUE KEY row .
|
||||
|
||||
*"* private components of class ZCL_EXCEL_WORKSHEET
|
||||
*"* do not include other source files here!!!
|
||||
DATA active_cell TYPE zexcel_s_cell_data .
|
||||
|
@ -663,7 +639,6 @@ CLASS zcl_excel_worksheet DEFINITION
|
|||
DATA hyperlinks TYPE REF TO cl_object_collection .
|
||||
DATA lower_cell TYPE zexcel_s_cell_data .
|
||||
DATA mo_pagebreaks TYPE REF TO zcl_excel_worksheet_pagebreaks .
|
||||
CLASS-DATA mth_font_cache TYPE mty_th_font_cache .
|
||||
DATA mt_row_outlines TYPE mty_ts_outlines_row .
|
||||
DATA print_title_col_from TYPE zexcel_cell_column_alpha .
|
||||
DATA print_title_col_to TYPE zexcel_cell_column_alpha .
|
||||
|
@ -1222,13 +1197,7 @@ CLASS ZCL_EXCEL_WORKSHEET IMPLEMENTATION.
|
|||
* - Add cell padding to simulate Excel behavior
|
||||
*--------------------------------------------------------------------*
|
||||
|
||||
CONSTANTS:
|
||||
lc_default_font_name TYPE zexcel_style_font_name VALUE 'Calibri', "#EC NOTEXT
|
||||
lc_default_font_height TYPE tdfontsize VALUE '110',
|
||||
lc_excel_cell_padding TYPE float VALUE '0.75'.
|
||||
|
||||
DATA: ld_cell_value TYPE zexcel_cell_value,
|
||||
ld_current_character TYPE c LENGTH 1,
|
||||
ld_style_guid TYPE zexcel_cell_style,
|
||||
ls_stylemapping TYPE zexcel_s_stylemapping,
|
||||
lo_table_object TYPE REF TO object,
|
||||
|
@ -1240,21 +1209,8 @@ CLASS ZCL_EXCEL_WORKSHEET IMPLEMENTATION.
|
|||
ld_flag_italic TYPE abap_bool VALUE abap_false,
|
||||
ld_date TYPE d,
|
||||
ld_date_char TYPE c LENGTH 50,
|
||||
ld_font_height TYPE tdfontsize VALUE lc_default_font_height,
|
||||
lt_itcfc TYPE STANDARD TABLE OF itcfc,
|
||||
ld_offset TYPE i,
|
||||
ld_length TYPE i,
|
||||
ld_uccp TYPE i,
|
||||
ls_font_metric TYPE mty_s_font_metric,
|
||||
ld_width_from_font_metrics TYPE i,
|
||||
ld_font_family TYPE itcfh-tdfamily,
|
||||
ld_font_name TYPE zexcel_style_font_name VALUE lc_default_font_name,
|
||||
lt_font_families LIKE STANDARD TABLE OF ld_font_family,
|
||||
ls_font_cache TYPE mty_s_font_cache.
|
||||
|
||||
FIELD-SYMBOLS: <ls_font_cache> TYPE mty_s_font_cache,
|
||||
<ls_font_metric> TYPE mty_s_font_metric,
|
||||
<ls_itcfc> TYPE itcfc.
|
||||
ld_font_height TYPE tdfontsize VALUE zcl_excel_font=>lc_default_font_height,
|
||||
ld_font_name TYPE zexcel_style_font_name VALUE zcl_excel_font=>lc_default_font_name.
|
||||
|
||||
" Determine cell content and cell style
|
||||
me->get_cell( EXPORTING ip_column = ip_column
|
||||
|
@ -1340,116 +1296,12 @@ CLASS ZCL_EXCEL_WORKSHEET IMPLEMENTATION.
|
|||
ENDTRY.
|
||||
ENDIF.
|
||||
|
||||
" Check if the same font (font name and font attributes) was already
|
||||
" used before
|
||||
READ TABLE mth_font_cache
|
||||
WITH TABLE KEY
|
||||
font_name = ld_font_name
|
||||
font_height = ld_font_height
|
||||
flag_bold = ld_flag_bold
|
||||
flag_italic = ld_flag_italic
|
||||
ASSIGNING <ls_font_cache>.
|
||||
|
||||
IF sy-subrc <> 0.
|
||||
" Font is used for the first time
|
||||
" Add the font to our local font cache
|
||||
ls_font_cache-font_name = ld_font_name.
|
||||
ls_font_cache-font_height = ld_font_height.
|
||||
ls_font_cache-flag_bold = ld_flag_bold.
|
||||
ls_font_cache-flag_italic = ld_flag_italic.
|
||||
INSERT ls_font_cache INTO TABLE mth_font_cache
|
||||
ASSIGNING <ls_font_cache>.
|
||||
|
||||
" Determine the SAPscript font family name from the Excel
|
||||
" font name
|
||||
SELECT tdfamily
|
||||
FROM tfo01
|
||||
INTO TABLE lt_font_families
|
||||
UP TO 1 ROWS
|
||||
WHERE tdtext = ld_font_name
|
||||
ORDER BY PRIMARY KEY.
|
||||
|
||||
" Check if a matching font family was found
|
||||
" Fonts can be uploaded from TTF files using transaction SE73
|
||||
IF lines( lt_font_families ) > 0.
|
||||
READ TABLE lt_font_families INDEX 1 INTO ld_font_family.
|
||||
|
||||
" Load font metrics (returns a table with the size of each letter
|
||||
" in the font)
|
||||
CALL FUNCTION 'LOAD_FONT'
|
||||
EXPORTING
|
||||
family = ld_font_family
|
||||
height = ld_font_height
|
||||
printer = 'SWIN'
|
||||
bold = ld_flag_bold
|
||||
italic = ld_flag_italic
|
||||
TABLES
|
||||
metric = lt_itcfc
|
||||
EXCEPTIONS
|
||||
font_family = 1
|
||||
codepage = 2
|
||||
device_type = 3
|
||||
OTHERS = 4.
|
||||
IF sy-subrc <> 0.
|
||||
CLEAR lt_itcfc.
|
||||
ENDIF.
|
||||
|
||||
" For faster access, convert each character number to the actual
|
||||
" character, and store the characters and their sizes in a hash
|
||||
" table
|
||||
LOOP AT lt_itcfc ASSIGNING <ls_itcfc>.
|
||||
ld_uccp = <ls_itcfc>-cpcharno.
|
||||
ls_font_metric-char =
|
||||
cl_abap_conv_in_ce=>uccpi( ld_uccp ).
|
||||
ls_font_metric-char_width = <ls_itcfc>-tdcwidths.
|
||||
INSERT ls_font_metric
|
||||
INTO TABLE <ls_font_cache>-th_font_metrics.
|
||||
ENDLOOP.
|
||||
|
||||
ENDIF.
|
||||
ENDIF.
|
||||
|
||||
" Calculate the cell width
|
||||
" If available, use font metrics
|
||||
IF lines( <ls_font_cache>-th_font_metrics ) = 0.
|
||||
" Font metrics are not available
|
||||
" -> Calculate the cell width using only the font size
|
||||
ld_length = strlen( ld_cell_value ).
|
||||
ep_width = ld_length * ld_font_height / lc_default_font_height + lc_excel_cell_padding.
|
||||
|
||||
ELSE.
|
||||
" Font metrics are available
|
||||
|
||||
" Calculate the size of the text by adding the sizes of each
|
||||
" letter
|
||||
ld_length = strlen( ld_cell_value ).
|
||||
DO ld_length TIMES.
|
||||
" Subtract 1, because the first character is at offset 0
|
||||
ld_offset = sy-index - 1.
|
||||
|
||||
" Read the current character from the cell value
|
||||
ld_current_character = ld_cell_value+ld_offset(1).
|
||||
|
||||
" Look up the size of the current letter
|
||||
READ TABLE <ls_font_cache>-th_font_metrics
|
||||
WITH TABLE KEY char = ld_current_character
|
||||
ASSIGNING <ls_font_metric>.
|
||||
IF sy-subrc = 0.
|
||||
" The size of the letter is known
|
||||
" -> Add the actual size of the letter
|
||||
ADD <ls_font_metric>-char_width TO ld_width_from_font_metrics.
|
||||
ELSE.
|
||||
" The size of the letter is unknown
|
||||
" -> Add the font height as the default letter size
|
||||
ADD ld_font_height TO ld_width_from_font_metrics.
|
||||
ENDIF.
|
||||
ENDDO.
|
||||
|
||||
" Add cell padding (Excel makes columns a bit wider than the space
|
||||
" that is needed for the text itself) and convert unit
|
||||
" (division by 100)
|
||||
ep_width = ld_width_from_font_metrics / 100 + lc_excel_cell_padding.
|
||||
ENDIF.
|
||||
ep_width = zcl_excel_font=>calculate_text_width(
|
||||
iv_font_name = ld_font_name
|
||||
iv_font_height = ld_font_height
|
||||
iv_flag_bold = ld_flag_bold
|
||||
iv_flag_italic = ld_flag_italic
|
||||
iv_cell_value = ld_cell_value ).
|
||||
|
||||
" If the current cell contains an auto filter, make it a bit wider.
|
||||
" The size used by the auto filter button does not depend on the font
|
||||
|
@ -1458,7 +1310,7 @@ CLASS ZCL_EXCEL_WORKSHEET IMPLEMENTATION.
|
|||
ADD 2 TO ep_width.
|
||||
ENDIF.
|
||||
|
||||
ENDMETHOD. "CALCULATE_CELL_WIDTH
|
||||
ENDMETHOD.
|
||||
|
||||
|
||||
METHOD calculate_column_widths.
|
||||
|
|
|
@ -753,12 +753,6 @@
|
|||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>Pagebreaks</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_EXCEL_WORKSHEET</CLSNAME>
|
||||
<CMPNAME>MTH_FONT_CACHE</CMPNAME>
|
||||
<LANGU>E</LANGU>
|
||||
<DESCRIPT>Hash table containing fonts and their metrics</DESCRIPT>
|
||||
</SEOCOMPOTX>
|
||||
<SEOCOMPOTX>
|
||||
<CLSNAME>ZCL_EXCEL_WORKSHEET</CLSNAME>
|
||||
<CMPNAME>MTY_MERGE</CMPNAME>
|
||||
|
|
Loading…
Reference in New Issue
Block a user