Giter Site home page Giter Site logo

soroban's Introduction

Gem Version Dependency Status Build Status Code Climate

Soroban

Soroban is a calculating engine that understands Excel formulas.

Getting Started

Apart from the examples on this page, look at the tests and the API docs to get up to speed.

Example Usage

s = Soroban::Sheet.new()

s.A1 = 2
s.set('B1:B5' => [1,2,3,4,5])
s.C1 = "=SUM(A1, B1:B5, 5) + A1 ^ 3"
s.C2 = "=IF(C1>30,'Large','Tiny')"

puts s.C1             # => 30

s.bind(:input => :A1, :output => :C2)

puts s.output         # => "Tiny"

s.input = 3

puts s.output         # => "Large"
puts s.C1             # => 50

Bindings

Soroban allows you to bind meaningful variable names to individual cells and to ranges of cells. When bound to a range, variables act as an array.

s.set(:A1 => 'hello', 'B1:B5' => [1,2,3,4,5])

s.bind(:foo => :A1, :bar => 'B1:B5')

puts s.foo            # => 'hello'
puts s.bar[0]         # => 1

s.bar[0] = 'howdy'

puts s.B1             # => 'howdy'

Persistence

Soroban formulas are strings that begin with the = symbol. It is therefore easy to persist them, which is mighty handy if you need to parse an Excel spreadsheet, rip out formulas, store everything to a database and then perform calculations based on user input.

Soroban makes this easy, as it can tell you which cells you need to add to make it possible to do the calculations you want, and it can iterate over all the cells you've defined, so you can easily rip them out for persistence.

s.F1 = "= E1 + SUM(D1:D5)"

puts s.missing        # => [:E1, :D1, :D2, :D3, :D4, :D5]

s.E1 = "= D1 ^ D2"
s.set("D1:D5" => [1,2,3,4,5])

puts s.missing             # => []

s.cells               # => {:F1=>"= E1 + SUM(D1:D5)", :E1=>"= D1 ^ D2", :D1=>"1", :D2=>"2", :D3=>"3", :D4=>"4", :D5=>"5"}

Importers

Soroban has a built-in importer for xlsx files. It requires the RubyXL gem. Use it as follows:

BINDINGS = {
  :planet => :B1,
  :mass => :B2,
  :force => :B3
}

s = Soroban::Import::rubyXL("files/Physics.xlsx", 0, BINDINGS)

s.planet = 'Earth'
s.mass = 80
puts s.force          # => 783.459251241996

s.planet = 'Venus'
s.mass = 80
puts s.force          # => 710.044826106394

The above example parses the first sheet of Physics.xlsx, which you can download.

This import process returns a new Soroban::Sheet object that contains all the cells required to calculate the values of the bound variables, and which has the bindings set up correctly.

