# Office Docs Generator: Markdown to Word, PDF, PPTX, XLSX (`shatrix/office-docs-generator`) Actor

Turn Markdown or HTML into Word and accessible PDF files, slide outlines with charts into PowerPoint decks, and JSON tables into Excel workbooks with tables, formulas and charts. Built for AI agents and automations: one call, one file URL.

- **URL**: https://apify.com/shatrix/office-docs-generator.md
- **Developed by:** [Sherif Elsayed](https://apify.com/shatrix) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 document generateds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Office Docs Generator: Markdown to Word, PDF, PPTX, XLSX

Turn text and data into real office files with one call:

- **Markdown or HTML → Word (DOCX) or PDF**: headings, bold/italic, links, nested and numbered
  lists, quotes, tables and code blocks become proper Word styles. PDFs get a title, a primary
  language and structure-ordered tabs, so they pass more accessibility checks. Right-to-left
  languages (Arabic, Hebrew, Persian, Urdu...) get right-to-left paragraphs, lists and tables.
- **Slides → PowerPoint (PPTX) or PDF**: a title slide, bullet slides, speaker notes and native,
  editable charts (column, bar, line, pie, doughnut, area, scatter), with 8 themes.
- **Tables → Excel (XLSX)**: one or more sheets, styled tables, formulas (with computed values),
  number formats, frozen header rows and native charts. CSV works too.

The result is a download URL, so an AI agent or an automation (Make, n8n, Zapier, your own
code) can hand the file straight to a user.

### Why use it

- **Made for agents.** One flat input, one output row with the file's URL. Works as an MCP tool.
- **Real files.** Native Word styles, editable PowerPoint charts, Excel formulas with cached
  results, all in the standard Office Open XML formats (checked with independent readers:
  python-docx, python-pptx and openpyxl).
- **Pay per document.** You are charged only when a file is produced. Invalid input fails
  before any charge.
- **Private.** Everything runs inside the Actor run; no third-party document API is called.

### Input examples

A PDF report from Markdown:

```json
{
  "format": "pdf",
  "fileName": "q3-report",
  "markdown": "# Q3 report\n\nRevenue grew **18%**.\n\n| Region | Q3 |\n|---|---:|\n| North | 1,850 |",
  "paperSize": "A4",
  "language": "en-US"
}
```

A PowerPoint deck with a chart:

```json
{
  "format": "pptx",
  "title": "Board update",
  "subtitle": "October",
  "theme": "Harbor",
  "slides": [
    {"title": "Agenda", "bullets": ["Results", "Plans"], "notes": "Keep it short."},
    {"title": "Revenue", "chart": {"type": "column", "title": "Revenue by quarter",
      "categories": ["Q1", "Q2", "Q3"], "series": [{"name": "2026", "values": [12, 18, 15]}]}}
  ]
}
```

An Excel workbook:

```json
{
  "format": "xlsx",
  "sheets": [{
    "name": "Sales",
    "rows": [["Region", "Q1", "Q2", "Total"], ["North", 1200, 1850, "=B2+C2"], ["South", 980, 1430, "=B3+C3"]],
    "numberFormats": [{"range": "B2:D3", "code": "#,##0"}],
    "chart": {"type": "column", "title": "Sales", "range": "A1:C3"}
  }]
}
```

### Output

One dataset row per run (also saved as the `OUTPUT` record):

```json
{
  "fileName": "q3-report.pdf",
  "format": "pdf",
  "url": "https://api.apify.com/v2/key-value-stores/.../records/q3-report.pdf",
  "contentType": "application/pdf",
  "bytes": 29831,
  "title": "Q3 report",
  "pages": 1
}
```

Files are kept in the run's key-value store (unnamed stores are deleted after 7 days; download
or copy what you need).

### Use with AI agents (MCP)

Add this Actor to any MCP client through Apify's MCP server:

`https://mcp.apify.com?tools=shatrix/office-docs-generator`

The agent sees one tool with the input fields above and gets the file URL back.

### Use from code

```bash
curl -X POST "https://api.apify.com/v2/acts/shatrix~office-docs-generator/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"format": "docx", "markdown": "# Hello\n\nGenerated by the API."}'
```

### Pricing

Pay per event: you pay for each generated document (see the Pricing tab). Runs that fail
because of invalid input are not charged. Set a maximum cost per run to cap spending.

### Limits

