Detecting transaction tables is the step that decides whether the rest of a bank statement parser can be trusted.
Bank statements look structured when opened in a PDF viewer. You see dates, descriptions, debit amounts, credit amounts, and balances arranged in rows. But a parser does not receive a clean table. It receives positioned text fragments.
A bank statement can contain many regions that look partially structured:
The parser must identify the region that contains actual transaction rows, not just any table-like block.
| Date | Description | Debit | Credit | Balance |
|---|---|---|---|---|
| 2024-03-14 | Amazon Marketplace | 49.90 | 950.10 |
Different banks use different schemas:
| Layout Type | Columns |
|---|---|
| Debit / Credit layout | Date | Description | Debit | Credit | Balance |
| Single amount layout | Date | Description | Amount |
| Running balance layout | Date | Transaction | Amount | Balance |
A transaction table usually has several visual and semantic signals:
Using Java and Apache PDFBox, we extract text fragments with their page coordinates. These coordinates are the raw material used for table detection.
public record TextElement(
int page,
String text,
float x,
float y,
float width,
float height
) {}
A transaction table is row-based, so the parser first groups text fragments by similar Y coordinates.
public class VisualRowBuilder {
private static final float Y_TOLERANCE = 3f;
public List<List<TextElement>> buildRows(List<TextElement> elements) {
List<List<TextElement>> rows = new ArrayList<>();
for (TextElement element : elements) {
boolean added = false;
for (List<TextElement> row : rows) {
TextElement reference = row.get(0);
if (Math.abs(reference.y() - element.y()) < Y_TOLERANCE) {
row.add(element);
added = true;
break;
}
}
if (!added) {
List<TextElement> row = new ArrayList<>();
row.add(element);
rows.add(row);
}
}
return rows;
}
}
Instead of assuming the first table-like structure is the transaction table, we score candidate regions.
public class TransactionTableScorer {
public int score(TableRegion region) {
int score = 0;
if (region.hasDateLikeRows()) score += 30;
if (region.hasAmountLikeValues()) score += 25;
if (region.hasConsistentXPositions()) score += 20;
if (region.hasKnownHeaders()) score += 15;
if (region.rowCount() >= 5) score += 10;
return score;
}
public boolean isLikelyTransactionTable(TableRegion region) {
return score(region) >= 60;
}
}
Date and amount detection provide strong signals.
public class TransactionPatterns {
private static final Pattern DATE =
Pattern.compile("\\\\b\\\\d{2}/\\\\d{2}/\\\\d{4}\\\\b|\\\\b\\\\d{4}-\\\\d{2}-\\\\d{2}\\\\b");
private static final Pattern AMOUNT =
Pattern.compile("[-(]?\\\\d{1,3}(?:[.,]\\\\d{3})*(?:[.,]\\\\d{2})[)]?");
public static boolean looksLikeDate(String value) {
return value != null && DATE.matcher(value).find();
}
public static boolean looksLikeAmount(String value) {
return value != null && AMOUNT.matcher(value).find();
}
}
03/14 ATM Withdrawal
Card Ending 0345
100.00
A naive parser might split this into multiple rows. A layout-aware parser keeps the continuation line attached to the previous transaction.
After selecting a candidate region, we apply lightweight validation:
previous_balance - debit + credit = next_balance
During internal testing across multiple bank statement layouts, this scoring approach helped identify the correct transaction table more reliably than selecting the first visible table-like region on the page.
This does not make detection perfect. Scanned documents, rotated pages, and highly irregular layouts still require fallback logic. But combining visual, semantic, and business validation signals produced a much more reliable detector than using headers or regex rules alone.
Date,Description,Debit,Credit,Balance 2024-03-14,Amazon Marketplace,49.90,,950.10
Detecting transaction tables in bank statements is not just about finding a table. It is about finding the correct region that contains financial transaction rows.
Reliable detection combines visual layout analysis, date and amount recognition, column consistency, and business validation.