File: format.rb

package info (click to toggle)
ruby-spreadsheet 1.3.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,964 kB
  • sloc: ruby: 6,943; makefile: 10
file content (218 lines) | stat: -rw-r--r-- 7,936 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
# encoding: utf-8
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 :reading_order  :text_direction
    alias :reading_order= :text_direction=
    ##
    # Indentation level
    enum :indent_level, 0, Integer
    alias :indent  :indent_level
    alias :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) : self.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 = location rescue ArgumentError
    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 do |writer| send writer, style end
    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.kind_of?(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 :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