rubyXL 1.1.12 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.12
1
+ 1.2.0
@@ -155,116 +155,136 @@ module RubyXL
155
155
  wb.worksheets[i] = Parser.create_matrix(wb, i, files)
156
156
  j = i+1
157
157
 
158
+ namespaces = files[j].root.namespaces()
158
159
  unless @data_only
159
- hash = Hash.xml_node_to_hash(files[j].root)
160
-
161
- wb.worksheets[i].sheet_view = hash[:sheetViews][:sheetView]
160
+ sheet_views_node= files[j].xpath('/xmlns:worksheet/xmlns:sheetViews[xmlns:sheetView]',namespaces).first
161
+ wb.worksheets[i].sheet_view = Hash.xml_node_to_hash(sheet_views_node)[:sheetView]
162
162
 
163
163
  ##col styles##
164
- col_data = hash[:cols]
165
- unless col_data.nil?
166
- wb.worksheets[i].cols=col_data[:col]
164
+ cols_node_set = files[j].xpath('/xmlns:worksheet/xmlns:cols/xmlns:col',namespaces)
165
+ unless cols_node_set.empty?
166
+ wb.worksheets[i].cols= cols_node_set.map(&:attributes)
167
167
  end
168
168
  ##end col styles##
169
169
 
170
170
  ##merge_cells##
171
- merge_data = hash[:mergeCells]
172
- unless merge_data.nil?
173
- wb.worksheets[i].merged_cells = merge_data[:mergeCell]
171
+ merge_cells_node = files[j].xpath('/xmlns:worksheet/xmlns:mergeCells[xmlns:mergeCell]',namespaces)
172
+ unless merge_cells_node.empty?
173
+ wb.worksheets[i].merged_cells = Hash.xml_node_to_hash(merge_cells_node.first)[:mergeCell]
174
174
  end
175
175
  ##end merge_cells##
176
176
 
177
177
  ##sheet_view pane##
178
- pane_data = hash[:sheetViews][:sheetView][:pane]
178
+ pane_data = wb.worksheets[i].sheet_view[:pane]
179
179
  wb.worksheets[i].pane = pane_data
180
180
  ##end sheet_view pane##
181
181
 
182
182
  ##data_validation##
183
- data_validation = hash[:dataValidations]
184
- unless data_validation.nil?
185
- data_validation = data_validation[:dataValidation]
183
+ data_validations_node = files[j].xpath('/xmlns:worksheet/xmlns:dataValidations[xmlns:dataValidation]',namespaces)
184
+ unless data_validations_node.empty?
185
+ wb.worksheets[i].validations = Hash.xml_node_to_hash(data_validations_node.first)[:dataValidation]
186
+ else
187
+ wb.worksheets[i].validations=nil
186
188
  end
187
- wb.worksheets[i].validations = data_validation
188
189
  ##end data_validation##
189
190
 
190
191
  #extLst
191
- wb.worksheets[i].extLst = hash[:extLst]
192
+ ext_list_node=files[j].xpath('/xmlns:worksheet/xmlns:extLst',namespaces)
193
+ unless ext_list_node.empty?
194
+ wb.worksheets[i].extLst = Hash.xml_node_to_hash(ext_list_node.first)
195
+ else
196
+ wb.worksheets[i].extLst=nil
197
+ end
192
198
  #extLst
193
199
 
194
200
  ##legacy drawing##
195
- drawing = hash[:legacyDrawing]
196
- wb.worksheets[i].legacy_drawing = drawing
201
+ legacy_drawing_node = files[j].xpath('/xmlns:worksheet/xmlns:legacyDrawing',namespaces)
202
+ unless legacy_drawing_node.empty?
203
+ wb.worksheets[i].legacy_drawing = Hash.xml_node_to_hash(legacy_drawing_node.first)
204
+ else
205
+ wb.worksheets[i].legacy_drawing = nil
206
+ end
197
207
  ##end legacy drawing
198
208
  end
199
209
 
