Each day, files every new row of your expenses sheet under one of your own categories, writing it into a Category column.
Uses
Claude
Google Sheets
Categorise expenses in a spreadsheet
spreadsheetUrl to blank.Set spreadsheetUrl to blank.categories to blank.Set categories to blank.expensesTab to Expenses.Set expensesTab to Expenses.maxPerRun to 200.Set maxPerRun to 200.
with , in categories and save it as categoryText.categoryText by , and save it as categoryList.Split categoryText by , and save it as categoryList.categoryText lowercase and save it as lowerCategories.Make categoryText lowercase and save it as lowerCategories.lowerCategories by , and save it as categoryKeys.Split lowerCategories by , and save it as categoryKeys.spreadsheetUrl. Save it as sheet.Read the rows of spreadsheetUrl. Save it as sheet.sheet.headers doesn't contain DescriptionIf sheet.headers doesn't contain DescriptionYes
No
No steps
sheet.headers where item in lowercase is category and save it as categoryHeaders.Keep each item in sheet.headers where item in lowercase is category and save it as categoryHeaders.categoryHeaders isn't empty and sheet.headers doesn't contain CategoryIf categoryHeaders isn't empty and sheet.headers doesn't contain CategoryYes
No
No steps
sheet.rows where item.Category is blank and item.Description isn't blank and save it as newExpenses.Keep each item in sheet.rows where item.Category is blank and item.Description isn't blank and save it as newExpenses.newExpenses and save it as newCount.Count the items in newExpenses and save it as newCount.maxPerRun items of newExpenses and save it as batch.Take the first maxPerRun items of newExpenses and save it as batch.filedCount to 0.Set filedCount to 0.uncategorisedCount to 0.Set uncategorisedCount to 0.failedRows to an empty list.Set failedRows to an empty list.lastError to blank.Set lastError to blank.expense in batch:For each expense in batch:fileErrorIf a step below fails, save the error as fileErrorTry
expense.Description Amount: expense.Amount Date: expense.Date and save it as verdict.Run an AI agent: Expense: expense.Description Amount: expense.Amount Date: expense.Date and save it as verdict.verdict.output.category lowercase and save it as answerKey.Make verdict.output.category lowercase and save it as answerKey.answerKey in categoryKeys and save it as position.Find the position of answerKey in categoryKeys and save it as position.category to Uncategorised.Set category to Uncategorised.position is greater than or equal to 0 and answerKey isn't blankIf position is greater than or equal to 0 and answerKey isn't blankYes
category to categoryList[@position].Change category to categoryList[@position].No
No steps
category on row expense.row_number of expensesTab in spreadsheetUrl.Set Category: category on row expense.row_number of expensesTab in spreadsheetUrl.filedCount.Add 1 to filedCount.category is UncategorisedIf category is UncategorisedYes
uncategorisedCount.Add 1 to uncategorisedCount.No
No steps
On error
expense.row_number to the end of failedRows and save it as failedRows.Add expense.row_number to the end of failedRows and save it as failedRows.lastError to fileError.message.Change lastError to fileError.message.failedRows is greater than or equal to 5If the length of failedRows is greater than or equal to 5Yes
No
No steps
failedRows isn't emptyIf failedRows isn't emptyYes
failedRows with , and save it as failedList.Join failedRows with , and save it as failedList.filedCount. Could not file the ones on these rows of the '@expensesTab' tab: failedList (the error was: lastError). Any expense still without a category is tried again on the next run.Stop and report a problem: New expenses filed: filedCount. Could not file the ones on these rows of the '@expensesTab' tab: failedList (the error was: lastError). Any expense still without a category is tried again on the next run.No
No steps
newCount is greater than maxPerRunIf newCount is greater than maxPerRunYes
leftCount to newCount minus maxPerRun.Set leftCount to newCount minus maxPerRun.filedCount, of which uncategorisedCount marked Uncategorised. leftCount more are waiting: at most maxPerRun are filed per run, so the rest follow on the next runs.Finish the run: New expenses filed on the '@expensesTab' tab: filedCount, of which uncategorisedCount marked Uncategorised. leftCount more are waiting: at most maxPerRun are filed per run, so the rest follow on the next runs.No
No steps
filedCount is 0If filedCount is 0Yes
No
No steps
filedCount, of which uncategorisedCount marked Uncategorised because none of your categories fit.Finish the run: New expenses filed on the '@expensesTab' tab: filedCount, of which uncategorisedCount marked Uncategorised because none of your categories fit.