robust_excel_ole 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,510 @@
1
+ = RobustExcelOle
2
+
3
+ robust_excel_ole processes Excel files, allows to perform all win32ole operations,
4
+ convenient methods for opening, saving and closing, and implements an Excel file management system.
5
+
6
+ This is work in progress.
7
+
8
+ == Requirements
9
+
10
+ * Ruby 1.8.6 or higher
11
+
12
+ == Install
13
+
14
+ gem install robust_excel_ole
15
+
16
+ == Usage
17
+
18
+ include RobustExcelOle
19
+
20
+ === Opening a book.
21
+
22
+ Example:
23
+
24
+ book = Book.open('simple.xls')
25
+
26
+ Open a book with a block.
27
+ The semantics is similar to, e.g., File.open.
28
+
29
+ Book.open('simple.xls') do |book|
30
+ # do something
31
+ end
32
+
33
+ Options are the following:
34
+
35
+ +:default_excel+:: open in the Excel instance used before if the book was once open (default: +reuse+)
36
+ +:force_excel+:: open in a new or given Excel instance (defaut: +:new+)
37
+ +:if_unsaved+:: specify behaviour if the book was unsaved (default: +new_excel+)
38
+ +:if_obstructed+:: specidy behaviour if the book is blocked by another book (default: +new_excel+)
39
+ +:read_only+:: open in read-only mode (default: +false+)
40
+ +:displayalerts+:: allow display alerts in Excel (default: +false+)
41
+ +:visible+:: make visibe in Excel (default: +false+)
42
+
43
+ The option +:defaut_excel+ :
44
+
45
+ If the book was open before, then open it in the Excel instance used before. If the book cannot be reopened, then
46
+
47
+ +:reuse+:: Connect to a running Excel, if it exists, open a new Excel otherwise.
48
+ +:new+:: Open in a new Excel.
49
+ [instance]:: Open in a given Excel instance.
50
+
51
+ The option +:force_excel :
52
+
53
+ No matter if the book was open before,
54
+
55
+ +:new+:: Open in a new Excel.
56
+ [instance]:: Open in a given Excel instance.
57
+
58
+ The option +:if_unsaved+ :
59
+
60
+ If an unsaved book with the same name is open, then
61
+
62
+ +:raise+:: Raise an exeption. Don't open the book.
63
+ +:accept+:: Let the unsaved book open.
64
+ +:forget+:: Discard any changes and reopen the book.
65
+ +:new_excel+:: Open the new book in a new Excel instance
66
+ +:alert+:: Give control to Excel.
67
+
68
+ The option +:if_obstructed+ :
69
+
70
+ If a book with same name in a different path is open, then
71
+
72
+ +:raise+:: Raise an exception. Don't open the book.
73
+ +:forget+:: Close the old book, open the new book.
74
+ +:save+:: Save the old book, close it, open the new book
75
+ +:close_if_saved+:: Close the old book and open the new book, if the old book is saved, raise an exception otherwise
76
+ +:new_excel+:: Open the new book in a new Excel instance.
77
+
78
+ The values :displayalerts and :visible are reached to the class Excel that controls opening and closing Excel instances.
79
+
80
+ === Closing a book.
81
+
82
+ Simple close.
83
+
84
+ book.close
85
+
86
+ The option is : +:if_unsaved+ . It can have one of the following values:
87
+
88
+ +:save+ (default), +:raise+, +:forget+, +:alert+
89
+
90
+ The option specifies: If the book is unsaved, then
91
+
92
+ +:save+:: Save the book before closing it.
93
+ +:raise+:: Raise an exception. Don't close the book.
94
+ +:forget+:: Close the book.
95
+ +:alert+:: Give control to Excel.
96
+
97
+
98
+ === Saving a book.
99
+
100
+ Simple save.
101
+
102
+ book.save
103
+
104
+ Saving a book with a file name.
105
+
106
+ book.save_as('another_simple.xls')
107
+
108
+ Options are the following:
109
+
110
+ +:if_exists+:: +:raise+ (default), +:overwrite+, +:alert+
111
+
112
+ The option +:if_exists+ :
113
+
114
+ If a book with the file name already exists, then
115
+
116
+ +:raise+:: Raise an exeption. Don't write the file.
117
+ +:overwrite+:: Delete the existing file and write the file. If the book is open in an Excel instance, then raise an exception.
118
+ +:alert+:: Give the control to Excel.
119
+
120
+
121
+ === Unobtrusively modifying a book
122
+
123
+ Sometimes the user wants to read and possibly modify a book, no matter if it is open in some Excel instance or not, is saved or unsaved. The method +unobtrusively+ provides this service. When modifying a book unobtrusively, its status remains unchanged. This status includes, wheter the book is opened or closed, saved or unsaved, readonly or writable. If the books were closed and the Excel instance are still running, then the book is opened in the Excel instance where it was opened most recently or in a new Excel. This is relevant if the book has references to other books.
124
+
125
+ Options are the following:
126
+
127
+ +:read_only+:: Open the book unobtrusively for reading only (default: false)
128
+ +:use_this+:: If the book is opened only as ReadOnly and shall be modified, then
129
+
130
+ true: close it and open it as writable in the excel instance where it was open so far
131
+ false (default): open it as writable in another running excel instance, if it exists
132
+ in a new excel instance, otherwise
133
+
134
+ +:visible+:: Make the book visible in the Excel (default: false)
135
+ +:keep_open+:: Let the book open after modification (default: false)
136
+
137
+ Book.unobtrusively('simple.xls') do |book|
138
+ # some modification
139
+ sheet = book[0]
140
+ sheet[0,0] = "c"
141
+ end
142
+
143
+ === Value of a named cell or range
144
+
145
+ Returning the value of a cell or range that has a with a defined name.
146
+
147
+ book.nvalue(name)
148
+
149
+ === Alive.
150
+
151
+ Checking whether the referenced Excel workbook responds to methods.
152
+
153
+ if book.alive? then sheet = book[0] end
154
+
155
+ === Make an Excel visible or invisible, and enable and disable DisplayAlerts.
156
+
157
+ Make an Excel visible
158
+
159
+ book.excel.visible = true
160
+
161
+ Enable DisplayAlerts.
162
+
163
+ book.excel.displayalerts = true
164
+
165
+ Options: +true+ -> enable DisplayAlerts , +false+ -> Disable DisplayAlerts
166
+
167
+
168
+ === Accessing a sheet.
169
+
170
+ A sheet object can be accessed with a Book#[] method via an integer number.
171
+
172
+ sheet = book[0]
173
+
174
+ Accessing a sheet object with the sheet name.
175
+
176
+ sheet = book['Sheet1']
177
+
178
+ Accessing sheet objects using the methods Book#each.
179
+
180
+ book.each do |sheet|
181
+ # do something with sheet
182
+ end
183
+
184
+ === Accessing a row or a column.
185
+
186
+ A sheet object is enumerable. Use the methods Sheet#each_column, Sheet#each_row or Sheet#each.
187
+
188
+ sheet.each do |cell|
189
+ # do something with cell
190
+ # read every row every column
191
+ end
192
+
193
+ sheet.each_row do |row|
194
+ # do something with row
195
+ end
196
+
197
+ sheet.each_column do |column|
198
+ # do something with column
199
+ end
200
+
201
+ === Accessing a cell.
202
+
203
+ Reading a cell from a sheet object.
204
+
205
+ sheet[0, 0] => first cell.
206
+
207
+ Reading a cell from a range object.
208
+
209
+ row_range[0] => first cell in row_range
210
+ column_range[1] => second cell in column_range
211
+
212
+ Reading the value of a cell.
213
+
214
+ cell = sheet[0,0]
215
+ cell.value => value of the cell.
216
+
217
+ Writing a cell
218
+
219
+ sheet[0,0] = "new_value"
220
+
221
+
222
+ === Accessing a range of a row or column.
223
+
224
+ Accessing a range of a row.
225
+
226
+ sheet.row_range(0) => first row
227
+ sheet.row_range(0, 0..2 ) => first three cells of the first row
228
+
229
+ Accessing a range of a column.
230
+
231
+ sheet.col_range(2) => third column
232
+ sheet.col_range(2, 0..1) => first two cells of the third column
233
+
234
+
235
+ === Adding a sheet.
236
+
237
+ Adding a new sheet.
238
+
239
+ book.add_sheet
240
+
241
+ Adding a new sheet with a name.
242
+
243
+ book.add_sheet(:as => 'new_sheet')
244
+
245
+ Adding a new sheet with a name before another sheet.
246
+
247
+ book.add_sheet(:as => 'new_sheet2', :before => another_sheet)
248
+
249
+ Adding a copy of a sheet with a name after another sheet.
250
+
251
+ book.add_sheet(sheet, :as => 'sheet_copy', :after => another_sheet)
252
+
253
+ === Value of a named cell or range
254
+
255
+ Returning the value of a cell or range that has a with a defined name.
256
+
257
+ sheet.nvalue(name)
258
+
259
+ === Creating and reusing an Excel instance.
260
+
261
+ Creating a new Excel.
262
+
263
+ excel1 = Excel.create
264
+
265
+ Getting a running Excel instance and reusing it.
266
+
267
+ excel2 = Excel.current
268
+
269
+ Reusing a running Excel instance, making it visible and turning on displayalerts.
270
+
271
+ excel2 = Excel.new(:reuse => true, :visible => true, :displayalerts => true).
272
+
273
+ Reusing a certain running Excel instance.
274
+
275
+ excel3 = Excel.new(:excel => excel1)
276
+
277
+ === Making Excel visible or invisible
278
+
279
+ Making Excel visible.
280
+
281
+ excel = Excel.create
282
+ excel.visible = true
283
+ puts "visible" if excel.visible
284
+
285
+ Making Excel invisible
286
+
287
+ excel.visible = false
288
+
289
+ === Turning on or off Displayalerts.
290
+
291
+ Turning DisplayAlerts on.
292
+
293
+ excel = Excel.create
294
+ excel.displayalerts = true
295
+ puts "allows displayalerts" if excel.displayalerts
296
+
297
+ Turning DisplayAlerts off.
298
+
299
+ excel.displayalerts = false
300
+
301
+ Turning on and off in a block.
302
+
303
+ with_displayalerts
304
+
305
+ excel = Excel.create
306
+ excel.with_displayalerts true do
307
+ book = Book.open('simple.xls')
308
+ end
309
+
310
+ === Closing all Excel instances.
311
+
312
+ Excel.close_all
313
+
314
+ === Examples
315
+
316
+ Including robust_excel_ole.
317
+
318
+ include RobustExcelOle
319
+
320
+ === Example 1
321
+
322
+ Opening a book.
323
+
324
+ book = Book.open('simple.xls')
325
+
326
+ Accessing a sheet via its name.
327
+
328
+ sheet = book['Sheet1']
329
+
330
+ Changing the first cell.
331
+
332
+ sheet[0,0] = "new"
333
+
334
+ Saving the book.
335
+
336
+ book.save
337
+
338
+ Saving the book with a different name, and overwrite if a file with this name exists.
339
+
340
+ book.save_as('different_simple.xls', :if_exists => :overwrite)
341
+
342
+ Closing the book.
343
+
344
+ book.close
345
+
346
+ === Example 2
347
+
348
+ Opening a book.
349
+
350
+ book = Book.open('simple.xls')
351
+
352
+ Opening the book in a new Excel instance and make it visible.
353
+
354
+ new_book = Book.open('simple.xls', :force_excel => :new, :visible => true)
355
+
356
+ Opening the book in a given Excel instance.
357
+
358
+ another_book = Book.open('simple.xls', :force_excel => book.excel)
359
+
360
+ Closing the books.
361
+
362
+ book.close
363
+ new_book.close
364
+ another_book.close
365
+
366
+ Reopening the book.
367
+
368
+ reopened_book = Book.open('simple.xls')
369
+
370
+ The writable book is being prefered.
371
+
372
+ reopened_book == book
373
+ => true
374
+
375
+ Opening another book.
376
+ Since the book was not open before, reopening the book fails and the :default_excel option applies.
377
+ According to :default_excel => :new a new Excel is created, and the book is opened there.
378
+
379
+ different_book = Book.open('different.xls', :default_excel => :new)
380
+
381
+
382
+ === Example 3
383
+
384
+ Opening a book.
385
+
386
+ book = Book.open('simple.xls')
387
+
388
+ Adding a copy of the first sheet after the second sheet.
389
+
390
+ book.add_sheet(book[0], :as => 'Sheet1_copy', :after => book[1])
391
+
392
+ Close the book.
393
+
394
+ Opening a new book with the same name in a new Excel. Leave the book that contains unsaved changes in the old Excel.
395
+
396
+ new_book = Book.open('simple.xls', :if_unsaved => :new_excel)
397
+
398
+ Accessing a sheet and change a cell.
399
+
400
+ sheet = new_book[0]
401
+ sheet[1,1] = "another"
402
+
403
+ Opening another book with the same name in the running Excel. The book that contains unsaved changes will be closed before.
404
+
405
+ third_book = Book.open('simple.xls', :if_unsaved => :forget)
406
+
407
+ Adding a sheet.
408
+
409
+ third_book.add_sheet
410
+
411
+ Closing the book without saving it.
412
+
413
+ third_book.close(:if_unsaved => :forget)
414
+
415
+ Closing the first book and saving it before.
416
+
417
+ book.close(:if_unsaved => :save)
418
+
419
+ === Example 4
420
+
421
+ Opening a book.
422
+
423
+ book1 = Book.open('simple.xls')
424
+
425
+ Opening a book with the same name in a different path. Close the old book.
426
+
427
+ book2 = Book.open('more/simple.xls', :if_obstructed => :forget)
428
+
429
+ Changing its cell.
430
+
431
+ sheet = book2[0]
432
+ sheet[0,0] = "new"
433
+
434
+ Opening a book with the same name in a different path. The old book that was modified will be saved and closed before.
435
+
436
+ book3 = Book.open('simple.xls', :if_obstructed => :save)
437
+
438
+ Opening a book with the same name in a different path. The other book will be closed, because it does not contain unsaved changes.
439
+
440
+ book4 = Book.open('more/simple.xls', :if_obstructed => :close_if_unsaved)
441
+
442
+ Closing the book.
443
+
444
+ book4.close
445
+
446
+
447
+ === Example 5
448
+
449
+ Opening a book.
450
+
451
+ book = Book.open('simple.xls')
452
+
453
+ Printing its first cell.
454
+
455
+ sheet = book[0]
456
+ p "1st cell: #{sheet[0,0].value}"
457
+
458
+ Unobtrusively modify the book.
459
+
460
+ Book.unobtrusively('simple.xls') do |book|
461
+ sheet = book[0]
462
+ sheet[0,0] = 'simple'
463
+ end
464
+
465
+ The book is modified, but its status is unchanged.
466
+
467
+ new_sheet = book[0]
468
+ not (new_sheet[0,0].value == sheet[0,0].value)
469
+ => true
470
+
471
+ book.Saved
472
+ => true
473
+
474
+
475
+ === Development
476
+
477
+ robust_excel_ole started as a simple fork from tomiacannondale's wrap_excel adapted to Ruby 1.8.6.
478
+ The functionality of wrap_excel is optimised and extended by new features.
479
+ Most notable extensions include:
480
+ * books can be opened in already running Excel instances (instead of opening a new Excel whenever a book is opened)
481
+ * a book management system stores all books that have been open. This book store is being used, e.g., for reopening a book that has been closed before. It provides transperency identity, i.e., equal Excel books correspond to equal Book objects of RobustExcelOle.
482
+
483
+ Some features in robust_excel_ole that are not compatible with wrap_excel:
484
+ * +open+ uses by default a running Excel instance instead of creating a new one,
485
+ and opens a book by default in writable mode instead of read_only
486
+ * +close+ closes the workbook instead of closing all workbooks and the Excel instance.
487
+ * +save_as+ instead of +save+.
488
+
489
+
490
+ === Want to do more things
491
+
492
+ All RobustExcelOle objects include the win32ole instance.
493
+ If you want to do something that not provide a function, you can use win32ole methods.
494
+
495
+ == Support
496
+
497
+ This is work in progress. Please contact us and to report issues and feature requests to github Issues.
498
+ https://github.com/Thomas008/robust_excel_ole/issues
499
+
500
+ == Collaborate
501
+
502
+ Please pull request on github.
503
+
504
+ == Author
505
+
506
+ thomas mailto:Thomas.Raths@gmx.net
507
+
508
+ == License
509
+
510
+ MIT License. For more imformation, please see LICENSE.
data/TodoList.md CHANGED
@@ -1,27 +1,34 @@
1
1
 