200
- row_data = files[j].css('sheetData row')
210
+
211
+ row_data = files[j].xpath('/xmlns:worksheet/xmlns:sheetData/xmlns:row[xmlns:c[xmlns:v]]',namespaces)
212
+ row_data.each do |row|
213
+ unless @data_only
214
+ ##row styles##
215
+ row_style = '0'
216
+ row_attributes = row.attributes
217
+ unless row_attributes['s'].nil?
218
+ row_style = row_attributes['s'].value
219
+ end
201
220
 
202
- if(row_data.to_s != "")
203
- row_data.each do |row|
221
+ wb.worksheets[i].row_styles[row_attributes['r'].content] = { :style => row_style }
204
222
 
205
- unless @data_only
206
- ##row styles##
207
- unless row.css('c').nil?
208
- row_style = '0'
209
- unless row.attribute('s').nil?
210
- row_style = row.attribute('s').value.to_s
211
- end
212
-
213
- wb.worksheets[i].row_styles[row.attribute('r').to_s] = { :style => row_style.to_s }
214
-
215
- unless row.attribute('ht').to_s == ""
216
- wb.worksheets[i].change_row_height(Integer(row.attribute('r').to_s)-1,
217
- Float(row.attribute('ht').to_s))
218
- end
219
- end
220
- ##end row styles##
223
+ unless row_attributes['ht'].content == ""
224
+ wb.worksheets[i].change_row_height(Integer(row_attributes['r'].content)-1,
225
+ Float(row_attributes['ht'].content))
221
226
  end
227
+ ##end row styles##
228
+ end
222
229
 
223
- row = row.css('c')
224
- row.each do |value|
225
- cell_index = Parser.convert_to_index(value.attribute('r').to_s)
226
- style_index = nil
227
-
228
- data_type = value.attribute('t').to_s
229
-
230
- if (value.css('v').to_s == "") || (value.css('v').children.to_s == "") #no data
231
- cell_data = nil
232
- elsif data_type == 's' #shared string
233
- str_index = Integer(value.css('v').children.to_s)
234
- cell_data = shared_strings[str_index].to_s
235
- elsif data_type=='str' #raw string
236
- cell_data = value.css('v').children.to_s
237
- elsif data_type=='e' #error
238
- cell_data = value.css('v').children.to_s
239
- else# (value.css('v').to_s != "") && (value.css('v').children.to_s != "") #is number
240
- data_type = ''
241
- if(value.css('v').children.to_s =~ /\./) #is float
242
- cell_data = Float(value.css('v').children.to_s)
243
- else
244
- cell_data = Integer(value.css('v').children.to_s)
245
- end
246
- end
247
- cell_formula = nil
248
- fmla_css = value.css('f')
249
- if(fmla_css.to_s != "")
250
- cell_formula = fmla_css.children.to_s
251
- cell_formula_attr = {}
252
- cell_formula_attr['t'] = fmla_css.attribute('t').to_s if fmla_css.attribute('t')
253
- cell_formula_attr['ref'] = fmla_css.attribute('ref').to_s if fmla_css.attribute('ref')
254
- cell_formula_attr['si'] = fmla_css.attribute('si').to_s if fmla_css.attribute('si')
255
- end
230
+ c_row = row.search('./xmlns:c[xmlns:v]')
231
+ c_row.each do |value|
232
+ value_attributes= value.attributes
233
+ cell_index = Parser.convert_to_index(value_attributes['r'].content)
234
+ style_index = nil
256
235
 
257
- unless @data_only
258
- style_index = value['s'].to_i #nil goes to 0 (default)
236
+ data_type = value_attributes['t'].content if value_attributes['t']
237
+ element_hash ={}
238
+ value.children.each do |node|
239
+ element_hash["#{node.name()}_element"]=node
240
+ end
241
+ # v is the value element that is part of the cell
242
+ if element_hash["v_element"]
243
+ v_element_content = element_hash["v_element"].content
244
+ else
245
+ v_element_content=""
246
+ end
247
+ if v_element_content =="" #no data
248
+ cell_data = nil
249
+ elsif data_type == 's' #shared string
250
+ str_index = Integer(v_element_content)
251
+ cell_data = shared_strings[str_index].to_s
252
+ elsif data_type=='str' #raw string
253
+ cell_data = v_element_content
254
+ elsif data_type=='e' #error
255
+ cell_data = v_element_content
256
+ else# (value.css('v').to_s != "") && (value.css('v').children.to_s != "") #is number
257
+ data_type = ''
258
+ if(v_element_content =~ /\./) #is float
259
+ cell_data = Float(v_element_content)
259
260
  else
