Dartvel, home
Docs
Features
Studio
Cloud
Compared

Search the site

GitHub
pub.dev

GETTING STARTED

Getting started
Existing Flutter apps
Existing Native apps
Run on your phone

APP

UI and styling
Routing
State
Accessibility
Keyboard shortcuts
Localization
Devices and desktop
Native device access
Media, 3D and XR

DATA

Data models
Forms
Search
Sync and offline
Import and export
Change capture
Database
Cache
File storage
Images
Privacy and erasure

BACKEND

Backend functions
Auth and sessions
Authorization
Queues and jobs
Workers and memory
Notifications and mail
Outbound HTTP
AI
Webhooks
GraphQL and OpenAPI
API keys and OAuth
Multi-tenancy
Billing and commerce
Modules

OPERATIONS

Edge security
Secrets and environments
Monitoring
Releases

SHIPPING

Build targets
Telegram Mini Apps
Static web hosting
Servers and deploying

REFERENCE

Testing
CLI reference
Coding agents

DATA

Import and export

Load a spreadsheet into a model and get a list of the rows that did not fit, with their row numbers.

Export the same model to CSV, JSON, NDJSON or Excel, with sensitive fields left out unless you ask for them.

ON THIS PAGE

Import a CSV file

Import a large file in chunks

Export to a file

Build a monthly report

Status

Import a CSV file

final DVImportResult<Article> result = Article.importCsv(csv);

for (final DVImportRowError error in result.errors) {
  DV.log('Row ${error.row}: ${error.message}');
}
for (final Article article in result.items) {
  await article.save();
}

Copy code to clipboard

Article.importCsv

Reads: CSV with a header row

Article.importNdjson

Reads: One JSON object per line

Article.importExcel

Reads: Tab-separated rows copied from a spreadsheet, with a header row

A row that does not parse becomes a DVImportRowError. The other rows still import.

Import builds models and saves nothing. You decide what to save.

Import a large file in chunks

// Handle each chunk in a worker. Every chunk carries the header row.
DV.Jobs.register<DVImportChunk>((DVImportChunk chunk) async {
  final String rows = <String>[chunk.header!, ...chunk.rows].join('\n');
  for (final Article article in Article.importCsv(rows).items) {
    await article.save();
  }
});

// Split a large file into jobs of 500 rows on the imports queue.
await Article.importResumableCsv(csv, queue: 'imports', chunkSize: 500);

Copy code to clipboard

resumableCsv and resumableNdjson queue one DVImportChunk job per chunk.

Each chunk carries its first row number and the header, so any worker can take any chunk.

Dartvel does not register the chunk handler. Register it as above.

Export to a file

final DVExportResult csv = Article.exportCsv(
  articles,
  options: DVExportOptions<Article>(
    policyFilter: (Article article) => article.published,
  ),
);
await DV.FileStorage.put(csv.fileName, csv.bytes, contentType: csv.contentType);

// Large exports in parts of 1,000 rows each.
await for (final DVExportResult part in Article.exportStreamNdjson(articles)) {
  await DV.FileStorage.put('exports/${part.fileName}', part.bytes);
}

Copy code to clipboard

csv, json, ndjson and excel return a DVExportResult with a file name, content type and bytes.

excel writes an Excel 2003 XML workbook, named .xls.

Sensitive fields are left out unless includeSensitiveFields: true.

Read and export as the same tenant

An export whose tenantId differs from the current tenant is refused. Run the query and the export inside DV.withTenant(...) so the file holds the rows its label says.

Build a monthly report

final DVReportResult report = ArticleReport.monthly(articles);
DV.log('${report.name}: ${report.metrics['count']} this month');

// Queue a report job. The cron is parsed here and travels in the payload.
await ArticleReport.dispatchMonthly(cron: '0 8 1 * *', queue: 'reports');

Copy code to clipboard

monthly counts the records you pass for a month.

scheduleMonthly and dispatchMonthly refuse a cron that does not parse, at the line that declares it.

You register the handler that builds a queued report.

Status

Partial

Spec section: Data Import, Export, and Reporting

Planned work and implementation limits

No PDF export.

No streaming import: a file is read whole before its rows are chunked onto the queue.

PREVIOUS Sync and offline Model changes, presence and offline writes
NEXT Change capture An ordered log of writes, copied to a warehouse
GitHub
pub.dev
npm
Acknowledgements
Privacy
Terms

FSL-1.1-MIT licensed. Built with Dartvel.

Dartvel is made by

SigmaDev Digital

To the bottom