Class: RubyXL::Workbook

Inherits:
OOXMLTopLevelObject show all
Includes:
Enumerable, RelationshipSupport, WorkbookConvenienceMethods
Defined in:
lib/rubyXL/objects/workbook.rb

Overview

Constant Summary collapse

CONTENT_TYPE =
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml'
CONTENT_TYPE_WITH_MACROS =
'application/vnd.ms-excel.sheet.macroEnabled.main+xml'
REL_TYPE =
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument'
SHEET_NAME_FORBIDDEN_CHARS =
/[\/\\\*\[\]\:\?]/
DATE1904 =
DateTime.new(1904, 1, 1)
DATE1899 =

Subtracting one day to accomodate for erroneous 1900 leap year compatibility only for 1900 based dates

DateTime.new(1899, 12, 31) - 1
MARCH_1_1900 =
61
APPLICATION =
'Microsoft Macintosh Excel'
APPVERSION =
'12.0000'

Constants included from WorkbookConvenienceMethods

RubyXL::WorkbookConvenienceMethods::SHEET_NAME_TEMPLATE

Constants inherited from OOXMLTopLevelObject

OOXMLTopLevelObject::ROOT, OOXMLTopLevelObject::SAVE_ORDER

Instance Attribute Summary collapse

Attributes included from RelationshipSupport

#generic_storage, #relationship_container

Attributes inherited from OOXMLTopLevelObject

#root

Attributes included from OOXMLObjectInstanceMethods

#local_namespaces

Instance Method Summary collapse

Methods included from WorkbookConvenienceMethods

#[], #add_worksheet, #application, #application=, #appversion, #appversion=, #borders, #cell_xfs, #company, #company=, #created_at, #created_at=, #creator, #creator=, #date1904, #date1904=, #each, #fills, #fonts, #get_fill_color, #modified_at, #modified_at=, #modifier, #modifier=, #modify_alignment, #modify_border, #modify_border_color, #modify_fill, #register_new_fill, #register_new_font, #register_new_xf

Methods included from RelationshipSupport

#attach_relationship, #collect_related_objects, included, #load_relationships, #store_relationship

Methods inherited from OOXMLTopLevelObject

#add_to_zip, #file_index, parse_file, set_namespaces

Methods included from OOXMLObjectInstanceMethods

#==, included, #index_in_collection, #write_xml

Constructor Details

#initialize(worksheets = [], src_file_path = nil, creator = nil, modifier = nil, created_at = nil, company = '', application = APPLICATION, appversion = APPVERSION, date1904 = 0) ⇒ Workbook



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
# File 'lib/rubyXL/objects/workbook.rb', line 432

def initialize(worksheets = [], src_file_path = nil, creator = nil, modifier = nil, created_at = nil,
               company = '', application = APPLICATION, appversion = APPVERSION, date1904 = 0)
  super()

  # Order of sheets in the +worksheets+ array corresponds to the order of pages in Excel UI.
  # SheetId's, rId's, etc. are completely unrelated to ordering.
  @worksheets = worksheets
  add_worksheet if @worksheets.empty?

  @theme                    = RubyXL::Theme.default
  @shared_strings_container = RubyXL::SharedStringsTable.new
  @stylesheet               = RubyXL::Stylesheet.default
  @relationship_container   = RubyXL::OOXMLRelationshipsFile.new
  @root                     = RubyXL::WorkbookRoot.default
  @root.workbook            = self
  @root.source_file_path    = src_file_path

  creation_time = DateTime.parse(created_at) rescue DateTime.now
  self.created_at  = creation_time
  self.modified_at = creation_time
  self.company     = company
  self.application = application
  self.appversion  = appversion
  self.creator     = creator
  self.modifier    = modifier
  self.date1904    = date1904 > 0
end

Instance Attribute Details

#worksheetsObject

Returns the value of attribute worksheets.



359
360
361
# File 'lib/rubyXL/objects/workbook.rb', line 359

def worksheets
  @worksheets
end

Instance Method Details

#before_write_xmlObject



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/rubyXL/objects/workbook.rb', line 361

def before_write_xml
  max_sheet_id = worksheets.collect(&:sheet_id).compact.max || 0

  self.sheets = RubyXL::Sheets.new

  worksheets.each { |sheet, i|
    rel = relationship_container.find_by_target(sheet.xlsx_path)

    raise "Worksheet name '#{sheet.sheet_name}' contains forbidden characters" if sheet.sheet_name =~ SHEET_NAME_FORBIDDEN_CHARS

    sheets << RubyXL::Sheet.new(:name     => sheet.sheet_name[0..30], # Max sheet name length is 31 char
                                :sheet_id => sheet.sheet_id || (max_sheet_id += 1),
                                :state    => sheet.state,
                                :r_id     => rel.id)
  }

  true
end

#content_typeObject



311
312
313
# File 'lib/rubyXL/objects/workbook.rb', line 311

def content_type
  if macros then CONTENT_TYPE_WITH_MACROS else CONTENT_TYPE end
end

#date_to_num(date) ⇒ Object



414
415
416
# File 'lib/rubyXL/objects/workbook.rb', line 414

def date_to_num(date)
  date && (date.ajd - base_date().ajd).to_f
end

#num_to_date(num) ⇒ Object



418
419
420
421
422
423
424
425
# File 'lib/rubyXL/objects/workbook.rb', line 418

def num_to_date(num)
  # Bug-for-bug Excel compatibility (https://support.microsoft.com/kb/214058/)
  if num && num < MARCH_1_1900 then
    num += 1 unless workbook_properties && workbook_properties.date1904
  end

  num && (base_date + num)
end


315
316
317
# File 'lib/rubyXL/objects/workbook.rb', line 315

def related_objects
  [ calculation_chain, stylesheet, theme, shared_strings_container, macros ] + @worksheets
end

#save(dst_file_path = nil) ⇒ Object Also known as: write

Save the resulting XLSX file to the specified location



390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/rubyXL/objects/workbook.rb', line 390

def save(dst_file_path = nil)
  dst_file_path ||= root.source_file_path

  extension = File.extname(dst_file_path)
  unless %w{.xlsx .xlsm}.include?(extension.downcase)
    raise "Unsupported extension: #{extension} (only .xlsx and .xlsm files are supported)."
  end

  File.open(dst_file_path, "wb") { |output_file| FileUtils.copy_stream(root.stream, output_file) }

  return dst_file_path
end

#streamObject

Return the resulting XLSX file in a stream (useful for sending over HTTP)



385
386
387
# File 'lib/rubyXL/objects/workbook.rb', line 385

def stream
  root.stream
end

#xlsx_pathObject



380
381
382
# File 'lib/rubyXL/objects/workbook.rb', line 380

def xlsx_path
  ROOT.join('xl', 'workbook.xml')
end