spreadsheet 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +15 -0
- data/README.md +3 -0
- data/bin/xlsopcodes +14 -12
- data/lib/spreadsheet.rb +1 -1
- data/lib/spreadsheet/excel/internals.rb +4 -0
- data/lib/spreadsheet/excel/reader.rb +74 -1
- data/lib/spreadsheet/excel/reader/biff8.rb +14 -2
- data/lib/spreadsheet/excel/worksheet.rb +5 -1
- data/spreadsheet.gemspec +1 -1
- data/test/integration.rb +7 -0
- metadata +2 -2
data/History.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
### 0.9.2 / 11.11.2013
|
2
|
+
|
3
|
+
commit e70dc0dbbc966ce312b45b0d44d0c3b1dc10aad6
|
4
|
+
Author: Malcolm Blyth <trashbat@co.ck>
|
5
|
+
Date: Mon Nov 11 15:53:58 2013 +0000
|
6
|
+
|
7
|
+
*Corrected compressed string formatting - *U (UTF-8) should have been *S (16-bit string)
|
8
|
+
*Completed addition of notes hash to worksheet
|
9
|
+
*Bumped revision
|
10
|
+
*Updated reader and note
|
11
|
+
Note class no longer extends string for simplicity and debug of class (pp now works a bit more easily)
|
12
|
+
Reader has had loads of changes (still WIP) to allow objects of class
|
13
|
+
Note and NoteObject to be created and combined in the postread_worksheet function
|
14
|
+
*Adding noteObject to deal with the Object (and ultimately text comment field) created by excel's madness
|
15
|
+
|
1
16
|
### 0.9.1 / 24.10.2013
|
2
17
|
|
3
18
|
* Author: Matti Lehtonen <matti.lehtonen@puujaa.com>
|
data/README.md
CHANGED
data/bin/xlsopcodes
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by Bundler.
|
4
|
-
#
|
5
|
-
# The application 'xlsopcodes' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
2
|
|
9
|
-
require '
|
10
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
-
Pathname.new(__FILE__).realpath)
|
3
|
+
require 'spreadsheet'
|
12
4
|
|
13
|
-
|
14
|
-
require 'bundler/setup'
|
5
|
+
source, target = ARGV
|
15
6
|
|
16
|
-
|
7
|
+
if source.nil?
|
8
|
+
puts "Usage: #{$0} <source> [<target>]"
|
9
|
+
exit -1
|
10
|
+
end
|
11
|
+
|
12
|
+
target = target ? File.open(target, 'w') : STDOUT
|
13
|
+
|
14
|
+
reader = Spreadsheet::Excel::Reader.new :print_opcodes => target
|
15
|
+
reader.setup File.open(source)
|
16
|
+
|
17
|
+
while tuple = reader.get_next_chunk
|
18
|
+
end
|
data/lib/spreadsheet.rb
CHANGED
@@ -380,6 +380,10 @@ module Internals
|
|
380
380
|
:wsbool => 0x0081, # ○ WSBOOL ➜ 6.113
|
381
381
|
:defcolwidth => 0x0055, # ○ DEFCOLWIDTH ➜ 6.29
|
382
382
|
:sort => 0x0090, # ○ SORT ➜ 6.95
|
383
|
+
:note => 0x001c,
|
384
|
+
:obj => 0x005d,
|
385
|
+
:drawing => 0x00EC,
|
386
|
+
:txo => 0x01B6,
|
383
387
|
}
|
384
388
|
=begin ## unknown opcodes
|
385
389
|
0x00bf, 0x00c0, 0x00c1, 0x00e1, 0x00e2, 0x00eb, 0x01af, 0x01bc
|
@@ -2,6 +2,8 @@ require 'spreadsheet/encodings'
|
|
2
2
|
require 'spreadsheet/font'
|
3
3
|
require 'spreadsheet/formula'
|
4
4
|
require 'spreadsheet/link'
|
5
|
+
require 'spreadsheet/note'
|
6
|
+
require 'spreadsheet/noteObject'
|
5
7
|
require 'spreadsheet/excel/error'
|
6
8
|
require 'spreadsheet/excel/internals'
|
7
9
|
require 'spreadsheet/excel/sst_entry'
|
@@ -113,6 +115,17 @@ class Reader
|
|
113
115
|
end
|
114
116
|
end
|
115
117
|
def postread_worksheet worksheet
|
118
|
+
#We now have a lot of Note and NoteObjects, but they're not linked
|
119
|
+
#So link the noteObject(text) to the note (with author, position)
|
120
|
+
#TODO
|
121
|
+
@noteList.each do |i|
|
122
|
+
matching_obj = @noteObjList.select {|j| j.objID == i.objID}
|
123
|
+
if matching_obj.length > 1
|
124
|
+
puts "ERROR - more than one matching object ID!"
|
125
|
+
end
|
126
|
+
i.text = matching_obj.first.text
|
127
|
+
worksheet.add_note i.row, i.col, i.text
|
128
|
+
end
|
116
129
|
end
|
117
130
|
##
|
118
131
|
# The entry-point for reading Excel-documents. Reads the Biff-Version and
|
@@ -830,6 +843,8 @@ class Reader
|
|
830
843
|
def read_worksheet worksheet, offset
|
831
844
|
@pos = offset
|
832
845
|
@detected_rows = {}
|
846
|
+
@noteObjList = []
|
847
|
+
@noteList = []
|
833
848
|
previous = nil
|
834
849
|
while tuple = get_next_chunk
|
835
850
|
pos, op, len, work = tuple
|
@@ -867,6 +882,42 @@ class Reader
|
|
867
882
|
read_merged_cells worksheet, work, pos, len
|
868
883
|
when :protect, :password
|
869
884
|
read_sheet_protection worksheet, op, work
|
885
|
+
when :note # a note references an :obj
|
886
|
+
read_note worksheet, work, pos, len
|
887
|
+
when :obj # it contains the author in the NTS structure
|
888
|
+
_ft, _cb, _ot, _objID = work.unpack('v4')
|
889
|
+
if _ot == 0x19
|
890
|
+
#puts "\nDEBUG: found Note Obj record"
|
891
|
+
@noteObject = NoteObject.new
|
892
|
+
@noteObject.objID = _objID
|
893
|
+
end
|
894
|
+
#p work
|
895
|
+
when :drawing # this can be followed by txo in case of a note
|
896
|
+
if previous == :obj
|
897
|
+
#puts "\nDEBUG: found MsDrawing record"
|
898
|
+
#p work
|
899
|
+
end
|
900
|
+
when :txo # this contains the length of the note text
|
901
|
+
if previous == :drawing
|
902
|
+
#puts "\nDEBUG: found TxO record"
|
903
|
+
#p work
|
904
|
+
end
|
905
|
+
when :continue # this contains the actual note text
|
906
|
+
if previous == :txo
|
907
|
+
#puts "\nDEBUG: found Continue record"
|
908
|
+
continueFmt = work.unpack('C')
|
909
|
+
if (continueFmt.first == 0)
|
910
|
+
#puts "Picking compressed charset"
|
911
|
+
#Skip to offset due to 'v5C' used above
|
912
|
+
_text = work.unpack('@1C*')
|
913
|
+
@noteObject.text = _text.pack('C*')
|
914
|
+
elsif (continueFmt.first == 1)
|
915
|
+
#puts "Picking uncompressed charset"
|
916
|
+
_text = work.unpack('@1S*')
|
917
|
+
@noteObject.text = _text.pack('U*')
|
918
|
+
end
|
919
|
+
@noteObjList << @noteObject
|
920
|
+
end
|
870
921
|
when :pagesetup
|
871
922
|
read_pagesetup(worksheet, work, pos, len)
|
872
923
|
when :leftmargin
|
@@ -882,7 +933,8 @@ class Reader
|
|
882
933
|
set_missing_row_address worksheet, work, pos, len
|
883
934
|
end
|
884
935
|
end
|
885
|
-
previous = op
|
936
|
+
previous = op
|
937
|
+
#previous = op unless op == :continue
|
886
938
|
end
|
887
939
|
end
|
888
940
|
|
@@ -1087,6 +1139,27 @@ class Reader
|
|
1087
1139
|
fmt.pattern_bg_color = COLOR_CODES[(xf_pattern & 0x3f80) >> 7] || :pattern_bg
|
1088
1140
|
@workbook.add_format fmt
|
1089
1141
|
end
|
1142
|
+
def read_note worksheet, work, pos, len
|
1143
|
+
#puts "\nDEBUG: found a note record in read_worksheet\n"
|
1144
|
+
row, col, _, _objID, _objAuthLen, _objAuthLenFmt = work.unpack('v5C')
|
1145
|
+
if (_objAuthLenFmt == 0)
|
1146
|
+
#puts "Picking compressed charset"
|
1147
|
+
#Skip to offset due to 'v5C' used above
|
1148
|
+
_objAuth = work.unpack('@11C*')
|
1149
|
+
elsif (_objAuthLenFmt == 1)
|
1150
|
+
#puts "Picking uncompressed charset"
|
1151
|
+
_objAuth = work.unpack('@11S*')
|
1152
|
+
end
|
1153
|
+
_objAuth = _objAuth.pack('C*')
|
1154
|
+
@note = Note.new
|
1155
|
+
@note.length = len
|
1156
|
+
@note.row = row
|
1157
|
+
@note.col = col
|
1158
|
+
@note.author = _objAuth
|
1159
|
+
@note.objID = _objID
|
1160
|
+
#Pop it on the list to be sorted in postread_worksheet
|
1161
|
+
@noteList << @note
|
1162
|
+
end
|
1090
1163
|
def read_sheet_protection worksheet, op, data
|
1091
1164
|
case op
|
1092
1165
|
when :protect
|
@@ -28,6 +28,18 @@ module Biff8
|
|
28
28
|
end
|
29
29
|
size + 1
|
30
30
|
end
|
31
|
+
# When a String is too long for one Opcode, it is continued in a Continue
|
32
|
+
# Opcode. Excel may reconsider compressing the remainder of the string.
|
33
|
+
# This method appends the available remainder (decompressed if necessary) to
|
34
|
+
# the incomplete string.
|
35
|
+
def unpack_string work
|
36
|
+
opts, _ = work.unpack 'C'
|
37
|
+
wide = opts & 1
|
38
|
+
string = work[1, -1]
|
39
|
+
if wide == 0
|
40
|
+
string = wide string
|
41
|
+
end
|
42
|
+
end
|
31
43
|
##
|
32
44
|
# When a String is too long for one Opcode, it is continued in a Continue
|
33
45
|
# Opcode. Excel may reconsider compressing the remainder of the string.
|
@@ -125,8 +137,8 @@ module Biff8
|
|
125
137
|
# the available data (unchanged).
|
126
138
|
def read_string_body work, offset, available, wide
|
127
139
|
data = work[offset, available]
|
128
|
-
|
129
|
-
[
|
140
|
+
widened_data = wide ? data : wide(data)
|
141
|
+
[widened_data, data]
|
130
142
|
end
|
131
143
|
##
|
132
144
|
# Read the header of a string. Returns the following information in an Array:
|
@@ -11,7 +11,7 @@ module Spreadsheet
|
|
11
11
|
class Worksheet < Spreadsheet::Worksheet
|
12
12
|
include Spreadsheet::Excel::Offset
|
13
13
|
offset :dimensions
|
14
|
-
attr_reader :offset, :ole, :links, :guts
|
14
|
+
attr_reader :offset, :ole, :links, :guts, :notes
|
15
15
|
def initialize opts = {}
|
16
16
|
@row_addresses = nil
|
17
17
|
super
|
@@ -19,10 +19,14 @@ class Worksheet < Spreadsheet::Worksheet
|
|
19
19
|
@dimensions = nil
|
20
20
|
@links = {}
|
21
21
|
@guts = {}
|
22
|
+
@notes = {}
|
22
23
|
end
|
23
24
|
def add_link row, column, link
|
24
25
|
@links.store [row, column], link
|
25
26
|
end
|
27
|
+
def add_note row, column, note
|
28
|
+
@notes.store [row, column], note
|
29
|
+
end
|
26
30
|
def column idx
|
27
31
|
ensure_rows_read
|
28
32
|
super
|
data/spreadsheet.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "spreadsheet"
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.9.2"
|
4
4
|
s.summary = "The Spreadsheet Library is designed to read and write Spreadsheet Documents"
|
5
5
|
s.description = "As of version 0.6.0, only Microsoft Excel compatible spreadsheets are supported"
|
6
6
|
s.author = "Masaomi Hatakeyama, Zeno R.R. Davatz"
|
data/test/integration.rb
CHANGED
@@ -1280,6 +1280,13 @@ module Spreadsheet
|
|
1280
1280
|
temp_file.unlink
|
1281
1281
|
end
|
1282
1282
|
|
1283
|
+
def test_andre
|
1284
|
+
path = File.join @data, 'test_comment.xls'
|
1285
|
+
book = Spreadsheet.open path
|
1286
|
+
assert_instance_of Excel::Workbook, book
|
1287
|
+
sheet = book.worksheet 0
|
1288
|
+
sheet.ensure_rows_read
|
1289
|
+
end
|
1283
1290
|
def test_read_pagesetup
|
1284
1291
|
path = File.join @data, 'test_pagesetup.xls'
|
1285
1292
|
book = Spreadsheet.open path
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spreadsheet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ruby-ole
|