rehan953 commited on
Commit
24bbd2e
·
verified ·
1 Parent(s): 6fbc105

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -1
app.py CHANGED
@@ -1730,6 +1730,84 @@ def _split_fused_multicolumn_header(grid):
1730
  return new_grid
1731
 
1732
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1733
  def normalize_html_tables(text: str) -> str:
1734
  """
1735
  For every <table>...</table>:
@@ -1759,8 +1837,9 @@ def normalize_html_tables(text: str) -> str:
1759
 
1760
  # Suppress known junk tables (OCR artifacts from page headers)
1761
  if _is_junk_table(grid):
 
1762
  out.append("")
1763
- last = m.end()
1764
  continue
1765
 
1766
  grid = _drop_truly_empty_columns(grid)
@@ -1780,6 +1859,9 @@ def normalize_html_tables(text: str) -> str:
1780
  # Fix 8: split fused multi-keyword header cell (First Horizon Bank)
1781
  grid = _split_fused_multicolumn_header(grid)
1782
 
 
 
 
1783
  # Fix 6: merge split rows where description wraps to next line
1784
  # (Hardin County Bank and similar monospace statement formats)
1785
  grid = _merge_split_rows(grid)
 
1730
  return new_grid
1731
 
1732
 
1733
+ def _normalize_daily_balance_table(grid):
1734
+ """
1735
+ Fix OCR artifact in DAILY BALANCE SUMMARY tables where:
1736
+ - OCR produces N DATE columns followed by N BALANCE columns
1737
+ instead of interleaved DATE|BALANCE|DATE|BALANCE pairs
1738
+ - Multiple dates are stacked in one cell "01/02\n01/03\n01/04\n01/05"
1739
+
1740
+ Reorders columns and expands stacked date cells into proper rows.
1741
+ Only fires when ALL of these hold:
1742
+ - Header has exactly 2N columns where N >= 2
1743
+ - First N columns are all DATE, last N columns are all BALANCE
1744
+ - At least one data cell contains a newline (stacked dates)
1745
+ """
1746
+ if not grid or len(grid) < 2:
1747
+ return grid
1748
+
1749
+ header = [str(c or "").strip().upper() for c in grid[0]]
1750
+ ncols = len(header)
1751
+
1752
+ if ncols < 4 or ncols % 2 != 0:
1753
+ return grid
1754
+
1755
+ half = ncols // 2
1756
+ date_half = header[:half]
1757
+ bal_half = header[half:]
1758
+
1759
+ if not all(h == "DATE" for h in date_half):
1760
+ return grid
1761
+ if not all(h == "BALANCE" for h in bal_half):
1762
+ return grid
1763
+
1764
+ # Build new interleaved header: DATE BALANCE DATE BALANCE ...
1765
+ new_header = []
1766
+ for i in range(half):
1767
+ new_header.append("DATE")
1768
+ new_header.append("BALANCE")
1769
+
1770
+ # Expand each data row
1771
+ new_rows = []
1772
+ _DATE_RE3 = re.compile(r"^\d{1,2}/\d{2}(?:/\d{2,4})?$")
1773
+
1774
+ for row in grid[1:]:
1775
+ cells = [str(c or "").strip() for c in row]
1776
+ while len(cells) < ncols:
1777
+ cells.append("")
1778
+
1779
+ # Dates are all stacked in cells[0]; balances follow immediately in cells[1..N]
1780
+ # (OCR layout: stacked_dates | bal1 | bal2 | bal3 | bal4 | empty...)
1781
+ # NOT: date | date | date | date | bal | bal | bal | bal (despite header order)
1782
+ date_cells = [cells[0]]
1783
+ bal_cells = cells[1:]
1784
+
1785
+ # Check if dates are stacked in first cell (newline OR space-separated)
1786
+ # e.g. "01/02 01/03 01/04 01/05" or "01/02\n01/03\n01/04\n01/05"
1787
+ first = date_cells[0]
1788
+ tokens = re.split(r"[\n\r\s]+", first)
1789
+ date_tokens = [t.strip() for t in tokens if t.strip() and _DATE_RE3.match(t.strip())]
1790
+ if len(date_tokens) >= 2:
1791
+ stacked = date_tokens
1792
+ else:
1793
+ stacked = date_cells # already one date per cell
1794
+
1795
+ # Build ONE interleaved row for this group of stacked dates
1796
+ new_row = [""] * ncols
1797
+ for i, date_val in enumerate(stacked):
1798
+ if not _DATE_RE3.match(date_val):
1799
+ continue
1800
+ bal_val = bal_cells[i] if i < len(bal_cells) else ""
1801
+ new_row[i * 2] = date_val
1802
+ new_row[i * 2 + 1] = bal_val
1803
+ new_rows.append(new_row)
1804
+
1805
+ if not new_rows:
1806
+ return grid
1807
+
1808
+ return [new_header] + new_rows
1809
+
1810
+
1811
  def normalize_html_tables(text: str) -> str:
1812
  """
1813
  For every <table>...</table>:
 
1837
 
1838
  # Suppress known junk tables (OCR artifacts from page headers)
1839
  if _is_junk_table(grid):
1840
+ # Append nothing (suppress the table), update last, skip rest of pipeline
1841
  out.append("")
1842
+ last = m.end() # must set here before continue since line below is outside try
1843
  continue
1844
 
1845
  grid = _drop_truly_empty_columns(grid)
 
1859
  # Fix 8: split fused multi-keyword header cell (First Horizon Bank)
1860
  grid = _split_fused_multicolumn_header(grid)
1861
 
1862
+ # Fix 9: normalize DAILY BALANCE SUMMARY tables with stacked dates
1863
+ grid = _normalize_daily_balance_table(grid)
1864
+
1865
  # Fix 6: merge split rows where description wraps to next line
1866
  # (Hardin County Bank and similar monospace statement formats)
1867
  grid = _merge_split_rows(grid)