roo 1.3.11 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,9 @@
1
- require 'xml'
1
+ require 'rubygems'
2
2
  require 'fileutils'
3
3
  require 'zip/zipfilesystem'
4
4
  require 'date'
5
5
  require 'base64'
6
- require 'cgi'
6
+ require 'nokogiri'
7
7
 
8
8
  class Openoffice < GenericSpreadsheet
9
9
 
@@ -36,7 +36,8 @@ class Openoffice < GenericSpreadsheet
36
36
  @file_nr = @@nr
37
37
  extract_content
38
38
  file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_content.xml"))
39
- @doc = XML::Parser.io(file).parse
39
+ #TODO: @doc = XML::Parser.io(file).parse
40
+ @doc = Nokogiri::XML(file)
40
41
  file.close
41
42
  ensure
42
43
  #if ENV["roo_local"] != "thomas-p"
@@ -55,6 +56,7 @@ class Openoffice < GenericSpreadsheet
55
56
  @style_defaults = Hash.new { |h,k| h[k] = [] }
56
57
  @style_definitions = Hash.new
57
58
  @header_line = 1
59
+ @labels = {}
58
60
  end
59
61
 
60
62
  # creates a new empty openoffice-spreadsheet file
@@ -78,7 +80,8 @@ class Openoffice < GenericSpreadsheet
78
80
  read_cells(sheet) unless @cells_read[sheet]
79
81
  row,col = normalize(row,col)
80
82
  if celltype(row,col,sheet) == :date
81
- yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
83
+ #TODO: yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
84
+ yyyy,mm,dd = @cell[sheet][[row,col]].to_s.split('-')
82
85
  return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
83
86
  end
84
87
  @cell[sheet][[row,col]]
@@ -170,8 +173,10 @@ class Openoffice < GenericSpreadsheet
170
173
 
171
174
  def sheets
172
175
  return_sheets = []
173
- @doc.find("//*[local-name()='table']").each do |sheet|
174
- return_sheets << sheet.attributes['name']
176
+ #TODO: @doc.find("//*[local-name()='table']").each do |sheet|
177
+ @doc.xpath("//*[local-name()='table']").each do |sheet|
178
+ #TODO: return_sheets << sheet.attributes['name']
179
+ return_sheets << sheet['name']
175
180
  end
176
181
  return_sheets
177
182
  end
@@ -213,12 +218,29 @@ class Openoffice < GenericSpreadsheet
213
218
  theformulas
214
219
  end
215
220
 
221
+ # returns the row,col values of the labelled cell
222
+ # (nil,nil) if label is not defined
223
+ # sheet parameter is not really needed because label names are global
224
+ # to the whole spreadsheet
225
+ def label(labelname,sheet=nil)
226
+ sheet = @default_sheet unless sheet
227
+ read_cells(sheet) unless @cells_read[sheet]
228
+ if @labels.has_key? labelname
229
+ return @labels[labelname][1].to_i,
230
+ GenericSpreadsheet.letter_to_number(@labels[labelname][2]),
231
+ @labels[labelname][0]
232
+ else
233
+ return nil,nil,nil
234
+ end
235
+ end
236
+
216
237
  private
217
238
 
218
239
  # read the version of the OO-Version
219
240
  def oo_version
220
- @doc.find("//*[local-name()='document-content']").each do |office|
221
- @officeversion = office.attributes['version']
241
+ #TODO: @doc.find("//*[local-name()='document-content']").each do |office|
242
+ @doc.xpath("//*[local-name()='document-content']").each do |office|
243
+ @officeversion = office.attributes['version'].to_s
222
244
  end
223
245
  end
224
246
 
@@ -238,10 +260,11 @@ class Openoffice < GenericSpreadsheet
238
260
  when :string
239
261
  @cell[sheet][key] = str_v
240
262
  when :date
241
- if table_cell.attributes['date-value'].size != "XXXX-XX-XX".size
263
+ #TODO: if table_cell.attributes['date-value'].size != "XXXX-XX-XX".size
264
+ if table_cell.attributes['date-value'].to_s.size != "XXXX-XX-XX".size
242
265
  #-- dann ist noch eine Uhrzeit vorhanden