260
- style_index = 0
261
+ cell_data = Integer(v_element_content)
261
262
  end
263
+ end
264
+ cell_formula = nil
265
+ fmla_css = element_hash["f_element"]
266
+ if fmla_css && fmla_css.content
267
+ fmla_css_content= fmla_css.content
268
+ if(fmla_css_content != "")
269
+ cell_formula = fmla_css_content
270
+ cell_formula_attr = {}
271
+ fmla_css_attributes = fmla_css.attributes
272
+ cell_formula_attr['t'] = fmla_css_attributes['t'].content if fmla_css_attributes['t']
273
+ cell_formula_attr['ref'] = fmla_css_attributes['ref'].content if fmla_css_attributes['ref']
274
+ cell_formula_attr['si'] = fmla_css_attributes['si'].content if fmla_css_attributes['si']
275
+ end
276
+ end
262
277
 
263
- wb.worksheets[i].sheet_data[cell_index[0]][cell_index[1]] =
264
- Cell.new(wb.worksheets[i],cell_index[0],cell_index[1],cell_data,cell_formula,
265
- data_type,style_index,cell_formula_attr)
266
- cell = wb.worksheets[i].sheet_data[cell_index[0]][cell_index[1]]
278
+ unless @data_only
279
+ style_index = value['s'].to_i #nil goes to 0 (default)
280
+ else
281
+ style_index = 0
267
282
  end
283
+
284
+ wb.worksheets[i].sheet_data[cell_index[0]][cell_index[1]] =
285
+ Cell.new(wb.worksheets[i],cell_index[0],cell_index[1],cell_data,cell_formula,
286
+ data_type,style_index,cell_formula_attr)
287
+ cell = wb.worksheets[i].sheet_data[cell_index[0]][cell_index[1]]
268
288
  end
269
289
  end
270
290
  end
@@ -288,13 +308,13 @@ module RubyXL
288
308
 
289
309
  files = Hash.new
290
310
 
291
- files['app'] = Nokogiri::XML.parse(File.read(File.join(dir_path,'docProps','app.xml')))
292
- files['core'] = Nokogiri::XML.parse(File.read(File.join(dir_path,'docProps','core.xml')))
311
+ files['app'] = Nokogiri::XML.parse(File.open(File.join(dir_path,'docProps','app.xml'),'r'))
312
+ files['core'] = Nokogiri::XML.parse(File.open(File.join(dir_path,'docProps','core.xml'),'r'))
293
313
 
294
- files['workbook'] = Nokogiri::XML.parse(File.read(File.join(dir_path,'xl','workbook.xml')))
314
+ files['workbook'] = Nokogiri::XML.parse(File.open(File.join(dir_path,'xl','workbook.xml'),'r'))
295
315
 
296
316
  if(File.exist?(File.join(dir_path,'xl','sharedStrings.xml')))
297
- files['sharedString'] = Nokogiri::XML.parse(File.read(File.join(dir_path,'xl','sharedStrings.xml')))
317
+ files['sharedString'] = Nokogiri::XML.parse(File.open(File.join(dir_path,'xl','sharedStrings.xml'),'r'))
298
318
  end
299
319
 
300
320
  unless @data_only
@@ -352,7 +372,7 @@ module RubyXL
352
372
  files['vbaProject'] = File.open(File.join(dir_path,"xl","vbaProject.bin"),'rb').read
353
373
  end
354
374
 
355
- files['styles'] = Nokogiri::XML.parse(File.read(File.join(dir_path,'xl','styles.xml')))
375
+ files['styles'] = Nokogiri::XML.parse(File.open(File.join(dir_path,'xl','styles.xml'),'r'))
356
376
  end
