roo 1.10.1 → 1.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +38 -0
  4. data/History.txt +4 -4
  5. data/License.txt +20 -0
  6. data/Manifest.txt +68 -0
  7. data/README.markdown +109 -0
  8. data/Rakefile +5 -4
  9. data/bin/roo +0 -0
  10. data/examples/roo_soap_client.rb +53 -0
  11. data/examples/roo_soap_server.rb +29 -0
  12. data/examples/write_me.rb +33 -0
  13. data/lib/roo.rb +20 -61
  14. data/lib/roo/csv.rb +13 -11
  15. data/lib/roo/excel.rb +108 -219
  16. data/lib/roo/excel2003xml.rb +312 -0
  17. data/lib/roo/excelx.rb +205 -341
  18. data/lib/roo/generic_spreadsheet.rb +371 -268
  19. data/lib/roo/google.rb +64 -54
  20. data/lib/roo/openoffice.rb +101 -156
  21. data/lib/roo/roo_rails_helper.rb +5 -5
  22. data/lib/roo/worksheet.rb +18 -0
  23. data/roo.gemspec +43 -0
  24. data/scripts/txt2html +67 -0
  25. data/test/all_ss.rb +8 -10
  26. data/test/{1900_base.xls → files/1900_base.xls} +0 -0
  27. data/test/{1904_base.xls → files/1904_base.xls} +0 -0
  28. data/test/{Bibelbund.csv → files/Bibelbund.csv} +0 -0
  29. data/test/{Bibelbund.ods → files/Bibelbund.ods} +0 -0
  30. data/test/{Bibelbund.xls → files/Bibelbund.xls} +0 -0
  31. data/test/{Bibelbund.xlsx → files/Bibelbund.xlsx} +0 -0
  32. data/test/files/Bibelbund.xml +62518 -0
  33. data/test/{Bibelbund1.ods → files/Bibelbund1.ods} +0 -0
  34. data/test/{Pfand_from_windows_phone.xlsx → files/Pfand_from_windows_phone.xlsx} +0 -0
  35. data/test/files/bad_excel_date.xls +0 -0
  36. data/test/{bbu.ods → files/bbu.ods} +0 -0
  37. data/test/{bbu.xls → files/bbu.xls} +0 -0
  38. data/test/{bbu.xlsx → files/bbu.xlsx} +0 -0
  39. data/test/files/bbu.xml +152 -0
  40. data/test/{bode-v1.ods.zip → files/bode-v1.ods.zip} +0 -0
  41. data/test/{bode-v1.xls.zip → files/bode-v1.xls.zip} +0 -0
  42. data/test/{boolean.ods → files/boolean.ods} +0 -0
  43. data/test/{boolean.xls → files/boolean.xls} +0 -0
  44. data/test/{boolean.xlsx → files/boolean.xlsx} +0 -0
  45. data/test/files/boolean.xml +112 -0
  46. data/test/{borders.ods → files/borders.ods} +0 -0
  47. data/test/{borders.xls → files/borders.xls} +0 -0
  48. data/test/{borders.xlsx → files/borders.xlsx} +0 -0
  49. data/test/files/borders.xml +144 -0
  50. data/test/{bug-row-column-fixnum-float.xls → files/bug-row-column-fixnum-float.xls} +0 -0
  51. data/test/files/bug-row-column-fixnum-float.xml +127 -0
  52. data/test/{comments.ods → files/comments.ods} +0 -0
  53. data/test/{comments.xls → files/comments.xls} +0 -0
  54. data/test/{comments.xlsx → files/comments.xlsx} +0 -0
  55. data/test/{csvtypes.csv → files/csvtypes.csv} +0 -0
  56. data/test/{datetime.ods → files/datetime.ods} +0 -0
  57. data/test/{datetime.xls → files/datetime.xls} +0 -0
  58. data/test/{datetime.xlsx → files/datetime.xlsx} +0 -0
  59. data/test/files/datetime.xml +142 -0
  60. data/test/{datetime_floatconv.xls → files/datetime_floatconv.xls} +0 -0
  61. data/test/files/datetime_floatconv.xml +148 -0
  62. data/test/{dreimalvier.ods → files/dreimalvier.ods} +0 -0
  63. data/test/{emptysheets.ods → files/emptysheets.ods} +0 -0
  64. data/test/{emptysheets.xls → files/emptysheets.xls} +0 -0
  65. data/test/{emptysheets.xlsx → files/emptysheets.xlsx} +0 -0
  66. data/test/files/emptysheets.xml +105 -0
  67. data/test/files/excel2003.xml +21140 -0
  68. data/test/{false_encoding.xls → files/false_encoding.xls} +0 -0
  69. data/test/files/false_encoding.xml +132 -0
  70. data/test/{formula.ods → files/formula.ods} +0 -0
  71. data/test/{formula.xls → files/formula.xls} +0 -0
  72. data/test/{formula.xlsx → files/formula.xlsx} +0 -0
  73. data/test/files/formula.xml +134 -0
  74. data/test/files/formula_parse_error.xls +0 -0
  75. data/test/files/formula_parse_error.xml +1833 -0
  76. data/test/{formula_string_error.xlsx → files/formula_string_error.xlsx} +0 -0
  77. data/test/{html-escape.ods → files/html-escape.ods} +0 -0
  78. data/test/{matrix.ods → files/matrix.ods} +0 -0
  79. data/test/{matrix.xls → files/matrix.xls} +0 -0
  80. data/test/{named_cells.ods → files/named_cells.ods} +0 -0
  81. data/test/{named_cells.xls → files/named_cells.xls} +0 -0
  82. data/test/{named_cells.xlsx → files/named_cells.xlsx} +0 -0
  83. data/test/{no_spreadsheet_file.txt → files/no_spreadsheet_file.txt} +0 -0
  84. data/test/{numbers1.csv → files/numbers1.csv} +0 -0
  85. data/test/{numbers1.ods → files/numbers1.ods} +0 -0
  86. data/test/{numbers1.xls → files/numbers1.xls} +0 -0
  87. data/test/{numbers1.xlsx → files/numbers1.xlsx} +0 -0
  88. data/test/files/numbers1.xml +312 -0
  89. data/test/{only_one_sheet.ods → files/only_one_sheet.ods} +0 -0
  90. data/test/{only_one_sheet.xls → files/only_one_sheet.xls} +0 -0
  91. data/test/{only_one_sheet.xlsx → files/only_one_sheet.xlsx} +0 -0
  92. data/test/files/only_one_sheet.xml +67 -0
  93. data/test/{paragraph.ods → files/paragraph.ods} +0 -0
  94. data/test/{paragraph.xls → files/paragraph.xls} +0 -0
  95. data/test/{paragraph.xlsx → files/paragraph.xlsx} +0 -0
  96. data/test/files/paragraph.xml +127 -0
  97. data/test/{prova.xls → files/prova.xls} +0 -0
  98. data/test/{ric.ods → files/ric.ods} +0 -0
  99. data/test/{simple_spreadsheet.ods → files/simple_spreadsheet.ods} +0 -0
  100. data/test/{simple_spreadsheet.xls → files/simple_spreadsheet.xls} +0 -0
  101. data/test/{simple_spreadsheet.xlsx → files/simple_spreadsheet.xlsx} +0 -0
  102. data/test/files/simple_spreadsheet.xml +225 -0
  103. data/test/{simple_spreadsheet_from_italo.ods → files/simple_spreadsheet_from_italo.ods} +0 -0
  104. data/test/{simple_spreadsheet_from_italo.xls → files/simple_spreadsheet_from_italo.xls} +0 -0
  105. data/test/files/simple_spreadsheet_from_italo.xml +242 -0
  106. data/test/{so_datetime.csv → files/so_datetime.csv} +0 -0
  107. data/test/{style.ods → files/style.ods} +0 -0
  108. data/test/{style.xls → files/style.xls} +0 -0
  109. data/test/{style.xlsx → files/style.xlsx} +0 -0
  110. data/test/files/style.xml +154 -0
  111. data/test/{time-test.csv → files/time-test.csv} +0 -0
  112. data/test/{time-test.ods → files/time-test.ods} +0 -0
  113. data/test/{time-test.xls → files/time-test.xls} +0 -0
  114. data/test/{time-test.xlsx → files/time-test.xlsx} +0 -0
  115. data/test/files/time-test.xml +131 -0
  116. data/test/{type_excel.ods → files/type_excel.ods} +0 -0
  117. data/test/{type_excel.xlsx → files/type_excel.xlsx} +0 -0
  118. data/test/{type_excelx.ods → files/type_excelx.ods} +0 -0
  119. data/test/{type_excelx.xls → files/type_excelx.xls} +0 -0
  120. data/test/{type_openoffice.xls → files/type_openoffice.xls} +0 -0
  121. data/test/{type_openoffice.xlsx → files/type_openoffice.xlsx} +0 -0
  122. data/test/{whitespace.ods → files/whitespace.ods} +0 -0
  123. data/test/{whitespace.xls → files/whitespace.xls} +0 -0
  124. data/test/{whitespace.xlsx → files/whitespace.xlsx} +0 -0
  125. data/test/files/whitespace.xml +184 -0
  126. data/test/test_generic_spreadsheet.rb +257 -0
  127. data/test/test_helper.rb +167 -27
  128. data/test/test_roo.rb +1178 -930
  129. data/website/index.html +385 -0
  130. data/website/index.txt +423 -0
  131. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  132. data/website/stylesheets/screen.css +130 -0
  133. data/website/template.rhtml +48 -0
  134. metadata +151 -121
  135. data/README.txt +0 -110
  136. data/lib/roo/.csv.rb.swp +0 -0
