Day 22 核心技術解析
交易檔匯總與 CSV 聚合
記憶體優化與動態命名策略
探討「交易檔匯總整理工具」的大數據量處理架構
Data Engineering & Automation
議程大綱
- 系統背景: 交易檔匯總整理工具的使命
- 效能挑戰: 大規模 CSV 匯入的記憶體危機
- 架構解法: 分塊處理與記憶體優化
- 動態邏輯: 根據 B1 儲存格動態命名工作表
- 資料對齊: 異質 CSV 欄位的映射策略
- 最佳實踐與總結
系統背景與痛點
每日營運會產出大量、分散的交易明細檔案 (CSV格式)。
傳統痛點:
- 人工逐一開啟、複製貼上耗時極大。
- 人為失誤率高,容易遺漏或錯置資料。
- 檔案格式不一,欄位順序可能調換。
目標:自動化匯總
打造一鍵匯入、自動清洗、分類存放的高效能整理工具。
核心操作流程
簡單三步驟,完成複雜的資料聚合任務:
1. 啟動工具
開啟匯總整理工具,初始化環境參數。
2. 批次匯入
選取多個來源 CSV 檔案進行自動讀取。
3. 動態建表
依據內容自動建置工作表並完成資料寫入。
挑戰 01
大規模 CSV 的記憶體危機
當資料量達到百萬筆級別時:
- Out of Memory (OOM): 一次性將整個巨大 CSV 讀入記憶體 (例如使用簡單的 `ReadAll` 方法) 容易導致程式崩潰。
- UI 卡頓/假死: 主執行緒被長時間的 I/O 阻塞。
- GC 壓力: 產生大量暫存字串物件,增加垃圾回收負擔。
記憶體優化:串流與分塊
❌ 傳統作法 (全量讀取)
File -> [ 1GB 記憶體緩衝區 ] -> 解析
極易崩潰
✅ 優化架構 (Streaming / Chunking)
File -> [ 讀取 N 行 ] -> 處理並寫入 -> 釋放
File -> [ 讀取下 N 行 ] ...
穩定低耗
透過逐行讀取 (Line-by-line) 或批次分塊 (Chunking),將記憶體使用量控制在常數級別 (O(1))。
挑戰 02
B1 儲存格動態命名機制
業務需求:
本次匯入的結果,必須另存工作頁,且必須根據來源檔儲存格 B1 的內容,來定義工作表名稱。
潛在陷阱:
- B1 內容包含非法字元 (如 `\`, `/`, `?`, `*`, `[`, `]`)。
- B1 內容超過長度限制 (通常限制為 31 個字元)。
- 不同檔案的 B1 內容相同,導致工作表名稱衝突。
命名清洗與防護策略
在讀取到 B1 內容後,寫入新表前必須執行的過濾機制:
1. 字元正規化 (Sanitization)
使用 Regex 替換非法字元為底線 `_`。
`Name.Replace(InvalidChars, "_")`
2. 長度截斷 (Truncation)
強制擷取前 31 碼,避免建立失敗。
`Name.Substring(0, Math.Min(31, Name.Length))`
3. 衝突處理 (De-duplication)
檢查名稱是否已存在,若存在則加上流水號 (例:`Name_v2`)。
B1 內容的精準萃取
既然我們採用了「串流讀取 (Streaming)」,如何獲取 B1?
- CSV 結構特性: B1 在 CSV 中代表「第一列的第二個欄位」。
- 萃取邏輯:
1. 讀取串流的第一行 (Row 1)。
2. 依據分隔符號 (通常為逗號) 進行字串分割。
3. 取得陣列索引 [1] 的值,即為 B1。
4. 暫存此名稱,隨後初始化對應的工作表。
挑戰 03
異質來源的欄位對齊
當匯總多個單位的交易檔時,常遇到 Schema 不一致:
來源 A (單位甲)
[交易日] [金額] [帳號] [備註]
來源 B (單位乙)
[帳號] [交易日] [幣別] [金額]
若直接以 Column Index 寫入,將導致資料嚴重錯置!
動態欄位映射 (Dynamic Mapping)
不依賴絕對位置,改依賴「欄位標題 (Header Name)」:
- 定義標準範本: 建立目標匯總表的標準欄位順序。
- 讀取來源 Header: 解析每個 CSV 的第一列 (Row 0,扣除可能作為標題的 B1 特殊列,需視實際格式而定)。
- 建立映射字典 (Dictionary): 記錄 `{"交易日": Index 1, "金額": Index 3...}`。
- 寫入時對位: 根據字典索引,將資料填入標準範本的正確欄位。
資料處理管線總覽
2. Stream Read
取第一列抓 B1
取第二列建 Mapping
3. Create Sheet
清洗 B1 名稱
建置標準表頭
4. Chunk Process
依 Mapping 對齊資料
批次寫入
使用者體驗 (UX) 優化
在處理龐大檔案時,系統不僅不能崩潰,還要讓使用者安心:
- 非同步處理 (Asynchronous): 確保 UI 介面不會因為背景處理大量資料而游標轉圈假死。
- 進度回饋 (Progress Bar): 依據檔案大小或已讀取行數,提供即時的百分比進度條。
- 異常日誌 (Error Logging): 遇到格式錯誤的單筆資料,記錄於 Log 表,不中斷整體匯總流程。
開發最佳實踐 (Best Practices)
- 記憶體先決: 處理資料檔永遠假設檔案大小大於可用 RAM,預設採用串流設計。
- 防呆與防禦性編程: 絕不信任來源檔案的命名與格式,做好 Sanitization 與 Mapping。
- 模組化: 將「讀取」、「清洗」、「寫入」解耦,方便未來擴充支援 Excel 或 TXT 格式。
Thank You!
交易檔匯總整理工具 - 架構解析
記憶體優化
動態命名
自動化整合