{
  "question_id": "CG-P1B-FULL-064",
  "slug": "how-to-automate-a-bank-reconciliation-with-a-spreadsheet-or-script",
  "display_title": "How do I automate a bank reconciliation outside my accounting software, using a spreadsheet with macros or a scripting language?",
  "format": "article-v2",
  "applies_to": {
    "countries": [
      "US"
    ],
    "frameworks": [],
    "tax_year": null,
    "platforms": []
  },
  "general_concept": true,
  "summary": "An outside automation can gather the extracts, normalize them, match items and report what it could not match, but the decisions about unmatched items and every correction stay in the accounting system. Build it to output the matched set, the unmatched items on each side and a summary carrying the bank balance to the book balance, prove it against a period you reconciled independently, keep each run's inputs, logic version and output, and post corrections as approved ledger entries.",
  "body": "## What can an outside automation do, and what has to stay in the books?\n\nA bank reconciliation matches the balances of a cash account in your accounting records to the corresponding information on the bank statement, and its goal is to find the differences between the two and book changes to the accounting records as appropriate. An automation built in a spreadsheet or a script is good at the mechanical middle of that job: reading two extracts, putting them in the same shape, pairing items that correspond, and listing everything left over.\n\nTwo things cannot move out of the accounting system:\n\n- **Judgment about the unmatched items.** Deciding that an unmatched book entry is a check still outstanding, that an unmatched bank line is a fee nobody recorded, or that a pair of near-misses is a keying error is a person's decision. The automation proposes; a person decides and signs.\n- **The corrections themselves.** A workbook or script output is not part of your books. An accounting worksheet is treated as an internal working paper rather than part of the official financial records, so a correction that exists only in the file has not corrected anything. Every adjustment the run identifies has to be posted in the ledger.\n\nDecide early whether this is a one-off or a routine. Clearing a large backlog once justifies a lighter build, but it still needs the full output and a check against a reconciled period. A routine used every close needs everything else below as well: documentation, version control, retained runs and a named owner. A one-off that quietly becomes the monthly process is how an unreviewed script ends up carrying the close.\n\n## What inputs does the automation need, and how do you get them?\n\nYou need two populations covering exactly the same period, plus the balances that frame them.\n\nFrom the ledger, export the detail of the bank account itself for the period, with the balance at the start and end. The fields matching depends on are the date, the amount, the direction, the check or reference number, the payee or memo, and a transaction identifier if your system exports one. In QuickBooks Online, for example, the General Ledger report can show direction in separate columns once you add the Credit and Debit columns under Columns. Intuit's help for that report does not say how to export it, so check in your own QuickBooks Online that the exported file keeps those columns and spans exactly your statement period. QuickBooks Online's bulk Export data tool produces \"reports and lists as Excel files in one.zip file\", but on its Reports tab the date is set from the Pre-selected date ranges dropdown, which may not match your statement period.\n\nFrom the bank, take the account activity for the same dates and the opening and closing balances as the statement states them. Take posted transactions only; a pending item is not on the statement and will not tie to the closing balance. What your bank offers varies by institution and by account type: file formats, which date columns appear, whether amounts are signed or split into debit and credit columns, and how far back the export reaches. Check your own bank's download options before designing anything.\n\nWrite down the exact layout of both extracts when you build: column names, column order, date format, sign convention and the file format. Your automation depends on that layout. If the bank or the software changes an export, a column can shift and the logic keeps running on the wrong field. The checks under verification exist largely to catch this.\n\n## How should the two extracts be normalized before matching?\n\nNormalization turns two differently shaped files into one comparable form. It is also where silent errors come from, because a transformation that is slightly too generous makes different items look identical, and the output still appears complete.\n\nNormalize these, each into a new column, never by overwriting the original:\n\n- **Direction and sign.** Pick one convention, such as positive for money into the account and negative for money out, and convert both sides to it. The ledger may present debit and credit columns while the bank presents a single signed amount, or the reverse. Test the conversion on a known deposit and a known payment from each file.\n- **Dates.** Parse dates explicitly in the format each file uses. Keep the original text beside the parsed value. Banks may carry more than one date, such as the transaction date and the posting date. Choose one per side and record which.\n- **Amount precision.** Convert amounts to exact cents. Excel stores binary floating-point numbers, and even common decimal fractions, such as 0.0001, can't be represented exactly in binary. In Excel, rounding with ROUND before comparing lets you successfully compare the result to another value. In a script, use a decimal type. Python's documentation says decimal is preferred in accounting applications which have strict equality invariants.\n- **References and descriptions.** Trim spaces, standardize case and strip leading zeros from check numbers. Do not strip so much that two different references become the same string. Keep a cleaned copy for matching and the raw text for review.\n- **Duplication from the extracts.** Overlapping download ranges or a repeated header can put the same transaction in the file twice. Remove a row only where the duplication is attributable to the extraction itself: a repeated header, or rows in the overlap between two download ranges that carry the same transaction identifier. Where the extract has no transaction identifier, keep both rows and let the opening-plus-activity-equals-closing check decide. Two genuine payments of the same amount on the same day are not duplicates. Log every removed row.\n\nKeep one rule throughout: normalization changes the representation of an item, never whether it exists. Count the rows and total the amounts before and after each step, and stop if either changes unexpectedly.\n\n## What matching logic does your data need?\n\nRun the match in passes, from the strictest rule to the loosest, and let each item be used only once. Which passes you need depends on what your two extracts share.\n\n**Unique key on both sides.** When both files carry the same check number or transaction reference, match on that key plus the exact amount. This is the safest pass and should run first. A key match whose amounts differ is not a match; report it as a pair with a difference.\n\n**Tolerance where no shared key exists.** Most deposits and card payments carry no common reference. Match on the exact amount and a date window, for example the book date up to a few days before the bank's posting date. Choose the window from your data, and record it as a parameter of the run. Where two or more candidates fit the same item, do not pick one: leave all of them for a person. A tolerance on amount should be used only for a known cause, and any pair matched that way should be reported with its difference rather than as a clean match.\n\n**Aggregation where one side totals the other.** When you deposit multiple customer payments at the bank, they're grouped into one total. If your books record each payment separately, no one-to-one rule will pair them. Where the books can record the deposit as one grouped total, do that instead; the aggregation pass exists for periods where they did not. An aggregation pass looks for a set of book receipts that sums exactly to one bank deposit within the date window. Limit it to small sets and a short window, because with enough candidates some combination will sum to almost any amount. A match found this way should show every component item.\n\nWhatever is left after the last pass is the residual. Those items go to a person. The unmatched lines are where the real reconciling items and the errors live, so a run with a high match rate and an unreviewed residual has not finished anything.\n\n## What output turns the result into a reconciliation?\n\nA list of matches is not a reconciliation. The run has to produce four things:\n\n1. **The matched set**, each pair or group with the rule that matched it.\n2. **Unmatched book items**, such as checks not yet presented and deposits not yet credited.\n3. **Unmatched bank items**, such as bank service fees, overdraft penalties and not sufficient funds deposits that the books have not yet recorded.\n4. **A summary carrying one balance to the other**, with control counts proving no row was lost.\n\nThe two ending balances are very unlikely to be identical before reconciliation, because payments and deposits are usually in transit at any given time. After adjustments, the adjusted bank balance should equal the adjusted book balance. If the summary shows any unexplained difference, the run has not reconciled.\n\nA worked example for one month, with invented figures. Each side after normalization, with the raw text kept:\n\n| Side | Parsed date | Signed amount in cents | Cleaned reference | Raw description as extracted |\n|---|---|---|---|---|\n| Bank | 2026-04-14 | -100000 | 1046 | CHECK # 001046 |\n| Book | 2026-04-11 | -100000 | 1046 | Check 1046 — Ace Supply |\n\nThose two rows form one matched pair: check 1046, 1,000.00, matched by key and amount, bank date 2026-04-14 against book date 2026-04-11.\n\n| Control count | Bank extract | Book extract |\n|---|---|---|\n| Rows read | 201 | 204 |\n| Matched one-to-one | 197 | 197 |\n| Matched by aggregation | 1 deposit | 4 receipts |\n| Unmatched | 3 | 3 |\n| Rows accounted for | 201 | 204 |\n\nUnmatched items: on the book side, a 2,400.00 deposit in transit and checks 1045 for 1,150.00 and 1047 for 2,085.00. On the bank side, a 35.00 service charge, 12.40 of interest and a 480.00 customer check returned for insufficient funds.\n\n| Summary line | Amount |\n|---|---|\n| Bank closing balance | 48,210.00 |\n| Add deposit in transit | 2,400.00 |\n| Less outstanding checks (1,150.00 + 2,085.00) | (3,235.00) |\n| Adjusted bank balance | 47,375.00 |\n| Book balance before adjustments | 47,877.60 |\n| Add interest not recorded | 12.40 |\n| Less service charge not recorded | (35.00) |\n| Less returned customer check | (480.00) |\n| Adjusted book balance | 47,375.00 |\n| Unexplained difference | 0.00 |\n\nThe three bank-only items become proposed entries for the books. The three book-only items carry forward and should clear next period. Any that do not clear go back to a person.\n\n## Formulas, a macro or a script: which should you build?\n\nChoose on volume, recurrence, who will run it, and how easily a reviewer can see what it did.\n\n- **A formula-driven sheet** suits a modest volume and a key-based match, for example a lookup on check number. Every step is visible in the cells, which helps review; lock the formula cells so a runner cannot overwrite them. Formulas struggle with ordered passes, one-use matching and aggregation, and a formula copied down one row too few drops items silently.\n- **A macro** automates the steps you would otherwise repeat each month inside the same workbook, and can handle ordered passes. It is harder to review than formulas and travels inside the file. VBA macros are a common way for malicious actors to gain access to deploy malware and ransomware, so Office blocks macros in files from the internet by default. A macro workbook shared by email or download may not run for the next person until the file is trusted in one of the ways Microsoft documents.\n- **A script** handles large volumes, exact decimal arithmetic, many passes and repeatable runs from raw files. The logic can live in version control and be tested. It needs a runner who can operate it and someone who can maintain it.\n\nIf you are unsure, the reviewable option you can maintain beats the powerful one you cannot.\n\n## How do you verify the automation before relying on it?\n\nSignificant worksheets should be independently reviewed for formula errors, assumptions, completeness, and consistency, and a reconciliation automation is one of them. Before the first period you rely on it, work through this sequence:\n\n1. Pick a period already reconciled without the automation and signed off. Run the automation on that period's original extracts.\n2. Confirm that every matched pair agrees with the manual work, and that the unmatched lists hold exactly the manual reconciling items.\n3. Confirm the summary lands on the same adjusted balances.\n4. Confirm the control counts: rows read equals rows matched plus rows unmatched on each side, and the totals in equal the totals out.\n5. Seed known traps into a copy of the inputs: two equal payments on the same day, a check number with leading zeros, a deposit made up of several receipts, and an amount off by one cent. Confirm each is handled as designed.\n6. Feed it bad input and confirm it stops with a clear message rather than producing output: a missing or renamed column, a shuffled column order, a date in another format, a non-numeric amount, a file cut off partway, and a file whose rows fall outside the period.\n7. Check each extract against itself before matching. The bank's opening balance plus the activity should equal its closing balance, and the same holds for the ledger. A truncated or incomplete file fails here.\n8. Have someone other than the builder review the logic and the results.\n\nKeep the checks in steps 4, 6 and 7 inside the automation so they run every time. When an export layout changes, those checks are what turn a quietly wrong result into a failed run.\n\n## What must you keep so a run can be re-performed?\n\nA reconciliation done outside the system of record leaves nothing behind in that system, so build the trail on purpose. For each run, keep:\n\n- the two extracts exactly as received, unedited;\n- the version of the workbook or script used, with its parameters such as the date window;\n- the full output, including the matched set, both unmatched lists and the summary;\n- the reviewer's sign-off and the resulting ledger entries.\n\nWorksheet controls should include version control, protected formulas, documented data sources, preparer and reviewer signoffs and retention with the close documentation. Store runs with the period's close file, so someone else can rerun the same version on the same inputs and get the same output.\n\n## How should the extracts and any credentials be handled?\n\nThe extracts carry the same financial detail as your ledger, and they now sit in a general-purpose tool. The Federal Trade Commission's business guide is written for personal information; the extracts usually contain some (payee and customer names, check numbers), and the same practices are a sensible standard for the rest. Treat them the way that guidance treats sensitive data:\n\n- **Know where the files are.** Inventory the computers, laptops, drives and other equipment, and find out where sensitive data is stored. Choose one controlled location for the extracts and the runs, not a desktop or an email thread.\n- **Limit who can read them.** Each employee should have access only to what their job needs. Give the folder the same access list as the books, not a broader one.\n- **Encrypt them** where they are stored, on the network location as well as on laptops or portable devices.\n- **Dispose of them properly.** Deleting files with ordinary commands usually isn't enough, because the files may still exist on the drive. Keep them as long as the close documentation they support is kept under your written records retention policy, then delete them securely.\n\nIf the automation retrieves data itself, from the bank or through the accounting system's interface, you also hold a standing credential outside the books. Keep it out of the script, the workbook and any configuration file saved with them, where credentials are often found hardcoded in plaintext. Store it in a secrets management system instead, and have the script read it at run time, so the credential is held in one place with its own access control rather than in any file that travels with the automation. Give it the narrowest access that works, ideally read-only on the one account. If the credential is an API key or token, rotate it regularly so a stolen copy stops working quickly; if it is a user login, the same guidance excludes it from routine rotation and says to change it on suspicion or evidence of compromise. Read your bank's own terms for automated access before connecting. Decide in advance what happens when authentication fails or the retrieval format changes: the run should stop and alert its owner, never proceed with partial data.\n\n## How do the corrections get back into the books?\n\nEvery item the automation classifies as a book correction becomes a proposed entry, and a person approves it before it is posted. Worksheet controls call for evidence of approval for adjustments. Bank charges on the statement that are not yet recorded are entered as expenses. Interest, returned items and any errors are recorded under your normal ledger treatment. Post each entry in the accounting system, dated in the period, with a memo that refers to the reconciliation run.\n\nDo not let the automation post entries itself. Then rerun or re-check the account: the adjusted book balance should now be the book balance, and the remaining reconciling items should be timing items only.\n\n## Who owns the automation after it is built?\n\nA recurring automation becomes part of your close, so it needs what any control needs:\n\n- **A named owner** who maintains it and answers for its output, and a named reviewer who is not that person.\n- **Written documentation:** the inputs and the layout each one requires, the normalization rules, the matching passes and their parameters, the output, and how to run it.\n- **Change discipline:** a new version is verified against a reconciled period before use, and the version in use is recorded on every run.\n- **A fallback:** when the automation fails, the layout changes or the owner leaves, the account is reconciled without it that period, and the automation is repaired and re-verified before it returns.\n\nThis matters most when the builder will not be the person running it later. Write the documentation for that person, and have them perform a run while the builder is still available.",
  "sources": [
    {
      "id": "SRC::af0bcb8bb87fcd26",
      "url": "https://www.accountingtools.com/articles/bank-reconciliation",
      "title": "Bank reconciliation definition",
      "publisher": "AccountingTools, Inc.",
      "published": "Published December 17, 2025",
      "retrieved_at": "2026-09-08T05:18:03+00:00",
      "sha256": "652b7db4e2c5ef3dd27a656feb55b5b4c646e8875b35107d9d651503a0fb138a",
      "supports": [
        "C1",
        "C2",
        "C10",
        "C11",
        "C12",
        "C25"
      ]
    },
    {
      "id": "REF::2",
      "url": "https://www.accountingtools.com/articles/accounting-worksheet",
      "title": "Accounting worksheet definition",
      "publisher": "AccountingTools, Inc.",
      "published": "June 25, 2026",
      "retrieved_at": "2026-09-18T17:07:19+00:00",
      "sha256": "1191b68c739497a44ea998ff792e76b2e0a2070862b0b0a7dabad00f9af68f90",
      "supports": [
        "C3",
        "C15",
        "C16",
        "C24"
      ]
    },
    {
      "id": "SRC::960c0c7b920a9f5f",
      "url": "https://quickbooks.intuit.com/learn-support/en-us/help-article/profit-loss-reports/create-report-shows-debits-credits-transaction/L1zvqNX0e_US_en_US",
      "title": "Run a ledger report that shows debits and credits for each transaction",
      "publisher": "Intuit Inc.",
      "published": "Last updated 3 August 2026",
      "retrieved_at": "2026-09-09T05:25:15+00:00",
      "sha256": "1311ae34b69ca0218160b7e418d8042d33278b4d55a233b2a47cfc505b10ab69",
      "supports": [
        "C4"
      ]
    },
    {
      "id": "SRC::5f84f24a7eadc807",
      "url": "https://quickbooks.intuit.com/learn-support/en-us/help-article/list-management/export-reports-lists-data-quickbooks-online/L1xleDrLp_US_en_US",
      "title": "Export your QuickBooks Online data",
      "publisher": "Intuit Inc.",
      "published": "last updated August 3, 2026",
      "retrieved_at": "2026-09-09T05:21:36+00:00",
      "sha256": "ff71edc8783b0495ede0769f7975e038fd19e715cf7da8454eed4d17d795ec2b",
      "supports": [
        "C5",
        "C26"
      ]
    },
    {
      "id": "REF::5",
      "url": "https://quickbooks.intuit.com/learn-support/en-us/help-article/bank-deposits/record-make-bank-deposits-quickbooks-online/L2BBZOPdr_US_en_US",
      "title": "Record and make bank deposits in QuickBooks Online",
      "publisher": "Intuit Inc.",
      "published": "last updated 8/3/2026",
      "retrieved_at": "2026-09-18T17:09:21+00:00",
      "sha256": "5ccc185baed3e4787a2cc884d84cc669f6372a634a98d1ed84b0ca564aba137d",
      "supports": [
        "C9",
        "C28"
      ]
    },
    {
      "id": "REF::6",
      "url": "https://learn.microsoft.com/en-us/troubleshoot/microsoft-365-apps/excel/floating-point-arithmetic-inaccurate-result",
      "title": "Floating-point arithmetic may give inaccurate result in Excel",
      "publisher": "Microsoft",
      "published": "2026-03-30",
      "retrieved_at": "2026-09-18T17:09:42+00:00",
      "sha256": "bfa9dd85e6c33df87efa2bca72b17350b00c461231d7697830eef7e5c94c2dce",
      "supports": [
        "C6",
        "C7"
      ]
    },
    {
      "id": "REF::7",
      "url": "https://docs.python.org/3/library/decimal.html",
      "title": "decimal — Decimal fixed-point and floating-point arithmetic",
      "publisher": "Python Software Foundation",
      "published": "Python 3.14.7 documentation",
      "retrieved_at": "2026-09-18T17:09:42+00:00",
      "sha256": "69f2fd61a501c3f84f9ccf7f69d6227754512675e1563f084b5132dc23beeade",
      "supports": [
        "C8"
      ]
    },
    {
      "id": "REF::8",
      "url": "https://learn.microsoft.com/en-us/microsoft-365-apps/security/internet-macros-blocked",
      "title": "Macros from the internet are blocked by default in Office",
      "publisher": "Microsoft",
      "published": "2026-07-17",
      "retrieved_at": "2026-09-18T17:09:44+00:00",
      "sha256": "464987b18017c239202facdb5b29d5586b7457d45cb0a18b7d5bd03dd8bc315e",
      "supports": [
        "C13",
        "C14"
      ]
    },
    {
      "id": "REF::9",
      "url": "https://www.ftc.gov/business-guidance/resources/protecting-personal-information-guide-business",
      "title": "Protecting Personal Information: A Guide for Business",
      "publisher": "Federal Trade Commission",
      "published": "October 2016",
      "retrieved_at": "2026-09-18T17:09:45+00:00",
      "sha256": "ecf5de77f5f8c765dc88ee887c25baebdfbf883eb2da6597f90471818373cc00",
      "supports": [
        "C17",
        "C18",
        "C19",
        "C20",
        "C29",
        "C33"
      ]
    },
    {
      "id": "REF::10",
      "url": "https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html",
      "title": "Secrets Management Cheat Sheet",
      "publisher": "OWASP Foundation",
      "published": "undated",
      "retrieved_at": "2026-09-18T17:09:45+00:00",
      "sha256": "9118ee3dd98f8198c52b5d1237bd9b65582d0347b089dff51b46a7a554f8d5c9",
      "supports": [
        "C21",
        "C22",
        "C23",
        "C30",
        "C31",
        "C32"
      ]
    }
  ],
  "related": [
    {
      "question_id": "CG-P1B-FULL-014",
      "slug": "what-automatic-reconciliation-does-and-how-to-check-what-it-reconciled",
      "display_title": "Can reconciliation be performed automatically in my accounting software - what does an automatic reconcile actually do, and how do I turn it on and check what it reconciled?"
    },
    {
      "question_id": "CG-P1B-002",
      "slug": "what-is-a-bank-reconciliation-and-how-to-tie-the-books-to-the-bank",
      "display_title": "What is a bank reconciliation, who prepares it, and how do I tie the books to the bank (with a worked example)?"
    }
  ],
  "review_class": "consequential",
  "review_class_trigger": "claim_level_review_required",
  "provenance": {
    "author_model": "claude-opus-5",
    "reviewer_model": "claude-opus-5-5",
    "review_verdict": "ACCEPT",
    "review_source": "closure",
    "review_verdict_on_sha256": "4cc1d96f8f0eee35c6bc9e2ece00a7ebd05240101282b177ee21d5e86c176bdc",
    "editorial_disposition": "ACCEPT",
    "corrections": 1,
    "approved_by": null,
    "approved_at": null,
    "article_sha256": "4cc1d96f8f0eee35c6bc9e2ece00a7ebd05240101282b177ee21d5e86c176bdc",
    "source_map_sha256": "29adaa6995c4c6249031e5ba627ea6b7b3c2882475e31f83be9eb241fca6e02a",
    "transform_sha256": "13cf8978c6b2bca82c919f631d8fb4b9da249864cd46222aa7d03a9eb5cca3b1"
  },
  "offer": "ask",
  "offer_id": null,
  "sample_target_id": null,
  "datePublished": "2026-09-24T17:07:16Z",
  "reviewed_at": "2026-09-24T17:07:16Z",
  "content_sha": "ffc8b5f24ff13c242ffec523c22c0339cf784c093a5e5694e1e3ae759d8bb7fb",
  "release": "2.4.0",
  "slug_provenance": "minted at first publication",
  "question_text": "How do I automate a bank reconciliation outside my accounting software, using a spreadsheet with macros or a scripting language?",
  "jsonld_types": [
    "Article"
  ],
  "related_question_ids": [
    "CG-P1B-FULL-014",
    "CG-P1B-FULL-112",
    "CG-P1B-FULL-073",
    "CG-P1B-FULL-124",
    "CG-P1B-002"
  ],
  "aliases": [],
  "alias_provenance": []
}
