spreadsheet 1.1.3 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,7 +20,7 @@ class Worksheet
20
20
  def initialize workbook, worksheet
21
21
  @workbook = workbook
22
22
  @worksheet = worksheet
23
- @io = StringIO.new ''
23
+ @io = StringIO.new ''.dup
24
24
  @biff_version = 0x0600
25
25
  @bof = 0x0809
26
26
  @build_id = 3515
@@ -243,84 +243,6 @@ class Worksheet
243
243
  end
244
244
  write_multiples row, first_idx, multiples if multiples
245
245
  end
246
- def write_changes reader, endpos, sst_status
247
-
248
- ## FIXME this is not smart solution to update outline_level.
249
- # without this process, outlines in row disappear in MS Excel.
250
- @worksheet.row_count.times do |i|
251
- if @worksheet.row(i).outline_level > 0
252
- @worksheet.row(i).outline_level = @worksheet.row(i).outline_level
253
- end
254
- end
255
-
256
- reader.seek @worksheet.offset
257
- blocks = row_blocks
258
- lastpos = reader.pos
259
- offsets = {}
260
- row_offsets = []
261
- changes = @worksheet.changes
262
- @worksheet.offsets.each do |key, pair|
263
- if changes.include?(key) \
264
- || (sst_status == :complete_update && key.is_a?(Integer))
265
- offsets.store pair, key
266
- end
267
- end
268
- ## FIXME it may be smarter to simply write all rowblocks, instead of doing a
269
- # song-and-dance routine for every row...
270
- work = offsets.invert
271
- work.each do |key, (pos, len)|
272
- case key
273
- when Integer
274
- row_offsets.push [key, [pos, len]]
275
- when :dimensions
276
- row_offsets.push [-1, [pos, len]]
277
- end
278
- end
279
- row_offsets.sort!
280
- row_offsets.reverse!
281
- control = changes.size
282
- @worksheet.each do |row|
283
- key = row.idx
284
- if changes.include?(key) && !work.include?(key)
285
- row, pair = row_offsets.find do |idx, _| idx <= key end
286
- work.store key, pair
287
- end
288
- end
289
- if changes.size > control
290
- warn <<-EOS
291
- Your Worksheet was modified while it was being written. This should not happen.
292
- Please contact the author (hannes dot wyss at gmail dot com) with a sample file
293
- and minimal code that generates this warning. Thanks!
294
- EOS
295
- end
296
- work = work.sort_by do |key, (pos, _)|
297
- [pos, key.is_a?(Integer) ? key : -1]
298
- end
299
- work.each do |key, (pos, len)|
300
- @io.write reader.read(pos - lastpos) if pos > lastpos
301
- if key.is_a?(Integer)
302
- if block = blocks.find do |rows| rows.any? do |row| row.idx == key end end
303
- write_rowblock block
304
- blocks.delete block
305
- end
306
- else
307
- send "write_#{key}"
308
- end
309
- lastpos = pos + len
310
- reader.seek lastpos
311
- end
312
-
313
- # Necessary for outline (grouping) and hiding functions
314
- # but these below are not necessary to run
315
- # if [Row|Column]#hidden? = false and [Row|Column]#outline_level == 0
316
- write_merged_cells
317
- write_pagesetup
318
- write_margins
319
- write_colinfos
320
- write_guts
321
-
322
- @io.write reader.read(endpos - lastpos)
323
- end
324
246
  def write_colinfo bunch
325
247
  col = bunch.first
326
248
  width = col.width.to_f * 256
@@ -642,7 +564,7 @@ and minimal code that generates this warning. Thanks!
642
564
  ##
643
565
  # Write multiple consecutive cells with RK values (see #write_rk)
644
566
  def write_mulrk row, idx, multiples
