spreadsheet 1.2.9 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a831e5c252775858cbdba547a3ac3228028cb6c9a56a92a77ab8fdc393de0658
|
4
|
+
data.tar.gz: 1240cd6a3b8362fa9c807c26d36fd6f8df19872e195ce09e98583597f73fa8cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35dd4c09f32c793bf85f4290a497eb25a298b2f59e107eb4ecebf3c37e1e6a1ee505eaec3409057c0914754ca9036fb8a4c173c8d251e448ef932e38489d0c04
|
7
|
+
data.tar.gz: b20106050e1370ced689559af16e97efc4b19abde21165091d9f4a1ebea02758625713f09e20be0ccf7b8be2075fc59567c5bf581e583a2250ccc81ee04b2e5f
|
@@ -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 ''.dup
|
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 = [
|
@@ -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
|
@@ -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
|
data/lib/spreadsheet/version.rb
CHANGED
data/test/integration.rb
CHANGED
@@ -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
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spreadsheet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hannes F. Wyss, Masaomi Hatakeyama, Zeno R.R. Davatz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-ole
|