雜記 › 技術筆記 › Excel 貼上轉 JSON:日期、長數字與精度在貼上那一刻就已經變了

Excel 貼上轉 JSON:日期、長數字與精度在貼上那一刻就已經變了

貼進來的已經不是表格裡那一格

做遷移的人都撞見過這一幕:Excel 裡一列訂單號,整塊複製、貼進轉換框,導出的 JSON 裡末尾幾位變了——110101199003072316 出來是 110101199003072320,長度仍是 18 位,只有末 2 位對不上;日期那一整列是帶引號的字串,行數一個不缺,就是當不了數字。第一反應是「工具算錯了」,但一位一位數過去會發現:失真分兩次,第一次在貼上那一刻就完成了。

能進文字方塊的只有字元。從 Excel 複製出來的是按儲存格格式渲染過的文字,工具看到的就是這串文字本身:2024/5/1、12,345.00、1.23457E+11、#N/A——都已經是 Excel 加工過的樣子,工具無從也沒有依據還原成日期或真實數字。

型別推斷只認 4 類,其餘一律落進字串

excel-to-json 裡唯一會改寫儲存格的步驟是型別推斷,辨識範圍只有整數、浮點、true/false、null 四類。勾選「自動識別資料型別(數字/布林值)」時實測如下:

貼進來的格子JSON 裡的樣子發生了什麼
2024/5/1"2024/5/1"不在辨識範圍,落進字串
12,345.00"12,345.00"千分位當文字,只多 2 個引號
1.23457E+11"1.23457E+11"指數串原樣保留,兩種狀態一樣
#N/A"#N/A"錯誤值也只是字串
0077被認成整數,前導零消失
110101199003072316110101199003072320被認成整數,末 2 位改寫

Excel 改寫過的四類文字(日期串、千分位、科學計數法、錯誤值)不在辨識範圍內,原樣退回成字串;看起來像整數的反倒被再加工一次——007→7、00→0、1.0→1、3.00→3、12345.67890→12345.6789、-0 寫成 0,全程沒有提示。裸值與帶引號值混在一份資料裡,下游怎麼讀標量,YAML 與 JSON 的標量型別改寫踩過同一組坑。

會不會失真,是位數和數值一起決定的

長數字容易被理解成「位數一多就出錯」,實測不是。15 位以內 3 個樣本都精確;16 位是否精確要看有沒有跨過 2^53(9007199254740992):同是 16 位,9007199254740991 原樣保留,9007199254740993 輸出成 9007199254740992。17 位起 3/3 失真,18 位普遍改掉末 2 位,19 位全 9 還進到 20 位。再往上就不是改幾位的問題:22 位起 JSON 常值換成指數形式,1000000000000000000000 輸出成 1e+21,長度從 22 字元縮到 5 字元。

也有被救回來的例子:末位帶一個字母(11010119900307231X),整串就不再被認成數字而保持字串——於是同一份 JSON 裡一行 number、一行 string。

位數 → 是否失真 → 輸出形態 15 位 整串精確 16 位 看數值,2^53 是分界 18 位 末 2 位被改寫 22 位 換成 1e+21 圖 1:位數不是唯一判準,跨過分界才改寫

想讓整列保持原文,只有一個開關

能整列保住貼上文字的只有一條:取消勾選「自動識別資料型別(數字/布林值)」。型別推斷在最前面短路,實測 48 組輸入在取消勾選後全部保持字串。邊界要劃清:保住的是貼進來那串字元,不是表格裡的原始精度——勾選或取消都不會讓 1.23457E+11 變回數字,也不會讓 2024/5/1 變回日期。

欄位是按 Tab 切死的,沒有分隔符可挑

切欄依賴寫死的 Tab,頁面上沒有分隔符控件,所以自動識別分隔符的說法不成立。CSV 直接貼進去,每列只算 1 欄——a,b,c 得到一個元素;標頭模式下整份資料塌成 1 個鍵。欄位內帶引號的 Tab 照樣被切開:zhang<TAB>"xin<TAB>guo" 切出 3 格,引號只是留在格子的字元。欄位內換行會把 1 列拆成 2 列,標頭模式下 2 列資料能變成 3 個物件,此後整表欄位都不再對齊。

