keeguon-spreadsheet 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +619 -0
  3. data/Manifest.txt +85 -0
  4. data/bin/xlsopcodes +18 -0
  5. data/lib/parseexcel.rb +27 -0
  6. data/lib/parseexcel/parseexcel.rb +75 -0
  7. data/lib/parseexcel/parser.rb +11 -0
  8. data/lib/spreadsheet.rb +80 -0
  9. data/lib/spreadsheet/column.rb +71 -0
  10. data/lib/spreadsheet/compatibility.rb +23 -0
  11. data/lib/spreadsheet/datatypes.rb +161 -0
  12. data/lib/spreadsheet/encodings.rb +57 -0
  13. data/lib/spreadsheet/excel.rb +88 -0
  14. data/lib/spreadsheet/excel/error.rb +26 -0
  15. data/lib/spreadsheet/excel/internals.rb +458 -0
  16. data/lib/spreadsheet/excel/internals/biff5.rb +17 -0
  17. data/lib/spreadsheet/excel/internals/biff8.rb +19 -0
  18. data/lib/spreadsheet/excel/offset.rb +41 -0
  19. data/lib/spreadsheet/excel/password_hash.rb +24 -0
  20. data/lib/spreadsheet/excel/reader.rb +1302 -0
  21. data/lib/spreadsheet/excel/reader/biff5.rb +42 -0
  22. data/lib/spreadsheet/excel/reader/biff8.rb +231 -0
  23. data/lib/spreadsheet/excel/rgb.rb +122 -0
  24. data/lib/spreadsheet/excel/row.rb +98 -0
  25. data/lib/spreadsheet/excel/sst_entry.rb +46 -0
  26. data/lib/spreadsheet/excel/workbook.rb +80 -0
  27. data/lib/spreadsheet/excel/worksheet.rb +115 -0
  28. data/lib/spreadsheet/excel/writer.rb +1 -0
  29. data/lib/spreadsheet/excel/writer/biff8.rb +75 -0
  30. data/lib/spreadsheet/excel/writer/format.rb +264 -0
  31. data/lib/spreadsheet/excel/writer/n_worksheet.rb +888 -0
  32. data/lib/spreadsheet/excel/writer/workbook.rb +735 -0
  33. data/lib/spreadsheet/excel/writer/worksheet.rb +940 -0
  34. data/lib/spreadsheet/font.rb +115 -0
  35. data/lib/spreadsheet/format.rb +209 -0
  36. data/lib/spreadsheet/formula.rb +9 -0
  37. data/lib/spreadsheet/helpers.rb +11 -0
  38. data/lib/spreadsheet/link.rb +43 -0
  39. data/lib/spreadsheet/note.rb +23 -0
  40. data/lib/spreadsheet/noteObject.rb +17 -0
  41. data/lib/spreadsheet/row.rb +151 -0
  42. data/lib/spreadsheet/workbook.rb +143 -0
  43. data/lib/spreadsheet/worksheet.rb +326 -0
  44. data/lib/spreadsheet/writer.rb +30 -0
  45. data/test/data/test_adding_data_to_existing_file.xls +0 -0
  46. data/test/data/test_borders.xls +0 -0
  47. data/test/data/test_changes.xls +0 -0
  48. data/test/data/test_comment.xls +0 -0
  49. data/test/data/test_copy.xls +0 -0
  50. data/test/data/test_datetime.xls +0 -0
  51. data/test/data/test_empty.xls +0 -0
  52. data/test/data/test_formula.xls +0 -0
  53. data/test/data/test_long_sst_record.xls +0 -0
  54. data/test/data/test_margin.xls +0 -0
  55. data/test/data/test_merged_and_protected.xls +0 -0
  56. data/test/data/test_merged_cells.xls +0 -0
  57. data/test/data/test_missing_row.xls +0 -0
  58. data/test/data/test_pagesetup.xls +0 -0
  59. data/test/data/test_version_excel5.xls +0 -0
  60. data/test/data/test_version_excel95.xls +0 -0
  61. data/test/data/test_version_excel97.xls +0 -0
  62. data/test/data/test_version_excel97_2010.xls +0 -0
  63. data/test/data/test_worksheet_visibility.xls +0 -0
  64. data/test/excel/reader.rb +30 -0
  65. data/test/excel/row.rb +40 -0
  66. data/test/excel/writer/workbook.rb +95 -0
  67. data/test/excel/writer/worksheet.rb +81 -0
  68. data/test/font.rb +163 -0
  69. data/test/format.rb +95 -0
  70. data/test/integration.rb +1390 -0
  71. data/test/row.rb +33 -0
  72. data/test/suite.rb +18 -0
  73. data/test/workbook.rb +55 -0
  74. data/test/workbook_protection.rb +19 -0
  75. data/test/worksheet.rb +112 -0
  76. 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