645
- fmt = 'v2'
567
+ fmt = ['v2']
646
568
  data = [
647
569
  row.idx, # Index to row
648
570
  idx, # Index to first column (fc)
@@ -655,7 +577,7 @@ and minimal code that generates this warning. Thanks!
655
577
  end
656
578
  # Index to last column (lc)
657
579
  data.push idx + multiples.size - 1
658
- write_op opcode(:mulrk), data.pack(fmt << 'v')
580
+ write_op opcode(:mulrk), data.pack((fmt << 'v').join)
659
581
  end
660
582
  def write_multiples row, idx, multiples
661
583
  case multiples.last
@@ -1,11 +1,5 @@
1
1
  require 'spreadsheet'
2
2
 
3
- warn <<-EOS
4
- [DEPRECATED] By requiring 'spreadsheet/excel' you are loading a Compatibility
5
- layer which provides a drop-in replacement for Spreadsheet::Excel
6
- versions <= 0.3.5.1. This code will be removed in Spreadsheet
7
- version 1.0.0
8
- EOS
9
3
  ##
10
4
  # Spreadsheet::Excel Compatibility Layer.
11
5
  # Drop-in replacement for Spreadsheet::Excel version <= 0.3.5.1
@@ -101,12 +101,12 @@ module Spreadsheet
101
101
  @pattern_fg_color = :border
102
102
  @pattern_bg_color = :pattern_bg
103
103
  @regexes = {
104
- :date => Regexp.new(client("[YMD]", 'UTF-8')),
104
+ :date => Regexp.new(client("[YMD]|d{2}|m{3}|y{2}", 'UTF-8')),
105
105
  :date_or_time => Regexp.new(client("[hmsYMD]", 'UTF-8')),
106
106
  :datetime => Regexp.new(client("([YMD].*[HS])|([HS].*[YMD])", 'UTF-8')),
107
107
  :time => Regexp.new(client("[hms]", 'UTF-8')),
108
108
  :number => Regexp.new(client("([\#]|0+)", 'UTF-8')),
109
- :locale => Regexp.new(client(/\A\[\$\-\d+\]/.to_s, 'UTF-8')),
109
+ :locale => Regexp.new(client(/\A\[\$\-\S+\]/.to_s, 'UTF-8')),
110
110
  }
111
111
 
112
112
  # Temp code to prevent merged formats in non-merged cells.
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spreadsheet
4
+ ##
5
+ # The version of Spreadsheet you are using.
6
+ VERSION = '1.3.1'
7
+ end
@@ -76,7 +76,7 @@ module Spreadsheet
76
76
  # Returns the count of total worksheets present.
77
77
  # Takes no arguments. Just returns the length of @worksheets array.
78
78
  def sheet_count
79
- @worksheets.length
79
+ @worksheets.length
80
80
  end
81
81
  ##
82
82
  # The Font at _idx_
@@ -49,7 +49,7 @@ module Spreadsheet
49
49
  :right => 0.75,
50
50
  :bottom => 1
51
51
  }
52
- @name = opts[:name] || 'Worksheet'
52
+ @name = sanitize_invalid_characters(opts[:name] || 'Worksheet')
53
53
  @workbook = opts[:workbook]
54
54
  @rows = []
55
55
  @columns = []
@@ -153,9 +153,13 @@ module Spreadsheet
153
153
  # If the argument skip is given, #each iterates from that row until but
154
154
  # omitting the first unused Row, effectively skipping the first _skip_ Rows
155
155
  # from the top of the Worksheet.
156
- def each skip=dimensions[0]
157
- skip.upto(dimensions[1] - 1) do |idx|
158
- yield row(idx)
156
+ def each(skip=dimensions[0], &block)
157
+ rows = skip.upto(dimensions[1] - 1).map { |index| row(index) }.to_enum
158
+
159
+ if block_given?
160
+ rows.each(&block)
161
+ else
162
+ rows
159
163
  end
160
164
  end
161
165
  def encoding # :nodoc:
@@ -228,6 +232,9 @@ module Spreadsheet
228
232
  updated_from idx
229
233
  res
230
234
  end
235
+ def << cells=[]
236
+ insert_row @rows.size, cells
237
+ end
231
238
  def inspect
232
239
  names = instance_variables
233
240
  names.delete '@rows'
@@ -314,7 +321,7 @@ module Spreadsheet
314
321
 
315
322
  def compact!
316
323
  recalculate_dimensions
317
-
324
+
318
325
  # detect first non-nil non-empty row if given first row is empty or nil
319
326
  if row(@dimensions[0]).empty? || row(@dimensions[0]).compact.join('').empty?
320
327
  (@dimensions[0]...@dimensions[1]).each do |i|
