ruby-spreadsheet 0.6.5
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.
- data/.document +5 -0
- data/GUIDE.txt +267 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +20 -0
- data/History.txt +307 -0
- data/LICENSE.txt +619 -0
- data/README.txt +91 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/xlsopcodes +18 -0
- data/lib/parseexcel.rb +27 -0
- data/lib/parseexcel/parseexcel.rb +75 -0
- data/lib/parseexcel/parser.rb +11 -0
- data/lib/spreadsheet.rb +79 -0
- data/lib/spreadsheet/column.rb +71 -0
- data/lib/spreadsheet/compatibility.rb +23 -0
- data/lib/spreadsheet/datatypes.rb +110 -0
- data/lib/spreadsheet/encodings.rb +46 -0
- data/lib/spreadsheet/excel.rb +88 -0
- data/lib/spreadsheet/excel/error.rb +26 -0
- data/lib/spreadsheet/excel/internals.rb +386 -0
- data/lib/spreadsheet/excel/internals/biff5.rb +17 -0
- data/lib/spreadsheet/excel/internals/biff8.rb +19 -0
- data/lib/spreadsheet/excel/offset.rb +41 -0
- data/lib/spreadsheet/excel/reader.rb +1173 -0
- data/lib/spreadsheet/excel/reader/biff5.rb +22 -0
- data/lib/spreadsheet/excel/reader/biff8.rb +193 -0
- data/lib/spreadsheet/excel/row.rb +92 -0
- data/lib/spreadsheet/excel/sst_entry.rb +46 -0
- data/lib/spreadsheet/excel/workbook.rb +80 -0
- data/lib/spreadsheet/excel/worksheet.rb +100 -0
- data/lib/spreadsheet/excel/writer.rb +1 -0
- data/lib/spreadsheet/excel/writer/biff8.rb +75 -0
- data/lib/spreadsheet/excel/writer/format.rb +253 -0
- data/lib/spreadsheet/excel/writer/workbook.rb +652 -0
- data/lib/spreadsheet/excel/writer/worksheet.rb +948 -0
- data/lib/spreadsheet/font.rb +92 -0
- data/lib/spreadsheet/format.rb +177 -0
- data/lib/spreadsheet/formula.rb +9 -0
- data/lib/spreadsheet/helpers.rb +11 -0
- data/lib/spreadsheet/link.rb +43 -0
- data/lib/spreadsheet/row.rb +132 -0
- data/lib/spreadsheet/workbook.rb +120 -0
- data/lib/spreadsheet/worksheet.rb +279 -0
- data/lib/spreadsheet/writer.rb +30 -0
- data/ruby-spreadsheet.gemspec +126 -0
- data/test/data/test_changes.xls +0 -0
- data/test/data/test_copy.xls +0 -0
- data/test/data/test_datetime.xls +0 -0
- data/test/data/test_empty.xls +0 -0
- data/test/data/test_formula.xls +0 -0
- data/test/data/test_missing_row.xls +0 -0
- data/test/data/test_version_excel5.xls +0 -0
- data/test/data/test_version_excel95.xls +0 -0
- data/test/data/test_version_excel97.xls +0 -0
- data/test/excel/row.rb +35 -0
- data/test/excel/writer/worksheet.rb +23 -0
- data/test/font.rb +163 -0
- data/test/integration.rb +1281 -0
- data/test/row.rb +33 -0
- data/test/suite.rb +14 -0
- data/test/workbook.rb +21 -0
- data/test/worksheet.rb +80 -0
- metadata +203 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'spreadsheet/compatibility'
|
2
|
+
|
3
|
+
module Spreadsheet
|
4
|
+
##
|
5
|
+
# This module defines convenience-methods for the definition of Spreadsheet
|
6
|
+
# attributes (boolean, colors and enumerations)
|
7
|
+
module Datatypes
|
8
|
+
include Compatibility
|
9
|
+
def Datatypes.append_features mod
|
10
|
+
super
|
11
|
+
mod.module_eval do
|
12
|
+
class << self
|
13
|
+
##
|
14
|
+
# Valid colors for color attributes.
|
15
|
+
COLORS = [ :builtin_black, :builtin_white, :builtin_red, :builtin_green,
|
16
|
+
:builtin_blue, :builtin_yellow, :builtin_magenta, :builtin_cyan,
|
17
|
+
:black, :white, :olive, :teal, :violet, :burgundy, :cream,
|
18
|
+
:light_cyan, :dark_purple, :dark_blue, :lavender, :red, :lime,
|
19
|
+
:blue, :yellow, :magenta, :cyan, :brown, :green, :navy, :silver,
|
20
|
+
:gray, :orange, :purple, :sky_blue, :sea_green, :canary_yellow,
|
21
|
+
:cornflower, :pink, :fuchsia, :peach, :medium_blue, :turquoise,
|
22
|
+
:yellow_green, :yellow_orange, :burnt_orange, :red_orange,
|
23
|
+
:dark_violet, :dark_gray, :midnight_blue, :border, :pattern_bg,
|
24
|
+
:dialog_bg, :chart_text, :chart_bg, :chart_border, :tooltip_bg,
|
25
|
+
:tooltip_text, :text, :aqua, :grey]
|
26
|
+
|
27
|
+
##
|
28
|
+
# Define instance methods to read and write boolean attributes.
|
29
|
+
def boolean *args
|
30
|
+
args.each do |key|
|
31
|
+
define_method key do
|
32
|
+
name = ivar_name key
|
33
|
+
!!(instance_variable_get(name) if instance_variables.include?(name))
|
34
|
+
end
|
35
|
+
define_method "#{key}?" do
|
36
|
+
send key
|
37
|
+
end
|
38
|
+
define_method "#{key}=" do |arg|
|
39
|
+
arg = false if arg == 0
|
40
|
+
instance_variable_set(ivar_name(key), !!arg)
|
41
|
+
end
|
42
|
+
define_method "#{key}!" do
|
43
|
+
send "#{key}=", true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
##
|
48
|
+
# Define instance methods to read and write color attributes.
|
49
|
+
# For valid colors see COLORS
|
50
|
+
def colors *args
|
51
|
+
args.each do |key|
|
52
|
+
attr_reader key
|
53
|
+
define_method "#{key}=" do |name|
|
54
|
+
name = name.to_s.downcase.to_sym
|
55
|
+
if COLORS.include?(name)
|
56
|
+
instance_variable_set ivar_name(key), name
|
57
|
+
else
|
58
|
+
raise ArgumentError, "unknown color '#{name}'"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
##
|
64
|
+
# Define instance methods to read and write enumeration attributes.
|
65
|
+
# * The first argument designates the attribute name.
|
66
|
+
# * The second argument designates the default value.
|
67
|
+
# * All subsequent attributes are possible values.
|
68
|
+
# * If the last attribute is a Hash, each value in the Hash designates
|
69
|
+
# aliases for the corresponding key.
|
70
|
+
def enum key, *values
|
71
|
+
aliases = {}
|
72
|
+
if values.last.is_a? Hash
|
73
|
+
values.pop.each do |value, synonyms|
|
74
|
+
if synonyms.is_a? Array
|
75
|
+
synonyms.each do |synonym| aliases.store synonym, value end
|
76
|
+
else
|
77
|
+
aliases.store synonyms, value
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
values.each do |value|
|
82
|
+
aliases.store value, value
|
83
|
+
end
|
84
|
+
define_method key do
|
85
|
+
name = ivar_name key
|
86
|
+
value = instance_variable_get(name) if instance_variables.include? name
|
87
|
+
value || values.first
|
88
|
+
end
|
89
|
+
define_method "#{key}=" do |arg|
|
90
|
+
if arg
|
91
|
+
arg = aliases.fetch arg do
|
92
|
+
aliases.fetch arg.to_s.downcase.gsub(/[ \-]/, '_').to_sym, arg
|
93
|
+
end
|
94
|
+
if values.any? do |val| val === arg end
|
95
|
+
instance_variable_set(ivar_name(key), arg)
|
96
|
+
else
|
97
|
+
valid = values.collect do |val| val.inspect end.join ', '
|
98
|
+
raise ArgumentError,
|
99
|
+
"Invalid value '#{arg.inspect}' for #{key}. Valid values are: #{valid}"
|
100
|
+
end
|
101
|
+
else
|
102
|
+
instance_variable_set ivar_name(key), values.first
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Spreadsheet
|
2
|
+
##
|
3
|
+
# Methods for Encoding-conversions. You should not need to use any of these.
|
4
|
+
module Encodings
|
5
|
+
if RUBY_VERSION >= '1.9'
|
6
|
+
def client string, internal='UTF-16LE'
|
7
|
+
string.force_encoding internal
|
8
|
+
string.encode Spreadsheet.client_encoding
|
9
|
+
end
|
10
|
+
def internal string, client=Spreadsheet.client_encoding
|
11
|
+
string.force_encoding client
|
12
|
+
string.encode('UTF-16LE').force_encoding('ASCII-8BIT')
|
13
|
+
end
|
14
|
+
def utf8 string, client=Spreadsheet.client_encoding
|
15
|
+
string.force_encoding client
|
16
|
+
string.encode('UTF-8')
|
17
|
+
end
|
18
|
+
else
|
19
|
+
require 'iconv'
|
20
|
+
@@iconvs = {}
|
21
|
+
def client string, internal='UTF-16LE'
|
22
|
+
key = [Spreadsheet.client_encoding, internal]
|
23
|
+
iconv = @@iconvs[key] ||= Iconv.new(Spreadsheet.client_encoding, internal)
|
24
|
+
iconv.iconv string
|
25
|
+
end
|
26
|
+
def internal string, client=Spreadsheet.client_encoding
|
27
|
+
key = ['UTF-16LE', client]
|
28
|
+
iconv = @@iconvs[key] ||= Iconv.new('UTF-16LE', client)
|
29
|
+
iconv.iconv string
|
30
|
+
end
|
31
|
+
def utf8 string, client=Spreadsheet.client_encoding
|
32
|
+
key = ['UTF-8', client]
|
33
|
+
iconv = @@iconvs[key] ||= Iconv.new('UTF-8', client)
|
34
|
+
iconv.iconv string
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
warn "You don't have Iconv support compiled in your Ruby. Spreadsheet may not work as expected"
|
39
|
+
def client string, internal='UTF-16LE'
|
40
|
+
string.delete "\0"
|
41
|
+
end
|
42
|
+
def internal string, internal='UTF-16LE'
|
43
|
+
string.split('').zip(Array.new(string.size, 0.chr)).join
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spreadsheet'
|
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
|
+
##
|
10
|
+
# Spreadsheet::Excel Compatibility Layer.
|
11
|
+
# Drop-in replacement for Spreadsheet::Excel version <= 0.3.5.1
|
12
|
+
module Spreadsheet
|
13
|
+
module Excel
|
14
|
+
class ExcelCompatibleWorkbook < Workbook
|
15
|
+
def initialize file_path, *args
|
16
|
+
super *args
|
17
|
+
@file_path = file_path
|
18
|
+
end
|
19
|
+
def close
|
20
|
+
write @file_path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
def Excel.new file_path
|
24
|
+
ExcelCompatibleWorkbook.new file_path
|
25
|
+
end
|
26
|
+
class Workbook
|
27
|
+
def add_worksheet name
|
28
|
+
if name.is_a? String
|
29
|
+
create_worksheet :name => name
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
class Worksheet
|
37
|
+
unless instance_methods.include? "new_format_column"
|
38
|
+
alias :new_format_column :format_column
|
39
|
+
def format_column column, width=nil, format=nil
|
40
|
+
if width.is_a? Format
|
41
|
+
new_format_column column, width, format
|
42
|
+
else
|
43
|
+
new_format_column column, format, :width => width
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def write row, col, data=nil, format=nil
|
48
|
+
if data.is_a? Array
|
49
|
+
write_row row, col, data, format
|
50
|
+
else
|
51
|
+
row = row(row)
|
52
|
+
row[col] = data
|
53
|
+
row.set_format col, format
|
54
|
+
end
|
55
|
+
end
|
56
|
+
def write_column row, col, data=nil, format=nil
|
57
|
+
if data.is_a? Array
|
58
|
+
data.each do |token|
|
59
|
+
if token.is_a? Array
|
60
|
+
write_row row, col, token, format
|
61
|
+
else
|
62
|
+
write row, col, token, format
|
63
|
+
end
|
64
|
+
row += 1
|
65
|
+
end
|
66
|
+
else
|
67
|
+
write row, col, data, format
|
68
|
+
end
|
69
|
+
end
|
70
|
+
def write_row row, col, data=nil, format=nil
|
71
|
+
if data.is_a? Array
|
72
|
+
data.each do |token|
|
73
|
+
if token.is_a? Array
|
74
|
+
write_column row, col, token, format
|
75
|
+
else
|
76
|
+
write row, col, token, format
|
77
|
+
end
|
78
|
+
col += 1
|
79
|
+
end
|
80
|
+
else
|
81
|
+
write row, col, data, format
|
82
|
+
end
|
83
|
+
end
|
84
|
+
def write_url row, col, url, string=url, format=nil
|
85
|
+
row(row)[col] = Link.new url, string
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spreadsheet
|
2
|
+
module Excel
|
3
|
+
##
|
4
|
+
# This class encapsulates Excel Error-Codes
|
5
|
+
class Error
|
6
|
+
attr_reader :code
|
7
|
+
ERROR_VALUES = {
|
8
|
+
0x00 => '#NULL!', # Intersection of two cell ranges is empty
|
9
|
+
0x07 => '#DIV/0!', # Division by zero
|
10
|
+
0x0F => '#VALUE!', # Wrong type of operand
|
11
|
+
0x17 => '#REF!', # Illegal or deleted cell reference
|
12
|
+
0x1D => '#NAME?', # Wrong function or range name
|
13
|
+
0x24 => '#NUM!', # Value range overflow
|
14
|
+
0x2A => '#N/A!', # Argument or function not available
|
15
|
+
}
|
16
|
+
def initialize code
|
17
|
+
@code = code
|
18
|
+
end
|
19
|
+
##
|
20
|
+
# The String value Excel associates with an Error code
|
21
|
+
def value
|
22
|
+
ERROR_VALUES.fetch @code, '#UNKNOWN'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,386 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Spreadsheet
|
4
|
+
module Excel
|
5
|
+
##
|
6
|
+
# Binary Formats and other configurations internal to Excel. This Module is
|
7
|
+
# likely to shrink as Support for older Versions of Excel grows and more Binary
|
8
|
+
# formats are moved away from here for disambiguation.
|
9
|
+
# If you need to work with constants defined in this module and are confused by
|
10
|
+
# names like SEDOC_ROLOC, try reading them backwards. (The reason for this weird
|
11
|
+
# naming convention is that according to my ri, Ruby 1.9 renames Hash#index to
|
12
|
+
# Hash#key without backward compatibility. Since I did not want to pepper my code
|
13
|
+
# with RUBY_VERSION-checks, I settled on this strategy to make the transition to
|
14
|
+
# Ruby 1.9 as simple as possible.
|
15
|
+
module Internals
|
16
|
+
EIGHT_BYTE_DOUBLE = [0.1].pack('E').size == 8 ? 'E' : 'e'
|
17
|
+
CODEPAGES = {
|
18
|
+
367 => "ASCII",
|
19
|
+
437 => "IBM437", #(US)
|
20
|
+
720 => "IBM720", #(OEM Arabic)
|
21
|
+
737 => "IBM737", #(Greek)
|
22
|
+
775 => "IBM775", #(Baltic)
|
23
|
+
850 => "IBM850", #(Latin I)
|
24
|
+
852 => "IBM852", #(Latin II (Central European))
|
25
|
+
855 => "IBM855", #(Cyrillic)
|
26
|
+
857 => "IBM857", #(Turkish)
|
27
|
+
858 => "IBM858", #(Multilingual Latin I with Euro)
|
28
|
+
860 => "IBM860", #(Portuguese)
|
29
|
+
861 => "IBM861", #(Icelandic)
|
30
|
+
862 => "IBM862", #(Hebrew)
|
31
|
+
863 => "IBM863", #(Canadian (French))
|
32
|
+
864 => "IBM864", #(Arabic)
|
33
|
+
865 => "IBM865", #(Nordic)
|
34
|
+
866 => "IBM866", #(Cyrillic (Russian))
|
35
|
+
869 => "IBM869", #(Greek (Modern))
|
36
|
+
874 => "WINDOWS-874", #(Thai)
|
37
|
+
932 => "WINDOWS-932", #(Japanese Shift-JIS)
|
38
|
+
936 => "WINDOWS-936", #(Chinese Simplified GBK)
|
39
|
+
949 => "WINDOWS-949", #(Korean (Wansung))
|
40
|
+
950 => "WINDOWS-950", #(Chinese Traditional BIG5)
|
41
|
+
1200 => "UTF-16LE", #(BIFF8)
|
42
|
+
1250 => "WINDOWS-1250", #(Latin II) (Central European)
|
43
|
+
1251 => "WINDOWS-1251", #(Cyrillic)
|
44
|
+
1252 => "WINDOWS-1252", #(Latin I) (BIFF4-BIFF7)
|
45
|
+
1253 => "WINDOWS-1253", #(Greek)
|
46
|
+
1254 => "WINDOWS-1254", #(Turkish)
|
47
|
+
1255 => "WINDOWS-1255", #(Hebrew)
|
48
|
+
1256 => "WINDOWS-1256", #(Arabic)
|
49
|
+
1257 => "WINDOWS-1257", #(Baltic)
|
50
|
+
1258 => "WINDOWS-1258", #(Vietnamese)
|
51
|
+
1361 => "WINDOWS-1361", #(Korean (Johab))
|
52
|
+
10000 => "MACINTOSH",
|
53
|
+
32768 => "MACINTOSH",
|
54
|
+
32769 => "WINDOWS-1252", #(Latin I) (BIFF2-BIFF3)
|
55
|
+
}
|
56
|
+
SEGAPEDOC = CODEPAGES.invert
|
57
|
+
COLOR_CODES = {
|
58
|
+
0x0000 => :builtin_black,
|
59
|
+
0x0001 => :builtin_white,
|
60
|
+
0x0002 => :builtin_red,
|
61
|
+
0x0003 => :builtin_green,
|
62
|
+
0x0004 => :builtin_blue,
|
63
|
+
0x0005 => :builtin_yellow,
|
64
|
+
0x0006 => :builtin_magenta,
|
65
|
+
0x0007 => :builtin_cyan,
|
66
|
+
0x0008 => :black,
|
67
|
+
0x0009 => :white,
|
68
|
+
0x0013 => :olive,
|
69
|
+
0x0015 => :teal,
|
70
|
+
0x0018 => :violet,
|
71
|
+
0x0019 => :burgundy,
|
72
|
+
0x001A => :cream,
|
73
|
+
0x001B => :light_cyan,
|
74
|
+
0x001C => :dark_purple,
|
75
|
+
0x001E => :dark_blue,
|
76
|
+
0x001F => :lavender,
|
77
|
+
0x000a => :red,
|
78
|
+
0x000b => :lime,
|
79
|
+
0x000c => :blue,
|
80
|
+
0x000d => :yellow,
|
81
|
+
0x000e => :magenta,
|
82
|
+
0x000f => :cyan,
|
83
|
+
0x0010 => :brown,
|
84
|
+
0x0011 => :green,
|
85
|
+
0x0012 => :navy,
|
86
|
+
0x0013 => :olive,
|
87
|
+
0x0016 => :silver,
|
88
|
+
0x0017 => :gray,
|
89
|
+
0x001d => :orange,
|
90
|
+
0x0024 => :purple,
|
91
|
+
0x0029 => :sky_blue,
|
92
|
+
0x002A => :sea_green,
|
93
|
+
0x002b => :canary_yellow,
|
94
|
+
0x002c => :cornflower,
|
95
|
+
0x002D => :pink,
|
96
|
+
0x002E => :fuchsia,
|
97
|
+
0x002F => :peach,
|
98
|
+
0x0030 => :medium_blue,
|
99
|
+
0x0031 => :turquoise,
|
100
|
+
0x0032 => :yellow_green,
|
101
|
+
0x0033 => :yellow_orange,
|
102
|
+
0x0034 => :burnt_orange,
|
103
|
+
0x0035 => :red_orange,
|
104
|
+
0x0036 => :dark_violet,
|
105
|
+
0x0037 => :dark_gray,
|
106
|
+
0x0038 => :midnight_blue,
|
107
|
+
0x0040 => :border,
|
108
|
+
0x0041 => :pattern_bg,
|
109
|
+
0x0043 => :dialog_bg,
|
110
|
+
0x004d => :chart_text,
|
111
|
+
0x004e => :chart_bg,
|
112
|
+
0x004f => :chart_border,
|
113
|
+
0x0050 => :tooltip_bg,
|
114
|
+
0x0051 => :tooltip_text,
|
115
|
+
0x7fff => :text
|
116
|
+
}
|
117
|
+
SEDOC_ROLOC = COLOR_CODES.invert.update( :aqua => 0x000f,
|
118
|
+
:grey => 0x0017 )
|
119
|
+
BINARY_FORMATS = {
|
120
|
+
:blank => 'v3',
|
121
|
+
:boolerr => 'v3C2',
|
122
|
+
:colinfo => 'v5x2',
|
123
|
+
:font => 'v5C3x',
|
124
|
+
:labelsst => 'v3V',
|
125
|
+
:number => "v3#{EIGHT_BYTE_DOUBLE}",
|
126
|
+
:pagesetup => "v8#{EIGHT_BYTE_DOUBLE}2v",
|
127
|
+
:rk => 'v3V',
|
128
|
+
:row => 'v4x4V',
|
129
|
+
:window2 => 'v4x2v2x4',
|
130
|
+
:xf => 'v3C4V2v',
|
131
|
+
}
|
132
|
+
# From BIFF5 on, the built-in number formats will be omitted. The built-in
|
133
|
+
# formats are dependent on the current regional settings of the operating
|
134
|
+
# system. The following table shows which number formats are used by
|
135
|
+
# default in a US-English environment. All indexes from 0 to 163 are
|
136
|
+
# reserved for built-in formats.
|
137
|
+
BUILTIN_FORMATS = { # TODO: locale support
|
138
|
+
0 => 'GENERAL',
|
139
|
+
1 => '0',
|
140
|
+
2 => '0.00',
|
141
|
+
3 => '#,##0',
|
142
|
+
4 => '#,##0.00',
|
143
|
+
5 => '"$"#,##0_);("$"#,##0)',
|
144
|
+
6 => '"$"#,##0_);[Red]("$"#,##0)',
|
145
|
+
7 => '"$"#,##0.00_);("$"#,##0.00)',
|
146
|
+
8 => '"$"#,##0.00_);[Red]("$"#,##0.00)',
|
147
|
+
9 => '0%',
|
148
|
+
10 => '0.00%',
|
149
|
+
11 => '0.00E+00',
|
150
|
+
12 => '# ?/?',
|
151
|
+
13 => '# ??/??',
|
152
|
+
14 => 'M/D/YY',
|
153
|
+
15 => 'D-MMM-YY',
|
154
|
+
16 => 'D-MMM',
|
155
|
+
17 => 'MMM-YY',
|
156
|
+
18 => 'h:mm AM/PM',
|
157
|
+
19 => 'h:mm:ss AM/PM',
|
158
|
+
20 => 'h:mm',
|
159
|
+
21 => 'h:mm:ss',
|
160
|
+
22 => 'M/D/YY h:mm',
|
161
|
+
37 => '_(#,##0_);(#,##0)',
|
162
|
+
38 => '_(#,##0_);[Red](#,##0)',
|
163
|
+
39 => '_(#,##0.00_);(#,##0.00)',
|
164
|
+
40 => '_(#,##0.00_);[Red](#,##0.00)',
|
165
|
+
41 => '_("$"* #,##0_);_("$"* (#,##0);_("$"* "-"_);_(@_)',
|
166
|
+
42 => '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)',
|
167
|
+
43 => '_("$"* #,##0.00_);_("$"* (#,##0.00);_("$"* "-"??_);_(@_)',
|
168
|
+
44 => '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)',
|
169
|
+
45 => 'mm:ss',
|
170
|
+
46 => '[h]:mm:ss',
|
171
|
+
47 => 'mm:ss.0',
|
172
|
+
48 => '##0.0E+0',
|
173
|
+
49 => '@',
|
174
|
+
}
|
175
|
+
BUILTIN_STYLES = {
|
176
|
+
0x00 => 'Normal',
|
177
|
+
0x01 => 'RowLevel_lv',
|
178
|
+
0x02 => 'ColLevel_lv',
|
179
|
+
0x03 => 'Comma',
|
180
|
+
0x04 => 'Currency',
|
181
|
+
0x05 => 'Percent',
|
182
|
+
0x06 => 'Comma',
|
183
|
+
0x07 => 'Currency',
|
184
|
+
0x08 => 'Hyperlink',
|
185
|
+
0x09 => 'Followed Hyperlink',
|
186
|
+
}
|
187
|
+
ESCAPEMENT_TYPES = {
|
188
|
+
0x0001 => :superscript,
|
189
|
+
0x0002 => :subscript,
|
190
|
+
}
|
191
|
+
SEPYT_TNEMEPACSE = ESCAPEMENT_TYPES.invert
|
192
|
+
FONT_ENCODINGS = {
|
193
|
+
0x00 => :iso_latin1,
|
194
|
+
0x01 => :default,
|
195
|
+
0x02 => :symbol,
|
196
|
+
0x4d => :apple_roman,
|
197
|
+
0x80 => :shift_jis,
|
198
|
+
0x81 => :korean_hangul,
|
199
|
+
0x82 => :korean_johab,
|
200
|
+
0x86 => :chinese_simplified,
|
201
|
+
0x88 => :chinese_traditional,
|
202
|
+
0xa1 => :greek,
|
203
|
+
0xa2 => :turkish,
|
204
|
+
0xa3 => :vietnamese,
|
205
|
+
0xb1 => :hebrew,
|
206
|
+
0xb2 => :arabic,
|
207
|
+
0xba => :baltic,
|
208
|
+
0xcc => :cyrillic,
|
209
|
+
0xde => :thai,
|
210
|
+
0xee => :iso_latin2,
|
211
|
+
0xff => :oem_latin1,
|
212
|
+
}
|
213
|
+
SGNIDOCNE_TNOF = FONT_ENCODINGS.invert
|
214
|
+
FONT_FAMILIES = {
|
215
|
+
0x01 => :roman,
|
216
|
+
0x02 => :swiss,
|
217
|
+
0x03 => :modern,
|
218
|
+
0x04 => :script,
|
219
|
+
0x05 => :decorative,
|
220
|
+
}
|
221
|
+
SEILIMAF_TNOF = FONT_FAMILIES.invert
|
222
|
+
FONT_WEIGHTS = {
|
223
|
+
:bold => 700,
|
224
|
+
:normal => 400,
|
225
|
+
}
|
226
|
+
LEAP_ERROR = Date.new 1900, 2, 28
|
227
|
+
OPCODES = {
|
228
|
+
:blank => 0x0201, # BLANK ➜ 6.7
|
229
|
+
:boolerr => 0x0205, # BOOLERR ➜ 6.10
|
230
|
+
:boundsheet => 0x0085, # ●● BOUNDSHEET ➜ 6.12
|
231
|
+
:codepage => 0x0042, # ○ CODEPAGE ➜ 6.17
|
232
|
+
:colinfo => 0x007d, # ○○ COLINFO ➜ 6.18
|
233
|
+
:continue => 0x003c, # ○ CONTINUE ➜ 6.22
|
234
|
+
:datemode => 0x0022, # ○ DATEMODE ➜ 6.25
|
235
|
+
:dbcell => 0x0a0b, # ○ DBCELL
|
236
|
+
:dimensions => 0x0200, # ● DIMENSIONS ➜ 6.31
|
237
|
+
:eof => 0x000a, # ● EOF ➜ 6.36
|
238
|
+
:font => 0x0031, # ●● FONT ➜ 6.43
|
239
|
+
:format => 0x041e, # ○○ FORMAT (Number Format) ➜ 6.45
|
240
|
+
:formula => 0x0006, # FORMULA ➜ 6.46
|
241
|
+
:hlink => 0x01b8, # HLINK ➜ 6.52 (BIFF8 only)
|
242
|
+
:label => 0x0204, # LABEL ➜ 6.59 (BIFF2-BIFF7)
|
243
|
+
:labelsst => 0x00fd, # LABELSST ➜ 6.61 (BIFF8 only)
|
244
|
+
:mulblank => 0x00be, # MULBLANK ➜ 6.64 (BIFF5-BIFF8)
|
245
|
+
:mulrk => 0x00bd, # MULRK ➜ 6.65 (BIFF5-BIFF8)
|
246
|
+
:number => 0x0203, # NUMBER ➜ 6.68
|
247
|
+
:rk => 0x027e, # RK ➜ 6.82 (BIFF3-BIFF8)
|
248
|
+
:row => 0x0208, # ● ROW ➜ 6.83
|
249
|
+
:rstring => 0x00d6, # RSTRING ➜ 6.84 (BIFF5/BIFF7)
|
250
|
+
:sst => 0x00fc, # ● SST ➜ 6.96
|
251
|
+
:string => 0x0207, # STRING ➜ 6.98
|
252
|
+
:style => 0x0293, # ●● STYLE ➜ 6.99
|
253
|
+
:xf => 0x00e0, # ●● XF ➜ 6.115
|
254
|
+
:sharedfmla => 0x04bc, # SHAREDFMLA ➜ 5.94
|
255
|
+
########################## Unhandled Opcodes ################################
|
256
|
+
:extsst => 0x00ff, # ● EXTSST ➜ 6.40
|
257
|
+
:index => 0x020b, # ○ INDEX ➜ 5.7 (Row Blocks), ➜ 6.55
|
258
|
+
:uncalced => 0x005e, # ○ UNCALCED ➜ 6.104
|
259
|
+
########################## ○ Calculation Settings Block ➜ 5.3
|
260
|
+
:calccount => 0x000c, # ○ CALCCOUNT ➜ 6.14
|
261
|
+
:calcmode => 0x000d, # ○ CALCMODE ➜ 6.15
|
262
|
+
:precision => 0x000e, # ○ PRECISION ➜ 6.74 (moved to Workbook Globals
|
263
|
+
# Substream in BIFF5-BIFF8)
|
264
|
+
:refmode => 0x000f, # ○ REFMODE ➜ 6.80
|
265
|
+
:delta => 0x0010, # ○ DELTA ➜ 6.30
|
266
|
+
:iteration => 0x0011, # ○ ITERATION ➜ 6.57
|
267
|
+
:saverecalc => 0x005f, # ○ SAVERECALC ➜ 6.85 (BIFF3-BIFF8 only)
|
268
|
+
########################## ○ Workbook Protection Block ➜ 5.18
|
269
|
+
:protect => 0x0012, # ○ PROTECT
|
270
|
+
# Worksheet contents: 1 = protected (➜ 6.77)
|
271
|
+
:windowprot => 0x0019, # ○ WINDOWPROTECT Window settings: 1 = protected
|
272
|
+
# (BIFF4W only, ➜ 6.110)
|
273
|
+
:objectprot => 0x0063, # ○ OBJECTPROTECT
|
274
|
+
# Embedded objects: 1 = protected (➜ 6.69)
|
275
|
+
:scenprotect => 0x00dd, # ○ SCENPROTECT
|
276
|
+
# Scenarios: 1 = protected (BIFF5-BIFF8, ➜ 6.86)
|
277
|
+
:password => 0x0013, # ○ PASSWORD Hash value of the password;
|
278
|
+
# 0 = no password (➜ 6.72)
|
279
|
+
########################## ○ File Protection Block ➜ 5.19
|
280
|
+
:writeprot => 0x0086, # ○ WRITEPROT File is write protected
|
281
|
+
# (BIFF3-BIFF8, ➜ 6.112), password in FILESHARING
|
282
|
+
:filepass => 0x002f, # ○ FILEPASS File is read/write-protected,
|
283
|
+
# encryption information (➜ 6.41)
|
284
|
+
:writeaccess => 0x005c, # ○ WRITEACCESS User name (BIFF3-BIFF8, ➜ 6.111)
|
285
|
+
:filesharing => 0x005b, # ○ FILESHARING File sharing options
|
286
|
+
# (BIFF3-BIFF8, ➜ 6.42)
|
287
|
+
########################## ○ Link Table ➜ 5.10.3
|
288
|
+
# ●● SUPBOOK Block(s)
|
289
|
+
# Settings for a referenced document
|
290
|
+
:supbook => 0x01ae, # ● SUPBOOK ➜ 6.100
|
291
|
+
:externname => 0x0223, # ○○ EXTERNNAME ➜ 6.38
|
292
|
+
:xct => 0x0059, # ○○ ● XCT ➜ 6.114
|
293
|
+
:crn => 0x005a, # ●● CRN ➜ 6.24
|
294
|
+
:externsheet => 0x0017, # ● EXTERNSHEET ➜ 6.39
|
295
|
+
:name => 0x0218, # ○○ NAME ➜ 6.66
|
296
|
+
##########################
|
297
|
+
:window1 => 0x003d, # ● WINDOW1 ➜ 6.108 (has information on
|
298
|
+
# which Spreadsheet is 'active')
|
299
|
+
:backup => 0x0040, # ○ BACKUP ➜ 6.5
|
300
|
+
:country => 0x008c, # ○ COUNTRY (Make writeable?) ➜ 6.23
|
301
|
+
:hideobj => 0x008d, # ○ HIDEOBJ ➜ 6.52
|
302
|
+
:palette => 0x0092, # ○ PALETTE ➜ 6.70
|
303
|
+
:fngroupcnt => 0x009c, # ○ FNGROUPCOUNT
|
304
|
+
:bookbool => 0x00da, # ○ BOOKBOOL ➜ 6.9
|
305
|
+
:tabid => 0x013d, # ○ TABID
|
306
|
+
:useselfs => 0x0160, # ○ USESELFS (Natural Language Formulas) ➜ 6.105
|
307
|
+
:dsf => 0x0161, # ○ DSF (Double Stream File) ➜ 6.32
|
308
|
+
:refreshall => 0x01b7, # ○ REFRESHALL
|
309
|
+
########################## ● Worksheet View Settings Block ➜ 5.5
|
310
|
+
:window2 => 0x023e, # ● WINDOW2 ➜ 5.110
|
311
|
+
:scl => 0x00a0, # ○ SCL ➜ 5.92 (BIFF4-BIFF8 only)
|
312
|
+
:pane => 0x0041, # ○ PANE ➜ 5.75
|
313
|
+
:selection => 0x001d, # ○○ SELECTION ➜ 5.93
|
314
|
+
########################## ○ Page Settings Block ➜ 5.4
|
315
|
+
:hpagebreaks => 0x001b, # ○ HORIZONTALPAGEBREAKS ➜ 6.54
|
316
|
+
:vpagebreaks => 0x001a, # ○ VERTICALPAGEBREAKS ➜ 6.107
|
317
|
+
:header => 0x0014, # ○ HEADER ➜ 6.51
|
318
|
+
:footer => 0x0015, # ○ FOOTER ➜ 6.44
|
319
|
+
:hcenter => 0x0083, # ○ HCENTER ➜ 6.50 (BIFF3-BIFF8 only)
|
320
|
+
:vcenter => 0x0084, # ○ VCENTER ➜ 6.106 (BIFF3-BIFF8 only)
|
321
|
+
:leftmargin => 0x0026, # ○ LEFTMARGIN ➜ 6.62
|
322
|
+
:rightmargin => 0x0027, # ○ RIGHTMARGIN ➜ 6.81
|
323
|
+
:topmargin => 0x0028, # ○ TOPMARGIN ➜ 6.103
|
324
|
+
:bottommargin => 0x0029, # ○ BOTTOMMARGIN ➜ 6.11
|
325
|
+
# ○ PLS (opcode unknown)
|
326
|
+
:pagesetup => 0x00a1, # ○ PAGESETUP ➜ 6.89 (BIFF4-BIFF8 only)
|
327
|
+
:bitmap => 0x00e9, # ○ BITMAP ➜ 6.6 (Background-Bitmap, BIFF8 only)
|
328
|
+
##########################
|
329
|
+
:printheaders => 0x002a, # ○ PRINTHEADERS ➜ 6.76
|
330
|
+
:printgridlns => 0x002b, # ○ PRINTGRIDLINES ➜ 6.75
|
331
|
+
:gridset => 0x0082, # ○ GRIDSET ➜ 6.48
|
332
|
+
:guts => 0x0080, # ○ GUTS ➜ 6.49
|
333
|
+
:defrowheight => 0x0225, # ○ DEFAULTROWHEIGHT ➜ 6.28
|
334
|
+
:wsbool => 0x0081, # ○ WSBOOL ➜ 6.113
|
335
|
+
:defcolwidth => 0x0055, # ○ DEFCOLWIDTH ➜ 6.29
|
336
|
+
:sort => 0x0090, # ○ SORT ➜ 6.95
|
337
|
+
}
|
338
|
+
=begin ## unknown opcodes
|
339
|
+
0x00bf, 0x00c0, 0x00c1, 0x00e1, 0x00e2, 0x00eb, 0x01af, 0x01bc
|
340
|
+
=end
|
341
|
+
SEDOCPO = OPCODES.invert
|
342
|
+
TWIPS = 20
|
343
|
+
UNDERLINE_TYPES = {
|
344
|
+
0x0001 => :single,
|
345
|
+
0x0002 => :double,
|
346
|
+
0x0021 => :single_accounting,
|
347
|
+
0x0022 => :double_accounting,
|
348
|
+
}
|
349
|
+
SEPYT_ENILREDNU = UNDERLINE_TYPES.invert
|
350
|
+
XF_H_ALIGN = {
|
351
|
+
:default => 0,
|
352
|
+
:left => 1,
|
353
|
+
:center => 2,
|
354
|
+
:right => 3,
|
355
|
+
:fill => 4,
|
356
|
+
:justify => 5,
|
357
|
+
:merge => 6,
|
358
|
+
:distributed => 7,
|
359
|
+
}
|
360
|
+
NGILA_H_FX = XF_H_ALIGN.invert
|
361
|
+
XF_TEXT_DIRECTION = {
|
362
|
+
:context => 0,
|
363
|
+
:left_to_right => 1,
|
364
|
+
:right_to_left => 2,
|
365
|
+
}
|
366
|
+
NOITCERID_TXET_FX = XF_TEXT_DIRECTION.invert
|
367
|
+
XF_V_ALIGN = {
|
368
|
+
:top => 0,
|
369
|
+
:middle => 1,
|
370
|
+
:bottom => 2,
|
371
|
+
:justify => 3,
|
372
|
+
:distributed => 4,
|
373
|
+
}
|
374
|
+
NGILA_V_FX = XF_V_ALIGN.invert
|
375
|
+
OPCODE_SIZE = 4
|
376
|
+
ROW_HEIGHT = 12.1
|
377
|
+
SST_CHUNKSIZE = 20
|
378
|
+
def binfmt key
|
379
|
+
BINARY_FORMATS[key]
|
380
|
+
end
|
381
|
+
def opcode key
|
382
|
+
OPCODES[key]
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|