@@ -0,0 +1,312 @@
1
+ require 'fileutils'
2
+ require 'zip/zipfilesystem'
3
+ require 'date'
4
+ require 'base64'
5
+ require 'cgi'
6
+
7
+ class Roo::Excel2003XML < Roo::GenericSpreadsheet
8
+
9
+ # initialization and opening of a spreadsheet file
10
+ # values for packed: :zip
11
+ def initialize(filename, packed=nil, file_warning=:error)
12
+ make_tmpdir do |tmpdir|
13
+ filename = open_from_uri(filename, tmpdir) if uri?(filename)
14
+ filename = unzip(filename, tmpdir) if packed == :zip
15
+
16
+ file_type_check(filename,'.xml','an Excel 2003 XML', file_warning)
17
+ @cells_read = Hash.new
18
+ @filename = filename
19
+ unless File.file?(@filename)
20
+ raise IOError, "file #{@filename} does not exist"
21
+ end
22
+ @doc = Nokogiri::XML(open(@filename))
23
+ end
24
+ @default_sheet = self.sheets.first
25
+ @cell = Hash.new
26
+ @cell_type = Hash.new
27
+ @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
+ @style = Hash.new
34
+ @style_defaults = Hash.new { |h,k| h[k] = [] }
35
+ @style_definitions = Hash.new
36
+ read_styles
37
+ end
38
+
39
+ # Returns the content of a spreadsheet-cell.
40
+ # (1,1) is the upper left corner.
41
+ # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
42
+ # cell at the first line and first row.
43
+ def cell(row, col, sheet=nil)
44
+ sheet ||= @default_sheet
45
+ read_cells(sheet) unless @cells_read[sheet]
46
+ row,col = normalize(row,col)
47
+ if celltype(row,col,sheet) == :date
48
+ yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
49
+ return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
50
+ end
51
+ @cell[sheet][[row,col]]
52
+ end
53
+
54
+ # Returns the formula at (row,col).
55
+ # Returns nil if there is no formula.
56
+ # The method #formula? checks if there is a formula.
57
+ def formula(row,col,sheet=nil)
58
+ 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]
72
+ row,col = normalize(row,col)
73
+ formula(row,col) != nil
74
+ end
75
+
76
+ class Font
77
+ attr_accessor :bold, :italic, :underline
78
+
79
+ def bold?
80
+ @bold == '1'
81
+ end
82
+
83
+ def italic?
84
+ @italic == '1'
85
+ end
86
+
87
+ def underline?
88
+ @underline != nil
89
+ end
90
+ end
91
+
92
+ # Given a cell, return the cell's style
93
+ def font(row, col, sheet=nil)
94
+ sheet ||= @default_sheet
95
+ read_cells(sheet) unless @cells_read[sheet]
96
+ row,col = normalize(row,col)
97
+ style_name = @style[sheet][[row,col]] || @style_defaults[sheet][col - 1] || 'Default'
98
+ @style_definitions[style_name]
99
+ end
100
+
101
+ # returns the type of a cell:
102
+ # * :float
103
+ # * :string
104
+ # * :date
105
+ # * :percentage
106
+ # * :formula
107
+ # * :time
108
+ # * :datetime
109
+ def celltype(row,col,sheet=nil)
110
+ sheet ||= @default_sheet
111
+ read_cells(sheet) unless @cells_read[sheet]
112
+ row,col = normalize(row,col)
113
+ if @formula[sheet][[row,col]]
114
+ return :formula
115
+ else
116
+ @cell_type[sheet][[row,col]]
117
+ end
118
+ end
119
+
120
+ def sheets
121
+ @doc.xpath("/ss:Workbook/ss:Worksheet").map do |sheet|
122
+ sheet['Name']
123
+ end
124
+ end
125
+
126
+ # version of the openoffice document
127
+ # at 2007 this is always "1.0"
128
+ def officeversion
129
+ oo_version
130
+ @officeversion
131
+ end
132
+
133
+ # shows the internal representation of all cells
134
+ # mainly for debugging purposes
135
+ def to_s(sheet=nil)
136
+ sheet ||= @default_sheet
137
+ read_cells(sheet) unless @cells_read[sheet]
138
+ @cell[sheet].inspect
139
+ end
140
+
141
+ # save spreadsheet
142
+ def save #:nodoc:
143
+ 42
144
+ end
145
+
146
+ # returns each formula in the selected sheet as an array of elements
147
+ # [row, col, formula]
148
+ def formulas(sheet=nil)
149
+ theformulas = Array.new
150
+ sheet ||= @default_sheet
151
+ read_cells(sheet) unless @cells_read[sheet]
152
+ first_row(sheet).upto(last_row(sheet)) {|row|
153
+ first_column(sheet).upto(last_column(sheet)) {|col|
154
+ if formula?(row,col,sheet)
155
+ f = [row, col, formula(row,col,sheet)]
156
+ theformulas << f
157
+ end
158
+ }
159
+ }
160
+ theformulas
161
+ end
162
+
163
+ private
164
+
165
+ # read the version of the OO-Version
166
+ def oo_version
167
+ @doc.find("//*[local-name()='document-content']").each do |office|
168
+ @officeversion = office['version']
169
+ end
170
+ end
171
+
172
+ # helper function to set the internal representation of cells
173
+ def set_cell_values(sheet,x,y,i,v,value_type,formula,table_cell,str_v,style_name)
174
+ key = [y,x+i]
175
+ @cell_type[sheet] = {} unless @cell_type[sheet]
176
+ @cell_type[sheet][key] = value_type
177
+ @formula[sheet] = {} unless @formula[sheet]
178
+ @formula[sheet][key] = formula if formula
179
+ @cell[sheet] = {} unless @cell[sheet]
180
+ @style[sheet] = {} unless @style[sheet]
181
+ @style[sheet][key] = style_name
182
+ @cell[sheet][key] =
183
+ case @cell_type[sheet][key]
184
+ when :float
185
+ v.to_f
186
+ when :string
187
+ str_v
188
+ when :datetime
189
+ DateTime.parse(v)
190
+ when :percentage
191
+ v.to_f
192
+ # when :time
193
+ # hms = v.split(':')
194
+ # hms[0].to_i*3600 + hms[1].to_i*60 + hms[2].to_i
195
+ else
196
+ v
197
+ end
198
+ end
199
+
200
+ # read all cells in the selected sheet
201
+ #--
202
+ # the following construct means '4 blanks'
203
+ # some content <text:s text:c="3"/>
204
+ #++
205
+ def read_cells(sheet=nil)
206
+ sheet ||= @default_sheet
207
+ 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
+ @doc.xpath("/ss:Workbook/ss:Worksheet[@ss:Name='#{sheet}']").each do |ws|
211
+ sheet_found = true
212
+ row = 1
213
+ col = 1
214
+ column_attributes = {}
215
+ idx = 0
216
+ ws.xpath('./ss:Table/ss:Column').each do |c|
217
+ column_attributes[(idx += 1).to_s] = c['StyleID']
218
+ end
219
+ ws.xpath('./ss:Table/ss:Row').each do |r|
220
+ skip_to_row = r['Index'].to_i
221
+ row = skip_to_row if skip_to_row > 0
222
+ style_name = r['StyleID'] if r['StyleID']
223
+ r.xpath('./ss:Cell').each do |c|
224
+ skip_to_col = c['Index'].to_i
225
+ col = skip_to_col if skip_to_col > 0
226
+ if c['StyleID']
227
+ style_name = c['StyleID']
228
+ elsif
229
+ style_name ||= column_attributes[c['Index']]
230
+ end
231
+ c.xpath('./ss:Data').each do |cell|
232
+ formula = cell['Formula']
233
+ value_type = cell['Type'].downcase.to_sym
234
+ v = cell.content
235
+ str_v = v
236
+ case value_type
237
+ when :number
238
+ v = v.to_f
239
+ value_type = :float
240
+ when :datetime
241
+ if v =~ /^1899-12-31T(\d{2}:\d{2}:\d{2})/
242
+ v = $1
243
+ value_type = :time
244
+ elsif v =~ /([^T]+)T00:00:00.000/
245
+ v = $1
246
+ value_type = :date
247
+ end
248
+ when :boolean
249
+ v = cell['boolean-value']
250
+ end
251
+ set_cell_values(sheet,col,row,0,v,value_type,formula,cell,str_v,style_name)
252
+ end
253
+ col += 1
254
+ end
255
+ row += 1
256
+ col = 1
257
+ end
258
+ end
259
+ if !sheet_found
260
+ raise RangeError, "Unable to find sheet #{sheet} for reading"
261
+ end
262
+ @cells_read[sheet] = true
263
+ end
264
+
265
+ def read_styles
266
+ @doc.xpath("/ss:Workbook/ss:Styles/ss:Style").each do |style|
267
+ style_id = style['ID']
268
+ @style_definitions[style_id] = Roo::Excel2003XML::Font.new
269
+ if font = style.at_xpath('./ss:Font')
270
+ @style_definitions[style_id].bold = font['Bold']
271
+ @style_definitions[style_id].italic = font['Italic']
272
+ @style_definitions[style_id].underline = font['Underline']
273
+ end
274
+ end
275
+ end
276
+
277
+ A_ROO_TYPE = {
278
+ "float" => :float,
279
+ "string" => :string,
280
+ "date" => :date,
281
+ "percentage" => :percentage,
282
+ "time" => :time,
283
+ }
284
+
285
+ def self.oo_type_2_roo_type(ootype)
286
+ return A_ROO_TYPE[ootype]
287
+ end
288
+
289
+ # helper method to convert compressed spaces and other elements within
290
+ # an text into a string
291
+ def children_to_string(children)
292
+ result = ''
293
+ children.each {|child|
294
+ if child.text?
295
+ result = result + child.content
296
+ else
297
+ if child.name == 's'
298
+ compressed_spaces = child['c'].to_i
299
+ # no explicit number means a count of 1:
300
+ if compressed_spaces == 0
301
+ compressed_spaces = 1
302
+ end
303
+ result = result + " "*compressed_spaces
304
+ else
305
+ result = result + child.content
306
+ end
307
+ end
308
+ }
309
+ result
310
+ end
311
+
312
+ end # class
data/lib/roo/excelx.rb CHANGED
@@ -12,7 +12,7 @@ if RUBY_VERSION < '1.9.0'
12
12
  end
