ActiveExcel 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ === 0.0.1 / 2009-06-04
2
+
3
+ * 1 major enhancement
4
+
5
+ * Initial creation of package
6
+
7
+
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/active_excel
6
+ lib/active_excel.rb
7
+ test/test_active_excel.rb
@@ -0,0 +1,48 @@
1
+ = active_excel
2
+
3
+ * FIX (url)
4
+
5
+ == DESCRIPTION:
6
+
7
+ FIX (describe your package)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIX (list of features or problems)
12
+
13
+ == SYNOPSIS:
14
+
15
+ FIX (code sample of usage)
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * FIX (list of requirements)
20
+
21
+ == INSTALL:
22
+
23
+ * FIX (sudo gem install, anything else)
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2009 FIX
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,30 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ $:.unshift(File.dirname(__FILE__) + "/lib")
6
+ require 'active_excel'
7
+
8
+ Hoe.spec 'active_excel' do |p|
9
+ #self.rubyforge_name = 'active_excelx' # if different than 'active_excel'
10
+ #p.developer('FIX', 'FIX@example.com')
11
+ #Hoe.new('ActiveExcel', ActiveExcel::VERSION) do |p|
12
+ p.name = "ActiveExcel"
13
+ p.author = "Rob Whitener"
14
+ p.description = "Excel as the container of model objects"
15
+ p.email = 'robwhitener@gmail.com'
16
+ p.summary = <<EXCEL
17
+ Use Excel to contain model objects. Each row in a sheet represents an object, each sheet in a workbook
18
+ represents a class. Make sure that you rename your sheets - this gem uses ActiveSupport to take advantage
19
+ of the pluralization familiar to Rails developers. Modeled liberally on ActiveRecord, not quite as cool but
20
+ hopefully useful enough. Cheers.
21
+ EXCEL
22
+ p.url = "http://robsexocortex.blogspot.com/2009/06/activeexcel.html"
23
+ p.clean_globs = ['test/actual'] # Remove this directory on "rake clean"
24
+ p.remote_rdoc_dir = '' # Release to root
25
+ #p.changes = p.paragraphs_of('CHANGELOG', 0..1).join("\n\n")
26
+ # * extra_deps - An array of rubygem dependencies.
27
+ #end
28
+ end
29
+
30
+ # vim: syntax=ruby
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ abort "you need to write me"
@@ -0,0 +1,432 @@
1
+ require 'win32ole'
2
+ require 'activesupport'
3
+
4
+ class ExcelConstants
5
+ XLBLACK = 1
6
+ XLRED = 3
7
+ XLGREEN = 4
8
+ XLBLUE = 5
9
+ XLYELLOW = 6
10
+ XLMAGENTA = 7
11
+ XLCYAN = 8
12
+ XLBROWN = 9
13
+ XLOLIVE = 10
14
+ XLROYAL = 11
15
+ XLVOMIT = 12
16
+ XLPURPLE = 13
17
+ XLNOCOLOR = -4142
18
+ end
19
+
20
+ module ActiveExcel
21
+ VERSION = '0.0.1'
22
+ #This class conatins the main Excel functionality that will be inherited
23
+ #by objects which intend to wrap data in the spreadsheet
24
+ class Root
25
+ attr_accessor :workbook, :workbook_name, :id, :fields, :dirty, :is_new, :this_workbook
26
+ @@excel = nil
27
+ @@sheets = nil
28
+ @@workbook = nil
29
+ @@sheet_name = nil
30
+
31
+ def initialize()
32
+ #this will be called by the new method and will be called for
33
+ #each instance of any subclass that is created.
34
+ #The initialize routine will handel adding attributes to the
35
+ #new instance based on the fieldnames from the spreadsheet.
36
+ #If Find was used to get an object out of the sheet, then the
37
+ #attributes will be populated. Each instance will also have
38
+ #an id field that corresponds to its row number in the spreadsheet
39
+ @fields = nil
40
+ @this_workbook = @@workbook
41
+ add_attributes
42
+ @id = -1 #the id can have a default value of -1, since there is no -1 row in a sheet
43
+ @dirty = false
44
+ @is_new = true
45
+
46
+ end
47
+
48
+ class << self ###Class methods
49
+
50
+ #Config is a hash that expects the following parameters
51
+ # :wkbook -> The name of the workbook to open
52
+ # :path -> pathe where the workbook can be found if the workbook isn't in the my docs folder
53
+ def workbook_connect(config=nil)
54
+ @workbook_name = config[:wkbook]
55
+ if config[:path]
56
+ #there was a path specified, prepend that to the workbook name
57
+ @workbook_name = config[:path] + "/" + @workbook_name
58
+ puts "Fully Qualified Workbook Path:>> #{@workbook_name}"
59
+ else
60
+ #otherwise, figure out where MyDocuments is
61
+ @workbook_name = ENV['USERPROFILE'] + "\\" + "My Documents" + "\\" + @workbook_name
62
+ end
63
+ #create the Excel application
64
+
65
+ begin
66
+ @@excel = WIN32OLE::connect('Excel.Application') if !@@excel
67
+ rescue
68
+ @@excel = WIN32OLE::new('Excel.Application')
69
+ end
70
+
71
+ #we now have a connection to a workbook.
72
+ #first, check to see if the desired workbook is open, if it is put that in @@workbook
73
+ if @@excel.Workbooks.Count > 0 then
74
+ #there are workbooks open, grab the one we want by name
75
+ @@workbook = nil
76
+ for wkbk in @@excel.Workbooks
77
+ if wkbk.Name == config[:wkbook] then
78
+ @@workbook = wkbk
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ #at this point if @@workbook is nil, then go ahead and open it.
85
+ if @@workbook == nil then
86
+ @@workbook = @@excel.Workbooks.Open(@workbook_name)
87
+ end
88
+ @@excel.Visible = 1
89
+ #get all the sheet names
90
+ @@sheets ||= {}
91
+ i = 1
92
+ for worksheet in @@workbook.Worksheets
93
+ @@sheets[i] = worksheet.Name
94
+ i += 1
95
+ end
96
+ @@workbook
97
+ end
98
+
99
+ def sheet_names
100
+ @@sheets
101
+ end
102
+
103
+ def load_constants
104
+ begin
105
+ ExcelConstants::XLDown #try to access a constant,
106
+ rescue
107
+ #if an error is thrown, load them.
108
+ WIN32OLE.const_load(@@excel, ExcelConstants) #load Excel constants into the module.
109
+ end
110
+ end
111
+
112
+ def connected?
113
+ return @@excel ? true : false
114
+ end
115
+
116
+ def workbook_disconnect
117
+ #this method will save any changes to the workbook and then close it down.
118
+ @@workbook.Save if @@workbook
119
+ @@workbook.Close if @@workbook
120
+ @@workbook = nil
121
+ end
122
+
123
+ def excel_disconnect
124
+ @@excel.Quit if @@excel
125
+ @@excel = nil
126
+ end
127
+
128
+ #Define a sheet name to use, in case the naming convention doesn't work for
129
+ #particular situations
130
+ def set_sheet_name(sht)
131
+ #Add the sheetname as a class variable
132
+ class_eval{ class_variable_set(:"@@sheet_name",sht.to_s)}
133
+ end
134
+
135
+ #This method will find one or more records in the spreadsheet and
136
+ #return them as ActiveExcel objects.
137
+ def find(rec_no)
138
+
139
+ if rec_no.is_a? Integer
140
+ #if its just an integer, then look up by id
141
+ return find_by_id(rec_no)
142
+ elsif rec_no.is_a? Hash
143
+ return nil
144
+ elsif rec_no.is_a? Symbol
145
+ case rec_no
146
+ when :all then return find_all
147
+ when :first then find_first
148
+ when :last then find_last
149
+ end
150
+ end
151
+ set_sheet_name(self.class.to_s.tableize)
152
+
153
+ end
154
+
155
+ def find_by_id(i)
156
+ return nil if i < 2 #The rowid has to be 2 or greater
157
+ o = new #create a new object, this will also set the workseet
158
+ o.this_workbook = @@workbook.clone
159
+ @wksheet = get_the_worksheet
160
+
161
+ #iterate over the list of field names
162
+ @columns.each_pair do |k,v|
163
+ #Access the Cell by passing in the Letter cooresponding to the field name and the
164
+ #Row index (1 based)
165
+ value = @wksheet.Range("#{v}#{i}").Value
166
+ o.send(:"#{k.to_s}=",value)
167
+
168
+ end
169
+ o.dirty = false
170
+ o.is_new = false
171
+ o.id=i
172
+ o #return the new object
173
+ end
174
+
175
+ def find_all
176
+ #basically, grab all the records except the header, roll them into ActiveExcel objects
177
+ obj_array = Array.new #make a new array to hold the objects
178
+ #figure out the current region size
179
+ current_region = get_the_current_region
180
+ 2.upto(current_region.Rows.Count) do |i|
181
+ o = new
182
+ o.this_workbook = @@workbook.clone
183
+ 1.upto(current_region.Columns.Count) do |j|
184
+ field = get_the_field_name_for_index(j-1) #the letters array is 0 based, but excel is 1 based.
185
+ o.send(:"#{field}=",@wksheet.Cells(i,j).Value.to_s)
186
+ o.is_new = false
187
+ o.dirty = false
188
+ o.id = i
189
+ end
190
+ obj_array << o
191
+ end
192
+ obj_array
193
+ end
194
+
195
+ #Returns a list of column names. If the columns hash hasn't been created, it will create the
196
+ #columns hash by scanning the first row of the CurrentRegion (Which is defined as a region on the
197
+ #active worksheet bounded by blank cells).
198
+ def column_names(sheet = nil)
199
+ if !@columns
200
+ if sheet
201
+ #if a sheet name was passed in we can just use that to get the column names
202
+ @wksheet = @@workbook.Worksheets(sheet)
203
+ else
204
+ #Test to see if a sheet_name class variable has been set
205
+ #if it has, then use that value other wise use the class name
206
+ classvar = self.class_eval{class_variable_get(:"@@sheet_name")}
207
+ classname = classvar ? classvar : self.class.to_s.tableize
208
+ puts "Tableized: #{classname}"
209
+ @wksheet = @@workbook.Worksheets(classname)
210
+ end
211
+ #now, grab the collumn names and put them into a hash name=>col_letter
212
+ row = @wksheet.Cells.CurrentRegion.Rows(1)
213
+ @columns = {}
214
+ @letters = []
215
+ col_name = "A"
216
+ row.Cells.each do |c|
217
+ #c represents a Cell in the worksheet
218
+ @columns[c.Value.to_sym] = col_name.clone
219
+ @letters << col_name.clone
220
+ col_name.succ! #advance the col_name one letter
221
+ end
222
+ end
223
+ #return a list of the keys
224
+ keys = []
225
+ @columns.each_key {|k| keys << k}
226
+ keys
227
+ end
228
+
229
+ def columns
230
+ return @columns
231
+ end
232
+
233
+ def wksheet
234
+ return @wksheet
235
+ end
236
+
237
+ #This implementation of method_missing will provide methods that will allow records
238
+ #to be looked up using find_by_<field_name>(value). For simplicity sake, this first
239
+ #iteration will only allow the search of individual fields.
240
+ def method_missing(methodid,*args,&blk)
241
+ #make sure the columns hash has been built
242
+ puts("METHOD ID --> #{methodid.to_s}")
243
+ column_names if !@columns
244
+
245
+ #if the words 'find_ and 'by' are not part of method id, then get out.
246
+ return if methodid.to_s !~ /find_.*by/
247
+
248
+ field = methodid.to_s.split("by_").last
249
+ letter = @columns[field.to_sym] #grab the column letter
250
+ col_index = @letters.index(letter) + 1 #get the column index, add 1 because Excel is one based.
251
+
252
+ if methodid.to_s.index("find_all_by")
253
+ return find_all_by_attribute(field,col_index,args[0])
254
+ else
255
+ return find_by_attribute(field,col_index,args[0])
256
+ end
257
+ end
258
+
259
+ #this method is caled from within method missing to return all objects
260
+ #that can be found which contain a particular value for a particular field
261
+ def find_all_by_attribute(field,col_index,args)
262
+ lookup_records(field,col_index,args,false)
263
+ end
264
+
265
+ #This method is called by method_missing to return the first object in the sheet which
266
+ #contains a particular value for a particular field.
267
+ def find_by_attribute(field,col_index,args)
268
+ lookup_records(field,col_index,args)
269
+ end
270
+
271
+ def lookup_records(field,col_index,args,first=true)
272
+ i = 1 #keep track of the row number with this variable
273
+ @wksheet = get_the_worksheet
274
+ current_region = get_the_current_region
275
+ records = Array.new
276
+ current_region.each do |range|
277
+ if @wksheet.Cells(i,col_index).Value == args then
278
+ #the value of the cell in the range matches the value passed into the
279
+ #missing method. Create a new object and return it
280
+ o = new
281
+ o.this_workbook = @@workbook.clone
282
+ 1.upto(current_region.Columns.Count) do |j|
283
+ #get the column letter
284
+ l = @letters[j-1]
285
+ #from the hash, go backward from the column letter to the field name
286
+ field = @columns.index(l)
287
+ o.send(:"#{field.to_s}=",@wksheet.Cells(i,j).Value.to_s)
288
+ end
289
+ o.id = i
290
+ o.dirty = false
291
+ o.is_new = false
292
+ return o if first
293
+ records << o
294
+ break if i == current_region.Rows.Count
295
+ end
296
+ i+=1
297
+ end
298
+ records
299
+ end
300
+
301
+ #Get the CurrentRegion of the spreadsheet as a standard range
302
+ def get_the_current_region
303
+ @wksheet = get_the_worksheet
304
+ curr_reg_addr = @wksheet.Cells.CurrentRegion.address.to_s.gsub(/\$/,'') #remove $ from address
305
+ current_region = @wksheet.Range(curr_reg_addr)
306
+ end
307
+
308
+ #returns the field name for a given column letter
309
+ def get_the_field_name_for_index(index)
310
+ l = @letters[index]
311
+ @columns.index(l)
312
+ end
313
+
314
+ def get_the_worksheet
315
+ puts("-----------------------------")
316
+ puts("\tself.name.tableize: #{self.name.tableize}")
317
+ puts("\tsheet_name: #{@@sheet_name}")
318
+ @@sheet_name = self.name.tableize if !@@sheet_name
319
+ puts("\tThe SheetName being used is: #{@@sheet_name}\n")
320
+ puts("-----------------------------")
321
+ @@workbook.Worksheets(@@sheet_name)
322
+
323
+ end
324
+
325
+ end ###End class methods####
326
+
327
+ #allows the workbook that an individual object comes from to be stored in the object.
328
+ #def this_workbook=(wkbk)
329
+ # @this_workbook = wkbk
330
+ #end
331
+ #
332
+ #def this_workbook
333
+ # @this_workbook
334
+ #end
335
+
336
+ #Define the attributes of the instance based on what is in the
337
+ #spreadheet
338
+ def add_attributes
339
+ #we should be able to use the column_names here
340
+ if !@@sheet_name then
341
+ @fields = self.class.column_names(self.class.to_s.tableize)
342
+ else
343
+ @fields = self.class.column_names()
344
+ end
345
+ #add a getter/setter pair for each column name
346
+ @fields.each do |c|
347
+ #add the setter method
348
+ self.class_eval do
349
+ define_method(:"#{c.to_s}=") do |v|
350
+ instance_variable_set(:"@#{c.to_s}",v)
351
+ instance_variable_set(:"@dirty",true)
352
+ end
353
+ end
354
+
355
+ #add the getter method
356
+ self.class_eval do
357
+ define_method(c) do
358
+ instance_variable_get(:"@#{c.to_s}")
359
+ end
360
+ end
361
+ end
362
+
363
+ end
364
+
365
+ #This method will save the object back into the spreadsheet. THIS DOES NOT SAVE
366
+ #CHANGES TO THE ACTUAL SPREADSHEET THAT IS IN MEMORY.
367
+ #
368
+ def save
369
+ update_or_create
370
+ end
371
+
372
+ #Returns whether or not this is a dirty object or not
373
+ def dirty?
374
+ dirty
375
+ end
376
+
377
+ def color_cell(name,const)
378
+ #first, get the cell name
379
+ letter = self.class.columns[name.to_sym]
380
+ #get the sheet name, if we don't already have it
381
+ @wksheet = @@workbook.worksheets(self.class.to_s.tableize) if !@wksheet
382
+ #color the cell
383
+ @wksheet.Range("#{letter}#{self.id}").Interior.ColorIndex = const
384
+ end
385
+
386
+ def get_cell_color(name)
387
+ #get the cell name
388
+ letter = self.class.columns[name.to_sym]
389
+ @wksheet = @@workbook.worksheets(self.class.to_s.tableize) if !@wksheet
390
+ #get the cell color
391
+ @wksheet.Range("#{letter}#{self.id}").Interior.ColorIndex
392
+ end
393
+
394
+ private
395
+ #This method will determine whether to update an existing record
396
+ #or create a brand new one
397
+ def update_or_create
398
+ res = (is_new == true) ? create : update
399
+ res != false
400
+ end
401
+
402
+ #This method will create a brand new row in the sheet
403
+ def create
404
+ #determine the last row in the table
405
+ row = self.class.wksheet.Cells.CurrentRegion.Rows.Count
406
+ row += 1 #add 1 to the row to point to the next empty row
407
+ self.class.columns.each_pair do |k,v|
408
+ #k: will be the field name
409
+ #v: will be the column letter
410
+ self.class.wksheet.Range("#{v}#{row}").Value = self.send(k)
411
+
412
+ end
413
+ self.dirty = false
414
+ self.is_new = false
415
+ self.id = row
416
+ end
417
+
418
+ #this method will save the existing record
419
+ def update
420
+ self.class.columns.each_pair do |k,v|
421
+ #k: will be the field name
422
+ #v: will be the column letter
423
+ self.class.wksheet.Range("#{v}#{self.id}").Value = self.send(k)
424
+ end
425
+ self.dirty = false
426
+ end
427
+
428
+
429
+
430
+ end #End of Root class
431
+
432
+ end #End of Module
@@ -0,0 +1,180 @@
1
+ require "test/unit"
2
+ require File.dirname(__FILE__)+ "/../lib/active_excel"
3
+
4
+ #this is a subclass of ActiveExcel::Root, it will be used
5
+ #to help verify inherited behaviors and connections
6
+ class OtherRecord < ActiveExcel::Root
7
+
8
+ end
9
+
10
+ class NoSheet < ActiveExcel::Root
11
+ set_sheet_name :other_records
12
+ end
13
+
14
+ class X12CarbonCopyTest < ActiveExcel::Root
15
+
16
+ end
17
+
18
+ class TestActiveExcel < Test::Unit::TestCase
19
+
20
+ def setup
21
+ @wkbk = ActiveExcel::Root.workbook_connect({:wkbook=>"gxstestsubs_billing.xls"})
22
+ #ActiveExcel::Root.load_constants if !@const_loaded
23
+ #@const_loaded = true
24
+ end
25
+
26
+ def teardown
27
+ puts "Closing down excel....."
28
+ ActiveExcel::Root.workbook_disconnect
29
+ ActiveExcel::Root.excel_disconnect
30
+ @wkbk = nil
31
+ GC.start
32
+ sleep(2)
33
+ end
34
+
35
+ def test_connect_to_workbook
36
+ #this test verifies that a workbook can be connected to by passing in a hash
37
+ #config = {:wkbook=>"gxstestsubs_billing.xls"}
38
+ #ActiveExcel::Root.workbook_connect(config)
39
+ assert_not_nil @wkbk
40
+ assert_equal 3,@wkbk.Worksheets.Count
41
+
42
+
43
+ end
44
+
45
+ #def test_connect_to_two_different_workbooks
46
+ # #this test verifies that ActiveExcel won't crash if two Excel workbooks are open.
47
+ # #the first one will be opened by the set up method, and the second will be a connection
48
+ # #to SmallCCTests_FEReq_FEPart_FERecip.xls
49
+ #
50
+ # #first, grab an OtherRecord object, this will store the first workbook in the object:
51
+ # orec = OtherRecord.find(3)
52
+ # #now, open up the second one.
53
+ # ActiveExcel::Root.workbook_connect({:wkbook=>"SmallCCTests_FEReq_FEPart_FERecip.xls"})
54
+ # ActiveExcel::Root.set_sheet_name :x12_carbon_copy_tests
55
+ # x12 = X12CarbonCopyTest.find(2)
56
+ # assert_not_equal(orec.this_workbook, x12.this_workbook )
57
+ # ActiveExcel::Root.set_sheet_name = nil
58
+ #end
59
+
60
+ def test_column_names
61
+ #ae = ActiveExcel::Root.new
62
+ h = ActiveExcel::Root.column_names("other_records")
63
+ 0.upto(3) do |i|
64
+ assert_equal true,h.include?(:"Field#{i+1}")
65
+ end
66
+ assert_equal "A",ActiveExcel::Root.columns[:Field1]
67
+ assert_equal "B",ActiveExcel::Root.columns[:Field2]
68
+ assert_equal "C",ActiveExcel::Root.columns[:Field3]
69
+ assert_equal "D",ActiveExcel::Root.columns[:Field4]
70
+ end
71
+
72
+ def test_using_a_subclass
73
+ oe = OtherRecord.new
74
+ h = oe.class.column_names
75
+ 0.upto(3) do |i|
76
+ assert_equal true,h.include?(:"Field#{i+1}")
77
+ end
78
+ end
79
+
80
+ def test_specifying_a_sheet_name
81
+
82
+ ns = NoSheet.new
83
+ #assert_equal "other_records",NoSheet.sheet_name
84
+ h = ns.class.column_names
85
+ 0.upto(3) do |i|
86
+ assert_equal true,h.include?(:"Field#{i+1}")
87
+ end
88
+ end
89
+
90
+ def test_verify_that_attr_added_dynamically
91
+ orec = OtherRecord.new
92
+ orec.Field1 = "A new value"
93
+ orec.Field4 = "BLAH BLAH"
94
+ assert_equal "A new value",orec.Field1
95
+ assert_equal -1,orec.id
96
+ assert_equal nil,orec.Field2
97
+ assert_equal nil,orec.Field3
98
+ assert_equal "BLAH BLAH",orec.Field4
99
+ end
100
+
101
+ def test_find_a_record_with_a_specific_id
102
+
103
+ #simply passing in an integer will cause it to find by id
104
+ orec = OtherRecord.find(3)
105
+ assert_equal "Value2",orec.Field1
106
+ assert_equal "Value10",orec.Field2
107
+ assert_equal "Value18",orec.Field3
108
+ assert_equal "Value26",orec.Field4
109
+ end
110
+
111
+ def test_find_by_attr_name
112
+ orec = OtherRecord.find_by_Field2("Value11")
113
+ assert_equal 4,orec.id
114
+ assert_equal "Value3",orec.Field1
115
+ assert_equal "Value11",orec.Field2
116
+ assert_equal "Value19",orec.Field3
117
+ assert_equal "Value27",orec.Field4
118
+ end
119
+
120
+ def test_find_all_by_attr_name
121
+ orecs = OtherRecord.find_all_by_Field1("Value8")
122
+ assert_equal 2,orecs.size
123
+ orec1 = orecs[0]
124
+ orec2 = orecs[1]
125
+ assert_equal "Value8",orec1.Field1
126
+ assert_equal "Value16",orec1.Field2
127
+ assert_equal "Value8", orec2.Field1
128
+ assert_equal "Value160",orec2.Field2
129
+ end
130
+
131
+ def test_find_by_attr_name_with_underscore
132
+ orec = OtherRecord.find_by_Field_Five("Value35")
133
+ assert_equal "Value3",orec.Field1
134
+ assert_equal "Value11",orec.Field2
135
+ assert_equal "Value19",orec.Field3
136
+ assert_equal "Value27",orec.Field4
137
+ assert_equal "Value35",orec.Field_Five
138
+ end
139
+
140
+ def test_save_an_edited_record
141
+ orec = OtherRecord.find_by_Field3("Value23")
142
+ orec.Field1="UPDATED"
143
+ orec.Field2="RECORD"
144
+ orec.save
145
+
146
+ teardown()
147
+ #sleep(5) #go to sleep for 5 seconds so I can watch the taskmanager
148
+
149
+ #open it back up now
150
+ ActiveExcel::Root.workbook_connect({:wkbook=>"gxstestsubs_billing.xls"})
151
+
152
+ uprec = OtherRecord.find_by_Field3("Value23")
153
+ assert_equal "UPDATED",uprec.Field1
154
+ assert_equal "RECORD",uprec.Field2
155
+
156
+ #change them again and ensure that the object has been marked dirty.
157
+ uprec.Field1 = "Value7"
158
+ uprec.Field2 = "Value15"
159
+
160
+ assert_equal true,uprec.dirty?
161
+ uprec.save
162
+ end
163
+
164
+ def test_find_all_records_in_sheet
165
+ recs = OtherRecord.find(:all)
166
+ assert_equal 9,recs.size
167
+ 0.upto(7) do |i|
168
+ assert_equal "OtherRecord",recs[i].class.to_s
169
+ assert_equal "Value#{i+1}",recs[i].send(:"Field1")
170
+ end
171
+ end
172
+
173
+ def test_colorize_cell
174
+ #this verifies that we can color a cell using an excel constant
175
+ oe = OtherRecord.find(4)
176
+ oe.color_cell("Field1",ExcelConstants::XLGREEN)
177
+ oe.color_cell("Field3",ExcelConstants::XLRED)
178
+ oe.save
179
+ end
180
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ActiveExcel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rob Whitener
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-02 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.0
24
+ version:
25
+ description: Excel as the container of model objects
26
+ email: robwhitener@gmail.com
27
+ executables:
28
+ - active_excel
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ files:
36
+ - History.txt
37
+ - Manifest.txt
38
+ - README.txt
39
+ - Rakefile
40
+ - bin/active_excel
41
+ - lib/active_excel.rb
42
+ - test/test_active_excel.rb
43
+ has_rdoc: true
44
+ homepage: http://robsexocortex.blogspot.com/2009/06/activeexcel.html
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --main
50
+ - README.txt
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project: active_excel
68
+ rubygems_version: 1.3.5
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Use Excel to contain model objects. Each row in a sheet represents an object, each sheet in a workbook represents a class. Make sure that you rename your sheets - this gem uses ActiveSupport to take advantage of the pluralization familiar to Rails developers. Modeled liberally on ActiveRecord, not quite as cool but hopefully useful enough. Cheers.
72
+ test_files:
73
+ - test/test_active_excel.rb