robust_excel_ole 1.0.3 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
data/Changelog CHANGED
@@ -1,6 +1,10 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [1.1] - 2017-09-29
5
+
6
+ ## [1.0.4] - 2017-08-30
7
+
4
8
  ## [1.0.3] - 2017-08-27
5
9
 
6
10
  ## [1.0.2] - 2017-07-26
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = RobustExcelOle
2
2
 
3
- This ruby gem automates modifying, reading and writing Excel files.
3
+ This ruby gem automates reading, modifying, and writing Excel files.
4
4
  It supports simultaneously running Excel instances and user interactions.
5
5
  RobustExcelOle deals with various cases of Excel and user behaviour,
6
6
  and implements workarounds for some Excel bugs.
@@ -9,7 +9,7 @@ It supports Excel 2010.
9
9
 
10
10
  RobustExcelOle works by sending VBA methods via Win32OLE.
11
11
  Moreover, it implements a management system and keeps track of Excel files and Excel instances.
12
- The tool is optimised with help of rcov.
12
+ The tool is optimised with help of the rcov tool.
13
13
 
14
14
  == Requirements
15
15
 
@@ -28,40 +28,71 @@ The tool is optimised with help of rcov.
28
28
 
29
29
  In the following, some features of RobustExcelOle are depicted.
30
30
 
31
- RobustExcelOle allows a "script mode" and an "interactive mode": Commands enable to open Excel files (or workbooks) in various Excel instances, enable to close, reopen, modify and save the Excel files, without the need of the user's interaction, and even without the user noticing. While running this script mode, the user can open and modify any Excel files in any Excel instances at any time. RobustExcelOle manages the complex cases of conflicts that might occur such that the user does not need to interfere and the script can continue.
31
+ RobustExcelOle enables opening and processing Excel files (or workbooks) in several Excel instances. Using more than one Excel process allows, e.g., running a script that operates in one Excel instance, while a user (or another script) modifies workbooks in another Excel instance.
32
32
 
33
- For example, suppose you want to process a list of workbooks (Excel files). RobustExcelOle allows to rapidly open, manipulate, close and save these workbooks (script mode). Now assume, the workbook "workbook.xls" is being processed, while the user has opened this workbook, has manipulated but not saved it yet. Excel would prompt a message and ask the user what to do. RobustExcelOle solves this conflict by using several options that state whether the changes of the user should be saved (accepted) or discarded before opening the workbook.
33
+ For example, suppose you want to open a workbook and make it visible.
34
34
 
35
- book1 = Book.open('workbook.xls') # user
36
- ...
37
- book2 = Book.open('workbook.xls', :if_unsaved => accept) # script
35
+ book1 = Book.open('workbook.xls', :visible => true)
36
+
37
+ Now we want to open another workbook in a different Excel instance.
38
+
39
+ book2 = Book.open('workbook2.xls', :force => {:excel => :new}, :visible => true)
40
+
41
+ We can also create a third Excel instance and open another workbook in this instance.
42
+
43
+ excel1 = Excel.create
44
+ book3 = Book.open('workbook3.xls', :force => {:excel => excel1}, :visible => true)
45
+
46
+ Another feature that RobustExcelOle povides is reopening workbooks after closing them.
47
+
48
+ book1.close
49
+ book1.reopen
50
+
51
+ A workbook is opened by default in the Excel instance where it was open before most recently.
52
+
53
+ book1.close
54
+ book1 = Book.open('workbook.xls')
55
+
56
+ If this Excel instance is damaged or closed, then options control whether the workbook shall be opened in the current (active), a new or a given Excel instance.
57
+
58
+ book1 = Book.open('workbook.xls', :default => {:excel => :new})
38
59
 
