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.
@@ -1,27 +1,24 @@
1
1
  require 'csv'
2
2
  require 'time'
3
3
 
4
- # The Csv class can read csv files (must be separated with commas) which then
4
+ # The CSV class can read csv files (must be separated with commas) which then
5
5
  # can be handled like spreadsheets. This means you can access cells like A5
6
6
  # within these files.
7
- # The Csv class provides only string objects. If you want conversions to other
7
+ # The CSV class provides only string objects. If you want conversions to other
8
8
  # types you have to do it yourself.
9
+ #
10
+ # You can pass options to the underlying CSV parse operation, via the
11
+ # :csv_options option.
12
+ #
9
13
 
10
- class Roo::Csv < Roo::GenericSpreadsheet
11
- def initialize(filename, packed=nil, file_warning=:error, tmpdir=nil)
12
- @filename = filename
13
- @cell = Hash.new
14
- @cell_type = Hash.new
15
- @cells_read = Hash.new
16
- @first_row = Hash.new
17
- @last_row = Hash.new
18
- @first_column = Hash.new
19
- @last_column = Hash.new
14
+ class Roo::CSV < Roo::Base
15
+ def initialize(filename, options = {})
16
+ super
20
17
  end
21
18
 
22
19
  attr_reader :filename
23
20
 
24
- # Returns an array with the names of the sheets. In Csv class there is only
21
+ # Returns an array with the names of the sheets. In CSV class there is only
25
22
  # one dummy sheet, because a csv file cannot have more than one sheet.
26
23
  def sheets
27
24
  ['default']
@@ -29,22 +26,24 @@ class Roo::Csv < Roo::GenericSpreadsheet
29
26
 
30
27
  def cell(row, col, sheet=nil)
31
28
  sheet ||= @default_sheet
32
- read_cells(sheet) unless @cells_read[sheet]
33
- row,col = normalize(row,col)
34
- @cell[[row,col]]
29
+ read_cells(sheet)
30
+ @cell[normalize(row,col)]
35
31
  end
36
32
 
37
33
  def celltype(row, col, sheet=nil)
38
34
  sheet ||= @default_sheet
39
- read_cells(sheet) unless @cells_read[sheet]
40
- row,col = normalize(row,col)
41
- @cell_type[[row,col]]
35
+ read_cells(sheet)
36
+ @cell_type[normalize(row,col)]
42
37
  end
43
38
 
44
39
  def cell_postprocessing(row,col,value)
45
40
  value
46
41
  end
47
42
 
43
+ def csv_options
44
+ @options[:csv_options] || {}
45
+ end
46
+
48
47
  private
49
48
 
