class InlineFormulaeAst

Attributes

count_replaced[RW]
current_sheet_name[RW]
inline_ast[RW]
references[RW]

Public Class Methods

new(references = nil, current_sheet_name = nil, inline_ast = nil) click to toggle source
# File src/simplify/inline_formulae.rb, line 22
def initialize(references = nil, current_sheet_name = nil, inline_ast = nil)
  @references, @current_sheet_name, @inline_ast = references, [current_sheet_name], inline_ast
  @count_replaced = 0
  @inline_ast ||= lambda { |sheet, ref, references| true } # Default is to always inline
end

Public Instance Methods

ast_or_blank(sheet, ref) click to toggle source
# File src/simplify/inline_formulae.rb, line 95
def ast_or_blank(sheet, ref)
  ast_to_inline = references[[sheet, ref]]
  return ast_to_inline if ast_to_inline
  # Need to add a new blank cell and return ast for an inlined blank
  references[[sheet, ref]] = [:blank]
  [:inlined_blank]
end
cell(ast) click to toggle source

Format [:cell, ref]

# File src/simplify/inline_formulae.rb, line 81
def cell(ast)
  sheet = current_sheet_name.last
  ref = ast[1].to_s.upcase.gsub('$', '').to_sym
  if inline_ast.call(sheet, ref, references)
    ast_to_inline = ast_or_blank(sheet, ref)
    @count_replaced += 1
    map(ast_to_inline)
    ast.replace(ast_to_inline)
  # FIXME: Check - is this right? does it work recursively enough?
  elsif current_sheet_name.size > 1 
    ast.replace([:sheet_reference, sheet, ast.dup])
  end
end
function(ast) click to toggle source
# File src/simplify/inline_formulae.rb, line 45
def function(ast)
  case ast[1]
  when :OFFSET
    # Don't map the second argument - it should be left as a cell refernce
    if (ast[2][0] == :cell || ast[2][0] == :sheet_reference)
      ast[3..-1].each {|a| map(a) }
    else
      ast.each { |a| map(a) }
    end
  when :COLUMN, :ROW
    # Don't map any arguments
  else
    # Otherwise good to map all the other arguments
    ast.each { |a| map(a) }
  end
end
map(ast) click to toggle source
# File src/simplify/inline_formulae.rb, line 28
def map(ast)
  return ast unless ast.is_a?(Array)
  case ast[0]
  when :function
    function(ast)
  when :sheet_reference
    sheet_reference(ast)
  when :cell
    cell(ast)
  else
    ast.each do |a| 
      map(a) if a.is_a?(Array)
    end
  end
  ast
end
sheet_reference(ast) click to toggle source

Should be of the form [:sheet_reference, sheet_name, reference] FIXME: Can we rely on reference always being a [:cell, ref] at this stage? FIXME: NO! Because they won't be when they are used in EmergencyArrayFormulaReplaceIndirectBodge

# File src/simplify/inline_formulae.rb, line 65
def sheet_reference(ast)
  return unless ast[2][0] == :cell
  sheet = ast[1].to_sym
  ref = ast[2][1].to_s.upcase.gsub('$','').to_sym
  # FIXME: Need to check if valid worksheet and return [:error, "#REF!"] if not
  # Now check user preference on this
  return unless inline_ast.call(sheet,ref, references)
  ast_to_inline = ast_or_blank(sheet, ref)
  @count_replaced += 1
  current_sheet_name.push(sheet)
  map(ast_to_inline)
  current_sheet_name.pop
  ast.replace(ast_to_inline)
end