rasta 0.1.8-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +32 -0
- data/README.txt +15 -0
- data/bin/rasta +4 -0
- data/examples/crud_worksheet.xls +0 -0
- data/examples/fixtures/ColumnLayout.rb +34 -0
- data/examples/fixtures/HtmlRegistration.rb +103 -0
- data/examples/fixtures/MathFunctions.rb +21 -0
- data/examples/fixtures/StringFunctions.rb +18 -0
- data/examples/fixtures/crud/CrudClass.rb +62 -0
- data/examples/fixtures/crud/CrudFixture.rb +37 -0
- data/examples/html/registration.html +102 -0
- data/examples/rasta_fixture.xls +0 -0
- data/examples/tests_in_column_layout.xls +0 -0
- data/examples/watir_example.xls +0 -0
- data/lib/rasta/extensions/rspec_extensions.rb +174 -0
- data/lib/rasta/fixture/base_fixture.rb +138 -0
- data/lib/rasta/fixture/rasta_fixture.rb +183 -0
- data/lib/rasta/fixture_runner.rb +195 -0
- data/lib/rasta/formatter/spreadsheet_formatter.rb +32 -0
- data/lib/rasta/spreadsheet.rb +528 -0
- data/lib/rasta/version.rb +9 -0
- data/lib/rasta.rb +198 -0
- data/test/fixtures/RastaTestFixture.rb +9 -0
- data/test/spreadsheets/rasta_fixture.xls +0 -0
- data/test/spreadsheets/spreadsheet_parsing.xls +0 -0
- data/test/test_bookmarks.rb +138 -0
- data/test/test_fixtures.rb +66 -0
- data/test/test_spreadsheet.rb +337 -0
- metadata +98 -0
@@ -0,0 +1,528 @@
|
|
1
|
+
|
2
|
+
module Rasta
|
3
|
+
module Spreadsheet
|
4
|
+
require 'logger'
|
5
|
+
require 'singleton'
|
6
|
+
|
7
|
+
WORKING_DIR = Dir.getwd
|
8
|
+
|
9
|
+
# Singleton Class to store Excel Constant Variables
|
10
|
+
class ExcelConst; include Singleton; end
|
11
|
+
|
12
|
+
# Exceptions
|
13
|
+
class SheetNotFound < RuntimeError; end
|
14
|
+
class BookmarkNotFound < RuntimeError; end
|
15
|
+
|
16
|
+
# Singleton Class to store Excel Instance
|
17
|
+
#
|
18
|
+
# :visible Make the Excel Spreadsheet visible when processing
|
19
|
+
# :continue Continue from a bookmark
|
20
|
+
# :pagecount Continue for n pages after a bookmark
|
21
|
+
#
|
22
|
+
class Excel
|
23
|
+
include Singleton
|
24
|
+
attr_reader :excel, :visible
|
25
|
+
attr_accessor :continue, :currentrecord, :currentpage, :pagecount, :recordcount
|
26
|
+
def initialize
|
27
|
+
@visible = false
|
28
|
+
@continue = false
|
29
|
+
@currentrecord = 0
|
30
|
+
@currentpage = 0
|
31
|
+
@pagecount = 0
|
32
|
+
@recordcount = 0
|
33
|
+
@open_workbooks = []
|
34
|
+
@excel = WIN32OLE::new('excel.Application')
|
35
|
+
WIN32OLE.const_load(@excel, ExcelConst) if ExcelConst.constants == [] # load Excel constants
|
36
|
+
end
|
37
|
+
|
38
|
+
def open(filename)
|
39
|
+
@excel.Workbooks.Open(File.expand_path(filename))
|
40
|
+
end
|
41
|
+
|
42
|
+
def cleanup
|
43
|
+
if !@excel.visible
|
44
|
+
while @excel.ActiveWorkbook
|
45
|
+
@excel.ActiveWorkbook.Close(0)
|
46
|
+
end
|
47
|
+
@excel.Quit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def visible=(x)
|
52
|
+
@excel['Visible'] = x
|
53
|
+
@visible = x
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Bookmarks are ways to continue the spreadsheet from a given point.
|
58
|
+
# You can start from a specific tab and/or row/col in the spreadsheet.
|
59
|
+
# Additionally you can specify the number of pages and/or records to process
|
60
|
+
# so a user can start from SheetA and process 2 Sheets in the spreadsheet.
|
61
|
+
#
|
62
|
+
# Bookmarks are formatted as follows:
|
63
|
+
#
|
64
|
+
# PageName[Col|Row]
|
65
|
+
#
|
66
|
+
# where the Col/Row is an optional parameter. This gives the
|
67
|
+
# following bookmarks as possible continuation points:
|
68
|
+
#
|
69
|
+
# SheetA start from this sheet
|
70
|
+
# SheetA[10] this sheet is style :row, so start from row 10
|
71
|
+
# SheetA[F] this sheet is style :col, so start from column F
|
72
|
+
# true use the bookmark stored in .bookmarks
|
73
|
+
#
|
74
|
+
# The pagecount allows the user to start at the desired bookmark
|
75
|
+
# but only run through 1 or more sheets in the workbook
|
76
|
+
class Bookmark
|
77
|
+
@foundpage = false
|
78
|
+
@foundrecord = false
|
79
|
+
attr_accessor :page, :record
|
80
|
+
|
81
|
+
def initialize(bookmark)
|
82
|
+
# Parse the bookmark into it's parts so we can
|
83
|
+
# check for it as we read in the Sheet Records and Cells
|
84
|
+
@page, @record = parse_bookmark(bookmark)
|
85
|
+
raise ArgumentError, "Invalid record '#{@record}' - argument must be a row or column name" if @record && @record !~ /^([A-Z]+|\d+)$/i
|
86
|
+
end
|
87
|
+
|
88
|
+
# Check to see if the current record or page matches the bookmark.
|
89
|
+
# For example, found?(:sheet, [pagename]) or found?(:record, [row/col])
|
90
|
+
# where pagename is the name of the worksheet and row/col could be the
|
91
|
+
# row or column depending on the style of the page (eg: 'A' or 6)
|
92
|
+
def found?(how, what)
|
93
|
+
case how
|
94
|
+
when :sheet
|
95
|
+
if @foundpage
|
96
|
+
# Trap the case when a record is specified
|
97
|
+
# for a page and it does not exist
|
98
|
+
if !@foundrecord && what != @page
|
99
|
+
raise Spreadsheet::BookmarkNotFound, "Record #{@record} does not exist on page #{@page}"
|
100
|
+
end
|
101
|
+
|
102
|
+
true
|
103
|
+
else
|
104
|
+
if what == @page
|
105
|
+
@foundpage = true
|
106
|
+
# Set the foundrecord true so that it always
|
107
|
+
# passes the comparison if the record is not set
|
108
|
+
@foundrecord = true if !@record
|
109
|
+
true
|
110
|
+
else
|
111
|
+
false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
when :record
|
115
|
+
raise Spreadsheet::BookmarkNotFound, 'Should never get here: page should have been found first' if !@foundpage
|
116
|
+
if @foundrecord
|
117
|
+
true
|
118
|
+
else
|
119
|
+
if what == @record
|
120
|
+
@foundrecord = true
|
121
|
+
true
|
122
|
+
else
|
123
|
+
# TODO: RAISE if wrong type. (row is specified but it's a col)
|
124
|
+
false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
else
|
128
|
+
raise ArgumentError, "Don't know how to check bookmark for '#{how}'"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Returns true when either bookmark is not found or when pagecount has been reached.
|
134
|
+
def do_not_execute?(how, what)
|
135
|
+
!found?(how, what)
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def parse_bookmark(name)
|
141
|
+
name =~ /([^\[]+)(\[(\S+)\])?/
|
142
|
+
pagename = $1
|
143
|
+
recordid = $3.upcase if $3
|
144
|
+
return pagename, recordid
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
# This object is a container for the Excel workbook and
|
151
|
+
# any options passed into the library.
|
152
|
+
#
|
153
|
+
# The book object can be parsed to find Records which in turn
|
154
|
+
# can be parsed to locate Cells.
|
155
|
+
class Book
|
156
|
+
require 'win32ole'
|
157
|
+
attr_reader :filename
|
158
|
+
attr_accessor :bookmark
|
159
|
+
|
160
|
+
def initialize(filename)
|
161
|
+
@excel = Excel.instance
|
162
|
+
@filename = filename
|
163
|
+
raise ArgumentError, 'XLS file required for Book.new()' if !@filename
|
164
|
+
raise IOError, "Unable to find file: '#{@filename}'" if ! File.file?(@filename)
|
165
|
+
|
166
|
+
# Create a bookmark
|
167
|
+
@bookmark = Bookmark.new(@excel.continue)
|
168
|
+
|
169
|
+
# Open the workbook and get the ole reference to the workbook object
|
170
|
+
@o = @excel.open(@filename)
|
171
|
+
end
|
172
|
+
|
173
|
+
def [](name)
|
174
|
+
worksheet = @o.Worksheets(name)
|
175
|
+
if valid_worksheet(worksheet)
|
176
|
+
Sheet.new(self, worksheet)
|
177
|
+
else
|
178
|
+
raise SheetNotFound, name
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def each
|
183
|
+
@o.Worksheets.each do |worksheet|
|
184
|
+
next if !valid_worksheet(worksheet)
|
185
|
+
Excel.instance.currentpage += 1
|
186
|
+
return if (@excel.pagecount > 0 && @excel.currentpage > @excel.pagecount)
|
187
|
+
return if (@excel.recordcount > 0 && @excel.currentrecord > @excel.recordcount)
|
188
|
+
yield Sheet.new(self, worksheet)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def valid_worksheet(worksheet)
|
193
|
+
return false if worksheet.Visible == 0 # Skip hidden worksheets
|
194
|
+
return false if worksheet.name =~ /^#/ # Skip commented sheets
|
195
|
+
return false if worksheet.Tab.ColorIndex != ExcelConst::XlColorIndexNone # Skip worksheets with colored tabs
|
196
|
+
return false if (@excel.continue && @bookmark.do_not_execute?(:sheet, worksheet.name))
|
197
|
+
return true
|
198
|
+
end
|
199
|
+
|
200
|
+
def ole_object
|
201
|
+
@o
|
202
|
+
end
|
203
|
+
|
204
|
+
def save
|
205
|
+
@o.Save if @excel
|
206
|
+
end
|
207
|
+
|
208
|
+
def close
|
209
|
+
@o.Close(0) if @excel
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# Sheets store the information about records on the sheet.
|
214
|
+
# In order to allow the user to add comments and have flexibility
|
215
|
+
# with how the data is laid out we have the following requirements:
|
216
|
+
#
|
217
|
+
# * The data will start at the first non-bold cell closest to Cell 'A1'
|
218
|
+
# * Bold cells will be ignored until we hit the first data cell.
|
219
|
+
# * The header row (this is usually the attribute you're going to set) needs
|
220
|
+
# to be bolded. We will use which side of the data (top or left) to determine
|
221
|
+
# if the data is laid out in rows or in columns.
|
222
|
+
#
|
223
|
+
# Iterating over the Sheet will return Records which represent the row/column
|
224
|
+
#
|
225
|
+
|
226
|
+
class Sheet
|
227
|
+
attr_reader :style, :name, :headers, :book,
|
228
|
+
:firstrow, :firstcol, :lastrow, :lastcol
|
229
|
+
|
230
|
+
class ObjectError < RuntimeError; end
|
231
|
+
|
232
|
+
def initialize(book, worksheet)
|
233
|
+
# TODO: Add check for duplicates if option set
|
234
|
+
@book = book
|
235
|
+
@o = worksheet
|
236
|
+
@name = worksheet.name
|
237
|
+
self.select
|
238
|
+
# Order here is important because in these functions we
|
239
|
+
# will use the class variables from the prior call
|
240
|
+
(@lastrow, @lastcol) = locate_last_data_cell
|
241
|
+
(@firstrow, @firstcol) = locate_first_data_cell
|
242
|
+
(@headers, @style) = locate_headers
|
243
|
+
end
|
244
|
+
|
245
|
+
def to_s
|
246
|
+
"firstrow = #{@firstrow}\n" +
|
247
|
+
"firstcol = #{@firstcol}\n" +
|
248
|
+
"lastrow = #{@lastrow}\n" +
|
249
|
+
"lastcol = #{@lastcol}\n" +
|
250
|
+
"style = #{@style}\n"
|
251
|
+
end
|
252
|
+
|
253
|
+
def select
|
254
|
+
begin
|
255
|
+
@o.Select
|
256
|
+
rescue WIN32OLERuntimeError
|
257
|
+
raise ObjectError, "Unable to locate worksheet #{@name}"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def select_home_cell
|
262
|
+
self.select
|
263
|
+
begin
|
264
|
+
@o.Cells(1,1).Select
|
265
|
+
rescue WIN32OLERuntimeError
|
266
|
+
raise ObjectError, "Unable to select cell in #{@name}"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# A cell is a data cell if the cell's font is not bold
|
271
|
+
# and there is no background color
|
272
|
+
def datacell?(row,col)
|
273
|
+
@o.Cells(row,col).Font.Bold == false && @o.Cells(row,col).Interior.ColorIndex == ExcelConst::XlColorIndexNone
|
274
|
+
end
|
275
|
+
|
276
|
+
# Get the ole range object for a row or column
|
277
|
+
def cellrange(index, style=@style)
|
278
|
+
case style
|
279
|
+
when :row
|
280
|
+
@o.Range("#{colname(@firstcol)}#{index}:#{colname(@lastcol)}#{index}")
|
281
|
+
when :col
|
282
|
+
@o.Range("#{colname(index)}#{@firstrow}:#{colname(index)}#{@lastrow}")
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# Get an array of the values of cells in the range describing the row or column
|
287
|
+
def cellrangevals(index, style=@style)
|
288
|
+
range = cellrange(index, style)
|
289
|
+
# It looks like range['Value'] returns an array with multiple
|
290
|
+
# items and a string with one item so coerce the string into
|
291
|
+
# a one-dimensional array
|
292
|
+
return [range['Value']] if range['Value'].class != Array
|
293
|
+
case style
|
294
|
+
when :row
|
295
|
+
range['Value'][0]
|
296
|
+
when :col
|
297
|
+
range['Value'].map{ |v| v[0] }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Translate a numerical column index to the alpha worksheet column the user sees
|
302
|
+
def colname(col)
|
303
|
+
@o.Columns(col).address.slice!(/(\w+)/)
|
304
|
+
end
|
305
|
+
|
306
|
+
def each
|
307
|
+
case @style
|
308
|
+
when :row
|
309
|
+
firstrecord = @firstrow
|
310
|
+
lastrecord = @lastrow
|
311
|
+
when :col
|
312
|
+
firstrecord = @firstcol
|
313
|
+
lastrecord = @lastcol
|
314
|
+
end
|
315
|
+
(firstrecord..lastrecord).each do |record_index|
|
316
|
+
case @style
|
317
|
+
when :row
|
318
|
+
recordid = record_index.to_s
|
319
|
+
when :col
|
320
|
+
recordid = colname(record_index)
|
321
|
+
end
|
322
|
+
excel = Excel.instance
|
323
|
+
next if excel.continue && !@book.bookmark.found?(:record, recordid)
|
324
|
+
excel.currentrecord += 1
|
325
|
+
return if (excel.recordcount > 0 && excel.currentrecord > excel.recordcount)
|
326
|
+
yield Record.new(self, record_index)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def ole_object
|
331
|
+
@o
|
332
|
+
end
|
333
|
+
|
334
|
+
def cell (record_index, cell_index)
|
335
|
+
Cell.new(self, record_index, cell_index)
|
336
|
+
end
|
337
|
+
|
338
|
+
def [](index)
|
339
|
+
Record.new(self, index)
|
340
|
+
end
|
341
|
+
|
342
|
+
def dump
|
343
|
+
vals = []
|
344
|
+
self.each { |record| vals << record.dump }
|
345
|
+
return vals
|
346
|
+
end
|
347
|
+
|
348
|
+
|
349
|
+
private
|
350
|
+
|
351
|
+
##
|
352
|
+
# Returns the fist row and column with data in the worksheet. If no data
|
353
|
+
# is found before the last row and column, these same values are returned.
|
354
|
+
def locate_first_data_cell
|
355
|
+
(1..@lastrow).each do |row|
|
356
|
+
(1..@lastcol).each do |col|
|
357
|
+
if datacell?(row,col)
|
358
|
+
return row, col
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
return @lastrow, @lastcol
|
363
|
+
end
|
364
|
+
|
365
|
+
##
|
366
|
+
# Returns the last row and column with data in the worksheet. If no
|
367
|
+
# data is found (i.e., the sheet is empty) 1, 1 is returned.
|
368
|
+
def locate_last_data_cell
|
369
|
+
lastrow = @o.Cells.Find('What' => '*',
|
370
|
+
'SearchDirection' => ExcelConst::XlPrevious,
|
371
|
+
'SearchOrder' => ExcelConst::XlByRows)
|
372
|
+
lastcol = @o.Cells.Find('What' => '*',
|
373
|
+
'SearchDirection' => ExcelConst::XlPrevious,
|
374
|
+
'SearchOrder' => ExcelConst::XlByColumns)
|
375
|
+
if lastcol then col = lastcol.Column else col = 0 end
|
376
|
+
if lastrow then row = lastrow.Row else row = 0 end
|
377
|
+
return row, col
|
378
|
+
end
|
379
|
+
|
380
|
+
def locate_headers
|
381
|
+
# handle empty spreadsheet
|
382
|
+
return [nil, nil] if @firstrow + @lastrow + @firstcol + @lastcol == 0
|
383
|
+
headerrow = @firstrow - 1
|
384
|
+
if headerrow == 0
|
385
|
+
testcell = @o.Cells(1,@firstcol)
|
386
|
+
else
|
387
|
+
testcell = @o.Cells(headerrow,@firstcol)
|
388
|
+
end
|
389
|
+
if headerrow > 0 && testcell.Font.Bold && testcell.Value.to_s.strip != ''
|
390
|
+
style = :row
|
391
|
+
headers = cellrangevals(@firstrow-1, :row)
|
392
|
+
else
|
393
|
+
style = :col
|
394
|
+
headers = cellrangevals(@firstcol-1, :col)
|
395
|
+
end
|
396
|
+
headers.map!{|x| x.strip if x}
|
397
|
+
return headers, style
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
# Records store the information of a particular row/col of
|
402
|
+
# a worksheet and allow iterating through the Record's Cells
|
403
|
+
class Record
|
404
|
+
attr_reader :recordindex, :sheet, :book
|
405
|
+
def initialize(sheet, index)
|
406
|
+
@sheet = sheet
|
407
|
+
@book = sheet.book
|
408
|
+
@recordindex = index
|
409
|
+
@range = @sheet.cellrange(@recordindex)
|
410
|
+
end
|
411
|
+
def each
|
412
|
+
@sheet.headers.each_index do |cell_index| # should be a value for each header
|
413
|
+
cell = @sheet.cell(@recordindex,cell_index + 1)
|
414
|
+
next if cell.nil? # Make sure the header exists
|
415
|
+
# Skip empty cells and italicized cells
|
416
|
+
next if (cell.value == '' || cell.italic)
|
417
|
+
yield cell
|
418
|
+
end
|
419
|
+
end
|
420
|
+
def select
|
421
|
+
@range.Select
|
422
|
+
end
|
423
|
+
def color=(c)
|
424
|
+
@range.Interior.ColorIndex = c
|
425
|
+
end
|
426
|
+
def [](index)
|
427
|
+
Cell.new(@sheet, @recordindex, index)
|
428
|
+
end
|
429
|
+
def to_s
|
430
|
+
@sheet.style.to_s + ':' + @recordindex.to_s
|
431
|
+
end
|
432
|
+
def dump
|
433
|
+
vals = []
|
434
|
+
self.each { |cell| vals << cell.value }
|
435
|
+
return vals
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
# Cells store information on a specific worksheet cell.
|
440
|
+
# The name is the Excel name for the cell (ie: A1, B2, etc),
|
441
|
+
# the value is the value of the cell and the header is the
|
442
|
+
# header for that row/column (usually the attribute/function parameter
|
443
|
+
# we're trying to set)
|
444
|
+
class Cell
|
445
|
+
ARRAY = /\A\s*\[.+\]\s*\Z/ms
|
446
|
+
HASH = /\A\s*\{.+\}\s*\Z/ms
|
447
|
+
BOOL = /\A\s*(true|false)\s*\Z/i
|
448
|
+
NUMBER = /\A\s*-?\d+\.??\d*?\s*\Z/
|
449
|
+
REGEXP = /\A\s*(\/.+\/)\s*\Z/ms
|
450
|
+
attr_reader :name, :value, :recordid, :recordindex,
|
451
|
+
:sheet, :book
|
452
|
+
|
453
|
+
def initialize(sheet, record_index, cell_index)
|
454
|
+
@sheet = sheet
|
455
|
+
@book = sheet.book
|
456
|
+
@o = sheet.ole_object
|
457
|
+
@cellindex = cell_index
|
458
|
+
@recordindex = record_index
|
459
|
+
case @sheet.style
|
460
|
+
when :row
|
461
|
+
@row = @recordindex
|
462
|
+
@col = @cellindex + @sheet.firstcol - 1 # taking into account the start of the used data range
|
463
|
+
@cell = @o.Cells(@row,@col)
|
464
|
+
@cell.NumberFormat == "@" ? @value = @cell.Value : @value = @cell.Text
|
465
|
+
when :col
|
466
|
+
@row = @cellindex + @sheet.firstrow - 1 # taking into account the start of the used data range
|
467
|
+
@col = @recordindex
|
468
|
+
@cell = @o.Cells(@row,@col)
|
469
|
+
@cell.NumberFormat == "@" ? @value = @cell.Value : @value = @cell.Text
|
470
|
+
end
|
471
|
+
# Ignore blank values. There's not much use for cells
|
472
|
+
# that are not set so skip them and normalize the return
|
473
|
+
# to nil so we know that's the case
|
474
|
+
@value = @value.to_s.strip
|
475
|
+
if @value =~ NUMBER
|
476
|
+
@value = eval(@value) unless @value =~ /^0\d/
|
477
|
+
elsif @value =~ ARRAY || @value =~ HASH || @value =~ BOOL || @value =~ REGEXP
|
478
|
+
@value = @value.downcase if @value =~ BOOL # make sure it's not confused with a constant
|
479
|
+
@value = eval(@value)
|
480
|
+
end
|
481
|
+
|
482
|
+
# Put together the cell's name
|
483
|
+
column_letter = @sheet.colname(@col)
|
484
|
+
@name = column_letter + @row.to_s
|
485
|
+
|
486
|
+
# The recordid is the row/col for the record
|
487
|
+
case @sheet.style
|
488
|
+
when :row
|
489
|
+
@recordid = @row.to_s
|
490
|
+
when :col
|
491
|
+
@recordid = column_letter
|
492
|
+
end
|
493
|
+
end
|
494
|
+
def header
|
495
|
+
# Return the header but strip off a trailing () if
|
496
|
+
# the user added for clarification purposes
|
497
|
+
@sheet.headers[@cellindex-1].gsub(/\(\)$/,'') if @sheet.headers[@cellindex-1]
|
498
|
+
end
|
499
|
+
def color=(c)
|
500
|
+
@cell.Interior.ColorIndex = c
|
501
|
+
end
|
502
|
+
def color
|
503
|
+
@cell.Interior.ColorIndex
|
504
|
+
end
|
505
|
+
def italic
|
506
|
+
@cell.Font.Italic
|
507
|
+
end
|
508
|
+
def comment=(c)
|
509
|
+
if c && !@cell.Comment
|
510
|
+
@cell.AddComment(c)
|
511
|
+
@cell.Comment.Shape.TextFrame.AutoSize = true
|
512
|
+
@cell.Comment.Shape.TextFrame.Characters.Font.Size=8
|
513
|
+
end
|
514
|
+
end
|
515
|
+
def selectrecord
|
516
|
+
range = @sheet.cellrange(@recordindex)
|
517
|
+
range.Select
|
518
|
+
end
|
519
|
+
def value=(v)
|
520
|
+
@cell.Value = v
|
521
|
+
end
|
522
|
+
def ole_object
|
523
|
+
@cell
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
end # module
|
528
|
+
end # module
|