Podium (Podium v0.3.0)

Copy Markdown View Source

Elixir library for generating PowerPoint (.pptx) files with editable charts.

Podium provides a pipe-friendly API for building presentations programmatically. Create slides independently with Podium.Slide.new/1, populate them with content using add_chart/4, add_image/3, add_text_box/3, etc., then add them to a presentation with add_slide/2 and save.

Example

alias Podium.Chart.ChartData

data =
  ChartData.new()
  |> ChartData.add_categories(["Q1", "Q2", "Q3"])
  |> ChartData.add_series("Revenue", [100, 200, 300])

slide =
  Podium.Slide.new(:title_content)
  |> Podium.add_chart(:column_clustered, data, x: {1, :inches}, y: {2, :inches}, width: {8, :inches}, height: {4, :inches})
  |> Podium.add_text_box("Hello", x: {1, :inches}, y: {6, :inches}, width: {4, :inches}, height: {1, :inches})

Podium.new()
|> Podium.add_slide(slide)
|> Podium.save("output.pptx")

Text Formatting Reference

Text content can be a plain string or rich text (a list of paragraphs).

Run options

Each run is a {text, opts} tuple. Available options:

  • :font_size - font size in points (e.g. 12)
  • :bold - true to bold
  • :italic - true to italicize
  • :underline - true for single underline, or one of :single, :double, :heavy, :dotted, :dotted_heavy, :dash, :dash_heavy, :dash_long, :dash_long_heavy, :dot_dash, :dot_dash_heavy, :dot_dot_dash, :dot_dot_dash_heavy, :wavy, :wavy_heavy, :wavy_double, :words
  • :strikethrough - true for single strikethrough
  • :superscript - true for superscript
  • :subscript - true for subscript
  • :color - hex RGB string (e.g. "FF0000")
  • :font - font family name (e.g. "Arial")
  • :hyperlink - URL string, [url: "...", tooltip: "..."], {:slide, slide} for slide-to-slide links, or an action atom (:next_slide, :previous_slide, :first_slide, :last_slide, :end_show)
  • :lang - language code (default "en-US")

Paragraph options

When using {runs, opts} tuple paragraphs:

  • :alignment - :left, :center, :right, or :justify
  • :line_spacing - line spacing multiplier (e.g. 1.5)
  • :space_before - space before paragraph in points
  • :space_after - space after paragraph in points
  • :bullet - true for bullet, :number for numbered, a character string for custom bullet, or false to suppress
  • :level - indentation level (0-based)

Fill types

  • Hex string - "4472C4" for solid fill
  • {:gradient, stops, opts} - gradient fill where stops are [{position, color}, ...] and opts include :angle (default 5_400_000 = 90 degrees in 60,000ths)
  • {:pattern, preset, opts} - pattern fill, see Podium.Pattern for presets; opts: :foreground, :background (hex color strings)
  • {:picture, binary} - picture fill from image binary data

Line types

  • Hex string - "000000" for a line with default width
  • Keyword list - [color: "000000", width: {2, :pt}, dash_style: :dash]
  • Dash styles: :solid, :dash, :dot, :dash_dot, :long_dash, :long_dash_dot, :long_dash_dot_dot, :sys_dot, :sys_dash, :sys_dash_dot, :sys_dash_dot_dot

Summary

Functions

Adds an auto shape to a slide.

Adds a chart to a slide. Returns the updated slide.

Adds a combo chart (multiple chart types in one plot area) to a slide. Returns the updated slide.

Adds a freeform shape (built with Podium.Freeform) to a slide.

Adds an image to a slide. Returns the updated slide.

Adds a video (movie) to a slide. Returns the updated slide.

Adds a text box with a picture (blip) fill to a slide. Returns the updated slide.

Adds a slide to the presentation. Returns the updated presentation.

Adds a table to a slide.

Adds a text box to a slide.

Creates a new presentation from your own template package.

Creates a new presentation from the bundled template.

Replaces a slide in the presentation with an updated version (matched by ref).

Saves the presentation to a file.

Saves the presentation to an in-memory binary.

Places a chart into a content placeholder. Returns the updated slide.

Sets core document properties (Dublin Core metadata).

Sets presentation-level footer, date, and slide number.

