Skip to content

Exporting data

See also: Importing data · Component dataframe · Glossary

Take a section's records and turn them into a flat downloadable table (CSV, TSV, ODS, XLSX, HTML or print), or a machine-readable raw CSV for the import tool. This page covers the export tool's UI and, for developers, the export pipeline and component contract. For a complete, verified copy of a section set — the backup, the move between installations, the preservation copy — see The archive door: the export tool is not that.

Introduction

Exporting is the counterpart of importing: it takes the data of a section and turns it into a flat table (rows and columns) that you can download as CSV, TSV, ODS (LibreOffice), XLSX (Excel), HTML, or print. You can also download the media files (images, audiovisuals, PDFs, 3D, SVG) referenced by the exported records.

Because Dédalo stores highly structured data — values in several languages, relations to lists and thesauri, hierarchies, dataframes — exporting is not a simple dump. The export tool lets you decide which components become columns, in which order, and how relations and hierarchies are flattened into a spreadsheet, so the result is meaningful for the use you have in mind (a report, a migration, a backup, an analysis in a spreadsheet, etc.).

A special raw format produces machine-shaped cells ({"dedalo_data": …}) the CSV import tool recognizes. It is not a backup and not a way to move data between installations — see Raw export and the import tool for what it does and does not preserve, and The archive door for the door that is.

What gets exported

The export always covers the whole current selection of the section — the set of records produced by your current search/filter — not just the page you are looking at. Configure the search first, then export.

Opening the export tool

  1. Open a section in list mode and configure the search/filter so the list shows the records you want to export.
  2. Click the Export button in the section toolbar.

The export tool opens in its own window with three areas:

  • Left — the list of the section's components (the available columns). Relation components can be expanded to reach the components of the related section.
  • CenterActive elements: the columns you have chosen, in order.
  • Right — the configuration panel: presets, format and options, the Export button, the download buttons, and the live preview.

Choosing the columns

Drag a component from the left list and drop it into the Active elements list in the center. Each dropped component becomes one column of the export.

  • Order matters. The export columns follow the exact order of the Active elements list. Drag the items up and down to reorder them; the output columns (and every download) follow that order.
  • Remove a column with the × on its item.
  • Activate all columns / Deactivate all columns add or clear the whole set at once.
  • Relations and hierarchies: expand a relation component (▶) on the left to reach the components of the related section and export them as columns too (for example, export the name of a related "Mint" instead of just the link).

The order you drop and drag is the order you get

The list of Active elements is the single source of truth for the column order. If you reorder the items, the next export — and the CSV/Excel/… you download — reflects the new order exactly.

Per-component "parents" (ancestor chain)

Hierarchical components (thesaurus terms) have a chain of ancestors. When you add such a component you get a small parents checkbox on its item: enable it to add a sibling column with the term's ancestor chain (joined with >). See Export parents for the global option.

Export options

All options are in the right-hand configuration panel.

Format

Format Value What it produces
Standard value One flat value per cell. Multiple values of a relation are joined in the same cell. The most readable format.
Breakdown grid_value Relation items are exploded into extra rows and/or extra \|n columns, so each related item gets its own cell. See Breakdown mode.
Dédalo (Raw) dedalo_raw Each cell is the stored Dédalo value wrapped as {"dedalo_data": …}. Not meant to be read by humans; it is the format the import tool unwraps (see Raw export and the import tool) — not a verbatim copy of the stored row.

Breakdown mode

Only applies to the Breakdown format. It controls how a component with several related items (for example a record linked to three "types") is laid out:

Mode Value Layout
Default default The first relation level becomes extra rows; deeper levels become extra \|n columns. Keeps the legacy behavior.
Rows rows Every related item becomes an extra row. Sibling columns are aligned; spanning (parent) values can be repeated down the rows (see Fill the gaps).
Columns columns Every related item becomes extra columns with a \|n suffix. One row per record.

Rows vs Columns

A record R1 linked to mints A and B:

Columns (one row per record):

id Mint|1 Mint|2
R1 A B

Rows (one row per related item):

id Mint
R1 A
R1 B