243
266
  #-- "1961-11-21T12:17:18"
244
- @cell[sheet][key] = DateTime.parse(table_cell.attributes['date-value'])
267
+ @cell[sheet][key] = DateTime.parse(table_cell.attributes['date-value'].to_s)
245
268
  @cell_type[sheet][key] = :datetime
246
269
  else
247
270
  @cell[sheet][key] = table_cell.attributes['date-value']
@@ -267,31 +290,59 @@ class Openoffice < GenericSpreadsheet
267
290
  raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
268
291
  raise RangeError unless self.sheets.include? sheet
269
292
 
270
- @doc.find("//*[local-name()='table']").each do |ws|
271
- if sheet == ws.attributes['name']
293
+ #-
294
+ # Labels
295
+ # should be factored out in separate method because labels are global
296
+ # to the whole spreadsheet file (and not to specific sheet)
297
+ #+
298
+ @doc.xpath("//table:named-range").each do |ne|
299
+ #-
300
+ # $Sheet1.$C$5
301
+ #+
302
+ name = ne.attribute('name').to_s
303
+ sheetname,coords = ne.attribute('cell-range-address').to_s.split('.')
304
+ col = coords.split('$')[1]
305
+ row = coords.split('$')[2]
306
+ sheetname = sheetname[1..-1] if sheetname[0,1] == '$'
307
+ @labels[name] = [sheetname,row,col]
308
+ end
309
+
310
+ #TODO: @doc.find("//*[local-name()='table']").each do |ws|
311
+ @doc.xpath("//*[local-name()='table']").each do |ws|
312
+ #TODO: if sheet == ws.attributes['name']
313
+ if sheet == ws['name']
272
314
  sheet_found = true
273
315
  col = 1
274
316
  row = 1
275
- ws.each_element do |table_element|
317
+ #TODO: ws.each_element do |table_element|
318
+ ws.children.each do |table_element|
276
319
  case table_element.name
277
320
  when 'table-column'
278
321
  @style_defaults[sheet] << table_element.attributes['default-cell-style-name']
279
322
  when 'table-row'
280
323
  if table_element.attributes['number-rows-repeated']
281
- skip_row = table_element.attributes['number-rows-repeated'].to_i
324
+ #TODO: skip_row = table_element.attributes['number-rows-repeated'].to_i
325
+ skip_row = table_element.attributes['number-rows-repeated'].to_s.to_i
282
326
  row = row + skip_row - 1
283
327
  end
284
- table_element.each_element do |cell|
285
- skip_col = cell.attributes['number-columns-repeated']
286
- formula = cell.attributes['formula']
287
- vt = cell.attributes['value-type']
288
- v = cell.attributes['value']
289
- style_name = cell.attributes['style-name']
328
+ #TODO: table_element.each_element do |cell|
329
+ table_element.children.each do |cell|
330
+ #TODO: skip_col = cell.attributes['number-columns-repeated']
331
+ skip_col = cell['number-columns-repeated']
332
+ #TODO: formula = cell.attributes['formula']
333
+ formula = cell['formula']
334
+ #TODO: vt = cell.attributes['value-type']
335
+ vt = cell['value-type']
336
+ #TODO: v = cell.attributes['value']
337
+ v = cell['value']
338
+ #TODO: style_name = cell.attributes['style-name']
339
+ style_name = cell['style-name']
290
340
  if vt == 'string'
291
341
  str_v = ''
292
342
  # insert \n if there is more than one paragraph
293
343
  para_count = 0
294
- cell.each_element do |str|
344
+ #TODO: cell.each_element do |str|
345
+ cell.children.each do |str|
295
346
  if str.name == 'p'
296
347
  v = str.content
297
348
  str_v += "\n" if para_count > 0
@@ -306,9 +357,10 @@ class Openoffice < GenericSpreadsheet
306
357
  str_v.gsub!(/&apos;/,"'") # special case not supported by unescapeHTML