357
377
 
358
378
  @num_sheets = files['workbook'].css('sheets').children.size
@@ -362,7 +382,7 @@ module RubyXL
362
382
  i=1
363
383
  1.upto(@num_sheets) do
364
384
  filename = 'sheet'+i.to_s
365
- files[i] = Nokogiri::XML.parse(File.read(File.join(dir_path,'xl','worksheets',filename+'.xml')))
385
+ files[i] = Nokogiri::XML.parse(File.open(File.join(dir_path,'xl','worksheets',filename+'.xml'),'r'))
366
386
  i=i+1
367
387
  end
368
388
 
@@ -47,7 +47,7 @@ module RubyXL
47
47
  @calc_chain = nil #unnecessary?
48
48
  @num_strings = 0 #num strings total
49
49
  @size = 0 #num strings in shared_strings array
50
- @date1904 = date1904
50
+ @date1904 = date1904 > 0
51
51
  @external_links = nil
52
52
  @style_corrector = nil
53
53
  @drawings = nil
@@ -78,6 +78,9 @@ module RubyXL
78
78
  #filepath of xlsx file (including file itself)
79
79
  def write(filepath=@filepath)
80
80
  validate_before_write
81
+ if !(filepath =~ /(.+)\.xls(x|m)/)
82
+ raise "Only xlsx and xlsm files are supported. Unsupported type for file: #{filepath}"
83
+ end
81
84
  dirpath = ''
82
85
  extension = 'xls'
83
86
  if(filepath =~ /((.|\s)*)\.xls(x|m)$/)
@@ -197,7 +200,7 @@ module RubyXL
197
200
  compare_date = DateTime.parse('December 31, 1899')
198
201
  end
199
202
  # add one day to compare date for erroneous 1900 leap year compatibility
200
- date.ajd - (compare_date.ajd + 1)
203
+ date.ajd + 1 - compare_date.ajd
201
204
  end
202
205
 
203
206
  def num_to_date(num)
@@ -207,8 +210,8 @@ module RubyXL
207
210
  else
208
211
  compare_date = DateTime.parse('December 31, 1899')
209
212
  end
210
- # add one day to compare date for erroneous 1900 leap year compatibility
211
- compare_date + 1 + num
213
+ # subtract one day to compare date for erroneous 1900 leap year compatibility
214
+ compare_date - 1 + num
212
215
  end
213
216
 
214
217
  #gets style object from style array given index
@@ -60,8 +60,11 @@ class Worksheet < PrivateClass
60
60
 
61
61
  # makes array of hashes in table_hash[:table]
62
62
  # as well as hash of arrays in table_hash[header]
63
- while !cell.nil? && !cell.value.nil?
64
- table_hash[header] << cell.value
63
+ table_index = current_row - original_row
64
+ cell_test= (!cell.nil? && !cell.value.nil?)
65
+ while cell_test || !table_hash[:table][table_index].empty?
66
+
67
+ table_hash[header] << (cell_test ? cell.value : nil)
65
68
 
66
69
  table_index = current_row - original_row
67
70
 
@@ -69,7 +72,7 @@ class Worksheet < PrivateClass
69
72
  table_hash[:table][table_index] = {}
70
73
  end
71
74
 
72
- table_hash[:table][table_index][header] = cell.value
75
+ table_hash[:table][table_index][header] = cell.value if cell_test
73
76
 
74
77
  current_row += 1
75
78
  if @sheet_data[current_row].nil?
@@ -77,6 +80,7 @@ class Worksheet < PrivateClass
77
80
  else
78
81
  cell = @sheet_data[current_row][index]
79
82
  end
83
+ cell_test= (!cell.nil? && !cell.value.nil?)
80
84
  end
81
85
  end
82
86
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rubyXL}
8
- s.version = "1.1.12"
8
+ s.version = "1.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Vivek Bhagwat"]
12
- s.date = %q{2011-11-29}
12
+ s.date = %q{2012-01-06}
13
13
  s.description = %q{rubyXL is a gem which allows the parsing, creation, and manipulation of Microsoft Excel (.xlsx/.xlsm) Documents}
