keeguon-spreadsheet 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +619 -0
  3. data/Manifest.txt +85 -0
  4. data/bin/xlsopcodes +18 -0
  5. data/lib/parseexcel.rb +27 -0
  6. data/lib/parseexcel/parseexcel.rb +75 -0
  7. data/lib/parseexcel/parser.rb +11 -0
  8. data/lib/spreadsheet.rb +80 -0
  9. data/lib/spreadsheet/column.rb +71 -0
  10. data/lib/spreadsheet/compatibility.rb +23 -0
  11. data/lib/spreadsheet/datatypes.rb +161 -0
  12. data/lib/spreadsheet/encodings.rb +57 -0
  13. data/lib/spreadsheet/excel.rb +88 -0
  14. data/lib/spreadsheet/excel/error.rb +26 -0
  15. data/lib/spreadsheet/excel/internals.rb +458 -0
  16. data/lib/spreadsheet/excel/internals/biff5.rb +17 -0
  17. data/lib/spreadsheet/excel/internals/biff8.rb +19 -0
  18. data/lib/spreadsheet/excel/offset.rb +41 -0
  19. data/lib/spreadsheet/excel/password_hash.rb +24 -0
  20. data/lib/spreadsheet/excel/reader.rb +1302 -0
  21. data/lib/spreadsheet/excel/reader/biff5.rb +42 -0
  22. data/lib/spreadsheet/excel/reader/biff8.rb +231 -0
  23. data/lib/spreadsheet/excel/rgb.rb +122 -0
  24. data/lib/spreadsheet/excel/row.rb +98 -0
  25. data/lib/spreadsheet/excel/sst_entry.rb +46 -0
  26. data/lib/spreadsheet/excel/workbook.rb +80 -0
  27. data/lib/spreadsheet/excel/worksheet.rb +115 -0
  28. data/lib/spreadsheet/excel/writer.rb +1 -0
  29. data/lib/spreadsheet/excel/writer/biff8.rb +75 -0
  30. data/lib/spreadsheet/excel/writer/format.rb +264 -0
  31. data/lib/spreadsheet/excel/writer/n_worksheet.rb +888 -0
  32. data/lib/spreadsheet/excel/writer/workbook.rb +735 -0
  33. data/lib/spreadsheet/excel/writer/worksheet.rb +940 -0
  34. data/lib/spreadsheet/font.rb +115 -0
  35. data/lib/spreadsheet/format.rb +209 -0
  36. data/lib/spreadsheet/formula.rb +9 -0
  37. data/lib/spreadsheet/helpers.rb +11 -0
  38. data/lib/spreadsheet/link.rb +43 -0
  39. data/lib/spreadsheet/note.rb +23 -0
  40. data/lib/spreadsheet/noteObject.rb +17 -0
  41. data/lib/spreadsheet/row.rb +151 -0
  42. data/lib/spreadsheet/workbook.rb +143 -0
  43. data/lib/spreadsheet/worksheet.rb +326 -0
  44. data/lib/spreadsheet/writer.rb +30 -0
  45. data/test/data/test_adding_data_to_existing_file.xls +0 -0
  46. data/test/data/test_borders.xls +0 -0
  47. data/test/data/test_changes.xls +0 -0
  48. data/test/data/test_comment.xls +0 -0
  49. data/test/data/test_copy.xls +0 -0
  50. data/test/data/test_datetime.xls +0 -0
  51. data/test/data/test_empty.xls +0 -0
  52. data/test/data/test_formula.xls +0 -0
  53. data/test/data/test_long_sst_record.xls +0 -0
  54. data/test/data/test_margin.xls +0 -0
  55. data/test/data/test_merged_and_protected.xls +0 -0
  56. data/test/data/test_merged_cells.xls +0 -0
  57. data/test/data/test_missing_row.xls +0 -0
  58. data/test/data/test_pagesetup.xls +0 -0
  59. data/test/data/test_version_excel5.xls +0 -0
  60. data/test/data/test_version_excel95.xls +0 -0
  61. data/test/data/test_version_excel97.xls +0 -0
  62. data/test/data/test_version_excel97_2010.xls +0 -0
  63. data/test/data/test_worksheet_visibility.xls +0 -0
  64. data/test/excel/reader.rb +30 -0
  65. data/test/excel/row.rb +40 -0
  66. data/test/excel/writer/workbook.rb +95 -0
  67. data/test/excel/writer/worksheet.rb +81 -0
  68. data/test/font.rb +163 -0
  69. data/test/format.rb +95 -0
  70. data/test/integration.rb +1390 -0
  71. data/test/row.rb +33 -0
  72. data/test/suite.rb +18 -0
  73. data/test/workbook.rb +55 -0
  74. data/test/workbook_protection.rb +19 -0
  75. data/test/worksheet.rb +112 -0
  76. metadata +148 -0