Fill the gaps

(Default on.) In the Rows breakdown, when a record explodes into several rows, the values that belong to the record itself (not to the exploded relation) are repeated on every row instead of being left blank. Turn it off to leave the spanning cells empty except on the first row.

Show ontology tipo

Adds the component ontology tipo to the column headers in the preview (useful to identify exactly which component a column maps to). This only changes the header text shown in the tool.

Export parents

(Default off, not available for the Dédalo raw format.) The global version of the per-component parents option: for every relation/hierarchical column, add a sibling column with the ancestor chain of each linked term (joined with >). You can instead enable it column by column with the per-item parents checkbox.

The preview

Press Export to run it. A table preview is rendered and fills in live as the records stream from the server, with a progress bar. The preview is what you see is what you get: every download is built from the same data shown in the preview.

The preview has a sticky header, a frozen first (id) column, zebra rows, image and audiovisual thumbnails, and clickable links — so even wide exports stay readable.

Downloading the data

Once the export has run, the download bar offers:

Button File Notes
CSV .csv ;-separated, RFC-4180 quoted. Re-importable (see below).
TSV .tsv Tab-separated, unquoted.
ODS .ods LibreOffice Calc.
XLSX .xlsx Microsoft Excel.
HTML .html The table as a standalone HTML page.
Media .zip Downloads the media files (image, audiovisual, PDF, 3D, SVG) referenced by the exported records. A dialog lets you pick the quality per media type.
Print Opens the browser print dialog for the preview.

Encoding

Text downloads are UTF-8. CSV uses ; as the field separator and escapes inner quotes by doubling them, matching the import format.

Saving export configurations (presets)

Building a useful export (the right columns, in the right order, with the right options) takes effort, so you can save it as a preset and reuse it later. Presets are stored per user in the database.

In the presets block at the top of the configuration panel:

  • + (New) — saves the current configuration (selected columns + format + breakdown + all options) as a new preset and opens a small editor to give it a name, and optionally mark it Public (shared with all users) or Default.
  • Apply (on a preset row) — loads that preset: it rebuilds the selected columns in order and restores the format and options.
  • Save changes — updates the currently selected preset with the current configuration.
  • Edit / Delete — rename/flag or remove a preset.

Presets are scoped to the section you are exporting (a preset created on one section does not appear on another). Public presets are visible to every user; your own presets are private unless you mark them public.

Presets vs the auto-remembered state

Independently of presets, the tool remembers your last column selection (per section) and your last format/breakdown choice in the browser, so reopening the tool restores where you left off. Presets are the named, shareable, cross-device version stored in the database.

Raw export and the import tool

The Dédalo (Raw) format (dedalo_raw) exports each cell as the stored value, wrapped with the dedalo_data property:

{"dedalo_data":[{"value":"Hello","lang":"lg-eng","id":1}]}

A CSV produced with this format can be fed to the CSV import tool, which detects and unwraps the dedalo_data wrapper. What it does not do is reproduce the stored row verbatim, and the manual used to say it did:

  • The import runs the same human-input conform over a wrapped cell as over a typed one. Measured over every component model: component_text_area rewrites <br> and newlines into paragraph markup, and component_geolocation writes the item without its stored id (so the save stamps a fresh one — the identity every remove, Time Machine restore and dataframe pairing addresses). The other models measured lossless.
  • A component with no stored data exports as an empty cell and imports as an explicit clear — a full-section re-import re-saves every component of every record and stamps a Time Machine row for each.
  • Relation cells carry locators{section_tipo, section_id} — and section_id is a per-installation counter value. The import checks a locator's shape only, so in another installation each link resolves to whatever record holds that id there.
  • Media cells carry files_info (a manifest of files) and no bytes; the media zip is a separate download with nothing tying the two together.

So use raw export for what it is: a machine-shaped CSV for the same installation, edited or filtered outside Dédalo and brought back through the import tool. For a backup, a move between installations or a preservation copy use The archive door.

See The dedalo_data wrapper and Dataframe columns for the details of the wire shape (including how dataframe rows travel in their own column).

Raw is not for reading

