# encoding: UTF-8 module Axlsx # The Shared String Table class is responsible for managing and serializing common strings in a workbook. # While the ECMA-376 spec allows for both inline and shared strings it seems that at least some applications like iWorks Numbers # and Google Docs require that the shared string table is populated in order to interoperate properly. # As a developer, you should never need to directly work against this class. Simply set 'use_shared_strings' # on the package or workbook to generate a package that uses the shared strings table instead of inline strings. # @note Serialization performance is affected by using this serialization method so if you do not need interoperability # it is recomended that you use the default inline string method of serialization. class SharedStringsTable # The total number of strings in the workbook including duplicates # Empty cells are treated as blank strings # @return [Integer] attr_reader :count # The total number of unique strings in the workbook. # @return [Integer] def unique_count @unique_cells.size end # An array of unique cells. Multiple attributes of the cell are used in comparison # each of these unique cells is parsed into the shared string table. # @see Cell#sharable attr_reader :unique_cells # The xml:space attribute # @see Workbook#xml_space attr_reader :xml_space # Creates a new Shared Strings Table agains an array of cells # @param [Array] cells This is an array of all of the cells in the workbook # @param [Symbol] xml_space The xml:space behavior for the shared string table. def initialize(cells, xml_space=:preserve) @index = 0 @xml_space = xml_space @unique_cells = {} @shared_xml_string = "" shareable_cells = cells.flatten.select{ |cell| cell.plain_string? } @count = shareable_cells.size resolve(shareable_cells) end # Serializes the object # @param [String] str # @return [String] def to_xml_string(str='') str << '' << @shared_xml_string << '' str = Axlsx::sanitize(str) end private # Interate over all of the cells in the array. # if our unique cells array does not contain a sharable cell, # add the cell to our unique cells array and set the ssti attribute on the index of this cell in the shared strings table # if a sharable cell already exists in our unique_cells array, set the ssti attribute of the cell and move on. # @return [Array] unique cells def resolve(cells) cells.each do |cell| cell_hash = cell.value if index = @unique_cells[cell_hash] cell.send :ssti=, index else cell.send :ssti=, @index @shared_xml_string << '' << CellSerializer.run_xml_string(cell) << '' @unique_cells[cell_hash] = @index @index += 1 end end end end end