@@ -0,0 +1,115 @@
1
+ # encoding: utf-8
2
+ require 'spreadsheet/datatypes'
3
+ require 'spreadsheet/encodings'
4
+
5
+ module Spreadsheet
6
+ ##
7
+ # Font formatting data
8
+ class Font
9
+ include Spreadsheet::Datatypes
10
+ include Spreadsheet::Encodings
11
+ attr_accessor :name
12
+ ##
13
+ # You can set the following boolean Font attributes
14
+ # * #italic
15
+ # * #strikeout
16
+ # * #outline
17
+ # * #shadow
18
+ boolean :italic, :strikeout, :outline, :shadow
19
+ ##
20
+ # Font color
21
+ colors :color
22
+ ##
23
+ # Font weight
24
+ # Valid values: :normal, :bold or any positive Integer.
25
+ # In Excel:
26
+ # 100 <= weight <= 1000
27
+ # :bold => 700
28
+ # :normal => 400
29
+ # Default: :normal
30
+ enum :weight, :normal, :bold, Integer, :bold => :b
31
+ ##
32
+ # Escapement
33
+ # Valid values: :normal, :superscript or :subscript.
34
+ # Default: :normal
35
+ enum :escapement, :normal, :superscript, :subscript,
36
+ :subscript => :sub,
37
+ :superscript => :super
38
+ # Font size
39
+ # Valid values: Any positive Integer.
40
+ # Default: 10
41
+ enum :size, 10, Numeric
42
+ # Underline type
43
+ # Valid values: :none, :single, :double, :single_accounting and
44
+ # :double_accounting.
45
+ # Default: :none
46
+ enum :underline, :none, :single, :double,
47
+ :single_accounting, :double_accounting,
48
+ :single => true
49
+ # Font Family
50
+ # Valid values: :none, :roman, :swiss, :modern, :script, :decorative
51
+ # Default: :none
52
+ enum :family, :none, :roman, :swiss, :modern, :script, :decorative
53
+ # Font Family
54
+ # Valid values: :default, :iso_latin1, :symbol, :apple_roman, :shift_jis,
55
+ # :korean_hangul, :korean_johab, :chinese_simplified,
56
+ # :chinese_traditional, :greek, :turkish, :vietnamese,
57
+ # :hebrew, :arabic, :cyrillic, :thai, :iso_latin2, :oem_latin1
58
+ # Default: :default
59
+ enum :encoding, :default, :iso_latin1, :symbol, :apple_roman, :shift_jis,
60
+ :korean_hangul, :korean_johab, :chinese_simplified,
61
+ :chinese_traditional, :greek, :turkish, :vietnamese,
62
+ :hebrew, :arabic, :baltic, :cyrillic, :thai, :iso_latin2,
63
+ :oem_latin1
64
+ def initialize name, opts={}
65
+ self.name = name
66
+ @color = :text
67
+ @previous_fast_key = nil
68
+ @size = nil
69
+ @weight = nil
70
+ @italic = nil
71
+ @strikeout = nil
72
+ @outline = nil
73
+ @shadow = nil
74
+ @escapement = nil
75
+ @underline = nil
76
+ @family = nil
77
+ @encoding = nil
78
+ opts.each do |key, val|
79
+ self.send "#{key}=", val
80
+ end
81
+ end
82
+ ##
83
+ # Sets #weight to :bold if(_bool_), :normal otherwise.
84
+ def bold= bool
85
+ self.weight = bool ? :bold : nil
86
+ end
87
+ def key # :nodoc:
88
+ fk = fast_key
89
+ return @key if @previous_fast_key == fk
90
+ @previous_fast_key = fk
91
+ @key = build_key
92
+ end
93
+ private
94
+ def build_key # :nodoc:
95
+ underscore = client('_', 'UTF-8')
96
+ key = []
97
+ key << @name
98
+ key << underscore << client(size.to_s, 'US-ASCII')
99
+ key << underscore << client(weight.to_s, 'US-ASCII')
100
+ key << client('_italic', 'UTF-8') if italic?
101
+ key << client('_strikeout', 'UTF-8') if strikeout?
102
+ key << client('_outline', 'UTF-8') if outline?
103
+ key << client('_shadow', 'UTF-8') if shadow?
104
+ key << underscore << client(escapement.to_s, 'US-ASCII')
105
+ key << underscore << client(underline.to_s, 'US-ASCII')
106
+ key << underscore << client(color.to_s, 'US-ASCII')
107
+ key << underscore << client(family.to_s, 'US-ASCII')
108
+ key << underscore << client(encoding.to_s, 'US-ASCII')
109
+ key.join("")
110
+ end
111
+ def fast_key
112
+ [@name, @size, @weight, @italic, @strikeout, @outline, @shadow, @escapement, @underline, @color, @family, @encoding]
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,209 @@
1
+ # encoding: utf-8
2
+ require 'spreadsheet/datatypes'
3
+ require 'spreadsheet/encodings'
4
+ require 'spreadsheet/font'
5
+
6
+ module Spreadsheet
7
+ ##
8
+ # Formatting data
9
+ class Format
10
+ include Spreadsheet::Datatypes
11
+ include Spreadsheet::Encodings
12
+ ##
13
+ # You can set the following boolean attributes:
14
+ # #cross_down:: Draws a Line from the top-left to the bottom-right
15
+ # corner of a cell.
16
+ # #cross_up:: Draws a Line from the bottom-left to the top-right
17
+ # corner of a cell.
18
+ # #hidden:: The cell is hidden.
19
+ # #locked:: The cell is locked.
20
+ # #merge_range:: The cell is in a merged range.
21
+ # #shrink:: Shrink the contents to fit the cell.
22
+ # #text_justlast:: Force the last line of a cell to be justified. This
23
+ # probably makes sense if horizontal_align = :justify
24
+ # #left:: Apply a border style to the left of the cell.
25
+ # #right:: Apply a border style to the right of the cell.
26
+ # #top:: Apply a border style at the top of the cell.
27
+ # #bottom:: Apply a border style at the bottom of the cell.
28
+ # #rotation_stacked:: Characters in the cell are stacked on top of each
29
+ # other. Excel will ignore other rotation values if
30
+ # this is set.
31
+ boolean :cross_down, :cross_up, :hidden, :locked,
32
+ :merge_range, :shrink, :text_justlast, :text_wrap,
33
+ :rotation_stacked
34
+ ##
35
+ # Border line styles
36
+ # Valid values: :none, :thin, :medium, :dashed, :dotted, :thick,
37
+ # :double, :hair, :medium_dashed, :thin_dash_dotted,
38
+ # :medium_dash_dotted, :thin_dash_dot_dotted,
39
+ # :medium_dash_dot_dotted, :slanted_medium_dash_dotted
40
+ # Default: :none
41
+ styles = [ :thin, :medium, :dashed, :dotted, :thick,
42
+ :double, :hair, :medium_dashed, :thin_dash_dotted,
43
+ :medium_dash_dotted, :thin_dash_dot_dotted,
44
+ :medium_dash_dot_dotted, :slanted_medium_dash_dotted ]
45
+ enum :left, :none, *styles
46
+ enum :right, :none, *styles
47
+ enum :top, :none, *styles
48
+ enum :bottom, :none, *styles
49
+
50
+ ##
51
+ # Color attributes
52
+ colors :bottom_color, :top_color, :left_color, :right_color,
53
+ :pattern_fg_color, :pattern_bg_color,
54
+ :diagonal_color
55
+ ##
56
+ # Text direction
57
+ # Valid values: :context, :left_to_right, :right_to_left
58
+ # Default: :context
59
+ enum :text_direction, :context, :left_to_right, :right_to_left,
60
+ :left_to_right => [:ltr, :l2r],
61
+ :right_to_left => [:rtl, :r2l]
62
+ alias :reading_order :text_direction
63
+ alias :reading_order= :text_direction=
64
+ ##
65
+ # Indentation level
66
+ enum :indent_level, 0, Integer
67
+ alias :indent :indent_level
68
+ alias :indent= :indent_level=
69
+ ##
70
+ # Horizontal alignment
71
+ # Valid values: :default, :left, :center, :right, :fill, :justify, :merge,
72
+ # :distributed
73
+ # Default: :default
74
+ enum :horizontal_align, :default, :left, :center, :right, :fill, :justify,
75
+ :merge, :distributed,
76
+ :center => :centre,
77
+ :merge => [ :center_across, :centre_across ],
78
+ :distributed => :equal_space
79
+ ##
80
+ # Vertical alignment
81
+ # Valid values: :bottom, :top, :middle, :justify, :distributed
82
+ # Default: :bottom
83
+ enum :vertical_align, :bottom, :top, :middle, :justify, :distributed,
84
+ :distributed => [:vdistributed, :vequal_space, :equal_space],
85
+ :justify => :vjustify,
86
+ :middle => [:vcenter, :vcentre, :center, :centre]
87
+ attr_accessor :font, :number_format, :name, :pattern, :used_merge
88
+ ##
89
+ # Text rotation
90
+ attr_reader :rotation
91
+ def initialize opts={}
92
+ @font = Font.new client("Arial", 'UTF-8'), :family => :swiss
93
+ @number_format = client 'GENERAL', 'UTF-8'
94
+ @rotation = 0
95
+ @pattern = 0
96
+ @bottom_color = :black
97
+ @top_color = :black
98
+ @left_color = :black
99
+ @right_color = :black
100
+ @diagonal_color = :black
101
+ @pattern_fg_color = :border
102
+ @pattern_bg_color = :pattern_bg
103
+ @regexes = {
104
+ :date => Regexp.new(client("[YMD]", 'UTF-8')),
105
+ :date_or_time => Regexp.new(client("[hmsYMD]", 'UTF-8')),
106
+ :datetime => Regexp.new(client("([YMD].*[HS])|([HS].*[YMD])", 'UTF-8')),
107
+ :time => Regexp.new(client("[hms]", 'UTF-8')),
108
+ :number => Regexp.new(client("[\#]", 'UTF-8'))
109
+ }
110
+
111
+ # Temp code to prevent merged formats in non-merged cells.
112
+ @used_merge = 0
113
+ update_format(opts)
114
+
115
+ yield self if block_given?
116
+ end
117
+
118
+ def update_format(opts = {})
119
+ opts.each do |attribute, value|
120
+ writer = "#{attribute}="
121
+ @font.respond_to?(writer) ? @font.send(writer,value) : self.send(writer, value)
122
+ end
123
+ self
124
+ end
125
+
126
+ ##
127
+ # Combined method for both horizontal and vertical alignment. Sets the
128
+ # first valid value (e.g. Format#align = :justify only sets the horizontal
129
+ # alignment. Use one of the aliases prefixed with :v if you need to
130
+ # disambiguate.)
131
+ #
132
+ # This is essentially a backward-compatibility method and may be removed at
133
+ # some point in the future.
134
+ def align= location
135
+ self.horizontal_align = location
136
+ rescue ArgumentError
137
+ self.vertical_align = location rescue ArgumentError
138
+ end
139
+ ##
140
+ # Returns an Array containing the line styles of the four borders:
141
+ # bottom, top, right, left
142
+ def border
143
+ [bottom, top, right, left]
144
+ end
145
+ ##
146
+ # Set same line style on all four borders at once (left, right, top, bottom)
147
+ def border=(style)
148
+ [:bottom=, :top=, :right=, :left=].each do |writer| send writer, style end
149
+ end
150
+ ##
151
+ # Returns an Array containing the colors of the four borders:
152
+ # bottom, top, right, left
153
+ def border_color
154
+ [@bottom_color,@top_color,@right_color,@left_color]
155
+ end
156
+ ##
157
+ # Set all four border colors to _color_ (left, right, top, bottom)
158
+ def border_color=(color)
159
+ [:bottom_color=, :top_color=, :right_color=, :left_color=].each do |writer|
160
+ send writer, color end
161
+ end
162
+ ##
163
+ # Set the Text rotation
164
+ # Valid values: Integers from -90 to 90,
165
+ # or :stacked (sets #rotation_stacked to true)
166
+ def rotation=(rot)
167
+ if rot.to_s.downcase == 'stacked'
168
+ @rotation_stacked = true
169
+ @rotation = 0
170
+ elsif rot.kind_of?(Integer)
171
+ @rotation_stacked = false
172
+ @rotation = rot % 360
173
+ else
174
+ raise TypeError, "rotation value must be an Integer or the String 'stacked'"
175
+ end
176
+ end
177
+ ##
178
+ # Backward compatibility method. May disappear at some point in the future.
179
+ def center_across!
180
+ self.horizontal_align = :merge
181
+ end
182
+ alias :merge! :center_across!
183
+ ##
184
+ # Is the cell formatted as a Date?
185
+ def date?
186
+ !number? && !!@regexes[:date].match(@number_format.to_s)
187
+ end
188
+ ##
189
+ # Is the cell formatted as a Date or Time?
190
+ def date_or_time?
191
+ !number? && !!@regexes[:date_or_time].match(@number_format.to_s)
192
+ end
193
+ ##
194
+ # Is the cell formatted as a DateTime?
195
+ def datetime?
196
+ !number? && !!@regexes[:datetime].match(@number_format.to_s)
197
+ end
198
+ ##
199
+ # Is the cell formatted as a Time?
200
+ def time?
201
+ !number? && !!@regexes[:time].match(@number_format.to_s)
202
+ end
203
+ ##
204
+ # Is the cell formatted as a number?
205
+ def number?
206
+ !!@regexes[:number].match(@number_format.to_s)
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,9 @@
1
+ module Spreadsheet
2
+ ##
3
+ # Formula implementation. At the moment this is just a placeholder.
4
+ # You may access the last calculated #value, other attributes are needed for
5
+ # writing the Formula back into modified Excel Files.
6
+ class Formula
7
+ attr_accessor :data, :value, :shared
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Spreadsheet
2
+ module Helpers
3
+ def rcompact(array)
4
+ while !array.empty? && array.last.nil?
5
+ array.pop
6
+ end
7
+ array
8
+ end
9
+ module_function :rcompact
10
+ end
11
+ end
@@ -0,0 +1,43 @@
1
+ require 'uri'
2
+ require 'spreadsheet/encodings'
3
+
4
+ module Spreadsheet
5
+ ##
6
+ # The Link class. Is a Subclass of String, which lets you treat a Cell that
7
+ # contains a Link just as if it was a String (containing the link's description
8
+ # if there is one or the url with fragment otherwise), but gives you access
9
+ # to the url, fragment and target_frame if you need it.
10
+ #
11
+ #
12
+ # Interesting Attributes
13
+ # #url :: The Uniform Resource Location this Link points to.
14
+ # #fragment :: Also called text mark: http://example.com/page.html#fragment
15
+ # #target_frame :: Which frame a Link should be opened in, should also support
16
+ # the special frames _blank, _parent, _self and _top.
17
+ # #dos :: Excel may store a DOS-Filename together with the long
18
+ # Filename introduced in VFAT. You probably will not need this,
19
+ # but if you do, here is where you can find it.
20
+ class Link < String
21
+ include Encodings
22
+ attr_accessor :target_frame, :url, :dos, :fragment
23
+ def initialize url='', description=url, fragment=nil
24
+ super description
25
+ @url = url
26
+ @fragment = fragment
27
+ end
28
+ ##
29
+ # The Url with the fragment appended if present.
30
+ def href
31
+ href = (@url || @dos).to_s.dup
32
+ if @fragment
33
+ href << client('#', 'UTF-8') << @fragment
34
+ end
35
+ href
36
+ end
37
+ ##
38
+ # Attempts to parse the output of href. May raise a URI::InvalidURIError
39
+ def to_uri
40
+ URI.parse href
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ require 'spreadsheet/encodings'
2
+
3
+ module Spreadsheet
4
+ ##
5
+ # The Note class is a Subclass of String and represents a comment/note/annotation
6
+ # someone made to a cell.
7
+ #
8
+ #
9
+ # Interesting Attributes
10
+ # #author :: The name of the author who wrote the note
11
+ class Note
12
+ include Encodings
13
+ attr_accessor :author, :length, :objID, :row, :col, :text
14
+ def initialize
15
+ @author = nil
16
+ @length = 0
17
+ @objID = nil
18
+ @row = -1
19
+ @col = -1
20
+ @text = ""
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ require 'spreadsheet/encodings'
2
+
3
+ module Spreadsheet
4
+ ##
5
+ # The NoteObject class is made to handle the text output from the
6
+ # object, txo, continue records which contain a comment's text record.
7
+ #
8
+ #
9
+ class NoteObject
10
+ include Encodings
11
+ attr_accessor :objID, :text
12
+ def initialize
13
+ @objID = -1
14
+ @text = ""
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,151 @@
1
+ require 'spreadsheet/helpers'
2
+
3
+ module Spreadsheet
4
+ ##
5
+ # The Row class. Encapsulates Cell data and formatting.
6
+ # Since Row is a subclass of Array, you may use all the standard Array methods
7
+ # to manipulate a Row.
8
+ # By convention, Row#at will give you raw values, while Row#[] may be
9
+ # overridden to return enriched data if necessary (see also the Date- and
10
+ # DateTime-handling in Excel::Row#[]
11
+ #
12
+ # Useful Attributes are:
13
+ # #idx:: The 0-based index of this Row in its Worksheet.
14
+ # #formats:: A parallel array containing Formatting information for
15
+ # all cells stored in a Row.
16
+ # #default_format:: The default Format used when writing a Cell if no explicit
17
+ # Format is stored in #formats for the cell.
18
+ # #height:: The height of this Row in points (defaults to 12).
19
+ class Row < Array
20
+ include Datatypes
21
+ class << self
22
+ def format_updater *keys
23
+ keys.each do |key|
24
+ unless instance_methods.include? "unupdated_#{key}="
25
+ alias_method :"unupdated_#{key}=", :"#{key}="
26
+ define_method "#{key}=" do |value|
27
+ send "unupdated_#{key}=", value
28
+ @worksheet.row_updated @idx, self if @worksheet
29
+ value
30
+ end
31
+ end
32
+ end
33
+ end
34
+ def updater *keys
35
+ keys.each do |key|
36
+ ## Passing blocks to methods defined with define_method is not possible
37
+ # in Ruby 1.8:
38
+ # http://groups.google.com/group/ruby-talk-google/msg/778184912b769e5f
39
+ # use class_eval as suggested by someone else in
40
+ # http://rubyforge.org/tracker/index.php?func=detail&aid=25732&group_id=678&atid=2677
41
+ class_eval <<-SRC, __FILE__, __LINE__
42
+ def #{key}(*args)
43
+ res = super(*args)
44
+ @worksheet.row_updated @idx, self if @worksheet
45
+ res
46
+ end
47
+ SRC
48
+ end
49
+ end
50
+ end
51
+ attr_reader :formats
52
+ attr_accessor :idx, :height, :worksheet
53
+ boolean :hidden, :collapsed
54
+ enum :outline_level, 0, Integer
55
+ updater :[]=, :clear, :concat, :delete, :delete_if, :fill, :insert, :map!,
56
+ :pop, :push, :reject!, :replace, :reverse!, :shift, :slice!,
57
+ :sort!, :uniq!, :unshift
58
+ format_updater :collapsed, :height, :hidden, :outline_level
59
+ def initialize worksheet, idx, cells=[]
60
+ @default_format = nil
61
+ @worksheet = worksheet
62
+ @idx = idx
63
+ super cells
64
+ @formats = []
65
+ @height = 12.1
66
+ end
67
+ ##
68
+ # The default Format of this Row, if you have set one.
69
+ # Returns the Worksheet's default or the Workbook's default Format otherwise.
70
+ def default_format
71
+ @default_format || @worksheet.default_format || @workbook.default_format
72
+ end
73
+ ##
74
+ # Set the default Format used when writing a Cell if no explicit Format is
75
+ # stored for the cell.
76
+ def default_format= format
77
+ @worksheet.add_format format if @worksheet
78
+ @default_format = format
79
+ end
80
+ format_updater :default_format
81
+ ##
82
+ # #first_used the 0-based index of the first non-blank Cell.
83
+ def first_used
84
+ [ index_of_first(self), index_of_first(@formats) ].compact.min
85
+ end
86
+ ##
87
+ # The Format for the Cell at _idx_ (0-based), or the first valid Format in
88
+ # Row#default_format, Column#default_format and Worksheet#default_format.
89
+ def format idx
90
+ @formats[idx] || @default_format \
91
+ || @worksheet.column(idx).default_format if @worksheet
92
+ end
93
+ ##
94
+ # Returns a copy of self with nil-values appended for empty cells that have
95
+ # an associated Format.
96
+ # This is primarily a helper-function for the writer classes.
97
+ def formatted
98
+ copy = dup
99
+ Helpers.rcompact(@formats)
100
+ if copy.length < @formats.size
101
+ copy.concat Array.new(@formats.size - copy.length)
102
+ end
103
+ copy
104
+ end
105
+ ##
106
+ # Same as Row#size, but takes into account formatted empty cells
107
+ def formatted_size
108
+ Helpers.rcompact(@formats)
109
+ sz = size
110
+ fs = @formats.size
111
+ fs > sz ? fs : sz
112
+ end
113
+ ##
114
+ # #first_unused (really last used + 1) - the 0-based index of the first of
115
+ # all remaining contiguous blank Cells.
116
+ alias :first_unused :formatted_size
117
+ def inspect
118
+ variables = instance_variables.collect do |name|
119
+ "%s=%s" % [name, instance_variable_get(name)]
120
+ end.join(' ')
121
+ sprintf "#<%s:0x%014x %s %s>", self.class, object_id, variables, super
122
+ end
123
+ ##
124
+ # Set the Format for the Cell at _idx_ (0-based).
125
+ def set_format idx, fmt
126
+ @formats[idx] = fmt
127
+ @worksheet.add_format fmt
128
+ @worksheet.row_updated @idx, self if @worksheet
129
+ fmt
130
+ end
131
+
132
+ def update_format(idx, opts = {})
133
+ if @formats[idx]
134
+ @formats[idx].update_format(opts)
135
+ else
136
+ fmt = default_format.clone
137
+ fmt.font = fmt.font.clone
138
+ @formats[idx] = fmt.update_format(opts)
139
+ end
140
+ @worksheet.add_format @formats[idx]
141
+ @worksheet.row_updated @idx, self if @worksheet
142
+ end
143
+
144
+ private
145
+ def index_of_first ary # :nodoc:
146
+ if first = ary.find do |elm| !elm.nil? end
147
+ ary.index first
148
+ end
149
+ end
150
+ end
151
+ end