307
358
  str_v = CGI.unescapeHTML(str_v)
308
359
  end # == 'p'
309
- end
360
+ end
310
361
  elsif vt == 'time'
311
- cell.each_element do |str|
362
+ #TODO: cell.each_element do |str|
363
+ cell.children.each do |str|
312
364
  if str.name == 'p'
313
365
  v = str.content
314
366
  end
@@ -322,8 +374,7 @@ class Openoffice < GenericSpreadsheet
322
374
  elsif vt == 'float'
323
375
  #
324
376
  elsif vt == 'boolean'
325
- v = cell.attributes['boolean-value']
326
- #
377
+ v = cell.attributes['boolean-value'].to_s
327
378
  else
328
379
  # raise "unknown type #{vt}"
329
380
  end
@@ -345,7 +396,8 @@ class Openoffice < GenericSpreadsheet
345
396
  end
346
397
  end
347
398
 
348
- @doc.find("//*[local-name()='automatic-styles']").each do |style|
399
+ #TODO: @doc.find("//*[local-name()='automatic-styles']").each do |style|
400
+ @doc.xpath("//*[local-name()='automatic-styles']").each do |style|
349
401
  read_styles(style)
350
402
  end
351
403
  if !sheet_found
@@ -434,7 +486,7 @@ class Openoffice < GenericSpreadsheet
434
486
  result = result + child.content
435
487
  else
436
488
  if child.name == 's'
437
- compressed_spaces = child.attributes['c'].to_i
489
+ compressed_spaces = child.attributes['c'].to_s.to_i
438
490
  # no explicit number means a count of 1:
439
491
  if compressed_spaces == 0
440
492
  compressed_spaces = 1
