summaryrefslogtreecommitdiffhomepage
path: root/lib/axlsx/workbook/worksheet/data_validation.rb
blob: a9e7ea9ff177dd7f71f21e535a41c1e811e40831 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# frozen_string_literal: true

module Axlsx
  # Data validation allows the validation of cell data
  #
  # @note The recommended way to manage data validations is via Worksheet#add_data_validation
  # @see Worksheet#add_data_validation
  class DataValidation
    include Axlsx::OptionsParser

    # Creates a new {DataValidation} object
    # @option options [String] formula1
    # @option options [String] formula2
    # @option options [Boolean] allowBlank - A boolean value indicating whether the data validation allows the use of empty or blank entries.
    # @option options [String] error - Message text of error alert.
    # @option options [Symbol] errorStyle - The style of error alert used for this data validation.
    # @option options [String] errorTitle - Title bar text of error alert.
    # @option options [Symbol] operator - The relational operator used with this data validation.
    # @option options [String] prompt - Message text of input prompt.
    # @option options [String] promptTitle - Title bar text of input prompt.
    # @option options [Boolean] showDropDown - A boolean value indicating whether to display a dropdown combo box for a list type data validation. Be careful: It has an inverted logic, false shows the dropdown list! You should use hideDropDown instead.
    # @option options [Boolean] hideDropDown - A boolean value indicating whether to hide the dropdown combo box for a list type data validation. Defaults to `false` (meaning the dropdown is visible by default).
    # @option options [Boolean] showErrorMessage - A boolean value indicating whether to display the error alert message when an invalid value has been entered, according to the criteria specified.
    # @option options [Boolean] showInputMessage - A boolean value indicating whether to display the input prompt message.
    # @option options [String] sqref - Range over which data validation is applied, in "A1:B2" format.
    # @option options [Symbol] type - The type of data validation.
    def initialize(options = {})
      # defaults
      @formula1 = @formula2 = @error = @errorTitle = @operator = @prompt = @promptTitle = @sqref = nil
      @allowBlank = @showErrorMessage = true
      @showDropDown = @showInputMessage = false
      @type = :none
      @errorStyle = :stop
      parse_options options
    end

    # instance values that must be serialized as their own elements - e.g. not attributes.
    CHILD_ELEMENTS = [:formula1, :formula2].freeze

    # Formula1
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [String]
    # default nil
    attr_reader :formula1

    # Formula2
    # Available for type whole, decimal, date, time, textLength
    # @see type
    # @return [String]
    # default nil
    attr_reader :formula2

    # Allow Blank
    # A boolean value indicating whether the data validation allows the use of empty or blank
    # entries. 1 means empty entries are OK and do not violate the validation constraints.
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [Boolean]
    # default true
    attr_reader :allowBlank

    # Error Message
    # Message text of error alert.
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [String]
    # default nil
    attr_reader :error

    # Error Style (ST_DataValidationErrorStyle)
    # The style of error alert used for this data validation.
    # Options are:
    #  * information: This data validation error style uses an information icon in the error alert.
    #  * stop: This data validation error style uses a stop icon in the error alert.
    #  * warning: This data validation error style uses a warning icon in the error alert.
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [Symbol]
    # default :stop
    attr_reader :errorStyle

    # Error Title
    # Title bar text of error alert.
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [String]
    # default nil
    attr_reader :errorTitle

    # Operator (ST_DataValidationOperator)
    # The relational operator used with this data validation.
    # Options are:
    #  * between: Data validation which checks if a value is between two other values.
    #  * equal: Data validation which checks if a value is equal to a specified value.
    #  * greater_than: Data validation which checks if a value is greater than a specified value.
    #  * greater_than_or_equal: Data validation which checks if a value is greater than or equal to a specified value.
    #  * less_than: Data validation which checks if a value is less than a specified value.
    #  * less_than_or_equal: Data validation which checks if a value is less than or equal to a specified value.
    #  * not_between: Data validation which checks if a value is not between two other values.
    #  * not_equal: Data validation which checks if a value is not equal to a specified value.
    # Available for type whole, decimal, date, time, textLength
    # @see type
    # @return [Symbol]
    # default nil
    attr_reader :operator

    # Input prompt
    # Message text of input prompt.
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [String]
    # default nil
    attr_reader :prompt

    # Prompt title
    # Title bar text of input prompt.
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [String]
    # default nil
    attr_reader :promptTitle

    # Show drop down
    # A boolean value indicating whether to display a dropdown combo box for a list type data
    # validation. Be careful: It has an inverted logic, false shows the dropdown list!
    # Available for type list
    # @see type
    # @return [Boolean]
    # default false
    attr_reader :showDropDown

    # Hide drop down
    # A boolean value indicating whether to hide a dropdown combo box for a list type data
    # validation. Defaults to `false` (meaning the dropdown is visible by default).
    # Available for type list
    # @see type
    # @return [Boolean]
    # default false
    alias :hideDropDown :showDropDown

    # Show error message
    # A boolean value indicating whether to display the error alert message when an invalid
    # value has been entered, according to the criteria specified.
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [Boolean]
    # default false
    attr_reader :showErrorMessage

    # Show input message
    # A boolean value indicating whether to display the input prompt message.
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [Boolean]
    # default false
    attr_reader :showInputMessage

    # Range over which data validation is applied, in "A1:B2" format
    # Available for type whole, decimal, date, time, textLength, list, custom
    # @see type
    # @return [String]
    # default nil
    attr_reader :sqref

    # The type (ST_DataValidationType) of data validation.
    # Options are:
    #  * custom: Data validation which uses a custom formula to check the cell value.
    #  * date: Data validation which checks for date values satisfying the given condition.
    #  * decimal: Data validation which checks for decimal values satisfying the given condition.
    #  * list: Data validation which checks for a value matching one of list of values.
    #  * none: No data validation.
    #  * textLength: Data validation which checks for text values, whose length satisfies the given condition.
    #  * time: Data validation which checks for time values satisfying the given condition.
    #  * whole: Data validation which checks for whole number values satisfying the given condition.
    # @return [Symbol]
    # default none
    attr_reader :type

    # @see formula1
    def formula1=(v); Axlsx.validate_string(v); @formula1 = v end

    # @see formula2
    def formula2=(v); Axlsx.validate_string(v); @formula2 = v end

    # @see allowBlank
    def allowBlank=(v); Axlsx.validate_boolean(v); @allowBlank = v end

    # @see error
    def error=(v); Axlsx.validate_string(v); @error = v end

    # @see errorStyle
    def errorStyle=(v); Axlsx.validate_data_validation_error_style(v); @errorStyle = v end

    # @see errorTitle
    def errorTitle=(v); Axlsx.validate_string(v); @errorTitle = v end

    # @see operator
    def operator=(v); Axlsx.validate_data_validation_operator(v); @operator = v end

    # @see prompt
    def prompt=(v); Axlsx.validate_string(v); @prompt = v end

    # @see promptTitle
    def promptTitle=(v); Axlsx.validate_string(v); @promptTitle = v end

    # @see showDropDown
    def showDropDown=(v)
      warn 'The `showDropDown` has an inverted logic, false shows the dropdown list! You should use `hideDropDown` instead.'
      Axlsx.validate_boolean(v)
      @showDropDown = v
    end

    # @see hideDropDown
    def hideDropDown=(v)
      Axlsx.validate_boolean(v)
      # It's just an alias for the showDropDown attribute, hideDropDown should set the value of the original showDropDown.
      @showDropDown = v
    end

    # @see showErrorMessage
    def showErrorMessage=(v); Axlsx.validate_boolean(v); @showErrorMessage = v end

    # @see showInputMessage
    def showInputMessage=(v); Axlsx.validate_boolean(v); @showInputMessage = v end

    # @see sqref
    def sqref=(v); Axlsx.validate_string(v); @sqref = v end

    # @see type
    def type=(v); Axlsx.validate_data_validation_type(v); @type = v end

    # Serializes the data validation
    # @param [String] str
    # @return [String]
    def to_xml_string(str = +'')
      valid_attributes = get_valid_attributes
      h = Axlsx.instance_values_for(self).select { |key, _| valid_attributes.include?(key.to_sym) && !CHILD_ELEMENTS.include?(key.to_sym) }

      str << '<dataValidation '
      h.each_with_index do |key_value, index|
        str << ' ' unless index.zero?
        str << key_value.first << '="' << Axlsx.booleanize(key_value.last).to_s << '"'
      end
      str << '>'
      str << '<formula1>' << formula1 << '</formula1>' if formula1 && valid_attributes.include?(:formula1)
      str << '<formula2>' << formula2 << '</formula2>' if formula2 && valid_attributes.include?(:formula2)
      str << '</dataValidation>'
    end

    private

    def get_valid_attributes
      attributes = [:allowBlank, :error, :errorStyle, :errorTitle, :prompt, :promptTitle, :showErrorMessage, :showInputMessage, :sqref, :type]

      if [:whole, :decimal, :data, :time, :date, :textLength].include?(@type)
        attributes << :operator << :formula1
        attributes << :formula2 if [:between, :notBetween].include?(@operator)
      elsif @type == :list
        attributes << :showDropDown << :formula1
      elsif @type == :custom
        attributes << :formula1
      end

      attributes
    end
  end
end