class ReplaceArraysWithSingleCellsAst

Constants

ERROR

Attributes

need_to_replace[RW]
ref[RW]

Public Instance Methods

all_references?(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 204
def all_references?(ast)
  ast[1..-1].all? do |row|
    row[1..-1].all? do |cell|
      cell.original.first == :sheet_reference
    end
  end
end
check_choose(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 95
def check_choose(ast)
  replacement_made = false
  i = 2
  while i < ast.length
    if ast[i].first == :array
      replacement_made = true
      ast[i] = try_and_convert_array(ast[i])
    end
    i +=1
  end
  replacement_made
end
check_if(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 121
def check_if(ast)
  replacement_made = false
  if ast[2] && ast[2].first == :array
    replacement_made = true
    ast[2] = try_and_convert_array(ast[2])
  end
  if ast[3] && ast[3].first == :array
    replacement_made = true
    ast[3] = try_and_convert_array(ast[3])
  end
  if ast[4] && ast[4].first == :array
    replacement_made = true
    ast[4] = try_and_convert_array(ast[4])
  end
  replacement_made

end
check_index(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 108
def check_index(ast)
  replacement_made = false
  if ast[3] && ast[3].first == :array
    replacement_made = true
    ast[3] = try_and_convert_array(ast[3])
  end
  if ast[4] && ast[4].first == :array
    replacement_made = true
    ast[4] = try_and_convert_array(ast[4])
  end
  replacement_made
end
check_indirect(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 146
def check_indirect(ast)
  return false unless ast[2].first == :array
  ast[2] = try_and_convert_array(ast[2])
  true
end
check_match(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 139
def check_match(ast)
  return false unless ast[2].first == :array
  ast[2] = try_and_convert_array(ast[2])
  ast[3..-1].each { |a| do_map(a) }
  true
end
check_offset(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 152
def check_offset(ast)
  replacement_made = false
  #We ALWAYS leave the reference unchanged
  #if ast[2] && ast[2].first == :array
  #  replacement_made = true
  #  ast[2] = try_and_convert_array(ast[2])
  #end
  if ast[3] && ast[3].first == :array
    replacement_made = true
    ast[3] = try_and_convert_array(ast[3])
  end
  if ast[4] && ast[4].first == :array
    replacement_made = true
    ast[4] = try_and_convert_array(ast[4])
  end
  if ast[5] && ast[5].first == :array
    replacement_made = true
    ast[5] = try_and_convert_array(ast[5])
  end
  if ast[6] && ast[6].first == :array
    replacement_made = true
    ast[6] = try_and_convert_array(ast[6])
  end
  replacement_made
end
check_sumifs(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 178
def check_sumifs(ast)
  replacement_made = false
  i = 4
  while i < ast.length
    if ast[i].first == :array
      replacement_made = true
      ast[i] = try_and_convert_array(ast[i])
    end
    i +=2
  end
  replacement_made
end
do_map(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 31
def do_map(ast)
  return ast unless ast.is_a?(Array)
  map_if_required(ast)
  case ast.first
  when :arithmetic
    left, op, right = ast[1], ast[2], ast[3]
    if left.first == :array || right.first == :array
      left = try_and_convert_array(left)
      right = try_and_convert_array(right)
      ast.replace([:arithmetic, left, op, right])
    end
  when :comparison
    left, op, right = ast[1], ast[2], ast[3]
    if left.first == :array || right.first == :array
      left = try_and_convert_array(left)
      right = try_and_convert_array(right)
      ast.replace([:comparison, left, op, right])
    end
  when :prefix
    op, left = ast[1], ast[2]
    if left.first == :array
      left = try_and_convert_array(left)
      ast.replace([:prefix, op, left])
    end
  when :string_join
    strings = ast[1..-1]
    if strings.any? { |s| s.first == :array }
      strings = strings.map { |s| try_and_convert_array(s) }
      ast.replace([:string_join, *strings])
    end
  when :function
    if ast[1] == :SUMIF && ast[3].first == :array
      ast[3] = try_and_convert_array(ast[3])
    elsif ast[1] == :SUMIFS && check_sumifs(ast)
      # Replacement madein check_sumif function
    elsif ast[1] == :MATCH && check_match(ast)
      # Replacement made in check_match function
    elsif ast[1] == :INDIRECT && check_indirect(ast)
      # Replacement made in check function
    elsif ast[1] == :OFFSET && check_offset(ast)
      # Replacement made in check function
    elsif ast[0] == :function && ast[1] == :INDEX && check_index(ast)
      # Replacement made in check
    end
  end
end
map(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 10
def map(ast)
  @need_to_replace = false
  return unless ast.is_a?(Array)
  map_if_required(ast)
  if ast.first == :array
    @need_to_replace = true
    new_ast = try_and_convert_array(ast)
    return ERROR if new_ast.first == :array
    return new_ast
  # Special case, only change if at the top level
  elsif ast[0] == :function && ast[1] == :CHOOSE && check_choose(ast)
    # Replacement made in check
  # Special case, only change if at the top level
  elsif ast[0] == :function && ast[1] == :IF && check_if(ast)
    # Replacement made in check
  else
    do_map(ast)
  end
  ast
end
map_if_required(arguments) click to toggle source

This tries to speed up the process by not recursively checking arguments that we know won't be interesting

# File src/simplify/replace_arrays_with_single_cells.rb, line 80
def map_if_required(arguments)
  return arguments unless arguments.is_a?(Array)
  arguments.each do |a|
    next unless a.is_a?(Array)
    case a.first
    when :error, :null, :space, :boolean_true, :boolean_false, :number, :string
      next
    when :sheet_reference, :table_reference, :local_table_reference
      next
    else
      do_map(a)
    end
  end
end
single_column(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 228
def single_column(ast)
  r = Reference.for(ref.last)
  r.calculate_excel_variables
  row = r.excel_row
  sheet = ref.first

  cells = ast[1..-1].map { |row| row.last }
  match = cells.find do |cell|
    s = cell.original[1]
    r = cell.original[2][1][/([A-Za-z]{1,3})(\d+)/,2]
    sheet == s && row == r
  end

  match || ast
end
single_row(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 212
def single_row(ast)
  r = Reference.for(ref.last)
  r.calculate_excel_variables
  column = r.excel_column
  sheet = ref.first

  cells = ast[1][1..-1]
  match = cells.find do |cell|
    s = cell.original[1]
    c = cell.original[2][1][/([A-Za-z]{1,3})/,1]
    sheet == s && column == c
  end

  match || ast
end
try_and_convert_array(ast) click to toggle source
# File src/simplify/replace_arrays_with_single_cells.rb, line 191
def try_and_convert_array(ast)
  return ast unless ast.first == :array
  return ast unless all_references?(ast)
  #return ast unless ast[1..-1].all? { |c| c.first == :sheet_reference }
  if ast.length == 2
    single_row(ast)
  elsif ast[1].length == 2
    single_column(ast)
  else
    ast
  end
end