重名標頭與第一欄做 key:行數會縮,統計條看不出來

標頭是物件輸出的鍵名,重名就在 JSON 裡塌縮:name + name + city 三欄只產出 2 個鍵,鍵的值來自第 2 欄(後寫覆蓋先寫);三欄同名只剩 1 個鍵;空欄名得到一個鍵 "",合法而無意義;資料欄比標頭多時,多出的欄靜默丟棄。

第一欄做 key 更陡:5 列只有 3 個不同的 key,輸出就 3 個鍵,2 列資料消失。統計條按物件鍵數顯示 資料列: 3,看不出丟了列。數字形的 key 還會被重排:貼上順序 42、7、3,輸出順序 3、7、42。

輸入規模 → 輸出鍵數 標頭 3 欄重名 只剩 2 個鍵 三欄同名 只剩 1 個鍵 第一欄做 key 的 5 列 輸出 3 個鍵 統計條 資料列: 3 圖 2:鍵數與統計條都不按行數回報

錯誤提示框基本看不到

這一頁的失敗幾乎都是靜默的結構改變。54 組實測輸入裡「解析錯誤」框顯示 0 次:空白類輸入被提前收進空態,非空輸入又至少留下 1 列,兩處拋錯分支走不到。單列輸入在標頭模式下只得到 [] 和 資料列: 0,頁面照常顯示,不作解釋。

規模不用擔心,體積要留意

沒有長度上限也沒有截斷錯誤:2000 列 5 欄、輸入 74669 字元一次跑完,美化輸出 156672 字元 / 14002 列,壓縮輸出 94671 字元。同一份資料 500 列時美化比壓縮多 15501 字元(約 1.7 倍),標頭模式又比陣列多 15000 字元——鍵名每列重寫一遍就是這筆開銷。輸出區那個 480px 只是顯示視窗,複製走的是全量文字;要比較兩份輸出的體積差,JSON 格式化裡的美化與壓縮口徑可以直接套用。

轉完之後建議核對這 4 處

  • 最長的數字欄與貼上前逐位對:18 位以上先看末 2 位,22 位以上先看它有沒有變成 1e+21 這種形狀。
  • 鍵數與欄數對一遍:標頭有重名或空欄名時,鍵數一定小於欄數。
  • 物件個數與貼上列數對一遍:第一欄做 key 與欄位內換行都會讓兩者不等。
  • 需要原樣文字的欄,取消勾選再跑一次,與勾選結果並排留檔。

常見問題

Q:日期欄能不能轉成真正的時間?

不能。型別推斷裡沒有日期分支,2024/5/1 只保持帶引號的字串,45412 這種序列號也只被當普通整數,兩者都不被當日期。

Q:把型別辨識關掉,就能拿回原始精度嗎?

它拿回的是貼進來那串字元,不是儲存格裡的原始值。像 1.23457E+11 這種貼上時已成指數串的文字,關掉勾選仍是指數字串;18 位號碼則只有關掉勾選才不被再改寫。

Q:貼之前要不要先把 CSV 轉成 Tab 分隔?

要。分隔符只有 Tab,其他符號一律整列當成 1 格,所以先在試算表軟體裡按 Tab 複製再貼,別指望轉換框認得逗號。

📎 相關文章

文本合併後行數對不上:缺尾末換行、被吃掉的 BOM 和不可靠的順序 2026-10-26 條碼解碼只吐原文:EAN-13 檢查碼、UPC-A 的前導零與 CODE128 的模 103 2026-10-26 二維碼解碼實測:糾錯等級救不了遮擋,每模組 2 像素才是生死線 2026-10-26 字頻還是詞頻:同一句中文,一份 23 項榜單和一份空表 2026-10-26 CSS 壓縮沒吃掉 calc 的空格,美化卻把 .btn:hover 劈成了兩截 2026-10-26