Sets speaker notes on a slide.

Sets a picture placeholder on a slide. Returns the updated slide.

Sets a placeholder's text content on a slide.

Places a table into a content placeholder. Returns the updated slide.

Types

alignment()

@type alignment() :: :left | :center | :right | :justify

anchor()

@type anchor() :: :top | :middle | :bottom

chart_type()

@type chart_type() ::
  :column_clustered
  | :column_stacked
  | :column_stacked_100
  | :bar_clustered
  | :bar_stacked
  | :bar_stacked_100
  | :line
  | :line_markers
  | :line_stacked
  | :line_markers_stacked
  | :line_stacked_100
  | :line_markers_stacked_100
  | :pie
  | :pie_exploded
  | :area
  | :area_stacked
  | :area_stacked_100
  | :doughnut
  | :doughnut_exploded
  | :radar
  | :radar_filled
  | :radar_markers
  | :scatter
  | :scatter_lines
  | :scatter_lines_no_markers
  | :scatter_smooth
  | :scatter_smooth_no_markers
  | :bubble
  | :bubble_3d

connector_type()

@type connector_type() :: :straight | :elbow | :curved

dimension()

@type dimension() :: emu() | {number(), :inches | :cm | :pt}

emu()

@type emu() :: non_neg_integer()

fill()

@type fill() ::
  hex_color()
  | {:gradient, [{non_neg_integer(), hex_color()}], keyword()}
  | {:pattern, atom(), keyword()}
  | {:picture, binary()}
  | nil

hex_color()

@type hex_color() :: String.t()

layout()

@type layout() ::
  :title_slide
  | :title_content
  | :section_header
  | :two_content
  | :comparison
  | :title_only
  | :blank
  | :content_caption
  | :picture_caption
  | :title_vertical_text
  | :vertical_title_text
  | pos_integer()

line()

@type line() :: hex_color() | keyword() | nil

paragraph()

@type paragraph() :: [run()] | {[run()], keyword()}

rich_text()

@type rich_text() :: String.t() | [paragraph()]

run()

@type run() :: String.t() | {String.t(), keyword()}

Functions

add_auto_shape(slide, preset, opts)

@spec add_auto_shape(Podium.Slide.t(), atom(), keyword()) :: Podium.Slide.t()

Adds an auto shape to a slide.

Parameters

Options (required)

  • :x, :y, :width, :height - position and size

Options (optional)

  • :text - text content for the shape (string or rich text)
  • :fill - fill (omit to use theme default)
  • :line - line color or line opts
  • :rotation - rotation in degrees
  • :margin_left, :margin_right, :margin_top, :margin_bottom - text margins
  • :anchor - vertical text anchor
  • :auto_size - auto sizing behavior
  • :word_wrap - word wrap setting
  • :alignment - default text alignment
  • :font_size - default font size in points

add_chart(slide, chart_type, chart_data, opts)

Adds a chart to a slide. Returns the updated slide.

Parameters

Options (required)

  • :x, :y, :width, :height - position and size

Options (optional)

  • :title - chart title as string, or keyword list with :text, :font_size, :bold, :italic, :color, :font
  • :legend - legend position atom (:left, :right, :top, :bottom) or false to hide, or keyword list with :position, :font_size, :bold, :italic, :color, :font
  • :data_labels - list of atoms to show (:value, :category, :series, :percent) or keyword list with :show (list), :position (:center, :inside_end, :inside_base, :outside_end, :top, :bottom, :left, :right, :best_fit), :number_format (Excel format string), :color (hex color for label text)
  • :category_axis - keyword list with :title, :type (:date for date axis), :number_format, :major_gridlines, :minor_gridlines, :visible, :reverse, :crosses, :label_rotation, :major_tick_mark, :minor_tick_mark, :base_time_unit, :major_time_unit, :minor_time_unit, :major_unit, :minor_unit, :color (hex color for tick label text), :line_color (hex color for axis line)
  • :value_axis - keyword list with :title, :number_format, :major_gridlines, :minor_gridlines, :min, :max, :major_unit, :minor_unit, :visible, :reverse, :crosses, :label_rotation, :major_tick_mark, :minor_tick_mark, :color (hex color for tick label text), :line_color (hex color for axis line), :major_gridlines_color, :minor_gridlines_color (hex colors for gridlines)

