跳到主要內容跳到頁尾
作品
  • 減錯
  • 省時

兩本佣金帳,從 4.3 萬列主表只追加新資料

從來源主表篩出符合條件的新資料,追加到兩本佣金帳,保留原有紀錄。

2026/07
兩本佣金帳、來源主表 4.3 萬列
案例閱讀約 2 分鐘
背景與使用技術(3 項)

業務佣金要算得出來,得先有一段乾淨的收付款紀錄。原本每期都要人工在四萬多列的試算表裡捲動、拖曳、複製,還得手動挑掉壞帳,兩本帳各做一遍。改成選單按一下的增量同步:用整列指紋判斷搬過沒有,只在表尾新增,絕不覆寫既有資料。

Google Apps ScriptGoogle 試算表增量同步

誰在用

負責佣金帳的財務人員,兩本帳由不同的人維護

原本怎麼做

佣金能不能算,取決於哪些帳單開出去、哪些錢真的收進來。這些紀錄躺在一張 4.3 萬列、沒有按日期排序的試算表裡。上次貼到哪一列、這次範圍有沒有重疊、壞帳有沒有漏掉,全靠人記得:漏一列佣金少算,重貼一列佣金多算。目的帳本是活的,已經有對好、據以發過佣金的舊資料,一次貼錯位置或先清空再整批重貼,舊資料就悄悄消失。

前後對比

上次貼到哪改造前靠人記得改造後每次從目的表現算,不存進度規格
重複與漏列改造前漏一列少算、重貼一列多算改造後整列指紋去重,重跑不會長出重複列規格
壞帳改造前散落各處,一列列用眼睛挑改造後自動排除,並回報排除幾列規格
舊資料改造前先清空再貼,舊資料會悄悄消失改造後只追加到表尾,從不清空、從不覆寫規格

量測:實測=有計時或有紀錄;估計=喜特先生推估;客戶自述=客戶回報;規格=設計上的固定條件;待補=尚未取得數字。

流程一眼看懂

改造前
  1. 4.3 萬列來源主表

  2. 捲動、拖曳、目測範圍

  3. 複製貼上到帳本

  4. 靠人記得上次貼到哪

改造後
  1. 選單「資料同步」

  2. 三層篩選

  3. 追加到表尾

  4. 回報新增、排除、跳過列數

流程示意:依本案既有做法整理,非客戶實際畫面。

做了什麼

  1. 整列指紋防重複:目的表現有的列先建成清單,指紋已存在就跳過。
  2. 三層篩選:近 N 個月、非壞帳、目的表尚未存在,三者都過才追加。
  3. 只追加:最壞情況只是多出幾列可刪除的資料,不會弄丟舊資料。
  4. 兩本帳各自獨立:一邊出問題不會波及另一邊。

程式碼與實作細節收在頁面下方,需要時再展開。

你的情況像這樣嗎?

  • 你要把一張大表的新資料搬到另一張表,靠人記得上次搬到哪。
  • 目的表已經有據以發過款的舊資料,不能被覆寫。
  • 同樣的搬運做在兩本帳上,各自維護、互不對帳。

更多成果與運作條件

  • 選單一鍵取代手動複製貼上

    不必再在 4.3 萬列中捲動、拖曳、目測範圍

  • 重疊與漏列由程式比對

    每次同步逐列對照,不再靠記憶回答「跟上次有沒有重疊」

  • 0 次覆寫

    上線後唯一的動作是表尾追加,最壞情況只是多出幾列可刪除的資料

  • 兩本帳各自獨立:一邊出問題不會波及另一邊

以上為本案既有成果與運作條件;估計值依原始資料標示,其他專案需另行評估,並非通用成效保證。

挑戰:原本遇到的困難

佣金能不能算,取決於「哪些帳單開出去、哪些錢真的收進來」。這些紀錄躺在一張 4.3 萬列、沒有按日期排序的試算表裡,而且佣金拆成兩本獨立的帳,各由不同的人維護。

  • 全靠人記得:上次貼到哪一列、這次範圍有沒有重疊、壞帳有沒有漏掉,沒有任何東西幫你記。漏一列佣金少算,重貼一列佣金多算
  • 壞帳散落各處:客戶最後沒付、認賠沖掉的列不會集中,還會被人不時搬動位置,只能一列列用眼睛挑
  • 目的表是活的:要寫入的帳本已經有對好、也據以發過佣金的舊資料。一次寫錯位置,或圖方便先清空再整批重貼,舊資料就悄悄消失
  • 同樣的事做兩遍:兩本帳要的東西一模一樣,卻各自維護、互不對帳

