spreadsheet 1.1.3 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Manifest.txt +1 -0
- data/bin/bundle +114 -0
- data/bin/bundler +17 -0
- data/bin/oletool +29 -0
- data/bin/rake +29 -0
- data/bin/sow +17 -0
- data/bin/xlsopcodes +22 -11
- data/lib/spreadsheet/excel/internals.rb +1 -1
- data/lib/spreadsheet/excel/reader/biff8.rb +1 -1
- data/lib/spreadsheet/excel/reader.rb +12 -10
- data/lib/spreadsheet/excel/workbook.rb +1 -2
- data/lib/spreadsheet/excel/writer/n_worksheet.rb +0 -75
- data/lib/spreadsheet/excel/writer/workbook.rb +5 -92
- data/lib/spreadsheet/excel/writer/worksheet.rb +3 -81
- data/lib/spreadsheet/excel.rb +0 -6
- data/lib/spreadsheet/format.rb +2 -2
- data/lib/spreadsheet/version.rb +7 -0
- data/lib/spreadsheet/workbook.rb +1 -1
- data/lib/spreadsheet/worksheet.rb +23 -13
- data/lib/spreadsheet.rb +2 -4
- data/test/data/test_compact_format_date.xls +0 -0
- data/test/data/test_compact_many_rows.xls +0 -0
- data/test/data/test_missing_format.xls +0 -0
- data/test/data/test_sizes.xls +0 -0
- data/test/excel/reader.rb +13 -0
- data/test/format.rb +2 -0
- data/test/integration.rb +36 -12
- data/test/suite.rb +2 -0
- data/test/worksheet.rb +26 -4
- metadata +65 -49
- data/.gitignore +0 -2
- data/.travis.yml +0 -35
- data/Excel97-2007BinaryFileFormatSpecification.pdf +0 -0
- data/GUIDE.md +0 -339
- data/Gemfile +0 -10
- data/Gemfile.lock +0 -23
- data/History.md +0 -746
- data/README.md +0 -113
- data/Rakefile +0 -21
- data/excelfileformat.pdf +0 -0
- data/spreadsheet.gemspec +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c0291eb7283e45bbe612232b8ee760af808b65440ec47b536236638b6f2ed96c
|
4
|
+
data.tar.gz: 5fe1c14cc4898d924e69a7b4c4d5d1590e5e822f04e9991222631c674399ad45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d77e1dd7a9b4bce2007d99e3a2a829fb27f51f3739dca76d877a5279999392ffe72206a1be2b6cabc0e2432fa3e4705f3bdf4a2060b9a0e66b4242c719438c2
|
7
|
+
data.tar.gz: f85e21c6b636713a9bcba68d436edbce67e3aab4fa01790be36a1b776e2cb0508fa9bbd4904c9d551258640109dbd574fb671503c6c6d62bd3af848dcbc955fe
|
data/Manifest.txt
CHANGED
data/bin/bundle
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../../Gemfile", __FILE__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_version
|
64
|
+
@bundler_version ||=
|
65
|
+
env_var_version || cli_arg_version ||
|
66
|
+
lockfile_version
|
67
|
+
end
|
68
|
+
|
69
|
+
def bundler_requirement
|
70
|
+
return "#{Gem::Requirement.default}.a" unless bundler_version
|
71
|
+
|
72
|
+
bundler_gem_version = Gem::Version.new(bundler_version)
|
73
|
+
|
74
|
+
requirement = bundler_gem_version.approximate_recommendation
|
75
|
+
|
76
|
+
return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
|
77
|
+
|
78
|
+
requirement += ".a" if bundler_gem_version.prerelease?
|
79
|
+
|
80
|
+
requirement
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_bundler!
|
84
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
85
|
+
|
86
|
+
activate_bundler
|
87
|
+
end
|
88
|
+
|
89
|
+
def activate_bundler
|
90
|
+
gem_error = activation_error_handling do
|
91
|
+
gem "bundler", bundler_requirement
|
92
|
+
end
|
93
|
+
return if gem_error.nil?
|
94
|
+
require_error = activation_error_handling do
|
95
|
+
require "bundler/version"
|
96
|
+
end
|
97
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
98
|
+
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
99
|
+
exit 42
|
100
|
+
end
|
101
|
+
|
102
|
+
def activation_error_handling
|
103
|
+
yield
|
104
|
+
nil
|
105
|
+
rescue StandardError, LoadError => e
|
106
|
+
e
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
m.load_bundler!
|
111
|
+
|
112
|
+
if m.invoked_as_script?
|
113
|
+
load Gem.bin_path("bundler", "bundle")
|
114
|
+
end
|
data/bin/bundler
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#
|
4
|
+
# This file was generated by Bundler.
|
5
|
+
#
|
6
|
+
# The application 'bundler' is installed as part of a gem, and
|
7
|
+
# this file is here to facilitate running it.
|
8
|
+
#
|
9
|
+
|
10
|
+
require "pathname"
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
12
|
+
Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
require "rubygems"
|
15
|
+
require "bundler/setup"
|
16
|
+
|
17
|
+
load Gem.bin_path("bundler", "bundler")
|
data/bin/oletool
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'oletool' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("ruby-ole", "oletool")
|
data/bin/rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rake", "rake")
|
data/bin/sow
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#
|
4
|
+
# This file was generated by Bundler.
|
5
|
+
#
|
6
|
+
# The application 'sow' is installed as part of a gem, and
|
7
|
+
# this file is here to facilitate running it.
|
8
|
+
#
|
9
|
+
|
10
|
+
require "pathname"
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
12
|
+
Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
require "rubygems"
|
15
|
+
require "bundler/setup"
|
16
|
+
|
17
|
+
load Gem.bin_path("hoe", "sow")
|
data/bin/xlsopcodes
CHANGED
@@ -1,18 +1,29 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'xlsopcodes' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
4
10
|
|
5
|
-
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
6
14
|
|
7
|
-
|
8
|
-
puts "Usage: #{$0} <source> [<target>]"
|
9
|
-
exit -1
|
10
|
-
end
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
11
16
|
|
12
|
-
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
13
25
|
|
14
|
-
|
15
|
-
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
16
28
|
|
17
|
-
|
18
|
-
end
|
29
|
+
load Gem.bin_path("spreadsheet", "xlsopcodes")
|
@@ -54,7 +54,7 @@ module Internals
|
|
54
54
|
32768 => "MACROMAN",
|
55
55
|
32769 => "WINDOWS-1252", #(Latin I) (BIFF2-BIFF3)
|
56
56
|
}
|
57
|
-
SEGAPEDOC = CODEPAGES.invert
|
57
|
+
SEGAPEDOC = CODEPAGES.reject { |k, _v| k >= 21010 }.invert
|
58
58
|
# color_codes according to http://support.softartisans.com/kbview_1205.aspx
|
59
59
|
# synonyms are in comments when reverse lookup
|
60
60
|
COLOR_CODES = {
|
@@ -56,7 +56,7 @@ class Reader
|
|
56
56
|
## remove two bits
|
57
57
|
integer, = work.unpack 'V'
|
58
58
|
integer &= 0xfffffffc
|
59
|
-
value, = ("\0\0\0\0"
|
59
|
+
value, = ("\0\0\0\0" + [integer].pack('V')).unpack EIGHT_BYTE_DOUBLE
|
60
60
|
else
|
61
61
|
## I can't find a format for unpacking a little endian signed integer.
|
62
62
|
# 'V' works for packing, but not for unpacking. But the following works
|
@@ -125,11 +125,12 @@ class Reader
|
|
125
125
|
#So link the noteObject(text) to the note (with author, position)
|
126
126
|
#TODO
|
127
127
|
@noteList.each do |i|
|
128
|
-
|
129
|
-
if
|
128
|
+
matching_objs = @noteObjList.select { |j| j.objID == i.objID }
|
129
|
+
if matching_objs.length > 1
|
130
130
|
puts "ERROR - more than one matching object ID!"
|
131
131
|
end
|
132
|
-
|
132
|
+
matching_obj = matching_objs.first
|
133
|
+
i.text = matching_obj.nil? ? '' : matching_obj.text
|
133
134
|
worksheet.add_note i.row, i.col, i.text
|
134
135
|
end
|
135
136
|
end
|
@@ -398,10 +399,10 @@ class Reader
|
|
398
399
|
end
|
399
400
|
formula.value = value
|
400
401
|
elsif rtype == 0
|
401
|
-
pos, op,
|
402
|
+
pos, op, _len, work = get_next_chunk
|
402
403
|
if op == :sharedfmla
|
403
404
|
## TODO: formula-support in 0.8.0
|
404
|
-
pos, op,
|
405
|
+
pos, op, _len, work = get_next_chunk
|
405
406
|
end
|
406
407
|
if op == :string
|
407
408
|
formula.value = client read_string(work, 2), @workbook.encoding
|
@@ -851,6 +852,7 @@ class Reader
|
|
851
852
|
@detected_rows = {}
|
852
853
|
@noteObjList = []
|
853
854
|
@noteList = []
|
855
|
+
@noteObject = nil
|
854
856
|
previous = nil
|
855
857
|
while tuple = get_next_chunk
|
856
858
|
pos, op, len, work = tuple
|
@@ -1273,11 +1275,11 @@ class Reader
|
|
1273
1275
|
end
|
1274
1276
|
def setup io
|
1275
1277
|
## Reading from StringIO fails without forced encoding
|
1276
|
-
if
|
1277
|
-
|
1278
|
-
|
1278
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.3.0')
|
1279
|
+
io.set_encoding('ASCII-8BIT')
|
1280
|
+
elsif io.respond_to?(:string) && (str = io.string) && str.respond_to?(:force_encoding)
|
1281
|
+
str.force_encoding('ASCII-8BIT')
|
1279
1282
|
end
|
1280
|
-
##
|
1281
1283
|
io.rewind
|
1282
1284
|
@ole = Ole::Storage.open io
|
1283
1285
|
@workbook = Workbook.new io, {}
|
@@ -241,81 +241,6 @@ class Worksheet
|
|
241
241
|
end
|
242
242
|
write_multiples row, first_idx, multiples if multiples
|
243
243
|
end
|
244
|
-
def write_changes reader, endpos, sst_status
|
245
|
-
|
246
|
-
## FIXME this is not smart solution to update outline_level.
|
247
|
-
# without this process, outlines in row disappear in MS Excel.
|
248
|
-
@worksheet.row_count.times do |i|
|
249
|
-
if @worksheet.row(i).outline_level > 0
|
250
|
-
@worksheet.row(i).outline_level = @worksheet.row(i).outline_level
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
reader.seek @worksheet.offset
|
255
|
-
blocks = row_blocks
|
256
|
-
lastpos = reader.pos
|
257
|
-
offsets = {}
|
258
|
-
row_offsets = []
|
259
|
-
changes = @worksheet.changes
|
260
|
-
@worksheet.offsets.each do |key, pair|
|
261
|
-
if changes.include?(key) \
|
262
|
-
|| (sst_status == :complete_update && key.is_a?(Integer))
|
263
|
-
offsets.store pair, key
|
264
|
-
end
|
265
|
-
end
|
266
|
-
## FIXME it may be smarter to simply write all rowblocks, instead of doing a
|
267
|
-
# song-and-dance routine for every row...
|
268
|
-
work = offsets.invert
|
269
|
-
work.each do |key, (pos, len)|
|
270
|
-
case key
|
271
|
-
when Integer
|
272
|
-
row_offsets.push [key, [pos, len]]
|
273
|
-
when :dimensions
|
274
|
-
row_offsets.push [-1, [pos, len]]
|
275
|
-
end
|
276
|
-
end
|
277
|
-
row_offsets.sort!
|
278
|
-
row_offsets.reverse!
|
279
|
-
control = changes.size
|
280
|
-
@worksheet.each do |row|
|
281
|
-
key = row.idx
|
282
|
-
if changes.include?(key) && !work.include?(key)
|
283
|
-
row, pair = row_offsets.find do |idx, _| idx <= key end
|
284
|
-
work.store key, pair
|
285
|
-
end
|
286
|
-
end
|
287
|
-
if changes.size > control
|
288
|
-
warn <<-EOS
|
289
|
-
Your Worksheet was modified while it was being written. This should not happen.
|
290
|
-
Please contact the author (hannes dot wyss at gmail dot com) with a sample file
|
291
|
-
and minimal code that generates this warning. Thanks!
|
292
|
-
EOS
|
293
|
-
end
|
294
|
-
work = work.sort_by do |key, (pos, len)|
|
295
|
-
[pos, key.is_a?(Integer) ? key : -1]
|
296
|
-
end
|
297
|
-
work.each do |key, (pos, len)|
|
298
|
-
@io.write reader.read(pos - lastpos) if pos > lastpos
|
299
|
-
if key.is_a?(Integer)
|
300
|
-
if block = blocks.find do |rows| rows.any? do |row| row.idx == key end end
|
301
|
-
write_rowblock block
|
302
|
-
blocks.delete block
|
303
|
-
end
|
304
|
-
else
|
305
|
-
send "write_#{key}"
|
306
|
-
end
|
307
|
-
lastpos = pos + len
|
308
|
-
reader.seek lastpos
|
309
|
-
end
|
310
|
-
|
311
|
-
# Necessary for outline (grouping) and hiding functions
|
312
|
-
# but these below are not necessary to run
|
313
|
-
# if [Row|Column]#hidden? = false and [Row|Column]#outline_level == 0
|
314
|
-
write_colinfos
|
315
|
-
write_guts
|
316
|
-
|
317
|
-
@io.write reader.read(endpos - lastpos)
|
318
|
-
end
|
319
244
|
def write_colinfo bunch
|
320
245
|
col = bunch.first
|
321
246
|
width = col.width.to_f * 256
|
@@ -164,93 +164,6 @@ class Workbook < Spreadsheet::Writer
|
|
164
164
|
end
|
165
165
|
end
|
166
166
|
##
|
167
|
-
# Copy unchanged data verbatim, adjust offsets and write new records for
|
168
|
-
# changed data.
|
169
|
-
def write_changes workbook, io
|
170
|
-
sanitize_worksheets workbook.worksheets
|
171
|
-
collect_formats workbook, :existing_document => true
|
172
|
-
reader = workbook.ole
|
173
|
-
sheet_data = {}
|
174
|
-
sst_status, sst_total, sst_strings = complete_sst_update? workbook
|
175
|
-
sst = {}
|
176
|
-
sst_strings.each_with_index do |str, idx| sst.store str, idx end
|
177
|
-
sheets = worksheets(workbook)
|
178
|
-
positions = []
|
179
|
-
newsheets = []
|
180
|
-
sheets.each do |sheet|
|
181
|
-
@sst[sheet] = sst
|
182
|
-
pos, len = workbook.offsets[sheet.worksheet]
|
183
|
-
if pos
|
184
|
-
positions.push pos
|
185
|
-
sheet.write_changes reader, pos + len, sst_status
|
186
|
-
else
|
187
|
-
newsheets.push sheet
|
188
|
-
sheet.write_from_scratch
|
189
|
-
end
|
190
|
-
sheet_data[sheet.worksheet] = sheet.data
|
191
|
-
end
|
192
|
-
Ole::Storage.open io do |ole|
|
193
|
-
ole.file.open 'Workbook', 'w' do |writer|
|
194
|
-
reader.seek lastpos = 0
|
195
|
-
workbook.offsets.select do |key, pair|
|
196
|
-
workbook.changes.include? key
|
197
|
-
end.sort_by do |key, (pos, _)|
|
198
|
-
pos
|
199
|
-
end.each do |key, (pos, len)|
|
200
|
-
data = reader.read(pos - lastpos)
|
201
|
-
writer.write data
|
202
|
-
case key
|
203
|
-
when Spreadsheet::Worksheet
|
204
|
-
writer.write sheet_data[key]
|
205
|
-
when :boundsheets
|
206
|
-
## boundsheets are hard to calculate. The offset below is only
|
207
|
-
# correct if there are no more changes in the workbook globals
|
208
|
-
# string after this.
|
209
|
-
oldoffset = positions.min - len
|
210
|
-
lastpos = pos + len
|
211
|
-
bytechange = 0
|
212
|
-
buffer = StringIO.new ''
|
213
|
-
if tuple = workbook.offsets[:sst]
|
214
|
-
write_sst_changes workbook, buffer, writer.pos,
|
215
|
-
sst_total, sst_strings
|
216
|
-
pos, len = tuple
|
217
|
-
if offset = workbook.offsets[:extsst]
|
218
|
-
len += offset[1].to_i
|
219
|
-
end
|
220
|
-
bytechange = buffer.size - len
|
221
|
-
write_boundsheets workbook, writer, oldoffset + bytechange
|
222
|
-
reader.seek lastpos
|
223
|
-
writer.write reader.read(pos - lastpos)
|
224
|
-
buffer.rewind
|
225
|
-
writer.write buffer.read
|
226
|
-
elsif sst.empty? || workbook.biff_version < 8
|
227
|
-
write_boundsheets workbook, writer, oldoffset + bytechange
|
228
|
-
else
|
229
|
-
write_sst workbook, buffer, writer.pos
|
230
|
-
write_boundsheets workbook, writer, oldoffset + buffer.size
|
231
|
-
pos = lastpos
|
232
|
-
len = positions.min - lastpos
|
233
|
-
if len > OPCODE_SIZE
|
234
|
-
reader.seek pos
|
235
|
-
writer.write reader.read(len - OPCODE_SIZE)
|
236
|
-
end
|
237
|
-
buffer.rewind
|
238
|
-
writer.write buffer.read
|
239
|
-
write_eof workbook, writer
|
240
|
-
end
|
241
|
-
else
|
242
|
-
send "write_#{key}", workbook, writer
|
243
|
-
end
|
244
|
-
lastpos = [pos + len, reader.size - 1].min
|
245
|
-
reader.seek lastpos
|
246
|
-
end
|
247
|
-
writer.write reader.read
|
248
|
-
newsheets.each do |sheet|
|
249
|
-
writer.write sheet.data
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
167
|
def write_datemode workbook, writer
|
255
168
|
mode = @date_base.year == 1899 ? 0x00 : 0x01
|
256
169
|
data = [
|
@@ -396,7 +309,7 @@ class Workbook < Spreadsheet::Writer
|
|
396
309
|
sanitize_worksheets workbook.worksheets
|
397
310
|
collect_formats workbook
|
398
311
|
sheets = worksheets workbook
|
399
|
-
buffer1 = StringIO.new ''
|
312
|
+
buffer1 = StringIO.new ''.dup
|
400
313
|
# ● BOF Type = workbook globals (➜ 6.8)
|
401
314
|
write_bof workbook, buffer1, :globals
|
402
315
|
# ○ File Protection Block ➜ 4.19
|
@@ -441,7 +354,7 @@ class Workbook < Spreadsheet::Writer
|
|
441
354
|
# ○ USESELFS ➜ 5.106
|
442
355
|
buffer1.rewind
|
443
356
|
# ●● BOUNDSHEET ➜ 5.95
|
444
|
-
buffer2 = StringIO.new ''
|
357
|
+
buffer2 = StringIO.new ''.dup
|
445
358
|
# ○ COUNTRY ➜ 5.22
|
446
359
|
# ○ Link Table ➜ 4.10.3
|
447
360
|
# ○○ NAME ➜ 6.66
|
@@ -639,8 +552,7 @@ class Workbook < Spreadsheet::Writer
|
|
639
552
|
write_op writer, 0x003d, data.pack('v*')
|
640
553
|
end
|
641
554
|
##
|
642
|
-
# The main writer method. Calls #write_from_scratch
|
643
|
-
# depending on the class and state of _workbook_.
|
555
|
+
# The main writer method. Calls #write_from_scratch.
|
644
556
|
def write_workbook workbook, io
|
645
557
|
unless workbook.is_a?(Excel::Workbook) && workbook.io
|
646
558
|
@date_base = Date.new 1899, 12, 31
|
@@ -650,7 +562,8 @@ class Workbook < Spreadsheet::Writer
|
|
650
562
|
if workbook.changes.empty?
|
651
563
|
super
|
652
564
|
else
|
653
|
-
|
565
|
+
@date_base = Date.new 1899, 12, 31
|
566
|
+
write_from_scratch workbook, io
|
654
567
|
end
|
655
568
|
end
|
656
569
|
ensure
|