唯杰地图 logo唯杰地图
VJMAP
EN

表格提取

vjcad/references/quickref/table-extraction.md 9.2 KB347 行
原文

从 CAD 图纸中自动识别并提取表格数据。

概念

extractTables() 函数可以自动识别图纸中由直线和文字构成的表格,提取表格结构和单元格数据。

支持识别:

  • 由 Line/Polyline 构成的表格边框
  • 单元格中的 Text/MText 内容
  • 合并单元格

基本用法

全图提取

const { extractTables } = vjcad;

// 全图提取(最简单)
const result = extractTables();

if (result.error) {
    console.error("提取失败:", result.error);
} else if (result.tables.length === 0) {
    console.log("未识别到表格数据");
} else {
    console.log(`识别到 ${result.tables.length} 个表格`);
    
    result.tables.forEach((table, index) => {
        console.log(`=== 表格 ${index + 1} ===`);
        console.log(`行数: ${table.rowCount}, 列数: ${table.colCount}`);
        
        // 打印表格数据
        for (let r = 0; r < table.rowCount; r++) {
            const row = table.datas[r] || [];
            console.log(`第${r + 1}行:`, row.join(' | '));
        }
    });
}

指定区域提取

const result = extractTables({
    bounds: { 
        minX: 0, 
        minY: -200, 
        maxX: 500, 
        maxY: 100 
    }
});

指定图层提取

const result = extractTables({
    layers: ['表格图层', '标注层']
});

完整参数

const result = extractTables({
    // 提取范围(可选)
    bounds: { minX: 0, minY: -200, maxX: 500, maxY: 100 },
    
    // 指定图层(可选)
    layers: ['图层1', '图层2'],
    
    // 包含的实体类型
    includeLine: true,      // 包含直线(默认 true)
    includePolyline: true,  // 包含多段线(默认 true)
    includeText: true,      // 包含单行文字(默认 true)
    includeMText: true,     // 包含多行文字(默认 true)
    includeBlocks: true,    // 包含块中实体(默认 true)
    includeGroups: true,    // 包含组中实体(默认 true)
    
    // 识别参数
    digit: 4,               // 小数精度(默认 4)
    tol: 0,                 // 误差值(0 为自动)
    tableEdgeMinPoint: 12,  // 表格边线最少端点数(默认 12)
    tableTextMinCount: 4,   // 表格最少文字数(默认 4)
    cellEmptyRatio: 90,     // 空值所占最大比例(默认 90)
    
    // 调试
    debug: false            // 调试模式
});

返回数据结构

返回值

interface TableExtractResult {
    tables: TableData[];      // 表格数组
    tol: number;              // 实际使用的误差值
    error?: string;           // 错误信息
    debug_table_lines?: string;   // 调试数据(debug=true 时)
    debug_table_bounds?: string;
    debug_table_posflag?: string;
    debug_table_corner?: string;
}

表格数据

interface TableData {
    rowCount: number;              // 行数
    colCount: number;              // 列数
    rect: string;                  // 表格范围(字符串形式边界)
    rows: string[];                // 行位置信息
    cols: string[];                // 列位置信息
    spans: Record<string, string>; // 合并单元格信息(键→字符串编码)
    datas: string[][];             // 单元格数据 [行][列]
    attr: TableAttr;               // 识别过程属性
}

interface TableAttr {
    cellEmptyRatio: number;
    tableTextCount: number;
    tableCellMaxCount: number;
    unLinkLineRatio: number;
}

示例:绘制并提取表格

const { 
    MainView, initCadContainer, 
    LineEnt, TextEnt, TextAlignmentEnum, 
    Engine, extractTables, message 
} = vjcad;

// 初始化
const cadView = new MainView({
    appname: "唯杰CAD",
    version: "v1.0.0",
    serviceUrl: env.serviceUrl,
    accessToken: env.accessToken,
    sidebarStyle: "none"
});

initCadContainer("map", cadView);
await cadView.onLoad();

// === 1. 绘制表格 ===
const tableStartX = 0;
const tableStartY = 0;
const cellWidth = 100;
const cellHeight = 40;
const rows = 3;
const cols = 4;

// 表格数据
const tableData = [
    ['序号', '名称', '数量', '单位'],
    ['1', '钢筋', '100', '吨'],
    ['2', '混凝土', '500', '立方米']
];