add_combo_chart(slide, chart_data, plots, opts)

@spec add_combo_chart(
  Podium.Slide.t(),
  Podium.Chart.ChartData.t(),
  [{chart_type(), keyword()}],
  keyword()
) :: Podium.Slide.t()

Adds a combo chart (multiple chart types in one plot area) to a slide. Returns the updated slide.

Parameters

  • chart_data - %ChartData{} with shared categories and series
  • plots - list of {chart_type, opts} tuples where opts are:
    • :series - list of zero-based series indices to include in this plot
    • :secondary_axis - true to plot on secondary value axis (default false)

Options (required)

  • :x, :y, :width, :height - position and size

Options (optional)

  • :title - chart title (string or keyword list)
  • :legend - legend position or keyword list
  • :data_labels - data label configuration
  • :category_axis - category axis options
  • :value_axis - primary value axis options
  • :secondary_value_axis - secondary value axis options (same keys as :value_axis)

add_connector(slide, connector_type, begin_x, begin_y, end_x, end_y, opts \\ [])

@spec add_connector(
  Podium.Slide.t(),
  connector_type(),
  dimension(),
  dimension(),
  dimension(),
  dimension(),
  keyword()
) :: Podium.Slide.t()

Adds a connector between two points on a slide.

Parameters

  • connector_type - :straight, :elbow, or :curved
  • begin_x, begin_y - start point coordinates
  • end_x, end_y - end point coordinates

Options

  • :line - line color string or keyword list with :color, :width, :dash_style

add_freeform(slide, fb, opts \\ [])

@spec add_freeform(Podium.Slide.t(), Podium.Freeform.t(), keyword()) ::
  Podium.Slide.t()

Adds a freeform shape (built with Podium.Freeform) to a slide.

Options

  • :origin_x, :origin_y - offset for the shape's bounding box origin
  • :fill - fill color or fill tuple
  • :line - line color or line opts
  • :rotation - rotation in degrees

add_image(slide, binary, opts)

@spec add_image(Podium.Slide.t(), binary(), keyword()) :: Podium.Slide.t()

Adds an image to a slide. Returns the updated slide.

Image format is auto-detected from magic bytes. Supported formats: PNG, JPEG, BMP, GIF, TIFF, EMF, WMF.

Options (required)

  • :x - horizontal position
  • :y - vertical position

Options (optional)

  • :width - image width (auto-calculated from native size if only :height given or neither given)
  • :height - image height (auto-calculated from native size if only :width given or neither given)
  • :crop - keyword list with :left, :top, :right, :bottom (values in 1/1000ths of a percent)
  • :rotation - rotation in degrees
  • :shape - clip shape preset: :ellipse, :diamond, :round_rect, :star5, :star6, :star8, :heart, :triangle, :hexagon, :octagon, or a preset geometry string (default "rect")

add_movie(slide, binary, opts)

@spec add_movie(Podium.Slide.t(), binary(), keyword()) :: Podium.Slide.t()

Adds a video (movie) to a slide. Returns the updated slide.

All position/size options are required (no auto-scaling for video).

Options (required)

  • :x, :y, :width, :height - position and size

Options (optional)

  • :mime_type - MIME type string (default "video/unknown")
  • :poster_frame - poster frame image binary (default: 1x1 transparent PNG)

add_picture_fill_text_box(slide, text, image_binary, opts)

@spec add_picture_fill_text_box(
  Podium.Slide.t(),
  rich_text(),
  binary(),
  keyword()
) :: Podium.Slide.t()

Adds a text box with a picture (blip) fill to a slide. Returns the updated slide.

Options (required)

  • :x, :y, :width, :height - position and size

Options (optional)

  • :fill_mode - :stretch (default) or :tile
  • All other text box options (:rotation, :margin_*, :anchor, etc.)

add_slide(prs, slide)

Adds a slide to the presentation. Returns the updated presentation.

Slides are created independently with Podium.Slide.new/1, populated with content, then added to the presentation.

Example

slide = Podium.Slide.new(:title_content)
prs = Podium.add_slide(prs, slide)

