Class Spreadsheet::Excel::Writer::Workbook
In: lib/spreadsheet/excel/writer/workbook.rb
Parent: Spreadsheet::Writer
Column Format Row Font Enumerable Worksheet\n[lib/spreadsheet/excel.rb\nlib/spreadsheet/worksheet.rb] Link Workbook Workbook\n[lib/spreadsheet/excel.rb\nlib/spreadsheet/excel/workbook.rb] SstEntry String Row Array Worksheet ExcelCompatibleWorkbook Format Worksheet Workbook DelegateClassSpreadsheet::Format Writer Compatibility Formula Reader\n[lib/parseexcel/parseexcel.rb\nlib/spreadsheet/excel/reader.rb\nlib/spreadsheet/excel/reader/biff5.rb\nlib/spreadsheet/excel/reader/biff8.rb] Error lib/spreadsheet/excel.rb lib/spreadsheet/link.rb lib/spreadsheet/formula.rb lib/spreadsheet/workbook.rb lib/spreadsheet/font.rb lib/spreadsheet/column.rb lib/spreadsheet/format.rb lib/spreadsheet/writer.rb lib/spreadsheet/row.rb Encodings lib/spreadsheet/excel.rb lib/spreadsheet/excel/row.rb lib/spreadsheet/excel/reader/biff5.rb lib/spreadsheet/excel/worksheet.rb lib/spreadsheet/excel/sst_entry.rb lib/spreadsheet/excel/error.rb lib/spreadsheet/excel/workbook.rb lib/spreadsheet/excel/writer/format.rb lib/spreadsheet/excel/writer/workbook.rb lib/spreadsheet/excel/writer/worksheet.rb Biff8 Writer Biff5 Biff8 Internals Offset Excel Datatypes ParseExcel Compatibility Spreadsheet dot/m_34_0.png

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

Methods

Included Modules

Spreadsheet::Excel::Writer::Biff8 Spreadsheet::Excel::Internals

Attributes

date_base  [R] 
fonts  [R] 

Public Class methods

[Source]

    # 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

Public Instance methods

[Source]

     # 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

[Source]

    # 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

[Source]

    # 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

[Source]

    # 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

[Source]

    # 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

[Source]

    # File lib/spreadsheet/excel/writer/workbook.rb, line 95
95:   def number_format_index workbook, format
96:     @number_formats[workbook][format] || 0
97:   end

[Source]

     # 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

[Source]

     # File lib/spreadsheet/excel/writer/workbook.rb, line 639
639:   def sst_index worksheet, str
640:     @sst[worksheet][str]
641:   end

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/spreadsheet/excel/writer/workbook.rb, line 132
132:   def write_bookbool workbook, writer
133:     write_placeholder writer, 0x00da
134:   end

[Source]

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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/spreadsheet/excel/writer/workbook.rb, line 270
270:   def write_eof workbook, writer
271:     write_op writer, 0x000a
272:   end

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

Write a new Excel file.

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/spreadsheet/excel/writer/workbook.rb, line 463
463:   def write_password workbook, writer
464:     write_placeholder writer, 0x0013
465:   end

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/spreadsheet/excel/writer/workbook.rb, line 473
473:   def write_protect workbook, writer
474:     write_placeholder writer, 0x0012
475:   end

[Source]

     # File lib/spreadsheet/excel/writer/workbook.rb, line 476
476:   def write_refreshall workbook, writer
477:     write_placeholder writer, 0x01b7
478:   end

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

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

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/spreadsheet/excel/writer/workbook.rb, line 642
642:   def xf_index workbook, format
643:     if fmt = @formats[workbook].find do |fm| fm.format == format end
644:       fmt.xf_index
645:     else
646:       0
647:     end
648:   end

[Validate]