// 绘制水平线
for (let r = 0; r <= rows; r++) {
    const y = tableStartY - r * cellHeight;
    const line = new LineEnt(
        [tableStartX, y],
        [tableStartX + cols * cellWidth, y]
    );
    line.setDefaults();
    Engine.addEntities(line);
}

// 绘制垂直线
for (let c = 0; c <= cols; c++) {
    const x = tableStartX + c * cellWidth;
    const line = new LineEnt(
        [x, tableStartY],
        [x, tableStartY - rows * cellHeight]
    );
    line.setDefaults();
    Engine.addEntities(line);
}

// 填充文字内容
for (let r = 0; r < rows; r++) {
    for (let c = 0; c < cols; c++) {
        const text = new TextEnt();
        text.text = tableData[r][c];
        text.insertionPoint = [
            tableStartX + c * cellWidth + cellWidth / 2,
            tableStartY - r * cellHeight - cellHeight / 2
        ];
        text.height = 15;
        text.textAlignment = TextAlignmentEnum.MidCenter;
        text.setDefaults();
        Engine.addEntities(text);
    }
}

Engine.zoomExtents();
message.info("表格已绘制完成");

// === 2. 提取表格 ===
const result = extractTables();

if (result.tables.length > 0) {
    const table = result.tables[0];
    
    message.info(`识别到表格: ${table.rowCount}行 x ${table.colCount}列`);
    
    // 打印表头
    if (table.datas && table.datas[0]) {
        message.info("表头: " + table.datas[0].join(', '));
    }
    
    // 遍历数据
    for (let r = 0; r < table.rowCount; r++) {
        const row = table.datas[r] || [];
        console.log(`第${r + 1}行:`, row);
    }
}

处理合并单元格

const result = extractTables();

result.tables.forEach(table => {
    // 检查合并单元格
    if (table.spans && Object.keys(table.spans).length > 0) {
        console.log("合并单元格信息:", table.spans);
        
        // spans 类型为 Record<string, string>——键为单元格标识,值为合并信息字符串
        for (const [key, span] of Object.entries(table.spans)) {
            console.log(`单元格 ${key} 合并信息:`, span);
        }
    }
});

导出为 JSON/CSV

导出为 JSON

const result = extractTables();

if (result.tables.length > 0) {
    const table = result.tables[0];
    const json = JSON.stringify(table.datas, null, 2);
    console.log(json);
}

导出为 CSV

const result = extractTables();

if (result.tables.length > 0) {
    const table = result.tables[0];
    const csv = table.datas.map(row => row.join(',')).join('\n');
    console.log(csv);
    
    // 下载 CSV 文件
    const blob = new Blob([csv], { type: 'text/csv' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'table.csv';
    a.click();
    URL.revokeObjectURL(url);
}

注意事项

  1. 表格结构:函数只能识别由直线/多段线构成的规则表格
  2. 文字位置:文字必须在单元格范围内才能被正确归类
  3. 误差容限:复杂图纸可能需要调整 tol 参数
  4. 性能:大型图纸建议使用 bounds 或 layers 限制范围

API 参考

extractTables(options?)

参数 类型 说明
bounds Bounds 提取范围 {minX, minY, maxX, maxY}
layers string[] 指定图层
includeLine boolean 包含直线(默认 true)
includePolyline boolean 包含多段线(默认 true)
includeText boolean 包含单行文字(默认 true)
includeMText boolean 包含多行文字(默认 true)
includeBlocks boolean 包含块中实体(默认 true)
includeGroups boolean 包含组中实体(默认 true)
digit number 小数精度(默认 4)
tol number 误差值(0 为自动)
tableEdgeMinPoint number 表格边线最少端点数(默认 12)
tableTextMinCount number 表格最少文字数(默认 4)
cellEmptyRatio number 空值所占最大比例(默认 90)
debug boolean 调试模式

返回值

字段 类型 说明
error string 错误信息(可选)
tables TableData[] 表格数据数组

TableData

字段 类型 说明
rowCount number 行数
colCount number 列数
rect string 表格范围(字符串形式)
rows string[] 行位置信息
cols string[] 列位置信息
datas string[][] 单元格数据 [行][列]
spans Record<string, string> 合并单元格信息
attr TableAttr 识别过程属性