---
title: Exporters
description: Turn an OWLF document into CSV, Excel or a printable PDF, and back.
---

| Package | Output | Round trip |
| --- | --- | --- |
| `@owlf/export-csv` | `toCsv(document, options?)`: string | `@owlf/import-csv` `fromCsv(text)` |
| `@owlf/export-xlsx` | `toXlsx(document)`: `Promise<Uint8Array>` | `@owlf/import-xlsx` `fromXlsx(bytes)` |
| `@owlf/export-pdf` | `toPdf(document, options?)`: `Promise<Uint8Array>` | none |

## CSV

One row per entry, English snake_case headers, RFC 4180.

```ts
import { toCsv } from "@owlf/export-csv";

const forSpreadsheets = toCsv(document, { bom: true, metadata: false });
const lossless = toCsv(document); // first line: # owlf 0.1 {scales, source, warnings}
```

- **Lossless round trip**: keep the default `metadata: true`. The first line holds the scales and app info as JSON, so `fromCsv` rebuilds the exact document.
- **For Excel**: `bom: true` keeps umlauts and emoji intact; `metadata: false` puts the header in row 1.
- **Formula guard**: text cells starting with `=`, `+`, `-` or `@` get a leading `'`, removed again on import.
- **Lists**: tags as `group/name`, joined with `, `, backslash-escaped.

## Excel

Sheets **Entries** (frozen header, filters, mood cells in the level color), **Mood scale**, **Sleep scale**, **About**. Text over Excel's 32,767-character cell limit continues on an **Overflow** sheet and is joined back on import.

## PDF

A printable report: title page, one year-in-pixels page per year, then entries by date. The default Helvetica covers Western European text; pass `font` with your own TTF or OTF bytes for emoji or CJK.
