从 Markdown 创建 Office 文档
create_from_markdown 可从单个 Markdown 字符串全新生成 DOCX、XLSX 或 PPTX 文件。一份 Markdown 源,三种目标格式。Markdown 是 LLM 生成内容的天然载体:让模型输出 Markdown——这比直接生成 Office XML 可靠得多——再按需渲染成目标 Office 格式。
在内部,Markdown 会被解析为 Office Oxide 的结构化 DocumentIR 并渲染到目标格式,因此获得的映射具有确定性,且与格式无关。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) |
如何从 Markdown 创建 DOCX、XLSX 或 PPTX?
将内容写成 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 会被解析为 Office Oxide 的结构化 IR,各格式再以确定性方式渲染该结构:
| Markdown 元素 | DOCX | XLSX | PPTX |
|---|---|---|---|
# 标题 |
应用 Heading{level} 样式的段落 |
节首的加粗单元格 | 幻灯片标题占位符 |
| 段落文本 | 正文段落 | 连续行中的单元格 | 正文文本占位符 |
- / 1. 列表 |
项目符号或编号列表 | A 列中的单元格 | 正文项目符号 |
| 表格 | Word 表格 | 从下一个空闲行开始的单元格 | PowerPoint 表格 |
**粗体** / *斜体* |
内联文字格式 | 单元格纯文本 | 内联文字格式 |
这套映射较为保守:所有 Markdown 元素都会生成确定性输出,但各 Office 格式还有 Markdown 无法表达的功能(XLSX 单元格数字格式、PPTX 动画、DOCX 批注线程)。如需更丰富的输出,可在创建文件后使用对应格式的编辑器,或直接调用格式专属的写入器。
如何跨格式读取、修改并写回?
将提取与创建结合使用,即可实现跨格式的内容编辑。以 Markdown 读取源文件,修改 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)的简洁方案——前提是只需重建文本结构。若要保留原始排版,请使用经 IR 进行完整往返的 save_as()。参见旧版格式转 OOXML。
为什么从 Markdown 生成 Office 文件?
- 格式无关的模板。 无需改写,只需切换
format参数,即可将同一内容生成为 DOCX(面向 Word 用户)、XLSX(面向数据分析师)或 PPTX(面向演示文稿)。 - LLM 原生。 让模型输出 Markdown,再将其物化为文件——Markdown 是模型最稳定的输出形式。
- 可做差异对比。 Markdown 是纯文本,可以提交到版本控制;Office 文件则成为构建产物。
- 速度快。 Office Oxide 的 Rust 核心能在毫秒内写出文件,在基准测试语料库上通过率达 100%。
进阶:直接从 DocumentIR 构建(Rust)
Rust crate 额外暴露了 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)为只读,无法创建。
Python 或其他绑定中有 create_from_ir 函数吗?
没有。create_from_ir 仅在 Rust crate 中暴露。在 Python、Go、JavaScript 和 C# 中,请使用 create_from_markdown 创建文件;IR(to_ir/to_ir_json)是提取侧的只读概念。
如何在保留排版的情况下对现有文档进行往返处理?
结构保留转换请使用 save_as();若只需重建文本结构,请使用 to_markdown() + create_from_markdown()。
文档创建速度如何? Office Oxide 的 Rust 核心能在毫秒内写出 Office 文件,在基准测试语料库上通过率达 100%,完全可以在请求处理器中按需生成文档。
另请参阅
- 结构化 IR — IR 模式详解(提取侧)
- 旧版格式转 OOXML — 迁移 DOC/XLS/PPT
- 编辑概述 — 就地修改现有文件