2
2
  ### immediately
3
3
 
4
- --- 2015-04-09 unobtrusively: save book only if it saved: Test
5
- --- 2015-04-09 unobtrusively: return the block result: implementation and test
6
- --- 2015-04-09 unobtrusively: namval: return the contents of cells or region with a given name
7
- --- 2015-04-09 unobtrusively: visible, displayalerts
8
- --- 2015-04-17 unobtrusively: readonly
9
-
4
+ --- 2015.05-05 unobtrusively:
5
+ more tests,
6
+ --- 2015-04-27 excel.rb: implement sucht that remove attr_writer
7
+ --- 2015-04-27 documentation: a crisp one and a detailed one, better examples
8
+ --- 2015-04-02 set options: make it dry
9
+ --- 2015-04-17 acceptance test from Testschmiede
10
10
 
11
11
  ### quick
12
12
 
13
+ --- 2015-05-09 open with option :reuse_excel:
14
+ choose the last opened Excel that is different to a certain Excel, if it exists,
15
+ open a new Excel, else
16
+
17
+ ### short-term
18
+
19
+ --- 2015-04-17 excel managements system
13
20
  --- 2015-04-02 if_unlocked
14
21
  --- 2015-04-02 standard use cases
15
- --- 2015-04-02 set options: make it dry
16
-
17
- ### rather quick
22
+ --- 2015-04-27 excel instances list
18
23
 