@@ -1,9 +1,9 @@
1
- module Roo #:nodoc:
2
- module VERSION #:nodoc:
3
- MAJOR = 1
4
- MINOR = 3
5
- TINY = 9
6
-
7
- STRING = [MAJOR, MINOR, TINY].join('.')
8
- end
9
- end
1
+ #module Roo #:nodoc:
2
+ # module VERSION #:nodoc:
3
+ # MAJOR = 1
4
+ # MINOR = 3
5
+ # TINY = 6
6
+ #
7
+ # STRING = [MAJOR, MINOR, TINY].join('.')
8
+ # end
9
+ #end
@@ -0,0 +1,80 @@
1
+
2
+ begin
3
+ require 'bones/smtp_tls'
4
+ rescue LoadError
5
+ require 'net/smtp'
6
+ end
7
+ require 'time'
8
+
9
+ namespace :ann do
10
+
11
+ # A prerequisites task that all other tasks depend upon
12
+ task :prereqs
13
+
14
+ file PROJ.ann.file do
15
+ ann = PROJ.ann
16
+ puts "Generating #{ann.file}"
17
+ File.open(ann.file,'w') do |fd|
18
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
19
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
20
+ fd.puts(" #{PROJ.url}") if PROJ.url.valid?
21
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
22
+ fd.puts
23
+ fd.puts("== DESCRIPTION")
24
+ fd.puts
25
+ fd.puts(PROJ.description)
26
+ fd.puts
27
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
28
+ fd.puts
29
+ ann.paragraphs.each do |p|
30
+ fd.puts "== #{p.upcase}"
31
+ fd.puts
32
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
33
+ fd.puts
34
+ end
35
+ fd.puts ann.text if ann.text
36
+ end
37
+ end
38
+
39
+ desc "Create an announcement file"
40
+ task :announcement => ['ann:prereqs', PROJ.ann.file]
41
+
42
+ desc "Send an email announcement"
43
+ task :email => ['ann:prereqs', PROJ.ann.file] do
44
+ ann = PROJ.ann
45
+ from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
46
+ to = Array(ann.email[:to])
47
+
48
+ ### build a mail header for RFC 822
49
+ rfc822msg = "From: #{from}\n"
50
+ rfc822msg << "To: #{to.join(',')}\n"
51
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
52
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
53
+ rfc822msg << "\n"
54
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
55
+ rfc822msg << "Message-Id: "
56
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
57
+ rfc822msg << File.read(ann.file)
58
+
59
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
60
+ ann.email[key]
61
+ end
62
+
63
+ params[3] = PROJ.email if params[3].nil?
64
+
65
+ if params[4].nil?
66
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
67
+ params[4] = STDIN.gets.chomp
68
+ end
69
+
70
+ ### send email
71
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
72
+ end
73
+ end # namespace :ann
74
+
75
+ desc 'Alias to ann:announcement'
76
+ task :ann => 'ann:announcement'
77
+
78
+ CLOBBER << PROJ.ann.file
79
+
80
+ # EOF
@@ -0,0 +1,20 @@
1
+
2
+ if HAVE_BONES
3
+
4
+ namespace :bones do
5
+
6
+ desc 'Show the PROJ open struct'
7
+ task :debug do |t|
8
+ atr = if t.application.top_level_tasks.length == 2
9
+ t.application.top_level_tasks.pop
10
+ end
11
+
12
+ if atr then Bones::Debug.show_attr(PROJ, atr)
13
+ else Bones::Debug.show PROJ end
14
+ end
15
+
16
+ end # namespace :bones
17
+
18
+ end # HAVE_BONES
19
+
20
+ # EOF
@@ -0,0 +1,201 @@
1
+
2
+ require 'find'
3
+ require 'rake/packagetask'
4
+ require 'rubygems/user_interaction'
5
+ require 'rubygems/builder'
6
+
7
+ module Bones
8
+ class GemPackageTask < Rake::PackageTask
9
+ # Ruby GEM spec containing the metadata for this package. The
10
+ # name, version and package_files are automatically determined
11
+ # from the GEM spec and don't need to be explicitly provided.
12
+ #
13
+ attr_accessor :gem_spec
14
+
15
+ # Tasks from the Bones gem directory
16
+ attr_reader :bones_files
17
+
18
+ # Create a GEM Package task library. Automatically define the gem
19
+ # if a block is given. If no block is supplied, then +define+
20
+ # needs to be called to define the task.
21
+ #
22
+ def initialize(gem_spec)
23
+ init(gem_spec)
24
+ yield self if block_given?
25
+ define if block_given?
26
+ end
27
+
28
+ # Initialization tasks without the "yield self" or define
29
+ # operations.
30
+ #
31
+ def init(gem)
32
+ super(gem.name, gem.version)
33
+ @gem_spec = gem
34
+ @package_files += gem_spec.files if gem_spec.files
35
+ @bones_files = []
36
+
37
+ local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
38
+ if !test(?e, local_setup)
39
+ Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
40
+ end
41
+ end
42
+
43
+ # Create the Rake tasks and actions specified by this
44
+ # GemPackageTask. (+define+ is automatically called if a block is
45
+ # given to +new+).
46
+ #
47
+ def define
48
+ super
49
+ task :prereqs
50
+ task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"]
51
+ file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do
52
+ when_writing("Creating GEM") {
53
+ chdir(package_dir_path) do
54
+ Gem::Builder.new(gem_spec).build
55
+ verbose(true) {
56
+ mv gem_file, "../#{gem_file}"
57
+ }
58
+ end
59
+ }
60
+ end
61
+
62
+ file package_dir_path => bones_files do
63
+ mkdir_p package_dir rescue nil
64
+
65
+ gem_spec.files = (gem_spec.files +
66
+ bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
67
+
68
+ bones_files.each do |fn|
69
+ base_fn = File.join('tasks', File.basename(fn))
70
+ f = File.join(package_dir_path, base_fn)
71
+ fdir = File.dirname(f)
72
+ mkdir_p(fdir) if !File.exist?(fdir)
73
+ if File.directory?(fn)
74
+ mkdir_p(f)
75
+ else
76
+ raise "file name conflict for '#{base_fn}' (conflicts with '#{fn}')" if test(?e, f)
77
+ safe_ln(fn, f)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ def gem_file
84
+ if @gem_spec.platform == Gem::Platform::RUBY
85
+ "#{package_name}.gem"
86
+ else
87
+ "#{package_name}-#{@gem_spec.platform}.gem"
88
+ end
89
+ end
90
+ end # class GemPackageTask
91
+ end # module Bones
92
+
93
+ namespace :gem do
94
+
95
+ PROJ.gem._spec = Gem::Specification.new do |s|
96
+ s.name = PROJ.name
97
+ s.version = PROJ.version
98
+ s.summary = PROJ.summary
99
+ s.authors = Array(PROJ.authors)
100
+ s.email = PROJ.email
101
+ s.homepage = Array(PROJ.url).first
102
+ s.rubyforge_project = PROJ.rubyforge.name
103
+
104
+ s.description = PROJ.description
105
+
106
+ PROJ.gem.dependencies.each do |dep|
107
+ s.add_dependency(*dep)
108
+ end
109
+
110
+ PROJ.gem.development_dependencies.each do |dep|
111
+ s.add_development_dependency(*dep)
112
+ end
113
+
114
+ s.files = PROJ.gem.files
115
+ s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
116
+ s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/
117
+
118
+ s.bindir = 'bin'
119
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
120
+ s.require_paths = dirs unless dirs.empty?
121
+
122
+ incl = Regexp.new(PROJ.rdoc.include.join('|'))
123
+ excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
124
+ excl = Regexp.new(excl.join('|'))
125
+ rdoc_files = PROJ.gem.files.find_all do |fn|
126
+ case fn
127
+ when excl; false
128
+ when incl; true
129
+ else false end
130
+ end
131
+ s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
132
+ s.extra_rdoc_files = rdoc_files
133
+ s.has_rdoc = true
134
+
135
+ if test ?f, PROJ.test.file
136
+ s.test_file = PROJ.test.file
137
+ else
138
+ s.test_files = PROJ.test.files.to_a
139
+ end
140
+
141
+ # Do any extra stuff the user wants
142
+ PROJ.gem.extras.each do |msg, val|
143
+ case val
144
+ when Proc
145
+ val.call(s.send(msg))
146
+ else
147
+ s.send "#{msg}=", val
148
+ end
149
+ end
150
+ end # Gem::Specification.new
151
+
152
+ Bones::GemPackageTask.new(PROJ.gem._spec) do |pkg|
153
+ pkg.need_tar = PROJ.gem.need_tar
154
+ pkg.need_zip = PROJ.gem.need_zip
155
+ end
156
+
157
+ desc 'Show information about the gem'
158
+ task :debug => 'gem:prereqs' do
159
+ puts PROJ.gem._spec.to_ruby
160
+ end
161
+
162
+ desc 'Write the gemspec '
163
+ task :spec => 'gem:prereqs' do
164
+ File.open("#{PROJ.name}.gemspec", 'w') do |f|
165
+ f.write PROJ.gem._spec.to_ruby
166
+ end
167
+ end
168
+
169
+ desc 'Install the gem'
170
+ task :install => [:clobber, 'gem:package'] do
171
+ sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
172
+
173
+ # use this version of the command for rubygems > 1.0.0
174
+ #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
175
+ end
176
+
177
+ desc 'Uninstall the gem'
178
+ task :uninstall do
179
+ installed_list = Gem.source_index.find_name(PROJ.name)
180
+ if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
181
+ sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
182
+ end
183
+ end
184
+
185
+ desc 'Reinstall the gem'
186
+ task :reinstall => [:uninstall, :install]
187
+
188
+ desc 'Cleanup the gem'
189
+ task :cleanup do
190
+ sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
191
+ end
192
+ end # namespace :gem
193
+
194
+
195
+ desc 'Alias to gem:package'
196
+ task :gem => 'gem:package'
197
+
198
+ task :clobber => 'gem:clobber_package'
199
+ remove_desc_for_task 'gem:clobber_package'
200
+
201
+ # EOF