@@ -325,19 +332,19 @@ module Spreadsheet
325
332
 
326
333
  # detect last non-nil non-empty row if given last row is empty or nil
327
334
  if row(@dimensions[1] - 1).empty? || row(@dimensions[1] - 1).compact.join('').empty?
328
- i = @dimensions[1] - 1
335
+ row_size = @dimensions[1] - 1
329
336
  @dimensions[1] = @dimensions[0]
330
337
  # divide and conquer
331
- while(i - @dimensions[1] > 1) do
332
- if row(i).empty? || row(i).compact.join('').empty?
333
- i = @dimensions[1] + (((i - @dimensions[1]) + 1) / 2).to_i
338
+ while(row_size - @dimensions[1] > 1) do
339
+ if row(row_size).empty? || row(row_size).compact.join('').empty?
340
+ row_size = @dimensions[1] + (((row_size - @dimensions[1]) + 1) / 2).to_i
334
341
  else
335
- _i = ((i - @dimensions[1]) / 2).to_i + 1
336
- @dimensions[1] = i
337
- i = i + _i
342
+ _i = ((row_size - @dimensions[1]) / 2).to_i + 1
343
+ @dimensions[1] = row_size
344
+ row_size = row_size + _i
338
345
  end
339
346
  end
340
- @dimensions[1] = i + 1
347
+ @dimensions[1] = row_size + 1
341
348
  end
342
349
 
343
350
  # detect first non-empty non-nil column if first column is empty or nil
@@ -359,6 +366,9 @@ module Spreadsheet
359
366
  end
360
367
 
361
368
  private
369
+ def sanitize_invalid_characters(name) # :nodoc:
370
+ name.gsub(Regexp.new('[\\\/\*\?\:\[\]]'.encode(Spreadsheet.client_encoding)), '_')
371
+ end
362
372
  def index_of_first ary # :nodoc:
363
373
  return unless ary
364
374
  ary.index(ary.find do |elm| elm end)
data/lib/spreadsheet.rb CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  ### Spreadsheet - A Library for reading and writing Spreadsheet Documents.
2
3
  #
3
4
  # Copyright (C) 2008-2010 ywesee GmbH
@@ -24,6 +25,7 @@
24
25
  # 8006 Zürich
25
26
  ### Switzerland
26
27
 
28
+ require 'spreadsheet/version'
27
29
  require 'spreadsheet/errors'
28
30
 
29
31
  require 'spreadsheet/excel/workbook'
@@ -43,10 +45,6 @@ require 'spreadsheet/excel/rgb'
43
45
  # sheet.each do |row| puts row[0] end
44
46
  module Spreadsheet
45
47
 
46
- ##
47
- # The version of Spreadsheet you are using.
48
- VERSION = '1.1.3'
49
-
50
48
  ##
51
49
  # Default client Encoding. Change this value if your application uses a
52
50
  # different Encoding:
Binary file
Binary file
data/test/excel/reader.rb CHANGED
@@ -25,6 +25,19 @@ module Spreadsheet
25
25
  reader.setup not_empty_io
26
26
  end
27
27
  end
28
+
29
+ def test_not_frozen_stream_error_on_setup
30
+ return if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3.0')
31
+
32
+ reader = Spreadsheet::Excel::Reader.new
33
+ data = File.expand_path File.join('test', 'data')
34
+ path = File.join data, 'test_empty.xls'
35
+ content_string = File.read path
36
+ frozen_io = StringIO.new(content_string.freeze)
37
+ assert_nothing_thrown do
38
+ reader.setup(frozen_io)
39
+ end
40
+ end
28
41
  end
29
42
  end
30
43
  end
data/test/format.rb CHANGED
@@ -25,6 +25,8 @@ module Spreadsheet
25
25
  assert_equal false, @format.date?
26
26
  @format.number_format = "0.00;[RED]\\-0.00"
27
27
  assert_equal false, @format.date?
28
+ @format.number_format = "[$-C0A]dd\\-mmm\\-yy"
29
+ assert_equal true, @format.date?
28
30
  end
29
31
  def test_date_or_time?
30
32
  assert_equal false, @format.date_or_time?
data/test/integration.rb CHANGED
@@ -36,7 +36,7 @@ module Spreadsheet
36
36
  end