19
- ### medium
24
+ ### mid-term
20
25
 
21
- ### slow
26
+ ### long-term
22
27
 
23
28
  ### done
24
29
 
30
+ --- 2015-04-17 unobtrusively: readonly
31
+ --- 2015-04-27 tests for life cycle (weakrefs to books)
25
32
  --- 2015-04-01 examples for unobtrusively
26
33
  --- 2015-04-01 further tests for unobtrusively
27
34
  --- 2015-03-26 connnect: check test outputs
@@ -31,3 +38,6 @@
31
38
  --- 2015-01-26 unobtrusively
32
39
  --- 2015-01-26 option keep_open
33
40
  --- 2015-01-26 separate class for book management
41
+ --- 2015-04-09 unobtrusively: save book only if it saved: Test
42
+ --- 2015-04-09 unobtrusively: return the block result: implementation and test
43
+ --- 2015-04-09 unobtrusively: namval: return the contents of cells or region with a given name
@@ -12,7 +12,7 @@ begin
12
12
  dir = create_tmpdir
13
13
  file_name = dir + 'simple.xls'
14
14
  book = Book.open(file_name) # open a book
15
- book.visible = true # make current Excel visible
15
+ book.excel.visible = true # make current Excel visible
16
16
  sleep 1
17
17
  sheet = book[0] # access a sheet
