diff options
Diffstat (limited to 'lib/roo/excelx.rb')
| -rwxr-xr-x[-rw-r--r--] | lib/roo/excelx.rb | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/lib/roo/excelx.rb b/lib/roo/excelx.rb index 82c1431..f9f0ee2 100644..100755 --- a/lib/roo/excelx.rb +++ b/lib/roo/excelx.rb @@ -24,8 +24,9 @@ module Roo require 'roo/excelx/sheet_doc' require 'roo/excelx/coordinate' require 'roo/excelx/format' + require 'roo/excelx/images' - delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files] => :@shared + delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files, :image_rels, :image_files] => :@shared ExceedsMaxError = Class.new(StandardError) # initialization and opening of a spreadsheet file @@ -39,7 +40,10 @@ module Roo sheet_options = {} sheet_options[:expand_merged_ranges] = (options[:expand_merged_ranges] || false) sheet_options[:no_hyperlinks] = (options[:no_hyperlinks] || false) + sheet_options[:empty_cell] = (options[:empty_cell] || false) + shared_options = {} + shared_options[:disable_html_wrapper] = (options[:disable_html_wrapper] || false) unless is_stream?(filename_or_stream) file_type_check(filename_or_stream, %w[.xlsx .xlsm], 'an Excel 2007', file_warning, packed) basename = find_basename(filename_or_stream) @@ -52,7 +56,7 @@ module Roo @tmpdir = self.class.make_tempdir(self, basename, options[:tmpdir_root]) ObjectSpace.define_finalizer(self, self.class.finalize(object_id)) - @shared = Shared.new(@tmpdir) + @shared = Shared.new(@tmpdir, shared_options) @filename = local_filename(filename_or_stream, @tmpdir, packed) process_zipfile(@filename || filename_or_stream) @@ -62,10 +66,10 @@ module Roo end end.compact @sheets = [] - @sheets_by_name = Hash[@sheet_names.map.with_index do |sheet_name, n| - @sheets[n] = Sheet.new(sheet_name, @shared, n, sheet_options) - [sheet_name, @sheets[n]] - end] + @sheets_by_name = {} + @sheet_names.each_with_index do |sheet_name, n| + @sheets_by_name[sheet_name] = @sheets[n] = Sheet.new(sheet_name, @shared, n, sheet_options) + end if cell_max cell_count = ::Roo::Utils.num_cells_in_range(sheet_for(options.delete(:sheet)).dimensions) @@ -94,7 +98,12 @@ module Roo def sheet_for(sheet) sheet ||= default_sheet validate_sheet!(sheet) - @sheets_by_name[sheet] + @sheets_by_name[sheet] || @sheets[sheet] + end + + def images(sheet = nil) + images_names = sheet_for(sheet).images.map(&:last) + images_names.map { |iname| image_files.find { |ifile| ifile[iname] } } end # Returns the content of a spreadsheet-cell. @@ -325,7 +334,7 @@ module Roo wb.extract(path) workbook_doc = Roo::Utils.load_xml(path).remove_namespaces! - workbook_doc.xpath('//sheet').map { |s| s.attributes['id'].value } + workbook_doc.xpath('//sheet').map { |s| s['id'] } end # Internal @@ -349,17 +358,13 @@ module Roo wb_rels.extract(path) rels_doc = Roo::Utils.load_xml(path).remove_namespaces! - worksheet_type = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet' relationships = rels_doc.xpath('//Relationship').select do |relationship| - relationship.attributes['Type'].value == worksheet_type + worksheet_types.include? relationship['Type'] end - relationships.inject({}) do |hash, relationship| - attributes = relationship.attributes - id = attributes['Id'] - hash[id.value] = attributes['Target'].value - hash + relationships.each_with_object({}) do |relationship, hash| + hash[relationship['Id']] = relationship['Target'] end end @@ -376,6 +381,15 @@ module Roo end end + def extract_images(entries, tmpdir) + img_entries = entries.select { |e| e.name[/media\/image([0-9]+)/] } + img_entries.each do |entry| + path = "#{@tmpdir}/roo#{entry.name.gsub(/xl\/|\//, "_")}" + image_files << path + entry.extract(path) + end + end + # Extracts all needed files from the zip file def process_zipfile(zipfilename_or_stream) @sheet_files = [] @@ -409,6 +423,7 @@ module Roo sheet_ids = extract_worksheet_ids(entries, "#{@tmpdir}/roo_workbook.xml") sheets = extract_worksheet_rels(entries, "#{@tmpdir}/roo_workbook.xml.rels") extract_sheets_in_order(entries, sheet_ids, sheets, @tmpdir) + extract_images(entries, @tmpdir) entries.each do |entry| path = @@ -435,6 +450,10 @@ module Roo # drawings, etc. nr = Regexp.last_match[1].to_i rels_files[nr - 1] = "#{@tmpdir}/roo_rels#{nr}" + when /drawing([0-9]+).xml.rels$/ + # Extracting drawing relationships to make images lists for each sheet + nr = Regexp.last_match[1].to_i + image_rels[nr - 1] = "#{@tmpdir}/roo_image_rels#{nr}" end entry.extract(path) if path @@ -442,7 +461,14 @@ module Roo end def safe_send(object, method, *args) - object.send(method, *args) if object && object.respond_to?(method) + object.send(method, *args) if object&.respond_to?(method) + end + + def worksheet_types + [ + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', # OOXML Transitional + 'http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet' # OOXML Strict + ] end end end |
