lib/write_xlsx/worksheet.rb in write_xlsx-1.11.2 vs lib/write_xlsx/worksheet.rb in write_xlsx-1.12.0

- old
+ new

@@ -111,11 +111,12 @@ @shape_hash = {} @drawing_rels = {} @drawing_rels_id = 0 @vml_drawing_rels = {} @vml_drawing_rels_id = 0 - @has_dynamic_arrays = false + @has_dynamic_functions = false + @has_embedded_images = false @use_future_functions = false @header_images = [] @footer_images = [] @@ -158,10 +159,12 @@ self.margins_top_bottom = 1 @page_setup.margin_header = 0.5 @page_setup.margin_footer = 0.5 @page_setup.header_footer_aligns = false end + + @embedded_image_indexes = @workbook.embedded_image_indexes end def set_xml_writer(filename) # :nodoc: @writer.set_xml_writer(filename) end @@ -1444,10 +1447,11 @@ formula = expand_formula(formula, 'GAMMA\(') formula = expand_formula(formula, 'GAUSS\(') formula = expand_formula(formula, 'HYPGEOM.DIST\(') formula = expand_formula(formula, 'IFNA\(') formula = expand_formula(formula, 'IFS\(') + formula = expand_formula(formula, 'IMAGE\(') formula = expand_formula(formula, 'IMCOSH\(') formula = expand_formula(formula, 'IMCOT\(') formula = expand_formula(formula, 'IMCSCH\(') formula = expand_formula(formula, 'IMCSC\(') formula = expand_formula(formula, 'IMSECH\(') @@ -1534,11 +1538,11 @@ _value = value end raise WriteXLSXInsufficientArgumentError if [_row, _col, _formula].include?(nil) # Check for dynamic array functions. - regex = /\bLET\(|\bSORT\(|\bLAMBDA\(|\bSINGLE\(|\bSORTBY\(|\bUNIQUE\(|\bXMATCH\(|\bFILTER\(|\bXLOOKUP\(|\bSEQUENCE\(|\bRANDARRAY\(|\bANCHORARRAY\(/ + regex = /\bANCHORARRAY\(|\bBYCOL\(|\bBYROW\(|\bCHOOSECOLS\(|\bCHOOSEROWS\(|\bDROP\(|\bEXPAND\(|\bFILTER\(|\bHSTACK\(|\bLAMBDA\(|\bMAKEARRAY\(|\bMAP\(|\bRANDARRAY\(|\bREDUCE\(|\bSCAN\(|\bSEQUENCE\(|\bSINGLE\(|\bSORT\(|\bSORTBY\(|\bSWITCH\(|\bTAKE\(|\bTEXTSPLIT\(|\bTOCOL\(|\bTOROW\(|\bUNIQUE\(|\bVSTACK\(|\bWRAPCOLS\(|\bWRAPROWS\(|\bXLOOKUP\(/ if _formula =~ regex return write_dynamic_array_formula( _row, _col, _row, _col, _formula, _format, _value ) end @@ -1547,11 +1551,11 @@ if _formula =~ /^\{=.*\}$/ write_array_formula(_row, _col, _row, _col, _formula, _format, _value) else check_dimensions(_row, _col) store_row_col_max_min_values(_row, _col) - _formula = _formula.sub(/^=/, '') + _formula = prepare_formula(_formula) store_data_to_table(FormulaCellData.new(_formula, _format, _value), _row, _col) end end @@ -1632,11 +1636,11 @@ # # Write a dynamic formula to the specified row and column (zero indexed). # def write_dynamic_array_formula(row1, col1, row2 = nil, col2 = nil, formula = nil, format = nil, value = nil) write_array_formula_base('d', row1, col1, row2, col2, formula, format, value) - @has_dynamic_arrays = true + @has_dynamic_functions = true end # # write_boolean(row, col, val, format) # @@ -1780,25 +1784,27 @@ # the invisible link. The visible label is the same as the link unless # an alternative label is specified. The label parameter is optional. # The label is written using the {#write()}[#method-i-write] method. Therefore it is # possible to write strings, numbers or formulas as labels. # - def write_url(row, col, url = nil, format = nil, str = nil, tip = nil) + def write_url(row, col, url = nil, format = nil, str = nil, tip = nil, ignore_write_string = false) # Check for a cell reference in A1 notation and substitute row and column if (row_col_array = row_col_notation(row)) - _row, _col = row_col_array - _url = col - _format = url - _str = format - _tip = str + _row, _col = row_col_array + _url = col + _format = url + _str = format + _tip = str + _ignore_write_string = tip else - _row = row - _col = col - _url = url - _format = format - _str = str - _tip = tip + _row = row + _col = col + _url = url + _format = format + _str = str + _tip = tip + _ignore_write_string = ignore_write_string end _format, _str = _str, _format if _str.respond_to?(:xf_index) || !_format.respond_to?(:xf_index) raise WriteXLSXInsufficientArgumentError if [_row, _col, _url].include?(nil) # Check that row and col are valid and store max and min values @@ -1812,11 +1818,11 @@ # Add the default URL format. _format ||= @default_url_format # Write the hyperlink string. - write_string(_row, _col, hyperlink.str, _format) + write_string(_row, _col, hyperlink.str, _format) unless _ignore_write_string end # # :call-seq: # write_date_time (row, col, date_string [ , format ]) @@ -1958,10 +1964,69 @@ x_scale, y_scale, url, tip, anchor, description, decorative ] end # + # Embed an image into the worksheet. + # + def embed_image(row, col, filename, options = nil) + # Check for a cell reference in A1 notation and substitute row and column. + if (row_col_array = row_col_notation(row)) + _row, _col = row_col_array + image = col + _options = filename + else + _row = row + _col = col + image = filename + _options = options + end + xf, url, tip, description, decorative = [] + + raise WriteXLSXInsufficientArgumentError if [_row, _col, image].include?(nil) + raise "Couldn't locate #{image}" unless File.exist?(image) + + # Check that row and col are valid and store max and min values + check_dimensions(_row, _col) + store_row_col_max_min_values(_row, _col) + + if options + xf = options[:cell_format] + url = options[:url] + tip = options[:tip] + description = options[:description] + decorative = options[:decorative] + end + + # Write the url without writing a string. + if url + xf ||= @default_url_format + + write_url(row, col, url, xf, nil, tip, true) + end + + # Get the image properties, mainly for the type and checksum. + image_properties = get_image_properties(image) + type = image_properties[0] + md5 = image_properties[6] + + # Check for duplicate images. + image_index = @embedded_image_indexes[md5] + + unless ptrue?(image_index) + @workbook.embedded_images << [image, type, description, decorative] + + image_index = @workbook.embedded_images.size + @embedded_image_indexes[md5] = image_index + end + + # Write the cell placeholder. + store_data_to_table(EmbedImageCellData.new(image_index, xf), _row, _col) + @has_embedded_images = true + end + + # # :call-seq: # repeat_formula(row, column, formula [ , format ]) # # Deprecated. This is a writeexcel gem's method that is no longer # required by WriteXLSX. @@ -2797,14 +2862,18 @@ sparkline.write_sparkline_group(@writer) end end end - def has_dynamic_arrays? - @has_dynamic_arrays + def has_dynamic_functions? + @has_dynamic_functions end + def has_embedded_images? + @has_embedded_images + end + private # # Compare adjacent column information structures. # @@ -3276,10 +3345,11 @@ @drawing_links << [rel_type, target, target_mode] if target && !@drawing_rels[url] drawing.url_rel_index = drawing_rel_index(url) end @drawing_links << ['/image', "../media/image#{image_id}.#{image_type}"] unless @drawing_rels[md5] + drawing.rel_index = drawing_rel_index(md5) end public :prepare_image def prepare_header_image(image_id, width, height, name, image_type, position, x_dpi, y_dpi, md5) @@ -4254,12 +4324,13 @@ # Get the link data for this cell. link = @hyperlinks[row_num][col_num] # If the cell isn't a string then we have to add the url as # the string to display - if ptrue?(@cell_data_table) && - ptrue?(@cell_data_table[row_num]) && - ptrue?(@cell_data_table[row_num][col_num]) && @cell_data_table[row_num][col_num].display_url_string? + if ptrue?(@cell_data_table) && + ptrue?(@cell_data_table[row_num]) && + ptrue?(@cell_data_table[row_num][col_num]) && + @cell_data_table[row_num][col_num].display_url_string? link.display_on end if link.respond_to?(:external_hyper_link) # External link with rel file relationship.