# encoding: UTF-8 module Axlsx # Table # @note Worksheet#add_pivot_table is the recommended way to create tables for your worksheets. # @see README for examples class PivotTable include Axlsx::OptionsParser # Creates a new PivotTable object # @param [String] ref The reference to where the pivot table lives like 'G4:L17'. # @param [String] range The reference to the pivot table data like 'A1:D31'. # @param [Worksheet] sheet The sheet containing the table data. # @option options [Cell, String] name # @option options [TableStyle] style def initialize(ref, range, sheet, options={}) @ref = ref self.range = range @sheet = sheet @sheet.workbook.pivot_tables << self @name = "PivotTable#{index+1}" @rows = [] @columns = [] @data = [] @pages = [] parse_options options yield self if block_given? end # The reference to the table data # @return [String] attr_reader :ref # The name of the table. # @return [String] attr_reader :name # The name of the sheet. # @return [String] attr_reader :sheet # The range where the data for this pivot table lives. # @return [String] attr_reader :range # (see #range) def range=(v) DataTypeValidator.validate "#{self.class}.range", [String], v if v.is_a?(String) @range = v end end # The rows # @return [Array] attr_reader :rows # (see #rows) def rows=(v) DataTypeValidator.validate "#{self.class}.rows", [Array], v v.each do |ref| DataTypeValidator.validate "#{self.class}.rows[]", [String], ref end @rows = v end # The columns # @return [Array] attr_reader :columns # (see #columns) def columns=(v) DataTypeValidator.validate "#{self.class}.columns", [Array], v v.each do |ref| DataTypeValidator.validate "#{self.class}.columns[]", [String], ref end @columns = v end # The data # @return [Array] attr_reader :data # (see #data) def data=(v) DataTypeValidator.validate "#{self.class}.data", [Array], v v.each do |ref| DataTypeValidator.validate "#{self.class}.data[]", [String], ref end @data = v end # The pages # @return [String] attr_reader :pages # (see #pages) def pages=(v) DataTypeValidator.validate "#{self.class}.pages", [Array], v v.each do |ref| DataTypeValidator.validate "#{self.class}.pages[]", [String], ref end @pages = v end # The index of this chart in the workbooks charts collection # @return [Integer] def index @sheet.workbook.pivot_tables.index(self) end # The part name for this table # @return [String] def pn "#{PIVOT_TABLE_PN % (index+1)}" end # The relationship part name of this pivot table # @return [String] def rels_pn "#{PIVOT_TABLE_RELS_PN % (index+1)}" end # The cache_definition for this pivot table # @return [PivotTableCacheDefinition] def cache_definition @cache_definition ||= PivotTableCacheDefinition.new(self) end # The worksheet relationships. This is managed automatically by the worksheet # @return [Relationships] def relationships r = Relationships.new r << Relationship.new(PIVOT_TABLE_CACHE_DEFINITION_R, "../#{cache_definition.pn}") r end # The relation reference id for this table # @return [String] def rId "rId#{index+1}" end # Serializes the object # @param [String] str # @return [String] def to_xml_string(str = '') str << '' str << '' str << '' str << '' header_cell_values.each do |cell_value| str << pivot_field_for(cell_value) end str << '' if rows.empty? str << '' str << ' ' else str << '' rows.each do |row_value| str << '' end str << '' str << '' rows.size.times do |i| str << '' end str << '' end if columns.empty? str << '' else str << '' columns.each do |column_value| str << '' end str << '' end unless pages.empty? str << '' pages.each do |page_value| str << '' end str << '' end unless data.empty? str << '' data.each do |datum_value| str << '' end str << '' end str << '' end # References for header cells # @return [Array] def header_cell_refs Axlsx::range_to_a(header_range).first end # The header cells for the pivot table # @return [Array] def header_cells @sheet[header_range] end # The values in the header cells collection # @return [Array] def header_cell_values header_cells.map(&:value) end # The number of cells in the header_cells collection # @return [Integer] def header_cells_count header_cells.count end # The index of a given value in the header cells # @return [Integer] def header_index_of(value) header_cell_values.index(value) end private def pivot_field_for(cell_ref) if rows.include? cell_ref '' << '' << '' elsif columns.include? cell_ref '' << '' << '' elsif pages.include? cell_ref '' << '' << '' elsif data.include? cell_ref '' << '' else '' << '' end end def header_range range.gsub(/^(\w+?)(\d+)\:(\w+?)\d+$/, '\1\2:\3\2') end end end