axlsx 1.1.7 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +41 -5
- data/Rakefile +3 -2
- data/examples/chart_colors.rb +18 -3
- data/examples/example.rb +100 -46
- data/examples/extractive.pdf +0 -0
- data/lib/axlsx.rb +7 -6
- data/lib/axlsx/content_type/content_type.rb +2 -0
- data/lib/axlsx/content_type/default.rb +21 -12
- data/lib/axlsx/content_type/override.rb +22 -11
- data/lib/axlsx/doc_props/app.rb +36 -32
- data/lib/axlsx/doc_props/core.rb +9 -5
- data/lib/axlsx/drawing/ax_data_source.rb +7 -6
- data/lib/axlsx/drawing/axis.rb +48 -27
- data/lib/axlsx/drawing/bar_3D_chart.rb +47 -37
- data/lib/axlsx/drawing/bar_series.rb +1 -0
- data/lib/axlsx/drawing/cat_axis.rb +42 -38
- data/lib/axlsx/drawing/chart.rb +34 -27
- data/lib/axlsx/drawing/drawing.rb +5 -4
- data/lib/axlsx/drawing/line_3D_chart.rb +1 -1
- data/lib/axlsx/drawing/num_data_source.rb +1 -1
- data/lib/axlsx/drawing/pie_3D_chart.rb +7 -7
- data/lib/axlsx/drawing/two_cell_anchor.rb +3 -8
- data/lib/axlsx/drawing/view_3D.rb +41 -31
- data/lib/axlsx/drawing/vml_drawing.rb +1 -1
- data/lib/axlsx/package.rb +11 -11
- data/lib/axlsx/rels/relationship.rb +3 -3
- data/lib/axlsx/stylesheet/styles.rb +1 -1
- data/lib/axlsx/util/constants.rb +4 -0
- data/lib/axlsx/util/simple_typed_list.rb +2 -2
- data/lib/axlsx/util/validators.rb +2 -2
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/workbook.rb +1 -2
- data/lib/axlsx/workbook/worksheet/cell.rb +1 -1
- data/lib/axlsx/workbook/worksheet/data_bar.rb +1 -1
- data/lib/axlsx/workbook/worksheet/page_setup.rb +9 -0
- data/lib/axlsx/workbook/worksheet/protected_range.rb +46 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +180 -56
- data/test/content_type/tc_content_type.rb +1 -6
- data/test/doc_props/tc_core.rb +1 -1
- data/test/drawing/tc_axis.rb +8 -0
- data/test/drawing/tc_bar_3D_chart.rb +12 -12
- data/test/drawing/tc_bar_series.rb +0 -1
- data/test/drawing/tc_chart.rb +1 -5
- data/test/drawing/tc_pie_3D_chart.rb +3 -7
- data/test/drawing/tc_view_3D.rb +18 -18
- data/test/tc_package.rb +2 -0
- data/test/workbook/worksheet/tc_page_setup.rb +20 -3
- data/test/workbook/worksheet/tc_protected_range.rb +18 -0
- data/test/workbook/worksheet/tc_selection.rb +1 -1
- data/test/workbook/worksheet/tc_worksheet.rb +39 -18
- metadata +54 -103
- data/examples/axis-titles.xlsx +0 -0
- data/examples/basic_charts.xlsx +0 -0
- data/examples/chart_colors.xlsx +0 -0
- data/examples/charts.xlsx +0 -0
- data/examples/conditional_formatting/getting_barred.xlsx +0 -0
- data/examples/doc/_index.html +0 -84
- data/examples/doc/class_list.html +0 -47
- data/examples/doc/css/common.css +0 -1
- data/examples/doc/css/full_list.css +0 -55
- data/examples/doc/css/style.css +0 -322
- data/examples/doc/file_list.html +0 -46
- data/examples/doc/frames.html +0 -13
- data/examples/doc/index.html +0 -84
- data/examples/doc/js/app.js +0 -205
- data/examples/doc/js/full_list.js +0 -173
- data/examples/doc/js/jquery.js +0 -16
- data/examples/doc/method_list.html +0 -46
- data/examples/doc/top-level-namespace.html +0 -95
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/examples_saved.xlsx +0 -0
- data/examples/extractive.xlsx +0 -0
- data/examples/fish.xlsx +0 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/pareto.rb +0 -28
- data/examples/pareto.xlsx +0 -0
- data/examples/pie_chart_excel.xlsx +0 -0
- data/examples/pie_chart_saved.xlsx +0 -0
- data/examples/shared_strings_example.xlsx +0 -0
- data/examples/sheet_protection.xlsx +0 -0
- data/examples/sheet_view.xlsx +0 -0
- data/examples/two_cell_anchor_image.xlsx +0 -0
- data/examples/~$example.xlsx +0 -0
- data/lib/axlsx/drawing/ax_data_source.rb~ +0 -55
- data/lib/axlsx/drawing/data_source.rb~ +0 -51
- data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
- data/lib/axlsx/drawing/hyperlink.rb~ +0 -64
- data/lib/axlsx/drawing/num_data.rb~ +0 -51
- data/lib/axlsx/drawing/num_data_source.rb~ +0 -54
- data/lib/axlsx/drawing/num_val.rb~ +0 -40
- data/lib/axlsx/drawing/picture_locking.rb~ +0 -36
- data/lib/axlsx/drawing/ref.rb~ +0 -41
- data/lib/axlsx/drawing/str_data.rb~ +0 -58
- data/lib/axlsx/drawing/str_val.rb~ +0 -35
- data/lib/axlsx/drawing/vml_drawing.rb~ +0 -6
- data/lib/axlsx/drawing/vml_shape.rb~ +0 -61
- data/lib/axlsx/util/cbf.rb +0 -333
- data/lib/axlsx/util/cfb.rb~ +0 -201
- data/lib/axlsx/util/font_tables.rb~ +0 -0
- data/lib/axlsx/util/ms_off_crypto.rb +0 -189
- data/lib/axlsx/util/ms_off_crypto.rb~ +0 -3
- data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
- data/lib/axlsx/util/parser.rb~ +0 -6
- data/lib/axlsx/util/storage.rb~ +0 -0
- data/lib/axlsx/workbook/shared_strings_table.rb~ +0 -69
- data/lib/axlsx/workbook/worksheet/cfvo.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/color_scale.rb~ +0 -46
- data/lib/axlsx/workbook/worksheet/comment.rb~ +0 -91
- data/lib/axlsx/workbook/worksheet/comments.rb~ +0 -86
- data/lib/axlsx/workbook/worksheet/data_bar.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/icon_set.rb~ +0 -95
- data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/table.rb~ +0 -97
- data/lib/schema/dc.xsd~ +0 -118
- data/lib/schema/dcterms.xsd~ +0 -331
- data/lib/schema/opc-coreProperties.xsd~ +0 -50
- data/test/drawing/tc_data_source.rb~ +0 -30
- data/test/drawing/tc_num_data.rb~ +0 -35
- data/test/drawing/tc_num_val.rb~ +0 -29
- data/test/drawing/tc_str_data.rb~ +0 -30
- data/test/drawing/tc_str_val.rb~ +0 -26
- data/test/drawing/tc_vml_drawing.rb~ +0 -0
- data/test/workbook/worksheet/table/tc_table.rb~ +0 -72
- data/test/workbook/worksheet/tc_cfvo.rb~ +0 -20
- data/test/workbook/worksheet/tc_col.rb~ +0 -10
- data/test/workbook/worksheet/tc_color_scale.rb~ +0 -0
- data/test/workbook/worksheet/tc_data_bar.rb~ +0 -0
- data/test/workbook/worksheet/tc_icon_set.rb~ +0 -0
data/lib/axlsx/package.rb
CHANGED
|
@@ -156,18 +156,18 @@ module Axlsx
|
|
|
156
156
|
# @return [Zip::ZipOutputStream]
|
|
157
157
|
def write_parts(zip)
|
|
158
158
|
p = parts
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
end
|
|
165
|
-
unless part[:path].nil?
|
|
166
|
-
zip.put_next_entry(part[:entry]);
|
|
167
|
-
# binread for 1.9.3
|
|
168
|
-
zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path])
|
|
169
|
-
end
|
|
159
|
+
p.each do |part|
|
|
160
|
+
unless part[:doc].nil?
|
|
161
|
+
zip.put_next_entry(part[:entry])
|
|
162
|
+
entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc]
|
|
163
|
+
zip.puts(entry)
|
|
170
164
|
end
|
|
165
|
+
unless part[:path].nil?
|
|
166
|
+
zip.put_next_entry(part[:entry]);
|
|
167
|
+
# binread for 1.9.3
|
|
168
|
+
zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path])
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
171
|
zip
|
|
172
172
|
end
|
|
173
173
|
|
|
@@ -30,9 +30,9 @@ module Axlsx
|
|
|
30
30
|
attr_reader :TargetMode
|
|
31
31
|
|
|
32
32
|
# creates a new relationship
|
|
33
|
-
# @param [String]
|
|
34
|
-
# @param [String]
|
|
35
|
-
# @option [Symbol] target_mode only accepts :external.
|
|
33
|
+
# @param [String] type The type of the relationship
|
|
34
|
+
# @param [String] target The target for the relationship
|
|
35
|
+
# @option [Symbol] :target_mode only accepts :external.
|
|
36
36
|
def initialize(type, target, options={})
|
|
37
37
|
self.Target=target
|
|
38
38
|
self.Type=type
|
|
@@ -133,7 +133,7 @@ module Axlsx
|
|
|
133
133
|
# @option options [Integer] family The font family to use.
|
|
134
134
|
# @option options [String] font_name The name of the font to use
|
|
135
135
|
# @option options [Integer] num_fmt The number format to apply
|
|
136
|
-
# @option options [String] format_code The formatting to apply.
|
|
136
|
+
# @option options [String] format_code The formatting to apply.
|
|
137
137
|
# @option options [Integer|Hash] border The border style to use.
|
|
138
138
|
# @option options [String] bg_color The background color to apply to the cell
|
|
139
139
|
# @option options [Boolean] hidden Indicates if the cell should be hidden
|
data/lib/axlsx/util/constants.rb
CHANGED
|
@@ -249,6 +249,10 @@ module Axlsx
|
|
|
249
249
|
|
|
250
250
|
# error message for sheets that use a name which is longer than 31 bytes
|
|
251
251
|
ERR_SHEET_NAME_TOO_LONG = "Your worksheet name '%s' is too long. Worksheet names must be 31 characters (bytes) or less"
|
|
252
|
+
|
|
253
|
+
# error message for sheets that use a name which includes a colon
|
|
254
|
+
|
|
255
|
+
ERR_SHEET_NAME_COLON_FORBIDDEN = "Your worksheet name '%s' contains a colon, which is not allowed by MS Excel and will cause repair warnings. Please change the name of your sheet."
|
|
252
256
|
|
|
253
257
|
# error message for duplicate sheet names
|
|
254
258
|
ERR_DUPLICATE_SHEET_NAME = "There is already a worksheet in this workbook named '%s'. Please use a unique name"
|
|
@@ -18,7 +18,7 @@ module Axlsx
|
|
|
18
18
|
|
|
19
19
|
# Creats a new typed list
|
|
20
20
|
# @param [Array, Class] type An array of Class objects or a single Class object
|
|
21
|
-
# @param [String]
|
|
21
|
+
# @param [String] serialize_as The tag name to use in serialization
|
|
22
22
|
# @raise [ArgumentError] if all members of type are not Class objects
|
|
23
23
|
def initialize type, serialize_as=nil
|
|
24
24
|
if type.is_a? Array
|
|
@@ -149,7 +149,7 @@ module Axlsx
|
|
|
149
149
|
|
|
150
150
|
def to_xml_string(str = '')
|
|
151
151
|
classname = @allowed_types[0].name.split('::').last
|
|
152
|
-
el_name = serialize_as || (classname[0,1].downcase + classname[1..-1])
|
|
152
|
+
el_name = serialize_as.to_s || (classname[0,1].downcase + classname[1..-1])
|
|
153
153
|
str << '<' << el_name << ' count="' << @list.size.to_s << '">'
|
|
154
154
|
@list.each { |item| item.to_xml_string(str) }
|
|
155
155
|
str << '</' << el_name << '>'
|
|
@@ -181,7 +181,7 @@ module Axlsx
|
|
|
181
181
|
# Requires that the value is a valid scatterStyle
|
|
182
182
|
# must be one of :none | :line | :lineMarker | :marker | :smooth | :smoothMarker
|
|
183
183
|
# must be one of "none" | "line" | "lineMarker" | "marker" | "smooth" | "smoothMarker"
|
|
184
|
-
# @param [Symbol|String] the value to validate
|
|
184
|
+
# @param [Symbol|String] v the value to validate
|
|
185
185
|
def self.validate_scatter_style(v)
|
|
186
186
|
Axlsx::RestrictionValidator.validate "ScatterChart.scatterStyle", [:none, :line, :lineMarker, :marker, :smooth, :smoothMarker], v.to_sym
|
|
187
187
|
end
|
|
@@ -262,4 +262,4 @@ module Axlsx
|
|
|
262
262
|
def self.validate_split_state_type(v)
|
|
263
263
|
RestrictionValidator.validate :split_state_type, [:frozen, :frozen_split, :split], v
|
|
264
264
|
end
|
|
265
|
-
end
|
|
265
|
+
end
|
data/lib/axlsx/version.rb
CHANGED
|
@@ -5,6 +5,6 @@ module Axlsx
|
|
|
5
5
|
# When using bunle exec rake and referencing the gem on github or locally
|
|
6
6
|
# it will use the gemspec, which preloads this constant for the gem's version.
|
|
7
7
|
# We check to make sure that it has not already been loaded
|
|
8
|
-
VERSION="1.1.
|
|
8
|
+
VERSION="1.1.8" unless defined? Axlsx::VERSION
|
|
9
9
|
|
|
10
10
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
module Axlsx
|
|
3
3
|
|
|
4
4
|
require 'axlsx/workbook/worksheet/date_time_converter.rb'
|
|
5
|
+
require 'axlsx/workbook/worksheet/protected_range.rb'
|
|
5
6
|
require 'axlsx/workbook/worksheet/cell.rb'
|
|
6
7
|
require 'axlsx/workbook/worksheet/page_margins.rb'
|
|
7
8
|
require 'axlsx/workbook/worksheet/page_setup.rb'
|
|
@@ -100,7 +101,6 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
|
100
101
|
# @return [SimpleTypedList]
|
|
101
102
|
attr_reader :tables
|
|
102
103
|
|
|
103
|
-
|
|
104
104
|
# A colllection of comments associated with this workbook
|
|
105
105
|
# @note The recommended way to manage comments is Worksheet#add_comment
|
|
106
106
|
# @see Worksheet#add_comment
|
|
@@ -143,7 +143,6 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
|
143
143
|
@drawings = SimpleTypedList.new Drawing
|
|
144
144
|
@charts = SimpleTypedList.new Chart
|
|
145
145
|
@images = SimpleTypedList.new Pic
|
|
146
|
-
|
|
147
146
|
# Are these even used????? Check package serialization parts
|
|
148
147
|
@tables = SimpleTypedList.new Table
|
|
149
148
|
@comments = SimpleTypedList.new Comments
|
|
@@ -142,7 +142,7 @@ module Axlsx
|
|
|
142
142
|
# The inline color property for the cell
|
|
143
143
|
# @return [Color]
|
|
144
144
|
attr_reader :color
|
|
145
|
-
# @param [String] The 8 character representation for an rgb color #FFFFFFFF"
|
|
145
|
+
# @param [String] v The 8 character representation for an rgb color #FFFFFFFF"
|
|
146
146
|
def color=(v)
|
|
147
147
|
@color = v.is_a?(Color) ? v : Color.new(:rgb=>v)
|
|
148
148
|
@is_text_run = true
|
|
@@ -65,7 +65,7 @@ module Axlsx
|
|
|
65
65
|
def showValue=(v); Axlsx.validate_boolean(v); @showValue = v end
|
|
66
66
|
|
|
67
67
|
# Sets the color for the data bars.
|
|
68
|
-
# @param [Color|String] The color object, or rgb string value to apply
|
|
68
|
+
# @param [Color|String] v The color object, or rgb string value to apply
|
|
69
69
|
def color=(v)
|
|
70
70
|
@color = v if v.is_a? Color
|
|
71
71
|
self.color.rgb = v if v.is_a? String
|
|
@@ -92,6 +92,15 @@ module Axlsx
|
|
|
92
92
|
[@fit_to_width, @fit_to_height]
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
+
|
|
96
|
+
# helper method for worksheet to determine if the page setup is configured for fit to page printing
|
|
97
|
+
# We treat any page set up that has a value set for fit_to_width or fit_to_height value as fit_to_page.
|
|
98
|
+
# @return [Boolean]
|
|
99
|
+
def fit_to_page?
|
|
100
|
+
# is there some better what to express this?
|
|
101
|
+
(fit_to_width != nil || fit_to_height != nil)
|
|
102
|
+
end
|
|
103
|
+
|
|
95
104
|
# Serializes the page settings element.
|
|
96
105
|
# @param [String] str
|
|
97
106
|
# @return [String]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# The Protected Range class represents a set of cells in the worksheet
|
|
3
|
+
# @note the recommended way to manage protected ranges with via Worksheet#protect_range
|
|
4
|
+
# @see Worksheet#protect_range
|
|
5
|
+
class ProtectedRange
|
|
6
|
+
|
|
7
|
+
# The reference for the protected range
|
|
8
|
+
# @return [String]
|
|
9
|
+
attr_reader :sqref
|
|
10
|
+
|
|
11
|
+
# The name of the protected range
|
|
12
|
+
# @return [String]
|
|
13
|
+
attr_reader :name
|
|
14
|
+
|
|
15
|
+
# Initializes a new protected range object
|
|
16
|
+
# @option [String] sqref The cell range reference to protect. This can be an absolute or a relateve range however, it only applies to the current sheet.
|
|
17
|
+
# @option [String] name An optional name for the protected name.
|
|
18
|
+
def initialize(options={})
|
|
19
|
+
options.each do |o|
|
|
20
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
21
|
+
end
|
|
22
|
+
yield self if block_given?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @see sqref
|
|
26
|
+
def sqref=(v)
|
|
27
|
+
Axlsx.validate_string(v)
|
|
28
|
+
@sqref = v
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @see name
|
|
32
|
+
def name=(v)
|
|
33
|
+
Axlsx.validate_string(v)
|
|
34
|
+
@name = v
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# serializes the proteted range
|
|
38
|
+
# @param [String] str if this string object is provided we append
|
|
39
|
+
# our output to that object. Use this - it helps limit the number of
|
|
40
|
+
# objects created during serialization
|
|
41
|
+
def to_xml_string(str="")
|
|
42
|
+
attrs = self.instance_values.reject{ |key, value| value == nil }
|
|
43
|
+
str << '<protectedRange ' << attrs.map { |key, value| '' << key << '="' << value.to_s << '"' }.join(' ') << '/>'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -16,7 +16,13 @@ module Axlsx
|
|
|
16
16
|
yield @sheet_protection if block_given?
|
|
17
17
|
@sheet_protection
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
# A collection of protected ranges in the worksheet
|
|
21
|
+
# @note The recommended way to manage protected ranges is with Worksheet#protect_range
|
|
22
|
+
# @see Worksheet#protect_range
|
|
23
|
+
# @return [SimpleTypedList] The protected ranges for this worksheet
|
|
24
|
+
attr_reader :protected_ranges
|
|
25
|
+
|
|
20
26
|
# The sheet view object for this worksheet
|
|
21
27
|
# @return [SheetView]
|
|
22
28
|
# @see [SheetView]
|
|
@@ -34,6 +40,8 @@ module Axlsx
|
|
|
34
40
|
# @return [Array] of Table
|
|
35
41
|
attr_reader :tables
|
|
36
42
|
|
|
43
|
+
# The comments associated with this worksheet
|
|
44
|
+
# @return [SimpleTypedList]
|
|
37
45
|
attr_reader :comments
|
|
38
46
|
|
|
39
47
|
# The rows in this worksheet
|
|
@@ -81,8 +89,9 @@ module Axlsx
|
|
|
81
89
|
# If you want the worksheet to fit on more pages (e.g. 2x2), set {PageSetup#fit_to_width} and {PageSetup#fit_to_height} accordingly.
|
|
82
90
|
# @return Boolean
|
|
83
91
|
# @see #page_setup
|
|
84
|
-
def fit_to_page
|
|
85
|
-
|
|
92
|
+
def fit_to_page?
|
|
93
|
+
return false unless @page_setup
|
|
94
|
+
@page_setup.fit_to_page?
|
|
86
95
|
end
|
|
87
96
|
|
|
88
97
|
|
|
@@ -110,7 +119,6 @@ module Axlsx
|
|
|
110
119
|
@page_margins ||= PageMargins.new
|
|
111
120
|
yield @page_margins if block_given?
|
|
112
121
|
@page_margins
|
|
113
|
-
|
|
114
122
|
end
|
|
115
123
|
|
|
116
124
|
# Page setup settings for printing the worksheet.
|
|
@@ -188,7 +196,7 @@ module Axlsx
|
|
|
188
196
|
@print_options = PrintOptions.new options[:print_options] if options[:print_options]
|
|
189
197
|
@rows = SimpleTypedList.new Row
|
|
190
198
|
@column_info = SimpleTypedList.new Col
|
|
191
|
-
|
|
199
|
+
@protected_ranges = SimpleTypedList.new ProtectedRange
|
|
192
200
|
@tables = SimpleTypedList.new Table
|
|
193
201
|
|
|
194
202
|
options.each do |o|
|
|
@@ -217,7 +225,7 @@ module Axlsx
|
|
|
217
225
|
cf.add_rules rules
|
|
218
226
|
@conditional_formattings << cf
|
|
219
227
|
end
|
|
220
|
-
|
|
228
|
+
|
|
221
229
|
# Add data validation to this worksheet.
|
|
222
230
|
#
|
|
223
231
|
# @param [String] cells The cells the validation will apply to.
|
|
@@ -237,23 +245,37 @@ module Axlsx
|
|
|
237
245
|
# worksheet.merge_cells worksheet.rows.first.cells[(2..4)]
|
|
238
246
|
# #alternatively you can do it from a single cell
|
|
239
247
|
# worksheet["C1"].merge worksheet["E1"]
|
|
240
|
-
# @param [Array, string]
|
|
248
|
+
# @param [Array, string] cells
|
|
241
249
|
def merge_cells(cells)
|
|
242
250
|
@merged_cells << if cells.is_a?(String)
|
|
243
251
|
cells
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
252
|
+
elsif cells.is_a?(Array)
|
|
253
|
+
cells = cells.sort { |x, y| [x.index, x.row.index] <=> [y.index, y.row.index] }
|
|
254
|
+
"#{cells.first.r}:#{cells.last.r}"
|
|
255
|
+
end
|
|
248
256
|
end
|
|
249
257
|
|
|
258
|
+
# Adds a new protected cell range to the worksheet. Note that protected ranges are only in effect when sheet protection is enabled.
|
|
259
|
+
# @param [String|Array] cells The string reference for the cells to protect or an array of cells.
|
|
260
|
+
# @return [ProtectedRange]
|
|
261
|
+
# @note When using an array of cells, a contiguous range is created from the minimum top left to the maximum top bottom of the cells provided.
|
|
262
|
+
def protect_range(cells)
|
|
263
|
+
sqref = if cells.is_a?(String)
|
|
264
|
+
cells
|
|
265
|
+
elsif cells.is_a?(SimpleTypedList)
|
|
266
|
+
cells = cells.sort { |x, y| [x.index, x.row.index] <=> [y.index, y.row.index] }
|
|
267
|
+
"#{cells.first.r}:#{cells.last.r}"
|
|
268
|
+
end
|
|
269
|
+
@protected_ranges << ProtectedRange.new(:sqref => sqref, :name => 'Range#{@protected_ranges.size}')
|
|
270
|
+
@protected_ranges.last
|
|
271
|
+
end
|
|
250
272
|
|
|
251
273
|
# The demensions of a worksheet. This is not actually a required element by the spec,
|
|
252
274
|
# but at least a few other document readers expect this for conversion
|
|
253
275
|
# @return [String] the A1:B2 style reference for the first and last row column intersection in the workbook
|
|
254
276
|
def dimension
|
|
255
277
|
dim_start = rows.first.cells.first == nil ? 'A1' : rows.first.cells.first.r
|
|
256
|
-
dim_end = rows.last.cells.last == nil ? '
|
|
278
|
+
dim_end = rows.last.cells.last == nil ? 'AA200' : rows.last.cells.last.r
|
|
257
279
|
"#{dim_start}:#{dim_end}"
|
|
258
280
|
end
|
|
259
281
|
|
|
@@ -281,7 +303,7 @@ module Axlsx
|
|
|
281
303
|
# @return [Boolean]
|
|
282
304
|
def fit_to_page=(v)
|
|
283
305
|
warn('axlsx::DEPRECIATED: Worksheet#fit_to_page has been depreciated. This value will automatically be set for you when you use PageSetup#fit_to.')
|
|
284
|
-
fit_to_page
|
|
306
|
+
fit_to_page?
|
|
285
307
|
end
|
|
286
308
|
|
|
287
309
|
|
|
@@ -300,6 +322,8 @@ module Axlsx
|
|
|
300
322
|
def name=(v)
|
|
301
323
|
DataTypeValidator.validate "Worksheet.name", String, v
|
|
302
324
|
raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % v) if v.size > 31
|
|
325
|
+
raise ArgumentError, (ERR_SHEET_NAME_COLON_FORBIDDEN % v) if v.include? ':'
|
|
326
|
+
v = Axlsx::coder.encode(v)
|
|
303
327
|
sheet_names = @workbook.worksheets.map { |s| s.name }
|
|
304
328
|
raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % v) if sheet_names.include?(v)
|
|
305
329
|
@name=v
|
|
@@ -402,8 +426,9 @@ module Axlsx
|
|
|
402
426
|
|
|
403
427
|
# Set the style for cells in a specific row
|
|
404
428
|
# @param [Integer] index or range of indexes in the table
|
|
405
|
-
# @param [Integer] the cellXfs index
|
|
406
|
-
# @
|
|
429
|
+
# @param [Integer] style the cellXfs index
|
|
430
|
+
# @param [Hash] options the options used when applying the style
|
|
431
|
+
# @option [Integer] :col_offset only cells after this column will be updated.
|
|
407
432
|
# @note You can also specify the style in the add_row call
|
|
408
433
|
# @see Worksheet#add_row
|
|
409
434
|
# @see README.md for an example
|
|
@@ -425,8 +450,9 @@ module Axlsx
|
|
|
425
450
|
|
|
426
451
|
# Set the style for cells in a specific column
|
|
427
452
|
# @param [Integer] index the index of the column
|
|
428
|
-
# @param [Integer] the cellXfs index
|
|
429
|
-
# @
|
|
453
|
+
# @param [Integer] style the cellXfs index
|
|
454
|
+
# @param [Hash] options
|
|
455
|
+
# @option [Integer] :row_offset only cells after this column will be updated.
|
|
430
456
|
# @note You can also specify the style for specific columns in the call to add_row by using an array for the :styles option
|
|
431
457
|
# @see Worksheet#add_row
|
|
432
458
|
# @see README.md for an example
|
|
@@ -449,9 +475,9 @@ module Axlsx
|
|
|
449
475
|
# @example This would set the first and third column widhts but leave the second column in autofit state.
|
|
450
476
|
# ws.column_widths 7.2, nil, 3
|
|
451
477
|
# @note For updating only a single column it is probably easier to just set the width of the ws.column_info[col_index].width directly
|
|
452
|
-
# @param [Integer|Float|Fixnum|nil]
|
|
453
|
-
def column_widths(*
|
|
454
|
-
|
|
478
|
+
# @param [Integer|Float|Fixnum|nil] widths
|
|
479
|
+
def column_widths(*widths)
|
|
480
|
+
widths.each_with_index do |value, index|
|
|
455
481
|
next if value == nil
|
|
456
482
|
Axlsx::validate_unsigned_numeric(value) unless value == nil
|
|
457
483
|
@column_info[index] ||= Col.new index+1, index+1
|
|
@@ -493,55 +519,49 @@ module Axlsx
|
|
|
493
519
|
end
|
|
494
520
|
|
|
495
521
|
# Adds a media item to the worksheets drawing
|
|
496
|
-
# @
|
|
497
|
-
# @option options [] unknown
|
|
522
|
+
# @option [Hash] options options passed to drawing.add_image
|
|
498
523
|
def add_image(options={})
|
|
499
524
|
image = drawing.add_image(options)
|
|
500
525
|
yield image if block_given?
|
|
501
526
|
image
|
|
502
527
|
end
|
|
503
528
|
|
|
504
|
-
# Serializes the object
|
|
505
|
-
#
|
|
529
|
+
# Serializes the worksheet object to an xml string
|
|
530
|
+
# This intentionally does not use nokogiri for performance reasons
|
|
506
531
|
# @return [String]
|
|
507
532
|
def to_xml_string
|
|
508
|
-
rels = relationships
|
|
509
533
|
str = '<?xml version="1.0" encoding="UTF-8"?>'
|
|
510
|
-
str
|
|
511
|
-
str
|
|
512
|
-
str
|
|
534
|
+
str << worksheet_node
|
|
535
|
+
str << sheet_pr_node
|
|
536
|
+
str << dimension_node
|
|
513
537
|
@sheet_view.to_xml_string(str) if @sheet_view
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
end
|
|
519
|
-
str.concat '<sheetData>'
|
|
520
|
-
@rows.each_with_index { |row, index| row.to_xml_string(index, str) }
|
|
521
|
-
str.concat '</sheetData>'
|
|
522
|
-
str.concat "<autoFilter ref='%s'></autoFilter>" % @auto_filter if @auto_filter
|
|
538
|
+
str << cols_node
|
|
539
|
+
str << sheet_data_node
|
|
540
|
+
|
|
541
|
+
str << auto_filter_node
|
|
523
542
|
@sheet_protection.to_xml_string(str) if @sheet_protection
|
|
524
|
-
str
|
|
525
|
-
|
|
543
|
+
str << protected_ranges_node
|
|
544
|
+
str << merged_cells_node
|
|
545
|
+
@print_options.to_xml_string(str) if @print_options
|
|
526
546
|
page_margins.to_xml_string(str) if @page_margins
|
|
527
547
|
page_setup.to_xml_string(str) if @page_setup
|
|
528
|
-
str <<
|
|
529
|
-
str <<
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
548
|
+
str << drawing_node
|
|
549
|
+
str << legacy_drawing_node
|
|
550
|
+
str << table_parts_node
|
|
551
|
+
str << conditional_formattings_node
|
|
552
|
+
str << data_validations_node
|
|
553
|
+
str << '</worksheet>'
|
|
554
|
+
# User reported that when parsing some old data that had control characters excel chokes.
|
|
555
|
+
# All of the following are defined as illegal xml characters in the xml spec, but for now I am only dealing with control
|
|
556
|
+
# characters. Thanks to asakusarb and @hsbt's flash of code on the screen!
|
|
557
|
+
# [#x1-#x8], [#xB-#xC], [#xE-#x1F], [#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF],
|
|
558
|
+
# [#x1FFFE-#x1FFFF], [#x2FFFE-#x2FFFF], [#x3FFFE-#x3FFFF],
|
|
559
|
+
# [#x4FFFE-#x4FFFF], [#x5FFFE-#x5FFFF], [#x6FFFE-#x6FFFF],
|
|
560
|
+
# [#x7FFFE-#x7FFFF], [#x8FFFE-#x8FFFF], [#x9FFFE-#x9FFFF],
|
|
561
|
+
# [#xAFFFE-#xAFFFF], [#xBFFFE-#xBFFFF], [#xCFFFE-#xCFFFF],
|
|
562
|
+
# [#xDFFFE-#xDFFFF], [#xEFFFE-#xEFFFF], [#xFFFFE-#xFFFFF],
|
|
563
|
+
# [#x10FFFE-#x10FFFF].
|
|
564
|
+
str.gsub(/[[:cntrl:]]/,'')
|
|
545
565
|
end
|
|
546
566
|
|
|
547
567
|
# The worksheet relationships. This is managed automatically by the worksheet
|
|
@@ -584,6 +604,110 @@ module Axlsx
|
|
|
584
604
|
|
|
585
605
|
private
|
|
586
606
|
|
|
607
|
+
# Helper method for parsingout the root node for worksheet
|
|
608
|
+
# @return [String]
|
|
609
|
+
def worksheet_node
|
|
610
|
+
"<worksheet xmlns=\"%s\" xmlns:r=\"%s\">" % [XML_NS, XML_NS_R]
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
# Helper method fo parsing out the sheetPr node
|
|
614
|
+
# @return [String]
|
|
615
|
+
def sheet_pr_node
|
|
616
|
+
return '' unless fit_to_page?
|
|
617
|
+
"<sheetPr><pageSetUpPr fitToPage=\"%s\"></pageSetUpPr></sheetPr>" % fit_to_page?
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
# Helper method for parsing out the demension node
|
|
621
|
+
# @return [String]
|
|
622
|
+
def dimension_node
|
|
623
|
+
return '' if rows.size == 0
|
|
624
|
+
"<dimension ref=\"%s\"></dimension>" % dimension
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
# Helper method for parsing out the sheetData node
|
|
628
|
+
# @return [String]
|
|
629
|
+
def sheet_data_node
|
|
630
|
+
str = '<sheetData>'
|
|
631
|
+
@rows.each_with_index { |row, index| row.to_xml_string(index, str) }
|
|
632
|
+
str << '</sheetData>'
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
# Helper method for parsing out the autoFilter node
|
|
636
|
+
# @return [String]
|
|
637
|
+
def auto_filter_node
|
|
638
|
+
return '' unless @auto_filter
|
|
639
|
+
"<autoFilter ref='%s'></autoFilter>" % @auto_filter
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
# Helper method for parsing out the cols node
|
|
643
|
+
# @return [String]
|
|
644
|
+
def cols_node
|
|
645
|
+
return '' if @column_info.empty?
|
|
646
|
+
str = "<cols>"
|
|
647
|
+
@column_info.each { |col| col.to_xml_string(str) }
|
|
648
|
+
str << '</cols>'
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
# Helper method for parsing out the protectedRanges node
|
|
652
|
+
# @return [String]
|
|
653
|
+
def protected_ranges_node
|
|
654
|
+
return '' if @protected_ranges.empty?
|
|
655
|
+
str = '<protectedRanges>'
|
|
656
|
+
@protected_ranges.each { |pr| pr.to_xml_string(str) }
|
|
657
|
+
str << '</protectedRanges>'
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
# Helper method for parsing out the mergedCells node
|
|
661
|
+
# @return [String]
|
|
662
|
+
def merged_cells_node
|
|
663
|
+
return '' if @merged_cells.size == 0
|
|
664
|
+
str = "<mergeCells count='#{@merged_cells.size}'>"
|
|
665
|
+
@merged_cells.each { |merged_cell| str << "<mergeCell ref='#{merged_cell}'></mergeCell>" }
|
|
666
|
+
str << '</mergeCells>'
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
# Helper method for parsing out the drawing node
|
|
670
|
+
# @return [String]
|
|
671
|
+
def drawing_node
|
|
672
|
+
return '' unless @drawing
|
|
673
|
+
"<drawing r:id='rId" << (relationships.index{ |r| r.Type == DRAWING_R } + 1).to_s << "'/>"
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
# Helper method for parsing out the legacyDrawing node required for comments
|
|
677
|
+
# @return [String]
|
|
678
|
+
def legacy_drawing_node
|
|
679
|
+
return '' if @comments.empty?
|
|
680
|
+
"<legacyDrawing r:id='rId" << (relationships.index{ |r| r.Type == VML_DRAWING_R } + 1).to_s << "'/>"
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
# Helper method for parsing out the tableParts node
|
|
684
|
+
# @return [String]
|
|
685
|
+
def table_parts_node
|
|
686
|
+
return '' if @tables.empty?
|
|
687
|
+
str = "<tableParts count='#{@tables.size}'>"
|
|
688
|
+
@tables.each { |table| str << "<tablePart r:id='#{table.rId}'/>" }
|
|
689
|
+
str << '</tableParts>'
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
# Helper method for parsing out the conditional formattings
|
|
693
|
+
# @return [String]
|
|
694
|
+
def conditional_formattings_node
|
|
695
|
+
return '' if @conditional_formattings.size == 0
|
|
696
|
+
str = ''
|
|
697
|
+
@conditional_formattings.each { |conditional_formatting| str << conditional_formatting.to_xml_string }
|
|
698
|
+
str
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
# Helper method for parsing out the dataValidations node
|
|
702
|
+
# @return [String]
|
|
703
|
+
def data_validations_node
|
|
704
|
+
return '' if @data_validations.size == 0
|
|
705
|
+
str = "<dataValidations count='#{@data_validations.size}'>"
|
|
706
|
+
@data_validations.each { |data_validation| str << data_validation.to_xml_string }
|
|
707
|
+
str << '</dataValidations>'
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
|
|
587
711
|
# assigns the owner workbook for this worksheet
|
|
588
712
|
def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end
|
|
589
713
|
|