Skip to content

Создание Office-документов из Markdown

create_from_markdown создаёт новый DOCX, XLSX или PPTX из единственной строки Markdown. Один источник — три целевых формата. Markdown — естественный выход для контента, сгенерированного LLM: пусть модель выдаёт Markdown (это куда надёжнее, чем просить её напрямую генерировать Office XML), а затем преобразуйте его в нужный Office-формат по запросу.

Внутри Markdown разбирается в структурированный DocumentIR Office Oxide и рендерится в целевой формат, поэтому маппинг получается детерминированным и независимым от формата. IR сам по себе — это в первую очередь поверхность для извлечения и инспекции (см. to_ir()); для создания документов публичная точка входа во всех биндингах — Markdown.

Какова сигнатура create_from_markdown?

Функция принимает строку Markdown, целевой формат ("docx", "xlsx" или "pptx", регистр не важен) и путь для вывода. При успехе ничего не возвращает; при ошибке бросает исключение или возвращает ошибку.

Биндинг Сигнатура
Python def create_from_markdown(markdown: str, format: str, path, /) -> None
Rust pub fn create_from_markdown(markdown: &str, format: DocumentFormat, path: impl AsRef<Path>) -> Result<()>
Go func CreateFromMarkdown(markdown, format, path string) error
JavaScript createFromMarkdown(markdown, format, path)
C# static void Document.CreateFromMarkdown(string markdown, string format, string path)

Как создать DOCX, XLSX или PPTX из Markdown?

Напишите содержимое один раз в Markdown, а затем меняйте аргумент format, чтобы выбрать целевой формат.

Rust

use office_oxide::create::create_from_markdown;
use office_oxide::format::DocumentFormat;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let markdown = "\
# Quarterly Report

Generated automatically from Markdown using Office Oxide.

## Highlights

- Revenue grew by **32%** year-over-year
- Customer satisfaction: 4.8 / 5.0

## Financial Summary

| Category   | Q3 2025 | Q4 2025 |
|------------|---------|---------|
| Revenue    | $1.2M   | $1.6M   |
| Net Profit | $0.4M   | $0.7M   |
";

    create_from_markdown(markdown, DocumentFormat::Docx, "report.docx")?;
    create_from_markdown(markdown, DocumentFormat::Xlsx, "report.xlsx")?;
    create_from_markdown(markdown, DocumentFormat::Pptx, "report.pptx")?;
    Ok(())
}

Python

from office_oxide import create_from_markdown

markdown = """\
# Quarterly Report

Generated automatically from Markdown using Office Oxide.

## Highlights

- Revenue grew by **32%** year-over-year
- Customer satisfaction: 4.8 / 5.0
- New products launched: Widget Pro, Widget Lite

## Financial Summary

| Category   | Q3 2025 | Q4 2025 |
|------------|---------|---------|
| Revenue    | $1.2M   | $1.6M   |
| Expenses   | $0.8M   | $0.9M   |
| Net Profit | $0.4M   | $0.7M   |
"""

# One Markdown source, three target formats:
create_from_markdown(markdown, "docx", "report.docx")
create_from_markdown(markdown, "xlsx", "report.xlsx")
create_from_markdown(markdown, "pptx", "report.pptx")

JavaScript

import { createFromMarkdown } from 'office-oxide';

const markdown = `# Quarterly Report

Generated automatically from Markdown using Office Oxide.

## Highlights

- Revenue grew by **32%** year-over-year
- Customer satisfaction: 4.8 / 5.0

## Financial Summary

| Category   | Q3 2025 | Q4 2025 |
|------------|---------|---------|
| Revenue    | $1.2M   | $1.6M   |
| Net Profit | $0.4M   | $0.7M   |
`;

for (const fmt of ['docx', 'xlsx', 'pptx']) {
  createFromMarkdown(markdown, fmt, `report.${fmt}`);
}

Go

package main

import (
    "log"

    oo "github.com/yfedoseev/office_oxide/go"
)

