space ocr
指南文章價格文件
documents

如何從圖片中提取表格資料並轉存為 CSV 檔案

將表格、訂單或出貨單的照片,轉換為乾淨的 CSV 檔案。了解 space-ocr 如何判讀項目明細,以及逐列驗證如何把需要人工核對的數值標示出來。

4 分鐘閱讀· 2026-08-31

將掃描表格的資料輸入試算表,是件傳統又繁瑣的工作。您可能有一張清晰的出貨單或採購單圖片,上面列滿了詳細項目,但這些終究只是像素。接下來的步驟通常是枯燥的人工資料輸入,逐一將品項、數量和價格複製到新的儲存格中。這個過程不僅緩慢,一個小小的打字錯誤就可能毀了整份資料。

A table-style order/delivery document
一張項目明細表——包含多列資料,但格式一致。

一個更好的方法,是把表格結構定義為一份 schema(欄位結構)。與其單純抓取一大塊文字,不如先宣告您需要的欄位。重複出現的項目明細區塊定義為 array 類型欄位,並在它的子欄位(children)中排列各欄;固定是數字的欄位則直接宣告類型。

1
2
3
4
5
6
7
8
9
10
{
  "name": "items",
  "type": "array",
  "children": [
    { "name": "name",   "type": "string" },
    { "name": "qty",    "type": "integer" },
    { "name": "price",  "type": "number" },
    { "name": "amount", "type": "number" }
  ]
}

您不需要指定列數,回傳多少列由頁面本身決定。每一列都以帶索引的路徑回傳(values.items[0]、values.items[1] ……),同一條路徑也就是逐值座標與驗證對照表的鍵 cells["items[0].price"]。宣告類型不會改變提取到的數值,因為類型不會傳給模型;它增加的是與 values 並列的第二層確定性資料 data.normalized。

為項目明細定義一個陣列欄位,然後上傳圖片,即可將表格提取為結構化網格。

即使是內容密集、充滿重複數值的表格,這種方法也同樣有效。系統會先使用大型語言模型來初步提取文字,但這只是第一步。對於每一個數值,例如品名為「刻みたくあん」或單價為「580」,系統都會進行交叉驗證。引擎會把語言模型的判讀與文件的欄位結構比對,並與頁面上原始偵測到的 OCR 符號逐字匹配。當某個數值滑到相鄰的資料列時,該座標處的字元通常就對不上了,這個欄位不會被悄悄放行,而是記入待核對清單。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
"data": {
  "values": {
    "items": [
      { "name": "刻みたくあん", "qty": "3",
        "price": "580", "amount": "1,740" }
    ]
  },
  "cells": {
    "items[0]": {
      "box": { "xmin": 263, "ymin": 460,
               "xmax": 738, "ymax": 523 },
      "quad": [ { "x": 263, "y": 460 }, { "x": 738, "y": 460 },
                { "x": 738, "y": 523 }, { "x": 263, "y": 523 } ],
      "verified": null, "review": null
    },
    "items[0].name": {
      "box": {…}, "quad": […],
      "verified": true, "review": null,
      "evidence": { "text_match": true, "match_ratio": 1.0 }
    },
    "items[0].qty": { "box": {…}, "quad": […],
                      "verified": true, "review": null },
    "items[0].price": {
      "box": { "xmin": 693, "ymin": 460,
               "xmax": 738, "ymax": 488 },
      "quad": […],
      "verified": false,
      "review": { "reasons": ["text_mismatch"] },
      "evidence": { "text_match": false, "match_ratio": 0.62 }
    }
  },
  "review": {
    "unit": "field",
    "flagged": [
      { "path": "items[0].price", "reasons": ["text_mismatch"] }
    ]
  },
  "normalized": {
    "items": [ { "qty": 3, "price": 580, "amount": 1740 } ]
  }
}

這份清單就是待辦佇列:data.review.flagged 會指名確切的路徑與理由,cells["items[0].price"] 則保留了當時比對的座標。但它並非萬無一失。相鄰列若印著相同的數字,框落在哪一列字元都能對上;兩個引擎若犯了同一個誤讀,也就沒有可供對照的一方。因此,逐字比對看不見的行列錯位,值得交給可宣告的規則:編碼欄位用 pattern,主檔已有的值用 enum,合理區間用 min 與 max。任何違反都會出現在同一份 review.flagged 之中。

