SQL Analysis of Excel, CSV, and Parquet in the Browser Using C++ and WebAssembly
WebAssembly lets you run C++17 code for parsing tabular data right in the browser. The excel_loader-based solution virtualizes files as SQL tables: XLSX, Parquet, and CSV are mounted without fully loading them into memory. This eliminates UI blocking and memory leaks common in JS libraries, while keeping user data private on their device.
The architecture combines a C++ core with Emscripten interop and a JS wrapper. The engine detects the format from the blob signature and supports JOINs between heterogeneous files in a single Workbook.
Architecture: From Parsing to SQL Queries
The C++ core of excel_loader handles parsing with native libraries, builds virtual tables, and plans queries. Emscripten exports the ExcelLoaderEngine, Workbook, and QueryResult classes to JS. The client layer passes an ArrayBuffer from the input and receives JSON results.
Workbook is the central abstraction: a container for multiple files treated as a single database. Supported formats:
- Excel/Office: XLSX, XLSB, XLS, ODS
- Flat Files: CSV, TSV, TXT
- Columnar/BigData: Parquet, DuckDB, ORC, AVRO
- Legacy DB: SQLite, DBF, MDB, ACCDB
- NoSQL/Docs: JSON, JSONL, XML, HTML
Automatic format detection simplifies integration: the frontend passes a Uint8Array without any preprocessing.
Practical API Implementation
Initializing the WASM module and loading a file requires minimal code. The engine automatically detects the type.
// Initialization WASM-modulya
const module = await ExcelLoaderModule();
const engine = new module.ExcelLoaderEngine();
// Poluchaem file from standartnogo input
const fileInput = document.getElementById("fileUploader");
const file = fileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
// Otkryvaem file how Workbook
const workbook = engine.openSingleFile(
file.name,
new Uint8Array(arrayBuffer)
);
window.currentWorkbook = workbook;
Executing an SQL query on the mounted file:
const sql = "SELECT * FROM 'Sheet1' WHERE Amount > 1000 ORDER BY Date DESC LIMIT 10";
try {
const result = window.currentWorkbook.executeQuery(sql);
const data = result.toJSON();
console.table(data);
} catch (e) {
console.error("SQL Error:", e);
}
For multi-file projects, use a JSON manifest:
// manifest.json
{
"files": [
{ "name": "data_2023.parquet", "alias": "History" },
{ "name": "new_orders.csv", "alias": "Current" }
]
}
const workbook = openProjectFromManifest(engine, manifestJson, fileBuffers);
// Dostupno: SELECT * FROM History JOIN Current ...
Metadata and Performance
The getStats() method returns data structures without executing queries:
{
"name": "sheet1$",
"displayName": "Otchet_Prodazhi",
"fileName": "report_final.xlsx",
"type": "excel-sheet",
"rows": 15400,
"columns": 24,
"memoryUsage": "..."
}
In-memory operations in C++ minimize overhead compared to V8. Parquet reads efficiently thanks to columnar structures and vectorization.
Key Performance Advantages:
- No UI blocking when parsing 50+ MB files
- JOINs between XLSX and CSV without a server
- Minimal memory usage vs JS alternatives (SheetJS, AlaSQL)
- Offline metadata access for UI
Applications in Development
This solution is ideal for middle/senior frontend and fullstack developers.
- Local-First Dashboards: Fully offline analytics without sending data anywhere
- Client-Side Validation: SQL rules to check files before upload
- Converters: Parquet → SQL filter → JSON/CSV right in the browser
- Office Editor Extensions: SQL queries on cells in web versions
Key Points
- Virtual tables mount files without fully loading them into RAM
- Automatic detection of 15+ formats from blob signatures
- Workbook supports JOINs across heterogeneous sources as a single database
- C++ via WASM outperforms JS on large datasets
- Full privacy: data never leaves the browser
— Editorial Team
No comments yet.