keeguon-spreadsheet 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +619 -0
- data/Manifest.txt +85 -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 +80 -0
- data/lib/spreadsheet/column.rb +71 -0
- data/lib/spreadsheet/compatibility.rb +23 -0
- data/lib/spreadsheet/datatypes.rb +161 -0
- data/lib/spreadsheet/encodings.rb +57 -0
- data/lib/spreadsheet/excel.rb +88 -0
- data/lib/spreadsheet/excel/error.rb +26 -0
- data/lib/spreadsheet/excel/internals.rb +458 -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/password_hash.rb +24 -0
- data/lib/spreadsheet/excel/reader.rb +1302 -0
- data/lib/spreadsheet/excel/reader/biff5.rb +42 -0
- data/lib/spreadsheet/excel/reader/biff8.rb +231 -0
- data/lib/spreadsheet/excel/rgb.rb +122 -0
- data/lib/spreadsheet/excel/row.rb +98 -0
- data/lib/spreadsheet/excel/sst_entry.rb +46 -0
- data/lib/spreadsheet/excel/workbook.rb +80 -0
- data/lib/spreadsheet/excel/worksheet.rb +115 -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 +264 -0
- data/lib/spreadsheet/excel/writer/n_worksheet.rb +888 -0
- data/lib/spreadsheet/excel/writer/workbook.rb +735 -0
- data/lib/spreadsheet/excel/writer/worksheet.rb +940 -0
- data/lib/spreadsheet/font.rb +115 -0
- data/lib/spreadsheet/format.rb +209 -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/note.rb +23 -0
- data/lib/spreadsheet/noteObject.rb +17 -0
- data/lib/spreadsheet/row.rb +151 -0
- data/lib/spreadsheet/workbook.rb +143 -0
- data/lib/spreadsheet/worksheet.rb +326 -0
- data/lib/spreadsheet/writer.rb +30 -0
- data/test/data/test_adding_data_to_existing_file.xls +0 -0
- data/test/data/test_borders.xls +0 -0
- data/test/data/test_changes.xls +0 -0
- data/test/data/test_comment.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_long_sst_record.xls +0 -0
- data/test/data/test_margin.xls +0 -0
- data/test/data/test_merged_and_protected.xls +0 -0
- data/test/data/test_merged_cells.xls +0 -0
- data/test/data/test_missing_row.xls +0 -0
- data/test/data/test_pagesetup.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/data/test_version_excel97_2010.xls +0 -0
- data/test/data/test_worksheet_visibility.xls +0 -0
- data/test/excel/reader.rb +30 -0
- data/test/excel/row.rb +40 -0
- data/test/excel/writer/workbook.rb +95 -0
- data/test/excel/writer/worksheet.rb +81 -0
- data/test/font.rb +163 -0
- data/test/format.rb +95 -0
- data/test/integration.rb +1390 -0
- data/test/row.rb +33 -0
- data/test/suite.rb +18 -0
- data/test/workbook.rb +55 -0
- data/test/workbook_protection.rb +19 -0
- data/test/worksheet.rb +112 -0
- metadata +148 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spreadsheet/encodings'
|
2
|
+
|
3
|
+
module Spreadsheet
|
4
|
+
module Excel
|
5
|
+
##
|
6
|
+
# Shared String Table Entry
|
7
|
+
class SstEntry
|
8
|
+
include Spreadsheet::Encodings
|
9
|
+
attr_accessor :chars, :phonetic, :richtext, :flags, :available,
|
10
|
+
:continued_chars, :wide
|
11
|
+
def initialize opts = {}
|
12
|
+
@content = nil
|
13
|
+
@offset = opts[:offset]
|
14
|
+
@ole = opts[:ole]
|
15
|
+
@reader = opts[:reader]
|
16
|
+
@continuations = []
|
17
|
+
end
|
18
|
+
##
|
19
|
+
# Access the contents of this Shared String
|
20
|
+
def content
|
21
|
+
@content or begin
|
22
|
+
data = nil
|
23
|
+
data = @ole[@offset, @available]
|
24
|
+
content, _ = @reader.read_string_body data, @flags, @available, @wide
|
25
|
+
@continuations.each do |offset, len|
|
26
|
+
@reader.continue_string(@ole[offset,len], [content, @chars])
|
27
|
+
end
|
28
|
+
content = client content, 'UTF-16LE'
|
29
|
+
if @reader.memoize?
|
30
|
+
@content = content
|
31
|
+
end
|
32
|
+
content
|
33
|
+
end
|
34
|
+
end
|
35
|
+
##
|
36
|
+
# Register the offset of a String continuation
|
37
|
+
def continue offset, size, chars
|
38
|
+
@continued_chars -= chars
|
39
|
+
@continuations.push [offset, size]
|
40
|
+
end
|
41
|
+
def continued? # :nodoc:
|
42
|
+
@continued_chars > 0
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spreadsheet/workbook'
|
2
|
+
require 'spreadsheet/excel/offset'
|
3
|
+
require 'spreadsheet/excel/writer'
|
4
|
+
require 'ole/storage'
|
5
|
+
|
6
|
+
module Spreadsheet
|
7
|
+
module Excel
|
8
|
+
##
|
9
|
+
# Excel-specific Workbook methods. These are mostly pertinent to the Excel
|
10
|
+
# reader. You should have no reason to use any of these.
|
11
|
+
class Workbook < Spreadsheet::Workbook
|
12
|
+
include Spreadsheet::Encodings
|
13
|
+
include Spreadsheet::Excel::Offset
|
14
|
+
BIFF_VERSIONS = {
|
15
|
+
0x000 => 2,
|
16
|
+
0x007 => 2,
|
17
|
+
0x200 => 2,
|
18
|
+
0x300 => 3,
|
19
|
+
0x400 => 4,
|
20
|
+
0x500 => 5,
|
21
|
+
0x600 => 8,
|
22
|
+
}
|
23
|
+
VERSION_STRINGS = {
|
24
|
+
0x600 => 'Microsoft Excel 97/2000/XP',
|
25
|
+
0x500 => 'Microsoft Excel 95',
|
26
|
+
}
|
27
|
+
offset :encoding, :boundsheets, :sst
|
28
|
+
attr_accessor :bof, :ole
|
29
|
+
attr_writer :date_base
|
30
|
+
def Workbook.open io, opts = {}
|
31
|
+
@reader = Reader.new opts
|
32
|
+
@reader.read io
|
33
|
+
end
|
34
|
+
def initialize *args
|
35
|
+
super
|
36
|
+
enc = 'UTF-16LE'
|
37
|
+
if RUBY_VERSION >= '1.9'
|
38
|
+
enc = Encoding.find enc
|
39
|
+
end
|
40
|
+
@encoding = enc
|
41
|
+
@version = 0x600
|
42
|
+
@sst = []
|
43
|
+
end
|
44
|
+
def add_shared_string str
|
45
|
+
@sst.push str
|
46
|
+
end
|
47
|
+
def add_worksheet worksheet
|
48
|
+
@changes.store :boundsheets, true
|
49
|
+
super
|
50
|
+
end
|
51
|
+
def biff_version
|
52
|
+
case @bof
|
53
|
+
when 0x009
|
54
|
+
2
|
55
|
+
when 0x209
|
56
|
+
3
|
57
|
+
when 0x409
|
58
|
+
4
|
59
|
+
else
|
60
|
+
BIFF_VERSIONS.fetch(@version) { raise "Unkown BIFF_VERSION '#@version'" }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
def date_base
|
64
|
+
@date_base ||= DateTime.new 1899, 12, 31
|
65
|
+
end
|
66
|
+
def shared_string idx
|
67
|
+
@sst[idx.to_i].content
|
68
|
+
end
|
69
|
+
def sst_size
|
70
|
+
@sst.size
|
71
|
+
end
|
72
|
+
def uninspect_variables
|
73
|
+
super.push '@sst', '@offsets', '@changes'
|
74
|
+
end
|
75
|
+
def version_string
|
76
|
+
client VERSION_STRINGS.fetch(@version, "Unknown"), 'UTF-8'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spreadsheet/excel/offset'
|
2
|
+
require 'spreadsheet/excel/row'
|
3
|
+
require 'spreadsheet/worksheet'
|
4
|
+
|
5
|
+
module Spreadsheet
|
6
|
+
module Excel
|
7
|
+
##
|
8
|
+
# Excel-specific Worksheet methods. These are mostly pertinent to the Excel
|
9
|
+
# reader, and to recording changes to the Worksheet. You should have no reason
|
10
|
+
# to use any of these.
|
11
|
+
class Worksheet < Spreadsheet::Worksheet
|
12
|
+
include Spreadsheet::Excel::Offset
|
13
|
+
offset :dimensions
|
14
|
+
attr_reader :offset, :ole, :links, :guts, :notes
|
15
|
+
def initialize opts = {}
|
16
|
+
@row_addresses = nil
|
17
|
+
super
|
18
|
+
@offset, @ole, @reader = opts[:offset], opts[:ole], opts[:reader]
|
19
|
+
@dimensions = nil
|
20
|
+
@links = {}
|
21
|
+
@guts = {}
|
22
|
+
@notes = {}
|
23
|
+
end
|
24
|
+
def add_link row, column, link
|
25
|
+
@links.store [row, column], link
|
26
|
+
end
|
27
|
+
def add_note row, column, note
|
28
|
+
@notes.store [row, column], note
|
29
|
+
end
|
30
|
+
def column idx
|
31
|
+
ensure_rows_read
|
32
|
+
super
|
33
|
+
end
|
34
|
+
def date_base
|
35
|
+
@workbook.date_base
|
36
|
+
end
|
37
|
+
def margins
|
38
|
+
ensure_rows_read
|
39
|
+
super
|
40
|
+
end
|
41
|
+
def pagesetup
|
42
|
+
ensure_rows_read
|
43
|
+
super
|
44
|
+
end
|
45
|
+
def each *args
|
46
|
+
ensure_rows_read
|
47
|
+
super
|
48
|
+
end
|
49
|
+
def ensure_rows_read
|
50
|
+
return if @row_addresses
|
51
|
+
@dimensions = nil
|
52
|
+
@row_addresses = []
|
53
|
+
@reader.read_worksheet self, @offset if @reader
|
54
|
+
end
|
55
|
+
def row idx
|
56
|
+
@rows[idx] or begin
|
57
|
+
ensure_rows_read
|
58
|
+
if addr = @row_addresses[idx]
|
59
|
+
row = @reader.read_row self, addr
|
60
|
+
[:default_format, :height, :outline_level, :hidden, ].each do |key|
|
61
|
+
row.send "unupdated_#{key}=", addr[key]
|
62
|
+
end
|
63
|
+
row.worksheet = self
|
64
|
+
row
|
65
|
+
else
|
66
|
+
Row.new self, idx
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
def rows
|
71
|
+
self.to_a
|
72
|
+
end
|
73
|
+
def row_updated idx, row
|
74
|
+
res = super
|
75
|
+
@workbook.changes.store self, true
|
76
|
+
@workbook.changes.store :boundsheets, true
|
77
|
+
@changes.store idx, true
|
78
|
+
@changes.store :dimensions, true
|
79
|
+
res
|
80
|
+
end
|
81
|
+
def set_row_address idx, opts
|
82
|
+
@offsets.store idx, opts[:row_block]
|
83
|
+
@row_addresses[idx] = opts
|
84
|
+
end
|
85
|
+
def shared_string idx
|
86
|
+
@workbook.shared_string idx
|
87
|
+
end
|
88
|
+
private
|
89
|
+
## premature optimization?
|
90
|
+
def have_set_dimensions value, pos, len
|
91
|
+
if @row_addresses.size < row_count
|
92
|
+
@row_addresses.concat Array.new(row_count - @row_addresses.size)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
def recalculate_dimensions
|
96
|
+
ensure_rows_read
|
97
|
+
shorten @rows
|
98
|
+
@dimensions = []
|
99
|
+
@dimensions[0] = [ index_of_first(@rows),
|
100
|
+
index_of_first(@row_addresses) ].compact.min || 0
|
101
|
+
@dimensions[1] = [ @rows.size, @row_addresses.size ].compact.max || 0
|
102
|
+
compact = @rows.compact
|
103
|
+
first_rows = compact.collect do |row| row.first_used end.compact.min
|
104
|
+
first_addrs = @row_addresses.compact.collect do |addr|
|
105
|
+
addr[:first_used] end.min
|
106
|
+
@dimensions[2] = [ first_rows, first_addrs ].compact.min || 0
|
107
|
+
last_rows = compact.collect do |row| row.first_unused end.max
|
108
|
+
last_addrs = @row_addresses.compact.collect do |addr|
|
109
|
+
addr[:first_unused] end.max
|
110
|
+
@dimensions[3] = [last_rows, last_addrs].compact.max || 0
|
111
|
+
@dimensions
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'spreadsheet/excel/writer/workbook'
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spreadsheet/encodings'
|
2
|
+
|
3
|
+
module Spreadsheet
|
4
|
+
module Excel
|
5
|
+
module Writer
|
6
|
+
##
|
7
|
+
# This Module collects writer methods such as unicode_string that are specific
|
8
|
+
# to Biff8. This Module is likely to be expanded as Support for older Versions
|
9
|
+
# of Excel grows and methods get moved here for disambiguation.
|
10
|
+
module Biff8
|
11
|
+
include Spreadsheet::Encodings
|
12
|
+
##
|
13
|
+
# Check whether the string _data_ can be compressed (i.e. every second byte
|
14
|
+
# is a Null-byte) and perform compression.
|
15
|
+
# Returns the data and compression_status (0/1)
|
16
|
+
def compress_unicode_string data
|
17
|
+
compressed = internal('')
|
18
|
+
expect_null = false
|
19
|
+
data.each_byte do |byte|
|
20
|
+
if expect_null
|
21
|
+
if byte != 0
|
22
|
+
return [data, 1] # 1 => Data consists of wide Chars
|
23
|
+
end
|
24
|
+
expect_null = false
|
25
|
+
else
|
26
|
+
compressed << byte
|
27
|
+
expect_null = true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
[compressed, 0] # 0 => Data consists of compressed Chars
|
31
|
+
end
|
32
|
+
##
|
33
|
+
# Encode _string_ into a Biff8 Unicode String. Header and body are encoded
|
34
|
+
# separately by #_unicode_string. This method simply combines the two.
|
35
|
+
def unicode_string string, count_length=1
|
36
|
+
header, data, _ = _unicode_string string, count_length
|
37
|
+
header << data
|
38
|
+
end
|
39
|
+
@@bytesize = RUBY_VERSION >= '1.9' ? :bytesize : :size
|
40
|
+
##
|
41
|
+
# Encode _string_ into a Biff8 Unicode String Header and Body.
|
42
|
+
def _unicode_string string, count_length=1
|
43
|
+
data = internal string
|
44
|
+
size = data.send(@@bytesize) / 2
|
45
|
+
fmt = count_length == 1 ? 'C2' : 'vC'
|
46
|
+
data, wide = compress_unicode_string data
|
47
|
+
opts = wide
|
48
|
+
header = [
|
49
|
+
size, # Length of the string (character count, ln)
|
50
|
+
opts, # Option flags:
|
51
|
+
# Bit Mask Contents
|
52
|
+
# 0 0x01 Character compression (ccompr):
|
53
|
+
# 0 = Compressed (8-bit characters)
|
54
|
+
# 1 = Uncompressed (16-bit characters)
|
55
|
+
# 2 0x04 Asian phonetic settings (phonetic):
|
56
|
+
# 0 = Does not contain Asian phonetic settings
|
57
|
+
# 1 = Contains Asian phonetic settings
|
58
|
+
# 3 0x08 Rich-Text settings (richtext):
|
59
|
+
# 0 = Does not contain Rich-Text settings
|
60
|
+
# 1 = Contains Rich-Text settings
|
61
|
+
#0x00,# (optional, only if richtext=1) Number of Rich-Text
|
62
|
+
# formatting runs (rt)
|
63
|
+
#0x00,# (optional, only if phonetic=1) Size of Asian phonetic
|
64
|
+
# settings block (in bytes, sz)
|
65
|
+
].pack fmt
|
66
|
+
data << '' # (optional, only if richtext=1)
|
67
|
+
# List of rt formatting runs (➜ 3.2)
|
68
|
+
data << '' # (optional, only if phonetic=1)
|
69
|
+
# Asian Phonetic Settings Block (➜ 3.4.2)
|
70
|
+
[header, data, wide]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,264 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'spreadsheet/format'
|
3
|
+
require 'spreadsheet/excel/internals'
|
4
|
+
|
5
|
+
module Spreadsheet
|
6
|
+
module Excel
|
7
|
+
module Writer
|
8
|
+
##
|
9
|
+
# This class encapsulates everything that is needed to write an XF record.
|
10
|
+
class Format < DelegateClass Spreadsheet::Format
|
11
|
+
include Spreadsheet::Excel::Internals
|
12
|
+
def Format.boolean *args
|
13
|
+
args.each do |key|
|
14
|
+
define_method key do
|
15
|
+
@format.send("#{key}?") ? 1 : 0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
def Format.color key, default
|
20
|
+
define_method key do
|
21
|
+
color_code(@format.send(key) || default)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
def Format.line_style key, default
|
25
|
+
define_method key do
|
26
|
+
style_code(@format.send(key) || default)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
boolean :hidden, :locked, :merge_range, :shrink, :text_justlast, :text_wrap,
|
30
|
+
:cross_down, :cross_up
|
31
|
+
line_style :left, :none
|
32
|
+
line_style :right, :none
|
33
|
+
line_style :top, :none
|
34
|
+
line_style :bottom, :none
|
35
|
+
color :left_color, :black
|
36
|
+
color :right_color, :black
|
37
|
+
color :top_color, :black
|
38
|
+
color :bottom_color, :black
|
39
|
+
color :diagonal_color, :black
|
40
|
+
color :pattern_fg_color, :pattern_bg
|
41
|
+
color :pattern_bg_color, :pattern_bg
|
42
|
+
attr_reader :format
|
43
|
+
def initialize writer, workbook, format=workbook.default_format, opts={}
|
44
|
+
@opts = { :type => :format }.merge opts
|
45
|
+
@format = format
|
46
|
+
@writer = writer
|
47
|
+
@workbook = workbook
|
48
|
+
super format
|
49
|
+
end
|
50
|
+
def color_code color
|
51
|
+
SEDOC_ROLOC[color]
|
52
|
+
end
|
53
|
+
def style_code style
|
54
|
+
SELYTS_ENIL_REDROB_FX[style]
|
55
|
+
end
|
56
|
+
def font_index
|
57
|
+
@writer.font_index @workbook, font.key
|
58
|
+
end
|
59
|
+
def horizontal_align
|
60
|
+
XF_H_ALIGN.fetch @format.horizontal_align, 0
|
61
|
+
end
|
62
|
+
def num_format
|
63
|
+
@writer.number_format_index @workbook, @format.number_format
|
64
|
+
end
|
65
|
+
def text_direction
|
66
|
+
XF_TEXT_DIRECTION.fetch @format.text_direction, 0
|
67
|
+
end
|
68
|
+
def vertical_align
|
69
|
+
XF_V_ALIGN.fetch @format.vertical_align, 2
|
70
|
+
end
|
71
|
+
def write_op writer, op, *args
|
72
|
+
data = args.join
|
73
|
+
writer.write [op,data.size].pack("v2")
|
74
|
+
writer.write data
|
75
|
+
end
|
76
|
+
def write_xf writer, type=@opts[:type]
|
77
|
+
xf_type = xf_type_prot type
|
78
|
+
data = [
|
79
|
+
font_index, # Index to FONT record (➜ 6.43)
|
80
|
+
num_format, # Index to FORMAT record (➜ 6.45)
|
81
|
+
xf_type, # Bit Mask Contents
|
82
|
+
# 2-0 0x0007 XF_TYPE_PROT – XF type, cell protection
|
83
|
+
# Bit Mask Contents
|
84
|
+
# 0 0x01 1 = Cell is locked
|
85
|
+
# 1 0x02 1 = Formula is hidden
|
86
|
+
# 2 0x04 0 = Cell XF; 1 = Style XF
|
87
|
+
# 15-4 0xfff0 Index to parent style XF
|
88
|
+
# (always 0xfff in style XFs)
|
89
|
+
xf_align, # Bit Mask Contents
|
90
|
+
# 2-0 0x07 XF_HOR_ALIGN – Horizontal alignment
|
91
|
+
# Value Horizontal alignment
|
92
|
+
# 0x00 General
|
93
|
+
# 0x01 Left
|
94
|
+
# 0x02 Centred
|
95
|
+
# 0x03 Right
|
96
|
+
# 0x04 Filled
|
97
|
+
# 0x05 Justified (BIFF4-BIFF8X)
|
98
|
+
# 0x06 Centred across selection
|
99
|
+
# (BIFF4-BIFF8X)
|
100
|
+
# 0x07 Distributed (BIFF8X)
|
101
|
+
# 3 0x08 1 = Text is wrapped at right border
|
102
|
+
# 6-4 0x70 XF_VERT_ALIGN – Vertical alignment
|
103
|
+
# Value Vertical alignment
|
104
|
+
# 0x00 Top
|
105
|
+
# 0x01 Centred
|
106
|
+
# 0x02 Bottom
|
107
|
+
# 0x03 Justified (BIFF5-BIFF8X)
|
108
|
+
# 0x04 Distributed (BIFF8X)
|
109
|
+
xf_rotation, # XF_ROTATION: Text rotation angle
|
110
|
+
# Value Text rotation
|
111
|
+
# 0 Not rotated
|
112
|
+
# 1-90 1 to 90 degrees counterclockwise
|
113
|
+
# 91-180 1 to 90 degrees clockwise
|
114
|
+
# 255 Letters are stacked top-to-bottom,
|
115
|
+
# but not rotated
|
116
|
+
xf_indent, # Bit Mask Contents
|
117
|
+
# 3-0 0x0f Indent level
|
118
|
+
# 4 0x10 1 = Shrink content to fit into cell
|
119
|
+
# 5 0x40 1 = Merge Range (djberger)
|
120
|
+
# 7-6 0xc0 Text direction (BIFF8X only)
|
121
|
+
# 0 = According to context
|
122
|
+
# 1 = Left-to-right
|
123
|
+
# 2 = Right-to-left
|
124
|
+
xf_used_attr, # Bit Mask Contents
|
125
|
+
# 7-2 0xfc XF_USED_ATTRIB – Used attributes
|
126
|
+
# Each bit describes the validity of a
|
127
|
+
# specific group of attributes. In cell XFs
|
128
|
+
# a cleared bit means the attributes of the
|
129
|
+
# parent style XF are used (but only if the
|
130
|
+
# attributes are valid there), a set bit
|
131
|
+
# means the attributes of this XF are used.
|
132
|
+
# In style XFs a cleared bit means the
|
133
|
+
# attribute setting is valid, a set bit
|
134
|
+
# means the attribute should be ignored.
|
135
|
+
# Bit Mask Contents
|
136
|
+
# 0 0x01 Flag for number format
|
137
|
+
# 1 0x02 Flag for font
|
138
|
+
# 2 0x04 Flag for horizontal and
|
139
|
+
# vertical alignment, text wrap,
|
140
|
+
# indentation, orientation,
|
141
|
+
# rotation, and text direction
|
142
|
+
# 3 0x08 Flag for border lines
|
143
|
+
# 4 0x10 Flag for background area style
|
144
|
+
# 5 0x20 Flag for cell protection (cell
|
145
|
+
# locked and formula hidden)
|
146
|
+
xf_borders, # Cell border lines and background area:
|
147
|
+
# Bit Mask Contents
|
148
|
+
# 3- 0 0x0000000f Left line style (➜ 3.10)
|
149
|
+
# 7- 4 0x000000f0 Right line style (➜ 3.10)
|
150
|
+
# 11- 8 0x00000f00 Top line style (➜ 3.10)
|
151
|
+
# 15-12 0x0000f000 Bottom line style (➜ 3.10)
|
152
|
+
# 22-16 0x007f0000 Colour index (➜ 6.70)
|
153
|
+
# for left line colour
|
154
|
+
# 29-23 0x3f800000 Colour index (➜ 6.70)
|
155
|
+
# for right line colour
|
156
|
+
# 30 0x40000000 1 = Diagonal line
|
157
|
+
# from top left to right bottom
|
158
|
+
# 31 0x80000000 1 = Diagonal line
|
159
|
+
# from bottom left to right top
|
160
|
+
xf_brdcolors, # Bit Mask Contents
|
161
|
+
# 6- 0 0x0000007f Colour index (➜ 6.70)
|
162
|
+
# for top line colour
|
163
|
+
# 13- 7 0x00003f80 Colour index (➜ 6.70)
|
164
|
+
# for bottom line colour
|
165
|
+
# 20-14 0x001fc000 Colour index (➜ 6.70)
|
166
|
+
# for diagonal line colour
|
167
|
+
# 24-21 0x01e00000 Diagonal line style (➜ 3.10)
|
168
|
+
# 31-26 0xfc000000 Fill pattern (➜ 3.11)
|
169
|
+
xf_pattern # Bit Mask Contents
|
170
|
+
# 6-0 0x007f Colour index (➜ 6.70)
|
171
|
+
# for pattern colour
|
172
|
+
# 13-7 0x3f80 Colour index (➜ 6.70)
|
173
|
+
# for pattern background
|
174
|
+
]
|
175
|
+
write_op writer, 0x00e0, data.pack(binfmt(:xf))
|
176
|
+
end
|
177
|
+
def xf_align
|
178
|
+
align = horizontal_align
|
179
|
+
align |= text_wrap << 3
|
180
|
+
align |= vertical_align << 4
|
181
|
+
align |= text_justlast << 7
|
182
|
+
align
|
183
|
+
end
|
184
|
+
def xf_borders
|
185
|
+
border = left
|
186
|
+
border |= right << 4
|
187
|
+
border |= top << 8
|
188
|
+
border |= bottom << 12
|
189
|
+
border |= left_color << 16
|
190
|
+
border |= right_color << 23
|
191
|
+
border |= cross_down << 30
|
192
|
+
border |= cross_up << 31
|
193
|
+
border
|
194
|
+
end
|
195
|
+
def xf_brdcolors
|
196
|
+
border = top_color
|
197
|
+
border |= bottom_color << 7
|
198
|
+
border |= diagonal_color << 14
|
199
|
+
border |= pattern << 26
|
200
|
+
border
|
201
|
+
end
|
202
|
+
def xf_indent
|
203
|
+
indent = indent_level & 0x0f
|
204
|
+
indent |= shrink << 4
|
205
|
+
indent |= merge_range << 5
|
206
|
+
indent |= text_direction << 6
|
207
|
+
indent
|
208
|
+
end
|
209
|
+
def xf_pattern
|
210
|
+
ptrn = pattern_fg_color
|
211
|
+
ptrn |= pattern_bg_color << 7
|
212
|
+
ptrn
|
213
|
+
end
|
214
|
+
def xf_rotation
|
215
|
+
rot = @format.rotation
|
216
|
+
if @format.rotation_stacked?
|
217
|
+
rot = 255
|
218
|
+
elsif rot >= -90 or rotation <= 90
|
219
|
+
rot = -rot + 90 if rot < 0
|
220
|
+
else
|
221
|
+
warn "rotation outside -90..90; rotation set to 0"
|
222
|
+
rot = 0
|
223
|
+
end
|
224
|
+
rot
|
225
|
+
end
|
226
|
+
def xf_type_prot type
|
227
|
+
type = type.to_s.downcase == 'style' ? 0xfff4 : 0x0000
|
228
|
+
type |= locked
|
229
|
+
type |= hidden << 1
|
230
|
+
type
|
231
|
+
end
|
232
|
+
def xf_used_attr
|
233
|
+
atr_num = num_format & 1
|
234
|
+
atr_fnt = font_index & 1
|
235
|
+
atr_fnt = 1 unless @format.font.color == :text
|
236
|
+
atr_alc = 0
|
237
|
+
if horizontal_align != 0 \
|
238
|
+
|| vertical_align != 2 \
|
239
|
+
|| indent_level > 0 \
|
240
|
+
|| shrink? || merge_range? || text_wrap?
|
241
|
+
then
|
242
|
+
atr_alc = 1
|
243
|
+
end
|
244
|
+
atr_bdr = 1
|
245
|
+
atr_pat = 0
|
246
|
+
if @format.pattern_fg_color != :border \
|
247
|
+
|| @format.pattern_bg_color != :pattern_bg \
|
248
|
+
|| pattern != 0x00
|
249
|
+
then
|
250
|
+
atr_pat = 1
|
251
|
+
end
|
252
|
+
atr_prot = hidden? || locked? ? 1 : 0
|
253
|
+
attrs = atr_num
|
254
|
+
attrs |= atr_fnt << 1
|
255
|
+
attrs |= atr_alc << 2
|
256
|
+
attrs |= atr_bdr << 3
|
257
|
+
attrs |= atr_pat << 4
|
258
|
+
attrs |= atr_prot << 5
|
259
|
+
attrs << 2
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|