func main() {
    markdown := `# Quarterly Report

Generated automatically from Markdown using Office Oxide.

## Highlights

- Revenue grew by **32%** year-over-year
- Customer satisfaction: 4.8 / 5.0

## Financial Summary

| Category   | Q3 2025 | Q4 2025 |
|------------|---------|---------|
| Revenue    | $1.2M   | $1.6M   |
| Net Profit | $0.4M   | $0.7M   |
`

    for _, fmt := range []string{"docx", "xlsx", "pptx"} {
        if err := oo.CreateFromMarkdown(markdown, fmt, "report."+fmt); err != nil {
            log.Fatalf("CreateFromMarkdown(%s): %v", fmt, err)
        }
    }
}

C#

using OfficeOxide;

const string markdown = """
    # Quarterly Report

    Generated automatically from Markdown using Office Oxide.

    ## Highlights

    - Revenue grew by **32%** year-over-year
    - Customer satisfaction: 4.8 / 5.0

    ## Financial Summary

    | Category   | Q3 2025 | Q4 2025 |
    |------------|---------|---------|
    | Revenue    | $1.2M   | $1.6M   |
    | Net Profit | $0.4M   | $0.7M   |
    """;

foreach (var fmt in new[] { "docx", "xlsx", "pptx" })
{
    Document.CreateFromMarkdown(markdown, fmt, $"report.{fmt}");
}

C

#include <stdio.h>
#include "office_oxide.h"

int main(void) {
    const char *markdown =
        "# Quarterly Report\n\n"
        "Generated automatically from Markdown using Office Oxide.\n\n"
        "## Highlights\n\n"
        "- Revenue grew by **32%** year-over-year\n"
        "- Customer satisfaction: 4.8 / 5.0\n\n"
        "## Financial Summary\n\n"
        "| Category   | Q3 2025 | Q4 2025 |\n"
        "|------------|---------|---------|\n"
        "| Revenue    | $1.2M   | $1.6M   |\n"
        "| Net Profit | $0.4M   | $0.7M   |\n";

    /* format: "docx" | "xlsx" | "pptx" (case-insensitive) */
    const char *formats[] = { "docx", "xlsx", "pptx" };
    for (int i = 0; i < 3; i++) {
        int err = 0;
        char path[32];
        snprintf(path, sizeof(path), "report.%s", formats[i]);
        if (office_create_from_markdown(markdown, formats[i], path, &err) != 0) {
            fprintf(stderr, "create_from_markdown(%s) failed: code=%d\n", formats[i], err);
            return 1;
        }
    }
    return 0;
}

Как Markdown рендерится в каждый целевой формат?

Markdown разбирается в структурированный IR Office Oxide, а затем каждый формат детерминированно рендерит эту структуру:

Конструкция Markdown DOCX XLSX PPTX
Заголовок # Абзац со стилем Heading{level} Жирная ячейка в начале раздела Заполнитель заголовка слайда
Текст абзаца Текстовый абзац Ячейки в последовательных строках Заполнитель основного текста
Список - / 1. Маркированный или нумерованный список Ячейки в столбце A Маркеры основного текста
Таблица Таблица Word Ячейки начиная со следующей свободной строки Таблица PowerPoint
**жирный** / *курсив* Форматирование встроенного текста Простой текст ячейки Форматирование встроенного текста

Маппинг намеренно консервативен: каждая конструкция Markdown даёт детерминированный результат, однако в каждом формате есть возможности, которые Markdown не моделирует (числовые форматы ячеек XLSX, анимации PPTX, цепочки комментариев DOCX). Для более богатого вывода создайте файл, а затем отредактируйте его в редакторе конкретного формата или воспользуйтесь специализированными писателями.

Как читать, изменять и записывать обратно между форматами?

Комбинируйте извлечение и создание, чтобы редактировать содержимое с сохранением работоспособности в разных форматах. Читайте источник как Markdown, вносите правки и записывайте новый файл:

Python

from office_oxide import Document, create_from_markdown

with Document.open("legacy.doc") as doc:
    markdown = doc.to_markdown()

# Append a new section
markdown += "\n## Appendix\n\nEffective 2026-06-22.\n"

create_from_markdown(markdown, "docx", "modernized.docx")

C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "office_oxide.h"