The raw format is meant for machines, not for analysis. Use Standard or Breakdown when a person or a spreadsheet will read the result.

The archive door

The archive is the one complete, self-describing, verified extraction of a section set, and its reconstruction. It is a command-line door on the server (bun scripts/archive.ts), not a button in the export tool:

bun scripts/archive.ts extract --sections <tipo,tipo,…> --out <directory>
bun scripts/archive.ts verify  --archive <directory>
bun scripts/archive.ts restore --archive <directory> --user-id <n> [--allow-external] …

extract writes a directory (tar it for transport) holding, for every record of every named section, all eleven stored columns exactly as the database holds them — nothing conformed, no item renumbered, every locator and every files_info as stored — plus the ontology subtree that gives them meaning, byte copies of every media file the records own, and a manifest.json with the engine version, the section list with record counts, a digest of the ontology, a digest of every file, and a census of every locator that points outside the set (with whether the source held its target). Time Machine history, soft-deleted media versions, subtitles files and the per-installation counters are deliberately not archived, and the manifest says so.

restore rebuilds the set in a database that need never have held it, and refuses before writing anything on a digest mismatch, on an ontology node that exists with a different definition, on a record that already exists, on a media file that exists with different bytes, and — the cross-installation case — on a locator that resolves neither to an archived record nor to a record the destination holds. Each refusal has an explicit override flag; the dangling locators written under --allow-external are reported, never silently re-pointed. Every restored record receives one whole-record Time Machine row, so the restore is visible in its history. Archive the sections that link to each other together and no locator is external.

The format is defined in the repository file engineering/ARCHIVE_FORMAT.md and verified by a reconstruction test that builds a section set with every component model, extracts it, drops it, restores it from the artifact alone and asserts byte equality on every column.


For developers

