keeguon-spreadsheet 0.9.3

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.
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