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