最後一層是您自己的核算,而它屬於下游。由於 qty 宣告為 integer、金額欄位宣告為 number,data.normalized 中放的是解析後的數值("1,740" 即 1740),因此一列的核算只需一次乘法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const { values, normalized, review } = data;

const rows = values.items.map((item, i) => {
  const n = normalized.items[i];
  const flagged = review.flagged.some((f) =>
    f.path.startsWith(`items[${i}]`)
  );
  return {
    name: item.name,
    qty: n.qty,
    price: n.price,
    amount: n.amount,
    // 需要人工核對的列:被標記,或這一列算不平
    check:
      flagged || n.qty == null || n.qty * n.price !== n.amount,
  };
});

無法解析的葉節點在 normalized 中回傳 null,失敗類型記在 cells[path].normalized.error,並以 type_mismatch 出現在待核對清單裡。計算時取用 normalized,顯示時保留 values——帶著座標與驗證的是 values 這一側。

資料提取完成後,只需點擊一下,即可將整張工作表匯出為乾淨的 CSV 檔案。
✓ Verified

每一個數值都會與它所在的那一頁對照。系統把模型的判讀與該處實際偵測到的 OCR 符號逐字匹配,匹配了多少記錄在 evidence.match_ratio;達到 0.85 或更高即為高信賴度匹配。結論本身是 verified,它是 review 的鏡像:只要有任何標記就是 false,比對跑過而沒有標記則是 true,沒有可比對的對象(例如整列的聯集框)則是 null。座標由匹配到的符號推導為 box 與 quad,並相對 data.image 標準化為 0–1000 的範圍。這是數值來自何處的證據,而不是它就是您要的那個數值的證明;沒有通過核對的數值,都列在 review.flagged 裡。

費用根據用量計算,處理每張圖片為 $0.05。您的帳戶每月包含 100 次免費掃描。如果因任何原因提取失敗,我們不會收取任何費用。

  1. 定義工作表結構
    建立一個新的工作表並定義您的欄位。對於項目明細,請使用「array」類型,並為其新增如品名、數量、價格等子欄位。
  2. 上傳您的圖片
    透過拖放或使用 API 將表格圖片上傳至該工作表。
  3. 檢視提取的資料
    圖片將會根據您定義的結構進行處理。表格中的每個項目明細都會以結構化資料列的形式出現在工作表中。
  4. 視情況修正
    點擊任一儲存格,即可在圖片上看到對應的區域。您可以直接在網格中手動修正任何數值。
  5. 匯出為 CSV
    點擊「匯出」按鈕並選擇 CSV。您的表格資料(包含所有項目明細)將會下載為一個乾淨、結構化的檔案。
如果我的表格有合併儲存格或複雜的版面配置該怎麼辦?
本系統專為標準的行列式表格設計。對於高度複雜的版面,您可以定義多份 schema(欄位結構),或在初步提取後於工作表中手動調整資料。
CSV 匯出功能如何處理項目明細?
如果您的陣列欄位名稱為「items」,且其子欄位為「name」和「price」,那麼 CSV 的標頭將會是「items.name」和「items.price」。圖片中的每個項目明細都會成為 CSV 檔案中的一個獨立資料列。
我可以處理含有表格的 PDF 檔案嗎?
可以,在我們的網頁應用程式中,您可以直接拖放 PDF 檔案,系統會自動將每一頁渲染成圖片進行處理。API 本身則接受如 JPEG 和 PNG 等點陣圖格式。
每個儲存格的座標是如何決定的?
對於每個提取出的數值,系統會將其字元與頁面上偵測到的 OCR 符號進行匹配。匹配到的符號決定了該數值的 `box` 與 `quad`,並相對實際判讀的頁面(`data.image`)標準化為 0–1000 的範圍。這組座標是該數值來源的證據,您可以把它畫回圖片上自行核對。
表格的列數有限制嗎?
沒有可設定的列數上限,回傳多少列取決於頁面本身。真正有上限的是同步呼叫:處理時間上限為 180 秒,超時會回傳 504 `ocr_engine_timeout`,且不計費。原因通常不是像素數量而是資訊密度,因此非常密集的表格建議一頁一張圖,或改用非同步的 `POST /upload`。

將您的圖片表格轉化為可用資料

每月獲取 100 次免費掃描。無需信用卡即可開始使用。

相關文章