rasta 0.1.8-x86-mswin32-60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|