Search the site
DATA
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
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.
// 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.
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.
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.
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.
FSL-1.1-MIT licensed. Built with Dartvel.
Dartvel is made by
To the bottom