tools/tool_export/server/tool_export.ts (toolExportGetExportGrid()) is a pure facade over the unified diffusion export engine (src/diffusion/export/): record RESOLUTION rides the shared diffusion engine (compileExportPlan turns ar_ddo_to_export into a PublicationPlan; the diffusion resolver's atom entry point walks relation hops and stored locators), and the tool handler delegates to it in a single call. The client (flat_table.js and friends) is vanilla JavaScript with an exact wire contract: one request shape, one NDJSON protocol, three data formats and a fixed set of options.

The stream/buffered duality and the protocol shape (meta first, every row cell referencing an already-emitted column ordinal, end last, its columns array a permutation of the emitted ordinals) are pinned by test/unit/diffusion_export_unified.test.ts; correctness of the resolved values is pinned by the parity fixture replay (test/parity/tool_export_differential.test.ts and test/parity/tool_export_breakdown_differential.test.ts).

The export pipeline

ar_ddo_to_export (chosen columns, user order)
        │  POST dd_api:'dd_tools_api', action:'tool_request', source.action:'get_export_grid'
        ▼
src/core/tools/dispatch.ts   dispatchToolRequest() — permission-gated per-tool registry
        ▼
tools/tool_export/server/tool_export.ts   toolExportGetExportGrid()
        │   resolves the SQO (search/sql_assembler.ts) then, per data_format,
        │   walks each export ddo's path to atoms and mints columns/rows —
        │   there is no separate per-component override class: the SAME
        │   leaf-value resolver the relation_list panel uses
        │   (resolve/relation_list.ts resolveCellValue/resolvePathValue) is
        │   reused so both surfaces stay byte-identical.
        ▼  NDJSON (ndjson_stream:true) or a whole {meta,columns,rows} object
flat_table.js       accumulate lines → preview + CSV/TSV/ODS/XLSX/HTML/media

The server forces the SQO to the full filtered selection (sqo.limit = null → ALL, offset = 0) after the read-permission gate, so the export always covers the whole search result rather than the client's clamped page limit.

API

tool_export.get_export_grid(options) — dispatched through dd_tools_api::tool_request (the RQO wire shape is unchanged). The TS module (tools/tool_export/server/index.ts) declares the action's own permission spec inline ({ permission: 'section', minLevel: 1, handler: ... }), enforced by the generic per-tool dispatcher dispatchToolRequest() (src/core/tools/dispatch.ts) — one explicit, typed dispatch table, shared by every tool, that resolves the tool name, checks it is active and authorized for the calling user, loads its server module, looks up the action in that module's allowlist, and enforces the action's declarative permission gate before running it. Request fields:

Field Meaning
section_tipo Target section (read-permission gated).
model 'section'.
data_format 'value' | 'grid_value' | 'dedalo_raw'.
breakdown 'default' | 'rows' | 'columns' (used with grid_value).
fill_the_gaps bool — repeat spanning values on exploded rows.
value_with_parents bool — add ancestor-chain sibling columns (n/a for dedalo_raw).
ar_ddo_to_export the columns, in output order.
sqo the search query object (the selection to export).
ndjson_stream bool — stream the flat-table protocol vs return it whole.

The flat-table NDJSON protocol

The server emits newline-delimited JSON; each line is discriminated by t:

Line Shape Purpose
meta {t:'meta', v, data_format, breakdown, fill_the_gaps, section_tipo, total} Stream header.
col {t:'col', i, key, group, path, label, ar_labels, cell_type, model, after} A column, emitted on first use. i is the stable ordinal cells reference; label is server-resolved; after hints live insertion.
row {t:'row', rec, sub, c:{ordinal:value, …}} A (sub)row; c is sparse (ordinal→value); sub is the explosion index.
end {t:'end', columns:[ordinal,…], rows, records} Authoritative display column order + counts.

The column order in the output equals the order of ar_ddo_to_export, which in the tool equals the order of the Active elements DOM list — i.e. the order the user defined by dragging. cell_type (text | img | av | iri | section_id | json) drives how flat_table.js renders each cell.

The component contract

Every component's export cell is resolved by ONE shared engine rather than a per-model override method: tool_export.ts resolves every cell through the SAME generic leaf-value walkers the relation_list panel uses (resolvePathValue / resolveCellValue in src/core/resolve/relation_list.ts), keyed on the export ddo's path. Per-model behavior is expressed declaratively instead — each component model's descriptor carries a flatValue facet that the shared walkers dispatch through, so relation components recurse component-driven (export-atom child recursion) without needing a bespoke override. Coverage is value, grid_value with all three breakdown modes, dedalo_raw, multi-hop paths, NDJSON streaming, and media/image cells — pinned by test/parity/tool_export_differential.test.ts, test/parity/tool_export_breakdown_differential.test.ts and test/unit/tool_export_relation_dataframe_fanout_native.test.ts. A genuinely new component shape that the shared resolver cannot express needs its own case added to the walkers rather than an override method.

  • The flat-join (value format) reference is resolvePathValue().
  • dedalo_raw cells are the exact stored value JSON-encoded with the dedalo_data wrapper, always exactly that: {dedalo_data: <stored value>}. A component with dataframe slots grows one EXTRA column per slot, headed by the dataframe component's tipo and carrying that component's own stored frames — see The dedalo_data wrapper and Dataframe columns for the shared shape with the import side.

Files

  • tools/tool_export/server/tool_export.ts — request handling + the P6 routing seam (toolExportGetExportGrid); the legacy in-file build stays behind DEDALO_EXPORT_UNIFIED=false until its ledgered deletion.
  • src/diffusion/export/{compile_columns,atoms,grid,index}.ts — the unified build: column-set plan compile, shared-walk atoms, NDJSON grid emission (exportGridUnified).
  • tools/tool_export/server/index.ts — the tool's ToolServerModule registration.
  • src/core/resolve/relation_list.ts — the shared leaf-value resolvers (resolvePathValue, resolveCellValue) reused from the relation_list panel.
  • tools/tool_export/js/flat_table.js — client accumulator, preview, downloads (copied as-is).
  • tools/tool_export/js/{render_tool_export,drag_tool_export}.js — UI and drag-and-drop column model (copied as-is).
  • tools/tool_export/js/export_user_presets.js, client/dedalo/core/section/js/view_export_user_presets.js — per-user presets (section dd1781; ordinary ontology data, no dedicated TS engine needed).