jagthedrummer-roo 1.3.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/History.txt +225 -0
  2. data/README.markdown +55 -0
  3. data/examples/roo_soap_client.rb +53 -0
  4. data/examples/roo_soap_server.rb +29 -0
  5. data/examples/write_me.rb +33 -0
  6. data/lib/roo.rb +29 -0
  7. data/lib/roo/excel.rb +469 -0
  8. data/lib/roo/excelx.rb +604 -0
  9. data/lib/roo/generic_spreadsheet.rb +626 -0
  10. data/lib/roo/google.rb +381 -0
  11. data/lib/roo/openoffice.rb +454 -0
  12. data/lib/roo/roo_rails_helper.rb +82 -0
  13. data/lib/roo/version.rb +9 -0
  14. data/test/1900_base.xls +0 -0
  15. data/test/1904_base.xls +0 -0
  16. data/test/Bibelbund.csv +3741 -0
  17. data/test/Bibelbund.ods +0 -0
  18. data/test/Bibelbund.xls +0 -0
  19. data/test/Bibelbund.xlsx +0 -0
  20. data/test/Bibelbund1.ods +0 -0
  21. data/test/bad_excel_date.xls +0 -0
  22. data/test/bbu.ods +0 -0
  23. data/test/bbu.xls +0 -0
  24. data/test/bbu.xlsx +0 -0
  25. data/test/bode-v1.ods.zip +0 -0
  26. data/test/bode-v1.xls.zip +0 -0
  27. data/test/boolean.ods +0 -0
  28. data/test/boolean.xls +0 -0
  29. data/test/boolean.xlsx +0 -0
  30. data/test/borders.ods +0 -0
  31. data/test/borders.xls +0 -0
  32. data/test/borders.xlsx +0 -0
  33. data/test/bug-row-column-fixnum-float.xls +0 -0
  34. data/test/datetime.ods +0 -0
  35. data/test/datetime.xls +0 -0
  36. data/test/datetime.xlsx +0 -0
  37. data/test/datetime_floatconv.xls +0 -0
  38. data/test/emptysheets.ods +0 -0
  39. data/test/emptysheets.xls +0 -0
  40. data/test/false_encoding.xls +0 -0
  41. data/test/formula.ods +0 -0
  42. data/test/formula.xls +0 -0
  43. data/test/formula.xlsx +0 -0
  44. data/test/formula_parse_error.xls +0 -0
  45. data/test/html-escape.ods +0 -0
  46. data/test/no_spreadsheet_file.txt +1 -0
  47. data/test/numbers1.csv +18 -0
  48. data/test/numbers1.ods +0 -0
  49. data/test/numbers1.xls +0 -0
  50. data/test/numbers1.xlsx +0 -0
  51. data/test/only_one_sheet.ods +0 -0
  52. data/test/only_one_sheet.xls +0 -0
  53. data/test/only_one_sheet.xlsx +0 -0
  54. data/test/paragraph.ods +0 -0
  55. data/test/paragraph.xls +0 -0
  56. data/test/paragraph.xlsx +0 -0
  57. data/test/ric.ods +0 -0
  58. data/test/simple_spreadsheet.ods +0 -0
  59. data/test/simple_spreadsheet.xls +0 -0
  60. data/test/simple_spreadsheet.xlsx +0 -0
  61. data/test/simple_spreadsheet_from_italo.ods +0 -0
  62. data/test/simple_spreadsheet_from_italo.xls +0 -0
  63. data/test/skipped_tests.rb +789 -0
  64. data/test/style.ods +0 -0
  65. data/test/style.xls +0 -0
  66. data/test/style.xlsx +0 -0
  67. data/test/test_helper.rb +19 -0
  68. data/test/test_roo.rb +1822 -0
  69. data/test/time-test.csv +2 -0
  70. data/test/time-test.ods +0 -0
  71. data/test/time-test.xls +0 -0
  72. data/test/time-test.xlsx +0 -0
  73. data/test/whitespace.ods +0 -0
  74. data/test/whitespace.xls +0 -0
  75. data/test/whitespace.xlsx +0 -0
  76. metadata +182 -0