18
18
  sheet[0,0] = sheet[0,0].value == "simple" ? "complex" : "simple" # change a cell
@@ -15,7 +15,7 @@ begin
15
15
  file_name3 = dir + 'book_with_blank.xls'
16
16
  file_name4 = dir + 'merge_cells.xls'
17
17
  book1 = Book.open(file_name1) # open a book in a new Excel instance since no Excel is open
18
- book1.visible = true # make current Excel visible
18
+ book1.excel.visible = true # make current Excel visible
19
19
  sleep 2
20
20
  book1.close # close the book
21
21
  sleep 2
@@ -12,12 +12,12 @@ begin
12
12
  dir = create_tmpdir
13
13
  simple_file = dir + 'simple.xls'
14
14
  book1 = Book.open(simple_file) # open a book in a new Excel instance since no Excel is open
15
- book1.visible = true # make current Excel visible
15
+ book1.excel.visible = true # make current Excel visible
16
16
  sleep 2
17
17
  book2 = Book.open(simple_file) # open a new book in the same Excel instance
18
18
  p "book1 == book2" if book2 == book1 # the books are identical
19
19
  sleep 2
20
- book3 = Book.open(simple_file, :force_excel => :new, :visible => true) # open another book in a new Excel instance, # make Excel visible
20
+ book3 = Book.open(simple_file, :force_excel => :new, :visible => true) # open another book in a new Excel instance,
21
21
  p "book3 != book1" if (not (book3 == book1)) # the books are not identical
