V2 - Sum data in a table

Hi, I recently started using Silverbullet (v2) and I have a feeling I can (finally) do away with the spreadsheet I’m using the calculate our disposable income of the next month. However, neither myself and ChatGPT can create working code to make the necessary calculations. I hope it’s allowed to ask this question here and that this is indeed possible to do in Silverbullet!

Rules in my spreadsheet:

  • Only costs and income with an x in the count column are counted.
  • Monthly credit card costs are part of the monthly credit card statement present in the one-off costs table. To prevent double counting the monthly credit card costs (only those marked with an x) are removed from the value present in the one-off costs table when calculating the one-off costs. The minimum value counted is 0 to prevent an incomplete (/negative) counting of the monthly costs.

So I guess my questions are:

  • How do I sum (for each table) all “Value” columns from rows with an “x” in the “Count” column?
  • How do I save these values in variables for further calculation?
  • How do I implement the if statement for the credit card costs?

The structure I have setup:

Relevant stats

Disposable income: total income - total costs
Total costs (sum of monthly costs + one-off costs):
Total income (sum of monthly income + one-off income):

One-off costs (this month)

Item Value Count
Credit card 100 x
Heat pump maintenance 250 x

One-off income (this month)

Item Value Count
Vacation money 1000 x

Monthly costs

Item Value Type Count
House 1000 Automatic x
Phone1 10 Manual
Gaming service 15 Credit card x

Monthly income

Item Value Count
Salary1 2000 x
Salary2 2000 x
Monthly tax return 500

After making a few adjustments to your table columns, here’s what I came up with:

As long as all of the last 4 present column headers (value, include, type & role) are included, you could also spread the transactions over multiple tables and add additional headers.

The / chars are apparently necessary to prevent silverbullet from just ignoring the cell:

This feels like a bug.


space-lua code:

-- (disposable) income calculator
ic = ic or {}

function ic.fi(table)
  return table[1]
end

function ic.transactions()
  return query [[from index.tag "table" where page == editor.getCurrentPage() and include == "x"]]
end

function ic.totalCosts()
  local total_costs = 0
  local transactions = ic.transactions()
  local costs = query [[from transactions where type == "mc" or type == "oc"]]
  -- credit card row 
  local cc = ic.fi(query [[from transactions where role == "cc"]])
  -- rows that are subtracted from the credit card
  local cc_costs = query [[from costs where role == "oncc"]]
  for cc_t in cc_costs do
    -- don't let credit card balance go below 0
    cc.value = math.max(cc.value - cc_t.value, 0)
  end
  
  total_costs = total_costs + cc.value
  for t in costs do
    total_costs = total_costs + tonumber(t.value)
  end
  return total_costs
end

function ic.totalIncome()
  local total_income = 0
  local transactions = ic.transactions()
  local incomes = query [[from transactions where type == "mi" or type == "oi"]]
  for t in incomes do
    total_income = total_income + tonumber(t.value)
  end
  return total_income
end

function ic.disposableIncome()
  return ic.totalIncome() - ic.totalCosts()
end

I hope I understood your requirements correctly ;D

3 Likes

Hi. Massive thanks! At first glance your code does the job! I’ll get back to you after inputting my spreadsheet. :smiley:

Based on your work (thanks again) I was able to create a working replacement for my sheet, including a working creditcard calculation. My code for everyone to enjoy:

-- (disposable) income calculator
ic = ic or {}

function ic.fi(table)
  return table[1]
end

function ic.transactions()
  return query [[from index.tag "table" where page == editor.getCurrentPage() and include == "x"]]
end

-- Function that calculates total costs
function ic.totalCosts()
  local total_costs = 0
  local transactions = ic.transactions()
  local costs = query [[from transactions where type == "oc"]]
  for t in costs do
    total_costs = total_costs + tonumber(t.value)
  end
  total_costs = total_costs + ic.monthlyCosts() + ic.ccCosts()
  return tonumber(string.format("%.2f", total_costs))
end

-- Function that calculates total income
function ic.totalIncome()
  local total_income = 0
  local transactions = ic.transactions()
  local incomes = query [[from transactions where type == "mi" or type == "oi"]]
  for t in incomes do
    total_income = total_income + tonumber(t.value)
  end
  return tonumber(string.format("%.2f", total_income))
end

-- Function that calculates total costs
function ic.monthlyCosts()
  local monthly_costs = 0
  local transactions = ic.transactions()

  for t in transactions do
    if t.type and string.find(t.type, "mc") then
      monthly_costs = monthly_costs + tonumber(t.value)
    end
  end
  return tonumber(string.format("%.2f", monthly_costs))
end

function ic.monthbudgetIncome()
  local monthbudget_income = ic.totalIncome() - ic.monthlyCosts() -ic.ccCosts()
  return tonumber(string.format("%.2f", monthbudget_income))
end

-- Function that calculates (one-off) credit card costs
function ic.ccCosts()
    local current_cc_costs = 0
    local monthly_cc_costs = 0
  local transactions = ic.transactions()
  local cc_current = query [[from transactions where type == "oc-cc"]]
    for t in cc_current do
    current_cc_costs = current_cc_costs + tonumber(t.value)
    end
  local cc_monthly = query [[from transactions where type == "mc-cc"]]
    for t in cc_monthly do
    monthly_cc_costs = monthly_cc_costs + tonumber(t.value)
    end
  local cc_extra = math.max(current_cc_costs - monthly_cc_costs, 0)
  return tonumber(string.format("%.2f", cc_extra))
end

-- Function that calculates disposable income
function ic.disposableIncome()
  local disp_income = ic.totalIncome() - ic.totalCosts()
  return tonumber(string.format("%.2f", disp_income))
end
1 Like