39
- Similarly, if the user has opened a workbook that has the same name but a different path, the conflict is solved via options.
60
+ The workbook can also be forced to be opened in the current, new or given Excel instance, no matter if and where it was opened before, e.g.
61
+
62
+ book2 = Book.open('workbook.xls', :force => {:excel => excel1})
63
+
64
+ As a further feature, RobustExcelOle allows processing workbooks, while still supporting user's interactions: The commands enable to open, close, reopen, read, modify, write and save Excel files, without the need of the user's interaction, and even without the user noticing. Thus, while running a script containing RobustExcelOle commands, the user can open and process Excel files in any Excel instances at any time. RobustExcelOle manages the complex cases of conflicts that might occur such that the user does not need to interfere and the script can continue.
65
+
66
+ For example, suppose you want to process a list of workbooks. RobustExcelOle allows to rapidly open, manipulate, close and save these workbooks. Now assume, the workbook "workbook.xls" is being processed, while the user has opened this workbook, has modified but not saved it yet. Excel would prompt a message and ask the user what to do. RobustExcelOle solves this conflict by using an option that states whether the changes of the user should be saved (accepted) or discarded before opening the workbook:
67
+
68
+ book = Book.open('workbook.xls', :if_unsaved => :accept)
69
+
70
+ Similarly, if the user has opened a workbook that has the same name but a different path, the conflict is solved via an option.
40
71
 
41
72
  book1 = Book.open('path1/workbook.xls')
42
73
  ...
43
74
  book2 = Book.open('workbook.xls', :if_obstructed => :forget)
44
75
 
45
- Another feature that RobustExcelOle povides is reopening workbooks after closing them. A workbook is opened by default in the Excel instance where it was open before most recently. If this Excel instance is damaged or closed, then RobustExcelIle controls via options whether the workbook is opened in the current (active) Excel instance, a new or a given Excel instance, e.g.
76
+ There are twelve options that control opening workbooks.
46
77
 
47
- book1 = Book.open('workbook.xls', :default => {:excel => :new})
48
-
49
- Moreover, RobustExcelOle allows unobtrusively reading and modifying workbooks, i.e. accessing workbooks without changing their "status". The status comprises whether the workbook is open or closed, saved or unsaved, read-only or writable, visible or invisible, calculation mode is manual or automatic, and checking compatibility is done or not done.
78
+ Finally, RobustExcelOle allows unobtrusively reading and modifying workbooks, i.e. accessing workbooks without changing their "status". The status comprises whether the workbook is open or closed, saved or unsaved, read-only or writable, visible or invisible, whether the calculation mode is manual or automatic, and checking compatibility is done or not done.
50
79
 
51
80
  Book.for_modifying('workbook.xls') do |book|
52
- ...
81
+ # do something
53
82
  end
54
83
 
55
84
  Book.for_reading('workbook.xls') do |book|
56
- ...
85
+ # do something
57
86
  end
58
87
 
59
- === The Book objects and transperence identity
88
+ === The Book objects and identity transparency
60
89
 
61
- An Excel file (or workbook) is represented by a Book object. A Book object is defined by the full name of the workbook and the Excel instance in which it is opened. RobustExcelOle aims to ensure identity transperency.
62
- Identity transparence means that the same Book objects refer to the same Excel files, and vice versa.
90
+ An Excel file (or workbook) is represented by a Book object. A Book object is defined by the full name of the workbook and the Excel instance in which it is opened. RobustExcelOle aims to ensure identity transparency.
91
+ Identity transparency means that the same Book objects refer to the same Excel files, and vice versa.
63
92
  In other words, a Book objects is a proxy of an Excel file.
64
93
 
94
+ Here are some more details about opening, closing, reading, writing and modifying Excel files.
95
+
65
96
  === Opening and closing workbooks
66
97
 
67
98
  Let's have a look at an example. Suppose, we want to open a workbook.
@@ -98,7 +129,7 @@ Reopening this workbook is done by
98
129
 
99
130
  book2.reopen
100
131
 
101
- === Modifying workbooks
132
+ === Reading and modifying workbooks
102
133
 
103
134
  We can get the value of a named range.
104
135
 
@@ -116,7 +147,7 @@ or
116
147
 
117
148
  book2.set_nameval("new", "bar")
118
149
 
119
- Now we access the first worksheet by
150
+ Then we access the first worksheet by
120
151
 
121
152
  sheet1 = book2.sheet(1)
122
153
 
@@ -156,7 +187,7 @@ and set the value
156
187
 
157
188
  sheet1.set_nameval("firstcell", "foo")
158
189
 
