Sheet Build & Verify
This example walks through building a .sheet workbook from a Lua script, filling it with CSV data, and verifying the fingerprint — a full provenance cycle for auditable spreadsheets.
Step 1: Write the build script
Section titled “Step 1: Write the build script”build.lua — defines the sheet structure:
-- Sheet 1: Summaryset("A1", "Metric")set("B1", "Value")set("A2", "Total Revenue")set("B2", "=SUM(tx!B:B)")set("A3", "Transaction Count")set("B3", "=COUNTA(tx!A:A)")set("A4", "Average Amount")set("B4", "=AVERAGE(tx!B:B)")
-- Metadata (included in fingerprint)meta("A1:B1", { header = true })meta("B2:B4", { format = "currency" })
-- Style (excluded from fingerprint)style("A1:B1", { bold = true })style("B2:B4", { number_format = "#,##0.00" })The script uses three functions:
set(cell, value)— set a cell value or formulameta(target, table)— semantic metadata (affects fingerprint)style(target, table)— presentation styling (excluded from fingerprint)
Step 2: Build the sheet
Section titled “Step 2: Build the sheet”vgrid sheet apply model.sheet --lua build.lua --stamp "Q1 Close v1"This creates model.sheet with:
- A “Summary” sheet with formulas referencing a “tx” sheet
- An embedded fingerprint stamped with the label “Q1 Close v1”
Use --dry-run to compute the fingerprint without writing:
vgrid sheet apply model.sheet --lua build.lua --dry-runStep 3: Fill with data
Section titled “Step 3: Fill with data”transactions.csv:
Date,Amount,Description2025-01-02,1200.00,Acme Corp Invoice2025-01-03,85.50,Office Supplies2025-01-06,3500.00,Client Paymentvgrid fill model.sheet \ --csv transactions.csv \ --target tx!A1 \ --headers \ --out filled.sheetThis loads the CSV into the “tx” sheet starting at A1. The Summary formulas (=SUM(tx!B:B), etc.) now compute against real data.
Step 4: Inspect the result
Section titled “Step 4: Inspect the result”# Check computed valuesvgrid sheet inspect filled.sheet --sheet Summary B2:B4 --json{ "cells": [ {"cell": "B2", "value": "4785.5", "formula": "=SUM(tx!B:B)"}, {"cell": "B3", "value": "3", "formula": "=COUNTA(tx!A:A)"}, {"cell": "B4", "value": "1595.1666...", "formula": "=AVERAGE(tx!B:B)"} ]}# List all sheetsvgrid sheet inspect filled.sheet --sheets --jsonStep 5: Verify fingerprint
Section titled “Step 5: Verify fingerprint”The fingerprint covers the build script’s operations (structure + metadata), not the filled data. This means you can verify that the model hasn’t been tampered with, independent of what data was loaded.
# Verify the model's structure matches the build scriptvgrid sheet verify model.sheetVerification: PASS (matches expected)If someone manually edits the sheet structure, verification fails:
Verification: FAIL (fingerprint mismatch) expected: v1:8:a3b2c1d4... actual: v1:9:f5e6d7c8...Step 6: Replay from scratch
Section titled “Step 6: Replay from scratch”To reproduce the sheet from source:
# Rebuild from the Lua scriptvgrid sheet apply rebuilt.sheet --lua build.lua --verify
# Fill with the same datavgrid fill rebuilt.sheet \ --csv transactions.csv \ --target tx!A1 \ --headers \ --out rebuilt-filled.sheet
# Compare the twovgrid diff filled.sheet rebuilt-filled.sheet \ --key A --no-fail --out jsonCI integration
Section titled “CI integration”#!/bin/bashset -e
# Buildvgrid sheet apply model.sheet --lua build.lua --verify
# Fillvgrid fill model.sheet \ --csv "$DATA_FILE" \ --target tx!A1 --headers \ --out output.sheet
# Assert expected valuesvgrid publish output.sheet \ --repo acme/analytics \ --assert-cell "Summary!B2:4785.50:0.01" \ --strictFingerprint scope
Section titled “Fingerprint scope”| Operation | In fingerprint | Applied on replay |
|---|---|---|
set() | Yes | Yes |
clear() | Yes | Yes |
meta() | Yes | Yes |
style() | No | Yes |
| Sort, merge | Yes (tamper detection) | No |
The fingerprint format is v1:<count>:<blake3-hash>. Scripts with nondeterministic functions (NOW(), RAND()) cannot be verified.