lib/workbook/row.rb in workbook-0.8.1 vs lib/workbook/row.rb in workbook-0.8.2
- old
+ new
@@ -1,35 +1,30 @@
# frozen_string_literal: true
-
-# -*- encoding : utf-8 -*-
# frozen_string_literal: true
+
module Workbook
- class Row < Array
+ class Row
include Workbook::Modules::Cache
+ include Enumerable
+ extend Forwardable
- alias_method :compare_without_header, :<=>
- attr_accessor :placeholder # The placeholder attribute is used in compares (corresponds to newly created or removed lines (depending which side you're on)
+ attr_accessor :placeholder # The placeholder attribute is used in compares (corresponds to newly created or removed lines (depending which side you're on)
attr_accessor :format
+ attr_reader :cells
+ delegate [:first, :last, :pop, :delete_at, :each, :count, :include?, :index, :delete_if, :to_csv, :length, :empty?] => :@cells
+
# Initialize a new row
#
# @param [Workbook::Row, Array<Workbook::Cell>, Array] cells list of cells to initialize the row with, default is empty
# @param [Workbook::Table] table a row normally belongs to a table, reference it here
# @param [Hash] options Supported options: parse_cells_on_batch_creation (parse cell values during row-initalization, default: false), cell_parse_options (default {}, see Workbook::Modules::TypeParser)
- def initialize cells=[], table=nil, options={}
- options=options ? {:parse_cells_on_batch_creation=>false,:cell_parse_options=>{},:clone_cells=>false}.merge(options) : {}
- cells = [] if cells==nil
- self.table= table
- cells.each do |c|
- if c.is_a? Workbook::Cell
- c = c.clone if options[:clone_cells]
- else
- c = Workbook::Cell.new(c, {row:self})
- c.parse!(options[:cell_parse_options]) if options[:parse_cells_on_batch_creation]
- end
- push c
- end
+ def initialize cells = [], table = nil, options = {}
+ options = options ? {parse_cells_on_batch_creation: false, cell_parse_options: {}, clone_cells: false}.merge(options) : {}
+ @cells = []
+ add_cells(cells, options)
+ self.table = table
end
# An internal function used in diffs
#
# @return [Boolean] returns true when this row is not an actual row, but a placeholder row to 'compare' against
@@ -53,159 +48,155 @@
# Set reference to the table this row belongs to and add the row to this table
#
# @param [Workbook::Table] t the table this row belongs to
def table= t
- raise ArgumentError, "table should be a Workbook::Table (you passed a #{t.class})" unless t.is_a?(Workbook::Table) or t == nil
+ raise ArgumentError, "table should be a Workbook::Table (you passed a #{t.class})" unless t.is_a?(Workbook::Table) || t.nil?
if t
@table = t
- table.push(self) #unless table.index(self) and self.placeholder?
+ table << self
end
end
- # Add cell
- # @param [Workbook::Cell, Numeric,String,Time,Date,TrueClass,FalseClass,NilClass] cell or value to add
- def push(cell)
- cell = Workbook::Cell.new(cell, {row:self}) unless cell.class == Workbook::Cell
- super(cell)
+ # Add row
+ # @param [Workbook::Table, Array] row(s) to add
+ def push(*args)
+ args.each do |arg|
+ self.<<(arg)
+ end
end
+ alias_method :append, :push
# Add cell
# @param [Workbook::Cell, Numeric,String,Time,Date,TrueClass,FalseClass,NilClass] cell or value to add
def <<(cell)
- cell = Workbook::Cell.new(cell, {row:self}) unless cell.class == Workbook::Cell
- super(cell)
+ @cells << (cell.is_a?(Workbook::Cell) ? cell : Workbook::Cell.new(cell, {row: self}))
end
# plus
# @param [Workbook::Row, Array] row to add
# @return [Workbook::Row] a new row, not linked to the table
- def +(row)
- rv = super(row)
- rv = Workbook::Row.new(rv) unless rv.class == Workbook::Row
- return rv
+ def +(other)
+ Workbook::Row.new(@cells + Row.new(other).cells)
end
# concat
# @param [Workbook::Row, Array] row to add
# @return [self] self
def concat(row)
- row = Workbook::Row.new(row) unless row.class == Workbook::Row
- super(row)
+ @cells.concat(Workbook::Row.new(row).cells)
+ self
end
-
# Overrides normal Array's []-function with support for symbols that identify a column based on the header-values and / or
#
# @example Lookup using fixnum or header value encoded as symbol
# row[1] #=> <Cell value="a">
# row["A"] #=> <Cell value="a">
# row[:a] #=> <Cell value="a">
#
- # @param [Fixnum, Symbol, String] index_or_hash that identifies the column (strings are converted to symbols)
+ # @param [Integer, Symbol, String] index_or_hash that identifies the column (strings are converted to symbols)
# @return [Workbook::Cell, nil]
def [](index_or_hash)
if index_or_hash.is_a? Symbol
rv = nil
begin
rv = to_hash[index_or_hash]
rescue NoMethodError
end
- return rv
- elsif index_or_hash.is_a? String and index_or_hash.match(/^[A-Z]*$/)
+ rv
+ elsif index_or_hash.is_a?(String) && index_or_hash.match(/^[A-Z]*$/)
# it looks like a column indicator
- return to_a[Workbook::Column.alpha_index_to_number_index(index_or_hash)]
+ @cells[Workbook::Column.alpha_index_to_number_index(index_or_hash)]
elsif index_or_hash.is_a? String
- symbolized = Workbook::Cell.new(index_or_hash, {row:self}).to_sym
+ symbolized = Workbook::Cell.new(index_or_hash, {row: self}).to_sym
self[symbolized]
- else
- if index_or_hash
- return to_a[index_or_hash]
- end
+ elsif index_or_hash
+ @cells[index_or_hash]
end
end
# Overrides normal Array's []=-function with support for symbols that identify a column based on the header-values
#
# @example Lookup using fixnum or header value encoded as symbol (strings are converted to symbols)
# row[1] #=> <Cell value="a">
# row[:a] #=> <Cell value="a">
#
- # @param [Fixnum, Symbol, String] index_or_hash that identifies the column
- # @param [String, Fixnum, NilClass, Date, DateTime, Time, Float] value
+ # @param [Integer, Symbol, String] index_or_hash that identifies the column
+ # @param [String, Integer, NilClass, Date, DateTime, Time, Float] value
# @return [Workbook::Cell, nil]
def []= index_or_hash, value
index = index_or_hash
if index_or_hash.is_a? Symbol
index = table_header_keys.index(index_or_hash)
- elsif index_or_hash.is_a? String and index_or_hash.match(/^[A-Z]*$/)
+ elsif index_or_hash.is_a?(String) && index_or_hash.match(/^[A-Z]*$/)
# it looks like a column indicator
index = Workbook::Column.alpha_index_to_number_index(index_or_hash)
elsif index_or_hash.is_a? String
- symbolized = Workbook::Cell.new(index_or_hash, {row:self}).to_sym
+ symbolized = Workbook::Cell.new(index_or_hash, {row: self}).to_sym
index = table_header_keys.index(symbolized)
end
value_celled = Workbook::Cell.new
if value.is_a? Workbook::Cell
value_celled = value
else
- current_cell = self[index]
+ current_cell = @cells[index]
if current_cell.is_a? Workbook::Cell
value_celled = current_cell
end
- value_celled.value=(value)
+ value_celled.value = value
end
value_celled.row = self
- super(index,value_celled)
+ @cells[index] = value_celled
end
# Returns an array of cells allows you to find cells by a given color, normally a string containing a hex
#
# @param [String] color a CSS-style hex-string
# @param [Hash] options Option :hash_keys (default true) returns row as an array of symbols
# @return [Array<Symbol>, Workbook::Row<Workbook::Cell>]
- def find_cells_by_background_color color=:any, options={}
- options = {:hash_keys=>true}.merge(options)
- cells = self.collect {|c| c if c.format.has_background_color?(color) }.compact
- r = Row.new cells
+ def find_cells_by_background_color color = :any, options = {}
+ options = {hash_keys: true}.merge(options)
+ found_cells = @cells.collect { |c| c if c.format.has_background_color?(color) }.compact
+ r = Row.new found_cells
options[:hash_keys] ? r.to_symbols : r
end
# Returns true when the row belongs to a table and it is the header row (typically the first row)
#
# @return [Boolean]
def header?
- table != nil and self.object_id == table_header.object_id
+ !table.nil? && (object_id == table_header.object_id)
end
# Is this the first row in the table
#
# @return [Boolean, NilClass] returns nil if it doesn't belong to a table, false when it isn't the first row of a table and true when it is.
def first?
- table != nil and self.object_id == table.first.object_id
+ !table.nil? && (object_id == table.first.object_id)
end
# Returns true when all the cells in the row have values whose to_s value equals an empty string
#
# @return [Boolean]
def no_values?
- all? {|c| c.value.to_s == ''}
+ @cells.all? { |c| c.value.to_s == "" }
end
# Converts a row to an array of symbol representations of the row content, see also: Workbook::Cell#to_sym
# @return [Array<Symbol>] returns row as an array of symbols
def to_symbols
- fetch_cache(:to_symbols){
- collect{|c| c.to_sym}
+ fetch_cache(:to_symbols) {
+ @cells.collect { |c| c.to_sym }
}
end
# Converts the row to an array of Workbook::Cell's
# @return [Array<Workbook::Cell>] returns row as an array of symbols
def to_a
- self.collect{|c| c}
+ @cells
end
def table_header
table.header
end
@@ -217,95 +208,119 @@
# Returns a hash representation of this row
#
# @return [Hash]
def to_hash
keys = table_header_keys
- values = self
+ values = @cells
hash = {}
- keys.each_with_index {|k,i| hash[k]=values[i]}
- return hash
+ keys.each_with_index { |k, i| hash[k] = values[i] }
+ hash
end
# Quick assessor to the book's template, if it exists
#
# @return [Workbook::Template]
def template
- table.template if table
+ table&.template
end
# Returns a hash representation of this row
#
# it differs from #to_hash as it doesn't contain the Workbook's Workbook::Cell-objects,
# but the actual values contained in these cells
#
# @return [Hash]
def to_hash_with_values
- keys = table_header_keys
- values = self
@hash_with_values = {}
- keys.each_with_index {|k,i| v=values[i]; v=v.value if v; @hash_with_values[k]=v}
- return @hash_with_values
+ table_header_keys.each_with_index { |k, i| @hash_with_values[k] = @cells[i]&.value }
+ @hash_with_values
end
# Compares one row wiht another
#
# @param [Workbook::Row] other row to compare against
# @return [Workbook::Row] a row with the diff result.
def <=> other
- a = self.header? ? 0 : 1
+ a = header? ? 0 : 1
b = other.header? ? 0 : 1
- return (a <=> b) if (a==0 or b==0)
- compare_without_header other
+ return (a <=> b) if (a == 0) || (b == 0)
+ @cells <=> other.cells
end
+ def == other
+ @cells.map(&:value) == other.is_a?(Workbook::Row) ? other.cells.map(&:value) : other
+ end
+
# The first cell of the row is considered to be the key
#
# @return [Workbook::Cell] the key cell
def key
first
end
# Compact detaches the row from the table
def compact
- r = self.clone
- r = r.collect{|c| c unless c.nil?}.compact
+ clone.collect { |c| c unless c.nil? }.compact
end
# clone the row with together with the cells
#
# @return [Workbook::Row] a cloned copy of self with cells
def clone
- Workbook::Row.new(self, nil, {:clone_cells=>true})
+ Workbook::Row.new(self, nil, {clone_cells: true})
end
# remove all the trailing nil-cells (returning a trimmed clone)
#
# @param [Integer] desired_length of the new row
# @return [Workbook::Row] a trimmed clone of the array
- def trim(desired_length=nil)
- self.clone.trim!(desired_length)
+ def trim(desired_length = nil)
+ clone.trim!(desired_length)
end
# remove all the trailing nil-cells (returning a trimmed self)
#
# @param [Integer] desired_length of the new row
# @return [Workbook::Row] self
- def trim!(desired_length=nil)
- self_count = self.count-1
- self.count.times do |index|
+ def trim!(desired_length = nil)
+ self_count = count - 1
+ count.times do |index|
index = self_count - index
- if desired_length and index < desired_length
+ if desired_length && (index < desired_length)
break
- elsif desired_length and index >= desired_length
- self.delete_at(index)
+ elsif desired_length && (index >= desired_length)
+ delete_at(index)
elsif self[index].nil?
- self.delete_at(index)
+ delete_at(index)
else
break
end
end
- (desired_length - self.count).times{|a| self << (Workbook::Cell.new(nil))} if desired_length and (desired_length - self.count) > 0
+ (desired_length - count).times { |a| @cells << Workbook::Cell.new(nil) } if desired_length && ((desired_length - count) > 0)
self
+ end
+
+ private
+
+ # Only to be used on initialization
+ # @param [Workbook::Row, Array<Workbook::Cell>, Array] cells list of cells to initialize the row with, default is empty
+ # @param [Hash] options Supported options: parse_cells_on_batch_creation (parse cell values during row-initalization, default: false), cell_parse_options (default {}, see Workbook::Modules::TypeParser)
+ def add_cells cells = [], options = {}
+ return nil if cells.nil?
+ cells.each do |c|
+ @cells << (prepare_cell(c, options))
+ end
+ end
+
+ def prepare_cell cell, options
+ if cell.is_a? Workbook::Cell
+ cell = cell.clone if options[:clone_cells]
+ else
+ cell = Workbook::Cell.new(cell, {row: self})
+ cell.parse!(options[:cell_parse_options]) if options[:parse_cells_on_batch_creation]
+ end
+
+ cell
end
end
end