提取表格
Office Oxide 把表格当作 IR 一等元素:DOCX 中的每一个 <w:tbl>、XLSX 中的每一个区间、PPTX 中的每一个 <a:tbl> 都会以带类型的 Table { rows: [[单元格, ...]] } 形式回来。一个循环处理三种格式。
遍历文档里的全部表格
Python
from office_oxide import Document
with Document.open("report.docx") as doc:
ir = doc.to_ir()
for section in ir["sections"]:
for el in section["elements"]:
if el["kind"] == "Table":
for row in el["rows"]:
print(row)
Rust
use office_oxide::Document;
use office_oxide::ir::Element;
let doc = Document::open("report.docx")?;
let ir = doc.to_ir();
for section in &ir.sections {
for el in §ion.elements {
if let Element::Table(t) = el {
for row in &t.rows {
println!("{row:?}");
}
}
}
}
JavaScript
using doc = Document.open('report.docx');
const ir = doc.toIr();
for (const section of ir.sections) {
for (const el of section.elements) {
if (el.kind === 'Table') {
for (const row of el.rows) {
console.log(row);
}
}
}
}
Go
doc, err := officeoxide.Open("report.docx")
if err != nil { log.Fatal(err) }
defer doc.Close()
irJSON, _ := doc.ToIRJSON()
var ir struct {
Sections []struct {
Elements []struct {
Kind string `json:"kind"`
Rows [][]string `json:"rows"`
} `json:"elements"`
} `json:"sections"`
}
json.Unmarshal([]byte(irJSON), &ir)
for _, section := range ir.Sections {
for _, el := range section.Elements {
if el.Kind == "Table" {
for _, row := range el.Rows {
fmt.Println(row)
}
}
}
}
C#
using OfficeOxide;
using System.Text.Json;
using var doc = Document.Open("report.docx");
using var ir = JsonDocument.Parse(doc.ToIrJson());
foreach (var section in ir.RootElement.GetProperty("sections").EnumerateArray())
{
foreach (var el in section.GetProperty("elements").EnumerateArray())
{
if (el.GetProperty("kind").GetString() != "Table") continue;
foreach (var row in el.GetProperty("rows").EnumerateArray())
{
Console.WriteLine(string.Join(" | ", row.EnumerateArray().Select(c => c.GetString())));
}
}
}
XLSX:每个工作表区间一张表
对电子表格来说,每个 section 对应一个工作表,表格对应检测到的使用区间。空单元格输出空字符串;合并单元格展开为左上角值,其余位置留空。
Python
import csv
from office_oxide import Document
with Document.open("budget.xlsx") as doc:
ir = doc.to_ir()
for section in ir["sections"]:
sheet_name = section.get("title", "Sheet")
out_path = f"{sheet_name}.csv"
with open(out_path, "w", newline="") as f:
w = csv.writer(f)
for el in section["elements"]:
if el["kind"] == "Table":
for row in el["rows"]:
w.writerow(row)
需要更细粒度的单元格访问(公式、合并、命名区域)时,转用格式特有 API:
with Document.open("budget.xlsx") as doc:
xlsx = doc.as_xlsx()
for sheet in xlsx.sheets():
print(sheet.name(), sheet.dimensions())
DOCX:表格与段落交错
IR 保留段落和表格的源顺序,因此可以还原文章流:
from office_oxide import Document
with Document.open("report.docx") as doc:
ir = doc.to_ir()
for section in ir["sections"]:
for el in section["elements"]:
if el["kind"] == "Heading":
print(f"\n## {el['text']}")
elif el["kind"] == "Paragraph":
print(" ".join(r["text"] for r in el["runs"]))
elif el["kind"] == "Table":
for row in el["rows"]:
print("|", " | ".join(row), "|")
PPTX:表格在幻灯片 section 里
每张幻灯片是独立 section。逐个 section 迭代以恢复幻灯片级别的上下文:
with Document.open("deck.pptx") as doc:
ir = doc.to_ir()
for i, section in enumerate(ir["sections"], 1):
for el in section["elements"]:
if el["kind"] == "Table":
print(f"幻灯片 {i}: {len(el['rows'])}×{len(el['rows'][0])} 表")
需要单元格类型而不是字符串时
IR 中的表格把单元格扁平化成字符串。要在 XLSX 中区分数字、文本、布尔,请用格式特有的访问器:
with Document.open("budget.xlsx") as doc:
xlsx = doc.as_xlsx()
for sheet in xlsx.sheets():
for cell in sheet.cells():
print(cell.address(), cell.value(), cell.value_type())
相关链接
- 结构化 IR — 完整 schema
- Markdown 提取 — 免费输出 GFM 管道表
- 写入 XLSX 单元格 — 把数据写回电子表格