add_table(slide, rows, opts)

@spec add_table(Podium.Slide.t(), [[term()]], keyword()) :: Podium.Slide.t()

Adds a table to a slide.

rows is a list of lists where each inner list is a row of cell values. Cell values can be:

  • Plain string - "text"
  • Rich text list - [{"bold", bold: true}]
  • Cell tuple with options - {"text", col_span: 2, fill: "FF0000"}
  • :merge atom for cells covered by a span

Options (required)

  • :x, :y, :width, :height - position and size

Options (optional)

  • :col_widths - list of column widths (auto-calculated if omitted)
  • :row_heights - list of row heights (auto-calculated if omitted)
  • :table_style - keyword list of style booleans:
    • :first_row - highlight first row (default true)
    • :last_row - highlight last row (default false)
    • :first_col - highlight first column (default false)
    • :last_col - highlight last column (default false)
    • :band_row - alternating row bands (default true)
    • :band_col - alternating column bands (default false)

Cell options

  • :col_span - number of columns to span
  • :row_span - number of rows to span
  • :fill - cell fill color or fill tuple
  • :borders - [left: color_or_opts, right: ..., top: ..., bottom: ...]
  • :padding - [left: dim, right: dim, top: dim, bottom: dim]
  • :anchor - vertical text alignment: :top, :middle, :bottom

add_text_box(slide, text, opts)

@spec add_text_box(Podium.Slide.t(), rich_text(), keyword()) :: Podium.Slide.t()

Adds a text box to a slide.

Options (required)

  • :x - horizontal position (EMU integer or {value, unit})
  • :y - vertical position
  • :width - box width
  • :height - box height

Options (optional)

  • :fill - fill color or fill tuple (see module doc)
  • :line - line color or line opts (see module doc)
  • :rotation - rotation in degrees
  • :margin_left, :margin_right, :margin_top, :margin_bottom - text margins
  • :anchor - vertical text anchor: :top, :middle, or :bottom
  • :auto_size - :none, :text_to_fit_shape, or :shape_to_fit_text
  • :word_wrap - true (default) or false
  • :alignment - default text alignment: :left, :center, :right, :justify
  • :font_size - default font size in points

from_template(source, opts \\ [])

@spec from_template(
  binary(),
  keyword()
) :: Podium.Presentation.t()

Creates a new presentation from your own template package.

source is either a path to a .pptx/.potx file or the bytes of one. The template keeps everything it declares: masters, layouts, themes, media, notes master, default text style and notes size. Podium adds slides to it.

Template requirements

  • ppt/presentation.xml, ppt/_rels/presentation.xml.rels and [Content_Types].xml must be present, as they are in any package saved by PowerPoint, Keynote or Google Slides.
  • The template must contain no slides. Slide masters, layouts and a notes master are what a template is for; existing slides would collide with the ones Podium writes.
  • The template must relate to at least one slide master, or its layouts have nothing for slides to sit on.
  • To set core properties, the template's _rels/.rels must already relate to docProps/core.xml. A package saved by PowerPoint always does.

Differences from new/1

Core-property options are the same as new/1.

Example

Podium.from_template("priv/brand/skeleton.pptx", title: "Q3 review")
|> Podium.add_slide(slide)
|> Podium.save("q3.pptx")

new(opts \\ [])

@spec new(keyword()) :: Podium.Presentation.t()

Creates a new presentation from the bundled template.

Use from_template/2 to build on a template of your own.

Options

  • :slide_width - slide width, default 16:9 (12_192_000 EMU). Accepts EMU integer or {value, unit}.
  • :slide_height - slide height, default 16:9 (6_858_000 EMU). Accepts EMU integer or {value, unit}.
  • :title - document title string
  • :author - document author string
  • :subject - document subject string
  • :keywords - keywords string
  • :category - category string
  • :comments - comments/description string
  • :last_modified_by - last modified by string
  • :created - DateTime for creation timestamp
  • :modified - DateTime for modification timestamp
  • :last_printed - DateTime for last printed timestamp
  • :revision - revision number (integer)
  • :content_status - content status string
  • :language - language code string
  • :version - version string

put_slide(prs, slide)

Replaces a slide in the presentation with an updated version (matched by ref).

