Getting started
Turn a messy spreadsheet into a clean SQLite database.
In this tutorial, you’ll upload a spreadsheet, convert it into a structured sheet, and download it as a SQLite database and individual CSV files.
Prerequisites
Section titled “Prerequisites”- Python 3.9+, Node.js 20+, Go 1.22+, or any shell (for the CLI)
- A DeepTable API key (get one at deeptable.com)
1. Install the SDK
Section titled “1. Install the SDK”pip install deeptablenpm install @deeptable/deeptablego get github.com/deeptable-com/deeptable-gogo install 'github.com/deeptable-com/deeptable-cli/cmd/deeptable@latest'If the deeptable command isn’t found after installation, add the Go bin directory to your PATH:
export PATH="$PATH:$(go env GOPATH)/bin"2. Set your API key
Section titled “2. Set your API key”export DEEPTABLE_API_KEY="your-api-key"3. Download an example spreadsheet
Section titled “3. Download an example spreadsheet”curl -O https://docs.deeptable.com/acme_subscriptions.xlsx4. Run this script
Section titled “4. Run this script”Create a file called main.py:
import asynciofrom pathlib import Path
from deeptable import AsyncDeepTable
async def main(): client = AsyncDeepTable()
# Upload your spreadsheet file = await client.files.upload( file=Path("acme_subscriptions.xlsx") )
# Create a structured sheet (this triggers the conversion) structured_sheet = await client.structured_sheets.create(file_id=file.id)
# Wait for processing to complete while structured_sheet.status in ("queued", "in_progress"): print(f"Status: {structured_sheet.status}") await asyncio.sleep(10) structured_sheet = await client.structured_sheets.retrieve(structured_sheet.id)
# Download as a SQLite database sqlite = await client.structured_sheets.download(structured_sheet.id, format="sqlite") await sqlite.write_to_file("acme_subscriptions.sqlite")
if __name__ == "__main__": asyncio.run(main())Run it:
python main.pyCreate a file called main.ts:
import DeepTable from "@deeptable/deeptable";import * as fs from "fs";
const client = new DeepTable();
async function main() { // Upload your spreadsheet const file = await client.files.upload({ file: fs.createReadStream("acme_subscriptions.xlsx"), });
// Create a structured sheet (this triggers the conversion) let structuredSheet = await client.structuredSheets.create({ file_id: file.id, });
// Wait for processing to complete while (structuredSheet.status === "queued" || structuredSheet.status === "in_progress") { console.log(`Status: ${structuredSheet.status}`); await new Promise((resolve) => setTimeout(resolve, 10000)); structuredSheet = await client.structuredSheets.retrieve(structuredSheet.id); }
if (structuredSheet.status === "failed") { throw new Error("Processing failed"); }
// Download as a SQLite database const response = await client.structuredSheets.download(structuredSheet.id, { format: "sqlite", }); const buffer = Buffer.from(await response.arrayBuffer()); fs.writeFileSync("acme_subscriptions.sqlite", buffer);}
main();Run it:
npx tsx main.tsCreate a file called main.go:
package main
import ( "context" "fmt" "io" "log" "os" "time"
"github.com/deeptable-com/deeptable-go")
func main() { client := deeptable.NewClient() ctx := context.Background()
// Upload your spreadsheet f, err := os.Open("acme_subscriptions.xlsx") if err != nil { log.Fatal(err) } defer f.Close()
file, err := client.Files.Upload(ctx, deeptable.FileUploadParams{ File: f, }) if err != nil { log.Fatal(err) }
// Create a structured sheet (this triggers the conversion) structuredSheet, err := client.StructuredSheets.New(ctx, deeptable.StructuredSheetNewParams{ FileID: file.ID, }) if err != nil { log.Fatal(err) }
// Wait for processing to complete for structuredSheet.Status == deeptable.StructuredSheetResponseStatusQueued || structuredSheet.Status == deeptable.StructuredSheetResponseStatusInProgress { fmt.Printf("Status: %s\n", structuredSheet.Status) time.Sleep(10 * time.Second) structuredSheet, err = client.StructuredSheets.Get(ctx, structuredSheet.ID) if err != nil { log.Fatal(err) } }
if structuredSheet.Status == deeptable.StructuredSheetResponseStatusFailed { log.Fatal("processing failed") }
// Download as a SQLite database resp, err := client.StructuredSheets.Download(ctx, structuredSheet.ID, deeptable.StructuredSheetDownloadParams{ Format: deeptable.StructuredSheetDownloadParamsFormatSqlite, }) if err != nil { log.Fatal(err) } defer resp.Body.Close()
out, err := os.Create("acme_subscriptions.sqlite") if err != nil { log.Fatal(err) } defer out.Close()
if _, err := io.Copy(out, resp.Body); err != nil { log.Fatal(err) } fmt.Println("Downloaded acme_subscriptions.sqlite")}Run it:
go run main.goRun this script:
# Upload your spreadsheetFILE_ID=$(deeptable files upload --file @acme_subscriptions.xlsx --format json --transform id | tr -d '"')
# Create a structured sheet (this triggers the conversion)SS_ID=$(deeptable structured-sheets create --file-id "$FILE_ID" --format json --transform id | tr -d '"')
# Wait for processing to completewhile true; do STATUS=$(deeptable structured-sheets retrieve --structured-sheet-id "$SS_ID" --format json --transform status) echo "Status: $STATUS" if [ "$STATUS" = '"completed"' ] || [ "$STATUS" = '"failed"' ] || [ "$STATUS" = '"cancelled"' ]; then break fi sleep 10done
# Download as a SQLite databasedeeptable structured-sheets download \ --structured-sheet-id "$SS_ID" \ --format sqlite \ --output acme_subscriptions.sqliteWhat just happened?
Section titled “What just happened?”You uploaded a spreadsheet, and DeepTable:
- Analyzed the structure - finding tables, headers, and relationships
- Converted the messy spreadsheet data into clean, normalized tables
- Returned a SQLite database you or an LLM can query directly
Download as CSV or Parquet
Section titled “Download as CSV or Parquet”Need individual tables instead of a database? You can download each table separately:
async for table in client.structured_sheets.tables.list(structured_sheet.id): csv = await client.structured_sheets.tables.download( structured_sheet_id=structured_sheet.id, table_id=table.id, format="csv", # or "parquet" ) await csv.write_to_file(f"{table.name}.csv")for await (const table of client.structuredSheets.tables.list(structuredSheet.id)) { const response = await client.structuredSheets.tables.download( structuredSheet.id, table.id, { format: "csv" } // or "parquet" ); const buffer = Buffer.from(await response.arrayBuffer()); fs.writeFileSync(`${table.name}.csv`, buffer);}iter := client.StructuredSheets.Tables.ListAutoPaging(ctx, structuredSheet.ID, deeptable.StructuredSheetTableListParams{})for iter.Next() { table := iter.Current() resp, err := client.StructuredSheets.Tables.Download(ctx, table.ID, deeptable.StructuredSheetTableDownloadParams{ StructuredSheetID: structuredSheet.ID, Format: deeptable.StructuredSheetTableDownloadParamsFormatCsv, }) if err != nil { log.Fatal(err) } defer resp.Body.Close() out, err := os.Create(table.Name + ".csv") if err != nil { log.Fatal(err) } defer out.Close() io.Copy(out, resp.Body)}if err := iter.Err(); err != nil { log.Fatal(err)}deeptable structured-sheets:tables list --structured-sheet-id "$SS_ID" --format json --transform id | tr -d '"' | while read TABLE_ID; do TABLE_NAME=$(deeptable structured-sheets:tables retrieve --structured-sheet-id "$SS_ID" --table-id "$TABLE_ID" --format json --transform name | tr -d '"') deeptable structured-sheets:tables download \ --structured-sheet-id "$SS_ID" \ --table-id "$TABLE_ID" \ --format csv \ --output "${TABLE_NAME}.csv" doneNext steps
Section titled “Next steps”- Explore the API Reference to see all available endpoints