- 省時
- 減錯
收據照片丟進表格,分段辨識並標出要複核的列
從試算表側欄分批辨識收據、回填指定欄位,並用標色提示需要人工複核的列。
背景與使用技術(4 項)
試算表裡有一欄收據或發票照片連結,要變成可用的資料,原本靠一支十來行的選單腳本做 OCR(把圖片辨識成文字):輸出欄位寫死、範圍每次要手動選、執行時沒有任何回饋,低信心度的結果也和正確結果混在一起。改成一份可貼進任何試算表的 Apps Script 側欄:分段執行以避開六分鐘上限,需要複核的列標黃底、失敗的列標紅底且留空,重跑時只補還沒有結果的列。
誰在用
需要把收據轉成申報用資料的財務人員
原本怎麼做
舊做法有四個缺口:輸出欄位寫死在程式碼裡,表格排版一變就得另外複製一份腳本;每次都要手動選範圍;執行久了像當機,看不出進度;低信心度的辨識結果和正確結果落在一樣的格子與格式裡,分不出可不可信。Apps Script 單次執行超過六分鐘會被強制終止,幾百列一次跑很容易超時。
前後對比
量測:實測=有計時或有紀錄;估計=喜特先生推估;客戶自述=客戶回報;規格=設計上的固定條件;待補=尚未取得數字。
流程一眼看懂
照片連結
舊腳本(欄位寫死、手動選範圍)
一次跑完,沒有進度與標記
照片連結
側欄勾選欄位
每 20 列一段辨識
回填並標色
人工複核黃、紅列
流程示意:依本案既有做法整理,非客戶實際畫面。
做了什麼
- 貼上即用:三個檔案貼進需要的試算表,設定存在該表裡,不必每次重填。
- 分段執行:每段 20 列、上一段完成才啟動下一段,不撞六分鐘上限。
- 標色而不是默默填入:需要複核的標黃,失敗的標紅且留空,讓人知道哪幾列要再看一眼。
- 跳過已有結果的列:修好壞連結後重跑,只補還空著的列,已經乾淨的不再花錢。
程式碼與實作細節收在頁面下方,需要時再展開。
你的情況像這樣嗎?
- 你手上有一大批收據或發票照片,要整理成可申報的欄位。
- 現有的辨識流程一跑就像當機,也分不出哪幾筆不可信。
- 你希望辨識結果仍由人複核,而不是直接信任。
運作方式與成本
分段處理,顯示進度
每段 20 列、各自獨立執行,避免整批撞上六分鐘時限
約 US$0.01/次
100 列約 US$1,修好幾條壞連結後重跑只補缺的列
按用途選回填欄位
共 13 欄可選,預設勾選申報用的 7 欄
以上為本案既有成果與運作條件;估計值依原始資料標示,其他專案需另行評估,並非通用成效保證。本案未公開前後工時量測,不以執行規格代替節時成果。
導入與維護條件
- 導入前準備
- 準備照片連結與輸出欄位;目前支援 JPG、PNG、PDF,HEIC 需先在來源端轉檔。
- 本案交付
- 本案交付三個範本檔案與 README,由使用端連接共用辨識服務;這份側欄負責設定、分段執行、回填與複核提示。
- 操作與維護
- 每張表各自設定函式庫版本、授權範圍與服務存取設定;範本更新須逐表貼上並在真實試算表測試。人工複核由使用者完成,部署與後續更新分工依合作範圍議定。
本案未公開導入工期;新專案的資料條件、驗收與維護範圍,需在初談後議定。
挑戰:原本遇到的困難
把發票照片連結變成可用的資料,本身不難,難的是批次處理的體驗與可信度。舊的做法有四個缺口:
- 設定寫死:輸出欄位寫在程式碼裡,表格排版一變就得另外複製一份腳本
- 範圍靠手動選:每次都要自己選要處理的範圍,跑一部分很麻煩
- 沒有回饋:執行時間一長就像當機,看不出進度
- 分不出可不可信:低信心度的辨識結果落在跟正確結果一樣的儲存格與格式裡,沒有任何標記
此外,Apps Script 單次執行超過六分鐘就會被強制終止,而且執行中沒有內建的斷點續跑。幾百列一次跑,很容易超過這條線。
完整解決方案與設計取捨
辨識本身交給共用的收據辨識服務,這個專案只負責使用端:選要跑什麼、用不會撞上執行時限的方式去跑、告訴人哪些列值得再看一眼。
核心設計
- 貼上即用的範本:三個檔案手動貼進需要的試算表的編輯器,設定存在該試算表裡,不必每次重新輸入
- 可選的欄位與固定欄序:側欄勾選要回填哪些欄位,輸出永遠照同一套欄序落位,結果欄位置不變
- 分段執行:每段 20 列,每段都是一次獨立的執行,上一段完成後才啟動下一段,側欄更新進度條
- 標色與留空:讀取乾淨的維持原色,需要複核的標黃底,失敗的標紅底且不寫值
- 跳過已有結果的列:勾選後,只為還空著的列重新送出辨識,已經乾淨的列不再花錢
技術與實作細節
展開完整實作說明
為什麼是範本,不是 clasp 專案
團隊裡其他 Apps Script 工具,都是用 clasp(在本機管理 Apps Script 專案、用指令推送到 Google 的工具)管理的專案,改完推送即可。這一份刻意做成範本,可以貼進任何一張試算表。
代價很實際:每一張在用的試算表都帶著一份獨立的程式副本,沒有「推一次、大家都拿到」這回事。修一個 bug,就得一張一張貼上新版。對一個要隨手給任何需要的表使用的工具來說,這個取捨是可以接受的,但它仍是取捨,維護時要記得。
失敗留空,不寫零
失敗的列,儲存格留空而不是寫零。零本身也是一個值,一張滿是公式的表無法分辨「這裡本來就是零」和「這裡失敗了、被寫成零」。留空可以保證表上其他地方的加總不會把失敗當成真實金額,悄悄算錯。
實際的錯誤訊息完全不在表上,只出現在側欄的複核清單裡,點擊即可跳到那一列。
底色是表上唯一的失敗訊號。黃底代表信心度偏低、格式代號對不到已知代號,或一個連結裡其實包含不只一張發票,值得回去看原圖。紅底代表該列徹底失敗,例如連結壞掉、檔案讀不出來或格式不支援。
每張表的首次設定
因為是範本,每一張採用的試算表都要手動做三件事,才能正常運作:
- 把共用的 Apps Script 函式庫加入為依賴,並指定使用 OCR 呼叫所需的那一版(不自動跟著最新版)
- 在該試算表自己的專案設定裡加上雲端硬碟唯讀的授權範圍。函式庫自己宣告的授權範圍,不會自動延伸到使用它的專案,所以即使函式庫已宣告,使用端仍要自己加一次
- 設定兩個指令碼屬性(Apps Script 存放設定值的地方),分別放辨識服務的網址與存取權杖
這些步驟寫在 README 裡,避免每一張新採用的表各自摸索。
重跑只為缺的部分付費
每次辨識呼叫約 US$0.01。不做任何處理的話,修好幾條壞連結後重跑,等於整欄再付一次錢。勾選「跳過已有結果的列」後,還空著的列會在每批送出前切成連續區段,只為真正缺的部分付費。
目前支援 JPG、PNG 與 PDF,不支援 HEIC(iPhone 預設的照片格式)。HEIC 連結會被歸為失敗的紅底列,要在來源端先轉檔。
離線測不出來的部分
寫回儲存格、套用底色、雲端硬碟授權範圍是否生效,只有在真正的 Google 試算表與 Apps Script 環境中才會發生。本機或 CI 無法合理模擬這些行為,所以每次改完範本,都得手動貼進真實的試算表,用一小段範圍實際跑一次,肉眼確認數值與顏色落在正確的位置,再推廣到其他在用的表。