int main(void) {
    int err = 0;

    /* Read the source as Markdown */
    OfficeDocumentHandle *doc = office_document_open("legacy.doc", &err);
    if (!doc) { fprintf(stderr, "open failed: code=%d\n", err); return 1; }
    char *md = office_document_to_markdown(doc, &err);
    office_document_free(doc);
    if (!md) { fprintf(stderr, "to_markdown failed: code=%d\n", err); return 1; }

    /* Append a new section */
    const char *appendix = "\n## Appendix\n\nEffective 2026-06-22.\n";
    char *modified = malloc(strlen(md) + strlen(appendix) + 1);
    strcpy(modified, md);
    strcat(modified, appendix);
    office_oxide_free_string(md);

    /* Write a fresh file */
    office_create_from_markdown(modified, "docx", "modernized.docx", &err);
    free(modified);
    return err;
}

Это также чистый путь для модернизации устаревших форматов в OOXML (DOC → DOCX, XLS → XLSX, PPT → PPTX), когда нужна только текстовая структура. Для конвертации с сохранением оригинальной разметки используйте save_as() — он делает полный обход через IR. См. Конвертация: устаревшие форматы → OOXML.

Зачем генерировать Office-файлы из Markdown?

  • Независимые от формата шаблоны. Генерируйте один и тот же контент в виде DOCX (для пользователей Word), XLSX (для аналитиков) или PPTX (для презентаций) без переписывания — просто меняйте аргумент format.
  • Нативно для LLM. Пусть модель выдаёт Markdown, а вы материализуете файл. Markdown — то, что модели генерируют наиболее надёжно.
  • Поддерживает диффы. Markdown — это обычный текст; его можно коммитить. Office-файл становится артефактом сборки.
  • Быстро. Rust-ядро Office Oxide записывает файлы за миллисекунды с показателем прохождения 100% на корпусе бенчмарков.

Продвинутый уровень: сборка напрямую из DocumentIR (Rust)

Rust-крейт дополнительно предоставляет create_from_ir для тех, кто хочет вручную строить или преобразовывать структурированный IR вместо работы через Markdown:

use office_oxide::create::create_from_ir;
use office_oxide::format::DocumentFormat;
use office_oxide::ir::DocumentIR;

// Build or transform a DocumentIR however you like, then render it:
let ir: DocumentIR = DocumentIR::from_markdown("# Title\n\nBody.\n", DocumentFormat::Docx);
create_from_ir(&ir, DocumentFormat::Docx, "report.docx")?;
pub fn create_from_ir(ir: &DocumentIR, format: DocumentFormat, path: impl AsRef<Path>) -> Result<()>

В биндингах Python, Go, JavaScript и C# IR доступен только для чтения — получайте его через to_ir() для инспекции и пайплайнов, а файлы создавайте с помощью create_from_markdown.

Ограничения

  • Форматирование ячеек (числовые форматы, валюты, пользовательские стили) в Markdown не выражается. Добавляйте его через редактор конкретного формата после создания.
  • Изображения, диаграммы, SmartArt и встроенные объекты через путь Markdown не передаются — используйте специализированные писатели (XlsxWriter, PptxWriter или DOCX-строитель).
  • Объединение ячеек XLSX, анимации PPTX и цепочки комментариев DOCX не имеют аналогов в Markdown.

Для всего, что выходит за пределы выразительных возможностей Markdown, используйте специализированные писатели для каждого формата. Они дают полный доступ к возможностям OOXML, но привязаны к конкретному формату.

Часто задаваемые вопросы

Какие форматы может генерировать create_from_markdown? DOCX, XLSX и PPTX. Аргумент format принимает значения "docx", "xlsx" или "pptx" (регистр не важен). Устаревшие бинарные форматы (DOC, XLS, PPT) доступны только для чтения и не могут быть созданы.

Есть ли функция create_from_ir в Python или других биндингах? Нет. create_from_ir доступна только в Rust-крейте. В Python, Go, JavaScript и C# создавайте файлы с помощью create_from_markdown; IR (to_ir/to_ir_json) — это концепция на стороне извлечения, доступная только для чтения.

Как сделать полный обход существующего документа с сохранением разметки? Используйте save_as() для конвертации с сохранением структуры. Используйте to_markdown() + create_from_markdown(), когда вам нужно чисто восстановить только текстовую структуру.

Насколько быстро происходит создание документов? Rust-ядро Office Oxide записывает Office-файлы за миллисекунды с показателем прохождения 100% на корпусе бенчмарков — достаточно быстро, чтобы генерировать документы по запросу прямо внутри обработчика запросов.

Смотрите также