37
37
  def teardown
38
38
  Spreadsheet.client_encoding = 'UTF-8'
39
- FileUtils.rm_r @var
39
+ FileUtils.rm_rf @var
40
40
  end
41
41
  def test_copy__identical__file_paths
42
42
  path = File.join @data, 'test_copy.xls'
@@ -70,7 +70,7 @@ module Spreadsheet
70
70
  def test_missing_format
71
71
  path = File.join @data, 'test_missing_format.xls'
72
72
  assert_nothing_thrown do
73
- workbook = Spreadsheet.open(path, "rb")
73
+ Spreadsheet.open(path, "rb")
74
74
  end
75
75
  end
76
76
  def test_version_excel97__excel2010__utf16
@@ -506,7 +506,7 @@ module Spreadsheet
506
506
  assert_equal 3, sheets.size
507
507
  sheet = book.worksheet 0
508
508
  assert_instance_of Excel::Worksheet, sheet
509
- str = "S\000h\000e\000e\000t\0001\000"
509
+ str = "S\000h\000e\000e\000t\0001\000".dup
510
510
  if RUBY_VERSION >= '1.9'
511
511
  str.force_encoding 'UTF-16LE' if str.respond_to?(:force_encoding)
512
512
  end
@@ -730,7 +730,7 @@ module Spreadsheet
730
730
  book = Spreadsheet::Excel::Workbook.new
731
731
  sheet = book.create_worksheet :name => 'My Worksheet'
732
732
  sheet[0,0] = 'my cell'
733
- data = StringIO.new ''
733
+ data = StringIO.new ''.dup
734
734
  assert_nothing_raised do
735
735
  book.write data
736
736
  end
@@ -749,7 +749,7 @@ module Spreadsheet
749
749
  sheet1 = book.create_worksheet
750
750
  str1 = 'My Shared String'
751
751
  str2 = 'Another Shared String'
752
- assert_equal 1, (str1.size + str2.size) % 2,
752
+ assert_equal 1, (str1.size + str2.size) % 2,
753
753
  "str3 should start at an odd offset to test splitting of wide strings"
754
754
  str3 = '–––––––––– ' * 1000
755
755
  str4 = '1234567890 ' * 1000
@@ -829,7 +829,7 @@ module Spreadsheet
829
829
  assert_equal 2, book.worksheets.size
830
830
  sheet = book.worksheets.first
831
831
  assert_instance_of Spreadsheet::Excel::Worksheet, sheet
832
- name = "W\000o\000r\000k\000s\000h\000e\000e\000t\0001\000"
832
+ name = "W\000o\000r\000k\000s\000h\000e\000e\000t\0001\000".dup
833
833
  name.force_encoding 'UTF-16LE' if name.respond_to?(:force_encoding)
834
834
  assert_equal name, sheet.name
835
835
  assert_not_nil sheet.offset
@@ -926,7 +926,7 @@ module Spreadsheet
926
926
  assert_equal 40, sheet1.row(11).height
927
927
  assert_instance_of Spreadsheet::Excel::Worksheet, sheet
928
928
  sheet = book.worksheets.last
929
- name = "m\000y\000 \000n\000a\000m\000e\000"
929
+ name = "m\000y\000 \000n\000a\000m\000e\000".dup
930
930
  name.force_encoding 'UTF-16LE' if name.respond_to?(:force_encoding)
931
931
  assert_equal name, sheet.name
932
932
  assert_not_nil sheet.offset
@@ -1211,8 +1211,8 @@ module Spreadsheet
1211
1211
  book = Spreadsheet::Workbook.new
1212
1212
  sheet = book.create_worksheet
1213
1213
  (0..200).each { |i| sheet.row(i).push "ëçáéíóú" }
1214
- assert_nothing_raised do
1215
- book.write StringIO.new("", "w+")
1214
+ assert_nothing_raised do
1215
+ book.write StringIO.new("".dup, "w+")
1216
1216
  end
1217
1217
  end
1218
1218
 
@@ -1257,7 +1257,7 @@ module Spreadsheet
1257
1257
  str1 = "Frozen String.".freeze
1258
1258
  sheet1[0,0] = str1
1259
1259
  sheet1.row(0).push str1