13
13
  end
14
14
 
15
- class Excelx < GenericSpreadsheet
15
+ class Roo::Excelx < Roo::GenericSpreadsheet
16
16
  FORMATS = {
17
17
  'General' => :float,
18
18
  '0' => :float,
@@ -51,7 +51,7 @@ class Excelx < GenericSpreadsheet
51
51
  'yyyy-mm-dd' => :date, # 2011-09-16
52
52
  # was used in a spreadsheet file from a windows phone
53
53
  }
54
- STANDARD_FORMATS = {
54
+ STANDARD_FORMATS = {
55
55
  0 => 'General',
56
56
  1 => '0',
57
57
  2 => '0.00',
@@ -81,62 +81,50 @@ class Excelx < GenericSpreadsheet
81
81
  48 => '##0.0E+0',
82
82
  49 => '@',
83
83
  }
84
- @@nr = 0
85
84
 
86
85
  # initialization and opening of a spreadsheet file
87
86
  # values for packed: :zip
88
87
  def initialize(filename, packed=nil, file_warning = :error) #, create = false)
89
- super()
90
- @file_warning = file_warning
91
- file_type_check(filename,'.xlsx','an Excel-xlsx',packed)
92
- @tmpdir = GenericSpreadsheet.next_tmpdir
93
- @tmpdir = File.join(ENV['ROO_TMP'], @tmpdir) if ENV['ROO_TMP']
94
- unless File.exists?(@tmpdir)
95
- FileUtils::mkdir(@tmpdir)
96
- end
97
- filename = open_from_uri(filename) if filename[0,7] == "http://"
98
- filename = unzip(filename) if packed and packed == :zip
99
- @cells_read = Hash.new
100
- @filename = filename
101
- unless File.file?(@filename)
102
- FileUtils::rm_r(@tmpdir)
103
- raise IOError, "file #{@filename} does not exist"
104
- end
105
- @@nr += 1
106
- @file_nr = @@nr
107
- @comments_files = Array.new
108
- extract_content(@filename)
109
- file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
110
- @workbook_doc = Nokogiri::XML(file)
111
- file.close
112
- @shared_table = []
113
- if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
114
- file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
115
- @sharedstring_doc = Nokogiri::XML(file)
116
- file.close
117
- read_shared_strings(@sharedstring_doc)
118
- end
119
- @styles_table = []
120
- @style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
121
- if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
122
- file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
123
- @styles_doc = Nokogiri::XML(file)
124
- file.close
125
- read_styles(@styles_doc)
126
- end
127
- @sheet_doc = []
128
- @sheet_files.each_with_index do |item, i|
129
- file = File.new(item)
130
- @sheet_doc[i] = Nokogiri::XML(file)
131
- file.close
132
- end
133
- @comments_doc = []
134
- @comments_files.each_with_index do |item, i|
135
- file = File.new(item)
136
- @comments_doc[i] = Nokogiri::XML(file)
137
- file.close
88
+ file_type_check(filename,'.xlsx','an Excel-xlsx', file_warning, packed)
89
+ make_tmpdir do |tmpdir|
90
+ filename = open_from_uri(filename, tmpdir) if uri?(filename)
91
+ filename = unzip(filename, tmpdir) if packed == :zip
92
+ @cells_read = Hash.new
93
+ @filename = filename
94
+ unless File.file?(@filename)
95
+ raise IOError, "file #{@filename} does not exist"
96
+ end
97
+ @comments_files = Array.new
98
+ extract_content(tmpdir, @filename)
99
+ @workbook_doc = File.open(File.join(tmpdir, "roo_workbook.xml")) do |file|
100
+ Nokogiri::XML(file)
101
+ end
102
+ @shared_table = []
103
+ if File.exist?(File.join(tmpdir, 'roo_sharedStrings.xml'))
104
+ @sharedstring_doc = File.open(File.join(tmpdir, 'roo_sharedStrings.xml')) do |file|
105
+ Nokogiri::XML(file)
106
+ end
107
+ read_shared_strings(@sharedstring_doc)
108
+ end
109
+ @styles_table = []
110
+ @style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
111
+ if File.exist?(File.join(tmpdir, 'roo_styles.xml'))
112
+ @styles_doc = File.open(File.join(tmpdir, 'roo_styles.xml')) do |file|
113
+ Nokogiri::XML(file)
114
+ end
115
+ read_styles(@styles_doc)
116
+ end
117
+ @sheet_doc = @sheet_files.map do |item|
118
+ File.open(item) do |file|
119
+ Nokogiri::XML(file)
120
+ end
121
+ end
122
+ @comments_doc = @comments_files.map do |item|
123
+ File.open(item) do |file|
124
+ Nokogiri::XML(file)
125
+ end
126
+ end
138
127
  end
139
- FileUtils::rm_r(@tmpdir)
140
128
  @default_sheet = self.sheets.first
141
129
  @cell = Hash.new
142
130
  @cell_type = Hash.new
@@ -149,17 +137,15 @@ class Excelx < GenericSpreadsheet
149
137
  @excelx_type = Hash.new
150
138
  @excelx_value = Hash.new
151
139
  @s_attribute = Hash.new # TODO: ggf. wieder entfernen nur lokal benoetigt
152
- @label = Hash.new
153
- @labels_read = false
154
140
  @comment = Hash.new
155
141
  @comments_read = Hash.new
156
142
  end
157
143
 
158
144
  def method_missing(m,*args)
159
145
  # is method name a label name
160
- read_labels unless @labels_read
146
+ read_labels
161
147
  if @label.has_key?(m.to_s)
162
- sheet = @default_sheet unless sheet
148
+ sheet ||= @default_sheet
163
149
  read_cells(sheet) unless @cells_read[sheet]
164
150
  row,col = label(m.to_s)
165
151
  cell(row,col)
@@ -168,13 +154,13 @@ class Excelx < GenericSpreadsheet
168
154
  super
169
155
  end
170
156
  end
171
-
157
+
172
158
  # Returns the content of a spreadsheet-cell.
173
159
  # (1,1) is the upper left corner.
174
160
  # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
175
161
  # cell at the first line and first row.
176
162
  def cell(row, col, sheet=nil)
177
- sheet = @default_sheet unless sheet
163
+ sheet ||= @default_sheet
178
164
  read_cells(sheet) unless @cells_read[sheet]
179
165
  row,col = normalize(row,col)
180
166
  if celltype(row,col,sheet) == :date
@@ -193,7 +179,7 @@ class Excelx < GenericSpreadsheet
193
179
  # Returns nil if there is no formula.
194
180
  # The method #formula? checks if there is a formula.
195
181
  def formula(row,col,sheet=nil)
196
- sheet = @default_sheet unless sheet
182
+ sheet ||= @default_sheet
197
183
  read_cells(sheet) unless @cells_read[sheet]
198
184
  row,col = normalize(row,col)
199
185
  if @formula[sheet][[row,col]] == nil
@@ -205,7 +191,7 @@ class Excelx < GenericSpreadsheet
205
191
 
206
192
  # true, if there is a formula
207
193
  def formula?(row,col,sheet=nil)
208
- sheet = @default_sheet unless sheet
194
+ sheet ||= @default_sheet
209
195
  read_cells(sheet) unless @cells_read[sheet]
210
196
  row,col = normalize(row,col)
211
197
  formula(row,col) != nil
@@ -214,7 +200,7 @@ class Excelx < GenericSpreadsheet
214
200
  # returns each formula in the selected sheet as an array of elements
215
201
  # [row, col, formula]
216
202
  def formulas(sheet=nil)
217
- sheet = @default_sheet unless sheet
203
+ sheet ||= @default_sheet
218
204
  read_cells(sheet) unless @cells_read[sheet]
219
205
  if @formula[sheet]
220
206
  @formula[sheet].each.collect do |elem|
@@ -227,47 +213,29 @@ class Excelx < GenericSpreadsheet
227
213
 
228
214
  class Font
229
215
  attr_accessor :bold, :italic, :underline
230
-
216
+
231
217
  def bold?
232
218
  @bold == true
233
219
  end
234
-
235
- def italic?
220
+
221
+ def italic?
236
222
  @italic == true
237
223
  end
238
-
224
+
239
225
  def underline?
240
226
  @underline == true
241
- end
227
+ end
242
228
  end
243
-
229
+
244
230
  # Given a cell, return the cell's style
245
231
  def font(row, col, sheet=nil)
246
- sheet = @default_sheet unless sheet
232
+ sheet ||= @default_sheet
247
233
  read_cells(sheet) unless @cells_read[sheet]
248
234
  row,col = normalize(row,col)
249
235
  s_attribute = @s_attribute[sheet][[row,col]]
250
236
  s_attribute ||= 0
251
237
  s_attribute = s_attribute.to_i
252
238
  @style_definitions[s_attribute]
253
- end
254
-
255
- # set a cell to a certain value
256
- # (this will not be saved back to the spreadsheet file!)
257
- def set(row,col,value,sheet=nil) #:nodoc:
258
- sheet = @default_sheet unless sheet
259
- read_cells(sheet) unless @cells_read[sheet]
260
- row,col = normalize(row,col)
261
- set_value(row,col,value,sheet)
262
- if value.class == Fixnum
263
- set_type(row,col,:float,sheet)
264
- elsif value.class == String
265
- set_type(row,col,:string,sheet)
266
- elsif value.class == Float
267
- set_type(row,col,:string,sheet)
268
- else
269
- raise ArgumentError, "Type for "+value.to_s+" not set"
270
- end
271
239
  end
272
240
 
273
241
  # returns the type of a cell:
@@ -279,7 +247,7 @@ class Excelx < GenericSpreadsheet
279
247
  # * :time
280
248
  # * :datetime
281
249
  def celltype(row,col,sheet=nil)
282
- sheet = @default_sheet unless sheet
250
+ sheet ||= @default_sheet
283
251
  read_cells(sheet) unless @cells_read[sheet]
284
252
  row,col = normalize(row,col)
285
253
  if @formula[sheet][[row,col]]
@@ -291,47 +259,44 @@ class Excelx < GenericSpreadsheet
291
259
 
292
260
  # returns the internal type of an excel cell
293
261
  # * :numeric_or_formula
294
- # * :string
295
- # Note: this is only available within the Excelx class
262
+ # * :string
263
+ # Note: this is only available within the Excelx class
296
264
  def excelx_type(row,col,sheet=nil)
297
- sheet = @default_sheet unless sheet
265
+ sheet ||= @default_sheet
298
266
  read_cells(sheet) unless @cells_read[sheet]
299
267
  row,col = normalize(row,col)
300
268
  return @excelx_type[sheet][[row,col]]
301
269
  end
302
-
270
+
303
271
  # returns the internal value of an excelx cell
304
- # Note: this is only available within the Excelx class
272
+ # Note: this is only available within the Excelx class
305
273
  def excelx_value(row,col,sheet=nil)
306
- sheet = @default_sheet unless sheet
274
+ sheet ||= @default_sheet
307
275
  read_cells(sheet) unless @cells_read[sheet]
308
276
  row,col = normalize(row,col)
309
277
  return @excelx_value[sheet][[row,col]]
310
278
  end
311
-
279
+
312
280
  # returns the internal format of an excel cell
313
281
  def excelx_format(row,col,sheet=nil)
314
- sheet = @default_sheet unless sheet
282
+ sheet ||= @default_sheet
315
283
  read_cells(sheet) unless @cells_read[sheet]
316
284
  row,col = normalize(row,col)
317
285
  s = @s_attribute[sheet][[row,col]]
318
- result = attribute2format(s).to_s
319
- result
286
+ attribute2format(s).to_s
320
287
  end
321
-
288
+
322
289
  # returns an array of sheet names in the spreadsheet
323
290
  def sheets
324
- return_sheets = []
325
- @workbook_doc.xpath("//*[local-name()='sheet']").each do |sheet|
326
- return_sheets << sheet['name']
291
+ @workbook_doc.xpath("//xmlns:sheet").map do |sheet|
292
+ sheet['name']
327
293
  end
328
- return_sheets
329
294
  end
330
295
 
331
296
  # shows the internal representation of all cells
332
297
  # for debugging purposes
333
298
  def to_s(sheet=nil)
334
- sheet = @default_sheet unless sheet
299
+ sheet ||= @default_sheet
335
300
  read_cells(sheet) unless @cells_read[sheet]
336
301
  @cell[sheet].inspect
337
302
  end
@@ -339,40 +304,35 @@ class Excelx < GenericSpreadsheet
339
304
  # returns the row,col values of the labelled cell
340
305
  # (nil,nil) if label is not defined
341
306
  def label(labelname)
342
- read_labels unless @labels_read
343
- unless @label.size > 0
307
+ read_labels
308
+ if @label.empty? || !@label.has_key?(labelname)
344
309
  return nil,nil,nil
345
- end
346
- if @label.has_key? labelname
310
+ else
347
311
  return @label[labelname][1].to_i,
348
- GenericSpreadsheet.letter_to_number(@label[labelname][2]),
312
+ Roo::GenericSpreadsheet.letter_to_number(@label[labelname][2]),
349
313
  @label[labelname][0]
350
- else
351
- return nil,nil,nil
352
314
  end
353
315
  end
354
316
 
355
317
  # Returns an array which all labels. Each element is an array with
356
- # [labelname, [sheetname,row,col]]
318
+ # [labelname, [row,col,sheetname]]
357
319
  def labels
358
- # sheet = @default_sheet unless sheet
320
+ # sheet ||= @default_sheet
359
321
  # read_cells(sheet) unless @cells_read[sheet]
360
- read_labels unless @labels_read
361
- result = []
362
- @label.each do |label|
363
- result << [ label[0], # name
322
+ read_labels
323
+ @label.map do |label|
324
+ [ label[0], # name
364
325
  [ label[1][1].to_i, # row
365
- GenericSpreadsheet.letter_to_number(label[1][2]), # column
326
+ Roo::GenericSpreadsheet.letter_to_number(label[1][2]), # column
366
327
  label[1][0], # sheet
367
328
  ] ]
368
329
  end
369
- result
370
330
  end
371
331
 
372
332
  # returns the comment at (row/col)
373
333
  # nil if there is no comment
374
334
  def comment(row,col,sheet=nil)
375
- sheet = @default_sheet unless sheet
335
+ sheet ||= @default_sheet
376
336
  #read_cells(sheet) unless @cells_read[sheet]
377
337
  read_comments(sheet) unless @comments_read[sheet]
378
338
  row,col = normalize(row,col)
@@ -382,7 +342,7 @@ class Excelx < GenericSpreadsheet
382
342
 
383
343
  # true, if there is a comment
384
344
  def comment?(row,col,sheet=nil)
385
- sheet = @default_sheet unless sheet
345
+ sheet ||= @default_sheet
386
346
  # read_cells(sheet) unless @cells_read[sheet]
387
347
  read_comments(sheet) unless @comments_read[sheet]
388
348
  row,col = normalize(row,col)
@@ -392,7 +352,7 @@ class Excelx < GenericSpreadsheet
392
352
  # returns each comment in the selected sheet as an array of elements
393
353
  # [row, col, comment]
394
354
  def comments(sheet=nil)
395
- sheet = @default_sheet unless sheet
355
+ sheet ||= @default_sheet
396
356
  read_comments(sheet) unless @comments_read[sheet]
397
357
  if @comment[sheet]
398
358
  @comment[sheet].each.collect do |elem|
@@ -406,37 +366,38 @@ class Excelx < GenericSpreadsheet
406
366
  private
407
367
 
408
368
  # helper function to set the internal representation of cells
409
- def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v,
369
+ def set_cell_values(sheet,x,y,i,v,value_type,formula,
410
370
  excelx_type=nil,
411
371
  excelx_value=nil,
412
372
  s_attribute=nil)
413
373
  key = [y,x+i]
414
- @cell_type[sheet] = {} unless @cell_type[sheet]
415
- @cell_type[sheet][key] = vt
416
- @formula[sheet] = {} unless @formula[sheet]
374
+ @cell_type[sheet] ||= {}
375
+ @cell_type[sheet][key] = value_type
376
+ @formula[sheet] ||= {}
417
377
  @formula[sheet][key] = formula if formula
418
- @cell[sheet] = {} unless @cell[sheet]
419
- case @cell_type[sheet][key]
420
- when :float
421
- @cell[sheet][key] = v.to_f
422
- when :string
423
- @cell[sheet][key] = str_v
424
- when :date
425
- @cell[sheet][key] = (Date.new(1899,12,30)+v.to_i).strftime("%Y-%m-%d")
426
- when :datetime
427
- @cell[sheet][key] = (DateTime.new(1899,12,30)+v.to_f).strftime("%Y-%m-%d %H:%M:%S")
428
- when :percentage
429
- @cell[sheet][key] = v.to_f
430
- when :time
431
- @cell[sheet][key] = v.to_f*(24*60*60)
432
- else
433
- @cell[sheet][key] = v
434
- end
435
- @excelx_type[sheet] = {} unless @excelx_type[sheet]
378
+ @cell[sheet] ||= {}
379
+ @cell[sheet][key] =
380
+ case @cell_type[sheet][key]
381
+ when :float
382
+ v.to_f
383
+ when :string
384
+ v
385
+ when :date
386
+ (Date.new(1899,12,30)+v.to_i).strftime("%Y-%m-%d")
387
+ when :datetime
388
+ (DateTime.new(1899,12,30)+v.to_f).strftime("%Y-%m-%d %H:%M:%S")
389
+ when :percentage
390
+ v.to_f
391
+ when :time
392
+ v.to_f*(24*60*60)
393
+ else
394
+ v
395
+ end
396
+ @excelx_type[sheet] ||= {}
436
397
  @excelx_type[sheet][key] = excelx_type
437
- @excelx_value[sheet] = {} unless @excelx_value[sheet]
398
+ @excelx_value[sheet] ||= {}
438
399
  @excelx_value[sheet][key] = excelx_value
439
- @s_attribute[sheet] = {} unless @s_attribute[sheet]
400
+ @s_attribute[sheet] ||= {}
440
401
  @s_attribute[sheet][key] = s_attribute
441
402
  end
442
403
 
@@ -451,107 +412,87 @@ class Excelx < GenericSpreadsheet
451
412
 
452
413
  # read all cells in the selected sheet
453
414
  def read_cells(sheet=nil)
454
- sheet = @default_sheet unless sheet
455
- sheet_found = false
456
- raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
457
- raise RangeError unless self.sheets.include? sheet
458
- n = self.sheets.index(sheet)
459
- @sheet_doc[n].xpath("//*[local-name()='c']").each do |c|
415
+ sheet ||= @default_sheet
416
+ validate_sheet!(sheet)
417
+ @sheet_doc[sheets.index(sheet)].xpath("/xmlns:worksheet/xmlns:sheetData/xmlns:row/xmlns:c").each do |c|
460
418
  s_attribute = c['s'].to_i # should be here
461
419
  # c: <c r="A5" s="2">
462
420
  # <v>22606</v>
463
421
  # </c>, format: , tmp_type: float
464
- if c['t'] == 's'
465
- tmp_type = :shared
466
- elsif c['t'] == 'b'
467
- tmp_type = :boolean
468
- # 2011-02-25 BEGIN
469
- elsif c['t'] == 'str'
470
- tmp_type = :string
471
- # 2011-02-25 END
472
- # 2011-09-15 BEGIN
473
- elsif c['t'] == 'inlineStr'
474
- tmp_type = :inlinestr
475
- # 2011-09-15 END
476
- else
477
- s_attribute = c['s'].to_i
478
- format = attribute2format(s_attribute)
479
- tmp_type = format2type(format)
480
- end
422
+ value_type =
423
+ case c['t']
424
+ when 's'
425
+ :shared
426
+ when 'b'
427
+ :boolean
428
+ # 2011-02-25 BEGIN
429
+ when 'str'
430
+ :string
431
+ # 2011-02-25 END
432
+ # 2011-09-15 BEGIN
433
+ when 'inlineStr'
434
+ :inlinestr
435
+ # 2011-09-15 END
436
+ else
437
+ format = attribute2format(s_attribute)
438
+ format2type(format)
439
+ end
481
440
  formula = nil
482
441
  c.children.each do |cell|
483
- # 2011-09-15 BEGIN
484
- if cell.name == 'is'
442
+ case cell.name
443
+ when 'is'
485
444
  cell.children.each do |is|
486
445
  if is.name == 't'
487
446
  inlinestr_content = is.content
488
- vt = :string
489
- str_v = inlinestr_content
447
+ value_type = :string
448
+ v = inlinestr_content
490
449
  excelx_type = :string
491
- y, x = GenericSpreadsheet.split_coordinate(c['r'])
492
- v = nil
493
- tr=nil #TODO: ???s
450
+ y, x = Roo::GenericSpreadsheet.split_coordinate(c['r'])
494
451
  excelx_value = inlinestr_content #cell.content
495
- set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
452
+ set_cell_values(sheet,x,y,0,v,value_type,formula,excelx_type,excelx_value,s_attribute)
496
453
  end
497
454
  end
498
- end
499
- # 2011-09-15 END
500
- if cell.name == 'f'
455
+ when 'f'
501
456
  formula = cell.content
502
- end
503
- if cell.name == 'v'
504
- if tmp_type == :time or tmp_type == :datetime
505
- if cell.content.to_f >= 1.0
506
- if (cell.content.to_f - cell.content.to_f.floor).abs > 0.000001
507
- tmp_type = :datetime
457
+ when 'v'
458
+ if [:time, :datetime].include?(value_type) && cell.content.to_f >= 1.0
459
+ value_type =
460
+ if (cell.content.to_f - cell.content.to_f.floor).abs > 0.000001
461
+ :datetime
508
462
  else
509
- tmp_type = :date
463
+ :date
510
464
  end
511
- else
512
- end
513
465
  end
514
466
  excelx_type = [:numeric_or_formula,format.to_s]
515
467
  excelx_value = cell.content
516
- if tmp_type == :shared
517
- vt = :string
518
- str_v = @shared_table[cell.content.to_i]
519
- excelx_type = :string
520
- elsif tmp_type == :boolean
521
- vt = :boolean
522
- cell.content.to_i == 1 ? v = 'TRUE' : v = 'FALSE'
523
- elsif tmp_type == :date
524
- vt = :date
525
- v = cell.content
526
- elsif tmp_type == :time
527
- vt = :time
528
- v = cell.content
529
- elsif tmp_type == :datetime
530
- vt = :datetime
531
- v = cell.content
532
- elsif tmp_type == :formula
533
- vt = :formula
534
- v = cell.content.to_f #TODO: !!!!
535
- # 2011-02-25 BEGIN
536
- elsif tmp_type == :string
537
- vt = :string
538
- str_v = cell.content
539
- excelx_type = :string
540
- # 2011-02-25 END
541
- else
542
- vt = :float
543
- v = cell.content
544
- end
545
- y, x = GenericSpreadsheet.split_coordinate(c['r'])
546
- tr=nil #TODO: ???s
547
- set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
468
+ v =
469
+ case value_type
470
+ when :shared
471
+ value_type = :string
472
+ excelx_type = :string
473
+ @shared_table[cell.content.to_i]
474
+ when :boolean
475
+ (cell.content.to_i == 1 ? 'TRUE' : 'FALSE')
476
+ when :date
477
+ cell.content
478
+ when :time
479
+ cell.content
480
+ when :datetime
481
+ cell.content
482
+ when :formula
483
+ cell.content.to_f #TODO: !!!!
484
+ when :string
485
+ excelx_type = :string
486
+ cell.content
487
+ else
488
+ value_type = :float
489
+ cell.content
490
+ end
491
+ y, x = Roo::GenericSpreadsheet.split_coordinate(c['r'])
492
+ set_cell_values(sheet,x,y,0,v,value_type,formula,excelx_type,excelx_value,s_attribute)
548
493
  end
549
494
  end
550
495
  end
551
- sheet_found = true #TODO:
552
- if !sheet_found
553
- raise RangeError
554
- end
555
496
  @cells_read[sheet] = true
556
497
  # begin comments
557
498
  =begin
@@ -599,71 +540,37 @@ Datei xl/comments1.xml
599
540
 
600
541
  # Reads all comments from a sheet
601
542
  def read_comments(sheet=nil)
602
- sheet = @default_sheet unless sheet
603
- #sheet_found = false
604
- raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
605
- raise RangeError unless self.sheets.include? sheet
543
+ sheet ||= @default_sheet
544
+ validate_sheet!(sheet)
606
545
  n = self.sheets.index(sheet)
607
546
  return unless @comments_doc[n] #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
608
- @comments_doc[n].xpath("//*[local-name()='comments']").each do |comment|
609
- comment.children.each do |cc|
610
- if cc.name == 'commentList'
611
- cc.children.each do |commentlist|
612
- if commentlist.name == 'comment'
613
- ref = commentlist.attributes['ref'].to_s
614
- row,col = GenericSpreadsheet.split_coordinate(ref)
615
- commentlist.children.each do |clc|
616
- if clc.name == 'text'
617
- clc.children.each do |text|
618
- if text.name == 'r'
619
- text.children.each do |r|
620
- if r.name == 't'
621
- comment = r.text
622
- @comment[sheet] = Hash.new unless @comment[sheet]
623
- @comment[sheet][[row,col]] = comment
624
- end
625
- end
626
- end
627
- end
628
- end
629
- end
630
- end
631
- end
632
- end
547
+ @comments_doc[n].xpath("//xmlns:comments/xmlns:commentList/xmlns:comment").each do |comment|
548
+ ref = comment.attributes['ref'].to_s
549
+ row,col = Roo::GenericSpreadsheet.split_coordinate(ref)
550
+ comment.xpath('./xmlns:text/xmlns:r/xmlns:t').each do |text|
551
+ @comment[sheet] ||= {}
552
+ @comment[sheet][[row,col]] = text.text
633
553
  end
634
554
  end
635
555
  @comments_read[sheet] = true
636
556
  end
637
557
 
638
558
  def read_labels
639
- @workbook_doc.xpath("//*[local-name()='definedName']").each do |defined_name|
559
+ @label ||= Hash[@workbook_doc.xpath("//xmlns:definedName").map do |defined_name|
640
560
  # "Sheet1!$C$5"
641
- sheet = defined_name.text.split('!').first
642
- coordinates = defined_name.text.split('!')[1]
643
- dummy,col,row = coordinates.split('$')
644
- @label[defined_name['name']] = [sheet,row,col]
645
- end
646
- @labels_read = true
647
- end
648
-
649
- # Checks if the default_sheet exists. If not an RangeError exception is
650
- # raised
651
- def check_default_sheet
652
- sheet_found = false
653
- raise ArgumentError, "Error: default_sheet not set" if @default_sheet == nil
654
- sheet_found = true if sheets.include?(@default_sheet)
655
- if ! sheet_found
656
- raise RangeError, "sheet '#{@default_sheet}' not found"
657
- end
561
+ sheet, coordinates = defined_name.text.split('!$', 2)
562
+ col,row = coordinates.split('$')
563
+ [defined_name['name'], [sheet,row,col]]
564
+ end]
658
565
  end
659
566
 
660
567
  # Extracts all needed files from the zip file
661
- def process_zipfile(zipfilename, zip, path='')
568
+ def process_zipfile(tmpdir, zipfilename, zip, path='')
662
569
  @sheet_files = []
663
570
  Zip::ZipFile.open(zipfilename) {|zf|
664
571
  zf.entries.each {|entry|
665
572
  if entry.to_s.end_with?('workbook.xml')
666
- open(@tmpdir+'/'+@file_nr.to_s+'_roo_workbook.xml','wb') {|f|
573
+ open(tmpdir+'/'+'roo_workbook.xml','wb') {|f|
667
574
  f << zip.read(entry)
668
575
  }
669
576
  end
@@ -673,28 +580,28 @@ Datei xl/comments1.xml
673
580
  # won't be both names in the archive.
674
581
  # Changed the casing of all the following filenames.
675
582
  if entry.to_s.downcase.end_with?('sharedstrings.xml')
676
- open(@tmpdir+'/'+@file_nr.to_s+'_roo_sharedStrings.xml','wb') {|f|
583
+ open(tmpdir+'/'+'roo_sharedStrings.xml','wb') {|f|
677
584
  f << zip.read(entry)
678
585
  }
679
586
  end
680
587
  if entry.to_s.downcase.end_with?('styles.xml')
681
- open(@tmpdir+'/'+@file_nr.to_s+'_roo_styles.xml','wb') {|f|
588
+ open(tmpdir+'/'+'roo_styles.xml','wb') {|f|
682
589
  f << zip.read(entry)
683
590
  }
684
591
  end
685
592
  if entry.to_s.downcase =~ /sheet([0-9]+).xml$/
686
593
  nr = $1
687
- open(@tmpdir+'/'+@file_nr.to_s+"_roo_sheet#{nr}",'wb') {|f|
594
+ open(tmpdir+'/'+"roo_sheet#{nr}",'wb') {|f|
688
595
  f << zip.read(entry)
689
596
  }
690
- @sheet_files[nr.to_i-1] = @tmpdir+'/'+@file_nr.to_s+"_roo_sheet#{nr}"
597
+ @sheet_files[nr.to_i-1] = tmpdir+'/'+"roo_sheet#{nr}"
691
598
  end
692
599
  if entry.to_s.downcase =~ /comments([0-9]+).xml$/
693
600
  nr = $1
694
- open(@tmpdir+'/'+@file_nr.to_s+"_roo_comments#{nr}",'wb') {|f|
601
+ open(tmpdir+'/'+"roo_comments#{nr}",'wb') {|f|
695
602
  f << zip.read(entry)
696
603
  }
697
- @comments_files[nr.to_i-1] = @tmpdir+'/'+@file_nr.to_s+"_roo_comments#{nr}"
604
+ @comments_files[nr.to_i-1] = tmpdir+'/'+"roo_comments#{nr}"
698
605
  end
699
606
  }
700
607
  }
@@ -702,27 +609,15 @@ Datei xl/comments1.xml
702
609
  end
703
610
 
704
611
  # extract files from the zip file
705
- def extract_content(zipfilename)
612
+ def extract_content(tmpdir, zipfilename)
706
613
  Zip::ZipFile.open(@filename) do |zip|
707
- process_zipfile(zipfilename,zip)
614
+ process_zipfile(tmpdir, zipfilename,zip)
708
615
  end
709
616
  end
710
617
 
711
- # sets the value of a cell
712
- def set_value(row,col,value,sheet=nil)
713
- sheet = @default_value unless sheet
714
- @cell[sheet][[row,col]] = value
715
- end
716
-
717
- # sets the type of a cell
718
- def set_type(row,col,type,sheet=nil)
719
- sheet = @default_value unless sheet
720
- @cell_type[sheet][[row,col]] = type
721
- end
722
-
723
618
  # read the shared strings xml document
724
619
  def read_shared_strings(doc)
725
- doc.xpath("//*[local-name()='si']").each do |si|
620
+ doc.xpath("/xmlns:sst/xmlns:si").each do |si|
726
621
  shared_table_entry = ''
727
622
  si.children.each do |elem|
728
623
  if elem.name == 'r' and elem.children
@@ -742,62 +637,31 @@ Datei xl/comments1.xml
742
637
 
743
638
  # read the styles elements of an excelx document
744
639
  def read_styles(doc)
745
- @numFmts = []
746
640
  @cellXfs = []
747
- fonts = []
748
-
749
- doc.xpath("//*[local-name()='numFmt']").each do |numFmt|
750
- numFmtId = numFmt.attributes['numFmtId']
751
- formatCode = numFmt.attributes['formatCode']
752
- @numFmts << [numFmtId, formatCode]
753
- end
754
- doc.xpath("//*[local-name()='fonts']").each do |fonts_el|
755
- fonts_el.children.each do |font_el|
756
- if font_el == 'font'
757
- font = Excelx::Font.new
758
- font_el.each_element do |font_sub_el|
759
- case font_sub_el.name
760
- when 'b'
761
- font.bold = true
762
- when 'i'
763
- font.italic = true
764
- when 'u'
765
- font.underline = true
766
- end
767
- end
768
- fonts << font
769
- end
641
+
642
+ @numFmts = Hash[doc.xpath("//xmlns:numFmt").map do |numFmt|
643
+ [numFmt['numFmtId'], numFmt['formatCode']]
644
+ end]
645
+ fonts = doc.xpath("//xmlns:fonts/xmlns:font").map do |font_el|
646
+ Font.new.tap do |font|
647
+ font.bold = !font_el.xpath('./xmlns:b').empty?
648
+ font.italic = !font_el.xpath('./xmlns:i').empty?
649
+ font.underline = !font_el.xpath('./xmlns:u').empty?
770
650
  end
771
651
  end
772
-
773
- doc.xpath("//*[local-name()='cellXfs']").each do |xfs|
652
+
653
+ doc.xpath("//xmlns:cellXfs").each do |xfs|
774
654
  xfs.children.each do |xf|
775
- numFmtId = xf['numFmtId']
776
- @cellXfs << [numFmtId]
777
- fontId = xf['fontId'].to_i
778
- @style_definitions << fonts[fontId]
655
+ @cellXfs << xf['numFmtId']
656
+ @style_definitions << fonts[xf['fontId'].to_i]
779
657
  end
780
658
  end
781
659
  end
782
660
 
783
661
  # convert internal excelx attribute to a format
784
662
  def attribute2format(s)
785
- result = nil
786
- @numFmts.each {|nf|
787
- # to_s weil das eine Nokogiri::XML::Attr und das
788
- # andere ein String ist
789
- if nf.first.to_s == @cellXfs[s.to_i].first
790
- result = nf[1]
791
- break
792
- end
793
- }
794
- unless result
795
- id = @cellXfs[s.to_i].first.to_i
796
- if STANDARD_FORMATS.has_key? id
797
- result = STANDARD_FORMATS[id]
798
- end
799
- end
800
- result
663
+ id = @cellXfs[s.to_i]
664
+ @numFmts[id] || STANDARD_FORMATS[id.to_i]
801
665
  end
802
666
 
803
667
  end # class