roo 1.11.2 → 1.12.0

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/CHANGELOG CHANGED
@@ -1,4 +1,29 @@
1
- == 1.11.2 (unreleased)
1
+ == 1.12.0 (unreleased)
2
+
3
+ * 3 deprecations
4
+ * Rename Openoffice -> OpenOffice, Libreoffice -> LibreOffice, Csv -> CSV, and redirect the old names to the new constants
5
+ * Enable Roo::Excel, Excel2003XML, Excelx, OpenOffice to accept an options hash, and deprecate the old method argument based approach to supplying them options
6
+ * Roo's roo_rails_helper, aka the `spreadsheet` html-generating view method is currently deprecated with no replacement. If you find it helpful, tell http://github.com/Empact or extract it yourself.
7
+
8
+ * 9 enhancements
9
+ * Add Roo::Excelx#load_xml so that people can customize to their data, e.g. https://github.com/Empact/roo/pull/23
10
+ * Enable passing csv_options to Roo::CSV, which are passed through to the underlying CSV call.
11
+ * Enable passing options through from Roo::Spreadsheet to any Roo type.
12
+ * Enable passing an :extension option to Roo::Spreadsheet.new, which will override the extension detected on in the path https://github.com/Empact/roo/pull/15
13
+ * Switch from google-spreadsheet-ruby to google_drive for Roo::Google access https://github.com/Empact/roo/pull/40
14
+ * Make all the classes consistent in that #read_cells is only effective if the sheet has not been read.
15
+ * Roo::Google supports login via oauth :access_token. https://github.com/Empact/roo/pull/61
16
+ * Roo::Excel now exposes its Spreadsheet workbook via #workbook
17
+ * Pull #load_xml down into Roo::Base, and use it in Excel2003XML and OpenOffice.
18
+
19
+ * 2 changes
20
+ * #formula? now returns truthy or falsey, rather than true/false.
21
+ * Base#longest_sheet was moved to Excel, as it only worked under Excel
22
+
23
+ * 1 bugfix
24
+ * Fix that Roo::CSV#parse(headers: true) would blow up. https://github.com/Empact/roo/pull/37
25
+
26
+ == 1.11.2 2013-04-10
2
27
 
3
28
  * 4 bugfixes
4
29
  * Fix that Roo::Spreadsheet.open wasn't tolerant to case differences.
data/Gemfile CHANGED
@@ -3,9 +3,9 @@ source 'http://rubygems.org'
3
3
  gem 'spreadsheet', '> 0.6.4'
4
4
  gem 'nokogiri'
5
5
  gem 'rubyzip'
6
- # gem 'google-spreadsheet-ruby'
7
6
 
8
7
  group :development do
8
+ gem 'google_drive'
9
9
  gem 'jeweler'
10
10
  end
11
11
 
@@ -14,4 +14,5 @@ group :test do
14
14
  gem 'webmock'
15
15
  gem 'shoulda'
16
16
  gem 'rspec'
17
+ gem 'vcr'
17
18
  end
@@ -4,14 +4,37 @@ GEM
4
4
  addressable (2.3.2)
5
5
  crack (0.3.1)
6
6
  diff-lcs (1.2.1)
7
+ faraday (0.8.7)
8
+ multipart-post (~> 1.1)
7
9
  git (1.2.5)
10
+ google_drive (0.3.6)
11
+ nokogiri (>= 1.4.4, != 1.5.2, != 1.5.1)
12
+ oauth (>= 0.3.6)
13
+ oauth2 (>= 0.5.0)
14
+ httpauth (0.2.0)
8
15
  jeweler (1.8.3)
9
16
  bundler (~> 1.0)
10
17
  git (>= 1.2.5)
11
18
  rake
12
19
  rdoc
13
20
  json (1.7.7)
21
+ json (1.7.7-java)
22
+ jwt (0.1.8)
23
+ multi_json (>= 1.5)
24
+ multi_json (1.7.3)
25
+ multi_xml (0.5.3)
26
+ multipart-post (1.2.0)
14
27
  nokogiri (1.5.6)
28
+ nokogiri (1.5.6-java)
29
+ oauth (0.4.7)
30
+ oauth2 (0.9.1)
31
+ faraday (~> 0.8)
32
+ httpauth (~> 0.1)
33
+ jwt (~> 0.1.4)
34
+ multi_json (~> 1.0)
35
+ multi_xml (~> 0.5)
36
+ rack (~> 1.2)
37
+ rack (1.5.2)
15
38
  rake (0.9.2.2)
16
39
  rdoc (3.12.2)
17
40
  json (~> 1.4)
@@ -32,6 +55,7 @@ GEM
32
55
  shoulda-matchers (1.0.0)
33
56
  spreadsheet (0.8.2)
34
57
  ruby-ole (>= 1.0)
58
+ vcr (2.5.0)
35
59
  webmock (1.9.0)
