🧩 為什麼 Excel 明明有欄位,程式卻一直報錯? —— 軟體工程師用白話解釋「KeyError」的真正原因
🧠 前言:
「Excel 明明就有這個欄位,為什麼程式一直說找不到?」
這是工程師最常被問、也最容易被誤會的問題之一。
很多人直覺會認為:
👉 「是不是程式壞掉了?」
👉 「是不是我改錯一行?」
但實際上,問題幾乎從來不在你「改的那一行」。
🚨 真實情境(簡化說明)
假設你有一個 Excel 檔案,看起來長這樣:
| LOT_ID | PRODUCT | QTY |
|---|---|---|
| A001 | IC-123 | 500 |
於是你在程式中寫:
value = row["LOT_ID"]
結果程式卻跳出錯誤:
❌ KeyError: 'LOT_ID'
你一定會很困惑:
「欄位就在那裡啊?我眼睛沒瞎吧?」
❗ 關鍵觀念:
👀「你看到的 Excel」≠「程式讀到的 Excel」
這一點非常重要。
🧩 為什麼會發生這種錯誤?(白話版)
原因一:
📄 Excel 的「表頭位置」不是固定的
很多 Excel 檔案其實長這樣:
(空白)
(說明文字)
LOT_ID | PRODUCT | QTY
資料列...
但程式如果 誤把「空白列」或「說明列」當成表頭,
那麼真正的欄位名稱就會被當成「資料內容」。
👉 結果就是:
程式以為根本沒有 LOT_ID 這個欄位
原因二:
🧼 欄位名稱有「肉眼看不到的髒東西」
例如:
-
LOT_ID␣(後面有空白) -
LOT_ID(不是一般空白,是特殊空白) -
Lot_ID(前後都有)
人眼看不出來,但程式是完全不同的字串。
原因三:
📑 同一家公司,Excel 格式卻不固定
今天的檔案:
LOT_ID 在第 1 列
明天的檔案:
LOT_ID 在第 3 列
👉 程式如果「假設永遠一樣」,就一定會翻車。
❌ 常見誤會(一定要澄清)
❗「我只是改了其中一行,為什麼整個程式壞掉?」
因為:
程式在你「真正用到那一行之前」,
就已經先嘗試讀取那個欄位了
所以錯誤並不是你新加的那行造成的,
而是「資料格式不穩定」這件事早就存在。
✅ 正確的工程師做法(概念版)
工程師不會假設 Excel 是乾淨的
工程師會「先確認表頭,再處理資料」
🛠️ 示意版解法(已全面重寫,非實際程式)
✅ 第一步:先掃描前幾列,找真正的表頭在哪
def find_header_row(sheet):
for row_index in range(0, 10):
row_values = read_row(sheet, row_index)
if "LOT_ID" in row_values:
return row_index
return None
📌 意思是:
👉「不要猜第幾列是表頭,用『找關鍵字』的方式確認」
✅ 第二步:重新用正確的表頭讀資料
header_line = find_header_row(excel_sheet)
data = load_excel(
file_path="example.xls",
header_row=header_line
)
✅ 第三步:把欄位名稱清乾淨(非常重要)
clean_columns = []
for name in data.columns:
clean_name = normalize_text(name)
clean_columns.append(clean_name)
data.columns = clean_columns
📌 這一步是在處理:
- 前後空白
- 奇怪符號
- 大小寫不一致
✅ 第四步:再存取欄位(就不會炸了)
for row in data:
lot_value = row["LOT_ID"]
🧠 工程師的核心思維(重點)
❝ 資料永遠不可信,程式一定要有防禦能力 ❞
真正穩定的系統,一定具備:
- ✔ 不假設格式固定
- ✔ 能自動辨識表頭
- ✔ 能處理多版本資料
- ✔ 出錯時給「人看得懂的錯誤」
📌 為什麼這種問題「很容易被誤會是工程師的錯」?
因為:
- 使用者看到的是「畫面正常」
- 工程師看到的是「資料結構錯亂」
這兩個世界,本來就不一樣。
🎯 結語:
問題不在 Excel,也不在你改的那一行
而在「系統沒有為不穩定資料做好準備」
只要補上:
- 表頭自動辨識
- 欄位名稱清洗
這類錯誤就能 永久消失。
留言
張貼留言