wechatpay: WeChat Bill Analyzer Turns Export Chaos Into a Private Financial X-Ray
A lean Electron app that finds the real table inside messy WeChat Pay spreadsheets, checks the totals, and turns local-only financial data into usable insight.
- The app’s real innovation is not visualization, but recovering structure from a messy WeChat export before any analysis can be trusted.
- Its parser treats the spreadsheet as evidence, anchoring on the transaction header and validating results against WeChat’s own summary fields.
- Local-only processing is the product, because keeping financial history on-device is what makes the analysis feel safe enough to use.
- The stack stays intentionally small, which keeps the app understandable while still covering parsing, cleanup, charts, and verification.
The export is the enemy
WeChat Pay gives you data, but not a clean analysis surface. The export arrives with metadata blocks, separator rows, locale quirks, and a table that only becomes useful after the app reconstructs its boundaries. That is why this repo feels less like a dashboard and more like a recovery tool.
The important move is philosophical. It does not trust the file just because it opened. It inspects the export first, then decides where the real dataset begins.
How the parser finds the real table
The repo’s most interesting move is a simple anchor search. In the parsing flow, the code scans the rows until it finds 交易时间, then treats that row as the real header. Everything above it becomes metadata to extract. Everything below it becomes candidate transaction data.
for (let i = 0; i < rawData.length; i++) {
if (rawData[i][0] === '交易时间') {
headerRowIndex = i;
break;
}
}
const metadata = extractMetadata(rawData.slice(0, headerRowIndex));
const billRows = rawData.slice(headerRowIndex + 1);
That split matters. It means the app can recover user identity fields, export timestamps, and summary totals before it cleans a single transaction row. Once the metadata is separated, the app can compare its own computed sums with the bill summary WeChat included in the file.
Why local-first changes the product
This app’s privacy story is not a marketing layer. It is the architecture. The data stays on the machine, which means users are not forced to hand financial history to a web service just to understand where their money went.
That changes the trust equation. A cloud finance product asks for faith up front. This one earns trust by never asking for the upload in the first place.
The repo’s small stack reinforces that promise. Electron handles the desktop shell, SheetJS handles spreadsheet parsing, Chart.js handles the visuals, and vanilla JavaScript ties the flow together. There is no extra platform to explain and no backend to defend.
The renderer is a controller, not just a view
The renderer does more than paint the screen. It manages view switching, stores the parsed bill data, and drives the analysis functions that feed the charts. In practice, it behaves like a lightweight client-side controller.
let billData = [];
function switchView(viewName) {
// toggle overview, analysis, trend, and other panels
}
function updateViewData(data) {
billData = data;
analyzeOverview(billData);
renderCharts(billData);
}
That design keeps the mental model tight. Parse once, store locally, and transform the same dataset into multiple views without sending it anywhere else.
Dirty data is the real edge case
The cleanup logic is where the app proves it understands reality. Empty rows, separator rows, and date formatting edge cases are not cosmetic problems. They are the reason many exports feel unusable in the first place.
A fragile parser can handle the happy path. A useful parser has to survive the junk between the useful rows.
What this tool is better than
| Workflow | Privacy | Effort | Robustness | Trust in totals | Best use case |
|---|---|---|---|---|---|
| Raw WeChat export | High, but unreadable | Low to start, high to inspect | Poor | Manual only | Glancing at the file |
| Manual spreadsheet cleanup | High | High | Medium | Depends on the user | One-off investigation |
| Local Electron analyzer | High and retained | Low after import | High | Automated verification | Private forensic analysis |
The comparison makes the niche obvious. This is not a general accounting suite, and it is not trying to replace a bank dashboard. It is a local forensic tool for one specific export format, and that narrowness is its strength.
Why the stack is intentionally small
The stack is almost a product statement. Electron keeps the app cross-platform. SheetJS handles the ugly file format. Chart.js gives the analysis a visual layer without pulling in a framework. Vanilla JS keeps the control flow legible.
That restraint matters. For a utility like this, complexity is a liability unless it directly improves the trust chain from file import to verified analysis.