50
49
  TYPE_MAP = {
@@ -58,27 +57,26 @@ class Roo::Csv < Roo::GenericSpreadsheet
58
57
  TYPE_MAP[value.class]
59
58
  end
60
59
 
61
- def data
62
- @data ||=
60
+ def each_row(options, &block)
61
+ if uri?(filename)
63
62
  make_tmpdir do |tmpdir|
64
- File.open(
65
- uri?(filename) ?
66
- open_from_uri(filename, tmpdir) :
67
- filename
68
- ) { |f| f.read }
63
+ filename = download_uri(filename, tmpdir)
64
+ CSV.foreach(filename, options, &block)
69
65
  end
66
+ else
67
+ CSV.foreach(filename, options, &block)
68
+ end
70
69
  end
71
70
 
72
71
  def read_cells(sheet=nil)
73
72
  sheet ||= @default_sheet
74
- @cell_type = {} unless @cell_type
75
- @cell = {} unless @cell
73
+ return if @cells_read[sheet]
76
74
  @first_row[sheet] = 1
77
75
  @last_row[sheet] = 0
78
76
  @first_column[sheet] = 1
79
77
  @last_column[sheet] = 1
80
78
  rownum = 1
81
- CSV.parse data do |row|
79
+ each_row csv_options do |row|
82
80
  row.each_with_index do |elem,i|
83
81
  @cell[[rownum,i+1]] = cell_postprocessing rownum,i+1, elem
84
82
  @cell_type[[rownum,i+1]] = celltype_class @cell[[rownum,i+1]]
@@ -112,4 +110,4 @@ class Roo::Csv < Roo::GenericSpreadsheet
112
110
  @last_column[sheet] -= 1
113
111
  end
114
112
  end
115
- end # class Csv
113
+ end
@@ -1,23 +1,33 @@
1
1
  require 'spreadsheet'
2
- #require 'lib/roo/generic_spreadsheet'
3
- #require 'parseexcel'
4
- CHARGUESS =
5
- begin
6
- require 'charguess'
7
- true
8
- rescue LoadError
9
- false
10
- end
11
2
 
12
3
  # Class for handling Excel-Spreadsheets
13
- class Roo::Excel < Roo::GenericSpreadsheet
4
+ class Roo::Excel < Roo::Base
5
+ FORMULAS_MESSAGE = 'the spreadsheet gem does not support forumulas, so roo can not.'
6
+ CHARGUESS =
7
+ begin
8
+ require 'charguess'
9
+ true
10
+ rescue LoadError
11
+ false
12
+ end
13
+
14
+ attr_reader :workbook
14
15
 
15
16
  # Creates a new Excel spreadsheet object.
16
17
  # Parameter packed: :zip - File is a zip-file
17
- def initialize(filename, packed = nil, file_warning = :error)
18
+ def initialize(filename, options = {}, deprecated_file_warning = :error)
19
+ if Hash === options
20
+ packed = options[:packed]
21
+ file_warning = options[:file_warning] || :error
22
+ else
23
+ warn 'Supplying `packed` or `file_warning` as separate arguments to `Roo::Excel.new` is deprected. Use an options hash instead.'
24
+ packed = options
25
+ file_warning = deprecated_file_warning
26
+ end
27
+
18
28
  file_type_check(filename,'.xls','an Excel', file_warning, packed)
19
29
  make_tmpdir do |tmpdir|
20
- filename = open_from_uri(filename, tmpdir) if uri?(filename)
30
+ filename = download_uri(filename, tmpdir) if uri?(filename)
21
31
  filename = open_from_stream(filename[7..-1], tmpdir) if filename[0,7] == "stream:"
22
32
  filename = unzip(filename, tmpdir) if packed == :zip
23
33
 
@@ -27,16 +37,8 @@ class Roo::Excel < Roo::GenericSpreadsheet
27
37
  end
28
38
  @workbook = Spreadsheet.open(filename)
29
39
  end
30
- @default_sheet = self.sheets.first
31
- @cell = Hash.new
32
- @cell_type = Hash.new
40
+ super(filename, options)
33
41
  @formula = Hash.new
34
- @first_row = Hash.new
35
- @last_row = Hash.new
36
- @first_column = Hash.new
37
- @last_column = Hash.new
38
- @header_line = 1
39
- @cells_read = Hash.new
40
42
  @fonts = Hash.new
41
43
  end
42
44
 
@@ -49,12 +51,19 @@ class Roo::Excel < Roo::GenericSpreadsheet
49
51
  @workbook.worksheets.collect {|worksheet| normalize_string(worksheet.name)}
50
52
  end
51
53
 
54
+ # this method lets you find the worksheet with the most data
55
+ def longest_sheet
56
+ sheet(@workbook.worksheets.inject {|m,o|
57
+ o.row_count > m.row_count ? o : m
58
+ }.name)
59
+ end
60
+
52
61
  # returns the content of a cell. The upper left corner is (1,1) or ('A',1)
53
62
  def cell(row,col,sheet=nil)
54
63
  sheet ||= @default_sheet
55
64
  validate_sheet!(sheet)
56
65
 
57
- read_cells(sheet) unless @cells_read[sheet]
66
+ read_cells(sheet)
58
67
  raise "should be read" unless @cells_read[sheet]
59
68
  row,col = normalize(row,col)
60
69
  if celltype(row,col,sheet) == :date
@@ -82,7 +91,7 @@ class Roo::Excel < Roo::GenericSpreadsheet
82
91
  # * :datetime
83
92
  def celltype(row,col,sheet=nil)
84
93
  sheet ||= @default_sheet
85
- read_cells(sheet) unless @cells_read[sheet]
94
+ read_cells(sheet)
86
95
  row,col = normalize(row,col)
87
96
  begin
88
97
  if @formula[sheet] and @formula[sheet][[row,col]]
@@ -98,23 +107,19 @@ class Roo::Excel < Roo::GenericSpreadsheet
98
107
 
99
108
  # returns NO formula in excel spreadsheets
100
109
  def formula(row,col,sheet=nil)
101
- wait_for_version_080
102
- end
103
-
104
- # raises an exception because formulas are not supported for excel files
105
- def formula?(row,col,sheet=nil)
106
- wait_for_version_080
110
+ raise NotImplementedError, FORMULAS_MESSAGE
107
111
  end
112
+ alias_method :formula?, :formula
108
113
 
109
114
  # returns NO formulas in excel spreadsheets
110
115
  def formulas(sheet=nil)
111
- wait_for_version_080
116
+ raise NotImplementedError, FORMULAS_MESSAGE
112
117
  end
113
118
 
114
119
  # Given a cell, return the cell's font
115
120
  def font(row, col, sheet=nil)
116
121
  sheet ||= @default_sheet
117
- read_cells(sheet) unless @cells_read[sheet]
122
+ read_cells(sheet)
118
123
  row,col = normalize(row,col)
119
124
  @fonts[sheet][[row,col]]
120
125
  end
@@ -123,7 +128,7 @@ class Roo::Excel < Roo::GenericSpreadsheet
123
128
  # mainly for debugging purposes
124
129
  def to_s(sheet=nil)
125
130
  sheet ||= @default_sheet
126
- read_cells(sheet) unless @cells_read[sheet]
131
+ read_cells(sheet)
127
132
  @cell[sheet].inspect
128
133
  end
129
134
 
@@ -239,10 +244,7 @@ class Roo::Excel < Roo::GenericSpreadsheet
239
244
  def read_cells(sheet=nil)
240
245
  sheet ||= @default_sheet
241
246
  validate_sheet!(sheet)
242
-
243
- if @cells_read[sheet]
244
- raise "sheet #{sheet} already read"
245
- end
247
+ return if @cells_read[sheet]
246
248
 
247
249
  worksheet = @workbook.worksheet(sheet_no(sheet))
248
250
  row_index=1
@@ -286,7 +288,6 @@ class Roo::Excel < Roo::GenericSpreadsheet
286
288
  false
287
289
  end
288
290
  end
289
- private :date_or_time?
290
291
 
291
292
  # Read the date-time cell and convert to,
292
293
  # the date-time values for Roo
@@ -326,7 +327,6 @@ class Roo::Excel < Roo::GenericSpreadsheet
326
327
  end
327
328
  return value_type, value
328
329
  end
329
- private :read_cell_date_or_time
330
330
 
331
331
  # Read the cell and based on the class,
332
332
  # return the values for Roo
@@ -345,15 +345,5 @@ class Roo::Excel < Roo::GenericSpreadsheet
345
345
  end # case
346
346
  return value_type, value
347
347
  end
348
- private :read_cell
349
-
350
- def wait_for_version_080
351
- if Spreadsheet::VERSION<='0.8.0'
352
- raise 'Formulas are not supported for excel spreadsheets.' +
353
- " We have to wait for the 0.8.0 version of the Spreadsheet gem (currently used version is #{Spreadsheet::VERSION})"
354
- else
355
- raise 'Thomas should implement formulas from Spreadsheet gem'
356
- end
357
- end
358
348
 
359
349
  end
@@ -1,35 +1,34 @@
1
- require 'fileutils'
2
1
  require 'date'
3
2
  require 'base64'
4
- require 'cgi'
5
3
  require 'nokogiri'
6
4
 
7
- class Roo::Excel2003XML < Roo::GenericSpreadsheet
5
+ class Roo::Excel2003XML < Roo::Base
8
6
 
9
7
  # initialization and opening of a spreadsheet file
10
8
  # values for packed: :zip
11
- def initialize(filename, packed=nil, file_warning=:error)
9
+ def initialize(filename, options={}, deprecated_file_warning=:error)
10
+ if Hash === options
11
+ packed = options[:packed]
12
+ file_warning = options[:file_warning] || :error
13
+ else
14
+ warn 'Supplying `packed` or `file_warning` as separate arguments to `Roo::Excel2003XML.new` is deprected. Use an options hash instead.'
15
+ packed = options
16
+ file_warning = deprecated_file_warning
17
+ end
18
+
12
19
  make_tmpdir do |tmpdir|
13
- filename = open_from_uri(filename, tmpdir) if uri?(filename)
20
+ filename = download_uri(filename, tmpdir) if uri?(filename)
14
21
  filename = unzip(filename, tmpdir) if packed == :zip
15
22
 
16
23
  file_type_check(filename,'.xml','an Excel 2003 XML', file_warning)
17
- @cells_read = Hash.new
18
24
  @filename = filename
19
25
  unless File.file?(@filename)
20
26
  raise IOError, "file #{@filename} does not exist"
21
27
  end
22
- @doc = Nokogiri::XML(open(@filename))
28
+ @doc = load_xml(@filename)
23
29
  end
24
- @default_sheet = self.sheets.first
25
- @cell = Hash.new
26
- @cell_type = Hash.new
30
+ super(filename, options)
27
31
  @formula = Hash.new
28
- @first_row = Hash.new
29
- @last_row = Hash.new
30
- @first_column = Hash.new
31
- @last_column = Hash.new
32
- @header_line = 1
33
32
  @style = Hash.new
34
33
  @style_defaults = Hash.new { |h,k| h[k] = [] }
35
34
  @style_definitions = Hash.new
@@ -42,7 +41,7 @@ class Roo::Excel2003XML < Roo::GenericSpreadsheet
42
41
  # cell at the first line and first row.
43
42
  def cell(row, col, sheet=nil)
44
43
  sheet ||= @default_sheet
45
- read_cells(sheet) unless @cells_read[sheet]
44
+ read_cells(sheet)
46
45
  row,col = normalize(row,col)
47
46
  if celltype(row,col,sheet) == :date
48
47
  yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
@@ -56,22 +55,11 @@ class Roo::Excel2003XML < Roo::GenericSpreadsheet
56
55
  # The method #formula? checks if there is a formula.
57
56
  def formula(row,col,sheet=nil)
58
57
  sheet ||= @default_sheet
59
- read_cells(sheet) unless @cells_read[sheet]
60
- row,col = normalize(row,col)
61
- if @formula[sheet][[row,col]] == nil
62
- return nil
63
- else
64
- return @formula[sheet][[row,col]]["oooc:".length..-1]
65
- end
66
- end
67
-
68
- # true, if there is a formula
69
- def formula?(row,col,sheet=nil)
70
- sheet ||= @default_sheet
71
- read_cells(sheet) unless @cells_read[sheet]
58
+ read_cells(sheet)
72
59
  row,col = normalize(row,col)
73
- formula(row,col) != nil
60
+ @formula[sheet][[row,col]] && @formula[sheet][[row,col]]["oooc:".length..-1]
74
61
  end
62
+ alias_method :formula?, :formula
75
63
 
76
64
  class Font
77
65
  attr_accessor :bold, :italic, :underline
@@ -92,7 +80,7 @@ class Roo::Excel2003XML < Roo::GenericSpreadsheet
92
80
  # Given a cell, return the cell's style
93
81
  def font(row, col, sheet=nil)
94
82
  sheet ||= @default_sheet
95
- read_cells(sheet) unless @cells_read[sheet]
83
+ read_cells(sheet)
96
84
  row,col = normalize(row,col)
97
85
  style_name = @style[sheet][[row,col]] || @style_defaults[sheet][col - 1] || 'Default'
98
86
  @style_definitions[style_name]
@@ -108,7 +96,7 @@ class Roo::Excel2003XML < Roo::GenericSpreadsheet
108
96
  # * :datetime
109
97
  def celltype(row,col,sheet=nil)
110
98
  sheet ||= @default_sheet
111
- read_cells(sheet) unless @cells_read[sheet]
99
+ read_cells(sheet)
112
100
  row,col = normalize(row,col)
113
101
  if @formula[sheet][[row,col]]
114
102
  return :formula
@@ -134,7 +122,7 @@ class Roo::Excel2003XML < Roo::GenericSpreadsheet
134
122
  # mainly for debugging purposes
135
123
  def to_s(sheet=nil)
136
124
  sheet ||= @default_sheet
137
- read_cells(sheet) unless @cells_read[sheet]
125
+ read_cells(sheet)
138
126
  @cell[sheet].inspect
139
127
  end
140
128
 
@@ -148,7 +136,7 @@ class Roo::Excel2003XML < Roo::GenericSpreadsheet
148
136
  def formulas(sheet=nil)
149
137
  theformulas = Array.new
150
138
  sheet ||= @default_sheet
151
- read_cells(sheet) unless @cells_read[sheet]
139
+ read_cells(sheet)
152
140
  first_row(sheet).upto(last_row(sheet)) {|row|
153
141
  first_column(sheet).upto(last_column(sheet)) {|col|
154
142
  if formula?(row,col,sheet)
@@ -204,9 +192,9 @@ class Roo::Excel2003XML < Roo::GenericSpreadsheet
204
192
  #++
205
193
  def read_cells(sheet=nil)
206
194
  sheet ||= @default_sheet
195
+ validate_sheet!(sheet)
196
+ return if @cells_read[sheet]
207
197
  sheet_found = false
208
- raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
209
- raise RangeError unless self.sheets.include? sheet
210
198
  @doc.xpath("/ss:Workbook/ss:Worksheet[@ss:Name='#{sheet}']").each do |ws|
211
199
  sheet_found = true
212
200
  row = 1
@@ -1,8 +1,7 @@
1
- require 'fileutils'
2
1
  require 'date'
3
2
  require 'nokogiri'
4
3
 
5
- class Roo::Excelx < Roo::GenericSpreadsheet
4
+ class Roo::Excelx < Roo::Base
6
5
  module Format
7
6
  EXCEPTIONAL_FORMATS = {
8
7
  'h:mm am/pm' => :date,
@@ -66,56 +65,47 @@ class Roo::Excelx < Roo::GenericSpreadsheet
66
65
 
67
66
  # initialization and opening of a spreadsheet file
68
67
  # values for packed: :zip
69
- def initialize(filename, packed=nil, file_warning = :error) #, create = false)
68
+ def initialize(filename, options = {}, deprecated_file_warning = :error)
69
+ if Hash === options
70
+ packed = options[:packed]
71
+ file_warning = options[:file_warning] || :error
72
+ else
73
+ warn 'Supplying `packed` or `file_warning` as separate arguments to `Roo::Excelx.new` is deprected. Use an options hash instead.'
74
+ packed = options
75
+ file_warning = deprecated_file_warning
76
+ end
77
+
70
78
  file_type_check(filename,'.xlsx','an Excel-xlsx', file_warning, packed)
71
79
  make_tmpdir do |tmpdir|
72
- filename = open_from_uri(filename, tmpdir) if uri?(filename)
80
+ filename = download_uri(filename, tmpdir) if uri?(filename)
73
81
  filename = unzip(filename, tmpdir) if packed == :zip
74
- @cells_read = Hash.new
75
82
  @filename = filename
76
83
  unless File.file?(@filename)
77
84
  raise IOError, "file #{@filename} does not exist"
78
85
  end
79
86
  @comments_files = Array.new
80
87
  extract_content(tmpdir, @filename)
81
- @workbook_doc = File.open(File.join(tmpdir, "roo_workbook.xml")) do |file|
82
- Nokogiri::XML(file)
83
- end
88
+ @workbook_doc = load_xml(File.join(tmpdir, "roo_workbook.xml"))
84
89
  @shared_table = []
85
90
  if File.exist?(File.join(tmpdir, 'roo_sharedStrings.xml'))
86
- @sharedstring_doc = File.open(File.join(tmpdir, 'roo_sharedStrings.xml')) do |file|
87
- Nokogiri::XML(file)
88
- end
91
+ @sharedstring_doc = load_xml(File.join(tmpdir, 'roo_sharedStrings.xml'))
89
92
  read_shared_strings(@sharedstring_doc)
90
93
  end
91
94
  @styles_table = []
92
95
  @style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
93
96
  if File.exist?(File.join(tmpdir, 'roo_styles.xml'))
94
- @styles_doc = File.open(File.join(tmpdir, 'roo_styles.xml')) do |file|
95
- Nokogiri::XML(file)
96
- end
97
+ @styles_doc = load_xml(File.join(tmpdir, 'roo_styles.xml'))
97
98
  read_styles(@styles_doc)
98
99
  end
99
100
  @sheet_doc = @sheet_files.map do |item|
100
- File.open(item) do |file|
101
- Nokogiri::XML(file)
102
- end
101
+ load_xml(item)
103
102
  end
104
103
  @comments_doc = @comments_files.map do |item|
105
- File.open(item) do |file|
106
- Nokogiri::XML(file)
107
- end
104
+ load_xml(item)
108
105
  end
109
106
  end
110
- @default_sheet = self.sheets.first
111
- @cell = Hash.new
112
- @cell_type = Hash.new
107
+ super(filename, options)
113
108
  @formula = Hash.new
114
- @first_row = Hash.new
115
- @last_row = Hash.new
116
- @first_column = Hash.new
117
- @last_column = Hash.new
118
- @header_line = 1
119
109
  @excelx_type = Hash.new
120
110
  @excelx_value = Hash.new
121
111
  @s_attribute = Hash.new # TODO: ggf. wieder entfernen nur lokal benoetigt
@@ -128,7 +118,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
128
118
  read_labels
129
119
  if @label.has_key?(m.to_s)
130
120
  sheet ||= @default_sheet
131
- read_cells(sheet) unless @cells_read[sheet]
121
+ read_cells(sheet)
132
122
  row,col = label(m.to_s)
133
123
  cell(row,col)
134
124
  else
@@ -143,7 +133,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
143
133
  # cell at the first line and first row.
144
134
  def cell(row, col, sheet=nil)
145
135
  sheet ||= @default_sheet
146
- read_cells(sheet) unless @cells_read[sheet]
136
+ read_cells(sheet)
147
137
  row,col = normalize(row,col)
148
138
  if celltype(row,col,sheet) == :date
149
139
  yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
@@ -162,28 +152,17 @@ class Roo::Excelx < Roo::GenericSpreadsheet
162
152
  # The method #formula? checks if there is a formula.
163
153
  def formula(row,col,sheet=nil)
164
154
  sheet ||= @default_sheet
165
- read_cells(sheet) unless @cells_read[sheet]
155
+ read_cells(sheet)
166
156
  row,col = normalize(row,col)
167
- if @formula[sheet][[row,col]] == nil
168
- return nil
169
- else
170
- return @formula[sheet][[row,col]]
171
- end
172
- end
173
-
174
- # true, if there is a formula
175
- def formula?(row,col,sheet=nil)
176
- sheet ||= @default_sheet
177
- read_cells(sheet) unless @cells_read[sheet]
178
- row,col = normalize(row,col)
179
- formula(row,col) != nil
157
+ @formula[sheet][[row,col]] && @formula[sheet][[row,col]]
180
158
  end
159
+ alias_method :formula?, :formula
181
160
 
182
161
  # returns each formula in the selected sheet as an array of elements
183
162
  # [row, col, formula]
184
163
  def formulas(sheet=nil)
185
164
  sheet ||= @default_sheet
186
- read_cells(sheet) unless @cells_read[sheet]
165
+ read_cells(sheet)
187
166
  if @formula[sheet]
188
167
  @formula[sheet].each.collect do |elem|
189
168
  [elem[0][0], elem[0][1], elem[1]]
@@ -212,7 +191,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
212
191
  # Given a cell, return the cell's style
213
192
  def font(row, col, sheet=nil)
214
193
  sheet ||= @default_sheet
215
- read_cells(sheet) unless @cells_read[sheet]
194
+ read_cells(sheet)
216
195
  row,col = normalize(row,col)
217
196
  s_attribute = @s_attribute[sheet][[row,col]]
218
197
  s_attribute ||= 0
@@ -230,7 +209,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
230
209
  # * :datetime
231
210
  def celltype(row,col,sheet=nil)
232
211
  sheet ||= @default_sheet
233
- read_cells(sheet) unless @cells_read[sheet]
212
+ read_cells(sheet)
234
213
  row,col = normalize(row,col)
235
214
  if @formula[sheet][[row,col]]
236
215
  return :formula
@@ -245,7 +224,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
245
224
  # Note: this is only available within the Excelx class
246
225
  def excelx_type(row,col,sheet=nil)
247
226
  sheet ||= @default_sheet
248
- read_cells(sheet) unless @cells_read[sheet]
227
+ read_cells(sheet)
249
228
  row,col = normalize(row,col)
250
229
  return @excelx_type[sheet][[row,col]]
251
230
  end
@@ -254,7 +233,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
254
233
  # Note: this is only available within the Excelx class
255
234
  def excelx_value(row,col,sheet=nil)
256
235
  sheet ||= @default_sheet
257
- read_cells(sheet) unless @cells_read[sheet]
236
+ read_cells(sheet)
258
237
  row,col = normalize(row,col)
259
238
  return @excelx_value[sheet][[row,col]]
260
239
  end
@@ -262,7 +241,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
262
241
  # returns the internal format of an excel cell
263
242
  def excelx_format(row,col,sheet=nil)
264
243
  sheet ||= @default_sheet
265
- read_cells(sheet) unless @cells_read[sheet]
244
+ read_cells(sheet)
266
245
  row,col = normalize(row,col)
267
246
  s = @s_attribute[sheet][[row,col]]
268
247
  attribute2format(s).to_s
@@ -279,7 +258,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
279
258
  # for debugging purposes
280
259
  def to_s(sheet=nil)
281
260
  sheet ||= @default_sheet
282
- read_cells(sheet) unless @cells_read[sheet]
261
+ read_cells(sheet)
283
262
  @cell[sheet].inspect
284
263
  end
285
264
 
@@ -291,7 +270,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
291
270
  return nil,nil,nil
292
271
  else
293
272
  return @label[labelname][1].to_i,
294
- Roo::GenericSpreadsheet.letter_to_number(@label[labelname][2]),
273
+ Roo::Base.letter_to_number(@label[labelname][2]),
295
274
  @label[labelname][0]
296
275
  end
297
276
  end
@@ -300,12 +279,12 @@ class Roo::Excelx < Roo::GenericSpreadsheet
300
279
  # [labelname, [row,col,sheetname]]
301
280
  def labels
302
281
  # sheet ||= @default_sheet
303
- # read_cells(sheet) unless @cells_read[sheet]
282
+ # read_cells(sheet)
304
283
  read_labels
305
284
  @label.map do |label|
306
285
  [ label[0], # name
307
286
  [ label[1][1].to_i, # row
308
- Roo::GenericSpreadsheet.letter_to_number(label[1][2]), # column
287
+ Roo::Base.letter_to_number(label[1][2]), # column
309
288
  label[1][0], # sheet
310
289
  ] ]
311
290
  end
@@ -315,7 +294,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
315
294
  # nil if there is no comment
316
295
  def comment(row,col,sheet=nil)
317
296
  sheet ||= @default_sheet
318
- #read_cells(sheet) unless @cells_read[sheet]
297
+ #read_cells(sheet)
319
298
  read_comments(sheet) unless @comments_read[sheet]
320
299
  row,col = normalize(row,col)
321
300
  return nil unless @comment[sheet]
@@ -325,7 +304,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
325
304
  # true, if there is a comment
326
305
  def comment?(row,col,sheet=nil)
327
306
  sheet ||= @default_sheet
328
- # read_cells(sheet) unless @cells_read[sheet]
307
+ # read_cells(sheet)
329
308
  read_comments(sheet) unless @comments_read[sheet]
330
309
  row,col = normalize(row,col)
331
310
  comment(row,col) != nil
@@ -365,9 +344,9 @@ class Roo::Excelx < Roo::GenericSpreadsheet
365
344
  when :string
366
345
  v
367
346
  when :date
368
- (Date.new(1899,12,30)+v.to_i).strftime("%Y-%m-%d")
347
+ (base_date+v.to_i).strftime("%Y-%m-%d")
369
348
  when :datetime
370
- (DateTime.new(1899,12,30)+v.to_f).strftime("%Y-%m-%d %H:%M:%S")
349
+ (base_date+v.to_f).strftime("%Y-%m-%d %H:%M:%S")
371
350
  when :percentage
372
351
  v.to_f
373
352
  when :time
@@ -387,6 +366,8 @@ class Roo::Excelx < Roo::GenericSpreadsheet
387
366
  def read_cells(sheet=nil)
388
367
  sheet ||= @default_sheet
389
368
  validate_sheet!(sheet)
369
+ return if @cells_read[sheet]
370
+
390
371
  @sheet_doc[sheets.index(sheet)].xpath("/xmlns:worksheet/xmlns:sheetData/xmlns:row/xmlns:c").each do |c|
391
372
  s_attribute = c['s'].to_i # should be here
392
373
  # c: <c r="A5" s="2">
@@ -420,7 +401,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
420
401
  value_type = :string
421
402
  v = inlinestr_content
422
403
  excelx_type = :string
423
- y, x = Roo::GenericSpreadsheet.split_coordinate(c['r'])
404
+ y, x = Roo::Base.split_coordinate(c['r'])
424
405
  excelx_value = inlinestr_content #cell.content
425
406
  set_cell_values(sheet,x,y,0,v,value_type,formula,excelx_type,excelx_value,s_attribute)
426
407
  end
@@ -461,7 +442,7 @@ class Roo::Excelx < Roo::GenericSpreadsheet
461
442
  value_type = :float
462
443
  cell.content
463
444
  end
464
- y, x = Roo::GenericSpreadsheet.split_coordinate(c['r'])
445
+ y, x = Roo::Base.split_coordinate(c['r'])
465
446
  set_cell_values(sheet,x,y,0,v,value_type,formula,excelx_type,excelx_value,s_attribute)
466
447
  end
467
448
  end
@@ -519,7 +500,7 @@ Datei xl/comments1.xml
519
500
  return unless @comments_doc[n] #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
520
501
  @comments_doc[n].xpath("//xmlns:comments/xmlns:commentList/xmlns:comment").each do |comment|
521
502
  ref = comment.attributes['ref'].to_s
522
- row,col = Roo::GenericSpreadsheet.split_coordinate(ref)
503
+ row,col = Roo::Base.split_coordinate(ref)
523
504
  comment.xpath('./xmlns:text/xmlns:r/xmlns:t').each do |text|
524
505
  @comment[sheet] ||= {}
525
506
  @comment[sheet][[row,col]] = text.text
@@ -637,4 +618,21 @@ Datei xl/comments1.xml
637
618
  @numFmts[id] || Format::STANDARD_FORMATS[id.to_i]
638
619
  end
639
620
 
621
+ def base_date
622
+ @base_date ||= read_base_date
623
+ end
624
+
625
+ # Default to 1900 (minus one day due to excel quirk) but use 1904 if
626
+ # it's set in the Workbook's workbookPr
627
+ # http://msdn.microsoft.com/en-us/library/ff530155(v=office.12).aspx
628
+ def read_base_date
629
+ base_date = Date.new(1899,12,30)
630
+ @workbook_doc.xpath("//xmlns:workbookPr").map do |workbookPr|
631
+ if workbookPr["date1904"] && workbookPr["date1904"] =~ /true|1/i
632
+ base_date = Date.new(1904,01,01)
633
+ end
634
+ end
635
+ base_date
636
+ end
637
+
640
638
  end # class