1260
- assert_nothing_raised do
1260
+ assert_nothing_raised do
1261
1261
  book.write path
1262
1262
  end
1263
1263
  end
@@ -1290,7 +1290,7 @@ module Spreadsheet
1290
1290
  sheet1 = book.create_worksheet
1291
1291
  (sheet1.row(0).format 0).border = :hair
1292
1292
  (sheet1.row(0).format 0).border_color = :brown
1293
- assert_nothing_raised do
1293
+ assert_nothing_raised do
1294
1294
  book.write path
1295
1295
  end
1296
1296
  book2 = Spreadsheet.open path
@@ -1391,7 +1391,7 @@ module Spreadsheet
1391
1391
  path = File.join @var, 'test_write_worksheet_visibility.xls'
1392
1392
  sheet1 = book.create_worksheet
1393
1393
  sheet1.visibility = :hidden
1394
- sheet2 = book.create_worksheet
1394
+ _sheet2 = book.create_worksheet
1395
1395
  assert_nothing_raised do
1396
1396
  book.write path
1397
1397
  end
@@ -1401,6 +1401,30 @@ module Spreadsheet
1401
1401
  assert_equal(:visible, book2.worksheet(1).visibility)
1402
1402
  end
1403
1403
 
1404
+ def test_append_and_reopen
1405
+ filename = path = File.join @var, 'test.xls'
1406
+ sheet_name = 'Test Sheet'
1407
+
1408
+ # Create excel
1409
+ excel = Spreadsheet::Workbook.new(filename)
1410
+ sheet = excel.create_worksheet(name: sheet_name)
1411
+ sheet.row(1).replace ['Data']
1412
+ excel.write(filename)
1413
+
1414
+ # Append something
1415
+ excel = Spreadsheet.open(filename, 'a+')
1416
+ sheet = excel.worksheet(sheet_name)
1417
+ sheet.row(2).replace ['Data2']
1418
+ filename = "test2.xls"
1419
+ excel.write(filename)
1420
+
1421
+ # Reopen
1422
+ excel = Spreadsheet.open filename
1423
+ sheet = excel.worksheet sheet_name
1424
+ ensure
1425
+ File.delete filename if File.exist? filename
1426
+ end
1427
+
1404
1428
  def test_text_drawing
1405
1429
  path = File.join @data, 'test_text_drawing.xls'
1406
1430
  book = Spreadsheet.open path
data/test/suite.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require 'rubygems'
4
4
  require 'bundler'
5
5
  require 'find'
6
+ require 'simplecov'
7
+ SimpleCov.start
6
8
 
7
9
  $VERBOSE = true
8
10
 
data/test/worksheet.rb CHANGED
@@ -108,18 +108,40 @@ module Spreadsheet
108
108
  assert_equal 6, @book.formats.length
109
109
 
110
110
  end
111
-
111
+
112
112
  def test_freeze_panel!
113
113
  assert_equal 0, @sheet.froze_top
114
114
  assert_equal 0, @sheet.froze_left
115
115
  assert_equal false, @sheet.has_frozen_panel?
116
-
116
+
117
117
  @sheet.freeze!(2, 3)
118
118
  assert_equal 2, @sheet.froze_top
119
119
  assert_equal 3, @sheet.froze_left
120
120
  assert_equal true, @sheet.has_frozen_panel?
121
-
121
+
122
+ end
123
+
124
+ def test_each_with_skip
125
+ @sheet[0, 0] = 'foo'
126
+ @sheet[1, 0] = 'bar'
127
+
128
+ assert_equal @sheet.each(1).count, 1
129
+ assert_equal @sheet.each(1).first[0], 'bar'
122
130
  end
123
-
131
+
132
+ def test_each_with_index
133
+ @sheet[0, 0] = 'foo'
134
+ @sheet[1, 0] = 'bar'
135
+
136
+ @sheet.each.with_index do |row, index|
137
+ assert_equal row[0], @sheet[index, 0]
138
+ end
139
+ end
140
+
141
+ def test_name
142
+ worksheet = Worksheet.new(name: '\a/b*c?d:e[f]')
143
+ assert_equal '_a_b_c_d_e_f_', worksheet.name
144
+ end
145
+
124
146
  end
125
147
  end