Markdown으로 Office 문서 만들기
create_from_markdown은 단일 Markdown 문자열에서 DOCX, XLSX, PPTX를 새로 생성합니다. 하나의 Markdown 소스로 세 가지 출력 형식을 지원합니다. Markdown은 LLM이 생성하는 콘텐츠의 자연스러운 출력 형태입니다. 모델에게 Office XML을 직접 생성하라고 요청하는 것보다 Markdown을 출력하게 하는 편이 훨씬 안정적이며, 그런 다음 필요한 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은 모델이 가장 안정적으로 생성하는 형태입니다.
- diff 가능. Markdown은 일반 텍스트이므로 커밋할 수 있습니다. Office 파일은 빌드 아티팩트가 됩니다.
- 빠름. Office Oxide의 Rust 코어는 밀리초 단위로 파일을 작성하며, 벤치마크 코퍼스 전체에서 100% 통과율을 달성합니다.
고급: DocumentIR에서 직접 빌드하기 (Rust)
Rust 크레이트는 Markdown을 거치지 않고 구조화된 IR을 직접 구성하거나 변환하려는 호출자를 위해 create_from_ir도 제공합니다.
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으로 표현할 수 없습니다. 생성 후 형식별 편집기를 통해 추가하세요.
- 이미지, 차트, 스마트 아트, 내장 개체는 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 크레이트에서만 제공됩니다. 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 현대화
- 편집 개요 — 기존 파일 인플레이스 수정