| Class | Spreadsheet::Excel::Writer::Workbook |
| In: |
lib/spreadsheet/excel/writer/workbook.rb
|
| Parent: | Spreadsheet::Writer |
Writer class for Excel Workbooks. Most write_* method correspond to an Excel-Record/Opcode. Designed to be able to write several Workbooks in parallel (just because I can‘t imagine why you would want to do that doesn‘t mean it shouldn‘t be possible ;). You should not need to call any of its methods directly. If you think you do, look at write_workbook
| date_base | [R] | |
| fonts | [R] |
# File lib/spreadsheet/excel/writer/workbook.rb, line 21
21: def initialize *args
22: super
23: @biff_version = 0x0600
24: @bof = 0x0809
25: @build_id = 3515
26: @build_year = 1996
27: @bof_types = {
28: :globals => 0x0005,
29: :visual_basic => 0x0006,
30: :worksheet => 0x0010,
31: :chart => 0x0020,
32: :macro_sheet => 0x0040,
33: :workspace => 0x0100,
34: }
35: @worksheets = {}
36: @sst = {}
37: @recordsize_limit = 8224
38: @fonts = {}
39: @formats = {}
40: @number_formats = {}
41: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 491
491: def _write_sst workbook, writer, offset, total, strings
492: sst = {}
493: worksheets(workbook).each do |worksheet|
494: offset += worksheet.boundsheet_size
495: @sst[worksheet] = sst
496: end
497: sst_size = strings.size
498: data = [total, sst_size].pack 'V2'
499: op = 0x00fc
500: wide = 0
501: offsets = []
502: strings.each_with_index do |string, idx|
503: sst.store string, idx
504: op_offset = data.size + 4
505: if idx % SST_CHUNKSIZE == 0
506: offsets.push [offset + writer.pos + op_offset, op_offset]
507: end
508: header, packed, next_wide = _unicode_string string, 2
509: # the first few bytes (header + first character) must not be split
510: must_fit = header.size + wide + 1
511: while data.size + must_fit > @recordsize_limit
512: op, data, wide = write_string_part writer, op, data, wide
513: end
514: wide = next_wide
515: data << header << packed
516: end
517: until data.empty?
518: op, data, wide = write_string_part writer, op, data, wide
519: end
520: write_extsst workbook, offsets, writer
521: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 42
42: def cleanup workbook
43: worksheets(workbook).each do |worksheet|
44: @sst.delete worksheet
45: end
46: @fonts.delete workbook
47: @formats.delete workbook
48: @number_formats.delete workbook
49: @worksheets.delete workbook
50: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 51
51: def collect_formats workbook, opts={}
52: # The default cell format is always present in an Excel file, described by
53: # the XF record with the fixed index 15 (0-based). By default, it uses the
54: # worksheet/workbook default cell style, described by the very first XF
55: # record (index 0).
56: formats = []
57: unless opts[:existing_document]
58: 15.times do
59: formats.push Format.new(self, workbook, workbook.default_format,
60: :type => :style)
61: end
62: formats.push Format.new(self, workbook)
63: end
64: workbook.formats.each do |fmt|
65: formats.push Format.new(self, workbook, fmt)
66: end
67: formats.each_with_index do |fmt, idx|
68: fmt.xf_index = idx
69: end
70: @formats[workbook] = formats
71: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 72
72: def complete_sst_update? workbook
73: stored = workbook.sst.collect do |entry| entry.content end
74: current = worksheets(workbook).inject [] do |memo, worksheet|
75: memo.concat worksheet.strings
76: end
77: total = current.size
78: current.uniq!
79: current.delete ''
80: if (stored - current).empty? && !stored.empty?
81: ## if all previously stored strings are still needed, we don't have to
82: # rewrite all cells because the sst-index of such string does not change.
83: additions = current - stored
84: [:partial_update, total, stored + additions]
85: else
86: [:complete_update, total, current]
87: end
88: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 89
89: def font_index workbook, font_key
90: idx = @fonts[workbook][font_key] || 0
91: ## this appears to be undocumented: the first 4 fonts seem to be accessed
92: # with a 0-based index, but all subsequent font indices are 1-based.
93: idx > 3 ? idx.next : idx
94: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 95
95: def number_format_index workbook, format
96: @number_formats[workbook][format] || 0
97: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 98
98: def sanitize_worksheets sheets
99: found_selected = false
100: sheets.each do |sheet|
101: found_selected ||= sheet.selected
102: sheet.format_dates!
103: end
104: unless found_selected
105: sheets.first.selected = true
106: end
107: sheets
108: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 639
639: def sst_index worksheet, str
640: @sst[worksheet][str]
641: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 109
109: def worksheets workbook
110: @worksheets[workbook] ||= workbook.worksheets.collect do |worksheet|
111: Excel::Writer::Worksheet.new self, worksheet
112: end
113: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 114
114: def write_bof workbook, writer, type
115: data = [
116: @biff_version, # BIFF version (always 0x0600 for BIFF8)
117: @bof_types[type], # Type of the following data:
118: # 0x0005 = Workbook globals
119: # 0x0006 = Visual Basic module
120: # 0x0010 = Worksheet
121: # 0x0020 = Chart
122: # 0x0040 = Macro sheet
123: # 0x0100 = Workspace file
124: @build_id, # Build identifier
125: @build_year, # Build year
126: 0x000, # File history flags
127: 0x006, # Lowest Excel version that can read
128: # all records in this file
129: ]
130: write_op writer, @bof, data.pack("v4V2")
131: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 132
132: def write_bookbool workbook, writer
133: write_placeholder writer, 0x00da
134: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 135
135: def write_boundsheets workbook, writer, offset
136: worksheets = worksheets(workbook)
137: worksheets.each do |worksheet|
138: # account for boundsheet-entry
139: offset += worksheet.boundsheet_size
140: end
141: worksheets.each do |worksheet|
142: data = [
143: offset, # Absolute stream position of the BOF record of the sheet
144: # represented by this record. This field is never encrypted
145: # in protected files.
146: 0x00, # Visibility: 0x00 = Visible
147: # 0x01 = Hidden
148: # 0x02 = Strong hidden (see below)
149: 0x00, # Sheet type: 0x00 = Worksheet
150: # 0x02 = Chart
151: # 0x06 = Visual Basic module
152: ]
153: write_op writer, 0x0085, data.pack("VC2"), worksheet.name
154: offset += worksheet.size
155: end
156: end
Copy unchanged data verbatim, adjust offsets and write new records for changed data.
# File lib/spreadsheet/excel/writer/workbook.rb, line 160
160: def write_changes workbook, io
161: sanitize_worksheets workbook.worksheets
162: collect_formats workbook, :existing_document => true
163: reader = workbook.ole
164: sheet_data = {}
165: sst_status, sst_total, sst_strings = complete_sst_update? workbook
166: sst = {}
167: sst_strings.each_with_index do |str, idx| sst.store str, idx end
168: sheets = worksheets(workbook)
169: positions = []
170: newsheets = []
171: sheets.each do |sheet|
172: @sst[sheet] = sst
173: pos, len = workbook.offsets[sheet.worksheet]
174: if pos
175: positions.push pos
176: sheet.write_changes reader, pos + len, sst_status
177: else
178: newsheets.push sheet
179: sheet.write_from_scratch
180: end
181: sheet_data[sheet.worksheet] = sheet.data
182: end
183: Ole::Storage.open io do |ole|
184: ole.file.open 'Workbook', 'w' do |writer|
185: reader.seek lastpos = 0
186: workbook.offsets.select do |key, pair|
187: workbook.changes.include? key
188: end.sort_by do |key, (pos, len)|
189: pos
190: end.each do |key, (pos, len)|
191: data = reader.read(pos - lastpos)
192: writer.write data
193: case key
194: when Spreadsheet::Worksheet
195: writer.write sheet_data[key]
196: when :boundsheets
197: ## boundsheets are hard to calculate. The offset below is only
198: # correct if there are no more changes in the workbook globals
199: # string after this.
200: oldoffset = positions.min - len
201: lastpos = pos + len
202: bytechange = 0
203: buffer = StringIO.new ''
204: if tuple = workbook.offsets[:sst]
205: write_sst_changes workbook, buffer, writer.pos,
206: sst_total, sst_strings
207: pos, len = tuple
208: if offset = workbook.offsets[:extsst]
209: len += offset[1].to_i
210: end
211: bytechange = buffer.size - len
212: write_boundsheets workbook, writer, oldoffset + bytechange
213: reader.seek lastpos
214: writer.write reader.read(pos - lastpos)
215: buffer.rewind
216: writer.write buffer.read
217: elsif sst.empty? || workbook.biff_version < 8
218: write_boundsheets workbook, writer, oldoffset + bytechange
219: else
220: write_sst workbook, buffer, writer.pos
221: write_boundsheets workbook, writer, oldoffset + buffer.size
222: pos = lastpos
223: len = positions.min - lastpos
224: if len > OPCODE_SIZE
225: reader.seek pos
226: writer.write reader.read(len - OPCODE_SIZE)
227: end
228: buffer.rewind
229: writer.write buffer.read
230: write_eof workbook, writer
231: end
232: else
233: send "write_#{key}", workbook, writer
234: end
235: lastpos = [pos + len, reader.size - 1].min
236: reader.seek lastpos
237: end
238: writer.write reader.read
239: newsheets.each do |sheet|
240: writer.write sheet.data
241: end
242: end
243: end
244: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 245
245: def write_datemode workbook, writer
246: mode = @date_base.year == 1899 ? 0x00 : 0x01
247: data = [
248: mode, # 0 = Base date is 1899-Dec-31
249: # (the cell value 1 represents 1900-Jan-01)
250: # 1 = Base date is 1904-Jan-01
251: # (the cell value 1 represents 1904-Jan-02)
252: ]
253: write_op writer, 0x0022, data.pack('v')
254: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 255
255: def write_dsf workbook, writer
256: data = [
257: 0x00, # 0 = Only the BIFF8 “Workbook” stream is present
258: # 1 = Additional BIFF5/BIFF7 “Book” stream is in the file
259: ]
260: write_op writer, 0x0161, data.pack('v')
261: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 262
262: def write_encoding workbook, writer
263: enc = workbook.encoding || 'UTF-16LE'
264: if RUBY_VERSION >= '1.9' && enc.is_a?(Encoding)
265: enc = enc.name.upcase
266: end
267: cp = SEGAPEDOC[enc] or raise "Invalid or Unknown Codepage '#{enc}'"
268: write_op writer, 0x0042, [cp].pack('v')
269: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 270
270: def write_eof workbook, writer
271: write_op writer, 0x000a
272: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 273
273: def write_extsst workbook, offsets, writer
274: header = [SST_CHUNKSIZE].pack('v')
275: data = offsets.collect do |pair| pair.push(0).pack('Vv2') end
276: write_op writer, 0x00ff, header, data
277: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 278
278: def write_font workbook, writer, font
279: # TODO: Colors/Palette index
280: size = font.size * TWIPS
281: color = SEDOC_ROLOC[font.color] || SEDOC_ROLOC[:text]
282: weight = FONT_WEIGHTS.fetch(font.weight, font.weight)
283: weight = [[weight, 1000].min, 100].max
284: esc = SEPYT_TNEMEPACSE.fetch(font.escapement, 0)
285: underline = SEPYT_ENILREDNU.fetch(font.underline, 0)
286: family = SEILIMAF_TNOF.fetch(font.family, 0)
287: encoding = SGNIDOCNE_TNOF.fetch(font.encoding, 0)
288: options = 0
289: options |= 0x0001 if weight > 600
290: options |= 0x0002 if font.italic?
291: options |= 0x0004 if underline > 0
292: options |= 0x0008 if font.strikeout?
293: options |= 0x0010 if font.outline?
294: options |= 0x0020 if font.shadow?
295: data = [
296: size, # Height of the font (in twips = 1/20 of a point)
297: options, # Option flags:
298: # Bit Mask Contents
299: # 0 0x0001 1 = Characters are bold (redundant, see below)
300: # 1 0x0002 1 = Characters are italic
301: # 2 0x0004 1 = Characters are underlined (redundant)
302: # 3 0x0008 1 = Characters are struck out
303: # 4 0x0010 1 = Characters are outlined (djberger)
304: # 5 0x0020 1 = Characters are shadowed (djberger)
305: color, # Palette index (➜ 6.70)
306: weight, # Font weight (100-1000). Standard values are
307: # 0x0190 (400) for normal text and
308: # 0x02bc (700) for bold text.
309: esc, # Escapement type: 0x0000 = None
310: # 0x0001 = Superscript
311: # 0x0002 = Subscript
312: underline,# Underline type: 0x00 = None
313: # 0x01 = Single
314: # 0x02 = Double
315: # 0x21 = Single accounting
316: # 0x22 = Double accounting
317: family, # Font family: 0x00 = None (unknown or don't care)
318: # 0x01 = Roman (variable width, serifed)
319: # 0x02 = Swiss (variable width, sans-serifed)
320: # 0x03 = Modern (fixed width,
321: # serifed or sans-serifed)
322: # 0x04 = Script (cursive)
323: # 0x05 = Decorative (specialised,
324: # e.g. Old English, Fraktur)
325: encoding, # Character set: 0x00 = 0 = ANSI Latin
326: # 0x01 = 1 = System default
327: # 0x02 = 2 = Symbol
328: # 0x4d = 77 = Apple Roman
329: # 0x80 = 128 = ANSI Japanese Shift-JIS
330: # 0x81 = 129 = ANSI Korean (Hangul)
331: # 0x82 = 130 = ANSI Korean (Johab)
332: # 0x86 = 134 = ANSI Chinese Simplified GBK
333: # 0x88 = 136 = ANSI Chinese Traditional BIG5
334: # 0xa1 = 161 = ANSI Greek
335: # 0xa2 = 162 = ANSI Turkish
336: # 0xa3 = 163 = ANSI Vietnamese
337: # 0xb1 = 177 = ANSI Hebrew
338: # 0xb2 = 178 = ANSI Arabic
339: # 0xba = 186 = ANSI Baltic
340: # 0xcc = 204 = ANSI Cyrillic
341: # 0xde = 222 = ANSI Thai
342: # 0xee = 238 = ANSI Latin II (Central European)
343: # 0xff = 255 = OEM Latin I
344: ]
345: name = unicode_string font.name # Font name: Unicode string,
346: # 8-bit string length (➜ 3.4)
347: write_op writer, opcode(:font), data.pack(binfmt(:font)), name
348: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 349
349: def write_fonts workbook, writer
350: fonts = @fonts[workbook] = {}
351: @formats[workbook].each do |format|
352: if(font = format.font) && !fonts.include?(font.key)
353: fonts.store font.key, fonts.size
354: write_font workbook, writer, font
355: end
356: end
357: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 358
358: def write_formats workbook, writer
359: # From BIFF5 on, the built-in number formats will be omitted. The built-in
360: # formats are dependent on the current regional settings of the operating
361: # system. BUILTIN_FORMATS shows which number formats are used by
362: # default in a US-English environment. All indexes from 0 to 163 are
363: # reserved for built-in formats.
364: # The first user-defined format starts at 164 (0xa4).
365: formats = @number_formats[workbook] = {}
366: BUILTIN_FORMATS.each do |idx, str|
367: formats.store client(str, 'UTF-8'), idx
368: end
369: ## Ensure at least a 'GENERAL' format is written
370: formats.delete client('GENERAL', 'UTF-8')
371: idx = 0xa4
372: workbook.formats.each do |fmt|
373: str = fmt.number_format
374: unless formats[str]
375: formats.store str, idx
376: # Number format string (Unicode string, 16-bit string length, ➜ 3.4)
377: write_op writer, opcode(:format), [idx].pack('v'), unicode_string(str, 2)
378: idx += 1
379: end
380: end
381: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 384
384: def write_from_scratch workbook, io
385: sanitize_worksheets workbook.worksheets
386: collect_formats workbook
387: sheets = worksheets workbook
388: buffer1 = StringIO.new ''
389: # ● BOF Type = workbook globals (➜ 6.8)
390: write_bof workbook, buffer1, :globals
391: # ○ File Protection Block ➜ 4.19
392: # ○ WRITEACCESS User name (BIFF3-BIFF8, ➜ 5.112)
393: # ○ FILESHARING File sharing options (BIFF3-BIFF8, ➜ 5.44)
394: # ○ CODEPAGE ➜ 6.17
395: write_encoding workbook, buffer1
396: # ○ DSF ➜ 6.32
397: write_dsf workbook, buffer1
398: # ○ TABID
399: write_tabid workbook, buffer1
400: # ○ FNGROUPCOUNT
401: # ○ Workbook Protection Block ➜ 4.18
402: # ○ WINDOWPROTECT Window settings: 1 = protected (➜ 5.111)
403: # ○ PROTECT Cell contents: 1 = protected (➜ 5.82)
404: write_protect workbook, buffer1
405: # ○ OBJECTPROTECT Embedded objects: 1 = protected (➜ 5.72)
406: # ○ PASSWORD Hash value of the password; 0 = No password (➜ 5.76)
407: write_password workbook, buffer1
408: # ○ BACKUP ➜ 5.5
409: # ○ HIDEOBJ ➜ 5.56
410: # ● WINDOW1 ➜ 5.109
411: write_window1 workbook, buffer1
412: # ○ DATEMODE ➜ 5.28
413: write_datemode workbook, buffer1
414: # ○ PRECISION ➜ 5.79
415: write_precision workbook, buffer1
416: # ○ REFRESHALL
417: write_refreshall workbook, buffer1
418: # ○ BOOKBOOL ➜ 5.9
419: write_bookbool workbook, buffer1
420: # ●● FONT ➜ 5.45
421: write_fonts workbook, buffer1
422: # ○○ FORMAT ➜ 5.49
423: write_formats workbook, buffer1
424: # ●● XF ➜ 5.115
425: write_xfs workbook, buffer1
426: # ●● STYLE ➜ 5.103
427: write_styles workbook, buffer1
428: # ○ PALETTE ➜ 5.74
429: # ○ USESELFS ➜ 5.106
430: buffer1.rewind
431: # ●● BOUNDSHEET ➜ 5.95
432: buffer2 = StringIO.new ''
433: # ○ COUNTRY ➜ 5.22
434: # ○ Link Table ➜ 4.10.3
435: # ○○ NAME ➜ 6.66
436: # ○ Shared String Table ➜ 4.11
437: # ● SST ➜ 5.100
438: # ● EXTSST ➜ 5.42
439: write_sst workbook, buffer2, buffer1.size
440: # ● EOF ➜ 5.37
441: write_eof workbook, buffer2
442: buffer2.rewind
443: # worksheet data can only be assembled after write_sst
444: sheets.each do |worksheet| worksheet.write_from_scratch end
445: Ole::Storage.open io do |ole|
446: ole.file.open 'Workbook', 'w' do |writer|
447: writer.write buffer1.read
448: write_boundsheets workbook, writer, buffer1.size + buffer2.size
449: writer.write buffer2.read
450: sheets.each do |worksheet|
451: writer.write worksheet.data
452: end
453: end
454: end
455: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 456
456: def write_op writer, op, *args
457: data = args.join
458: limited = data.slice!(0...@recordsize_limit)
459: writer.write [op,limited.size].pack("v2")
460: writer.write limited
461: data
462: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 463
463: def write_password workbook, writer
464: write_placeholder writer, 0x0013
465: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 466
466: def write_placeholder writer, op, value=0x0000, fmt='v'
467: write_op writer, op, [value].pack(fmt)
468: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 469
469: def write_precision workbook, writer
470: # 0 = Use displayed values; 1 = Use real cell values
471: write_placeholder writer, 0x000e, 0x0001
472: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 473
473: def write_protect workbook, writer
474: write_placeholder writer, 0x0012
475: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 476
476: def write_refreshall workbook, writer
477: write_placeholder writer, 0x01b7
478: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 479
479: def write_sst workbook, writer, offset
480: # Offset Size Contents
481: # 0 4 Total number of strings in the workbook (see below)
482: # 4 4 Number of following strings (nm)
483: # 8 var. List of nm Unicode strings, 16-bit string length (➜ 3.4)
484: strings = worksheets(workbook).inject [] do |memo, worksheet|
485: memo.concat worksheet.strings
486: end
487: total = strings.size
488: strings.uniq!
489: _write_sst workbook, writer, offset, total, strings
490: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 522
522: def write_sst_changes workbook, writer, offset, total, strings
523: _write_sst workbook, writer, offset, total, strings
524: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 525
525: def write_string_part writer, op, data, wide
526: bef = data.size
527: ## if we're writing wide characters, we need to make sure we don't cut
528: # characters in half
529: if wide > 0 && data.size > @recordsize_limit
530: remove = @recordsize_limit - data.size
531: remove -= remove % 2
532: rest = data.slice!(remove..-1)
533: write_op writer, op, data
534: data = rest
535: else
536: data = write_op writer, op, data
537: end
538: op = 0x003c
539: # Unicode strings are split in a special way. At the beginning of each
540: # CONTINUE record the option flags byte is repeated. Only the
541: # character size flag will be set in this flags byte, the Rich-Text
542: # flag and the Far-East flag are set to zero.
543: unless data.empty?
544: if wide == 1
545: # check if we can compress the rest of the string
546: data, wide = compress_unicode_string data
547: end
548: data = [wide].pack('C') << data
549: end
550: [op, data, wide]
551: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 552
552: def write_styles workbook, writer
553: # TODO: Style implementation. The following is simply a standard builtin
554: # style.
555: # TODO: User defined styles
556: data = [
557: 0x8000, # Bit Mask Contents
558: # 11- 0 0x0fff Index to style XF record (➜ 6.115)
559: # 15 0x8000 Always 1 for built-in styles
560: 0x00, # Identifier of the built-in cell style:
561: # 0x00 = Normal
562: # 0x01 = RowLevel_lv (see next field)
563: # 0x02 = ColLevel_lv (see next field)
564: # 0x03 = Comma
565: # 0x04 = Currency
566: # 0x05 = Percent
567: # 0x06 = Comma [0] (BIFF4-BIFF8)
568: # 0x07 = Currency [0] (BIFF4-BIFF8)
569: # 0x08 = Hyperlink (BIFF8)
570: # 0x09 = Followed Hyperlink (BIFF8)
571: 0xff, # Level for RowLevel or ColLevel style (zero-based, lv),
572: # 0xff otherwise
573: # The RowLevel and ColLevel styles specify the formatting of
574: # subtotal cells in a specific outline level. The level is
575: # specified by the last field in the STYLE record. Valid values
576: # are 0…6 for the outline levels 1…7.
577: ]
578: write_op writer, 0x0293, data.pack('vC2')
579: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 580
580: def write_tabid workbook, writer
581: write_op writer, 0x013d, [1].pack('v')
582: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 583
583: def write_window1 workbook, writer
584: selected = workbook.worksheets.find do |sheet| sheet.selected end
585: actidx = workbook.worksheets.index selected
586: data = [
587: 0x0000, # Horizontal position of the document window
588: # (in twips = 1/20 of a point)
589: 0x0000, # Vertical position of the document window
590: # (in twips = 1/20 of a point)
591: 0x4000, # Width of the document window (in twips = 1/20 of a point)
592: 0x2000, # Height of the document window (in twips = 1/20 of a point)
593: 0x0038, # Option flags:
594: # Bit Mask Contents
595: # 0 0x0001 0 = Window is visible
596: # 1 = Window is hidden
597: # 1 0x0002 0 = Window is open
598: # 1 = Window is minimised
599: # 3 0x0008 0 = Horizontal scroll bar hidden
600: # 1 = Horizontal scroll bar visible
601: # 4 0x0010 0 = Vertical scroll bar hidden
602: # 1 = Vertical scroll bar visible
603: # 5 0x0020 0 = Worksheet tab bar hidden
604: # 1 = Worksheet tab bar visible
605: actidx, # Index to active (displayed) worksheet
606: 0x0000, # Index of first visible tab in the worksheet tab bar
607: 0x0001, # Number of selected worksheets
608: # (highlighted in the worksheet tab bar)
609: 0x00e5, # Width of worksheet tab bar (in 1/1000 of window width).
610: # The remaining space is used by the horizontal scrollbar.
611: ]
612: write_op writer, 0x003d, data.pack('v*')
613: end
The main writer method. Calls write_from_scratch or write_changes depending on the class and state of workbook.
# File lib/spreadsheet/excel/writer/workbook.rb, line 617
617: def write_workbook workbook, io
618: unless workbook.is_a?(Excel::Workbook) && workbook.io
619: @date_base = Date.new 1899, 12, 31
620: write_from_scratch workbook, io
621: else
622: @date_base = workbook.date_base
623: if workbook.changes.empty?
624: super
625: else
626: write_changes workbook, io
627: end
628: end
629: ensure
630: cleanup workbook
631: end
# File lib/spreadsheet/excel/writer/workbook.rb, line 632
632: def write_xfs workbook, writer
633: # The default cell format is always present in an Excel file, described by
634: # the XF record with the fixed index 15 (0-based). By default, it uses the
635: # worksheet/workbook default cell style, described by the very first XF
636: # record (index 0).
637: @formats[workbook].each do |fmt| fmt.write_xf writer end
638: end