Sheets
Sheet is a notepad-style calculator that computes answers as you type. It has full access to your transactions, making it easy to solve a wide range of financial questions.
Let's start with a simple example: calculating the monthly EMI for a
home loan. The sheet below is live, you can modify the price or other
inputs, and the monthly_payment will update in real time.
Syntax
Number
Commas are supported as separators for improved readability. The % symbol is interpreted as a shortcut for dividing by 100. For example, 8% is treated as 0.08.
Operators
The following arithmetic operators are supported. The ^ symbol represents exponentiation.
Variables
Variables can be defined using the = operator. Each variable must be
assigned a value before it is used in a calculation.
Comments
Single-line comments are supported and can start with ; or //.
Functions
Built-in functions are available, and you can define your own as well. A function begins with its name, followed by a list of arguments, and its body consists of a single expression.
Query
Query is what makes Sheet especially powerful, enabling you to perform calculations on your transactions.
In a real scenario, queries run on your own transaction list, but for this documentation, the transactions shown here will be used instead.
Before we dive into writing queries, it's important to understand the difference between transactions, postings and lots.
Transactions
Transaction is probably what you are most familiar with. It represents a movement of money from one or more accounts to one or more accounts.
Postings
Every transaction is made up of two or more postings. Each posting affects an account, and the overall sum of all postings in a transaction is always zero. A posting is considered negative (-) if it appears on the left side and positive (+) if it appears on the right.
Let's look at the Purchase Mutual Fund transaction from January 10,
2025 in the image. It has three postings:
| Account | Amount |
|---|---|
| SBI Bank | -1,00,005 |
| UTI Nifty | +1,00,000 |
| Misc Charges | +5 |
| Total | 0 |
Queries operate at the posting level (or lot level), not the transaction level. This means each individual posting or lot is evaluated separately.
For example, if you want to calculate the total amount spent on Utilities in August 2025, you can use the
built-in cost function, which sums the amounts of all matching
postings:
A query is enclosed in {} and uses the format: property operator value
Let's break that down:
-
Property: The field to match on. Supported properties:
account– the posting account nameaccount_tag– the posting account tagtransaction_tag– the posting transaction tagcategory– the account's category (e.g. assets, expenses)account_type– the account's instrument type (e.g. mf, stock, cash)amount– the posting amountdescription– the transaction descriptiondate– the transaction date
-
Operator:
=– equals=~– matches regular expression<,<=,>,>=– numerical comparisons
-
Value: Depends on the property. It can be:
- A string (for account or description)
- A number (for amount)
- A date
- A regular expression
You can use queries with built-in functions like cost, which adds up the amounts of all postings that match the given query.
Here are a few examples:
For account_tag and transaction_tag, the value is composed of a
category name and a category value, joined by a colon. For example:
ExpenseCategory:Food. You can also use a regular expression to match
any value within the same category:
Queries are values too. You can assign them to variables, combine them with AND / OR, or negate them with NOT. This helps make queries more readable and reusable.
Lots
Let’s focus on the UTI Nifty account shown in the image. We first purchased 4 units, and later sold 10 units. In most countries, profits from such transactions are subject to capital gains tax. To calculate the profit, you need to track the lots you purchased.
Each purchase creates a lot. When units are sold, they are assumed to be sold from the earliest lot first, then the next one, and so on. This method is commonly known as FIFO (First-In, First-Out) and is used to determine the cost basis and the resulting capital gains.
| Account | Lot Type | Buy Date | Buy Price | Sell Date | Sell Price | Units | PNL |
|---|---|---|---|---|---|---|---|
| UTI Nifty | buy | 25,000 | 4 | ||||
| UTI Nifty | sell | 20,000 | 30,000 | 6 | 60,000 | ||
| UTI Nifty | sell | 25,000 | 30,000 | 4 | 20,000 |
You can operate on lots in a way similar to postings, with a
slightly different syntax. To work with lots, use ~lot{}.
-
Property: The field to match against. Supported properties include:
account– the lot’s account nameaccount_tag– the lot’s account tagcategory– the lot account’s category (e.g. assets, expenses)account_type– the lot account’s instrument type (e.g. mf, stock, cash)lot_type– the lot type (buyorsell)buy_date– the lot’s buy datesell_date– the lot’s sell date (only available forselllots)pnl– the profit or loss (only available forselllots)
-
Operator and Value behave the same way as they do for postings.
Date Range
Dates are treated as ranges with a start and end. For example:
[2023-01-01]represents a single day[2023-01]covers the entire month of January 2023[2023]includes the full year
Natural language shortcuts are also supported. You can use expressions like:
[last month][this month][last year][last week][jan 2023][730 days ago]
These shortcuts are automatically rounded to their natural boundaries. For example, [last year] expands to cover the full calendar year (January 1 to December 31), and [last month] covers the entire previous month from the first to the last day.
Regular Expression
Regular
expressions
are supported wherever string values are used. Use the =~ operator
followed by the pattern. For example, to calculate the total cost of
mobile-related bills under the Utilities
account:
This adds up all postings where the description contains "mobile" (case-insensitive) and the account is Utilities.
Built-in Functions
cost(query)
Returns the total amount across all postings that match the
query. This is a short form of sum(query, "amount")
sum(query, field)
Returns the total sum for all postings or lots that match the given query.
- For posting queries,
fieldcan beamountorunit. - For lot queries,
fieldcan beunitorpnl.
balance(query, asOn?)
Computes the current balance for the given query. By default, it uses the latest market prices. You can pass a date to pin the price lookup to a specific day. Only the price data is affected, not the set of postings or lots used in the calculation.
fifo(query)
Returns the list of postings or lots after applying FIFO (First In, First Out) cost basis logic.
realizedProfitAndLoss(query)
Computes the realized profit and loss for the given query.
unrealizedProfitAndLoss(query, asOn?)
Computes the unrealized profit and loss for the given query. By default, it uses the latest market prices. You can pass a date to pin the price lookup to a specific day.
log(x)
Computes the natural logarithm of a number.
max(a, b, ...)
Returns the largest of the given numbers. Useful for clamping values, such as ensuring a taxable amount is never negative.
min(a, b, ...)
Returns the smallest of the given numbers. Useful for capping values or finding the lower bound.