14
14
  s.email = %q{bhagwat.vivek@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -196,9 +196,18 @@ describe RubyXL::Cell do
196
196
  it 'should return the value of a date' do
197
197
  date = Date.parse('January 1, 2011')
198
198
  @cell.change_contents(date)
199
- @cell.should_receive(:is_date?).once.and_return(true)
199
+ @cell.should_receive(:is_date?).any_number_of_times.and_return(true)
200
200
  @cell.value.should == date
201
201
  end
202
+
203
+ it 'should convert date numbers correctly' do
204
+ date = 41019
205
+ @cell.change_contents(date)
206
+ @cell.should_receive(:is_date?).any_number_of_times.and_return(true)
207
+ puts @cell.value
208
+ puts Date.parse('April 20, 2012')
209
+ @cell.value.should == Date.parse('April 20, 2012')
210
+ end
202
211
  end
203
212
 
204
213
  describe '.change_contents' do
@@ -211,7 +220,7 @@ describe RubyXL::Cell do
211
220
  it 'should cause cell value to match a date that is passed in' do
212
221
  date = Date.parse('January 1, 2011')
213
222
  @cell.change_contents(date)
214
- @cell.should_receive(:is_date?).once.and_return(true)
223
+ @cell.should_receive(:is_date?).any_number_of_times.and_return(true)
215
224
  @cell.value.should == date
216
225
  @cell.formula.should == nil
217
226
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubyXL
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 1
9
- - 12
10
- version: 1.1.12
8
+ - 2
9
+ - 0
10
+ segments_generated: true
11
+ version: 1.2.0
11
12
  platform: ruby
12
13
  authors:
13
14
  - Vivek Bhagwat
@@ -15,7 +16,7 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2011-11-29 00:00:00 -05:00
19
+ date: 2012-01-06 00:00:00 -05:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
@@ -28,6 +29,7 @@ dependencies:
28
29
  hash: 3
29
30
  segments:
30
31
  - 0
32
+ segments_generated: true
31
33
  version: "0"
32
34
  name: shoulda
33
35
  requirement: *id001
@@ -44,6 +46,7 @@ dependencies:
44
46
  - 1
45
47
  - 0
46
48
  - 0
49
+ segments_generated: true
47
50
  version: 1.0.0
48
51
  name: bundler
49
52
  requirement: *id002
@@ -60,6 +63,7 @@ dependencies:
60
63
  - 1
61
64
  - 6
62
65
  - 0
66
+ segments_generated: true
63
67
  version: 1.6.0
64
68
  name: jeweler
65
69
  requirement: *id003
@@ -74,6 +78,7 @@ dependencies:
74
78
  hash: 3
75
79
  segments:
76
80
  - 0
81
+ segments_generated: true
77
82
  version: "0"
78
83
  name: rcov
79
84
  requirement: *id004
@@ -90,6 +95,7 @@ dependencies:
90
95
  - 1
91
96
  - 4
92
97
  - 4
98
+ segments_generated: true
93
99
  version: 1.4.4
94
100
  name: nokogiri
95
101
  requirement: *id005
@@ -106,6 +112,7 @@ dependencies:
106
112
  - 0
107
113
  - 9
108
114
  - 4
115
+ segments_generated: true
109
116
  version: 0.9.4
110
117
  name: rubyzip
111
118
  requirement: *id006
@@ -122,6 +129,7 @@ dependencies:
122
129
  - 1
123
130
  - 3
124
131
  - 4
132
+ segments_generated: true
125
133
  version: 1.3.4
126
134
  name: rspec
127
135
  requirement: *id007
@@ -187,6 +195,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
187
195
  hash: 3
188
196
  segments:
189
197
  - 0
198
+ segments_generated: true
190
199
  version: "0"
191
200
  required_rubygems_version: !ruby/object:Gem::Requirement
192
201
  none: false
@@ -196,6 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
205
  hash: 3
197
206
  segments:
198
207
  - 0
208
+ segments_generated: true
199
209
  version: "0"
200
210
  requirements: []
201
211