所以動工前先訂四條不能破的規則:只補新的、跑幾次結果都一樣、不動舊資料、兩邊互不牽連。

完整解決方案與設計取捨

在兩本帳的試算表各加一個「資料同步」選單,點一下就把來源主表的新資料追加到對應工作表最底下,並回報三個數字:新增幾列、因壞帳排除幾列、因已存在而跳過幾列。

核心設計

  1. 整列指紋防重複:把整列的值串成一個識別字串(指紋),目的表現有的列先建成集合,指紋已存在就跳過,重跑不會長出重複列
  2. 三層篩選:近 N 個月 AND 非壞帳沖銷 AND 目的表尚未存在,三者皆過才追加
  3. 只追加(append-only):從不清空、從不覆寫,唯一的寫入動作就是接在表尾
  4. 完全無狀態:不存進度指標,「上次同步到哪」每次從目的表現算,出問題只需檢查來源與目的兩張表
  5. 設定集中:來源 ID、回溯月數、工作表與日期欄對應都放在一個設定物件(CONFIG),改窗口範圍不必動流程

技術與實作細節

展開完整實作說明

為什麼不直接把來源表排序就好?

按日期排序確實會讓「最近六個月」集中在底部,這是第一個會想到的辦法,但它解決不了問題:

  • 那張來源表是別人每天在用的活資料,為了方便而去重排它,這個寫入不該做
  • 壞帳是看描述欄內容標出來的,不是看日期,排完序依然散落各處
  • 排好序的表仍然無法回答「上一輪貼到哪裡」,重複與漏列都是從這裡來的

工具真正做的是逐列跟目的地現有資料比對,答案不依賴來源有沒有排序。

兩份幾乎一樣的程式,刻意不抽共用 library

兩本帳的同步程式邏輯完全相同,唯一差別是綁定的試算表。照「不要重複自己」的直覺應該抽成 library,但這會把兩張原本毫無關係的試算表綁在一條程式依賴上:改一次核心邏輯兩邊同時生效,一邊的資料形狀出狀況,另一邊也被拖下水。

代價是修 bug 要改兩個地方;換來的是一邊出事不連累另一邊。這裡選的是後者。

整列指紋的細節

同一個日期在不同儲存格可能是字串、日期物件或不同顯示格式,直接序列化會算出不同指紋。做法是日期型別的儲存格先轉成時間戳再序列化。追加成功的列也會即時放進同一個集合,所以來源表本來就重複的兩列,也只會搬一次。

壞帳判斷只在收款那張工作表啟用,且用「整格完全相等」而非「包含」:該欄平常放的是銀行摘要,用「包含」會誤刪剛好提到這兩個字的正常交易。

綁定專案的推送是鏡像,不是合併

這類綁在試算表上的 Apps Script,用 clasp(在本機管理 Apps Script 專案、用指令推送到 Google 的工具)推送時,是把整個本地資料夾鏡像到遠端,本地少了什麼遠端就跟著被清掉,而且版本歷史救不回「從沒被推上去過」的檔案。

所以綁定專案的做法是:本地資料夾就是遠端專案的完整快照,要動它,先拉取最新版。

注意

Append-only 的前提是來源是只增不改的交易流水。若來源會回頭修改既有列,被改過的列會被當成新列追加,這時要改成有主鍵的 upsert。

日期欄容錯

日期欄可以用欄號或標題名指定,標題比對不分大小寫並先去空白。來源表的欄位順序或標題大小寫有些出入時仍找得到;真的找不到就丟出寫明工作表與欄位名的錯誤,而不是靜靜算出空結果。來源表不歸我們管,遲早會有人動它一下。

延伸閱讀

有類似的情境想討論

帶著現有流程與去識別範例,討論適合的做法。