36
60
  addressable (>= 2.2.7)
37
61
  crack (>= 0.1.7)
@@ -41,10 +65,12 @@ PLATFORMS
41
65
  ruby
42
66
 
43
67
  DEPENDENCIES
68
+ google_drive
44
69
  jeweler
45
70
  nokogiri
46
71
  rspec
47
72
  rubyzip
48
73
  shoulda
49
74
  spreadsheet (> 0.6.4)
75
+ vcr
50
76
  webmock
@@ -2,108 +2,128 @@
2
2
 
3
3
  Roo implements read access for all spreadsheet types and read/write access for
4
4
  Google spreadsheets. It can handle
5
- * Openoffice
5
+ * OpenOffice
6
6
  * Excel
7
7
  * Google spreadsheets
8
8
  * Excelx
9
- * Libreoffice
9
+ * LibreOffice
10
10
  * CSV
11
11
 
12
+ ## Notes
13
+
14
+ ### XLS
15
+
16
+ There is no support for formulas in Roo for .xls files - you can get the result
17
+ of a formula but not the formula itself.
18
+
19
+ ### Google Spreadsheet
20
+
12
21
  Using Roo to access Google spreadsheets requires you install the 'google-spreadsheet-ruby' gem separately.
13
22
 
14
- Unless the underlying 'spreadsheet' gem supports formulas there is no support
15
- for formulas in Roo for .xls files (you get the result of a formula in such a
16
- file but not the formula itself)
23
+ ## License
24
+
25
+ While Roo is licensed under the MIT / Expat license, please note that the 'spreadsheet' gem [is released under](https://github.com/zdavatz/spreadsheet/blob/master/LICENSE.txt) the GPLv3 license.
17
26
 
18
27
  ## Usage:
19
28
 
20
- require 'roo'
29
+ require 'roo'
30
+
31
+ s = Roo::OpenOffice.new("myspreadsheet.ods") # loads an OpenOffice Spreadsheet
32
+ s = Roo::Excel.new("myspreadsheet.xls") # loads an Excel Spreadsheet
33
+ s = Roo::Google.new("myspreadsheetkey_at_google") # loads a Google Spreadsheet
34
+ s = Roo::Excelx.new("myspreadsheet.xlsx") # loads an Excel Spreadsheet for Excel .xlsx files
35
+ s = Roo::CSV.new("mycsv.csv") # loads a CSV file
21
36
 
22
- s = Roo::Openoffice.new("myspreadsheet.ods") # creates an Openoffice Spreadsheet instance
23
- s = Roo::Excel.new("myspreadsheet.xls") # creates an Excel Spreadsheet instance
24
- s = Roo::Google.new("myspreadsheetkey_at_google") # creates an Google Spreadsheet instance
25
- s = Roo::Excelx.new("myspreadsheet.xlsx") # creates an Excel Spreadsheet instance for Excel .xlsx files
37
+ # You can use CSV to load TSV files, or files of a certain encoding by passing
38
+ # in options under the :csv_options key
39
+ s = Roo::CSV.new("mytsv.tsv", csv_options: {col_sep: "\t"}) # TSV
40
+ s = Roo::CSV.new("mycsv.csv", csv_options: {encoding: Encoding::ISO_8859_1}) # csv with explicit encoding
26
41
 
27
- s.default_sheet = s.sheets.first # first sheet in the spreadsheet file will be used
42
+ s.default_sheet = s.sheets.first # first sheet in the spreadsheet file will be used
28
43
 
29
- # s.sheet is an array which holds the names of the sheets within
30
- # a spreadsheet.
31
- # you can also write
32
- # s.default_sheet = s.sheets[3] or
33
- # s.default_sheet = 'Sheet 3'
44
+ # s.sheets is an array which holds the names of the sheets within
45
+ # a spreadsheet.
46
+ # you can also write
47
+ # s.default_sheet = s.sheets[3] or
48
+ # s.default_sheet = 'Sheet 3'
34
49
 
35
- s.cell(1,1) # returns the content of the first row/first cell in the sheet
36
- s.cell('A',1) # same cell
37
- s.cell(1,'A') # same cell
38
- s.cell(1,'A',s.sheets[0]) # same cell
50
+ s.cell(1,1) # returns the content of the first row/first cell in the sheet
51
+ s.cell('A',1) # same cell
52
+ s.cell(1,'A') # same cell
53
+ s.cell(1,'A',s.sheets[0]) # same cell
39
54
 
40
- # almost all methods have an optional argument 'sheet'.
41
- # If this parameter is omitted, the default_sheet will be used.
55
+ # almost all methods have an optional argument 'sheet'.
56
+ # If this parameter is omitted, the default_sheet will be used.
42
57
 
43
- s.info # prints infos about the spreadsheet file
58
+ s.info # prints infos about the spreadsheet file
44
59
 
45
- s.first_row # the number of the first row
46
- s.last_row # the number of the last row
47
- s.first_column # the number of the first column
48
- s.last_column # the number of the last column
60
+ s.first_row # the number of the first row
61
+ s.last_row # the number of the last row
62
+ s.first_column # the number of the first column
63
+ s.last_column # the number of the last column
49
64
 
50
- # limited font information is available
65
+ # limited font information is available
51
66
 
52
- s.font(1,1).bold?
53
- s.font(1,1).italic?
54
- s.font(1,1).underline?
67
+ s.font(1,1).bold?
68
+ s.font(1,1).italic?
69
+ s.font(1,1).underline?
55
70
 
56
71
 
57
72
  see http://roo.rubyforge.org for a more complete tutorial
58
73
 
59
74
  # Fork Changelog / New Features
60
75
 
61
- # Spreadsheet.open can accept both files and paths
76
+ # Spreadsheet.open can accept both files and paths
77
+
78
+ xls = Roo::Spreadsheet.open('./new_prices.xls')
79
+
80
+ # If the File.path or provided path string does not have an extension, you can optionally
81
+ # provide one as a string or symbol
62
82
 
63
- xls = Roo::Spreadsheet.open('./new_prices.xls')
83
+ xls = Roo::Spreadsheet.open('./rails_temp_upload', extension: :xls)
64
84
 
65
- # no more setting xls.default_sheet, just use this
85
+ # no more setting xls.default_sheet, just use this
66
86
 
67
- xls.sheet('Info').row_count
68
- xls.sheet(0).row_count
87
+ xls.sheet('Info').row(1)
88
+ xls.sheet(0).row(1)
69
89
 
70
- # excel likes to create random "Data01" sheets for macros
71
- # use this to find the sheet with the most data to parse
90
+ # excel likes to create random "Data01" sheets for macros
91
+ # use this to find the sheet with the most data to parse
72
92
 
73
- xls.longest_sheet
93
+ xls.longest_sheet
74
94
 
75
- # this excel file has multiple worksheets, let's iterate through each of them and process
95
+ # this excel file has multiple worksheets, let's iterate through each of them and process
76
96
 
77
- xls.each_with_pagename do |name,sheet|
78
- puts sheet.row_count
79
- end
97
+ xls.each_with_pagename do |name, sheet|
98
+ p sheet.row(1)
99
+ end
80
100
 
81
- # pull out a hash of exclusive column data (get rid of useless columns and save memory)
101
+ # pull out a hash of exclusive column data (get rid of useless columns and save memory)
82
102
 
83
- xls.each(:id => 'UPC',:qty => 'ATS') {|hash| arr << hash}
84
- #=> hash will appear like {:upc=>727880013358, :qty => 12}
103
+ xls.each(:id => 'UPC',:qty => 'ATS') {|hash| arr << hash}
104
+ #=> hash will appear like {:upc=>727880013358, :qty => 12}
85
105
 
86
- # NOTE: .parse does the same as .each, except it returns an array (similar to each vs. map)
106
+ # NOTE: .parse does the same as .each, except it returns an array (similar to each vs. map)
87
107
 
88
- # not sure exactly what a column will be named? try a wildcard search with the character *
89
- # regex characters are allowed ('^price\s')
90
- # case insensitive
108
+ # not sure exactly what a column will be named? try a wildcard search with the character *
109
+ # regex characters are allowed ('^price\s')
110
+ # case insensitive
91
111
 
92
- xls.parse(:id => 'UPC*SKU',:qty => 'ATS*\sATP\s*QTY$')
112
+ xls.parse(:id => 'UPC*SKU',:qty => 'ATS*\sATP\s*QTY$')
93
113
 
94
- # if you need to locate the header row and assign the header names themselves,
95
- # use the :header_search option
114
+ # if you need to locate the header row and assign the header names themselves,
115
+ # use the :header_search option
96
116
 
97
- xls.parse(:header_search => ['UPC*SKU','ATS*\sATP\s*QTY$'])
98
- #=> each element will appear in this fashion:
99
- #=> {"UPC" => 123456789012, "STYLE" => "987B0", "COLOR" => "blue", "QTY" => 78}
117
+ xls.parse(:header_search => ['UPC*SKU','ATS*\sATP\s*QTY$'])
118
+ #=> each element will appear in this fashion:
119
+ #=> {"UPC" => 123456789012, "STYLE" => "987B0", "COLOR" => "blue", "QTY" => 78}
100
120
 
101
- # want to strip out annoying unicode characters and surrounding white space?
121
+ # want to strip out annoying unicode characters and surrounding white space?
102
122
 
103
- xls.parse(:clean => true)
123
+ xls.parse(:clean => true)
104
124
 
105
- # another bonus feature is a patch to prevent the Spreadsheet gem from parsing
106
- # thousands and thousands of blank lines. i got fed up after watching my computer
107
- # nearly catch fire for 4 hours for a spreadsheet with only 200 ACTUAL lines
108
- # - located in lib/roo/worksheet.rb
125
+ # another bonus feature is a patch to prevent the Spreadsheet gem from parsing
126
+ # thousands and thousands of blank lines. i got fed up after watching my computer
127
+ # nearly catch fire for 4 hours for a spreadsheet with only 200 ACTUAL lines
128
+ # - located in lib/roo/worksheet.rb
109
129
 
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ Jeweler::Tasks.new do |gem|
4
4
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
5
5
  gem.name = "roo"
6
6
  gem.summary = "Roo can access the contents of various spreadsheet files."
7
- gem.description = "Roo can access the contents of various spreadsheet files. It can handle\n* Openoffice\n* Excel\n* Google spreadsheets\n* Excelx\n* Libreoffice\n* CSV"
7
+ gem.description = "Roo can access the contents of various spreadsheet files. It can handle\n* OpenOffice\n* Excel\n* Google spreadsheets\n* Excelx\n* LibreOffice\n* CSV"
8
8
  gem.email = "ruby.ruby.ruby.roo@gmail.com"
9
9
  gem.homepage = "http://github.com/Empact/roo"
10
10
  gem.authors = ['Thomas Preymesser', 'Hugh McGowan', 'Ben Woosley']
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.11.2
1
+ 1.12.0
@@ -5,7 +5,7 @@ NS = "spreadsheetserver" # name of your service = namespace
5
5
  class Server2 < SOAP::RPC::StandaloneServer
6
6
 
7
7
  def on_init
8
- spreadsheet = Openoffice.new("./Ferien-de.ods")
8
+ spreadsheet = OpenOffice.new("./Ferien-de.ods")
9
9
  add_method(spreadsheet, 'cell', 'row', 'col')
10
10
  add_method(spreadsheet, 'officeversion')
11
11
  add_method(spreadsheet, 'first_row')
data/lib/roo.rb CHANGED
@@ -1,16 +1,34 @@
1
1
  module Roo
2
2
 
3
- VERSION = '1.10.3'
3
+ VERSION = '1.12.0'
4
4
 
5
- autoload :Spreadsheet, 'roo/spreadsheet'
5
+ def self.const_missing(const_name)
6
+ case const_name
7
+ when :Libreoffice
8
+ warn "`Roo::Libreoffice` has been deprecated. Use `Roo::LibreOffice` instead."
9
+ LibreOffice
10
+ when :Openoffice
11
+ warn "`Roo::Openoffice` has been deprecated. Use `Roo::OpenOffice` instead."
12
+ OpenOffice
13
+ when :Csv
14
+ warn "`Roo::Csv` has been deprecated. Use `Roo::CSV` instead."
15
+ CSV
16
+ when :GenericSpreadsheet
17
+ warn "`Roo::GenericSpreadsheet` has been deprecated. Use `Roo::Base` instead."
18
+ Base
19
+ else
20
+ super
21
+ end
22
+ end
6
23
 
7
- autoload :GenericSpreadsheet, 'roo/generic_spreadsheet'
8
- autoload :Openoffice, 'roo/openoffice'
9
- autoload :Excel, 'roo/excel'
10
- autoload :Excelx, 'roo/excelx'
11
- autoload :Google, 'roo/google'
12
- autoload :Csv, 'roo/csv'
24
+ autoload :Spreadsheet, 'roo/spreadsheet'
25
+ autoload :Base, 'roo/base'
13
26
 
14
- autoload :Excel2003XML, 'roo/excel2003xml'
15
- autoload :RooRailsHelper, 'roo/roo_rails_helper'
27
+ autoload :OpenOffice, 'roo/openoffice'
28
+ autoload :LibreOffice, 'roo/openoffice'
29
+ autoload :Excel, 'roo/excel'
30
+ autoload :Excelx, 'roo/excelx'
31
+ autoload :Excel2003XML, 'roo/excel2003xml'
32
+ autoload :Google, 'roo/google'
33
+ autoload :CSV, 'roo/csv'
16
34
  end
@@ -5,7 +5,7 @@ require 'stringio'
5
5
  require 'zip/zipfilesystem'
6
6
 
7
7
  # Base class for all other types of spreadsheets
8
- class Roo::GenericSpreadsheet
8
+ class Roo::Base
9
9
  include Enumerable
10
10
 
11
11
  TEMP_PREFIX = "oo_"
@@ -18,7 +18,7 @@ class Roo::GenericSpreadsheet
18
18
  protected
19
19
 
20
20
  def self.split_coordinate(str)
21
- letter,number = Roo::GenericSpreadsheet.split_coord(str)
21
+ letter,number = Roo::Base.split_coord(str)
22
22
  x = letter_to_number(letter)
23
23
  y = number
24
24
  return y, x
@@ -37,9 +37,12 @@ class Roo::GenericSpreadsheet
37
37
 
38
38
  public
39
39
 
40
- def initialize(filename, packed=nil, file_warning=:error, tmpdir=nil)
41
- @cell = Hash.new{|h,k| h[k] = {}}
42
- @cell_type = Hash.new{|h,k| h[k] = {}}
40
+ def initialize(filename, options={}, file_warning=:error, tmpdir=nil)
41
+ @filename = filename
42
+ @options = options
43
+
44
+ @cell = {}
45
+ @cell_type = {}
43
46
  @cells_read = {}
44
47
 
45
48
  @first_row = {}
@@ -47,12 +50,8 @@ class Roo::GenericSpreadsheet
47
50
  @first_column = {}
48
51
  @last_column = {}
49
52
 
50
- @style = {}
51
- @style_defaults = Hash.new { |h,k| h[k] = [] }
52
- @style_definitions = {}
53
-
53
+ @header_line = 1
54
54
  @default_sheet = self.sheets.first
55
- @formula = {}
56
55
  @header_line = 1
57
56
  end
58
57
 
@@ -67,18 +66,18 @@ class Roo::GenericSpreadsheet
67
66
 
68
67
  # first non-empty column as a letter
69
68
  def first_column_as_letter(sheet=nil)
70
- Roo::GenericSpreadsheet.number_to_letter(first_column(sheet))
69
+ Roo::Base.number_to_letter(first_column(sheet))
71
70
  end
72
71
 
73
72
  # last non-empty column as a letter
74
73
  def last_column_as_letter(sheet=nil)
75
- Roo::GenericSpreadsheet.number_to_letter(last_column(sheet))
74
+ Roo::Base.number_to_letter(last_column(sheet))
76
75
  end
77
76
 
78
77
  # returns the number of the first non-empty row
79
78
  def first_row(sheet=nil)
80
79
  sheet ||= @default_sheet
81
- read_cells(sheet) unless @cells_read[sheet]
80
+ read_cells(sheet)
82
81
  if @first_row[sheet]
83
82
  return @first_row[sheet]
84
83
  end
@@ -96,7 +95,7 @@ class Roo::GenericSpreadsheet
96
95
  # returns the number of the last non-empty row
97
96
  def last_row(sheet=nil)
98
97
  sheet ||= @default_sheet
99
- read_cells(sheet) unless @cells_read[sheet]
98
+ read_cells(sheet)
100
99
  if @last_row[sheet]
101
100
  return @last_row[sheet]
102
101
  end
@@ -114,7 +113,7 @@ class Roo::GenericSpreadsheet
114
113
  # returns the number of the first non-empty column
115
114
  def first_column(sheet=nil)
116
115
  sheet ||= @default_sheet
117
- read_cells(sheet) unless @cells_read[sheet]
116
+ read_cells(sheet)
118
117
  if @first_column[sheet]
119
118
  return @first_column[sheet]
120
119
  end
@@ -132,7 +131,7 @@ class Roo::GenericSpreadsheet
132
131
  # returns the number of the last non-empty column
133
132
  def last_column(sheet=nil)
134
133
  sheet ||= @default_sheet
135
- read_cells(sheet) unless @cells_read[sheet]
134
+ read_cells(sheet)
136
135
  if @last_column[sheet]
137
136
  return @last_column[sheet]
138
137
  end
@@ -166,7 +165,7 @@ class Roo::GenericSpreadsheet
166
165
  result << " col: #{col} \n"
167
166
  result << " celltype: #{self.celltype(row,col,sheet)} \n"
168
167
  if self.celltype(row,col,sheet) == :time
169
- result << " value: #{Roo::GenericSpreadsheet.integer_to_timestring( self.cell(row,col,sheet))} \n"
168
+ result << " value: #{Roo::Base.integer_to_timestring( self.cell(row,col,sheet))} \n"
170
169
  else
171
170
  result << " value: #{self.cell(row,col,sheet)} \n"
172
171
  end
@@ -255,7 +254,7 @@ class Roo::GenericSpreadsheet
255
254
  # row numbers are 1,2,3,... like in the spreadsheet
256
255
  def row(rownumber,sheet=nil)
257
256
  sheet ||= @default_sheet
258
- read_cells(sheet) unless @cells_read[sheet]
257
+ read_cells(sheet)
259
258
  first_column(sheet).upto(last_column(sheet)).map do |col|
260
259
  cell(rownumber,col,sheet)
261
260
  end
@@ -268,7 +267,7 @@ class Roo::GenericSpreadsheet
268
267
  columnnumber = Roo::Excel.letter_to_number(columnnumber)
269
268
  end
270
269
  sheet ||= @default_sheet
271
- read_cells(sheet) unless @cells_read[sheet]
270
+ read_cells(sheet)
272
271
  first_row(sheet).upto(last_row(sheet)).map do |row|
273
272
  cell(row,columnnumber,sheet)
274
273
  end
@@ -278,7 +277,7 @@ class Roo::GenericSpreadsheet
278
277
  # (this will not be saved back to the spreadsheet file!)
279
278
  def set(row,col,value,sheet=nil) #:nodoc:
280
279
  sheet ||= @default_sheet
281
- read_cells(sheet) unless @cells_read[sheet]
280
+ read_cells(sheet)
282
281
  row, col = normalize(row,col)
283
282
  cell_type = case value
284
283
  when Fixnum then :float
@@ -293,21 +292,15 @@ class Roo::GenericSpreadsheet
293
292
 
294
293
  # reopens and read a spreadsheet document
295
294
  def reload
296
- # von Abfrage der Klasse direkt auf .to_s == '..' umgestellt
297
295
  ds = @default_sheet
298
- if self.class.to_s == 'Google'
299
- initialize(@spreadsheetkey,@user,@password)
300
- else
301
- initialize(@filename)
302
- end
296
+ reinitialize
303
297
  self.default_sheet = ds
304
- #@first_row = @last_row = @first_column = @last_column = nil
305
298
  end
306
299
 
307
300
  # true if cell is empty
308
301
  def empty?(row, col, sheet=nil)
309
302
  sheet ||= @default_sheet
310
- read_cells(sheet) unless @cells_read[sheet] or self.class == Roo::Excel
303
+ read_cells(sheet)
311
304
  row,col = normalize(row,col)
312
305
  contents = cell(row, col, sheet)
313
306
  !contents || (celltype(row, col, sheet) == :string && contents.empty?) \
@@ -329,8 +322,8 @@ class Roo::GenericSpreadsheet
329
322
  else
330
323
  result << " First row: #{first_row}\n"
331
324
  result << " Last row: #{last_row}\n"
332
- result << " First column: #{Roo::GenericSpreadsheet.number_to_letter(first_column)}\n"
333
- result << " Last column: #{Roo::GenericSpreadsheet.number_to_letter(last_column)}"
325
+ result << " First column: #{Roo::Base.number_to_letter(first_column)}\n"
326
+ result << " Last column: #{Roo::Base.number_to_letter(last_column)}"
334
327
  end
335
328
  result << "\n" if sheet != sheets.last
336
329
  n += 1
@@ -370,7 +363,7 @@ class Roo::GenericSpreadsheet
370
363
  # #aa42 => #cell('aa',42)
371
364
  # #aa42('Sheet1') => #cell('aa',42,'Sheet1')
372
365
  if m =~ /^([a-z]+)(\d)$/
373
- col = Roo::GenericSpreadsheet.letter_to_number($1)
366
+ col = Roo::Base.letter_to_number($1)
374
367
  row = $2.to_i
375
368
  if args.empty?
376
369
  cell(row,col)
@@ -382,148 +375,120 @@ class Roo::GenericSpreadsheet
382
375
  end
383
376
  end
384
377
 
385
- =begin
386
- #TODO: hier entfernen
387
- # returns each formula in the selected sheet as an array of elements
388
- # [row, col, formula]
389
- def formulas(sheet=nil)
390
- theformulas = Array.new
391
- sheet ||= @default_sheet
392
- read_cells(sheet) unless @cells_read[sheet]
393
- return theformulas unless first_row(sheet) # if there is no first row then
394
- # there can't be formulas
395
- first_row(sheet).upto(last_row(sheet)) {|row|
396
- first_column(sheet).upto(last_column(sheet)) {|col|
397
- if formula?(row,col,sheet)
398
- theformulas << [row, col, formula(row,col,sheet)]
399
- end
400
- }
401
- }
402
- theformulas
378
+ # access different worksheets by calling spreadsheet.sheet(1)
379
+ # or spreadsheet.sheet('SHEETNAME')
380
+ def sheet(index,name=false)
381
+ @default_sheet = String === index ? index : self.sheets[index]
382
+ name ? [@default_sheet,self] : self
403
383
  end
404
- =end
405
-
406
-
407
-
408
- # FestivalBobcats fork changes begin here
409
384
 
410
-
411
-
412
- # access different worksheets by calling spreadsheet.sheet(1)
413
- # or spreadsheet.sheet('SHEETNAME')
414
- def sheet(index,name=false)
415
- @default_sheet = String === index ? index : self.sheets[index]
416
- name ? [@default_sheet,self] : self
385
+ # iterate through all worksheets of a document
386
+ def each_with_pagename
387
+ self.sheets.each do |s|
388
+ yield sheet(s,true)
417
389
  end
390
+ end
418
391
 
419
- # iterate through all worksheets of a document
420
- def each_with_pagename
421
- self.sheets.each do |s|
422
- yield sheet(s,true)
423
- end
424
- end
392
+ # by passing in headers as options, this method returns
393
+ # specific columns from your header assignment
394
+ # for example:
395
+ # xls.sheet('New Prices').parse(:upc => 'UPC', :price => 'Price') would return:
396
+ # [{:upc => 123456789012, :price => 35.42},..]
425
397
 
426
- # by passing in headers as options, this method returns
427
- # specific columns from your header assignment
428
- # for example:
429
- # xls.sheet('New Prices').parse(:upc => 'UPC', :price => 'Price') would return:
430
- # [{:upc => 123456789012, :price => 35.42},..]
398
+ # the queries are matched with regex, so regex options can be passed in
399
+ # such as :price => '^(Cost|Price)'
400
+ # case insensitive by default
431
401
 
432
- # the queries are matched with regex, so regex options can be passed in
433
- # such as :price => '^(Cost|Price)'
434
- # case insensitive by default
435
402
 
403
+ # by using the :header_search option, you can query for headers
404
+ # and return a hash of every row with the keys set to the header result
405
+ # for example:
406
+ # xls.sheet('New Prices').parse(:header_search => ['UPC*SKU','^Price*\sCost\s'])
436
407
 
437
- # by using the :header_search option, you can query for headers
438
- # and return a hash of every row with the keys set to the header result
439
- # for example:
440
- # xls.sheet('New Prices').parse(:header_search => ['UPC*SKU','^Price*\sCost\s'])
408
+ # that example searches for a column titled either UPC or SKU and another
409
+ # column titled either Price or Cost (regex characters allowed)
410
+ # * is the wildcard character
441
411
 
442
- # that example searches for a column titled either UPC or SKU and another
443
- # column titled either Price or Cost (regex characters allowed)
444
- # * is the wildcard character
412
+ # you can also pass in a :clean => true option to strip the sheet of
413
+ # odd unicode characters and white spaces around columns
445
414
 
446
- # you can also pass in a :clean => true option to strip the sheet of
447
- # odd unicode characters and white spaces around columns
415
+ def each(options={})
416
+ if options.empty?
417
+ 1.upto(last_row) do |line|
418
+ yield row(line)
419
+ end
420
+ else
421
+ if options[:clean]
422
+ options.delete(:clean)
423
+ @cleaned ||= {}
424
+ @cleaned[@default_sheet] || clean_sheet(@default_sheet)
425
+ end
448
426
 
449
- def each(options={})
450
- if options.empty?
451
- 1.upto(last_row) do |line|
452
- yield row(line)
453
- end
427
+ if options[:header_search]
428
+ @headers = nil
429
+ @header_line = row_with(options[:header_search])
430
+ elsif [:first_row,true].include?(options[:headers])
431
+ @headers = []
432
+ row(first_row).each_with_index {|x,i| @headers << [x,i + 1]}
454
433
  else
455
- if options[:clean]
456
- options.delete(:clean)
457
- @cleaned ||= {}
458
- @cleaned[@default_sheet] || clean_sheet(@default_sheet)
459
- end
460
-
461
- if options[:header_search]
462
- @headers = nil
463
- @header_line = row_with(options[:header_search])
464
- elsif [:first_row,true].include?(options[:headers])
465
- @headers = []
466
- row(first_row).each_with_index {|x,i| @headers << [x,i + 1]}
467
- else
468
- set_headers(options)
469
- end
434
+ set_headers(options)
435
+ end
470
436
 
471
- headers = @headers ||
472
- Hash[(first_column..last_column).map do |col|
473
- [cell(@header_line,col), col]
474
- end]
437
+ headers = @headers ||
438
+ Hash[(first_column..last_column).map do |col|
439
+ [cell(@header_line,col), col]
440
+ end]
475
441
 
476
- @header_line.upto(last_row) do |line|
477
- yield(Hash[headers.map {|k,v| [k,cell(line,v)]}])
478
- end
442
+ @header_line.upto(last_row) do |line|
443
+ yield(Hash[headers.map {|k,v| [k,cell(line,v)]}])
479
444
  end
480
445
  end
446
+ end
481
447
 
482
- def parse(options={})
483
- ary = []
484
- if block_given?
485
- each(options) {|row| ary << yield(row)}
486
- else
487
- each(options) {|row| ary << row}
488
- end
489
- ary
490
- end
491
-
492
- def row_with(query,return_headers=false)
493
- query.map! {|x| Array(x.split('*'))}
494
- line_no = 0
495
- each do |row|
496
- line_no += 1
497
- # makes sure headers is the first part of wildcard search for priority
498
- # ex. if UPC and SKU exist for UPC*SKU search, UPC takes the cake
499
- headers = query.map do |q|
500
- q.map {|i| row.grep(/#{i}/i)[0]}.compact[0]
501
- end.compact
502
-
503
- if headers.length == query.length
504
- @header_line = line_no
505
- return return_headers ? headers : line_no
506
- elsif line_no > 100
507
- raise "Couldn't find header row."
508
- end
448
+ def parse(options={})
449
+ ary = []
450
+ if block_given?
451
+ each(options) {|row| ary << yield(row)}
452
+ else
453
+ each(options) {|row| ary << row}
454
+ end
455
+ ary
456
+ end
457
+
458
+ def row_with(query,return_headers=false)
459
+ query.map! {|x| Array(x.split('*'))}
460
+ line_no = 0
461
+ each do |row|
462
+ line_no += 1
463
+ # makes sure headers is the first part of wildcard search for priority
464
+ # ex. if UPC and SKU exist for UPC*SKU search, UPC takes the cake
465
+ headers = query.map do |q|
466
+ q.map {|i| row.grep(/#{i}/i)[0]}.compact[0]
467
+ end.compact
468
+
469
+ if headers.length == query.length
470
+ @header_line = line_no
471
+ return return_headers ? headers : line_no
472
+ elsif line_no > 100
473
+ raise "Couldn't find header row."
509
474
  end
510
475
  end
511
-
512
- # this method lets you find the worksheet with the most data
513
- def longest_sheet
514
- sheet(@workbook.worksheets.inject {|m,o|
515
- o.row_count > m.row_count ? o : m
516
- }.name)
517
- end
476
+ end
518
477
 
519
478
  protected
520
479
 
480
+ def load_xml(path)
481
+ File.open(path) do |file|
482
+ Nokogiri::XML(file)
483
+ end
484
+ end
485
+
521
486
  def file_type_check(filename, ext, name, warning_level, packed=nil)
522
487
  new_expression = {
523
- '.ods' => 'Roo::Openoffice.new',
488
+ '.ods' => 'Roo::OpenOffice.new',
524
489
  '.xls' => 'Roo::Excel.new',
525
490
  '.xlsx' => 'Roo::Excelx.new',
526
- '.csv' => 'Roo::Csv.new',
491
+ '.csv' => 'Roo::CSV.new',
527
492
  '.xml' => 'Roo::Excel2003XML.new',
528
493
  }
529
494
  if packed == :zip
@@ -574,6 +539,10 @@ class Roo::GenericSpreadsheet
574
539
 
575
540
  private
576
541
 
542
+ def reinitialize
543
+ initialize(@filename)
544
+ end
545
+
577
546
  def make_tmpdir(tmp_root = nil)
578
547
  Dir.mktmpdir(TEMP_PREFIX, tmp_root || ENV['ROO_TMP']) do |tmpdir|
579
548
  yield tmpdir
@@ -581,7 +550,7 @@ class Roo::GenericSpreadsheet
581
550
  end
582
551
 
583
552
  def clean_sheet(sheet)
584
- read_cells(sheet) unless @cells_read[sheet]
553
+ read_cells(sheet)
585
554
  @cell[sheet].each_pair do |coord,value|
586
555
  if String === value
587
556
  @cell[sheet][coord] = sanitize_value(value)
@@ -627,7 +596,7 @@ class Roo::GenericSpreadsheet
627
596
  end
628
597
  end
629
598
  if col.class == String
630
- col = Roo::GenericSpreadsheet.letter_to_number(col)
599
+ col = Roo::Base.letter_to_number(col)
631
600
  end
632
601
  return row,col
633
602
  end
@@ -636,21 +605,20 @@ class Roo::GenericSpreadsheet
636
605
  filename.start_with?("http://", "https://")
637
606
  end
638
607
 
639
- def open_from_uri(uri, tmpdir)
608
+ def download_uri(uri, tmpdir)
640
609
  require 'open-uri'
610
+ tempfilename = File.join(tmpdir, File.basename(uri))
641
611
  response = ''
642
612
  begin
643
- open(uri, "User-Agent" => "Ruby/#{RUBY_VERSION}") { |net|
644
- response = net.read
645
- tempfilename = File.join(tmpdir, File.basename(uri))
646
- File.open(tempfilename,"wb") do |file|
647
- file.write(response)
648
- end
649
- }
613
+ File.open(tempfilename,"wb") do |file|
614
+ open(uri, "User-Agent" => "Ruby/#{RUBY_VERSION}") { |net|
615
+ file.write(net.read)
616
+ }
617
+ end
650
618
  rescue OpenURI::HTTPError
651
619
  raise "could not open #{uri}"
652
620
  end
653
- File.join(tmpdir, File.basename(uri))
621
+ tempfilename
654
622
  end
655
623
 
656
624
  def open_from_stream(stream, tmpdir)
@@ -790,7 +758,7 @@ class Roo::GenericSpreadsheet
790
758
  when :date, :datetime
791
759
  onecell.to_s
792
760
  when :time
793
- Roo::GenericSpreadsheet.integer_to_timestring(onecell)
761
+ Roo::Base.integer_to_timestring(onecell)
794
762
  else
795
763
  raise "unhandled celltype #{celltype(row,col,sheet)}"
796
764
  end || ""