- One document per run; up to 200 slides, 50 sheets and 200,000 cells.
- Images in Markdown or HTML are left out: the document engine doesn't import them yet.
- Markdown links are kept (clickable in DOCX and PDF) but not styled in a link colour.
- Fonts: the image adds Noto (most of the world's scripts) and metric-compatible stand-ins for
  Calibri, Cambria, Arial, Times New Roman and Courier New to the engines' bundled fonts.
  Checked: Latin, Greek, Cyrillic, Hebrew, Arabic, Devanagari, Bengali, Tamil, Thai, Georgian,
  Armenian, Chinese, Japanese and Korean all render.
- Right-to-left layout follows `language` (for example `ar` or `he-IL`) and covers Word and PDF
  documents from Markdown or HTML; slides and spreadsheets stay left to right.
- Tested with long real-world Markdown: a 320 KB README with 53 tables became a 205-page PDF.
- The document engines are young, actively developed open-source projects; check important
  documents before sending them on.

### Credits

Built on open-source engines from the ArtCraft project (WordCraft, DeckCraft, GridCraft and
PdfCraft, MIT OR Apache-2.0). Their license texts ship in the Actor's image under
`/opt/engines/licenses/`. This Actor is not affiliated with or endorsed by the ArtCraft project.

# Actor input Schema

## `format` (type: `string`):

File to create. pdf and docx use markdown or html; pptx (or pdf with slides) uses slides; xlsx uses sheets or csv.

## `fileName` (type: `string`):

Name of the output file, without extension.

## `title` (type: `string`):

Document title, stored in the file's properties. For presentations it also makes a title slide. For Markdown, the first top-level heading is used when this is empty.

## `author` (type: `string`):

Author stored in the file's properties.

## `language` (type: `string`):

Document language as a BCP 47 tag, e.g. en-US or de-DE. Used for spelling and for accessibility (PDF primary language). Right-to-left languages (e.g. ar, he, fa, ur) also lay out Word and PDF documents right to left: paragraphs, lists and tables.

## `markdown` (type: `string`):

Content for pdf or docx: headings, bold/italic, links, nested and numbered lists, quotes, tables and code blocks.

## `html` (type: `string`):

Content for pdf or docx as HTML, instead of markdown.

## `paperSize` (type: `string`):

Page size of pdf and docx documents.

## `slides` (type: `array`):

Content slides for pptx (or pdf). Each slide: {"title": text, "bullets": \[text], "notes": text, "chart": {"type": column|bar|line|pie|doughnut|area|scatter, "title": text, "categories": \[text], "series": \[{"name": text, "values": \[number]}]}}. All fields are optional.

## `subtitle` (type: `string`):

Subtitle on the title slide.

## `theme` (type: `string`):

Presentation theme.

## `sheets` (type: `array`):

Worksheets for xlsx. Each sheet: {"name": text, "rows": \[\[cell, ...], ...], "header": true, "numberFormats": \[{"range": "B2:C9", "code": "#,##0.00"}], "chart": {"type": column|bar|line|pie|doughnut|area|scatter, "title": text, "range": "A1:C9"}}. The first row is a header: it becomes a styled table with a frozen top row. Text starting with = is a formula.

## `csv` (type: `string`):

A single sheet as CSV text, instead of sheets.

## `parseValues` (type: `boolean`):

Read text like "2.500" or "05.04.2026" as numbers and dates (en-US rules). Off keeps text as typed; numbers and formulas work either way.

## Actor input object example

```json
{
  "format": "pdf",
  "fileName": "document",
  "language": "en-US",
  "markdown": "# Quarterly report\n\nRevenue grew **18%** this quarter.\n\n## Highlights\n\n- Two new markets\n- Faster delivery\n\n| Region | Q1 | Q2 |\n|---|---:|---:|\n| North | 1,200 | 1,850 |\n| South | 980 | 1,430 |\n",
  "paperSize": "A4",
  "slides": [
    {
      "title": "Agenda",
      "bullets": [
        "Results",
        "Plans"
      ],
      "notes": "Keep it short."
    },
    {
      "title": "Revenue",
      "chart": {
        "type": "column",
        "categories": [
          "Q1",
          "Q2"
        ],
        "series": [
          {
            "name": "2026",
            "values": [
              12,
              18
            ]
          }
        ]
      }
    }
  ],
  "theme": "Default",
  "sheets": [
    {
      "name": "Sales",
      "rows": [
        [
          "Region",
          "Q1",
          "Q2",
          "Total"
        ],
        [
          "North",
          1200,
          1850,
          "=B2+C2"
        ],
        [
          "South",
          980,
          1430,
          "=B3+C3"
        ]
      ],
      "numberFormats": [
        {
          "range": "B2:D3",
          "code": "#,##0"
        }
      ],
      "chart": {
        "type": "column",
        "title": "Sales",
        "range": "A1:C3"
      }
    }
  ],
  "parseValues": false
}
```

# Actor output Schema

## `document` (type: `string`):

No description

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "markdown": `# Quarterly report

Revenue grew **18%** this quarter.

## Highlights

- Two new markets
- Faster delivery

| Region | Q1 | Q2 |
|---|---:|---:|
| North | 1,200 | 1,850 |
| South | 980 | 1,430 |`
};

// Run the Actor and wait for it to finish
const run = await client.actor("shatrix/office-docs-generator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "markdown": """# Quarterly report

Revenue grew **18%** this quarter.

## Highlights

- Two new markets
- Faster delivery

| Region | Q1 | Q2 |
|---|---:|---:|
| North | 1,200 | 1,850 |
| South | 980 | 1,430 |
""" }

# Run the Actor and wait for it to finish
run = client.actor("shatrix/office-docs-generator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "markdown": "# Quarterly report\\n\\nRevenue grew **18%** this quarter.\\n\\n## Highlights\\n\\n- Two new markets\\n- Faster delivery\\n\\n| Region | Q1 | Q2 |\\n|---|---:|---:|\\n| North | 1,200 | 1,850 |\\n| South | 980 | 1,430 |\\n"
}' |
apify call shatrix/office-docs-generator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,shatrix/office-docs-generator"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/g8AkjbLYNE0BZkgx4/builds/fPV8rWdgmZBTTfnxY/openapi.json
