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)」:

  1. 定義標準範本: 建立目標匯總表的標準欄位順序。
  2. 讀取來源 Header: 解析每個 CSV 的第一列 (Row 0,扣除可能作為標題的 B1 特殊列,需視實際格式而定)。
  3. 建立映射字典 (Dictionary): 記錄 `{"交易日": Index 1, "金額": Index 3...}`。
  4. 寫入時對位: 根據字典索引,將資料填入標準範本的正確欄位。

資料處理管線總覽

1. Init

選取多檔 CSV

2. Stream Read

取第一列抓 B1
取第二列建 Mapping

3. Create Sheet

清洗 B1 名稱
建置標準表頭

4. Chunk Process

依 Mapping 對齊資料
批次寫入

5. Finalize

釋放資源
產出匯總檔

使用者體驗 (UX) 優化

在處理龐大檔案時,系統不僅不能崩潰,還要讓使用者安心:

  • 非同步處理 (Asynchronous): 確保 UI 介面不會因為背景處理大量資料而游標轉圈假死。
  • 進度回饋 (Progress Bar): 依據檔案大小或已讀取行數,提供即時的百分比進度條。
  • 異常日誌 (Error Logging): 遇到格式錯誤的單筆資料,記錄於 Log 表,不中斷整體匯總流程。

開發最佳實踐 (Best Practices)

  • 記憶體先決: 處理資料檔永遠假設檔案大小大於可用 RAM,預設採用串流設計。
  • 防呆與防禦性編程: 絕不信任來源檔案的命名與格式,做好 Sanitization 與 Mapping。
  • 模組化: 將「讀取」、「清洗」、「寫入」解耦,方便未來擴充支援 Excel 或 TXT 格式。

Q & A

開放提問與技術交流

Thank You!

交易檔匯總整理工具 - 架構解析

記憶體優化 動態命名 自動化整合