spreadsheet-martica 0.6.5.7.m1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/GUIDE.txt +267 -0
  2. data/History.txt +365 -0
  3. data/LICENSE.txt +619 -0
  4. data/Manifest.txt +62 -0
  5. data/README.txt +107 -0
  6. data/bin/xlsopcodes +18 -0
  7. data/lib/parseexcel/parseexcel.rb +75 -0
  8. data/lib/parseexcel/parser.rb +11 -0
  9. data/lib/parseexcel.rb +27 -0
  10. data/lib/spreadsheet/column.rb +71 -0
  11. data/lib/spreadsheet/compatibility.rb +23 -0
  12. data/lib/spreadsheet/datatypes.rb +116 -0
  13. data/lib/spreadsheet/encodings.rb +57 -0
  14. data/lib/spreadsheet/excel/error.rb +26 -0
  15. data/lib/spreadsheet/excel/internals/biff5.rb +17 -0
  16. data/lib/spreadsheet/excel/internals/biff8.rb +19 -0
  17. data/lib/spreadsheet/excel/internals.rb +402 -0
  18. data/lib/spreadsheet/excel/offset.rb +41 -0
  19. data/lib/spreadsheet/excel/reader/biff5.rb +22 -0
  20. data/lib/spreadsheet/excel/reader/biff8.rb +199 -0
  21. data/lib/spreadsheet/excel/reader.rb +1173 -0
  22. data/lib/spreadsheet/excel/row.rb +92 -0
  23. data/lib/spreadsheet/excel/sst_entry.rb +46 -0
  24. data/lib/spreadsheet/excel/workbook.rb +80 -0
  25. data/lib/spreadsheet/excel/worksheet.rb +100 -0
  26. data/lib/spreadsheet/excel/writer/biff8.rb +75 -0
  27. data/lib/spreadsheet/excel/writer/format.rb +253 -0
  28. data/lib/spreadsheet/excel/writer/workbook.rb +653 -0
  29. data/lib/spreadsheet/excel/writer/worksheet.rb +882 -0
  30. data/lib/spreadsheet/excel/writer.rb +1 -0
  31. data/lib/spreadsheet/excel.rb +88 -0
  32. data/lib/spreadsheet/font.rb +92 -0
  33. data/lib/spreadsheet/format.rb +177 -0
  34. data/lib/spreadsheet/formula.rb +9 -0
  35. data/lib/spreadsheet/helpers.rb +11 -0
  36. data/lib/spreadsheet/link.rb +43 -0
  37. data/lib/spreadsheet/row.rb +132 -0
  38. data/lib/spreadsheet/workbook.rb +126 -0
  39. data/lib/spreadsheet/worksheet.rb +277 -0
  40. data/lib/spreadsheet/writer.rb +30 -0
  41. data/lib/spreadsheet.rb +79 -0
  42. data/test/data/test_changes.xls +0 -0
  43. data/test/data/test_copy.xls +0 -0
  44. data/test/data/test_datetime.xls +0 -0
  45. data/test/data/test_empty.xls +0 -0
  46. data/test/data/test_formula.xls +0 -0
  47. data/test/data/test_long_sst_record.xls +0 -0
  48. data/test/data/test_missing_row.xls +0 -0
  49. data/test/data/test_version_excel5.xls +0 -0
  50. data/test/data/test_version_excel95.xls +0 -0
  51. data/test/data/test_version_excel97.xls +0 -0
  52. data/test/excel/row.rb +35 -0
  53. data/test/excel/writer/workbook.rb +23 -0
  54. data/test/excel/writer/worksheet.rb +24 -0
  55. data/test/font.rb +163 -0
  56. data/test/integration.rb +1311 -0
  57. data/test/row.rb +33 -0
  58. data/test/suite.rb +17 -0
  59. data/test/workbook.rb +29 -0
  60. data/test/worksheet.rb +80 -0
  61. metadata +118 -0
