caxlsx 2.0.2 → 3.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +125 -30
- data/README.md +65 -151
- data/Rakefile +9 -11
- data/examples/{image1.jpeg → assets/image1.jpeg} +0 -0
- data/examples/generate.rb +15 -0
- data/lib/axlsx.rb +35 -17
- data/lib/axlsx/content_type/abstract_content_type.rb +1 -1
- data/lib/axlsx/content_type/content_type.rb +1 -1
- data/lib/axlsx/doc_props/app.rb +1 -1
- data/lib/axlsx/doc_props/core.rb +5 -5
- data/lib/axlsx/drawing/area_chart.rb +99 -0
- data/lib/axlsx/drawing/area_series.rb +110 -0
- data/lib/axlsx/drawing/axes.rb +1 -1
- data/lib/axlsx/drawing/axis.rb +12 -9
- data/lib/axlsx/drawing/bar_3D_chart.rb +13 -13
- data/lib/axlsx/drawing/bar_chart.rb +143 -0
- data/lib/axlsx/drawing/bar_series.rb +12 -14
- data/lib/axlsx/drawing/bubble_chart.rb +59 -0
- data/lib/axlsx/drawing/bubble_series.rb +63 -0
- data/lib/axlsx/drawing/cat_axis.rb +5 -5
- data/lib/axlsx/drawing/chart.rb +52 -8
- data/lib/axlsx/drawing/d_lbls.rb +4 -4
- data/lib/axlsx/drawing/drawing.rb +6 -1
- data/lib/axlsx/drawing/graphic_frame.rb +3 -3
- data/lib/axlsx/drawing/hyperlink.rb +1 -3
- data/lib/axlsx/drawing/line_3D_chart.rb +2 -2
- data/lib/axlsx/drawing/line_chart.rb +10 -10
- data/lib/axlsx/drawing/line_series.rb +32 -3
- data/lib/axlsx/drawing/marker.rb +1 -1
- data/lib/axlsx/drawing/num_data.rb +4 -4
- data/lib/axlsx/drawing/num_data_source.rb +6 -6
- data/lib/axlsx/drawing/num_val.rb +3 -1
- data/lib/axlsx/drawing/one_cell_anchor.rb +3 -2
- data/lib/axlsx/drawing/pic.rb +25 -19
- data/lib/axlsx/drawing/picture_locking.rb +1 -3
- data/lib/axlsx/drawing/pie_3D_chart.rb +5 -6
- data/lib/axlsx/drawing/pie_series.rb +6 -6
- data/lib/axlsx/drawing/scaling.rb +6 -6
- data/lib/axlsx/drawing/scatter_chart.rb +10 -10
- data/lib/axlsx/drawing/scatter_series.rb +40 -7
- data/lib/axlsx/drawing/ser_axis.rb +2 -2
- data/lib/axlsx/drawing/series.rb +3 -3
- data/lib/axlsx/drawing/series_title.rb +4 -2
- data/lib/axlsx/drawing/str_data.rb +3 -3
- data/lib/axlsx/drawing/str_val.rb +3 -1
- data/lib/axlsx/drawing/title.rb +23 -4
- data/lib/axlsx/drawing/two_cell_anchor.rb +6 -1
- data/lib/axlsx/drawing/val_axis.rb +1 -1
- data/lib/axlsx/drawing/view_3D.rb +2 -2
- data/lib/axlsx/drawing/vml_drawing.rb +1 -1
- data/lib/axlsx/package.rb +58 -47
- data/lib/axlsx/rels/relationship.rb +27 -26
- data/lib/axlsx/rels/relationships.rb +7 -4
- data/lib/axlsx/stylesheet/border_pr.rb +2 -2
- data/lib/axlsx/stylesheet/cell_alignment.rb +1 -3
- data/lib/axlsx/stylesheet/cell_protection.rb +1 -3
- data/lib/axlsx/stylesheet/cell_style.rb +1 -3
- data/lib/axlsx/stylesheet/color.rb +1 -3
- data/lib/axlsx/stylesheet/font.rb +11 -3
- data/lib/axlsx/stylesheet/gradient_stop.rb +1 -1
- data/lib/axlsx/stylesheet/num_fmt.rb +10 -3
- data/lib/axlsx/stylesheet/pattern_fill.rb +1 -1
- data/lib/axlsx/stylesheet/styles.rb +7 -7
- data/lib/axlsx/stylesheet/table_style_element.rb +1 -3
- data/lib/axlsx/util/accessors.rb +6 -6
- data/lib/axlsx/util/constants.rb +108 -99
- data/lib/axlsx/util/mime_type_utils.rb +11 -0
- data/lib/axlsx/util/options_parser.rb +2 -1
- data/lib/axlsx/util/serialized_attributes.rb +16 -6
- data/lib/axlsx/util/simple_typed_list.rb +28 -52
- data/lib/axlsx/util/storage.rb +4 -4
- data/lib/axlsx/util/validators.rb +31 -19
- data/lib/axlsx/util/zip_command.rb +73 -0
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/defined_name.rb +11 -12
- data/lib/axlsx/workbook/defined_names.rb +2 -2
- data/lib/axlsx/workbook/shared_strings_table.rb +5 -5
- data/lib/axlsx/workbook/workbook.rb +36 -20
- data/lib/axlsx/workbook/workbook_view.rb +80 -0
- data/lib/axlsx/workbook/workbook_views.rb +22 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +2 -2
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +1 -3
- data/lib/axlsx/workbook/worksheet/break.rb +1 -3
- data/lib/axlsx/workbook/worksheet/cell.rb +164 -75
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +63 -43
- data/lib/axlsx/workbook/worksheet/cfvo.rb +1 -3
- data/lib/axlsx/workbook/worksheet/cfvos.rb +4 -1
- data/lib/axlsx/workbook/worksheet/col.rb +14 -13
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +2 -2
- data/lib/axlsx/workbook/worksheet/cols.rb +5 -2
- data/lib/axlsx/workbook/worksheet/comment.rb +5 -6
- data/lib/axlsx/workbook/worksheet/comments.rb +9 -12
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +1 -1
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
- data/lib/axlsx/workbook/worksheet/data_bar.rb +4 -6
- data/lib/axlsx/workbook/worksheet/data_validation.rb +8 -6
- data/lib/axlsx/workbook/worksheet/dimension.rb +2 -2
- data/lib/axlsx/workbook/worksheet/header_footer.rb +6 -8
- data/lib/axlsx/workbook/worksheet/icon_set.rb +3 -5
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +4 -2
- data/lib/axlsx/workbook/worksheet/outline_pr.rb +33 -0
- data/lib/axlsx/workbook/worksheet/page_margins.rb +1 -3
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -1
- data/lib/axlsx/workbook/worksheet/page_setup.rb +21 -23
- data/lib/axlsx/workbook/worksheet/pane.rb +1 -3
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +44 -28
- data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -4
- data/lib/axlsx/workbook/worksheet/print_options.rb +1 -3
- data/lib/axlsx/workbook/worksheet/protected_range.rb +1 -3
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +5 -2
- data/lib/axlsx/workbook/worksheet/rich_text.rb +55 -0
- data/lib/axlsx/workbook/worksheet/rich_text_run.rb +250 -0
- data/lib/axlsx/workbook/worksheet/row.rb +42 -52
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +2 -2
- data/lib/axlsx/workbook/worksheet/selection.rb +1 -3
- data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +21 -3
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -3
- data/lib/axlsx/workbook/worksheet/table.rb +6 -6
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +1 -3
- data/lib/axlsx/workbook/worksheet/tables.rb +4 -1
- data/lib/axlsx/workbook/worksheet/worksheet.rb +76 -81
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +10 -10
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +3 -3
- data/lib/caxlsx.rb +2 -0
- data/test/drawing/tc_area_chart.rb +39 -0
- data/test/drawing/tc_area_series.rb +71 -0
- data/test/drawing/tc_axis.rb +27 -0
- data/test/drawing/tc_bar_chart.rb +71 -0
- data/test/drawing/tc_bubble_chart.rb +44 -0
- data/test/drawing/tc_bubble_series.rb +21 -0
- data/test/drawing/tc_chart.rb +23 -10
- data/test/drawing/tc_data_source.rb +6 -0
- data/test/drawing/tc_drawing.rb +4 -4
- data/test/drawing/tc_hyperlink.rb +1 -1
- data/test/drawing/tc_line_chart.rb +5 -5
- data/test/drawing/tc_line_series.rb +47 -6
- data/test/drawing/tc_one_cell_anchor.rb +1 -1
- data/test/drawing/tc_pic.rb +11 -15
- data/test/drawing/tc_pie_series.rb +2 -1
- data/test/drawing/tc_scatter_series.rb +36 -1
- data/test/drawing/tc_series_title.rb +21 -0
- data/test/drawing/tc_str_val.rb +9 -0
- data/test/drawing/tc_title.rb +21 -0
- data/test/fixtures/image1.gif +0 -0
- data/test/fixtures/image1.jpeg +0 -0
- data/test/fixtures/image1.jpg +0 -0
- data/test/fixtures/image1.png +0 -0
- data/test/fixtures/image1_fake.jpg +0 -0
- data/test/rels/tc_relationship.rb +8 -0
- data/test/stylesheet/tc_font.rb +14 -2
- data/test/stylesheet/tc_styles.rb +29 -3
- data/test/tc_axlsx.rb +37 -0
- data/test/tc_helper.rb +2 -0
- data/test/tc_package.rb +50 -13
- data/test/util/tc_mime_type_utils.rb +13 -0
- data/test/util/tc_simple_typed_list.rb +2 -3
- data/test/util/tc_validators.rb +35 -11
- data/test/workbook/tc_defined_name.rb +12 -4
- data/test/workbook/tc_shared_strings_table.rb +16 -1
- data/test/workbook/tc_workbook.rb +38 -3
- data/test/workbook/tc_workbook_view.rb +50 -0
- data/test/workbook/worksheet/auto_filter/tc_filters.rb +1 -1
- data/test/workbook/worksheet/tc_break.rb +1 -1
- data/test/workbook/worksheet/tc_cell.rb +143 -9
- data/test/workbook/worksheet/tc_col.rb +18 -3
- data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
- data/test/workbook/worksheet/tc_data_bar.rb +1 -1
- data/test/workbook/worksheet/tc_data_validation.rb +11 -11
- data/test/workbook/worksheet/tc_header_footer.rb +2 -2
- data/test/workbook/worksheet/tc_icon_set.rb +1 -1
- data/test/workbook/worksheet/tc_outline_pr.rb +19 -0
- data/test/workbook/worksheet/tc_page_setup.rb +3 -3
- data/test/workbook/worksheet/tc_pivot_table.rb +21 -6
- data/test/workbook/worksheet/tc_print_options.rb +1 -1
- data/test/workbook/worksheet/tc_rich_text.rb +44 -0
- data/test/workbook/worksheet/tc_rich_text_run.rb +173 -0
- data/test/workbook/worksheet/tc_row.rb +24 -2
- data/test/workbook/worksheet/tc_sheet_calc_pr.rb +1 -1
- data/test/workbook/worksheet/tc_sheet_format_pr.rb +4 -4
- data/test/workbook/worksheet/tc_sheet_pr.rb +26 -4
- data/test/workbook/worksheet/tc_sheet_protection.rb +5 -5
- data/test/workbook/worksheet/tc_sheet_view.rb +4 -4
- data/test/workbook/worksheet/tc_table.rb +2 -3
- data/test/workbook/worksheet/tc_worksheet.rb +123 -60
- metadata +180 -128
- data/examples/2010_comments.rb +0 -17
- data/examples/anchor_swapping.rb +0 -28
- data/examples/auto_filter.rb +0 -16
- data/examples/basic_charts.rb +0 -58
- data/examples/chart_colors.rb +0 -88
- data/examples/colored_links.rb +0 -59
- data/examples/conditional_formatting/example_conditional_formatting.rb +0 -74
- data/examples/conditional_formatting/getting_barred.rb +0 -37
- data/examples/conditional_formatting/hitting_the_high_notes.rb +0 -37
- data/examples/conditional_formatting/scaled_colors.rb +0 -39
- data/examples/conditional_formatting/stop_and_go.rb +0 -37
- data/examples/data_validation.rb +0 -50
- data/examples/example.rb +0 -777
- data/examples/extractive.rb +0 -45
- data/examples/ios_preview.rb +0 -14
- data/examples/page_setup.rb +0 -11
- data/examples/pivot_table.rb +0 -39
- data/examples/sheet_protection.rb +0 -10
- data/examples/skydrive/real_example.rb +0 -63
- data/examples/styles.rb +0 -66
- data/examples/underline.rb +0 -13
- data/examples/wrap_text.rb +0 -21
- data/lib/axlsx/util/parser.rb +0 -44
data/lib/axlsx/version.rb
CHANGED
@@ -24,16 +24,16 @@
|
|
24
24
|
# </xsd:simpleContent>
|
25
25
|
|
26
26
|
module Axlsx
|
27
|
-
# This element defines the defined names that are defined within this workbook.
|
27
|
+
# This element defines the defined names that are defined within this workbook.
|
28
28
|
# Defined names are descriptive text that is used to represents a cell, range of cells, formula, or constant value.
|
29
29
|
# Use easy-to-understand names, such as Products, to refer to hard to understand ranges, such as Sales!C20:C30.
|
30
|
-
# A defined name in a formula can make it easier to understand the purpose of the formula.
|
30
|
+
# A defined name in a formula can make it easier to understand the purpose of the formula.
|
31
31
|
# @example
|
32
32
|
# The formula =SUM(FirstQuarterSales) might be easier to identify than =SUM(C20:C30
|
33
33
|
#
|
34
34
|
# Names are available to any sheet.
|
35
35
|
# @example
|
36
|
-
# If the name ProjectedSales refers to the range A20:A30 on the first worksheet in a workbook,
|
36
|
+
# If the name ProjectedSales refers to the range A20:A30 on the first worksheet in a workbook,
|
37
37
|
# you can use the name ProjectedSales on any other sheet in the same workbook to refer to range A20:A30 on the first worksheet.
|
38
38
|
# Names can also be used to represent formulas or values that do not change (constants).
|
39
39
|
#
|
@@ -71,7 +71,7 @@ module Axlsx
|
|
71
71
|
# applied. This represents the source data range, unfiltered.
|
72
72
|
# b. This defined name refers to a range to which an AutoFilter has been
|
73
73
|
# applied.
|
74
|
-
# _xlnm.Extract: this defined name refers to the range containing the filtered output
|
74
|
+
# _xlnm.Extract: this defined name refers to the range containing the filtered output
|
75
75
|
# values resulting from applying an advanced filter criteria to a source range.
|
76
76
|
# Miscellaneous
|
77
77
|
# _xlnm.Consolidate_Area: the defined name refers to a consolidation area.
|
@@ -88,14 +88,14 @@ module Axlsx
|
|
88
88
|
# This attribute is used when there is an add-in or other code project associated with the file.
|
89
89
|
# @option [Boolean] vb_proceedure - Specifies a boolean value that indicates whether the defined name is related to an external function, command, or other executable code.
|
90
90
|
# @option [Boolean] xlm - Specifies a boolean value that indicates whether the defined name is related to an external function, command, or other executable code.
|
91
|
-
# @option [Integer] function_group_id - Specifies the function group index if the defined name refers to a function.
|
91
|
+
# @option [Integer] function_group_id - Specifies the function group index if the defined name refers to a function.
|
92
92
|
# The function group defines the general category for the function.
|
93
93
|
# This attribute is used when there is an add-in or other code project associated with the file.
|
94
94
|
# See Open Office XML Part 1 for more info.
|
95
95
|
# @option [String] short_cut_key - Specifies the keyboard shortcut for the defined name.
|
96
|
-
# @option [Boolean] publish_to_server - Specifies a boolean value that indicates whether the defined name is included in the
|
96
|
+
# @option [Boolean] publish_to_server - Specifies a boolean value that indicates whether the defined name is included in the
|
97
97
|
# version of the workbook that is published to or rendered on a Web or application server.
|
98
|
-
# @option [Boolean] workbook_parameter - Specifies a boolean value that indicates that the name is used as a workbook parameter on a
|
98
|
+
# @option [Boolean] workbook_parameter - Specifies a boolean value that indicates that the name is used as a workbook parameter on a
|
99
99
|
# version of the workbook that is published to or rendered on a Web or application server.
|
100
100
|
def initialize(formula, options={})
|
101
101
|
@formula = formula
|
@@ -116,14 +116,13 @@ module Axlsx
|
|
116
116
|
boolean_attr_accessor :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden
|
117
117
|
|
118
118
|
serializable_attributes :short_cut_key, :status_bar, :help, :description, :custom_menu, :comment,
|
119
|
-
:workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden, :
|
119
|
+
:workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden, :local_sheet_id
|
120
120
|
|
121
121
|
def to_xml_string(str='')
|
122
|
-
raise ArgumentError, 'you must specify the name for this defined name. Please read the documentation for Axlsx::DefinedName for more details' unless name
|
123
|
-
str << '<definedName '
|
122
|
+
raise ArgumentError, 'you must specify the name for this defined name. Please read the documentation for Axlsx::DefinedName for more details' unless name
|
123
|
+
str << ('<definedName ' << 'name="' << name << '" ')
|
124
124
|
serialized_attributes str
|
125
|
-
str << '>' << @formula
|
126
|
-
str << '</definedName>'
|
125
|
+
str << ('>' << @formula << '</definedName>')
|
127
126
|
end
|
128
127
|
end
|
129
128
|
end
|
@@ -11,8 +11,8 @@ module Axlsx
|
|
11
11
|
# @param [String] str
|
12
12
|
# @return [String]
|
13
13
|
def to_xml_string(str = '')
|
14
|
-
return if
|
15
|
-
str <<
|
14
|
+
return if empty?
|
15
|
+
str << '<definedNames>'
|
16
16
|
each { |defined_name| defined_name.to_xml_string(str) }
|
17
17
|
str << '</definedNames>'
|
18
18
|
end
|
@@ -38,7 +38,7 @@ module Axlsx
|
|
38
38
|
@xml_space = xml_space
|
39
39
|
@unique_cells = {}
|
40
40
|
@shared_xml_string = ""
|
41
|
-
shareable_cells = cells.flatten.select{ |cell| cell.plain_string? }
|
41
|
+
shareable_cells = cells.flatten.select{ |cell| cell.plain_string? || cell.contains_rich_text? }
|
42
42
|
@count = shareable_cells.size
|
43
43
|
resolve(shareable_cells)
|
44
44
|
end
|
@@ -47,10 +47,10 @@ module Axlsx
|
|
47
47
|
# @param [String] str
|
48
48
|
# @return [String]
|
49
49
|
def to_xml_string(str='')
|
50
|
-
|
51
|
-
str << '
|
52
|
-
str << '
|
53
|
-
str =
|
50
|
+
Axlsx::sanitize(@shared_xml_string)
|
51
|
+
str << ('<?xml version="1.0" encoding="UTF-8"?><sst xmlns="' << XML_NS << '"')
|
52
|
+
str << (' count="' << @count.to_s << '" uniqueCount="' << unique_count.to_s << '"')
|
53
|
+
str << (' xml:space="' << xml_space.to_s << '">' << @shared_xml_string << '</sst>')
|
54
54
|
end
|
55
55
|
|
56
56
|
private
|
@@ -5,10 +5,13 @@ require 'axlsx/workbook/worksheet/auto_filter/auto_filter.rb'
|
|
5
5
|
require 'axlsx/workbook/worksheet/date_time_converter.rb'
|
6
6
|
require 'axlsx/workbook/worksheet/protected_range.rb'
|
7
7
|
require 'axlsx/workbook/worksheet/protected_ranges.rb'
|
8
|
+
require 'axlsx/workbook/worksheet/rich_text_run'
|
9
|
+
require 'axlsx/workbook/worksheet/rich_text'
|
8
10
|
require 'axlsx/workbook/worksheet/cell_serializer.rb'
|
9
11
|
require 'axlsx/workbook/worksheet/cell.rb'
|
10
12
|
require 'axlsx/workbook/worksheet/page_margins.rb'
|
11
13
|
require 'axlsx/workbook/worksheet/page_set_up_pr.rb'
|
14
|
+
require 'axlsx/workbook/worksheet/outline_pr.rb'
|
12
15
|
require 'axlsx/workbook/worksheet/page_setup.rb'
|
13
16
|
require 'axlsx/workbook/worksheet/header_footer.rb'
|
14
17
|
require 'axlsx/workbook/worksheet/print_options.rb'
|
@@ -37,7 +40,8 @@ require 'axlsx/workbook/worksheet/worksheet_hyperlinks'
|
|
37
40
|
require 'axlsx/workbook/worksheet/break'
|
38
41
|
require 'axlsx/workbook/worksheet/row_breaks'
|
39
42
|
require 'axlsx/workbook/worksheet/col_breaks'
|
40
|
-
|
43
|
+
require 'axlsx/workbook/workbook_view'
|
44
|
+
require 'axlsx/workbook/workbook_views'
|
41
45
|
|
42
46
|
|
43
47
|
require 'axlsx/workbook/worksheet/worksheet.rb'
|
@@ -93,6 +97,15 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
93
97
|
@use_shared_strings = v
|
94
98
|
end
|
95
99
|
|
100
|
+
# If true reverse the order in which the workbook is serialized
|
101
|
+
# @return [Boolean]
|
102
|
+
attr_reader :is_reversed
|
103
|
+
|
104
|
+
def is_reversed=(v)
|
105
|
+
Axlsx::validate_boolean(v)
|
106
|
+
@is_reversed = v
|
107
|
+
end
|
108
|
+
|
96
109
|
|
97
110
|
# A collection of worksheets associated with this workbook.
|
98
111
|
# @note The recommended way to manage worksheets is add_worksheet
|
@@ -139,6 +152,10 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
139
152
|
# @return [SimpleTypedList]
|
140
153
|
attr_reader :pivot_tables
|
141
154
|
|
155
|
+
# A collection of views for this workbook
|
156
|
+
def views
|
157
|
+
@views ||= WorkbookViews.new
|
158
|
+
end
|
142
159
|
|
143
160
|
# A collection of defined names for this workbook
|
144
161
|
# @note The recommended way to manage defined names is Workbook#add_defined_name
|
@@ -180,15 +197,6 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
180
197
|
@worksheets[index] if index
|
181
198
|
end
|
182
199
|
|
183
|
-
# lets come back to this later when we are ready for parsing.
|
184
|
-
#def self.parse entry
|
185
|
-
# io = entry.get_input_stream
|
186
|
-
# w = self.new
|
187
|
-
# w.parser_xml = Nokogiri::XML(io.read)
|
188
|
-
# w.parse_string :date1904, "//xmlns:workbookPr/@date1904"
|
189
|
-
# w
|
190
|
-
#end
|
191
|
-
|
192
200
|
# Creates a new Workbook
|
193
201
|
# The recomended way to work with workbooks is via Package#workbook
|
194
202
|
# @option options [Boolean] date1904. If this is not specified, date1904 is set to false. Office 2011 for Mac defaults to false.
|
@@ -263,6 +271,14 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
263
271
|
worksheet
|
264
272
|
end
|
265
273
|
|
274
|
+
# Adds a new WorkbookView
|
275
|
+
# @return WorkbookViews
|
276
|
+
# @option options [Hash] options passed into the added WorkbookView
|
277
|
+
# @see WorkbookView#initialize
|
278
|
+
def add_view(options={})
|
279
|
+
views << WorkbookView.new(options)
|
280
|
+
end
|
281
|
+
|
266
282
|
# Adds a defined name to this workbook
|
267
283
|
# @return [DefinedName]
|
268
284
|
# @param [String] formula @see DefinedName
|
@@ -283,7 +299,7 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
283
299
|
end
|
284
300
|
r << Relationship.new(self, STYLES_R, STYLES_PN)
|
285
301
|
if use_shared_strings
|
286
|
-
r << Relationship.new(self, SHARED_STRINGS_R,
|
302
|
+
r << Relationship.new(self, SHARED_STRINGS_R, SHARED_STRINGS_PN)
|
287
303
|
end
|
288
304
|
r
|
289
305
|
end
|
@@ -327,23 +343,23 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
327
343
|
# @param [String] str
|
328
344
|
# @return [String]
|
329
345
|
def to_xml_string(str='')
|
330
|
-
add_worksheet unless worksheets.size > 0
|
346
|
+
add_worksheet(name: 'Sheet1') unless worksheets.size > 0
|
331
347
|
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
332
|
-
str << '<workbook xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '">'
|
333
|
-
str << '<workbookPr date1904="' << @@date1904.to_s << '"/>'
|
348
|
+
str << ('<workbook xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '">')
|
349
|
+
str << ('<workbookPr date1904="' << @@date1904.to_s << '"/>')
|
350
|
+
views.to_xml_string(str)
|
334
351
|
str << '<sheets>'
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
end
|
352
|
+
if is_reversed
|
353
|
+
worksheets.reverse_each { |sheet| sheet.to_sheet_node_xml_string(str) }
|
354
|
+
else
|
355
|
+
worksheets.each { |sheet| sheet.to_sheet_node_xml_string(str) }
|
340
356
|
end
|
341
357
|
str << '</sheets>'
|
342
358
|
defined_names.to_xml_string(str)
|
343
359
|
unless pivot_tables.empty?
|
344
360
|
str << '<pivotCaches>'
|
345
361
|
pivot_tables.each do |pivot_table|
|
346
|
-
str << '<pivotCache cacheId="' << pivot_table.cache_definition.cache_id.to_s << '" r:id="' << pivot_table.cache_definition.rId << '"/>'
|
362
|
+
str << ('<pivotCache cacheId="' << pivot_table.cache_definition.cache_id.to_s << '" r:id="' << pivot_table.cache_definition.rId << '"/>')
|
347
363
|
end
|
348
364
|
str << '</pivotCaches>'
|
349
365
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# <xsd:complexType name="CT_BookView">
|
2
|
+
# <xsd:sequence>
|
3
|
+
# <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
|
4
|
+
# </xsd:sequence>
|
5
|
+
# <xsd:attribute name="visibility" type="ST_Visibility" use="optional" default="visible"/>
|
6
|
+
# <xsd:attribute name="minimized" type="xsd:boolean" use="optional" default="false"/>
|
7
|
+
# <xsd:attribute name="showHorizontalScroll" type="xsd:boolean" use="optional" default="true"/>
|
8
|
+
# <xsd:attribute name="showVerticalScroll" type="xsd:boolean" use="optional" default="true"/>
|
9
|
+
# <xsd:attribute name="showSheetTabs" type="xsd:boolean" use="optional" default="true"/>
|
10
|
+
# <xsd:attribute name="xWindow" type="xsd:int" use="optional"/>
|
11
|
+
# <xsd:attribute name="yWindow" type="xsd:int" use="optional"/>
|
12
|
+
# <xsd:attribute name="windowWidth" type="xsd:unsignedInt" use="optional"/>
|
13
|
+
# <xsd:attribute name="windowHeight" type="xsd:unsignedInt" use="optional"/>
|
14
|
+
# <xsd:attribute name="tabRatio" type="xsd:unsignedInt" use="optional" default="600"/>
|
15
|
+
# <xsd:attribute name="firstSheet" type="xsd:unsignedInt" use="optional" default="0"/>
|
16
|
+
# <xsd:attribute name="activeTab" type="xsd:unsignedInt" use="optional" default="0"/>
|
17
|
+
# <xsd:attribute name="autoFilterDateGrouping" type="xsd:boolean" use="optional"
|
18
|
+
# default="true"/>
|
19
|
+
# </xsd:complexType>
|
20
|
+
|
21
|
+
module Axlsx
|
22
|
+
|
23
|
+
# A BookView defines the display properties for a workbook.
|
24
|
+
# Units for window widths and other dimensions are expressed in twips.
|
25
|
+
# Twip measurements are portable between different display resolutions.
|
26
|
+
# The formula is (screen pixels) * (20 * 72) / (logical device dpi),
|
27
|
+
# where the logical device dpi can be different for x and y coordinates.
|
28
|
+
class WorkbookView
|
29
|
+
|
30
|
+
include Axlsx::SerializedAttributes
|
31
|
+
include Axlsx::OptionsParser
|
32
|
+
include Axlsx::Accessors
|
33
|
+
|
34
|
+
|
35
|
+
# Creates a new BookView object
|
36
|
+
# @param [Hash] options A hash of key/value pairs that will be mapped to this instances attributes.
|
37
|
+
# @option [Symbol] visibility Specifies visible state of the workbook window. The default value for this attribute is :visible.
|
38
|
+
# @option [Boolean] minimized Specifies a boolean value that indicates whether the workbook window is minimized.
|
39
|
+
# @option [Boolean] show_horizontal_scroll Specifies a boolean value that indicates whether to display the horizontal scroll bar in the user interface.
|
40
|
+
# @option [Boolean] show_vertical_scroll Specifies a boolean value that indicates whether to display the vertical scroll bar.
|
41
|
+
# @option [Boolean] show_sheet_tabs Specifies a boolean value that indicates whether to display the sheet tabs in the user interface.
|
42
|
+
# @option [Integer] tab_ratio Specifies ratio between the workbook tabs bar and the horizontal scroll bar.
|
43
|
+
# @option [Integer] first_sheet Specifies the index to the first sheet in this book view.
|
44
|
+
# @option [Integer] active_tab Specifies an unsignedInt that contains the index to the active sheet in this book view.
|
45
|
+
# @option [Integer] x_window Specifies the X coordinate for the upper left corner of the workbook window. The unit of measurement for this value is twips.
|
46
|
+
# @option [Integer] y_window Specifies the Y coordinate for the upper left corner of the workbook window. The unit of measurement for this value is twips.
|
47
|
+
# @option [Integer] window_width Specifies the width of the workbook window. The unit of measurement for this value is twips.
|
48
|
+
# @option [Integer] window_height Specifies the height of the workbook window. The unit of measurement for this value is twips.
|
49
|
+
# @option [Boolean] auto_filter_date_grouping Specifies a boolean value that indicates whether to group dates when presenting the user with filtering options in the user interface.
|
50
|
+
def initialize(options={})
|
51
|
+
parse_options options
|
52
|
+
yield self if block_given?
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
unsigned_int_attr_accessor :x_window, :y_window, :window_width, :window_height,
|
57
|
+
:tab_ratio, :first_sheet, :active_tab
|
58
|
+
|
59
|
+
validated_attr_accessor [:visibility], :validate_view_visibility
|
60
|
+
|
61
|
+
serializable_attributes :visibility, :minimized,
|
62
|
+
:show_horizontal_scroll, :show_vertical_scroll,
|
63
|
+
:show_sheet_tabs, :tab_ratio, :first_sheet, :active_tab,
|
64
|
+
:x_window, :y_window, :window_width, :window_height,
|
65
|
+
:auto_filter_date_grouping
|
66
|
+
|
67
|
+
boolean_attr_accessor :minimized, :show_horizontal_scroll, :show_vertical_scroll,
|
68
|
+
:show_sheet_tabs, :auto_filter_date_grouping
|
69
|
+
|
70
|
+
|
71
|
+
# Serialize the WorkbookView
|
72
|
+
# @param [String] str
|
73
|
+
# @return [String]
|
74
|
+
def to_xml_string(str = '')
|
75
|
+
str << '<workbookView '
|
76
|
+
serialized_attributes str
|
77
|
+
str << '></workbookView>'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Axlsx
|
2
|
+
# a simple types list of BookView objects
|
3
|
+
class WorkbookViews < SimpleTypedList
|
4
|
+
|
5
|
+
# creates the book views object
|
6
|
+
def initialize
|
7
|
+
super WorkbookView
|
8
|
+
end
|
9
|
+
|
10
|
+
# Serialize to xml
|
11
|
+
# @param [String] str
|
12
|
+
# @return [String]
|
13
|
+
def to_xml_string(str = '')
|
14
|
+
return if empty?
|
15
|
+
str << "<bookViews>"
|
16
|
+
each { |view| view.to_xml_string(str) }
|
17
|
+
str << '</bookViews>'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
@@ -47,8 +47,8 @@ module Axlsx
|
|
47
47
|
columns.last
|
48
48
|
end
|
49
49
|
|
50
|
-
# actually performs the filtering of rows who's cells do not
|
51
|
-
# match the filter.
|
50
|
+
# actually performs the filtering of rows who's cells do not
|
51
|
+
# match the filter.
|
52
52
|
def apply
|
53
53
|
first_cell, last_cell = range.split(':')
|
54
54
|
start_point = Axlsx::name_to_indices(first_cell)
|
@@ -237,9 +237,7 @@ include Axlsx::SerializedAttributes
|
|
237
237
|
# Serialize the object to xml
|
238
238
|
# @param [String] str The string object this serialization will be concatenated to.
|
239
239
|
def to_xml_string(str = '')
|
240
|
-
|
241
|
-
serialized_attributes str
|
242
|
-
str << '/>'
|
240
|
+
serialized_tag('dateGroupItem', str)
|
243
241
|
end
|
244
242
|
end
|
245
243
|
end
|
@@ -12,7 +12,7 @@ module Axlsx
|
|
12
12
|
|
13
13
|
# @param [Row] row The row this cell belongs to.
|
14
14
|
# @param [Any] value The value associated with this cell.
|
15
|
-
# @option options [Symbol] type The intended data type for this cell. If not specified the data type will be determined internally based on the
|
15
|
+
# @option options [Symbol] type The intended data type for this cell. If not specified the data type will be determined internally based on the value provided.
|
16
16
|
# @option options [Integer] style The index of the cellXfs item to be applied to this cell. If not specified, the default style (0) will be applied.
|
17
17
|
# @option options [String] font_name
|
18
18
|
# @option options [Integer] charset
|
@@ -30,17 +30,30 @@ module Axlsx
|
|
30
30
|
# @option options [String] color an 8 letter rgb specification
|
31
31
|
# @option options [Number] formula_value The value to cache for a formula cell.
|
32
32
|
# @option options [Symbol] scheme must be one of :none, major, :minor
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@
|
39
|
-
|
40
|
-
parse_options options
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
# @option options [Boolean] escape_formulas - Whether to treat a value starting with an equal
|
34
|
+
# sign as formula (default) or as simple string.
|
35
|
+
# Allowing user generated data to be interpreted as formulas can be dangerous
|
36
|
+
# (see https://www.owasp.org/index.php/CSV_Injection for details).
|
37
|
+
def initialize(row, value = nil, options = {})
|
38
|
+
@row = row
|
39
|
+
# Do not use instance vars if not needed to use less RAM
|
40
|
+
# And do not call parse_options on frequently used options
|
41
|
+
# to get less GC cycles
|
42
|
+
type = options.delete(:type) || cell_type_from_value(value)
|
43
|
+
self.type = type unless type == :string
|
44
|
+
|
45
|
+
escape_formulas = options[:escape_formulas]
|
46
|
+
self.escape_formulas = escape_formulas unless escape_formulas.nil?
|
47
|
+
|
48
|
+
val = options.delete(:style)
|
49
|
+
self.style = val unless val.nil? || val == 0
|
50
|
+
val = options.delete(:formula_value)
|
51
|
+
self.formula_value = val unless val.nil?
|
52
|
+
|
53
|
+
parse_options(options)
|
54
|
+
|
55
|
+
self.value = value
|
56
|
+
value.cell = self if contains_rich_text?
|
44
57
|
end
|
45
58
|
|
46
59
|
# this is the cached value for formula cells. If you want the values to render in iOS/Mac OSX preview
|
@@ -53,21 +66,27 @@ module Axlsx
|
|
53
66
|
# needs to define bla=(v) and bla methods on the class that hook into a
|
54
67
|
# set_attr method that kicks the suplied validator and updates the instance_variable
|
55
68
|
# for the key
|
56
|
-
INLINE_STYLES = [
|
57
|
-
|
58
|
-
|
59
|
-
|
69
|
+
INLINE_STYLES = [:value, :type, :font_name, :charset,
|
70
|
+
:family, :b, :i, :strike, :outline,
|
71
|
+
:shadow, :condense, :extend, :u,
|
72
|
+
:vertAlign, :sz, :color, :scheme].freeze
|
73
|
+
|
74
|
+
# An array of valid cell types
|
75
|
+
CELL_TYPES = [:date, :time, :float, :integer, :richtext,
|
76
|
+
:string, :boolean, :iso_8601, :text].freeze
|
60
77
|
|
61
78
|
# The index of the cellXfs item to be applied to this cell.
|
62
79
|
# @return [Integer]
|
63
80
|
# @see Axlsx::Styles
|
64
|
-
|
81
|
+
def style
|
82
|
+
defined?(@style) ? @style : 0
|
83
|
+
end
|
65
84
|
|
66
85
|
# The row this cell belongs to.
|
67
86
|
# @return [Row]
|
68
87
|
attr_reader :row
|
69
88
|
|
70
|
-
# The cell's data type.
|
89
|
+
# The cell's data type.
|
71
90
|
# Changing the type for a cell will recast the value into that type. If no type option is specified in the constructor, the type is
|
72
91
|
# automatically determed.
|
73
92
|
# @see Cell#cell_type_from_value
|
@@ -78,18 +97,33 @@ module Axlsx
|
|
78
97
|
# :string to :integer or :float, type conversions always return 0 or 0.0
|
79
98
|
# :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
|
80
99
|
# No support is currently implemented for parsing time strings.
|
81
|
-
|
100
|
+
def type
|
101
|
+
defined?(@type) ? @type : :string
|
102
|
+
end
|
103
|
+
|
82
104
|
# @see type
|
83
105
|
def type=(v)
|
84
|
-
RestrictionValidator.validate
|
85
|
-
@type=v
|
86
|
-
self.value = @value unless @value.nil?
|
106
|
+
RestrictionValidator.validate :cell_type, CELL_TYPES, v
|
107
|
+
@type = v
|
108
|
+
self.value = @value unless !defined?(@value) || @value.nil?
|
87
109
|
end
|
88
110
|
|
111
|
+
# Whether to treat a value starting with an equal
|
112
|
+
# sign as formula (default) or as simple string.
|
113
|
+
# Allowing user generated data to be interpreted as formulas can be dangerous
|
114
|
+
# (see https://www.owasp.org/index.php/CSV_Injection for details).
|
115
|
+
# @return [Boolean]
|
116
|
+
attr_reader :escape_formulas
|
117
|
+
|
118
|
+
def escape_formulas=(v)
|
119
|
+
Axlsx.validate_boolean(v)
|
120
|
+
@escape_formulas = v
|
121
|
+
end
|
89
122
|
|
90
123
|
# The value of this cell.
|
91
124
|
# @return [String, Integer, Float, Time, Boolean] casted value based on cell's type attribute.
|
92
125
|
attr_reader :value
|
126
|
+
|
93
127
|
# @see value
|
94
128
|
def value=(v)
|
95
129
|
#TODO: consider doing value based type determination first?
|
@@ -99,16 +133,20 @@ module Axlsx
|
|
99
133
|
# Indicates that the cell has one or more of the custom cell styles applied.
|
100
134
|
# @return [Boolean]
|
101
135
|
def is_text_run?
|
102
|
-
@is_text_run
|
136
|
+
defined?(@is_text_run) && @is_text_run && !contains_rich_text?
|
137
|
+
end
|
138
|
+
|
139
|
+
def contains_rich_text?
|
140
|
+
type == :richtext
|
103
141
|
end
|
104
142
|
|
105
143
|
# Indicates if the cell is good for shared string table
|
106
144
|
def plain_string?
|
107
|
-
|
145
|
+
(type == :string || type == :text) && # String typed
|
108
146
|
!is_text_run? && # No inline styles
|
109
147
|
!@value.nil? && # Not nil
|
110
148
|
!@value.empty? && # Not empty
|
111
|
-
!@value.start_with?(
|
149
|
+
!@value.start_with?(?=) # Not a formula
|
112
150
|
end
|
113
151
|
|
114
152
|
# The inline font_name property for the cell
|
@@ -231,7 +269,7 @@ module Axlsx
|
|
231
269
|
attr_reader :vertAlign
|
232
270
|
# @see vertAlign
|
233
271
|
def vertAlign=(v)
|
234
|
-
RestrictionValidator.validate
|
272
|
+
RestrictionValidator.validate :cell_vertAlign, [:baseline, :subscript, :superscript], v
|
235
273
|
set_run_style nil, :vertAlign, v
|
236
274
|
end
|
237
275
|
|
@@ -241,7 +279,7 @@ module Axlsx
|
|
241
279
|
attr_reader :scheme
|
242
280
|
# @see scheme
|
243
281
|
def scheme=(v)
|
244
|
-
RestrictionValidator.validate
|
282
|
+
RestrictionValidator.validate :cell_scheme, [:none, :major, :minor], v
|
245
283
|
set_run_style nil, :scheme, v
|
246
284
|
end
|
247
285
|
|
@@ -251,14 +289,14 @@ module Axlsx
|
|
251
289
|
|
252
290
|
# @return [Integer] The index of the cell in the containing row.
|
253
291
|
def index
|
254
|
-
@row.
|
292
|
+
@row.index(self)
|
255
293
|
end
|
256
294
|
|
257
295
|
# @return [String] The alpha(column)numeric(row) reference for this sell.
|
258
296
|
# @example Relative Cell Reference
|
259
297
|
# ws.rows.first.cells.first.r #=> "A1"
|
260
298
|
def r
|
261
|
-
Axlsx::cell_r index, @row.
|
299
|
+
Axlsx::cell_r index, @row.row_index
|
262
300
|
end
|
263
301
|
|
264
302
|
# @return [String] The absolute alpha(column)numeric(row) reference for this sell.
|
@@ -272,26 +310,26 @@ module Axlsx
|
|
272
310
|
# @raise [ArgumentError] Invalid cellXfs id if the value provided is not within cellXfs items range.
|
273
311
|
def style=(v)
|
274
312
|
Axlsx::validate_unsigned_int(v)
|
275
|
-
count =
|
313
|
+
count = styles.cellXfs.size
|
276
314
|
raise ArgumentError, "Invalid cellXfs id" unless v < count
|
277
315
|
@style = v
|
278
316
|
end
|
279
317
|
|
280
|
-
# @return [Array] of x/y coordinates in the
|
318
|
+
# @return [Array] of x/y coordinates in the sheet for this cell.
|
281
319
|
def pos
|
282
|
-
[index, row.
|
320
|
+
[index, row.row_index]
|
283
321
|
end
|
284
322
|
|
285
323
|
# Merges all the cells in a range created between this cell and the cell or string name for a cell provided
|
286
324
|
# @see worksheet.merge_cells
|
287
325
|
# @param [Cell, String] target The last cell, or str ref for the cell in the merge range
|
288
326
|
def merge(target)
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
self.row.worksheet.merge_cells "#{
|
327
|
+
start, stop = if target.is_a?(String)
|
328
|
+
[self.r, target]
|
329
|
+
elsif(target.is_a?(Cell))
|
330
|
+
Axlsx.sort_cells([self, target]).map { |c| c.r }
|
331
|
+
end
|
332
|
+
self.row.worksheet.merge_cells "#{start}:#{stop}" unless stop.nil?
|
295
333
|
end
|
296
334
|
|
297
335
|
# Serializes the cell
|
@@ -304,17 +342,13 @@ module Axlsx
|
|
304
342
|
end
|
305
343
|
|
306
344
|
def is_formula?
|
307
|
-
|
345
|
+
return false if escape_formulas
|
346
|
+
|
347
|
+
type == :string && @value.to_s.start_with?(?=)
|
308
348
|
end
|
309
349
|
|
310
|
-
|
311
|
-
|
312
|
-
# - different fonts have different mdw and char widths
|
313
|
-
def autowidth
|
314
|
-
return if is_formula? || value == nil
|
315
|
-
mdw = 1.78 #This is the widest width of 0..9 in arial@10px)
|
316
|
-
font_scale = (font_size/10.0).to_f
|
317
|
-
((value.to_s.count(Worksheet.thin_chars) * mdw + 5) / mdw * 256) / 256.0 * font_scale
|
350
|
+
def is_array_formula?
|
351
|
+
type == :string && @value.to_s.start_with?('{=') && @value.to_s.end_with?('}')
|
318
352
|
end
|
319
353
|
|
320
354
|
# returns the absolute or relative string style reference for
|
@@ -326,21 +360,72 @@ module Axlsx
|
|
326
360
|
absolute ? r_abs : r
|
327
361
|
end
|
328
362
|
|
363
|
+
# Creates a defined name in the workbook for this cell.
|
364
|
+
def name=(label)
|
365
|
+
row.worksheet.workbook.add_defined_name "#{row.worksheet.name}!#{r_abs}", name: label
|
366
|
+
@name = label
|
367
|
+
end
|
368
|
+
|
369
|
+
# returns the name of the cell
|
370
|
+
attr_reader :name
|
371
|
+
|
372
|
+
# Attempts to determine the correct width for this cell's content
|
373
|
+
# @return [Float]
|
374
|
+
def autowidth
|
375
|
+
return if is_formula? || value.nil?
|
376
|
+
|
377
|
+
if contains_rich_text?
|
378
|
+
string_width('', font_size) + value.autowidth
|
379
|
+
elsif styles.cellXfs[style].alignment && styles.cellXfs[style].alignment.wrap_text
|
380
|
+
max_width = 0
|
381
|
+
value.to_s.split(/\r?\n/).each do |line|
|
382
|
+
width = string_width(line, font_size)
|
383
|
+
max_width = width if width > max_width
|
384
|
+
end
|
385
|
+
max_width
|
386
|
+
else
|
387
|
+
string_width(value, font_size)
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
# Returns the sanatized value
|
392
|
+
# TODO find a better way to do this as it accounts for 30% of
|
393
|
+
# processing time in benchmarking...
|
394
|
+
def clean_value
|
395
|
+
if (type == :string || type == :text) && !Axlsx::trust_input
|
396
|
+
Axlsx::sanitize(::CGI.escapeHTML(@value.to_s))
|
397
|
+
else
|
398
|
+
@value.to_s
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
329
402
|
private
|
330
403
|
|
404
|
+
def styles
|
405
|
+
row.worksheet.styles
|
406
|
+
end
|
407
|
+
|
408
|
+
# Returns the width of a string according to the current style
|
409
|
+
# This is still not perfect...
|
410
|
+
# - scaling is not linear as font sizes increase
|
411
|
+
def string_width(string, font_size)
|
412
|
+
font_scale = font_size / 10.0
|
413
|
+
(string.to_s.size + 3) * font_scale
|
414
|
+
end
|
415
|
+
|
331
416
|
# we scale the font size if bold style is applied to either the style font or
|
332
417
|
# the cell itself. Yes, it is a bit of a hack, but it is much better than using
|
333
418
|
# imagemagick and loading metrics for every character.
|
334
419
|
def font_size
|
335
|
-
|
336
|
-
|
337
|
-
|
420
|
+
return sz if sz
|
421
|
+
font = styles.fonts[styles.cellXfs[style].fontId] || styles.fonts[0]
|
422
|
+
(font.b || (defined?(@b) && @b)) ? (font.sz * 1.5) : font.sz
|
338
423
|
end
|
339
424
|
|
340
425
|
# Utility method for setting inline style attributes
|
341
|
-
def set_run_style(
|
342
|
-
return unless INLINE_STYLES.include?(attr.
|
343
|
-
Axlsx.send(validator, value) unless validator
|
426
|
+
def set_run_style(validator, attr, value)
|
427
|
+
return unless INLINE_STYLES.include?(attr.to_sym)
|
428
|
+
Axlsx.send(validator, value) unless validator.nil?
|
344
429
|
self.instance_variable_set :"@#{attr.to_s}", value
|
345
430
|
@is_text_run = true
|
346
431
|
end
|
@@ -351,9 +436,6 @@ module Axlsx
|
|
351
436
|
@ssti = v
|
352
437
|
end
|
353
438
|
|
354
|
-
# assigns the owning row for this cell.
|
355
|
-
def row=(v) @row=v end
|
356
|
-
|
357
439
|
# Determines the cell type based on the cell value.
|
358
440
|
# @note This is only used when a cell is created but no :type option is specified, the following rules apply:
|
359
441
|
# 1. If the value is an instance of Date, the type is set to :date
|
@@ -369,15 +451,16 @@ module Axlsx
|
|
369
451
|
:time
|
370
452
|
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
371
453
|
:boolean
|
372
|
-
elsif v.to_s =~
|
454
|
+
elsif v.to_s =~ Axlsx::NUMERIC_REGEX && v.respond_to?(:to_i)
|
373
455
|
:integer
|
374
|
-
elsif v.to_s =~
|
456
|
+
elsif v.to_s =~ Axlsx::SAFE_FLOAT_REGEX && v.respond_to?(:to_f)
|
375
457
|
:float
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
elsif v.to_s =~/\A(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z/
|
458
|
+
elsif (matchdata = v.to_s.match(MAYBE_FLOAT_REGEX)) && (Float::MIN_10_EXP..Float::MAX_10_EXP).cover?(matchdata[:exp].to_i) && v.respond_to?(:to_f)
|
459
|
+
:float
|
460
|
+
elsif v.to_s =~ Axlsx::ISO_8601_REGEX
|
380
461
|
:iso_8601
|
462
|
+
elsif v.is_a? RichText
|
463
|
+
:richtext
|
381
464
|
else
|
382
465
|
:string
|
383
466
|
end
|
@@ -388,27 +471,33 @@ module Axlsx
|
|
388
471
|
# About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values.
|
389
472
|
# @see Axlsx#date1904
|
390
473
|
def cast_value(v)
|
391
|
-
return
|
392
|
-
|
474
|
+
return v if v.is_a?(RichText) || v.nil?
|
475
|
+
case type
|
476
|
+
when :date
|
393
477
|
self.style = STYLE_DATE if self.style == 0
|
394
|
-
v
|
395
|
-
|
478
|
+
if !v.is_a?(Date) && v.respond_to?(:to_date)
|
479
|
+
v.to_date
|
480
|
+
else
|
481
|
+
v
|
482
|
+
end
|
483
|
+
when :time
|
396
484
|
self.style = STYLE_DATE if self.style == 0
|
397
|
-
v.
|
398
|
-
|
485
|
+
if !v.is_a?(Time) && v.respond_to?(:to_time)
|
486
|
+
v.to_time
|
487
|
+
else
|
488
|
+
v
|
489
|
+
end
|
490
|
+
when :float
|
399
491
|
v.to_f
|
400
|
-
|
492
|
+
when :integer
|
401
493
|
v.to_i
|
402
|
-
|
494
|
+
when :boolean
|
403
495
|
v ? 1 : 0
|
404
|
-
|
496
|
+
when :iso_8601
|
405
497
|
#consumer is responsible for ensuring the iso_8601 format when specifying this type
|
406
498
|
v
|
407
499
|
else
|
408
|
-
|
409
|
-
# TODO find a better way to do this as it accounts for 30% of
|
410
|
-
# processing time in benchmarking...
|
411
|
-
Axlsx::trust_input ? v.to_s : ::CGI.escapeHTML(v.to_s)
|
500
|
+
v.to_s
|
412
501
|
end
|
413
502
|
end
|
414
503
|
|