ruby-spreadsheet 0.6.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/GUIDE.txt +267 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +20 -0
- data/History.txt +307 -0
- data/LICENSE.txt +619 -0
- data/README.txt +91 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/xlsopcodes +18 -0
- data/lib/parseexcel.rb +27 -0
- data/lib/parseexcel/parseexcel.rb +75 -0
- data/lib/parseexcel/parser.rb +11 -0
- data/lib/spreadsheet.rb +79 -0
- data/lib/spreadsheet/column.rb +71 -0
- data/lib/spreadsheet/compatibility.rb +23 -0
- data/lib/spreadsheet/datatypes.rb +110 -0
- data/lib/spreadsheet/encodings.rb +46 -0
- data/lib/spreadsheet/excel.rb +88 -0
- data/lib/spreadsheet/excel/error.rb +26 -0
- data/lib/spreadsheet/excel/internals.rb +386 -0
- data/lib/spreadsheet/excel/internals/biff5.rb +17 -0
- data/lib/spreadsheet/excel/internals/biff8.rb +19 -0
- data/lib/spreadsheet/excel/offset.rb +41 -0
- data/lib/spreadsheet/excel/reader.rb +1173 -0
- data/lib/spreadsheet/excel/reader/biff5.rb +22 -0
- data/lib/spreadsheet/excel/reader/biff8.rb +193 -0
- data/lib/spreadsheet/excel/row.rb +92 -0
- data/lib/spreadsheet/excel/sst_entry.rb +46 -0
- data/lib/spreadsheet/excel/workbook.rb +80 -0
- data/lib/spreadsheet/excel/worksheet.rb +100 -0
- data/lib/spreadsheet/excel/writer.rb +1 -0
- data/lib/spreadsheet/excel/writer/biff8.rb +75 -0
- data/lib/spreadsheet/excel/writer/format.rb +253 -0
- data/lib/spreadsheet/excel/writer/workbook.rb +652 -0
- data/lib/spreadsheet/excel/writer/worksheet.rb +948 -0
- data/lib/spreadsheet/font.rb +92 -0
- data/lib/spreadsheet/format.rb +177 -0
- data/lib/spreadsheet/formula.rb +9 -0
- data/lib/spreadsheet/helpers.rb +11 -0
- data/lib/spreadsheet/link.rb +43 -0
- data/lib/spreadsheet/row.rb +132 -0
- data/lib/spreadsheet/workbook.rb +120 -0
- data/lib/spreadsheet/worksheet.rb +279 -0
- data/lib/spreadsheet/writer.rb +30 -0
- data/ruby-spreadsheet.gemspec +126 -0
- data/test/data/test_changes.xls +0 -0
- data/test/data/test_copy.xls +0 -0
- data/test/data/test_datetime.xls +0 -0
- data/test/data/test_empty.xls +0 -0
- data/test/data/test_formula.xls +0 -0
- data/test/data/test_missing_row.xls +0 -0
- data/test/data/test_version_excel5.xls +0 -0
- data/test/data/test_version_excel95.xls +0 -0
- data/test/data/test_version_excel97.xls +0 -0
- data/test/excel/row.rb +35 -0
- data/test/excel/writer/worksheet.rb +23 -0
- data/test/font.rb +163 -0
- data/test/integration.rb +1281 -0
- data/test/row.rb +33 -0
- data/test/suite.rb +14 -0
- data/test/workbook.rb +21 -0
- data/test/worksheet.rb +80 -0
- metadata +203 -0
@@ -0,0 +1,92 @@
|
|
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
|
+
opts.each do |key, val|
|
68
|
+
self.send "#{key}=", val
|
69
|
+
end
|
70
|
+
end
|
71
|
+
##
|
72
|
+
# Sets #weight to :bold if(_bool_), :normal otherwise.
|
73
|
+
def bold= bool
|
74
|
+
self.weight = bool ? :bold : nil
|
75
|
+
end
|
76
|
+
def key # :nodoc:
|
77
|
+
key = @name.dup
|
78
|
+
underscore = client('_', 'UTF-8')
|
79
|
+
key << underscore << client(size.to_s, 'US-ASCII')
|
80
|
+
key << client('_', 'UTF-8') << client(weight.to_s, 'US-ASCII')
|
81
|
+
key << client('_italic', 'UTF-8') if italic?
|
82
|
+
key << client('_strikeout', 'UTF-8') if strikeout?
|
83
|
+
key << client('_outline', 'UTF-8') if outline?
|
84
|
+
key << client('_shadow', 'UTF-8') if shadow?
|
85
|
+
key << underscore << client(escapement.to_s, 'US-ASCII')
|
86
|
+
key << underscore << client(underline.to_s, 'US-ASCII')
|
87
|
+
key << underscore << client(color.to_s, 'US-ASCII')
|
88
|
+
key << underscore << client(family.to_s, 'US-ASCII')
|
89
|
+
key << underscore << client(encoding.to_s, 'US-ASCII')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,177 @@
|
|
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:: Draw a border to the left of the cell.
|
25
|
+
# #right:: Draw a border to the right of the cell.
|
26
|
+
# #top:: Draw a border at the top of the cell.
|
27
|
+
# #bottom:: Draw a border 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, :left, :right,
|
33
|
+
:top, :bottom, :rotation_stacked
|
34
|
+
##
|
35
|
+
# Color attributes
|
36
|
+
colors :bottom_color, :top_color, :left_color, :right_color,
|
37
|
+
:pattern_fg_color, :pattern_bg_color,
|
38
|
+
:diagonal_color
|
39
|
+
##
|
40
|
+
# Text direction
|
41
|
+
# Valid values: :context, :left_to_right, :right_to_left
|
42
|
+
# Default: :context
|
43
|
+
enum :text_direction, :context, :left_to_right, :right_to_left,
|
44
|
+
:left_to_right => [:ltr, :l2r],
|
45
|
+
:right_to_left => [:rtl, :r2l]
|
46
|
+
alias :reading_order :text_direction
|
47
|
+
alias :reading_order= :text_direction=
|
48
|
+
##
|
49
|
+
# Indentation level
|
50
|
+
enum :indent_level, 0, Integer
|
51
|
+
alias :indent :indent_level
|
52
|
+
alias :indent= :indent_level=
|
53
|
+
##
|
54
|
+
# Horizontal alignment
|
55
|
+
# Valid values: :default, :left, :center, :right, :fill, :justify, :merge,
|
56
|
+
# :distributed
|
57
|
+
# Default: :default
|
58
|
+
enum :horizontal_align, :default, :left, :center, :right, :fill, :justify,
|
59
|
+
:merge, :distributed,
|
60
|
+
:center => :centre,
|
61
|
+
:merge => [ :center_across, :centre_across ],
|
62
|
+
:distributed => :equal_space
|
63
|
+
##
|
64
|
+
# Vertical alignment
|
65
|
+
# Valid values: :bottom, :top, :middle, :justify, :distributed
|
66
|
+
# Default: :bottom
|
67
|
+
enum :vertical_align, :bottom, :top, :middle, :justify, :distributed,
|
68
|
+
:distributed => [:vdistributed, :vequal_space, :equal_space],
|
69
|
+
:justify => :vjustify,
|
70
|
+
:middle => [:vcenter, :vcentre, :center, :centre]
|
71
|
+
attr_accessor :font, :number_format, :name, :pattern, :used_merge
|
72
|
+
##
|
73
|
+
# Text rotation
|
74
|
+
attr_reader :rotation
|
75
|
+
def initialize opts={}
|
76
|
+
@font = Font.new client("Arial", 'UTF-8'), :family => :swiss
|
77
|
+
@number_format = client 'GENERAL', 'UTF-8'
|
78
|
+
@rotation = 0
|
79
|
+
@pattern = 0
|
80
|
+
@bottom_color = :builtin_black
|
81
|
+
@top_color = :builtin_black
|
82
|
+
@left_color = :builtin_black
|
83
|
+
@right_color = :builtin_black
|
84
|
+
@diagonal_color = :builtin_black
|
85
|
+
@pattern_fg_color = :border
|
86
|
+
@pattern_bg_color = :pattern_bg
|
87
|
+
# Temp code to prevent merged formats in non-merged cells.
|
88
|
+
@used_merge = 0
|
89
|
+
opts.each do |key, val|
|
90
|
+
writer = "#{key}="
|
91
|
+
if @font.respond_to? writer
|
92
|
+
@font.send writer, val
|
93
|
+
else
|
94
|
+
self.send writer, val
|
95
|
+
end
|
96
|
+
end
|
97
|
+
yield self if block_given?
|
98
|
+
end
|
99
|
+
##
|
100
|
+
# Combined method for both horizontal and vertical alignment. Sets the
|
101
|
+
# first valid value (e.g. Format#align = :justify only sets the horizontal
|
102
|
+
# alignment. Use one of the aliases prefixed with :v if you need to
|
103
|
+
# disambiguate.)
|
104
|
+
#
|
105
|
+
# This is essentially a backward-compatibility method and may be removed at
|
106
|
+
# some point in the future.
|
107
|
+
def align= location
|
108
|
+
self.horizontal_align = location
|
109
|
+
rescue ArgumentError
|
110
|
+
self.vertical_align = location rescue ArgumentError
|
111
|
+
end
|
112
|
+
##
|
113
|
+
# Returns an Array containing the status of the four borders:
|
114
|
+
# bottom, top, right, left
|
115
|
+
def border
|
116
|
+
[bottom,top,right,left]
|
117
|
+
end
|
118
|
+
##
|
119
|
+
# Activate or deactivate all four borders (left, right, top, bottom)
|
120
|
+
def border=(boolean)
|
121
|
+
[:bottom=, :top=, :right=, :left=].each do |writer| send writer, boolean end
|
122
|
+
end
|
123
|
+
##
|
124
|
+
# Returns an Array containing the colors of the four borders:
|
125
|
+
# bottom, top, right, left
|
126
|
+
def border_color
|
127
|
+
[@bottom_color,@top_color,@left_color,@right_color]
|
128
|
+
end
|
129
|
+
##
|
130
|
+
# Set all four border colors to _color_ (left, right, top, bottom)
|
131
|
+
def border_color=(color)
|
132
|
+
[:bottom_color=, :top_color=, :right_color=, :left_color=].each do |writer|
|
133
|
+
send writer, color end
|
134
|
+
end
|
135
|
+
##
|
136
|
+
# Set the Text rotation
|
137
|
+
# Valid values: Integers from -90 to 90,
|
138
|
+
# or :stacked (sets #rotation_stacked to true)
|
139
|
+
def rotation=(rot)
|
140
|
+
if rot.to_s.downcase == 'stacked'
|
141
|
+
@rotation_stacked = true
|
142
|
+
@rotation = 0
|
143
|
+
elsif rot.kind_of?(Integer)
|
144
|
+
@rotation_stacked = false
|
145
|
+
@rotation = rot % 360
|
146
|
+
else
|
147
|
+
raise TypeError, "rotation value must be an Integer or the String 'stacked'"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
##
|
151
|
+
# Backward compatibility method. May disappear at some point in the future.
|
152
|
+
def center_across!
|
153
|
+
self.horizontal_align = :merge
|
154
|
+
end
|
155
|
+
alias :merge! :center_across!
|
156
|
+
##
|
157
|
+
# Is the cell formatted as a Date?
|
158
|
+
def date?
|
159
|
+
!!Regexp.new(client("[YMD]", 'UTF-8')).match(@number_format.to_s)
|
160
|
+
end
|
161
|
+
##
|
162
|
+
# Is the cell formatted as a Date or Time?
|
163
|
+
def date_or_time?
|
164
|
+
!!Regexp.new(client("[hmsYMD]", 'UTF-8')).match(@number_format.to_s)
|
165
|
+
end
|
166
|
+
##
|
167
|
+
# Is the cell formatted as a DateTime?
|
168
|
+
def datetime?
|
169
|
+
!!Regexp.new(client("([YMD].*[HS])|([HS].*[YMD])", 'UTF-8')).match(@number_format.to_s)
|
170
|
+
end
|
171
|
+
##
|
172
|
+
# Is the cell formatted as a Time?
|
173
|
+
def time?
|
174
|
+
!!Regexp.new(client("[hms]", 'UTF-8')).match(@number_format.to_s)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
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,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,132 @@
|
|
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, :default_format
|
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
|
+
# Set the default Format used when writing a Cell if no explicit Format is
|
69
|
+
# stored for the cell.
|
70
|
+
def default_format= format
|
71
|
+
@worksheet.add_format format if @worksheet
|
72
|
+
@default_format = format
|
73
|
+
end
|
74
|
+
format_updater :default_format
|
75
|
+
##
|
76
|
+
# #first_used the 0-based index of the first non-blank Cell.
|
77
|
+
def first_used
|
78
|
+
[ index_of_first(self), index_of_first(@formats) ].compact.min
|
79
|
+
end
|
80
|
+
##
|
81
|
+
# The Format for the Cell at _idx_ (0-based), or the first valid Format in
|
82
|
+
# Row#default_format, Column#default_format and Worksheet#default_format.
|
83
|
+
def format idx
|
84
|
+
@formats[idx] || @default_format \
|
85
|
+
|| @worksheet.column(idx).default_format if @worksheet
|
86
|
+
end
|
87
|
+
##
|
88
|
+
# Returns a copy of self with nil-values appended for empty cells that have
|
89
|
+
# an associated Format.
|
90
|
+
# This is primarily a helper-function for the writer classes.
|
91
|
+
def formatted
|
92
|
+
copy = dup
|
93
|
+
@formats.rcompact!
|
94
|
+
if copy.length < @formats.size
|
95
|
+
copy.concat Array.new(@formats.size - copy.length)
|
96
|
+
end
|
97
|
+
copy
|
98
|
+
end
|
99
|
+
##
|
100
|
+
# Same as Row#size, but takes into account formatted empty cells
|
101
|
+
def formatted_size
|
102
|
+
@formats.rcompact!
|
103
|
+
sz = size
|
104
|
+
fs = @formats.size
|
105
|
+
fs > sz ? fs : sz
|
106
|
+
end
|
107
|
+
##
|
108
|
+
# #first_unused (really last used + 1) - the 0-based index of the first of
|
109
|
+
# all remaining contiguous blank Cells.
|
110
|
+
alias :first_unused :formatted_size
|
111
|
+
def inspect
|
112
|
+
variables = instance_variables.collect do |name|
|
113
|
+
"%s=%s" % [name, instance_variable_get(name)]
|
114
|
+
end.join(' ')
|
115
|
+
sprintf "#<%s:0x%014x %s %s>", self.class, object_id, variables, super
|
116
|
+
end
|
117
|
+
##
|
118
|
+
# Set the Format for the Cell at _idx_ (0-based).
|
119
|
+
def set_format idx, fmt
|
120
|
+
@formats[idx] = fmt
|
121
|
+
@worksheet.add_format fmt
|
122
|
+
@worksheet.row_updated @idx, self if @worksheet
|
123
|
+
fmt
|
124
|
+
end
|
125
|
+
private
|
126
|
+
def index_of_first ary # :nodoc:
|
127
|
+
if first = ary.find do |elm| !elm.nil? end
|
128
|
+
ary.index first
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|