C 語言處理 Excel 轉 JSON 實戰
工作中常需將 Excel 數據轉為 JSON 供前端或其他系統使用。雖然 C 語言非首選(上層語言如 Python、C# 處理更簡單),但理解其原理有助於嵌入式或跨平台場景。本文採用「Excel → CSV → C 解析 → JSON」的間接方案,避免直接處理複雜的 OOXML 格式。
核心思路
- Excel 另存為 CSV(逗號分隔值)純文字格式
- 自建 CSV 解析器 (
sccsv.h/.c) 讀取並結構化
- 根據 CSV 結構拼接 JSON 字串輸出
關鍵元件架構
| 檔案 | 職責 |
schead.h/.c | 跨平台基礎巨集、記憶體管理、時間工具、錯誤碼定義 |
sclog.h/.c | 執行緒安全的日誌系統(支援等級、輪轉、上下文資訊) |
tstring.h/.c | 動態字串封裝(自動擴容、追加、檔案讀寫) |
sccsv.h/.c | CSV 解析器(支援雙引號跳脫、換行、空欄位) |
test_xlsmtojson.c | 主程式:串聯 CSV 讀取 → JSON 輸出 |
CSV 解析器亮點
- 狀態機解析:處理雙引號包裹欄位、內嵌逗號/換行、雙引號跳脫 (
"" 代表 ")
- 一維陣列模擬二維:
data[r*clen + c] 存取,記憶體連續,快取友好
- 自動修剪尾部空行/空列
核心轉換邏輯
static void _csvtojson(sccsv_t csv, FILE* json) {
// 假設第 0 列為標題,第 1 列為主鍵名,資料從第 2 列開始
int clen = csv->clen - 1; // 實際資料欄數
int rlen = csv->rlen - 1; // 實際資料行數
// 修剪尾部空行/空列
while (rlen > 2 && !*sccsv_get(csv, rlen, 1)) --rlen;
while (clen > 1 && !*sccsv_get(csv, 0, clen)) --clen;
fputs("[\n", json); // JSON 陣列開始
for (int r = 2; r <= rlen; ++r) {
fputs("\t{\n", json); // 物件開始
for (int c = 1; c <= clen; ++c) {
fprintf(json, "\t\t\"%s\":%s",
sccsv_get(csv, 1, c), // 鍵:第 1 列
sccsv_get(csv, r, c)); // 值:當前列
fputs(c == clen ? "\n" : ",\n", json);
}
fputs(r == rlen ? "\t}\n" : "\t},\n", json);
}
fputs("]", json); // 陣列結束
}
執行範例
$ ./xlsm2json destiny.csv
destiny.csv 轉換成功
$ cat destiny.json
[
{
"id":1,
"name":"張三",
"age":25
},
{
"id":2,
"name":"李四",
"age":30
}
]
優缺點分析
| 優點 | 缺點 |
| 零依賴,純 C 實現,極易移植 | 需手動另存為 CSV,無法直接讀 .xlsx/.xlsm |
| 解析器可複用於其他 CSV 場景 | 大檔案記憶體佔用高(全載入記憶體) |
| 理解資料序列化本質 | JSON 重複鍵值浪費空間,不如二進制協議緊湊 |
優化方向
- 流式處理:邊讀邊寫,避免全量載入
- Schema 驅動:首行定義型別,輸出強型別 JSON(數值不加引號)
- 並行化:大檔案分塊並行解析
- 替代方案:生產環境建議用 Python
pandas/openpyxl 或 C# NPOI 直接處理 Excel