159
- We get the value of a range of a locally defined name.
190
+ We get the value of a range of a locally defined name.
160
191
 
161
192
  sheet1.rangeval("firstcell") # => "foo"
162
193
 
@@ -172,7 +203,7 @@ We can copy the first worksheet, name it and add it before the third worksheet.
172
203
 
173
204
  book2.add_or_copy_sheet(sheet1, :as => "copied_name, :before => book2.last_sheet)
174
205
 
175
- === Saving workbooks
206
+ === Saving (writing) workbooks
176
207
 
177
208
  Simple save is done by
178
209
 
@@ -200,7 +231,6 @@ or
200
231
 
201
232
  excel1 = Excel.new(:reuse => true)
202
233
 
203
-
204
234
  Now we want to start a new, visible Excel instance.
205
235
 
206
236
  excel2 = Excel.create(:visible => true)
@@ -213,7 +243,7 @@ We open a workbook in this Excel instance.
213
243
 
214
244
  book4 = Book.open('more_data/workbook', {:force => {:excel => excel2}})
215
245
 
216
- We can close Closing an Excel instance is dony by
246
+ We close the Excel instance by
217
247
 
218
248
  excel1.close
219
249
 
@@ -245,7 +275,7 @@ and set its value by
245
275
 
246
276
  excel2.set_rangeval("firstcell, "bar")
247
277
 
248
- Closing all Excel instances ist done by
278
+ Closing all Excel instances is done by
249
279
 
250
280
  Excel.close_all(:if_unsaved => :forget)
251
281
 
@@ -255,7 +285,7 @@ Hard terminating all Excel processes is done by
255
285
 
256
286
  === More details
257
287
 
258
- {Readme_detail.rdoc}[file:../Readme_detail.rdoc]
288
+ {README_detail.rdoc}[https://github.com/Thomas008/robust_excel_ole/blob/master/README_detail.rdoc]
259
289
 
260
290
  === Want to do more things
261
291
 
data/README_detail.rdoc CHANGED
@@ -219,6 +219,24 @@ If a workbook blocks the workbook that should be saved, then the former one can
219
219
  book2 = Book.open('another_workbook.xls')
220
220
  book2.save_as('dir/workbook.xls', :if_exists => :overwrite, :if_obstructed => :save)
221
221
 
222
+ === Opening, closing and saving a workbook under a certain name
223
+
224
+ You can open a workbook with given file name.
225
+
226
+ book = Book.open('workbook.xls')
227
+
228
+ You can save a workbook with given file name, if it is open.
229
+
230
+ Book.save('workbook.xls')
231
+
232
+ The workbook can be saved under a new file name, if it is open.
233
+
234
+ Book.save_as('workbook.xls', 'new_workbook.xls')
235
+
236
+ Finally the workbook can be closed with a given filename.
237
+
238
+ Book.close('workbook.xls')
239
+
222
240
  === Unobtrusively modifying a workbook
223
241
 
224
242
  The method +unobtrusively+ enables the user to read or modify a workbook, no matter if it is open in some Excel instance, if it is saved or unsaved, and if it is writable or not. When opening a workbook unobtrusively, its status remains unchanged. This status includes, whether the workbook is opened or closed, saved or unsaved, readonly or writable, visible or invisible, calculation mode is automatic or manual, and checking compatibility is turned on or off.
@@ -328,12 +328,8 @@ module RobustExcelOle
328
328
  filename = General::absolute_path(file)
329
329
  begin
330
330
  workbooks = @excel.Workbooks
331
- rescue RuntimeError => msg
332
- if msg.message =~ /method missing: Excel not alive/
333
- raise ExcelDamaged, "Excel instance not alive or damaged"
334
- else
335
- raise UnexpectedError, "unknown RuntimeError: #{msg.message}"
336
- end
331
+ rescue WIN32OLERuntimeError => msg
332
+ raise UnexpectedError, "WIN32OLERuntimeError: #{msg.message} #{msg.backtrace}"
337
333
  end
338
334
  begin
339
335
  with_workaround_linked_workbooks_excel2007(options) do
@@ -343,15 +339,14 @@ module RobustExcelOle
343
339
  rescue WIN32OLERuntimeError => msg
344
340
  # for Excel2007: for option :if_unsaved => :alert and user cancels: this error appears?
345
341
  # if yes: distinguish these events
346
- #raise
347
- # trace "WIN32OLERuntimeError: #{msg.message}"
342
+ raise UnexpectedError, "WIN32OLERuntimeError: #{msg.message} #{msg.backtrace}"
348
343
  end
349
344
  begin
350
345
  # workaround for bug in Excel 2010: workbook.Open does not always return the workbook when given file name
351
346
  begin
352
347
  @ole_workbook = workbooks.Item(File.basename(filename))
353
348
  rescue WIN32OLERuntimeError => msg
354
- raise UnexpectedError, "unexpected WIN32OLERuntimeError: #{msg.message}"
349
+ raise UnexpectedError, "WIN32OLERuntimeError: #{msg.message}"
355
350
  end
356
351
  if options[:force][:visible].nil? && (not options[:default][:visible].nil?)
357
352
  if @excel.created
@@ -366,7 +361,7 @@ module RobustExcelOle
366
361
  @excel.calculation = options[:calculation] unless options[:calculation].nil?
367
362
  self.Saved = true # unless self.Saved # ToDo: this is too hard
368
363
  rescue WIN32OLERuntimeError => msg
369
- raise UnexpectedError, "unexpected WIN32OLERuntimeError: #{msg.message} #{msg.backtrace}"
364
+ raise UnexpectedError, "WIN32OLERuntimeError: #{msg.message} #{msg.backtrace}"
370
365
  end
371
366
  end
372
367
  end
@@ -556,7 +551,7 @@ module RobustExcelOle
556
551
  if msg.message =~ /SaveAs/ and msg.message =~ /Workbook/ then
557
552
  raise WorkbookNotSaved, "workbook not saved"
558
553
  else
559
- raise UnexpectedError, "unknown WIN32OELERuntimeError:\n#{msg.message}"
554
+ raise UnexpectedError, "unknown WIN32OLERuntimeError:\n#{msg.message}"
560
555
  end
561
556
  end
562
557
  true
@@ -656,6 +651,24 @@ module RobustExcelOle
656
651
 
657
652
  public
658
653
 
654
+ # closes a given file if it is open
655
+ def self.close(file, opts = {:if_unsaved => :raise})
656
+ book = bookstore.fetch(file) rescue nil
657
+ book.close(opts) if book && book.alive?
658
+ end
659
+
660
+ # saves a given file if it is open
661
+ def self.save(file)
662
+ book = bookstore.fetch(file) rescue nil
663
+ book.save if book && book.alive?
664
+ end
665
+
666
+ # saves a given file under a new name if it is open
667
+ def self.save_as(file, new_file, opts = { })
668
+ book = bookstore.fetch(file) rescue nil
669
+ book.save_as(new_file, opts) if book && book.alive?
670
+ end
671
+
659
672
  # returns a sheet, if a sheet name or a number is given
660
673
  # @param [String] or [Number]
661
674
  # @returns [Sheet]
@@ -350,7 +350,7 @@ module RobustExcelOle
350
350
  #trace $!.backtrace.first(9).join "\n"
351
351
  end
352
352
  end
353
- trace "went through #{anz_objekte} OLE objects"
353
+ #trace "went through #{anz_objekte} OLE objects"
354
354
  end
355
355
 
356
356
 
@@ -361,12 +361,13 @@ module RobustExcelOle
361
361
  # kill all Excel instances
362
362
  # @return [Fixnum] number of killed Excel processes
363
363
  def self.kill_all
364
- procs = WIN32OLE.connect("winmgmts:\\\\.")
365
- processes = procs.InstancesOf("win32_process")
366
- number = processes.select{|p| (p.name == "EXCEL.EXE")}.size
367
- procs.InstancesOf("win32_process").each do |p|
364
+ number = 0
365
+ WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process").each do |p|
368
366
  begin
369
- Process.kill('KILL', p.processid) if p.name == "EXCEL.EXE"
367
+ if p.name == "EXCEL.EXE"
368
+ Process.kill('KILL', p.processid)
369
+ number += 1
370
+ end
370
371
  rescue
371
372
  #trace "kill error: #{$!}"
372
373
  end
@@ -376,7 +377,8 @@ module RobustExcelOle
376
377
  end
377
378
 
378
379
  def self.excels_number
379
- WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process").select{|p| (p.name == "EXCEL.EXE")}.size
380
+ processes = WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process")
381
+ processes.select{ |p| p.name == "EXCEL.EXE"}.size
380
382
  end
381
383
 
382
384
  # provide Excel objects
@@ -394,8 +396,10 @@ module RobustExcelOle
394
396
  pid2excel[pid] = excel
395
397
  end
396
398
  end
397
- procs = WIN32OLE.connect("winmgmts:\\\\.")
398
- processes = procs.InstancesOf("win32_process")
399
+ processes = WIN32OLE.connect("winmgmts:\\\\.").InstancesOf("win32_process")
400
+ #excel_processes = processes.select{ |p| p.name == "EXCEL.EXE" && pid2excel.include?(p.processid)}
401
+ #excel_processes.map{ |p| Excel.new(pid2excel[p.processid]) }
402
+ processes.select{ |p| Excel.new(pid2excel[p.processid]) if p.name == "EXCEL.EXE" && pid2excel.include?(p.processid)}
399
403
  result = []
400
404
  processes.each do |p|
401
405
  if p.name == "EXCEL.EXE"
@@ -486,7 +490,7 @@ module RobustExcelOle
486
490
  raise FileNotFound, "could not save workbook with filename #{file_name.inspect}"
487
491
  else
488
492
  # todo some time: find out when this occurs :
489
- raise UnexpectedError, "unknown WIN32OELERuntimeError with filename #{file_name.inspect}: \n#{msg.message}"
493
+ raise UnexpectedError, "unknown WIN32OLERuntimeError with filename #{file_name.inspect}: \n#{msg.message}"
490
494
  end
491
495
  end
492
496
  end
@@ -730,5 +734,9 @@ module RobustExcelOle
730
734
  end
731
735
  end
732
736
 
733
- end
737
+ end
734
738
  end
739
+
740
+ class WIN32OLE
741
+ include Enumerable
742
+ end
@@ -1,4 +1,4 @@
1
- include Enumerable
1
+ # -*- coding: utf-8 -*-
2
2
 
3
3
  module General
4
4
 
@@ -118,5 +118,4 @@ module MethodHelpers
118
118
 
119
119
  end
120
120
 
121
- #REO = General
122
- REO = RobustExcelOle
121
+ REO = RobustExcelOle
@@ -1,3 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
1
3
  LOG_TO_STDOUT = true unless Object.const_defined?(:LOG_TO_STDOUT)
2
4
  REO_LOG_DIR = "" unless Object.const_defined?(:REO_LOG_DIR)
3
5
  REO_LOG_FILE = "reo.log" unless Object.const_defined?(:REO_LOG_FILE)
@@ -1,3 +1,3 @@
1
1
  module RobustExcelOle
2
- VERSION = "1.0.3"
2
+ VERSION = "1.1"
3
3
  end
data/spec/book_spec.rb CHANGED
@@ -29,6 +29,7 @@ describe Book do
29
29
  @simple_file_xlsx = @dir + '/workbook.xlsx'
30
30
  @simple_file1 = @simple_file
31
31
  @simple_file_other_path1 = @simple_file_other_path
32
+ @simple_save_file1 = @simple_save_file
32
33
  end
33
34
 
34
35
  after do
@@ -48,6 +49,89 @@ describe Book do
48
49
  end
49
50
  end
50
51
 
52
+ describe "Book::save" do
53
+
54
+ it "should save a file, if it is open" do
55
+ @book = Book.open(@simple_file)
56
+ @book.add_sheet(@sheet, :as => 'a_name')
57
+ @new_sheet_count = @book.ole_workbook.Worksheets.Count
58
+ expect {
59
+ Book.save(@simple_file)
60
+ }.to_not raise_error
61
+ @book.ole_workbook.Worksheets.Count.should == @new_sheet_count
62
+ @book.close
63
+ end
64
+
65
+ it "should not save a file, if it is not open" do
66
+ @book = Book.open(@simple_file)
67
+ @book.add_sheet(@sheet, :as => 'a_name')
68
+ @new_sheet_count = @book.ole_workbook.Worksheets.Count
69
+ @book.close(:if_unsaved => :forget)
70
+ expect {
71
+ Book.save(@simple_file)
72
+ }.to_not raise_error
73
+ end
74
+
75
+ end
76
+
77
+ describe "Book::save_as" do
78
+
79
+ it "should save to 'simple_save_file.xls'" do
80
+ book = Book.open(@simple_file1)
81
+ Book.save_as(@simple_file1, @simple_save_file1, :if_exists => :overwrite)
82
+ File.exist?(@simple_save_file1).should be_true
83
+ end
84
+ end
85
+
86
+ describe "Book::close" do
87
+
88
+ it "should close the book if it is open" do
89
+ book = Book.open(@simple_file1)
90
+ Book.close(@simple_file1)
91
+ book.should_not be_alive
92
+ end
93
+
94
+ it "should not close the book if it is not open" do
95
+ book = Book.open(@simple_file1, :visible => true)
96
+ book.close
97
+ Book.close(@simple_file1)
98
+ book.should_not be_alive
99
+ end
100
+
101
+ it "should raise error if the book is unsaved and open" do
102
+ book = Book.open(@simple_file1)
103
+ sheet = book.sheet(1)
104
+ book.add_sheet(sheet, :as => 'a_name')
105
+ expect{
106
+ Book.close(@simple_file1)
107
+ }.to raise_error(WorkbookNotSaved, /workbook is unsaved: "workbook.xls"/)
108
+ expect{
109
+ Book.close(@simple_file, :if_unsaved => :raise)
110
+ }.to raise_error(WorkbookNotSaved, /workbook is unsaved: "workbook.xls"/)
111
+ end
112
+
113
+ it "should save and close the book" do
114
+ book = Book.open(@simple_file1)
115
+ sheet_count = book.ole_workbook.Worksheets.Count
116
+ sheet = book.sheet(1)
117
+ book.add_sheet(sheet, :as => 'a_name')
118
+ ole_workbook = book.ole_workbook
119
+ excel = book.excel
120
+ excel.Workbooks.Count.should == 1
121
+ Book.close(@simple_file1, {:if_unsaved => :save})
122
+ excel.Workbooks.Count.should == 0
123
+ book.ole_workbook.should == nil
124
+ book.should_not be_alive
125
+ expect{ole_workbook.Name}.to raise_error(WIN32OLERuntimeError)
126
+ new_book = Book.open(@simple_file1)
127
+ begin
128
+ new_book.ole_workbook.Worksheets.Count.should == sheet_count + 1
129
+ ensure
130
+ new_book.close
131
+ end
132
+ end
133
+ end
134
+
51
135
  describe "open" do
52
136
 
53
137
  context "with various file formats" do
Binary file
Binary file
data/spec/excel_spec.rb CHANGED
@@ -1568,6 +1568,12 @@ module RobustExcelOle
1568
1568
  excel.close
1569
1569
  end
1570
1570
 
1571
+ it "should return list of two Excel processes" do
1572
+ excel1 = Excel.create
1573
+ excel2 = Excel.create
1574
+ Excel.excel_processes.should == [excel1,excel2]
1575
+ end
1576
+
1571
1577
  it "should return list of two Excel processes" do
1572
1578
  excel1 = Excel.new
1573
1579
  excel2 = Excel.current
@@ -1575,6 +1581,8 @@ module RobustExcelOle
1575
1581
  Excel.excel_processes.should == [excel1,excel3]
1576
1582
  end
1577
1583
 
1584
+
1585
+
1578
1586
  end
1579
1587
 
1580
1588
  context "with hwnd and hwnd2excel" do
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: robust_excel_ole
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 0
9
- - 3
10
- version: 1.0.3
8
+ - 1
9
+ version: "1.1"
11
10
  platform: ruby
12
11
  authors:
13
12
  - traths
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2017-08-27 00:00:00 +02:00
17
+ date: 2017-10-02 00:00:00 +02:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency