Compute running per-client trust balances from ledger debits/credits and alert on negatives. The workbook becomes the system of record; Apps Script owns the joins and business rules so analysts are not pasting monthly formulas.
Entry point `reconcileTrustBalances` reads typed columns with SpreadsheetApp batch APIs. SpreadsheetApp is the primary service; Installable describes how you usually invoke it after authorization.
Keep thresholds (grace days, bands, alert emails, API keys) in Config cells or Script Properties so the same .gs file promotes from sandbox to production without code edits.
This page is technical only: sheet layout, edge cases, runnable code, deploy steps, and FAQs for reconcile client trust account balances. No consulting pitch—just the pattern you can paste and harden.
Need this built? Hire a Google Apps Script developer →
Sheet / project setup
| Tab | Columns | Notes |
|---|---|---|
| TrustLedger | Date, Client, Debit, Credit | Ledger |
| Balances | Running + Flag | Output |
What this script does
reconcileTrustBalances() compute running per-client trust balances from ledger debits/credits and alert on negatives.
- Chronological ledger
- Running balance
- NEG alert mail
Prerequisites
Container-bound script on the workbook that contains the tabs in the setup table. Authorize SpreadsheetApp scopes on first run.
- V8 runtime
- Exact sheet names
- Script timezone = ops timezone
Walkthrough
Sort ledger chronologically, running credit−debit per client, flag NEG and email TRUST_ALERT.
Paste the code, set Config/Properties, run reconcileTrustBalances once, verify the output tab, then attach a Installable trigger.
Edge cases
Ledger must include opening balances as credits; otherwise running bal starts cold at 0.
Testing
Use a sandbox copy with 3–5 known rows. Compute expected outputs for reconcile client trust account balances offline, run reconcileTrustBalances, and diff the output tab including one intentional bad row.
Hardening
Add LockService around multi-sheet writes if triggers can overlap. Log run timestamps. Keep API keys and alert emails in PropertiesService—not in shared cells.
Variations
Fork ideas: filter to one business unit, change grain (daily→weekly), or POST a summary payload after reconcileTrustBalances succeeds.
Operations notes
Assign an owner for the output tab, document regenerate steps, and treat `reconcileTrustBalances` as source of truth over ad-hoc cell formulas.
Full code: reconcileTrustBalances()
Run reconcileTrustBalances when source tabs are current. Edit sheet names and Config/Properties first.
function reconcileTrustBalances(){
const ss=SpreadsheetApp.getActive();
const rows=ss.getSheetByName('TrustLedger').getDataRange().getValues().slice(1);
rows.sort((a,b)=> new Date(a[0])-new Date(b[0]));
const bal={};
const out=[];
rows.forEach(r=>{
const client=String(r[1]);
const debit=Number(r[2])||0, credit=Number(r[3])||0;
bal[client]=(bal[client]||0)+credit-debit;
out.push([r[0],client,debit,credit,bal[client], bal[client]<0?'NEG':'OK']);
});
const sh=ss.getSheetByName('Balances');
sh.clearContents();
sh.appendRow(['Date','Client','Debit','Credit','Balance','Flag']);
if(out.length) sh.getRange(2,1,out.length+1,6).setValues(out);
const neg=out.filter(r=>r[5]==='NEG');
if(neg.length){
const email=PropertiesService.getScriptProperties().getProperty('TRUST_ALERT');
if(email) MailApp.sendEmail(email,'Trust balance negative', neg.map(r=>r[1]+' '+r[4]).join('\\n'));
}
}- Line 1: Entry point — bind triggers to reconcileTrustBalances.
- Line 3: Batch read; avoid per-cell getValue in loops.
- Line 16: Batch write output rows in one setValues call.
- Line 19: Script Properties for thresholds/secrets.
- Line 20: Digest email; authorize mail scopes once.
Deploy this example
- 01
Open Apps Script
In the bound spreadsheet: Extensions → Apps Script. For standalone projects, create one at script.google.com and link your Sheet by ID.
- 02
Paste and save
Add a .gs file, paste the code below, rename constants at the top (sheet names, column letters, API property keys), then save.
- 03
Authorize once
Run the main function from the editor. Accept OAuth scopes when prompted — triggers cannot run until authorization succeeds once.
- 04
Add the trigger
Triggers → Add trigger → choose the handler function and event (time-driven, on edit, or on form submit). Delete test triggers before production.
Before you run: reconcile client trust account balances
- 1Setup tabs exist with headers matching reconcileTrustBalances
- 2Dry-run on a copy workbook
- 3Timezone verified
- 4SpreadsheetApp authorization completed
- 5Output spot-checked against hand calc
- 6Installable trigger added only after validation
- 7Owners + alert recipients documented
Frequently asked questions
At minimum the tabs listed in the setup table for Reconcile Client Trust Account Balances. Output tabs may be cleared each run—do not store source-of-truth data there.
Run from the Apps Script editor for dry runs. Production usually uses a Installable trigger after OAuth succeeds once.
Ledger must include opening balances as credits; otherwise running bal starts cold at 0.
Per-cell calls burn quota and wall time. One read + one write keeps this pattern under the 6-minute execution cap longer.
PropertiesService (Script Properties) for API keys and alert inboxes. Config sheet is fine for non-secret thresholds.
Simple ratios maybe; reconcile client trust account balances needs joins, branching, or side effects (email/Docs/API) that Apps Script handles cleanly.
Keep the .gs in clasp/git. Avoid divergent copies of formulas on the output tab—regenerate from the script.