File: format.rb

package info (click to toggle)
ruby-spreadsheet 1.3.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,980 kB
  • sloc: ruby: 6,939; makefile: 10
file content (233 lines) | stat: -rw-r--r-- 7,786 bytes parent folder | download
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
require "spreadsheet/datatypes"
require "spreadsheet/encodings"
require "spreadsheet/font"

module Spreadsheet
  ##
  # Formatting data
  class Format
    include Spreadsheet::Datatypes
    include Spreadsheet::Encodings
    ##
    # You can set the following boolean attributes:
    # #cross_down::       Draws a Line from the top-left to the bottom-right
    #                     corner of a cell.
    # #cross_up::         Draws a Line from the bottom-left to the top-right
    #                     corner of a cell.
    # #hidden::           The cell is hidden.
    # #locked::           The cell is locked.
    # #merge_range::      The cell is in a merged range.
    # #shrink::           Shrink the contents to fit the cell.
    # #text_justlast::    Force the last line of a cell to be justified. This
    #                     probably makes sense if horizontal_align = :justify
    # #left::             Apply a border style to the left of the cell.
    # #right::            Apply a border style to the right of the cell.
    # #top::              Apply a border style at the top of the cell.
    # #bottom::           Apply a border style at the bottom of the cell.
    # #rotation_stacked:: Characters in the cell are stacked on top of each
    #                     other. Excel will ignore other rotation values if
    #                     this is set.
    boolean :cross_down, :cross_up, :hidden, :locked,
      :merge_range, :shrink, :text_justlast, :text_wrap,
      :rotation_stacked
    ##
    # Border line styles
    # Valid values: :none, :thin, :medium, :dashed, :dotted, :thick,
    #               :double, :hair, :medium_dashed, :thin_dash_dotted,
    #               :medium_dash_dotted, :thin_dash_dot_dotted,
    #               :medium_dash_dot_dotted, :slanted_medium_dash_dotted
    # Default:			:none
    styles = [:thin, :medium, :dashed, :dotted, :thick,
      :double, :hair, :medium_dashed, :thin_dash_dotted,
      :medium_dash_dotted, :thin_dash_dot_dotted,
      :medium_dash_dot_dotted, :slanted_medium_dash_dotted]
    enum :left,	:none, *styles
    enum :right,	:none, *styles
    enum :top,	:none, *styles
    enum :bottom,	:none, *styles

    ##
    # Color attributes
    colors :bottom_color, :top_color, :left_color, :right_color,
      :pattern_fg_color, :pattern_bg_color,
      :diagonal_color
    ##
    # Text direction
    # Valid values: :context, :left_to_right, :right_to_left
    # Default:      :context
    enum :text_direction, :context, :left_to_right, :right_to_left,
      left_to_right: [:ltr, :l2r],
      right_to_left: [:rtl, :r2l]
    alias_method :reading_order, :text_direction
    alias_method :reading_order=, :text_direction=
    ##
    # Indentation level
    enum :indent_level, 0, Integer
    alias_method :indent, :indent_level
    alias_method :indent=, :indent_level=
    ##
    # Horizontal alignment
    # Valid values: :default, :left, :center, :right, :fill, :justify, :merge,
    #               :distributed
    # Default:      :default
    enum :horizontal_align, :default, :left, :center, :right, :fill, :justify,
      :merge, :distributed,
      center: :centre,
      merge: [:center_across, :centre_across],
      distributed: :equal_space
    ##
    # Vertical alignment
    # Valid values: :bottom, :top, :middle, :justify, :distributed
    # Default:      :bottom
    enum :vertical_align, :bottom, :top, :middle, :justify, :distributed,
      distributed: [:vdistributed, :vequal_space, :equal_space],
      justify: :vjustify,
      middle: [:vcenter, :vcentre, :center, :centre]
    attr_accessor :font, :number_format, :name, :pattern, :used_merge
    ##
    # Text rotation
    attr_reader :rotation
    def initialize opts = {}
      @font = Font.new client("Arial", "UTF-8"), family: :swiss
      @number_format = client "GENERAL", "UTF-8"
      @rotation = 0
      @pattern = 0
      @bottom_color = :black
      @top_color = :black
      @left_color = :black
      @right_color = :black
      @diagonal_color = :black
      @pattern_fg_color = :border
      @pattern_bg_color = :pattern_bg
      @regexes = {
        date: Regexp.new(client("[YMD]|d{2}|m{3}|y{2}", "UTF-8")),
        date_or_time: Regexp.new(client("[hmsYMD]", "UTF-8")),
        datetime: Regexp.new(client("([YMD].*[HS])|([HS].*[YMD])", "UTF-8")),
        time: Regexp.new(client("[hms]", "UTF-8")),
        number: Regexp.new(client("([#]|0+)", "UTF-8")),
        locale: Regexp.new(client(/\A\[\$-\S+\]/.to_s, "UTF-8"))
      }

      # Temp code to prevent merged formats in non-merged cells.
      @used_merge = 0
      update_format(opts)

      yield self if block_given?
    end

    def update_format(opts = {})
      opts.each do |attribute, value|
        writer = "#{attribute}="
        @font.respond_to?(writer) ? @font.send(writer, value) : send(writer, value)
      end
      self
    end

    ##
    # Combined method for both horizontal and vertical alignment. Sets the
    # first valid value (e.g. Format#align = :justify only sets the horizontal
    # alignment. Use one of the aliases prefixed with :v if you need to
    # disambiguate.)
    #
    # This is essentially a backward-compatibility method and may be removed at
    # some point in the future.
    def align= location
      self.horizontal_align = location
    rescue ArgumentError
      self.vertical_align = begin
        location
      rescue
        ArgumentError
      end
    end

    ##
    # Returns an Array containing the line styles of the four borders:
    # bottom, top, right, left
    def border
      [bottom, top, right, left]
    end

    ##
    # Set same line style on all four borders at once (left, right, top, bottom)
    def border=(style)
      [:bottom=, :top=, :right=, :left=].each { |writer| send writer, style }
    end

    ##
    # Returns an Array containing the colors of the four borders:
    # bottom, top, right, left
    def border_color
      [@bottom_color, @top_color, @right_color, @left_color]
    end

    ##
    # Set all four border colors to _color_ (left, right, top, bottom)
    def border_color=(color)
      [:bottom_color=, :top_color=, :right_color=, :left_color=].each do |writer|
        send writer, color
      end
    end

    ##
    # Set the Text rotation
    # Valid values: Integers from -90 to 90,
    # or :stacked (sets #rotation_stacked to true)
    def rotation=(rot)
      if rot.to_s.downcase == "stacked"
        @rotation_stacked = true
        @rotation = 0
      elsif rot.is_a?(Integer)
        @rotation_stacked = false
        @rotation = rot % 360
      else
        raise TypeError, "rotation value must be an Integer or the String 'stacked'"
      end
    end

    ##
    # Backward compatibility method. May disappear at some point in the future.
    def center_across!
      self.horizontal_align = :merge
    end
    alias_method :merge!, :center_across!
    ##
    # Is the cell formatted as a Date?
    def date?
      !number? && matches_format?(:date)
    end

    ##
    # Is the cell formatted as a Date or Time?
    def date_or_time?
      !number? && matches_format?(:date_or_time)
    end

    ##
    # Is the cell formatted as a DateTime?
    def datetime?
      !number? && matches_format?(:datetime)
    end

    ##
    # Is the cell formatted as a Time?
    def time?
      !number? && matches_format?(:time)
    end

    ##
    # Is the cell formatted as a number?
    def number?
      matches_format?(:number)
    end

    ##
    # Does the cell match a particular preset format?
    def matches_format?(name)
      # Excel number formats may optionally include a locale identifier like this:
      #   [$-409]
      format = @number_format.to_s.sub(@regexes[:locale], "")
      !!@regexes[name].match(format)
    end
  end
end