save(prs, path)

@spec save(Podium.Presentation.t(), String.t()) :: :ok | {:error, term()}

Saves the presentation to a file.

save_to_memory(prs)

@spec save_to_memory(Podium.Presentation.t()) :: {:ok, binary()} | {:error, term()}

Saves the presentation to an in-memory binary.

set_chart_placeholder(prs, slide, name, chart_type, chart_data, opts \\ [])

Places a chart into a content placeholder. Returns the updated slide.

Addressed by a bundled-template name, the placeholder must be a content placeholder (type: nil) — e.g. :content on :title_content, or :left_content/:right_content on :two_content. Addressed by the {type, idx} pair Podium.Template.inspect/1 reports, it works on any template. Position and size are taken from the layout.

set_core_properties(prs, opts)

@spec set_core_properties(
  Podium.Presentation.t(),
  keyword()
) :: Podium.Presentation.t()

Sets core document properties (Dublin Core metadata).

Options

  • :title - document title
  • :author - document author
  • :subject - document subject
  • :keywords - keywords
  • :category - category
  • :comments - comments/description
  • :last_modified_by - last modified by
  • :created - creation timestamp (DateTime)
  • :modified - modification timestamp (DateTime)
  • :last_printed - last printed timestamp (DateTime)
  • :revision - revision number (integer)
  • :content_status - content status string
  • :language - language code string
  • :version - version string

set_footer(prs, opts)

@spec set_footer(
  Podium.Presentation.t(),
  keyword()
) :: Podium.Presentation.t()

Sets presentation-level footer, date, and slide number.

Each is emitted on a slide only when the slide's layout defines the matching placeholder, and at the idx that layout uses.

Options

  • :footer - footer text string
  • :date - date text string
  • :slide_number - boolean, whether to show slide numbers

set_notes(slide, text)

@spec set_notes(Podium.Slide.t(), String.t()) :: Podium.Slide.t()

Sets speaker notes on a slide.

set_picture_placeholder(slide, name, binary)

@spec set_picture_placeholder(
  Podium.Slide.t(),
  atom() | {String.t(), non_neg_integer()},
  binary()
) :: Podium.Slide.t()

Sets a picture placeholder on a slide. Returns the updated slide.

With a bundled-template name, this only works on layouts that have a picture placeholder (e.g. :picture_caption). A {type, idx} pair from Podium.Template.inspect/1 works on any template, including dropping a picture into a content placeholder such as {"obj", 14}.

set_placeholder(slide, name, text)

@spec set_placeholder(
  Podium.Slide.t(),
  atom() | {String.t(), non_neg_integer()},
  rich_text()
) :: Podium.Slide.t()

Sets a placeholder's text content on a slide.

The slide must have been created with a layout that has the given placeholder.

Available placeholders by layout

LayoutPlaceholders
:title_slide:title, :subtitle
:title_content:title, :content
:section_header:title, :body
:two_content:title, :left_content, :right_content
:comparison:title, :left_heading, :left_content, :right_heading, :right_content
:title_only:title
:blank(none)
:content_caption:title, :content, :caption
:picture_caption:title, :caption (use set_picture_placeholder/3 for :picture)
:title_vertical_text:title, :body
:vertical_title_text:title, :body

By type and idx

On a presentation built with from_template/2, address the placeholder by the {type, idx} pair Podium.Template.inspect/1 reports for it:

Podium.set_placeholder(slide, {"title", 0}, "Category performance")
Podium.set_placeholder(slide, {"obj", 14}, "Volume grew 4.2%")

The type is always the layout placeholder's own, so a content placeholder is {"obj", idx} even when it holds a picture or a chart.

set_table_placeholder(prs, slide, name, rows, opts \\ [])

@spec set_table_placeholder(
  Podium.Presentation.t(),
  Podium.Slide.t(),
  atom() | {String.t(), non_neg_integer()},
  [[term()]],
  keyword()
) :: Podium.Slide.t()

Places a table into a content placeholder. Returns the updated slide.

Addressed by a bundled-template name, the placeholder must be a content placeholder (type: nil). Addressed by the {type, idx} pair Podium.Template.inspect/1 reports, it works on any template. Position and size are taken from the layout.