22
22
  sleep 2
23
23
  new_excel = Excel.new(:reuse => false) # create a third Excel instance
@@ -12,7 +12,7 @@ begin
12
12
  dir = create_tmpdir
13
13
  file_name = dir + 'simple.xls'
14
14
  book = Book.open(file_name) # open a book
15
- book.visible = true # make current Excel visible
15
+ book.excel.visible = true # make current Excel visible
16
16
  sleep 1
17
17
  sheet = book[0] # access a sheet
18
18
  first_cell = sheet[0,0].value
@@ -12,8 +12,8 @@ begin
12
12
  dir = create_tmpdir
13
13
  file_name = dir + 'simple.xls'
14
14
  book = Book.open(file_name) # open a book
15
- book.visible = true # make current Excel visible
16
- sleep 1
15
+ book.excel.visible = true # make current Excel visible
16
+ sleep
17
17
  sheet = book[0] # access a sheet
18
18
  first_cell = sheet[0,0].value
19
19
  sheet[0,0] = first_cell == "simple" ? "complex" : "simple" # change a cell
@@ -12,7 +12,7 @@ begin
12
12
  dir = create_tmpdir
13
13
  file_name = dir + 'simple.xls'
14
14
  book = Book.open(file_name) # open a book. default: :read_only => false
15
- book.visible = true # make current Excel visible
15
+ book.excel.visible = true # make current Excel visible
16
16
  sheet = book[0]
17
17
  #sheet.Names.Add("Wert","$A$1"
18
18
 
@@ -14,7 +14,7 @@ begin
14
14
  file_name3 = dir + 'different_simple.xls'
15
15
  file_name4 = dir + 'book_with_blank.xls'
16
16
  book1 = Book.open(file_name1) # open a book in a new Excel instance since no Excel is open
17
- book1.visible = true # make current Excel visible
17
+ book1.excel.visible = true # make current Excel visible
18
18
  sleep 2
19
19
  book2 = Book.open(file_name2) # open a new book in the same Excel instance
20
20
  sleep 2
@@ -13,7 +13,7 @@ begin
13
13
  file_name = dir + 'simple.xls'
14
14
  other_file_name = dir + 'different_simple.xls'
15
15
  book = Book.open(file_name) # open a book. default: :read_only => false
16
- book.visible = true # make current Excel visible
16
+ book.excel.visible = true # make current Excel visible
17
17
  sheet = book[0] # access a sheet
18
18
  sleep 1
19
19
  sheet[0,0] = sheet[0,0].value == "simple" ? "complex" : "simple" # change a cell