@@ -0,0 +1,92 @@
1
+ require 'date'
2
+ require 'spreadsheet/row'
3
+
4
+ module Spreadsheet
5
+ module Excel
6
+ ##
7
+ # Excel-specific Row methods
8
+ class Row < Spreadsheet::Row
9
+ ##
10
+ # The Excel date calculation erroneously assumes that 1900 is a leap-year. All
11
+ # Dates after 28.2.1900 are off by one.
12
+ LEAP_ERROR = Date.new 1900, 2, 28
13
+ ##
14
+ # Force convert the cell at _idx_ to a Date
15
+ def date idx
16
+ _date at(idx)
17
+ end
18
+ ##
19
+ # Force convert the cell at _idx_ to a DateTime
20
+ def datetime idx
21
+ _datetime at(idx)
22
+ end
23
+ def each &block
24
+ size.times do |idx|
25
+ block.call self[idx]
26
+ end
27
+ end
28
+ ##
29
+ # Access data in this Row like you would in an Array. If a cell is formatted
30
+ # as a Date or DateTime, the decoded Date or DateTime value is returned.
31
+ def [] idx, len=nil
32
+ if len
33
+ idx = idx...(idx+len)
34
+ end
35
+ if idx.is_a? Range
36
+ data = []
37
+ idx.each do |i|
38
+ data.push enriched_data(i, at(i))
39
+ end
40
+ data
41
+ else
42
+ enriched_data idx, at(idx)
43
+ end
44
+ end
45
+ private
46
+ def _date data # :nodoc:
47
+ return data if data.is_a?(Date)
48
+ datetime = _datetime data
49
+ Date.new datetime.year, datetime.month, datetime.day
50
+ end
51
+ def _datetime data # :nodoc:
52
+ return data if data.is_a?(DateTime)
53
+ base = @worksheet.date_base
54
+ date = base + data.to_f
55
+ hour = (data % 1) * 24
56
+ min = (hour % 1) * 60
57
+ sec = ((min % 1) * 60).round
58
+ min = min.floor
59
+ hour = hour.floor
60
+ if sec > 59
61
+ sec = 0
62
+ min += 1
63
+ end
64
+ if min > 59
65
+ min = 0
66
+ hour += 1
67
+ end
68
+ if hour > 23
69
+ hour = 0
70
+ date += 1
71
+ end
72
+ if LEAP_ERROR > base
73
+ date -= 1
74
+ end
75
+ DateTime.new(date.year, date.month, date.day, hour, min, sec)
76
+ end
77
+ def enriched_data idx, data # :nodoc:
78
+ res = nil
79
+ if link = @worksheet.links[[@idx, idx]]
80
+ res = link
81
+ elsif data.is_a?(Numeric) && fmt = format(idx)
82
+ res = if fmt.datetime? || fmt.time?
83
+ _datetime data
84
+ elsif fmt.date?
85
+ _date data
86
+ end
87
+ end
88
+ res || data
89
+ end
90
+ end
91
+ end
92
+ end
@@ -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,100 @@
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
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
+ end
23
+ def add_link row, column, link
24
+ @links.store [row, column], link
25
+ end
26
+ def column idx
27
+ ensure_rows_read
28
+ super
29
+ end
30
+ def date_base
31
+ @workbook.date_base
32
+ end
33
+ def each *args
34
+ ensure_rows_read
35
+ super
36
+ end
37
+ def ensure_rows_read
38
+ return if @row_addresses
39
+ @dimensions = nil
40
+ @row_addresses = []
41
+ @reader.read_worksheet self, @offset if @reader
42
+ end
43
+ def row idx
44
+ @rows[idx] or begin
45
+ ensure_rows_read
46
+ if addr = @row_addresses[idx]
47
+ row = @reader.read_row self, addr
48
+ [:default_format, :height, :outline_level, :hidden, ].each do |key|
49
+ row.send "unupdated_#{key}=", addr[key]
50
+ end
51
+ row.worksheet = self
52
+ row
53
+ else
54
+ Row.new self, idx
55
+ end
56
+ end
57
+ end
58
+ def row_updated idx, row
59
+ res = super
60
+ @workbook.changes.store self, true
61
+ @workbook.changes.store :boundsheets, true
62
+ @changes.store idx, true
63
+ @changes.store :dimensions, true
64
+ res
65
+ end
66
+ def set_row_address idx, opts
67
+ @offsets.store idx, opts[:row_block]
68
+ @row_addresses[idx] = opts
69
+ end
70
+ def shared_string idx
71
+ @workbook.shared_string idx
72
+ end
73
+ private
74
+ ## premature optimization?
75
+ def have_set_dimensions value, pos, len
76
+ if @row_addresses.size < row_count
77
+ @row_addresses.concat Array.new(row_count - @row_addresses.size)
78
+ end
79
+ end
80
+ def recalculate_dimensions
81
+ ensure_rows_read
82
+ shorten @rows
83
+ @dimensions = []
84
+ @dimensions[0] = [ index_of_first(@rows),
85
+ index_of_first(@row_addresses) ].compact.min || 0
86
+ @dimensions[1] = [ @rows.size, @row_addresses.size ].compact.max || 0
87
+ compact = @rows.compact
88
+ first_rows = compact.collect do |row| row.first_used end.compact.min
89
+ first_addrs = @row_addresses.compact.collect do |addr|
90
+ addr[:first_used] end.min
91
+ @dimensions[2] = [ first_rows, first_addrs ].compact.min || 0
92
+ last_rows = compact.collect do |row| row.first_unused end.max
93
+ last_addrs = @row_addresses.compact.collect do |addr|
94
+ addr[:first_unused] end.max
95
+ @dimensions[3] = [last_rows, last_addrs].compact.max || 0
96
+ @dimensions
97
+ end
98
+ end
99
+ end
100
+ end
@@ -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,253 @@
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
+ boolean :hidden, :locked, :merge_range, :shrink, :text_justlast, :text_wrap,
25
+ :cross_down, :cross_up, :left, :right, :top, :bottom
26
+ color :left_color, :border
27
+ color :right_color, :border
28
+ color :top_color, :border
29
+ color :bottom_color, :border
30
+ color :diagonal_color, :border
31
+ color :pattern_fg_color, :pattern_bg
32
+ color :pattern_bg_color, :pattern_bg
33
+ attr_accessor :xf_index
34
+ attr_reader :format
35
+ def initialize writer, workbook, format=workbook.default_format, opts={}
36
+ @opts = { :type => :format }.merge opts
37
+ @format = format
38
+ @writer = writer
39
+ @workbook = workbook
40
+ super format
41
+ end
42
+ def color_code color
43
+ SEDOC_ROLOC[color]
44
+ end
45
+ def font_index
46
+ @writer.font_index @workbook, font.key
47
+ end
48
+ def horizontal_align
49
+ XF_H_ALIGN.fetch @format.horizontal_align, 0
50
+ end
51
+ def num_format
52
+ @writer.number_format_index @workbook, @format.number_format
53
+ end
54
+ def text_direction
55
+ XF_TEXT_DIRECTION.fetch @format.text_direction, 0
56
+ end
57
+ def vertical_align
58
+ XF_V_ALIGN.fetch @format.vertical_align, 2
59
+ end
60
+ def write_op writer, op, *args
61
+ data = args.join
62
+ writer.write [op,data.size].pack("v2")
63
+ writer.write data
64
+ end
65
+ def write_xf writer, type=@opts[:type]
66
+ xf_type = xf_type_prot type
67
+ data = [
68
+ font_index, # Index to FONT record (➜ 6.43)
69
+ num_format, # Index to FORMAT record (➜ 6.45)
70
+ xf_type, # Bit Mask Contents
71
+ # 2-0 0x0007 XF_TYPE_PROT – XF type, cell protection
72
+ # Bit Mask Contents
73
+ # 0 0x01 1 = Cell is locked
74
+ # 1 0x02 1 = Formula is hidden
75
+ # 2 0x04 0 = Cell XF; 1 = Style XF
76
+ # 15-4 0xfff0 Index to parent style XF
77
+ # (always 0xfff in style XFs)
78
+ xf_align, # Bit Mask Contents
79
+ # 2-0 0x07 XF_HOR_ALIGN – Horizontal alignment
80
+ # Value Horizontal alignment
81
+ # 0x00 General
82
+ # 0x01 Left
83
+ # 0x02 Centred
84
+ # 0x03 Right
85
+ # 0x04 Filled
86
+ # 0x05 Justified (BIFF4-BIFF8X)
87
+ # 0x06 Centred across selection
88
+ # (BIFF4-BIFF8X)
89
+ # 0x07 Distributed (BIFF8X)
90
+ # 3 0x08 1 = Text is wrapped at right border
91
+ # 6-4 0x70 XF_VERT_ALIGN – Vertical alignment
92
+ # Value Vertical alignment
93
+ # 0x00 Top
94
+ # 0x01 Centred
95
+ # 0x02 Bottom
96
+ # 0x03 Justified (BIFF5-BIFF8X)
97
+ # 0x04 Distributed (BIFF8X)
98
+ xf_rotation, # XF_ROTATION: Text rotation angle
99
+ # Value Text rotation
100
+ # 0 Not rotated
101
+ # 1-90 1 to 90 degrees counterclockwise
102
+ # 91-180 1 to 90 degrees clockwise
103
+ # 255 Letters are stacked top-to-bottom,
104
+ # but not rotated
105
+ xf_indent, # Bit Mask Contents
106
+ # 3-0 0x0f Indent level
107
+ # 4 0x10 1 = Shrink content to fit into cell
108
+ # 5 0x40 1 = Merge Range (djberger)
109
+ # 7-6 0xc0 Text direction (BIFF8X only)
110
+ # 0 = According to context
111
+ # 1 = Left-to-right
112
+ # 2 = Right-to-left
113
+ xf_used_attr, # Bit Mask Contents
114
+ # 7-2 0xfc XF_USED_ATTRIB – Used attributes
115
+ # Each bit describes the validity of a
116
+ # specific group of attributes. In cell XFs
117
+ # a cleared bit means the attributes of the
118
+ # parent style XF are used (but only if the
119
+ # attributes are valid there), a set bit
120
+ # means the attributes of this XF are used.
121
+ # In style XFs a cleared bit means the
122
+ # attribute setting is valid, a set bit
123
+ # means the attribute should be ignored.
124
+ # Bit Mask Contents
125
+ # 0 0x01 Flag for number format
126
+ # 1 0x02 Flag for font
127
+ # 2 0x04 Flag for horizontal and
128
+ # vertical alignment, text wrap,
129
+ # indentation, orientation,
130
+ # rotation, and text direction
131
+ # 3 0x08 Flag for border lines
132
+ # 4 0x10 Flag for background area style
133
+ # 5 0x20 Flag for cell protection (cell
134
+ # locked and formula hidden)
135
+ xf_borders, # Cell border lines and background area:
136
+ # Bit Mask Contents
137
+ # 3- 0 0x0000000f Left line style (➜ 3.10)
138
+ # 7- 4 0x000000f0 Right line style (➜ 3.10)
139
+ # 11- 8 0x00000f00 Top line style (➜ 3.10)
140
+ # 15-12 0x0000f000 Bottom line style (➜ 3.10)
141
+ # 22-16 0x007f0000 Colour index (➜ 6.70)
142
+ # for left line colour
143
+ # 29-23 0x3f800000 Colour index (➜ 6.70)
144
+ # for right line colour
145
+ # 30 0x40000000 1 = Diagonal line
146
+ # from top left to right bottom
147
+ # 31 0x80000000 1 = Diagonal line
148
+ # from bottom left to right top
149
+ xf_brdcolors, # Bit Mask Contents
150
+ # 6- 0 0x0000007f Colour index (➜ 6.70)
151
+ # for top line colour
152
+ # 13- 7 0x00003f80 Colour index (➜ 6.70)
153
+ # for bottom line colour
154
+ # 20-14 0x001fc000 Colour index (➜ 6.70)
155
+ # for diagonal line colour
156
+ # 24-21 0x01e00000 Diagonal line style (➜ 3.10)
157
+ # 31-26 0xfc000000 Fill pattern (➜ 3.11)
158
+ xf_pattern # Bit Mask Contents
159
+ # 6-0 0x007f Colour index (➜ 6.70)
160
+ # for pattern colour
161
+ # 13-7 0x3f80 Colour index (➜ 6.70)
162
+ # for pattern background
163
+ ]
164
+ write_op writer, 0x00e0, data.pack(binfmt(:xf))
165
+ end
166
+ def xf_align
167
+ align = horizontal_align
168
+ align |= text_wrap << 3
169
+ align |= vertical_align << 4
170
+ align |= text_justlast << 7
171
+ align
172
+ end
173
+ def xf_borders
174
+ border = left
175
+ border |= right << 4
176
+ border |= top << 8
177
+ border |= bottom << 12
178
+ border |= left_color << 16
179
+ border |= right_color << 23
180
+ border |= cross_down << 30
181
+ border |= cross_up << 31
182
+ border
183
+ end
184
+ def xf_brdcolors
185
+ border = top_color
186
+ border |= bottom_color << 7
187
+ border |= diagonal_color << 14
188
+ border |= pattern << 26
189
+ border
190
+ end
191
+ def xf_indent
192
+ indent = indent_level & 0x0f
193
+ indent |= shrink << 4
194
+ indent |= merge_range << 5
195
+ indent |= text_direction << 6
196
+ indent
197
+ end
198
+ def xf_pattern
199
+ ptrn = pattern_fg_color
200
+ ptrn |= pattern_bg_color << 7
201
+ ptrn
202
+ end
203
+ def xf_rotation
204
+ rot = @format.rotation
205
+ if @format.rotation_stacked?
206
+ rot = 255
207
+ elsif rot >= -90 or rotation <= 90
208
+ rot = -rot + 90 if rot < 0
209
+ else
210
+ warn "rotation outside -90..90; rotation set to 0"
211
+ rot = 0
212
+ end
213
+ rot
214
+ end
215
+ def xf_type_prot type
216
+ type = type.to_s.downcase == 'style' ? 0xfff5 : 0x0000
217
+ type |= locked
218
+ type |= hidden << 1
219
+ type
220
+ end
221
+ def xf_used_attr
222
+ atr_num = num_format & 1
223
+ atr_fnt = font_index & 1
224
+ atr_fnt = 1 unless @format.font.color == :text
225
+ atr_alc = 0
226
+ if horizontal_align != 0 \
227
+ || vertical_align != 2 \
228
+ || indent_level > 0 \
229
+ || shrink? || merge_range? || text_wrap?
230
+ then
231
+ atr_alc = 1
232
+ end
233
+ atr_bdr = [top, bottom, left, right, cross_up, cross_down].max
234
+ atr_pat = 0
235
+ if @format.pattern_fg_color != :border \
236
+ || @format.pattern_bg_color != :pattern_bg \
237
+ || pattern != 0x00
238
+ then
239
+ atr_pat = 1
240
+ end
241
+ atr_prot = hidden? || locked? ? 1 : 0
242
+ attrs = atr_num
243
+ attrs |= atr_fnt << 1
244
+ attrs |= atr_alc << 2
245
+ attrs |= atr_bdr << 3
246
+ attrs |= atr_pat << 4
247
+ attrs |= atr_prot << 5
248
+ attrs << 2
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end