@@ -0,0 +1,604 @@
1
+ require 'xml'
2
+ require 'fileutils'
3
+ require 'zip/zipfilesystem'
4
+ require 'date'
5
+
6
+ class String
7
+ def end_with?(str)
8
+ self[-str.length,str.length] == str
9
+ end
10
+ end
11
+
12
+ module Roo
13
+ class Excelx < GenericSpreadsheet
14
+ FORMATS = {
15
+ 'General' => :float,
16
+ '0' => :float,
17
+ '0.00' => :float,
18
+ '#,##0' => :float,
19
+ '#,##0.00' => :float,
20
+ '0%' => :percentage,
21
+ '0.00%' => :percentage,
22
+ '0.00E+00' => :float,
23
+ '# ?/?' => :float, #??? TODO:
24
+ '# ??/??' => :float, #??? TODO:
25
+ 'mm-dd-yy' => :date,
26
+ 'd-mmm-yy' => :date,
27
+ 'd-mmm' => :date,
28
+ 'mmm-yy' => :date,
29
+ 'h:mm AM/PM' => :date,
30
+ 'h:mm:ss AM/PM' => :date,
31
+ 'h:mm' => :time,
32
+ 'h:mm:ss' => :time,
33
+ 'm/d/yy h:mm' => :date,
34
+ '#,##0 ;(#,##0)' => :float,
35
+ '#,##0 ;[Red](#,##0)' => :float,
36
+ '#,##0.00;(#,##0.00)' => :float,
37
+ '#,##0.00;[Red](#,##0.00)' => :float,
38
+ 'mm:ss' => :time,
39
+ '[h]:mm:ss' => :time,
40
+ 'mmss.0' => :time,
41
+ '##0.0E+0' => :float,
42
+ '@' => :float,
43
+ #-- zusaetzliche Formate, die nicht standardmaessig definiert sind:
44
+ "yyyy\\-mm\\-dd" => :date,
45
+ 'dd/mm/yy' => :date,
46
+ 'hh:mm:ss' => :time,
47
+ "dd/mm/yy\\ hh:mm" => :datetime,
48
+ }
49
+ STANDARD_FORMATS = {
50
+ 0 => 'General',
51
+ 1 => '0',
52
+ 2 => '0.00',
53
+ 3 => '#,##0',
54
+ 4 => '#,##0.00',
55
+ 9 => '0%',
56
+ 10 => '0.00%',
57
+ 11 => '0.00E+00',
58
+ 12 => '# ?/?',
59
+ 13 => '# ??/??',
60
+ 14 => 'mm-dd-yy',
61
+ 15 => 'd-mmm-yy',
62
+ 16 => 'd-mmm',
63
+ 17 => 'mmm-yy',
64
+ 18 => 'h:mm AM/PM',
65
+ 19 => 'h:mm:ss AM/PM',
66
+ 20 => 'h:mm',
67
+ 21 => 'h:mm:ss',
68
+ 22 => 'm/d/yy h:mm',
69
+ 37 => '#,##0 ;(#,##0)',
70
+ 38 => '#,##0 ;[Red](#,##0)',
71
+ 39 => '#,##0.00;(#,##0.00)',
72
+ 40 => '#,##0.00;[Red](#,##0.00)',
73
+ 45 => 'mm:ss',
74
+ 46 => '[h]:mm:ss',
75
+ 47 => 'mmss.0',
76
+ 48 => '##0.0E+0',
77
+ 49 => '@',
78
+ }
79
+ @@nr = 0
80
+
81
+ # initialization and opening of a spreadsheet file
82
+ # values for packed: :zip
83
+ def initialize(filename, packed=nil, file_warning = :error) #, create = false)
84
+ super()
85
+ @file_warning = file_warning
86
+ @tmpdir = "oo_"+$$.to_s
87
+ @tmpdir = File.join(ENV['ROO_TMP'], @tmpdir) if ENV['ROO_TMP']
88
+ unless File.exists?(@tmpdir)
89
+ FileUtils::mkdir(@tmpdir)
90
+ end
91
+ filename = open_from_uri(filename) if filename[0,7] == "http://"
92
+ filename = unzip(filename) if packed and packed == :zip
93
+ begin
94
+ file_type_check(filename,'.xlsx','an Excel-xlsx')
95
+ @cells_read = Hash.new
96
+ @filename = filename
97
+ unless File.file?(@filename)
98
+ raise IOError, "file #{@filename} does not exist"
99
+ end
100
+ @@nr += 1
101
+ @file_nr = @@nr
102
+ extract_content(@filename)
103
+ file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
104
+ @workbook_doc = XML::Parser.io(file).parse
105
+ file.close
106
+ @shared_table = []
107
+ if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
108
+ file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
109
+ @sharedstring_doc = XML::Parser.io(file).parse
110
+ file.close
111
+ read_shared_strings(@sharedstring_doc)
112
+ end
113
+ @styles_table = []
114
+ @style_definitions = Array.new { |h,k| h[k] = {} }
115
+ if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
116
+ file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
117
+ @styles_doc = XML::Parser.io(file).parse
118
+ file.close
119
+ read_styles(@styles_doc)
120
+ end
121
+ @sheet_doc = []
122
+ @sheet_files.each_with_index do |item, i|
123
+ file = File.new(item)
124
+ @sheet_doc[i] = XML::Parser.io(file).parse
125
+ file.close
126
+ end
127
+ ensure
128
+ #if ENV["roo_local"] != "thomas-p"
129
+ FileUtils::rm_r(@tmpdir)
130
+ #end
131
+ end
132
+ @default_sheet = self.sheets.first
133
+ @cell = Hash.new
134
+ @cell_type = Hash.new
135
+ @formula = Hash.new
136
+ @first_row = Hash.new
137
+ @last_row = Hash.new
138
+ @first_column = Hash.new
139
+ @last_column = Hash.new
140
+ @header_line = 1
141
+ @excelx_type = Hash.new
142
+ @excelx_value = Hash.new
143
+ @s_attribute = Hash.new # TODO: ggf. wieder entfernen nur lokal benoetigt
144
+ end
145
+
146
+ # Returns the content of a spreadsheet-cell.
147
+ # (1,1) is the upper left corner.
148
+ # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
149
+ # cell at the first line and first row.
150
+ def cell(row, col, sheet=nil)
151
+ sheet = @default_sheet unless sheet
152
+ read_cells(sheet) unless @cells_read[sheet]
153
+ row,col = normalize(row,col)
154
+ if celltype(row,col,sheet) == :date
155
+ yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
156
+ return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
157
+ elsif celltype(row,col,sheet) == :datetime
158
+ date_part,time_part = @cell[sheet][[row,col]].split(' ')
159
+ yyyy,mm,dd = date_part.split('-')
160
+ hh,mi,ss = time_part.split(':')
161
+ return DateTime.civil(yyyy.to_i,mm.to_i,dd.to_i,hh.to_i,mi.to_i,ss.to_i)
162
+ end
163
+ @cell[sheet][[row,col]]
164
+ end
165
+
166
+ # Returns the formula at (row,col).
167
+ # Returns nil if there is no formula.
168
+ # The method #formula? checks if there is a formula.
169
+ def formula(row,col,sheet=nil)
170
+ sheet = @default_sheet unless sheet
171
+ read_cells(sheet) unless @cells_read[sheet]
172
+ row,col = normalize(row,col)
173
+ if @formula[sheet][[row,col]] == nil
174
+ return nil
175
+ else
176
+ return @formula[sheet][[row,col]]
177
+ end
178
+ end
179
+
180
+ # true, if there is a formula
181
+ def formula?(row,col,sheet=nil)
182
+ sheet = @default_sheet unless sheet
183
+ read_cells(sheet) unless @cells_read[sheet]
184
+ row,col = normalize(row,col)
185
+ formula(row,col) != nil
186
+ end
187
+
188
+ class Font
189
+ attr_accessor :bold, :italic, :underline
190
+
191
+ def bold?
192
+ @bold == true
193
+ end
194
+
195
+ def italic?
196
+ @italic == true
197
+ end
198
+
199
+ def underline?
200
+ @underline == true
201
+ end
202
+ end
203
+
204
+ # Given a cell, return the cell's style
205
+ def font(row, col, sheet=nil)
206
+ sheet = @default_sheet unless sheet
207
+ read_cells(sheet) unless @cells_read[sheet]
208
+ row,col = normalize(row,col)
209
+ s_attribute = @s_attribute[sheet][[row,col]]
210
+ s_attribute ||= 0
211
+ s_attribute = s_attribute.to_i
212
+ @style_definitions[s_attribute]
213
+ end
214
+
215
+ # set a cell to a certain value
216
+ # (this will not be saved back to the spreadsheet file!)
217
+ def set(row,col,value,sheet=nil) #:nodoc:
218
+ sheet = @default_sheet unless sheet
219
+ read_cells(sheet) unless @cells_read[sheet]
220
+ row,col = normalize(row,col)
221
+ set_value(row,col,value,sheet)
222
+ if value.class == Fixnum
223
+ set_type(row,col,:float,sheet)
224
+ elsif value.class == String
225
+ set_type(row,col,:string,sheet)
226
+ elsif value.class == Float
227
+ set_type(row,col,:string,sheet)
228
+ else
229
+ raise ArgumentError, "Type for "+value.to_s+" not set"
230
+ end
231
+ end
232
+
233
+ # returns the type of a cell:
234
+ # * :float
235
+ # * :string,
236
+ # * :date
237
+ # * :percentage
238
+ # * :formula
239
+ # * :time
240
+ # * :datetime
241
+ def celltype(row,col,sheet=nil)
242
+ sheet = @default_sheet unless sheet
243
+ read_cells(sheet) unless @cells_read[sheet]
244
+ row,col = normalize(row,col)
245
+ if @formula[sheet][[row,col]]
246
+ return :formula
247
+ else
248
+ @cell_type[sheet][[row,col]]
249
+ end
250
+ end
251
+
252
+ # returns the internal type of an excel cell
253
+ # * :numeric_or_formula
254
+ # * :string
255
+ # Note: this is only available within the Excelx class
256
+ def excelx_type(row,col,sheet=nil)
257
+ sheet = @default_sheet unless sheet
258
+ read_cells(sheet) unless @cells_read[sheet]
259
+ row,col = normalize(row,col)
260
+ return @excelx_type[sheet][[row,col]]
261
+ end
262
+
263
+ # returns the internal value of an excelx cell
264
+ # Note: this is only available within the Excelx class
265
+ def excelx_value(row,col,sheet=nil)
266
+ sheet = @default_sheet unless sheet
267
+ read_cells(sheet) unless @cells_read[sheet]
268
+ row,col = normalize(row,col)
269
+ return @excelx_value[sheet][[row,col]]
270
+ end
271
+
272
+ # returns the internal format of an excel cell
273
+ def excelx_format(row,col,sheet=nil)
274
+ sheet = @default_sheet unless sheet
275
+ read_cells(sheet) unless @cells_read[sheet]
276
+ row,col = normalize(row,col)
277
+ s = @s_attribute[sheet][[row,col]]
278
+ result = attribute2format(s)
279
+ result
280
+ end
281
+
282
+ # returns an array of sheet names in the spreadsheet
283
+ def sheets
284
+ return_sheets = []
285
+ @workbook_doc.find("//*[local-name()='sheet']").each do |sheet|
286
+ return_sheets << sheet.attributes.to_h['name']
287
+ end
288
+ return_sheets
289
+ end
290
+ # shows the internal representation of all cells
291
+ # for debugging purposes
292
+ def to_s(sheet=nil)
293
+ sheet = @default_sheet unless sheet
294
+ read_cells(sheet) unless @cells_read[sheet]
295
+ @cell[sheet].inspect
296
+ end
297
+
298
+ # returns each formula in the selected sheet as an array of elements
299
+ # [row, col, formula]
300
+ def formulas(sheet=nil)
301
+ theformulas = Array.new
302
+ sheet = @default_sheet unless sheet
303
+ read_cells(sheet) unless @cells_read[sheet]
304
+ first_row(sheet).upto(last_row(sheet)) {|row|
305
+ first_column(sheet).upto(last_column(sheet)) {|col|
306
+ if formula?(row,col,sheet)
307
+ f = [row, col, formula(row,col,sheet)]
308
+ theformulas << f
309
+ end
310
+ }
311
+ }
312
+ theformulas
313
+ end
314
+
315
+ private
316
+
317
+ # helper function to set the internal representation of cells
318
+ def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v,
319
+ excelx_type=nil,
320
+ excelx_value=nil,
321
+ s_attribute=nil)
322
+ key = [y,x+i]
323
+ @cell_type[sheet] = {} unless @cell_type[sheet]
324
+ @cell_type[sheet][key] = vt
325
+ @formula[sheet] = {} unless @formula[sheet]
326
+ @formula[sheet][key] = formula if formula
327
+ @cell[sheet] = {} unless @cell[sheet]
328
+ case @cell_type[sheet][key]
329
+ when :float
330
+ @cell[sheet][key] = v.to_f
331
+ when :string
332
+ @cell[sheet][key] = str_v
333
+ when :date
334
+ @cell[sheet][key] = (Date.new(1899,12,30)+v.to_i).strftime("%Y-%m-%d")
335
+ when :datetime
336
+ @cell[sheet][key] = (DateTime.new(1899,12,30)+v.to_f).strftime("%Y-%m-%d %H:%M:%S")
337
+ when :percentage
338
+ @cell[sheet][key] = v.to_f
339
+ when :time
340
+ @cell[sheet][key] = v.to_f*(24*60*60)
341
+ else
342
+ @cell[sheet][key] = v
343
+ end
344
+ @excelx_type[sheet] = {} unless @excelx_type[sheet]
345
+ @excelx_type[sheet][key] = excelx_type
346
+ @excelx_value[sheet] = {} unless @excelx_value[sheet]
347
+ @excelx_value[sheet][key] = excelx_value
348
+ @s_attribute[sheet] = {} unless @s_attribute[sheet]
349
+ @s_attribute[sheet][key] = s_attribute
350
+ end
351
+
352
+ # splits a coordinate like "AA12" into the parts "AA" (String) and 12 (Fixnum)
353
+ def split_coord(s)
354
+ letter = ""
355
+ number = 0
356
+ i = 0
357
+ while i<s.length and "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".include?(s[i,1])
358
+ letter += s[i,1]
359
+ i+=1
360
+ end
361
+ while i<s.length and "0123456789".include?(s[i,1])
362
+ number = number*10 + s[i,1].to_i
363
+ i+=1
364
+ end
365
+ if letter=="" or number==0
366
+ raise ArgumentError
367
+ end
368
+ return letter,number
369
+ end
370
+
371
+ def split_coordinate(str)
372
+ letter,number = split_coord(str)
373
+ x = GenericSpreadsheet.letter_to_number(letter)
374
+ y = number
375
+ return x,y
376
+ end
377
+
378
+ # read all cells in the selected sheet
379
+ def format2type(format)
380
+ if FORMATS.has_key? format
381
+ FORMATS[format]
382
+ else
383
+ :float
384
+ end
385
+ end
386
+
387
+ # read all cells in the selected sheet
388
+ def read_cells(sheet=nil)
389
+ sheet = @default_sheet unless sheet
390
+ sheet_found = false
391
+ raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
392
+ raise RangeError unless self.sheets.include? sheet
393
+ n = self.sheets.index(sheet)
394
+ @sheet_doc[n].find("//*[local-name()='c']").each do |c|
395
+ s_attribute = c.attributes.to_h['s'].to_i # should be here
396
+ if (c.attributes.to_h['t'] == 's')
397
+ tmp_type = :shared
398
+ elsif (c.attributes.to_h['t'] == 'b')
399
+ tmp_type = :boolean
400
+ else
401
+ # s_attribute = c.attributes.to_h['s'].to_i # was here
402
+ format = attribute2format(s_attribute)
403
+ tmp_type = format2type(format)
404
+ end
405
+ formula = nil
406
+ c.each_element do |cell|
407
+ if cell.name == 'f'
408
+ formula = cell.content
409
+ end
410
+ if cell.name == 'v'
411
+ if tmp_type == :time or tmp_type == :datetime
412
+ if cell.content.to_f >= 1.0
413
+ if (cell.content.to_f - cell.content.to_f.floor).abs > 0.000001
414
+ tmp_type = :datetime
415
+ else
416
+ tmp_type = :date
417
+ end
418
+ else
419
+ end
420
+ end
421
+ excelx_type = [:numeric_or_formula,format]
422
+ excelx_value = cell.content
423
+ if tmp_type == :shared
424
+ vt = :string
425
+ str_v = @shared_table[cell.content.to_i]
426
+ excelx_type = :string
427
+ elsif tmp_type == :boolean
428
+ vt = :boolean
429
+ cell.content.to_i == 1 ? v = 'TRUE' : v = 'FALSE'
430
+ elsif tmp_type == :date
431
+ vt = :date
432
+ v = cell.content
433
+ elsif tmp_type == :time
434
+ vt = :time
435
+ v = cell.content
436
+ elsif tmp_type == :datetime
437
+ vt = :datetime
438
+ v = cell.content
439
+ elsif tmp_type == :formula
440
+ vt = :formula
441
+ v = cell.content.to_f #TODO: !!!!
442
+ else
443
+ vt = :float
444
+ v = cell.content
445
+ end
446
+ #puts "vt: #{vt}" if cell.text.include? "22606.5120"
447
+ x,y = split_coordinate(c.attributes.to_h['r'])
448
+ tr=nil #TODO: ???s
449
+ set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
450
+ end
451
+ end
452
+ end
453
+ sheet_found = true #TODO:
454
+ if !sheet_found
455
+ raise RangeError
456
+ end
457
+ @cells_read[sheet] = true
458
+ end
459
+
460
+ # Checks if the default_sheet exists. If not an RangeError exception is
461
+ # raised
462
+ def check_default_sheet
463
+ sheet_found = false
464
+ raise ArgumentError, "Error: default_sheet not set" if @default_sheet == nil
465
+
466
+ sheet_found = true if sheets.include?(@default_sheet)
467
+
468
+ if ! sheet_found
469
+ raise RangeError, "sheet '#{@default_sheet}' not found"
470
+ end
471
+ end
472
+
473
+ # extracts all needed files from the zip file
474
+ def process_zipfile(zipfilename, zip, path='')
475
+ @sheet_files = []
476
+ Zip::ZipFile.open(zipfilename) {|zf|
477
+ zf.entries.each {|entry|
478
+ #entry.extract
479
+ if entry.to_s.end_with?('workbook.xml')
480
+ open(@tmpdir+'/'+@file_nr.to_s+'_roo_workbook.xml','wb') {|f|
481
+ f << zip.read(entry)
482
+ }
483
+ end
484
+ if entry.to_s.end_with?('sharedStrings.xml')
485
+ open(@tmpdir+'/'+@file_nr.to_s+'_roo_sharedStrings.xml','wb') {|f|
486
+ f << zip.read(entry)
487
+ }
488
+ end
489
+ if entry.to_s.end_with?('styles.xml')
490
+ open(@tmpdir+'/'+@file_nr.to_s+'_roo_styles.xml','wb') {|f|
491
+ f << zip.read(entry)
492
+ }
493
+ end
494
+ if entry.to_s =~ /sheet([0-9]+).xml$/
495
+ nr = $1
496
+ open(@tmpdir+'/'+@file_nr.to_s+"_roo_sheet#{nr}",'wb') {|f|
497
+ f << zip.read(entry)
498
+ }
499
+ @sheet_files[nr.to_i-1] = @tmpdir+'/'+@file_nr.to_s+"_roo_sheet#{nr}"
500
+ end
501
+ }
502
+ }
503
+ return
504
+ end
505
+
506
+ # extract files from the zip file
507
+ def extract_content(zipfilename)
508
+ Zip::ZipFile.open(@filename) do |zip|
509
+ process_zipfile(zipfilename,zip)
510
+ end
511
+ end
512
+
513
+ # sets the value of a cell
514
+ def set_value(row,col,value,sheet=nil)
515
+ sheet = @default_value unless sheet
516
+ @cell[sheet][[row,col]] = value
517
+ end
518
+
519
+ # sets the type of a cell
520
+ def set_type(row,col,type,sheet=nil)
521
+ sheet = @default_value unless sheet
522
+ @cell_type[sheet][[row,col]] = type
523
+ end
524
+
525
+ # read the shared strings xml document
526
+ def read_shared_strings(doc)
527
+ doc.find("//*[local-name()='si']").each do |si|
528
+ shared_table_entry = ''
529
+ si.each_element do |elem|
530
+ if (elem.name == 'r')
531
+ elem.each_element do |r_elem|
532
+ if (r_elem.name == 't')
533
+ shared_table_entry << r_elem.content
534
+ end
535
+ end
536
+ end
537
+ if (elem.name == 't')
538
+ shared_table_entry = elem.content
539
+ end
540
+ end
541
+ @shared_table << shared_table_entry
542
+ end
543
+ end
544
+
545
+ # read the styles elements of an excelx document
546
+ def read_styles(doc)
547
+ @numFmts = []
548
+ @cellXfs = []
549
+ fonts = []
550
+
551
+ doc.find("//*[local-name()='numFmt']").each do |numFmt|
552
+ numFmtId = numFmt.attributes.to_h['numFmtId']
553
+ formatCode = numFmt.attributes.to_h['formatCode']
554
+ @numFmts << [numFmtId, formatCode]
555
+ end
556
+ doc.find("//*[local-name()='fonts']").each do |fonts_el|
557
+ fonts_el.each_element do |font_el|
558
+ if font_el.name == 'font'
559
+ font = Excelx::Font.new
560
+ font_el.each_element do |font_sub_el|
561
+ case font_sub_el.name
562
+ when 'b'
563
+ font.bold = true
564
+ when 'i'
565
+ font.italic = true
566
+ when 'u'
567
+ font.underline = true
568
+ end
569
+ end
570
+ fonts << font
571
+ end
572
+ end
573
+ end
574
+
575
+ doc.find("//*[local-name()='cellXfs']").each do |xfs|
576
+ xfs.each do |xf|
577
+ numFmtId = xf.attributes.to_h['numFmtId']
578
+ @cellXfs << [numFmtId]
579
+ fontId = xf.attributes.to_h['fontId'].to_i
580
+ @style_definitions << fonts[fontId]
581
+ end
582
+ end
583
+ end
584
+
585
+ # convert internal excelx attribute to a format
586
+ def attribute2format(s)
587
+ result = nil
588
+ @numFmts.each {|nf|
589
+ if nf.first == @cellXfs[s.to_i].first
590
+ result = nf[1]
591
+ break
592
+ end
593
+ }
594
+ unless result
595
+ id = @cellXfs[s.to_i].first.to_i
596
+ if STANDARD_FORMATS.has_key? id
597
+ result = STANDARD_FORMATS[id]
598
+ end
599
+ end
600
+ result
601
+ end
602
+
603
+ end # class
604
+ end # module Roo