keeguon-spreadsheet 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +619 -0
- data/Manifest.txt +85 -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 +80 -0
- data/lib/spreadsheet/column.rb +71 -0
- data/lib/spreadsheet/compatibility.rb +23 -0
- data/lib/spreadsheet/datatypes.rb +161 -0
- data/lib/spreadsheet/encodings.rb +57 -0
- data/lib/spreadsheet/excel.rb +88 -0
- data/lib/spreadsheet/excel/error.rb +26 -0
- data/lib/spreadsheet/excel/internals.rb +458 -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/password_hash.rb +24 -0
- data/lib/spreadsheet/excel/reader.rb +1302 -0
- data/lib/spreadsheet/excel/reader/biff5.rb +42 -0
- data/lib/spreadsheet/excel/reader/biff8.rb +231 -0
- data/lib/spreadsheet/excel/rgb.rb +122 -0
- data/lib/spreadsheet/excel/row.rb +98 -0
- data/lib/spreadsheet/excel/sst_entry.rb +46 -0
- data/lib/spreadsheet/excel/workbook.rb +80 -0
- data/lib/spreadsheet/excel/worksheet.rb +115 -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 +264 -0
- data/lib/spreadsheet/excel/writer/n_worksheet.rb +888 -0
- data/lib/spreadsheet/excel/writer/workbook.rb +735 -0
- data/lib/spreadsheet/excel/writer/worksheet.rb +940 -0
- data/lib/spreadsheet/font.rb +115 -0
- data/lib/spreadsheet/format.rb +209 -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/note.rb +23 -0
- data/lib/spreadsheet/noteObject.rb +17 -0
- data/lib/spreadsheet/row.rb +151 -0
- data/lib/spreadsheet/workbook.rb +143 -0
- data/lib/spreadsheet/worksheet.rb +326 -0
- data/lib/spreadsheet/writer.rb +30 -0
- data/test/data/test_adding_data_to_existing_file.xls +0 -0
- data/test/data/test_borders.xls +0 -0
- data/test/data/test_changes.xls +0 -0
- data/test/data/test_comment.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_long_sst_record.xls +0 -0
- data/test/data/test_margin.xls +0 -0
- data/test/data/test_merged_and_protected.xls +0 -0
- data/test/data/test_merged_cells.xls +0 -0
- data/test/data/test_missing_row.xls +0 -0
- data/test/data/test_pagesetup.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/data/test_version_excel97_2010.xls +0 -0
- data/test/data/test_worksheet_visibility.xls +0 -0
- data/test/excel/reader.rb +30 -0
- data/test/excel/row.rb +40 -0
- data/test/excel/writer/workbook.rb +95 -0
- data/test/excel/writer/worksheet.rb +81 -0
- data/test/font.rb +163 -0
- data/test/format.rb +95 -0
- data/test/integration.rb +1390 -0
- data/test/row.rb +33 -0
- data/test/suite.rb +18 -0
- data/test/workbook.rb +55 -0
- data/test/workbook_protection.rb +19 -0
- data/test/worksheet.rb +112 -0
- 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,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
|