Module: Writexlsx::Worksheet::Autofilter
- Includes:
- Constants
- Included in:
- Writexlsx::Worksheet
- Defined in:
- lib/write_xlsx/worksheet/autofilter.rb
Overview
Autofilter-related operations extracted from Worksheet to slim the main class.
Constant Summary
Constants included from Constants
Constants::COL_MAX, Constants::ROW_MAX, Constants::SHEETNAME_MAX, Constants::STR_MAX
Instance Method Summary collapse
-
#autofilter(row1, col1 = nil, row2 = nil, col2 = nil) ⇒ Object
:call-seq: autofilter(first_row, first_col, last_row, last_col).
-
#filter_column(col, expression) ⇒ Object
Set the column filter criteria.
-
#filter_column_list(col, *tokens) ⇒ Object
Set the column filter criteria in Excel 2007 list style.
-
#prepare_filter_column(col) ⇒ Object
:nodoc:.
-
#write_auto_filter ⇒ Object
Write the
element. -
#write_autofilters ⇒ Object
Function to iterate through the columns that form part of an autofilter range and write the appropriate filters.
-
#write_custom_filter(operator, val) ⇒ Object
Write the
element. -
#write_custom_filters(*tokens) ⇒ Object
Write the
element. -
#write_filter(val) ⇒ Object
Write the
element. -
#write_filter_column(col_id, type, *filters) ⇒ Object
Write the
element. -
#write_filters(*filters) ⇒ Object
Write the
element.
Instance Method Details
#autofilter(row1, col1 = nil, row2 = nil, col2 = nil) ⇒ Object
:call-seq:
autofilter(first_row, first_col, last_row, last_col)
Set the autofilter area in the worksheet.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 17 def autofilter(row1, col1 = nil, row2 = nil, col2 = nil) if (row_col_array = row_col_notation(row1)) _row1, _col1, _row2, _col2 = row_col_array else _row1 = row1 _col1 = col1 _row2 = row2 _col2 = col2 end return if [_row1, _col1, _row2, _col2].include?(nil) # Reverse max and min values if necessary. _row1, _row2 = _row2, _row1 if _row2 < _row1 _col1, _col2 = _col2, _col1 if _col2 < _col1 @autofilter_area = convert_name_area(_row1, _col1, _row2, _col2) @autofilter_ref = xl_range(_row1, _row2, _col1, _col2) @filter_range = [_col1, _col2] # Store the filter cell positions for use in the autofit calculation. (_col1.._col2).each do |col| @filter_cells["#{_row1}:#{col}"] = 1 end end |
#filter_column(col, expression) ⇒ Object
Set the column filter criteria.
The filter_column method can be used to filter columns in a autofilter range based on simple conditions.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 48 def filter_column(col, expression) raise "Must call autofilter before filter_column" unless @autofilter_area col = prepare_filter_column(col) tokens = extract_filter_tokens(expression) raise "Incorrect number of tokens in expression '#{expression}'" unless [3, 7].include?(tokens.size) tokens = parse_filter_expression(expression, tokens) # Excel handles single or double custom filters as default filters. We need # to check for them and handle them accordingly. if tokens.size == 2 && tokens[0] == 2 # Single equality. filter_column_list(col, tokens[1]) elsif tokens.size == 5 && tokens[0] == 2 && tokens[2] == 1 && tokens[3] == 2 # Double equality with "or" operator. filter_column_list(col, tokens[1], tokens[4]) else # Non default custom filter. @filter_cols[col] = Array.new(tokens) @filter_type[col] = 0 end @filter_on = 1 end |
#filter_column_list(col, *tokens) ⇒ Object
Set the column filter criteria in Excel 2007 list style.
79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 79 def filter_column_list(col, *tokens) tokens.flatten! raise "Incorrect number of arguments to filter_column_list" if tokens.empty? raise "Must call autofilter before filter_column_list" unless @autofilter_area col = prepare_filter_column(col) @filter_cols[col] = tokens @filter_type[col] = 1 # Default style. @filter_on = 1 end |
#prepare_filter_column(col) ⇒ Object
:nodoc:
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 91 def prepare_filter_column(col) # :nodoc: # Check for a column reference in A1 notation and substitute. if col.to_s =~ /^\D/ col_letter = col # Convert col ref to a cell ref and then to a col number. _dummy, col = substitute_cellref("#{col}1") raise "Invalid column '#{col_letter}'" if col >= COL_MAX end col_first, col_last = @filter_range # Reject column if it is outside filter range. raise "Column '#{col}' outside autofilter column range (#{col_first} .. #{col_last})" if col < col_first || col > col_last col end |
#write_auto_filter ⇒ Object
Write the
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 112 def write_auto_filter # :nodoc: return unless autofilter_ref? attributes = [ ['ref', @autofilter_ref] ] if filter_on? # Autofilter defined active filters. @writer.tag_elements('autoFilter', attributes) do write_autofilters end else # Autofilter defined without active filters. @writer.empty_tag('autoFilter', attributes) end end |
#write_autofilters ⇒ Object
Function to iterate through the columns that form part of an autofilter range and write the appropriate filters.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 134 def write_autofilters # :nodoc: col1, col2 = @filter_range (col1..col2).each do |col| # Skip if column doesn't have an active filter. next unless @filter_cols[col] # Retrieve the filter tokens and write the autofilter records. tokens = @filter_cols[col] type = @filter_type[col] # Filters are relative to first column in the autofilter. write_filter_column(col - col1, type, *tokens) end end |
#write_custom_filter(operator, val) ⇒ Object
Write the
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 220 def write_custom_filter(operator, val) # :nodoc: operators = { 1 => 'lessThan', 2 => 'equal', 3 => 'lessThanOrEqual', 4 => 'greaterThan', 5 => 'notEqual', 6 => 'greaterThanOrEqual', 7 => 'startsWith', 8 => 'notStartsWith', 9 => 'endsWith', 10 => 'notEndsWith', 11 => 'contains', 12 => 'notContains', 13 => 'between', 14 => 'notBetween' } attributes = [ ['operator', operators[operator]], ['val', val] ] @writer.empty_tag('customFilter', attributes) end |
#write_custom_filters(*tokens) ⇒ Object
Write the
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 195 def write_custom_filters(*tokens) # :nodoc: if tokens.size == 2 # One filter expression only. @writer.tag_elements('customFilters') { write_custom_filter(*tokens) } else # Two filter expressions. # Check if the "join" operand is "and" or "or". attributes = if tokens[2] == 0 [['and', 1]] else [['and', 0]] end # Write the two custom filters. @writer.tag_elements('customFilters', attributes) do write_custom_filter(tokens[0], tokens[1]) write_custom_filter(tokens[3], tokens[4]) end end end |
#write_filter(val) ⇒ Object
Write the
188 189 190 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 188 def write_filter(val) # :nodoc: @writer.empty_tag('filter', [['val', val]]) end |
#write_filter_column(col_id, type, *filters) ⇒ Object
Write the
153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 153 def write_filter_column(col_id, type, *filters) # :nodoc: @writer.tag_elements('filterColumn', [['colId', col_id]]) do if type == 1 # Type == 1 is the new XLSX style filter. write_filters(*filters) else # Type == 0 is the classic "custom" filter. write_custom_filters(*filters) end end end |
#write_filters(*filters) ⇒ Object
Write the
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/write_xlsx/worksheet/autofilter.rb', line 168 def write_filters(*filters) # :nodoc: non_blanks = filters.reject { |filter| filter.to_s =~ /^blanks$/i } attributes = [] attributes = [['blank', 1]] if filters != non_blanks if filters.size == 1 && non_blanks.empty? # Special case for blank cells only. @writer.empty_tag('filters', attributes) else # General case. @writer.tag_elements('filters', attributes) do non_blanks.sort.each { |filter| write_filter(filter) } end end end |