axlsx 1.2.3 → 1.3.1
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/.yardopts +3 -2
- data/CHANGELOG.md +34 -1
- data/README.md +26 -37
- data/Rakefile +1 -1
- data/examples/auto_filter.rb +16 -0
- data/examples/auto_filter.xlsx +0 -0
- data/examples/example.rb +3 -2
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/shared_strings_example.xlsx +0 -0
- data/examples/skydrive/real_example.rb +6 -6
- data/examples/sprk2012/Screen Shot 2012-09-11 at 10.42.06 PM.png +0 -0
- data/examples/sprk2012/Screen Shot 2012-09-11 at 11.07.48 PM.png +0 -0
- data/examples/sprk2012/Screen Shot 2012-09-11 at 8.31.50 PM.png +0 -0
- data/examples/sprk2012/Screen Shot 2012-09-11 at 9.23.27 PM.png +0 -0
- data/examples/sprk2012/Screen Shot 2012-09-11 at 9.32.06 PM.png +0 -0
- data/examples/sprk2012/Screen Shot 2012-09-11 at 9.33.35 PM.png +0 -0
- data/examples/sprk2012/Screen Shot 2012-09-11 at 9.46.44 PM.png +0 -0
- data/examples/sprk2012/Screen Shot 2012-09-12 at 5.07.23 PM.png +0 -0
- data/examples/sprk2012/basics.rb +1 -0
- data/examples/sprk2012/basics.xlsx +0 -0
- data/examples/sprk2012/gravatar.jpeg +0 -0
- data/examples/sprk2012/hair_club.jpg +0 -0
- data/examples/sprk2012/images.rb +7 -12
- data/examples/sprk2012/images.xlsx +0 -0
- data/examples/sprk2012/line_chart.rb +56 -0
- data/examples/sprk2012/line_chart.xlsx +0 -0
- data/examples/sprk2012/sprk2012.key +0 -0
- data/examples/sprk2012/styles.rb +13 -12
- data/examples/sprk2012/styles.xlsx +0 -0
- data/examples/styles.rb +62 -0
- data/examples/styles.xlsx +0 -0
- data/lib/axlsx.rb +8 -1
- data/lib/axlsx/stylesheet/styles.rb +4 -0
- data/lib/axlsx/util/constants.rb +90 -5
- data/lib/axlsx/util/validators.rb +26 -8
- data/lib/axlsx/version.rb +2 -2
- data/lib/axlsx/workbook/workbook.rb +4 -1
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +77 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +102 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +253 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +9 -4
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +1 -1
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +47 -0
- data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +49 -0
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +87 -4
- data/lib/axlsx/workbook/worksheet/table.rb +8 -1
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +68 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +18 -3
- data/test/stylesheet/tc_styles.rb +13 -0
- data/test/util/tc_validators.rb +8 -1
- data/test/workbook/worksheet/auto_filter/tc_auto_filter.rb +38 -0
- data/test/workbook/worksheet/auto_filter/tc_filter_column.rb +76 -0
- data/test/workbook/worksheet/auto_filter/tc_filters.rb +50 -0
- data/test/workbook/worksheet/tc_cell.rb +5 -0
- data/test/workbook/worksheet/tc_page_set_up_pr.rb +15 -0
- data/test/workbook/worksheet/tc_sheet_calc_pr.rb +18 -0
- data/test/workbook/worksheet/tc_sheet_pr.rb +27 -0
- data/test/workbook/worksheet/{table/tc_table.rb → tc_table.rb} +6 -1
- data/test/workbook/worksheet/tc_table_style_info.rb +53 -0
- data/test/workbook/worksheet/tc_worksheet.rb +17 -3
- metadata +45 -7
- data/examples/~$extractive.xlsx +0 -0
- data/lib/axlsx/workbook/worksheet/auto_filter.rb +0 -35
Binary file
|
data/lib/axlsx.rb
CHANGED
@@ -37,7 +37,12 @@ if !Object.respond_to?(:instance_values)
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
# xlsx generation with charts, images, automated column width, customizable styles
|
40
|
+
# xlsx generation with charts, images, automated column width, customizable styles
|
41
|
+
# and full schema validation. Axlsx excels at helping you generate beautiful
|
42
|
+
# Office Open XML Spreadsheet documents without having to understand the entire
|
43
|
+
# ECMA specification. Check out the README for some examples of how easy it is.
|
44
|
+
# Best of all, you can validate your xlsx file before serialization so you know
|
45
|
+
# for sure that anything generated is going to load on your client's machine.
|
41
46
|
module Axlsx
|
42
47
|
|
43
48
|
# determines the cell range for the items provided
|
@@ -65,6 +70,7 @@ module Axlsx
|
|
65
70
|
# returns the x, y position of a cell
|
66
71
|
def self.name_to_indices(name)
|
67
72
|
raise ArgumentError, 'invalid cell name' unless name.size > 1
|
73
|
+
# capitalization?!?
|
68
74
|
v = name[/[A-Z]+/].reverse.chars.reduce({:base=>1, :i=>0}) do |val, c|
|
69
75
|
val[:i] += ((c.bytes.first - 64) * val[:base]); val[:base] *= 26; val
|
70
76
|
end
|
@@ -95,6 +101,7 @@ module Axlsx
|
|
95
101
|
# @param [String] s The snake case string to camelize
|
96
102
|
# @return [String]
|
97
103
|
def self.camel(s="", all_caps = true)
|
104
|
+
s = s.to_s
|
98
105
|
s = s.capitalize if all_caps
|
99
106
|
s.gsub(/_(.)/){ $1.upcase }
|
100
107
|
end
|
@@ -279,6 +279,10 @@ module Axlsx
|
|
279
279
|
# @return [Font|Integer]
|
280
280
|
def parse_font_options(options={})
|
281
281
|
return if (options.keys & [:fg_color, :sz, :b, :i, :u, :strike, :outline, :shadow, :charset, :family, :font_name]).empty?
|
282
|
+
fonts.first.instance_values.each do |key, value|
|
283
|
+
# Thanks for that 1.8.7 - cant do a simple merge...
|
284
|
+
options[key.to_sym] = value unless options.keys.include?(key.to_sym)
|
285
|
+
end
|
282
286
|
font = Font.new(options)
|
283
287
|
font.color = Color.new(:rgb => options[:fg_color]) if options[:fg_color]
|
284
288
|
font.name = options[:font_name] if options[:font_name]
|
data/lib/axlsx/util/constants.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
module Axlsx
|
3
2
|
|
4
3
|
# XML Encoding
|
@@ -129,7 +128,7 @@ module Axlsx
|
|
129
128
|
|
130
129
|
# digital signature origin content type
|
131
130
|
DIGITAL_SIGNATURE_ORIGIN_CT = "application/vnd.openxmlformats-package.digital-signature-origin"
|
132
|
-
|
131
|
+
|
133
132
|
# digital signature certificate content type
|
134
133
|
DIGITAL_SIGNATURE_CERTIFICATE_CT = "application/vnd.openxmlformats-package.digital-signature-certificate"
|
135
134
|
|
@@ -151,7 +150,7 @@ module Axlsx
|
|
151
150
|
#drawing content type
|
152
151
|
DRAWING_CT = "application/vnd.openxmlformats-officedocument.drawing+xml"
|
153
152
|
|
154
|
-
|
153
|
+
|
155
154
|
# xml content type extensions
|
156
155
|
XML_EX = "xml"
|
157
156
|
|
@@ -263,11 +262,14 @@ module Axlsx
|
|
263
262
|
# error message for RegexValidator
|
264
263
|
ERR_REGEX = "Invalid Data. %s does not match %s."
|
265
264
|
|
265
|
+
# error message for RangeValidator
|
266
|
+
ERR_RANGE = "Invalid Data. %s must be between %s and %s, (inclusive:%s) you gave: %s"
|
267
|
+
|
266
268
|
# error message for sheets that use a name which is longer than 31 bytes
|
267
269
|
ERR_SHEET_NAME_TOO_LONG = "Your worksheet name '%s' is too long. Worksheet names must be 31 characters (bytes) or less"
|
268
|
-
|
270
|
+
|
269
271
|
# error message for sheets that use a name which includes a colon
|
270
|
-
|
272
|
+
|
271
273
|
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."
|
272
274
|
|
273
275
|
# error message for duplicate sheet names
|
@@ -284,4 +286,87 @@ module Axlsx
|
|
284
286
|
|
285
287
|
# error message for non 'integerish' value
|
286
288
|
ERR_INTEGERISH = "You value must be, or be castable via to_i, an Integer. You provided %s"
|
289
|
+
|
290
|
+
# Regex to match forbidden control characters
|
291
|
+
# The following will be automatically stripped from worksheets.
|
292
|
+
#
|
293
|
+
# x00 Null
|
294
|
+
# x01 Start Of Heading
|
295
|
+
# x02 Start Of Text
|
296
|
+
# x03End Of Text
|
297
|
+
# x04 End Of Transmission
|
298
|
+
# x05 Enquiry
|
299
|
+
# x06 Acknowledge
|
300
|
+
# x07 Bell
|
301
|
+
# x08 Backspace
|
302
|
+
# x0B Line Tabulation
|
303
|
+
# x0C Form Feed
|
304
|
+
# x0E Shift Out
|
305
|
+
# x0F Shift In
|
306
|
+
# x10 Data Link Escape
|
307
|
+
# x11 Device Control One
|
308
|
+
# x12 Device Control Two
|
309
|
+
# x13 Device Control Three
|
310
|
+
# x14 Device Control Four
|
311
|
+
# x15 Negative Acknowledge
|
312
|
+
# x16 Synchronous Idle
|
313
|
+
# x17 End Of Transmission Block
|
314
|
+
# x18 Cancel
|
315
|
+
# x19 End Of Medium
|
316
|
+
# x1A Substitute
|
317
|
+
# x1B Escape
|
318
|
+
# x1C Information Separator Four
|
319
|
+
# x1D Information Separator Three
|
320
|
+
# x1E Information Separator Two
|
321
|
+
# x1F Information Separator One
|
322
|
+
#
|
323
|
+
# The following are not dealt with.
|
324
|
+
# If you have this in your data, expect excel to blow up!
|
325
|
+
#
|
326
|
+
# x7F Delete
|
327
|
+
# x80 Control 0080
|
328
|
+
# x81 Control 0081
|
329
|
+
# x82 Break Permitted Here
|
330
|
+
# x83 No Break Here
|
331
|
+
# x84 Control 0084
|
332
|
+
# x85 Next Line (Nel)
|
333
|
+
# x86 Start Of Selected Area
|
334
|
+
# x87 End Of Selected Area
|
335
|
+
# x88 Character Tabulation Set
|
336
|
+
# x89 Character Tabulation With Justification
|
337
|
+
# x8A Line Tabulation Set
|
338
|
+
# x8B Partial Line Forward
|
339
|
+
# x8C Partial Line Backward
|
340
|
+
# x8D Reverse Line Feed
|
341
|
+
# x8E Single Shift Two
|
342
|
+
# x8F Single Shift Three
|
343
|
+
# x90 Device Control String
|
344
|
+
# x91 Private Use One
|
345
|
+
# x92 Private Use Two
|
346
|
+
# x93 Set Transmit State
|
347
|
+
# x94 Cancel Character
|
348
|
+
# x95 Message Waiting
|
349
|
+
# x96 Start Of Guarded Area
|
350
|
+
# x97 End Of Guarded Area
|
351
|
+
# x98 Start Of String
|
352
|
+
# x99 Control 0099
|
353
|
+
# x9A Single Character Introducer
|
354
|
+
# x9B Control Sequence Introducer
|
355
|
+
# x9C String Terminator
|
356
|
+
# x9D Operating System Command
|
357
|
+
# x9E Privacy Message
|
358
|
+
# x9F Application Program Command
|
359
|
+
#
|
360
|
+
# The following are allowed:
|
361
|
+
#
|
362
|
+
# x0A Line Feed (Lf)
|
363
|
+
# x0D Carriage Return (Cr)
|
364
|
+
# x09 Character Tabulation
|
365
|
+
# @see http://www.codetable.net/asciikeycodes
|
366
|
+
pattern = "[\x0-\x08\x0B\x0C\x0E-\x1F]"
|
367
|
+
pattern= pattern.respond_to?(:encode) ? pattern.encode('UTF-8') : pattern
|
368
|
+
|
369
|
+
# The regular expression used to remove control characters from worksheets
|
370
|
+
CONTROL_CHAR_REGEX = Regexp.new(pattern, 'n')
|
371
|
+
|
287
372
|
end
|
@@ -14,6 +14,24 @@ module Axlsx
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
# Validate that the value provided is between a specific range
|
18
|
+
# Note that no data conversions will be done for you!
|
19
|
+
# Comparisons will be made using < and > or <= and <= when the inclusive parameter is true
|
20
|
+
class RangeValidator
|
21
|
+
# @param [String] name The name of what is being validated
|
22
|
+
# @param [Any] min The minimum allowed value
|
23
|
+
# @param [Any] max The maximum allowed value
|
24
|
+
# @param [Any] value The value to be validated
|
25
|
+
# @param [Boolean] inclusive Flag indicating if the comparison should be inclusive.
|
26
|
+
def self.validate(name, min, max, value, inclusive = true)
|
27
|
+
passes = if inclusive
|
28
|
+
min <= value && value <= max
|
29
|
+
else
|
30
|
+
min < value && value < max
|
31
|
+
end
|
32
|
+
raise ArgumentError, (ERR_RANGE % [value.inspect, min.to_s, max.to_s, inclusive]) unless passes
|
33
|
+
end
|
34
|
+
end
|
17
35
|
# Validates the value against the regular expression provided.
|
18
36
|
class RegexValidator
|
19
37
|
# @param [String] name The name of what is being validated. This is included in the output when the value is invalid
|
@@ -73,7 +91,7 @@ module Axlsx
|
|
73
91
|
# @raise [ArgumentError] raised if the value is not a Fixnun, Integer, Float value greater or equal to 0
|
74
92
|
# @return [Boolean] true if the data is valid
|
75
93
|
def self.validate_unsigned_numeric(v)
|
76
|
-
DataTypeValidator.validate("Invalid column width", [Fixnum, Integer, Float], v, lambda { |arg| arg.respond_to?(:>=) && arg >= 0 })
|
94
|
+
DataTypeValidator.validate("Invalid column width", [Fixnum, Integer, Float], v, lambda { |arg| arg.respond_to?(:>=) && arg.to_i >= 0 })
|
77
95
|
end
|
78
96
|
|
79
97
|
# Requires that the value is a Fixnum or Integer
|
@@ -112,7 +130,7 @@ module Axlsx
|
|
112
130
|
def self.validate_scale_10_400(v)
|
113
131
|
DataTypeValidator.validate "page_scale", [Fixnum, Integer], v, lambda { |arg| arg >= 10 && arg <= 400 }
|
114
132
|
end
|
115
|
-
|
133
|
+
|
116
134
|
# Requires that the value is an integer ranging from 10 to 400 or 0.
|
117
135
|
def self.validate_scale_0_10_400(v)
|
118
136
|
DataTypeValidator.validate "page_scale", [Fixnum, Integer], v, lambda { |arg| arg == 0 || (arg >= 10 && arg <= 400) }
|
@@ -129,7 +147,7 @@ module Axlsx
|
|
129
147
|
# @param [Any] v The value validated
|
130
148
|
def self.validate_pattern_type(v)
|
131
149
|
RestrictionValidator.validate :pattern_type, [:none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown, :darkUp, :darkGrid,
|
132
|
-
|
150
|
+
:darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, :gray0625], v
|
133
151
|
end
|
134
152
|
|
135
153
|
# Requires that the value is one of the ST_TimePeriod types
|
@@ -226,7 +244,7 @@ module Axlsx
|
|
226
244
|
def self.validate_data_validation_error_style(v)
|
227
245
|
RestrictionValidator.validate :validate_data_validation_error_style, [:information, :stop, :warning], v
|
228
246
|
end
|
229
|
-
|
247
|
+
|
230
248
|
# Requires that the value is valid data validation operator.
|
231
249
|
# valid operators must be one of lessThan, lessThanOrEqual, equal,
|
232
250
|
# notEqual, greaterThanOrEqual, greaterThan, between, notBetween
|
@@ -234,28 +252,28 @@ module Axlsx
|
|
234
252
|
def self.validate_data_validation_operator(v)
|
235
253
|
RestrictionValidator.validate :data_validation_operator, [:lessThan, :lessThanOrEqual, :equal, :notEqual, :greaterThanOrEqual, :greaterThan, :between, :notBetween], v
|
236
254
|
end
|
237
|
-
|
255
|
+
|
238
256
|
# Requires that the value is valid data validation type.
|
239
257
|
# valid types must be one of custom, data, decimal, list, none, textLength, time, whole
|
240
258
|
# @param [Any] v The value validated
|
241
259
|
def self.validate_data_validation_type(v)
|
242
260
|
RestrictionValidator.validate :data_validation_type, [:custom, :data, :decimal, :list, :none, :textLength, :time, :whole], v
|
243
261
|
end
|
244
|
-
|
262
|
+
|
245
263
|
# Requires that the value is a valid sheet view type.
|
246
264
|
# valid types must be one of normal, page_break_preview, page_layout
|
247
265
|
# @param [Any] v The value validated
|
248
266
|
def self.validate_sheet_view_type(v)
|
249
267
|
RestrictionValidator.validate :sheet_view_type, [:normal, :page_break_preview, :page_layout], v
|
250
268
|
end
|
251
|
-
|
269
|
+
|
252
270
|
# Requires that the value is a valid active pane type.
|
253
271
|
# valid types must be one of bottom_left, bottom_right, top_left, top_right
|
254
272
|
# @param [Any] v The value validated
|
255
273
|
def self.validate_pane_type(v)
|
256
274
|
RestrictionValidator.validate :active_pane_type, [:bottom_left, :bottom_right, :top_left, :top_right], v
|
257
275
|
end
|
258
|
-
|
276
|
+
|
259
277
|
# Requires that the value is a valid split state type.
|
260
278
|
# valid types must be one of frozen, frozen_split, split
|
261
279
|
# @param [Any] v The value validated
|
data/lib/axlsx/version.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
module Axlsx
|
3
|
-
require 'axlsx/workbook/worksheet/
|
3
|
+
require 'axlsx/workbook/worksheet/sheet_calc_pr.rb'
|
4
|
+
require 'axlsx/workbook/worksheet/auto_filter/auto_filter.rb'
|
4
5
|
require 'axlsx/workbook/worksheet/date_time_converter.rb'
|
5
6
|
require 'axlsx/workbook/worksheet/protected_range.rb'
|
6
7
|
require 'axlsx/workbook/worksheet/protected_ranges.rb'
|
7
8
|
require 'axlsx/workbook/worksheet/cell.rb'
|
8
9
|
require 'axlsx/workbook/worksheet/page_margins.rb'
|
10
|
+
require 'axlsx/workbook/worksheet/page_set_up_pr.rb'
|
9
11
|
require 'axlsx/workbook/worksheet/page_setup.rb'
|
10
12
|
require 'axlsx/workbook/worksheet/print_options.rb'
|
11
13
|
require 'axlsx/workbook/worksheet/cfvo.rb'
|
@@ -33,6 +35,7 @@ require 'axlsx/workbook/worksheet/worksheet.rb'
|
|
33
35
|
require 'axlsx/workbook/shared_strings_table.rb'
|
34
36
|
require 'axlsx/workbook/defined_name.rb'
|
35
37
|
require 'axlsx/workbook/defined_names.rb'
|
38
|
+
require 'axlsx/workbook/worksheet/table_style_info.rb'
|
36
39
|
require 'axlsx/workbook/worksheet/table.rb'
|
37
40
|
require 'axlsx/workbook/worksheet/tables.rb'
|
38
41
|
require 'axlsx/workbook/worksheet/data_validation.rb'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
require 'axlsx/workbook/worksheet/auto_filter/filter_column.rb'
|
3
|
+
require 'axlsx/workbook/worksheet/auto_filter/filters.rb'
|
4
|
+
|
5
|
+
module Axlsx
|
6
|
+
|
7
|
+
#This class represents an auto filter range in a worksheet
|
8
|
+
class AutoFilter
|
9
|
+
|
10
|
+
# creates a new Autofilter object
|
11
|
+
# @param [Worksheet] worksheet
|
12
|
+
def initialize(worksheet)
|
13
|
+
raise ArgumentError, 'you must provide a worksheet' unless worksheet.is_a?(Worksheet)
|
14
|
+
@worksheet = worksheet
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :worksheet
|
18
|
+
|
19
|
+
# The range the autofilter should be applied to.
|
20
|
+
# This should be a string like 'A1:B8'
|
21
|
+
# @return [String]
|
22
|
+
attr_accessor :range
|
23
|
+
|
24
|
+
# the formula for the defined name required for this auto filter
|
25
|
+
# This prepends the worksheet name to the absolute cell reference
|
26
|
+
# e.g. A1:B2 -> 'Sheet1'!$A$1:$B$2
|
27
|
+
# @return [String]
|
28
|
+
def defined_name
|
29
|
+
return unless range
|
30
|
+
Axlsx.cell_range(range.split(':').collect { |name| worksheet.name_to_cell(name)})
|
31
|
+
end
|
32
|
+
|
33
|
+
# A collection of filterColumns for this auto_filter
|
34
|
+
# @return [SimpleTypedList]
|
35
|
+
def columns
|
36
|
+
@columns ||= SimpleTypedList.new FilterColumn
|
37
|
+
end
|
38
|
+
|
39
|
+
# Adds a filter column. This is the recommended way to create and manage filter columns for your autofilter.
|
40
|
+
# In addition to the require id and type parameters, options will be passed to the filter column during instantiation.
|
41
|
+
# @param [String] col_id Zero-based index indicating the AutoFilter column to which this filter information applies.
|
42
|
+
# @param [Symbol] filter_type A symbol representing one of the supported filter types.
|
43
|
+
# @param [Hash] options a hash of options to pass into the generated filter
|
44
|
+
# @return [FilterColumn]
|
45
|
+
def add_column(col_id, filter_type, options = {})
|
46
|
+
columns << FilterColumn.new(col_id, filter_type, options)
|
47
|
+
columns.last
|
48
|
+
end
|
49
|
+
|
50
|
+
# actually performs the filtering of rows who's cells do not
|
51
|
+
# match the filter.
|
52
|
+
def apply
|
53
|
+
first_cell, last_cell = range.split(':')
|
54
|
+
start_point = Axlsx::name_to_indices(first_cell)
|
55
|
+
end_point = Axlsx::name_to_indices(last_cell)
|
56
|
+
# The +1 is so we skip the header row with the filter drop downs
|
57
|
+
rows = worksheet.rows[(start_point.last+1)..end_point.last] || []
|
58
|
+
|
59
|
+
column_offset = start_point.first
|
60
|
+
columns.each do |column|
|
61
|
+
rows.each do |row|
|
62
|
+
next if row.hidden
|
63
|
+
column.apply(row, column_offset)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
# serialize the object
|
68
|
+
# @return [String]
|
69
|
+
def to_xml_string(str='')
|
70
|
+
return unless range
|
71
|
+
str << "<autoFilter ref='#{range}'>"
|
72
|
+
columns.each { |filter_column| filter_column.to_xml_string(str) }
|
73
|
+
str << "</autoFilter>"
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Axlsx
|
2
|
+
# The filterColumn collection identifies a particular column in the AutoFilter
|
3
|
+
# range and specifies filter information that has been applied to this column.
|
4
|
+
# If a column in the AutoFilter range has no criteria specified,
|
5
|
+
# then there is no corresponding filterColumn collection expressed for that column.
|
6
|
+
class FilterColumn
|
7
|
+
|
8
|
+
# Allowed filters
|
9
|
+
FILTERS = [:filters] #, :top10, :custom_filters, :dynamic_filters, :color_filters, :icon_filters]
|
10
|
+
|
11
|
+
# Creates a new FilterColumn object
|
12
|
+
# @note This class yeilds its filter object as that is where the vast majority of processing will be done
|
13
|
+
# @param [Integer|Cell] col_id The zero based index for the column to which this filter will be applied
|
14
|
+
# @param [Symbol] filter_type The symbolized class name of the filter to apply to this column.
|
15
|
+
# @param [Hash] options options for this object and the filter
|
16
|
+
# @option [Boolean] hidden_button @see hidden_button
|
17
|
+
# @option [Boolean] show_button @see show_button
|
18
|
+
def initialize(col_id, filter_type, options = {})
|
19
|
+
RestrictionValidator.validate 'FilterColumn.filter', FILTERS, filter_type
|
20
|
+
#Axlsx::validate_unsigned_int(col_id)
|
21
|
+
self.col_id = col_id
|
22
|
+
options.each do |o|
|
23
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
24
|
+
end
|
25
|
+
@filter = Axlsx.const_get(Axlsx.camel(filter_type)).new(options)
|
26
|
+
yield @filter if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
# Zero-based index indicating the AutoFilter column to which this filter information applies.
|
30
|
+
# @return [Integer]
|
31
|
+
attr_reader :col_id
|
32
|
+
|
33
|
+
# The actual filter being dealt with here
|
34
|
+
# This could be any one of the allowed filter types
|
35
|
+
attr_reader :filter
|
36
|
+
|
37
|
+
# Flag indicating whether the filter button is visible.
|
38
|
+
# When the cell containing the filter button is merged with another cell,
|
39
|
+
# the filter button can be hidden, and not drawn.
|
40
|
+
# @return [Boolean]
|
41
|
+
def show_button
|
42
|
+
@show_button ||= true
|
43
|
+
end
|
44
|
+
|
45
|
+
# Flag indicating whether the AutoFilter button for this column is hidden.
|
46
|
+
# @return [Boolean]
|
47
|
+
def hidden_button
|
48
|
+
@hidden_button ||= false
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sets the col_id attribute for this filter column.
|
52
|
+
# @param [Integer | Cell] column_index The zero based index of the column to which this filter applies.
|
53
|
+
# When you specify a cell, the column index will be read off the cell
|
54
|
+
# @return [Integer]
|
55
|
+
def col_id=(column_index)
|
56
|
+
column_index = column_index.col if column_index.is_a?(Cell)
|
57
|
+
Axlsx.validate_unsigned_int column_index
|
58
|
+
@col_id = column_index
|
59
|
+
end
|
60
|
+
|
61
|
+
# Apply the filters for this column
|
62
|
+
# @param [Array] row A row from a worksheet that needs to be
|
63
|
+
# filtered.
|
64
|
+
def apply(row, offset)
|
65
|
+
row.hidden = @filter.apply(row.cells[offset+col_id.to_i])
|
66
|
+
end
|
67
|
+
# @param [Boolean] hidden Flag indicating whether the AutoFilter button for this column is hidden.
|
68
|
+
# @return [Boolean]
|
69
|
+
def hidden_button=(hidden)
|
70
|
+
Axlsx.validate_boolean hidden
|
71
|
+
@hidden_button = hidden
|
72
|
+
end
|
73
|
+
|
74
|
+
# Flag indicating whether the AutoFilter button is show. This is
|
75
|
+
# undocumented in the spec, but exists in the schema file as an
|
76
|
+
# optional attribute.
|
77
|
+
# @param [Boolean] show Show or hide the button
|
78
|
+
# @return [Boolean]
|
79
|
+
def show_button=(show)
|
80
|
+
Axlsx.validate_boolean show
|
81
|
+
@show_botton = show
|
82
|
+
end
|
83
|
+
|
84
|
+
# Serialize the object to xml
|
85
|
+
def to_xml_string(str='')
|
86
|
+
str << "<filterColumn #{serialized_attributes}>"
|
87
|
+
@filter.to_xml_string(str)
|
88
|
+
str << "</filterColumn>"
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def serialized_attributes(str='')
|
94
|
+
instance_values.each do |key, value|
|
95
|
+
if %(show_button hidden_button col_id).include? key.to_s
|
96
|
+
str << "#{Axlsx.camel(key, false)}='#{value}' "
|
97
|
+
end
|
98
|
+
end
|
99
|
+
str
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|