You can import other kinds of file using the following pattern:

  • Add the cells that correspond to bound inputs and outputs
  • Add the cells reported by missing (and continue to do so until it's empty)
  • Persist the hash returned by cells

Iteration

Note that cells returns the label of the cell along with its raw contents. If you want to iterate over cell values (including computed values of formulas), then use walk.

s.set('D1:D5' => [1,2,3,4,5])
s.walk('D1:D5').reduce(:+)    # => 15

Functions

Soroban implements some Excel functions, but you may find that you need more than those. In that case, it's easy to add more.

Soroban::functions            # => ["AND", "AVERAGE", "EXP", "IF", "LN", "MAX", "MIN", "NOT", "OR", "SUM", "VLOOKUP"]

Soroban::define :FOO => lambda { |lo, hi|
  raise ArgumentError if lo > hi
  rand(hi-lo) + lo
}

s.g = "=FOO(10, 20)"

puts s.g              # => 17

Contributing to Soroban

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright

Copyright (c) 2014 Agworld Pty. Ltd. See LICENSE.txt for further details.

soroban's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

soroban's Issues

Multiple sheets

Hi,

I would be interested to add multiple sheet support i.e. reference for cells like this "!". I started to look at the grammar for this but got a bit lost. Any pointers or tips for implementing?

Thank you
Matt

No support for percentages

To use the example given in the README:

This works:

s.C1 = "=A1-10"

This doesn't:

s.C1 = "=A1-10%"

Error:

Soroban::ParseError: Expected one of ., ^, *, /, +, -, =, <>, >=, <=, >, <, and, or at line 1, column 7 (byte 7) after
    from /path/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/soroban-0.9.1/lib/soroban/cell.rb:43:in `set'

I'm importing a spreadsheet.

Errors when cell reference is prefixed with '$'

To use the example given in the README:

This works:

s.C1 = "=SUM(A1, B1:B5, 5) + A1 ^ 3"

This doesn't:

s.C1 = "=SUM(A1, B1:B5, 5) + $A$1 ^ 3"

I'm importing a spreadsheet and would like to either have Soroban ignore the dollars or strip them out. I don't mind doing the work, but I could do with someone pointing me in the right direction. I assume the change would need to go in one of the two 'parse' scripts.

NameError: uninitialized constant RubyXL::PrivateClass

ls /var/lib/gems/1.9.1/gems/
mini_portile2-2.0.0.rc2 nokogiri-1.6.7.2 polyglot-0.3.5 rubyXL-3.3.17 rubyzip-1.2.0 soroban-0.10.0 treetop-1.5.3

irb eg.rb
eg.rb(main):001:0> require 'rubyXL'
=> true
eg.rb(main):002:0> require 'soroban'
NameError: uninitialized constant RubyXL::PrivateClass

undefined method A1 for #<Soroban::Sheet:0x007f844c9ffb28>

s.A1 is throwing an error. Am I doing something wrong? Thank you.

$ irb

1.9.3p392 :001 > require 'soroban'
=> true

1.9.3p392 :002 > s = Soroban::Sheet.new()
=> #<Soroban::Sheet:0x007f844c9ffb28 @logger=nil, @cells={}, @changes={}, @bindings={}>

1.9.3p392 :003 > s.A1
NoMethodError: undefined method A1' for #<Soroban::Sheet:0x007f844c9ffb28> from /Users/thirdreplicator/.rvm/gems/ruby-1.9.3-p392/gems/soroban-0.5.4/lib/soroban/sheet.rb:29:inmethod_missing'
from (irb):3
from /Users/thirdreplicator/.rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in `

'

1.9.3p392 :004 > s.A1=2
NameError: uninitialized constant Soroban::Sheet::Set
from /Users/thirdreplicator/.rvm/gems/ruby-1.9.3-p392/gems/soroban-0.5.4/lib/soroban/sheet.rb:17:in block in initialize' from /Users/thirdreplicator/.rvm/gems/ruby-1.9.3-p392/gems/soroban-0.5.4/lib/soroban/sheet.rb:144:inyield'
from /Users/thirdreplicator/.rvm/gems/ruby-1.9.3-p392/gems/soroban-0.5.4/lib/soroban/sheet.rb:144:in default' from /Users/thirdreplicator/.rvm/gems/ruby-1.9.3-p392/gems/soroban-0.5.4/lib/soroban/sheet.rb:144:in_clear'
from /Users/thirdreplicator/.rvm/gems/ruby-1.9.3-p392/gems/soroban-0.5.4/lib/soroban/sheet.rb:140:in _set' from /Users/thirdreplicator/.rvm/gems/ruby-1.9.3-p392/gems/soroban-0.5.4/lib/soroban/sheet.rb:129:in_add'
from /Users/thirdreplicator/.rvm/gems/ruby-1.9.3-p392/gems/soroban-0.5.4/lib/soroban/sheet.rb:27:in method_missing' from (irb):4 from /Users/thirdreplicator/.rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in

'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.