caxlsx 3.4.1 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -1
- data/README.md +9 -11
- data/Rakefile +7 -5
- data/examples/generate.rb +3 -1
- data/lib/axlsx/content_type/abstract_content_type.rb +12 -4
- data/lib/axlsx/content_type/content_type.rb +8 -6
- data/lib/axlsx/content_type/default.rb +7 -2
- data/lib/axlsx/content_type/override.rb +7 -2
- data/lib/axlsx/doc_props/app.rb +95 -26
- data/lib/axlsx/doc_props/core.rb +8 -6
- data/lib/axlsx/drawing/area_chart.rb +10 -8
- data/lib/axlsx/drawing/area_series.rb +20 -12
- data/lib/axlsx/drawing/ax_data_source.rb +2 -0
- data/lib/axlsx/drawing/axes.rb +6 -4
- data/lib/axlsx/drawing/axis.rb +42 -22
- data/lib/axlsx/drawing/bar_3D_chart.rb +14 -12
- data/lib/axlsx/drawing/bar_chart.rb +13 -11
- data/lib/axlsx/drawing/bar_series.rb +20 -9
- data/lib/axlsx/drawing/bubble_chart.rb +6 -4
- data/lib/axlsx/drawing/bubble_series.rb +8 -6
- data/lib/axlsx/drawing/cat_axis.rb +29 -12
- data/lib/axlsx/drawing/chart.rb +46 -20
- data/lib/axlsx/drawing/d_lbls.rb +10 -8
- data/lib/axlsx/drawing/drawing.rb +59 -56
- data/lib/axlsx/drawing/graphic_frame.rb +6 -4
- data/lib/axlsx/drawing/hyperlink.rb +19 -8
- data/lib/axlsx/drawing/line_3D_chart.rb +7 -5
- data/lib/axlsx/drawing/line_chart.rb +10 -8
- data/lib/axlsx/drawing/line_series.rb +20 -12
- data/lib/axlsx/drawing/marker.rb +24 -7
- data/lib/axlsx/drawing/num_data.rb +9 -7
- data/lib/axlsx/drawing/num_data_source.rb +9 -7
- data/lib/axlsx/drawing/num_val.rb +7 -5
- data/lib/axlsx/drawing/one_cell_anchor.rb +13 -5
- data/lib/axlsx/drawing/pic.rb +26 -15
- data/lib/axlsx/drawing/picture_locking.rb +3 -1
- data/lib/axlsx/drawing/pie_3D_chart.rb +6 -4
- data/lib/axlsx/drawing/pie_chart.rb +36 -0
- data/lib/axlsx/drawing/pie_series.rb +23 -9
- data/lib/axlsx/drawing/scaling.rb +25 -9
- data/lib/axlsx/drawing/scatter_chart.rb +7 -5
- data/lib/axlsx/drawing/scatter_series.rb +14 -12
- data/lib/axlsx/drawing/ser_axis.rb +13 -5
- data/lib/axlsx/drawing/series.rb +13 -5
- data/lib/axlsx/drawing/series_title.rb +6 -4
- data/lib/axlsx/drawing/str_data.rb +7 -5
- data/lib/axlsx/drawing/str_val.rb +6 -4
- data/lib/axlsx/drawing/title.rb +13 -14
- data/lib/axlsx/drawing/two_cell_anchor.rb +4 -2
- data/lib/axlsx/drawing/val_axis.rb +4 -2
- data/lib/axlsx/drawing/view_3D.rb +16 -8
- data/lib/axlsx/drawing/vml_drawing.rb +18 -16
- data/lib/axlsx/drawing/vml_shape.rb +24 -22
- data/lib/axlsx/package.rb +73 -67
- data/lib/axlsx/rels/relationship.rb +21 -6
- data/lib/axlsx/rels/relationships.rb +6 -4
- data/lib/axlsx/stylesheet/border.rb +15 -4
- data/lib/axlsx/stylesheet/border_pr.rb +19 -6
- data/lib/axlsx/stylesheet/cell_alignment.rb +41 -10
- data/lib/axlsx/stylesheet/cell_protection.rb +12 -3
- data/lib/axlsx/stylesheet/cell_style.rb +33 -8
- data/lib/axlsx/stylesheet/color.rb +15 -7
- data/lib/axlsx/stylesheet/dxf.rb +34 -9
- data/lib/axlsx/stylesheet/fill.rb +7 -2
- data/lib/axlsx/stylesheet/font.rb +65 -17
- data/lib/axlsx/stylesheet/gradient_fill.rb +12 -4
- data/lib/axlsx/stylesheet/gradient_stop.rb +14 -5
- data/lib/axlsx/stylesheet/num_fmt.rb +14 -10
- data/lib/axlsx/stylesheet/pattern_fill.rb +18 -5
- data/lib/axlsx/stylesheet/styles.rb +124 -82
- data/lib/axlsx/stylesheet/table_style.rb +19 -6
- data/lib/axlsx/stylesheet/table_style_element.rb +15 -4
- data/lib/axlsx/stylesheet/table_styles.rb +14 -5
- data/lib/axlsx/stylesheet/xf.rb +73 -18
- data/lib/axlsx/util/accessors.rb +10 -6
- data/lib/axlsx/util/buffered_zip_output_stream.rb +60 -0
- data/lib/axlsx/util/constants.rb +117 -104
- data/lib/axlsx/util/mime_type_utils.rb +3 -5
- data/lib/axlsx/util/options_parser.rb +3 -1
- data/lib/axlsx/util/serialized_attributes.rb +42 -17
- data/lib/axlsx/util/simple_typed_list.rb +47 -47
- data/lib/axlsx/util/storage.rb +11 -10
- data/lib/axlsx/util/validators.rb +101 -41
- data/lib/axlsx/util/zip_command.rb +10 -10
- data/lib/axlsx/version.rb +3 -1
- data/lib/axlsx/workbook/defined_name.rb +6 -4
- data/lib/axlsx/workbook/defined_names.rb +4 -2
- data/lib/axlsx/workbook/shared_strings_table.rb +8 -6
- data/lib/axlsx/workbook/workbook.rb +94 -79
- data/lib/axlsx/workbook/workbook_view.rb +3 -1
- data/lib/axlsx/workbook/workbook_views.rb +4 -2
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +65 -8
- data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +11 -5
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +11 -7
- data/lib/axlsx/workbook/worksheet/auto_filter/sort_condition.rb +51 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/sort_state.rb +56 -0
- data/lib/axlsx/workbook/worksheet/border_creator.rb +5 -3
- data/lib/axlsx/workbook/worksheet/break.rb +3 -1
- data/lib/axlsx/workbook/worksheet/cell.rb +83 -64
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +31 -27
- data/lib/axlsx/workbook/worksheet/cfvo.rb +11 -3
- data/lib/axlsx/workbook/worksheet/cfvos.rb +3 -1
- data/lib/axlsx/workbook/worksheet/col.rb +5 -3
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +6 -4
- data/lib/axlsx/workbook/worksheet/color_scale.rb +12 -10
- data/lib/axlsx/workbook/worksheet/cols.rb +4 -2
- data/lib/axlsx/workbook/worksheet/comment.rb +8 -6
- data/lib/axlsx/workbook/worksheet/comments.rb +6 -4
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +16 -5
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +73 -16
- data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +4 -2
- data/lib/axlsx/workbook/worksheet/data_bar.rb +14 -13
- data/lib/axlsx/workbook/worksheet/data_validation.rb +69 -28
- data/lib/axlsx/workbook/worksheet/data_validations.rb +4 -2
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +7 -5
- data/lib/axlsx/workbook/worksheet/dimension.rb +4 -2
- data/lib/axlsx/workbook/worksheet/header_footer.rb +4 -2
- data/lib/axlsx/workbook/worksheet/icon_set.rb +38 -9
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +6 -6
- data/lib/axlsx/workbook/worksheet/outline_pr.rb +6 -2
- data/lib/axlsx/workbook/worksheet/page_margins.rb +39 -11
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +7 -4
- data/lib/axlsx/workbook/worksheet/page_setup.rb +34 -9
- data/lib/axlsx/workbook/worksheet/pane.rb +17 -9
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +20 -19
- data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +8 -6
- data/lib/axlsx/workbook/worksheet/pivot_tables.rb +3 -1
- data/lib/axlsx/workbook/worksheet/print_options.rb +3 -1
- data/lib/axlsx/workbook/worksheet/protected_range.rb +3 -1
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +6 -4
- data/lib/axlsx/workbook/worksheet/rich_text.rb +3 -1
- data/lib/axlsx/workbook/worksheet/rich_text_run.rb +46 -24
- data/lib/axlsx/workbook/worksheet/row.rb +11 -9
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +7 -5
- data/lib/axlsx/workbook/worksheet/selection.rb +15 -7
- data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +6 -2
- data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
- data/lib/axlsx/workbook/worksheet/sheet_format_pr.rb +6 -2
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +8 -4
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +11 -9
- data/lib/axlsx/workbook/worksheet/sheet_view.rb +38 -15
- data/lib/axlsx/workbook/worksheet/table.rb +9 -7
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +4 -2
- data/lib/axlsx/workbook/worksheet/tables.rb +4 -2
- data/lib/axlsx/workbook/worksheet/worksheet.rb +56 -39
- data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +4 -2
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +8 -2
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +7 -5
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +5 -3
- data/lib/axlsx.rb +56 -42
- data/lib/caxlsx.rb +3 -1
- metadata +39 -71
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# Sheet formatting properties
|
3
5
|
# <xsd:complexType name="CT_SheetFormatPr">
|
@@ -46,8 +48,10 @@ module Axlsx
|
|
46
48
|
# serializes this object to an xml string
|
47
49
|
# @param [String] str The string this objects serialization will be appended to
|
48
50
|
# @return [String]
|
49
|
-
def to_xml_string(str = '')
|
50
|
-
str <<
|
51
|
+
def to_xml_string(str = +'')
|
52
|
+
str << '<sheetFormatPr '
|
53
|
+
serialized_attributes(str)
|
54
|
+
str << '/>'
|
51
55
|
end
|
52
56
|
|
53
57
|
private
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# The SheetPr class manages serialization of a worksheet's sheetPr element.
|
3
5
|
class SheetPr
|
@@ -48,9 +50,11 @@ module Axlsx
|
|
48
50
|
# Serialize the object
|
49
51
|
# @param [String] str serialized output will be appended to this object if provided.
|
50
52
|
# @return [String]
|
51
|
-
def to_xml_string(str = '')
|
53
|
+
def to_xml_string(str = +'')
|
52
54
|
update_properties
|
53
|
-
str <<
|
55
|
+
str << '<sheetPr '
|
56
|
+
serialized_attributes(str)
|
57
|
+
str << '>'
|
54
58
|
tab_color.to_xml_string(str, 'tabColor') if tab_color
|
55
59
|
outline_pr.to_xml_string(str) if @outline_pr
|
56
60
|
page_setup_pr.to_xml_string(str)
|
@@ -71,14 +75,14 @@ module Axlsx
|
|
71
75
|
|
72
76
|
# @see tab_color
|
73
77
|
def tab_color=(v)
|
74
|
-
@tab_color = Color.new(:
|
78
|
+
@tab_color = Color.new(rgb: v)
|
75
79
|
end
|
76
80
|
|
77
81
|
private
|
78
82
|
|
79
83
|
def update_properties
|
80
84
|
page_setup_pr.fit_to_page = worksheet.fit_to_page?
|
81
|
-
|
85
|
+
unless worksheet.auto_filter.columns.empty?
|
82
86
|
self.filter_mode = 1
|
83
87
|
self.enable_format_conditions_calculation = 1
|
84
88
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# The SheetProtection object manages worksheet protection options per sheet.
|
3
5
|
class SheetProtection
|
@@ -65,7 +67,7 @@ module Axlsx
|
|
65
67
|
|
66
68
|
# encodes password for protection locking
|
67
69
|
def password=(v)
|
68
|
-
return if v
|
70
|
+
return if v.nil?
|
69
71
|
|
70
72
|
@password = create_password_hash(v)
|
71
73
|
end
|
@@ -73,7 +75,7 @@ module Axlsx
|
|
73
75
|
# Serialize the object
|
74
76
|
# @param [String] str
|
75
77
|
# @return [String]
|
76
|
-
def to_xml_string(str = '')
|
78
|
+
def to_xml_string(str = +'')
|
77
79
|
serialized_tag('sheetProtection', str)
|
78
80
|
end
|
79
81
|
|
@@ -85,27 +87,27 @@ module Axlsx
|
|
85
87
|
encoded_password = encode_password(password)
|
86
88
|
|
87
89
|
password_as_hex = [encoded_password].pack("v")
|
88
|
-
password_as_string = password_as_hex.
|
90
|
+
password_as_string = password_as_hex.unpack1("H*").upcase
|
89
91
|
|
90
92
|
password_as_string[2..3] + password_as_string[0..1]
|
91
93
|
end
|
92
94
|
|
93
95
|
# Encodes a given password
|
94
96
|
# Based on the algorithm provided by Daniel Rentz of OpenOffice.
|
95
|
-
#
|
97
|
+
# https://www.openoffice.org/sc/excelfileformat.pdf, Revision 1.42, page 115 (21.05.2012)
|
96
98
|
# @return [String]
|
97
99
|
def encode_password(password)
|
98
100
|
i = 0
|
99
|
-
chars = password.
|
101
|
+
chars = password.chars
|
100
102
|
count = chars.size
|
101
103
|
|
102
104
|
chars.collect! do |char|
|
103
105
|
i += 1
|
104
|
-
char = char.
|
106
|
+
char = char.unpack1('c') << i # ord << i
|
105
107
|
low_15 = char & 0x7fff
|
106
|
-
high_15 = char & 0x7fff << 15
|
107
|
-
high_15
|
108
|
-
|
108
|
+
high_15 = char & (0x7fff << 15)
|
109
|
+
high_15 >>= 15
|
110
|
+
low_15 | high_15
|
109
111
|
end
|
110
112
|
|
111
113
|
encoded_password = 0x0000
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# View options for a worksheet.
|
3
5
|
#
|
@@ -31,8 +33,8 @@ module Axlsx
|
|
31
33
|
def initialize(options = {})
|
32
34
|
# defaults
|
33
35
|
@color_id = @top_left_cell = @pane = nil
|
34
|
-
@right_to_left = @show_formulas = @
|
35
|
-
@default_grid_color = @show_grid_lines = @show_row_col_headers = @show_ruler = @show_zeros = true
|
36
|
+
@right_to_left = @show_formulas = @show_white_space = @tab_selected = @window_protection = false
|
37
|
+
@default_grid_color = @show_grid_lines = @show_row_col_headers = @show_ruler = @show_zeros = @show_outline_symbols = true
|
36
38
|
@zoom_scale = 100
|
37
39
|
@zoom_scale_normal = @zoom_scale_page_layout_view = @zoom_scale_sheet_layout_view = @workbook_view_id = 0
|
38
40
|
@selections = {}
|
@@ -48,7 +50,7 @@ module Axlsx
|
|
48
50
|
:view, :top_left_cell, :color_id, :zoom_scale
|
49
51
|
|
50
52
|
# instance values that must be serialized as their own elements - e.g. not attributes.
|
51
|
-
CHILD_ELEMENTS = [:pane, :selections]
|
53
|
+
CHILD_ELEMENTS = [:pane, :selections].freeze
|
52
54
|
|
53
55
|
# The pane object for the sheet view
|
54
56
|
# @return [Pane]
|
@@ -156,47 +158,68 @@ module Axlsx
|
|
156
158
|
# param [Hash] options
|
157
159
|
# return [Selection]
|
158
160
|
def add_selection(pane, options = {})
|
159
|
-
@selections[pane] = Selection.new(options.merge(:
|
161
|
+
@selections[pane] = Selection.new(options.merge(pane: pane))
|
160
162
|
end
|
161
163
|
|
162
164
|
# @see color_id
|
163
|
-
def color_id=(v)
|
165
|
+
def color_id=(v)
|
166
|
+
Axlsx.validate_unsigned_int(v)
|
167
|
+
@color_id = v
|
168
|
+
end
|
164
169
|
|
165
170
|
# @see top_left_cell
|
166
171
|
def top_left_cell=(v)
|
167
|
-
cell = (v.
|
168
|
-
Axlsx
|
172
|
+
cell = (v.instance_of?(Axlsx::Cell) ? v.r_abs : v)
|
173
|
+
Axlsx.validate_string(cell)
|
169
174
|
@top_left_cell = cell
|
170
175
|
end
|
171
176
|
|
172
177
|
# @see view
|
173
|
-
def view=(v)
|
178
|
+
def view=(v)
|
179
|
+
Axlsx.validate_sheet_view_type(v)
|
180
|
+
@view = v
|
181
|
+
end
|
174
182
|
|
175
183
|
# @see workbook_view_id
|
176
|
-
def workbook_view_id=(v)
|
184
|
+
def workbook_view_id=(v)
|
185
|
+
Axlsx.validate_unsigned_int(v)
|
186
|
+
@workbook_view_id = v
|
187
|
+
end
|
177
188
|
|
178
189
|
# @see zoom_scale
|
179
|
-
def zoom_scale=(v)
|
190
|
+
def zoom_scale=(v)
|
191
|
+
Axlsx.validate_scale_0_10_400(v)
|
192
|
+
@zoom_scale = v
|
193
|
+
end
|
180
194
|
|
181
195
|
# @see zoom_scale_normal
|
182
|
-
def zoom_scale_normal=(v)
|
196
|
+
def zoom_scale_normal=(v)
|
197
|
+
Axlsx.validate_scale_0_10_400(v)
|
198
|
+
@zoom_scale_normal = v
|
199
|
+
end
|
183
200
|
|
184
201
|
# @see zoom_scale_page_layout_view
|
185
|
-
def zoom_scale_page_layout_view=(v)
|
202
|
+
def zoom_scale_page_layout_view=(v)
|
203
|
+
Axlsx.validate_scale_0_10_400(v)
|
204
|
+
@zoom_scale_page_layout_view = v
|
205
|
+
end
|
186
206
|
|
187
207
|
# @see zoom_scale_sheet_layout_view
|
188
|
-
def zoom_scale_sheet_layout_view=(v)
|
208
|
+
def zoom_scale_sheet_layout_view=(v)
|
209
|
+
Axlsx.validate_scale_0_10_400(v)
|
210
|
+
@zoom_scale_sheet_layout_view = v
|
211
|
+
end
|
189
212
|
|
190
213
|
# Serializes the data validation
|
191
214
|
# @param [String] str
|
192
215
|
# @return [String]
|
193
|
-
def to_xml_string(str = '')
|
216
|
+
def to_xml_string(str = +'')
|
194
217
|
str << '<sheetViews>'
|
195
218
|
str << '<sheetView '
|
196
219
|
serialized_attributes str
|
197
220
|
str << '>'
|
198
221
|
@pane.to_xml_string(str) if @pane
|
199
|
-
@selections.
|
222
|
+
@selections.each_value do |selection|
|
200
223
|
selection.to_xml_string(str)
|
201
224
|
end
|
202
225
|
str << '</sheetView>'
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# Table
|
3
5
|
# @note Worksheet#add_table is the recommended way to create tables for your worksheets.
|
@@ -42,7 +44,7 @@ module Axlsx
|
|
42
44
|
# The part name for this table
|
43
45
|
# @return [String]
|
44
46
|
def pn
|
45
|
-
|
47
|
+
format(TABLE_PN, index + 1)
|
46
48
|
end
|
47
49
|
|
48
50
|
# The relationship id for this table.
|
@@ -71,14 +73,14 @@ module Axlsx
|
|
71
73
|
# Serializes the object
|
72
74
|
# @param [String] str
|
73
75
|
# @return [String]
|
74
|
-
def to_xml_string(str = '')
|
76
|
+
def to_xml_string(str = +'')
|
75
77
|
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
76
|
-
str <<
|
77
|
-
str <<
|
78
|
-
str <<
|
79
|
-
str <<
|
78
|
+
str << '<table xmlns="' << XML_NS << '" id="' << (index + 1).to_s << '" name="' << @name << '" displayName="' << @name.gsub(/\s/, '_') << '" '
|
79
|
+
str << 'ref="' << @ref << '" totalsRowShown="0">'
|
80
|
+
str << '<autoFilter ref="' << @ref << '"/>'
|
81
|
+
str << '<tableColumns count="' << header_cells.length.to_s << '">'
|
80
82
|
header_cells.each_with_index do |cell, index|
|
81
|
-
str <<
|
83
|
+
str << '<tableColumn id ="' << (index + 1).to_s << '" name="' << cell.clean_value << '"/>'
|
82
84
|
end
|
83
85
|
str << '</tableColumns>'
|
84
86
|
table_style_info.to_xml_string(str)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# The table style info class manages style attributes for defined tables in
|
3
5
|
# a worksheet
|
@@ -32,7 +34,7 @@ module Axlsx
|
|
32
34
|
# explicitly be disabled or all will show.
|
33
35
|
def initialize_defaults
|
34
36
|
%w(show_first_column show_last_column show_row_stripes show_column_stripes).each do |attr|
|
35
|
-
|
37
|
+
send(:"#{attr}=", 0)
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
@@ -41,7 +43,7 @@ module Axlsx
|
|
41
43
|
|
42
44
|
# seralizes this object to an xml string
|
43
45
|
# @param [String] str the string to contact this objects serialization to.
|
44
|
-
def to_xml_string(str = '')
|
46
|
+
def to_xml_string(str = +'')
|
45
47
|
serialized_tag('tableStyleInfo', str)
|
46
48
|
end
|
47
49
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# A simple, self serializing class for storing tables
|
3
5
|
class Tables < SimpleTypedList
|
@@ -5,7 +7,7 @@ module Axlsx
|
|
5
7
|
def initialize(worksheet)
|
6
8
|
raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
|
7
9
|
|
8
|
-
super
|
10
|
+
super(Table)
|
9
11
|
@worksheet = worksheet
|
10
12
|
end
|
11
13
|
|
@@ -23,7 +25,7 @@ module Axlsx
|
|
23
25
|
# renders the tables xml
|
24
26
|
# @param [String] str
|
25
27
|
# @return [String]
|
26
|
-
def to_xml_string(str =
|
28
|
+
def to_xml_string(str = +'')
|
27
29
|
return if empty?
|
28
30
|
|
29
31
|
str << "<tableParts count='#{size}'>"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "border_creator"
|
2
4
|
|
3
5
|
module Axlsx
|
@@ -33,7 +35,7 @@ module Axlsx
|
|
33
35
|
# @param [Hash] options Options passed in from the initializer
|
34
36
|
def initialize_page_options(options)
|
35
37
|
@page_margins = PageMargins.new options[:page_margins] if options[:page_margins]
|
36
|
-
@page_setup = PageSetup.new options[:page_setup]
|
38
|
+
@page_setup = PageSetup.new options[:page_setup] if options[:page_setup]
|
37
39
|
@print_options = PrintOptions.new options[:print_options] if options[:print_options]
|
38
40
|
@header_footer = HeaderFooter.new options[:header_footer] if options[:header_footer]
|
39
41
|
@row_breaks = RowBreaks.new
|
@@ -43,7 +45,7 @@ module Axlsx
|
|
43
45
|
# The name of the worksheet
|
44
46
|
# @return [String]
|
45
47
|
def name
|
46
|
-
@name ||= "Sheet
|
48
|
+
@name ||= "Sheet#{index + 1}"
|
47
49
|
end
|
48
50
|
|
49
51
|
# Whether to treat values starting with an equals sign as formulas or as literal strings.
|
@@ -63,7 +65,7 @@ module Axlsx
|
|
63
65
|
# Specifies the visible state of this sheet. Allowed states are
|
64
66
|
# :visible, :hidden or :very_hidden. The default value is :visible.
|
65
67
|
#
|
66
|
-
# Worksheets in the :hidden state can be shown using the sheet formatting properties in
|
68
|
+
# Worksheets in the :hidden state can be shown using the sheet formatting properties in Excel.
|
67
69
|
# :very_hidden sheets should be inaccessible to end users.
|
68
70
|
# @param [Symbol] sheet_state The visible state for this sheet.
|
69
71
|
def state=(sheet_state)
|
@@ -171,7 +173,7 @@ module Axlsx
|
|
171
173
|
@rows.transpose(&block)
|
172
174
|
end
|
173
175
|
|
174
|
-
# A range that
|
176
|
+
# A range that Excel will apply an auto-filter to "A1:B3"
|
175
177
|
# This will turn filtering on for the cells in the range.
|
176
178
|
# The first row is considered the header, while subsequent rows are considered to be data.
|
177
179
|
# @return String
|
@@ -185,7 +187,7 @@ module Axlsx
|
|
185
187
|
# @return Boolean
|
186
188
|
# @see #page_setup
|
187
189
|
def fit_to_page?
|
188
|
-
return false unless Axlsx.instance_values_for(self).
|
190
|
+
return false unless Axlsx.instance_values_for(self).key?('page_setup')
|
189
191
|
|
190
192
|
page_setup.fit_to_page?
|
191
193
|
end
|
@@ -325,7 +327,7 @@ module Axlsx
|
|
325
327
|
# @param [String] name
|
326
328
|
def name=(name)
|
327
329
|
validate_sheet_name name
|
328
|
-
@name = Axlsx
|
330
|
+
@name = Axlsx.coder.encode(name)
|
329
331
|
end
|
330
332
|
|
331
333
|
# The auto filter range for the worksheet
|
@@ -343,13 +345,13 @@ module Axlsx
|
|
343
345
|
# The part name of this worksheet
|
344
346
|
# @return [String]
|
345
347
|
def pn
|
346
|
-
|
348
|
+
format(WORKSHEET_PN, index + 1)
|
347
349
|
end
|
348
350
|
|
349
351
|
# The relationship part name of this worksheet
|
350
352
|
# @return [String]
|
351
353
|
def rels_pn
|
352
|
-
|
354
|
+
format(WORKSHEET_RELS_PN, index + 1)
|
353
355
|
end
|
354
356
|
|
355
357
|
# The relationship id of this worksheet.
|
@@ -427,7 +429,6 @@ module Axlsx
|
|
427
429
|
# Allowing user generated data to be interpreted as formulas can be dangerous
|
428
430
|
# (see https://www.owasp.org/index.php/CSV_Injection for details).
|
429
431
|
def add_row(values = [], options = {})
|
430
|
-
options[:escape_formulas] = escape_formulas if options[:escape_formulas].nil?
|
431
432
|
row = Row.new(self, values, options)
|
432
433
|
update_column_info row, options.delete(:widths)
|
433
434
|
yield row if block_given?
|
@@ -447,7 +448,7 @@ module Axlsx
|
|
447
448
|
# @see ConditionalFormattingRule#initialize
|
448
449
|
# @see file:examples/example_conditional_formatting.rb
|
449
450
|
def add_conditional_formatting(cells, rules)
|
450
|
-
cf = ConditionalFormatting.new(:
|
451
|
+
cf = ConditionalFormatting.new(sqref: cells)
|
451
452
|
cf.add_rules rules
|
452
453
|
conditional_formattings << cf
|
453
454
|
conditional_formattings
|
@@ -518,7 +519,7 @@ module Axlsx
|
|
518
519
|
end
|
519
520
|
|
520
521
|
# Adds a page break (row break) to the worksheet
|
521
|
-
# @param cell A Cell object or
|
522
|
+
# @param cell A Cell object or Excel style string reference indicating where the break
|
522
523
|
# should be added to the sheet.
|
523
524
|
# @example
|
524
525
|
# ws.add_page_break("A4")
|
@@ -530,9 +531,9 @@ module Axlsx
|
|
530
531
|
cell.pos
|
531
532
|
end
|
532
533
|
if column_index > 0
|
533
|
-
col_breaks.add_break(:
|
534
|
+
col_breaks.add_break(id: column_index)
|
534
535
|
end
|
535
|
-
row_breaks.add_break(:
|
536
|
+
row_breaks.add_break(id: row_index)
|
536
537
|
end
|
537
538
|
|
538
539
|
# This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go.
|
@@ -544,13 +545,26 @@ module Axlsx
|
|
544
545
|
# @param [Integer|Float|nil] widths
|
545
546
|
def column_widths(*widths)
|
546
547
|
widths.each_with_index do |value, index|
|
547
|
-
next if value
|
548
|
+
next if value.nil?
|
548
549
|
|
549
|
-
Axlsx
|
550
|
+
Axlsx.validate_unsigned_numeric(value) unless value.nil?
|
550
551
|
find_or_create_column_info(index).width = value
|
551
552
|
end
|
552
553
|
end
|
553
554
|
|
555
|
+
# This is a helper method that lets you specify a default style for multiple columns in a worksheet in one go.
|
556
|
+
# This style will be applied for all not-yet-defined cells in a column.
|
557
|
+
# Note that you must call column_styles BEFORE adding data, otherwise the styles will not be set successfully for new cells.
|
558
|
+
# @param [Integer] styles the cellXfs indexes
|
559
|
+
def column_styles(*styles)
|
560
|
+
styles.each_with_index do |style, index|
|
561
|
+
next if style.nil?
|
562
|
+
|
563
|
+
Axlsx.validate_unsigned_int(style)
|
564
|
+
find_or_create_column_info(index).style = style
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
554
568
|
# Set the style for cells in a specific column
|
555
569
|
# @param [Integer] index the index of the column
|
556
570
|
# @param [Integer] style the cellXfs index
|
@@ -580,10 +594,10 @@ module Axlsx
|
|
580
594
|
end
|
581
595
|
|
582
596
|
# Set the style for cells in a specific column
|
583
|
-
# @param [String|Array]
|
597
|
+
# @param [String|Array] cell_refs Cell references
|
584
598
|
# @param [Hash] styles
|
585
599
|
def add_style(cell_refs, *styles)
|
586
|
-
|
600
|
+
unless cell_refs.is_a?(Array)
|
587
601
|
cell_refs = [cell_refs]
|
588
602
|
end
|
589
603
|
|
@@ -601,8 +615,8 @@ module Axlsx
|
|
601
615
|
end
|
602
616
|
|
603
617
|
# Set the style for cells in a specific column
|
604
|
-
# @param [String|Array]
|
605
|
-
# @param [Hash|Array|Symbol] border options
|
618
|
+
# @param [String|Array] cell_refs Cell references
|
619
|
+
# @param [Hash|Array|Symbol] options border options
|
606
620
|
def add_border(cell_refs, options = nil)
|
607
621
|
if options.is_a?(Hash)
|
608
622
|
border_edges = options[:edges]
|
@@ -612,7 +626,7 @@ module Axlsx
|
|
612
626
|
border_edges = options
|
613
627
|
end
|
614
628
|
|
615
|
-
|
629
|
+
unless cell_refs.is_a?(Array)
|
616
630
|
cell_refs = [cell_refs]
|
617
631
|
end
|
618
632
|
|
@@ -626,18 +640,18 @@ module Axlsx
|
|
626
640
|
end
|
627
641
|
|
628
642
|
# Returns a sheet node serialization for this sheet in the workbook.
|
629
|
-
def to_sheet_node_xml_string(str = '')
|
643
|
+
def to_sheet_node_xml_string(str = +'')
|
630
644
|
add_autofilter_defined_name_to_workbook
|
631
645
|
str << '<sheet '
|
632
646
|
serialized_attributes str
|
633
|
-
str <<
|
634
|
-
str <<
|
647
|
+
str << 'name="' << name << '" '
|
648
|
+
str << 'r:id="' << rId << '"></sheet>'
|
635
649
|
end
|
636
650
|
|
637
651
|
# Serializes the worksheet object to an xml string
|
638
652
|
# This intentionally does not use nokogiri for performance reasons
|
639
653
|
# @return [String]
|
640
|
-
def to_xml_string
|
654
|
+
def to_xml_string(str = +'')
|
641
655
|
add_autofilter_defined_name_to_workbook
|
642
656
|
auto_filter.apply if auto_filter.range
|
643
657
|
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
@@ -660,7 +674,7 @@ module Axlsx
|
|
660
674
|
r
|
661
675
|
end
|
662
676
|
|
663
|
-
# Returns the cell or cells defined using
|
677
|
+
# Returns the cell or cells defined using Excel style A1:B3 references.
|
664
678
|
# @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber
|
665
679
|
# @return [Cell, Array]
|
666
680
|
def [](cell_def)
|
@@ -672,11 +686,11 @@ module Axlsx
|
|
672
686
|
parts.first
|
673
687
|
else
|
674
688
|
if parts.size > 2
|
675
|
-
raise ArgumentError, (ERR_CELL_REFERENCE_INVALID
|
689
|
+
raise ArgumentError, format(ERR_CELL_REFERENCE_INVALID, cell_def)
|
676
690
|
elsif parts.first.nil?
|
677
|
-
raise ArgumentError, (ERR_CELL_REFERENCE_MISSING_CELL
|
691
|
+
raise ArgumentError, format(ERR_CELL_REFERENCE_MISSING_CELL, cell_def.split(":").first, cell_def)
|
678
692
|
elsif parts.last.nil?
|
679
|
-
raise ArgumentError, (ERR_CELL_REFERENCE_MISSING_CELL
|
693
|
+
raise ArgumentError, format(ERR_CELL_REFERENCE_MISSING_CELL, cell_def.split(":").last, cell_def)
|
680
694
|
end
|
681
695
|
|
682
696
|
range(*parts)
|
@@ -687,12 +701,12 @@ module Axlsx
|
|
687
701
|
# @param [String] name The cell or cell range to return. "A1" will return the first cell of the first row.
|
688
702
|
# @return [Cell]
|
689
703
|
def name_to_cell(name)
|
690
|
-
col_index, row_index = *Axlsx
|
704
|
+
col_index, row_index = *Axlsx.name_to_indices(name)
|
691
705
|
|
692
706
|
r = rows[row_index]
|
693
707
|
|
694
708
|
if r
|
695
|
-
|
709
|
+
r[col_index]
|
696
710
|
end
|
697
711
|
end
|
698
712
|
|
@@ -710,7 +724,7 @@ module Axlsx
|
|
710
724
|
# @note The XLSX format does not support worksheet-specific styles. Even when using this method
|
711
725
|
# you're still working with the single global {Axlsx::Styles} object in the workbook.
|
712
726
|
def styles
|
713
|
-
@styles ||=
|
727
|
+
@styles ||= workbook.styles
|
714
728
|
end
|
715
729
|
|
716
730
|
# shortcut level to specify the outline level for a series of rows
|
@@ -752,15 +766,15 @@ module Axlsx
|
|
752
766
|
def validate_sheet_name(name)
|
753
767
|
DataTypeValidator.validate :worksheet_name, String, name
|
754
768
|
# ignore first character (BOM) after encoding to utf16 because Excel does so, too.
|
755
|
-
raise ArgumentError,
|
769
|
+
raise ArgumentError, ERR_SHEET_NAME_EMPTY if name.empty?
|
756
770
|
|
757
771
|
character_length = name.encode("utf-16")[1..-1].encode("utf-16").bytesize / 2
|
758
|
-
raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG
|
759
|
-
raise ArgumentError, (ERR_SHEET_NAME_CHARACTER_FORBIDDEN
|
772
|
+
raise ArgumentError, format(ERR_SHEET_NAME_TOO_LONG, name) if character_length > WORKSHEET_MAX_NAME_LENGTH
|
773
|
+
raise ArgumentError, format(ERR_SHEET_NAME_CHARACTER_FORBIDDEN, name) if WORKSHEET_NAME_FORBIDDEN_CHARS.any? { |char| name.include? char }
|
760
774
|
|
761
|
-
name = Axlsx
|
762
|
-
sheet_names = @workbook.worksheets.reject { |s| s == self }.map
|
763
|
-
raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME
|
775
|
+
name = Axlsx.coder.encode(name)
|
776
|
+
sheet_names = @workbook.worksheets.reject { |s| s == self }.map(&:name)
|
777
|
+
raise ArgumentError, format(ERR_DUPLICATE_SHEET_NAME, name) if sheet_names.include?(name)
|
764
778
|
end
|
765
779
|
|
766
780
|
def serializable_parts
|
@@ -832,7 +846,10 @@ module Axlsx
|
|
832
846
|
@worksheet_comments ||= WorksheetComments.new self
|
833
847
|
end
|
834
848
|
|
835
|
-
def workbook=(v)
|
849
|
+
def workbook=(v)
|
850
|
+
DataTypeValidator.validate "Worksheet.workbook", Workbook, v
|
851
|
+
@workbook = v
|
852
|
+
end
|
836
853
|
|
837
854
|
def update_column_info(cells, widths = nil)
|
838
855
|
cells.each_with_index do |cell, index|
|
@@ -849,7 +866,7 @@ module Axlsx
|
|
849
866
|
end
|
850
867
|
|
851
868
|
def add_autofilter_defined_name_to_workbook
|
852
|
-
return
|
869
|
+
return unless auto_filter.range
|
853
870
|
|
854
871
|
workbook.add_defined_name auto_filter.defined_name, name: '_xlnm._FilterDatabase', local_sheet_id: index, hidden: 1
|
855
872
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# A wraper class for comments that defines its on worksheet
|
3
5
|
# serailization
|
@@ -35,7 +37,7 @@ module Axlsx
|
|
35
37
|
|
36
38
|
# Helper method to tell us if there are comments in the comments collection
|
37
39
|
# @return [Boolean]
|
38
|
-
def has_comments?
|
40
|
+
def has_comments? # rubocop:disable Naming/PredicateName
|
39
41
|
!comments.empty?
|
40
42
|
end
|
41
43
|
|
@@ -49,7 +51,7 @@ module Axlsx
|
|
49
51
|
# Seraalize the object
|
50
52
|
# @param [String] str
|
51
53
|
# @return [String]
|
52
|
-
def to_xml_string(str = '')
|
54
|
+
def to_xml_string(str = +'')
|
53
55
|
return unless has_comments?
|
54
56
|
|
55
57
|
str << "<legacyDrawing r:id='#{drawing_rId}' />"
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Axlsx
|
2
4
|
# This is a utility class for serialing the drawing node in a
|
3
5
|
# worksheet. Drawing objects have their own serialization that exports
|
@@ -13,8 +15,12 @@ module Axlsx
|
|
13
15
|
@drawing = nil
|
14
16
|
end
|
15
17
|
|
18
|
+
# The worksheet that owns the drawing
|
19
|
+
# @return [Worksheet]
|
16
20
|
attr_reader :worksheet
|
17
21
|
|
22
|
+
# The drawing object
|
23
|
+
# @return [Drawing]
|
18
24
|
attr_reader :drawing
|
19
25
|
|
20
26
|
# adds a chart to the drawing object
|
@@ -36,7 +42,7 @@ module Axlsx
|
|
36
42
|
|
37
43
|
# helper method to tell us if the drawing has something in it or not
|
38
44
|
# @return [Boolean]
|
39
|
-
def has_drawing?
|
45
|
+
def has_drawing? # rubocop:disable Naming/PredicateName
|
40
46
|
@drawing.is_a? Drawing
|
41
47
|
end
|
42
48
|
|
@@ -50,7 +56,7 @@ module Axlsx
|
|
50
56
|
|
51
57
|
# Serialize the drawing for the worksheet
|
52
58
|
# @param [String] str
|
53
|
-
def to_xml_string(str = '')
|
59
|
+
def to_xml_string(str = +'')
|
54
60
|
return unless has_drawing?
|
55
61
|
|
56
62
|
str << "<drawing r:id='#{relationship.Id}'/>"
|