# `GanttEx.Export`
[🔗](https://github.com/rocket4ce/gantt_ex/blob/v0.1.0/lib/gantt_ex/export.ex#L1)

Exports a `GanttEx.Store` to common formats.

| Format              | Function           | File            |
| ------------------- | ------------------ | --------------- |
| DHTMLX JSON         | `to_json/2`        | `.json`         |
| CSV (Excel)         | `to_csv/2`         | `.csv`          |
| iCalendar           | `to_ical/2`        | `.ics`          |
| MS Project (MSPDI)  | `to_ms_project/2`  | `.xml`          |
| SVG image           | `to_svg/2`         | `.svg`          |

PNG images are the SVG rasterized by the browser (the toolbar offers both),
and PDF output uses the print stylesheet: the toolbar "Print" button opens
the print dialog, where "Save as PDF" is available.

`GanttEx.Live.Gantt` uses `export/3` for its toolbar export menu.

    iex> store = GanttEx.Store.new!([%{id: 1, text: "Kickoff", start_date: ~D[2025-01-06], duration: 1}])
    iex> {filename, mime, content} = GanttEx.Export.export(store, :csv, filename: "plan")
    iex> {filename, mime}
    {"plan.csv", "text/csv"}
    iex> content |> String.split("\r\n") |> Enum.at(1)
    "1,Kickoff,task,2025-01-06 00:00,2025-01-07 00:00,1,0,,"

# `export`

```elixir
@spec export(GanttEx.Store.t(), atom(), keyword()) ::
  {String.t(), String.t(), String.t()}
```

Exports to `format`, returning `{filename, mime_type, content}`.

## Options

  * `:filename` - base file name, without extension. Defaults to `"gantt"`.
  * any option accepted by the format function.

# `formats`

```elixir
@spec formats() :: [atom()]
```

Returns the supported export formats.

    iex> GanttEx.Export.formats()
    [:json, :csv, :ical, :ms_project, :svg]

# `to_csv`

```elixir
@spec to_csv(GanttEx.Store.t(), keyword()) :: String.t()
```

Exports tasks to CSV (RFC 4180, `\r\n` line endings), ready for Excel.

The last column lists the predecessors of each task (`source_id` or
`source_id:TYPE` for non finish-to-start links).

## Options

  * `:headers` - list of the 9 column titles. Defaults to English titles.

## Examples

    iex> store = GanttEx.Store.new!(
    ...>   [%{id: 1, text: "Plan, review", start_date: ~D[2025-01-06]}, %{id: 2, text: ~s(Say "hi"), start_date: ~D[2025-01-07]}],
    ...>   [%{id: 1, source: 1, target: 2, type: :start_to_start}]
    ...> )
    iex> store |> GanttEx.Export.to_csv() |> String.split("\r\n")
    [
      "ID,Name,Type,Start,End,Duration,Progress (%),Parent,Predecessors",
      ~s(1,"Plan, review",task,2025-01-06 00:00,2025-01-07 00:00,1,0,,),
      ~s(2,"Say ""hi""",task,2025-01-07 00:00,2025-01-08 00:00,1,0,,1:SS),
      ""
    ]

# `to_ical`

```elixir
@spec to_ical(GanttEx.Store.t(), keyword()) :: String.t()
```

Exports tasks as iCalendar (RFC 5545) events. Tasks that start and end at
midnight become all-day events; times are exported as floating local time.

## Options

  * `:name` - calendar name. Defaults to `"Gantt"`.
  * `:now` - the `DTSTAMP` value (`DateTime`). Defaults to the current time.

## Examples

    iex> store = GanttEx.Store.new!([%{id: 1, text: "Launch; v1", start_date: ~D[2025-01-06], duration: 2}])
    iex> ics = GanttEx.Export.to_ical(store, now: ~U[2025-01-01 12:00:00Z])
    iex> ics |> String.split("\r\n") |> Enum.filter(&String.starts_with?(&1, ["DTSTART", "DTEND", "SUMMARY", "UID"]))
    ["UID:1@gantt_ex", "DTSTART;VALUE=DATE:20250106", "DTEND;VALUE=DATE:20250108", "SUMMARY:Launch\\; v1"]

# `to_json`

```elixir
@spec to_json(GanttEx.Store.t(), keyword()) :: String.t()
```

Exports to the DHTMLX Gantt JSON format (`{"data": [...], "links": [...]}`),
which `GanttEx.Import.from_json/1` and DHTMLX Gantt can read back.

    iex> store = GanttEx.Store.new!([%{id: 1, text: "A", start_date: ~D[2025-01-06], duration: 2}])
    iex> store |> GanttEx.Export.to_json() |> JSON.decode!() |> Map.fetch!("data")
    [%{"id" => 1, "text" => "A", "start_date" => "2025-01-06 00:00", "end_date" => "2025-01-08 00:00", "duration" => 2, "progress" => 0.0, "parent" => 0, "type" => "task", "open" => true}]

# `to_ms_project`

```elixir
@spec to_ms_project(GanttEx.Store.t(), keyword()) :: String.t()
```

Exports to Microsoft Project XML (MSPDI), which MS Project, ProjectLibre and
GanttProject can import. Durations are elapsed time; lags assume 8-hour days.

## Options

  * `:name` - project name. Defaults to `"Gantt"`.

## Examples

    iex> store = GanttEx.Store.new!(
    ...>   [%{id: "a", text: "R&D", start_date: ~D[2025-01-06], duration: 2}, %{id: "b", text: "Ship", start_date: ~D[2025-01-08], type: :milestone}],
    ...>   [%{id: 1, source: "a", target: "b"}]
    ...> )
    iex> xml = GanttEx.Export.to_ms_project(store)
    iex> xml =~ "<Name>R&amp;D</Name>" and xml =~ "<PredecessorUID>1</PredecessorUID><Type>1</Type>"
    true

# `to_svg`

```elixir
@spec to_svg(GanttEx.Store.t(), keyword()) :: String.t()
```

Renders the chart as a standalone SVG image (grid, time scale, bars and
dependencies), using the same layout rules as the live chart.

## Options

  * `:locale` - language of the labels and dates. Defaults to `"en"`.
  * `:zoom` - zoom level name used when no `:timeline` is given. Defaults to `:day`.
  * `:rows` - the rows to draw (see `GanttEx.Store.rows/2`), so collapsed
    branches or filters are respected. Defaults to all tasks.
  * `:timeline` - a `GanttEx.Timeline`. Defaults to one that fits the tasks.
  * `:row_height`, `:bar_height` - sizes in pixels.
  * `:grid` - draw the task grid. Defaults to `true`.

## Examples

    iex> store = GanttEx.Store.new!(
    ...>   [%{id: 1, text: "Design <v2>", start_date: ~D[2025-01-06], duration: 3}, %{id: 2, text: "Ship", start_date: ~D[2025-01-10], type: :milestone}],
    ...>   [%{id: 1, source: 1, target: 2}]
    ...> )
    iex> svg = GanttEx.Export.to_svg(store, locale: "es")
    iex> String.starts_with?(svg, "<svg")
    true
    iex> svg =~ "Design &lt;v2&gt;" and svg =~ "enero 2025" and svg =~ ~s(class="link")
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
