Excel 轉 PDF

整個轉換在這個分頁裡跑完,而且我們不會憑空生出任何一個數字。

本機處理

把檔案拖進來,或點擊選擇

支援 XLSX, XLSM。沒有大小上限,不用註冊。

選好檔案之後,這一頁會先把它的結構讀出來 —— 分欄、文字方框、圖表、公式,以及它要畫的每一個字 —— 然後告訴你哪些會保留、哪些不會。這個檢查在轉檔之前就跑完,而且整個過程沒有任何一個位元組離開這個分頁。

    這個工具不做的事

    • 公式一律不重算。我們印的是你的試算表存進檔案的結果;如果某個公式沒有存下結果,那一格會留空,而不是填一個看起來很合理的 0。
    • 第一版不畫工作表裡的圖片。儲存格的文字與數字全部保留。
    • 比紙張寬的工作表會橫向切成好幾疊 —— 這正是 Excel 自己列印時的做法。
    • 超出欄寬的文字會截斷並加省略號,而不是溢出去蓋掉隔欄。
    • 儲存格樣式只支援底色、粗體表頭,以及檔案裡已經存好的數字格式。

    隨站的中文字型是 Noto Sans TC,授權為 SIL Open Font License 1.1,授權全文隨檔案一起提供。OFL 第 5 節末句明文寫著「使用本字型產生的文件」不受「必須維持在本授權下」這個要求約束 —— 也就是你在這裡下載的 PDF 本身不帶任何授權義務。看字型授權

    這一頁會讀你的 .xlsx、把每一張工作表排成表格、然後寫出 PDF,全部在瀏覽器裡完成。儲存格的文字與數字都是可選取的向量文字。有兩件事它刻意不做:不重算你的公式,也不會在檔案裡其實沒有數字的地方印出一個看起來很合理的數字。

    先講最誠實的那件事:我們不重算公式

    .xlsx 對每一個公式儲存格會存兩樣東西:公式本身,以及你的試算表程式上一次算出來的結果。Excel、LibreOffice 與 Google Sheets 存檔時都會寫下那個快取結果,所以只要檔案是從這三者之一存出來的,直接印快取值就是完全正確的,跟重算的結果分不出差別。

    有些檔案沒有那個值。自訂系統的匯出、報表產生器、程式函式庫寫出來的檔案,有時只有公式而沒有存下結果。一個相信「找到什麼數字就印什麼」的轉檔器會在那裡印出 0 —— 而成長率那一欄或合計那一列出現 0,是最危險的一種輸出,因為它看起來完全合理,沒有人會去複查。我們的第一版就是這樣:一整欄 0% 的成長率,加上一列全是 0 的合計。

    現在我們會偵測這種情況並把那一格留空,同時明確告訊你有幾格受影響。留空是誠實的:它會告訴你有東西不見了。而修法只要十秒 —— 用 Excel 或 Google Sheets 把檔案開起來再存一次,結果就補上去了。要做完整的重算引擎,意味著實作幾百個 Excel 函式與它們的邊角情況,而其中任何一個做得稍微不對,我們就又回到「印出看起來合理的錯數字」那個原點。

    寬表,以及為什麼切塊才是正確答案

    試算表通常比紙寬。處理方式有三種:把所有東西縮到看不清、把塞不下的欄位直接切掉,或者把整張表橫向切成好幾疊來印 —— 前面幾欄印一組頁,接下來幾欄再印一組。Excel 自己選的是第三種,我們也是。

    發生的時候這一頁會告訴你,並且指名是哪一張工作表、切成幾疊,所以少一欄絕對不會是驚喜。欄寬優先用你檔案裡存的寬度;沒有存的話,我們量前六十列的內容再依內容調寬,並且夾在合理範圍內 —— 免得某一格裡的一長段文字把其他所有欄位擠出紙外。

    超出欄寬的文字會截斷並加省略號,而不是溢出到隔壁格。這一點跟 Excel 不同:Excel 在右邊那一格是空的時候會讓文字溢出去。但在 PDF 裡,溢出的結果是兩格的字疊在一起而且分不出哪個是哪個,所以「截斷並留下看得見的記號」是比較小的惡。被截斷的格數會回報給你。

    哪些東西不在輸出裡,以及數字為什麼會騙你

    第一版不畫圖片。圖表與樞紐分析表不轉換。如果你的工作簿主要就是一格一格的數字,這些都無關緊要。如果它是一份每一列都有一張照片的商品目錄,那就非常要緊 —— 而這正是保真度指標會騙你的地方。

    我們測過一份真實的 4.2 MB 工作簿,量出文字保留率 100%。那個數字完全誤導:那份檔案裡有 4.00 MB、也就是百分之九十三,是八十六張商品照。我們保住了每一個字,同時丟掉了幾乎整份文件。基準輸出是五十四頁,我們是八頁。

    所以要看的不只是「文字留下多少」,還要看「這份檔案是由什麼組成的」。這一頁會量圖片佔你工作簿多少比例、有多少個錨點把它們放在工作表上,當圖片超過檔案的一半時,它會直接告訴你這份檔案的主要內容不是文字、轉換結果會嚴重不完整。那種情況換一個工具才是對的答案,我們寧願講出來,而不是給你八頁然後讓你自己發現。

    中文,以及試算表特有的那幾個細節

    PDF 要畫中文就必須在檔案裡嵌一份字型,因為每個 PDF 閱讀器內建的字型只有拉丁字母。我們隨站帶一份涵蓋 6,403 個字元的 Noto Sans TC 子集,而且只在你選了檔案、並且那份檔案需要中文時才抓。抓下來之後,還會再依你工作簿真正用到的字切一次子集才嵌進去,所以輸出的 PDF 一樣小 —— 不論下載的是哪一份字集,字型資料通常只佔幾十 KB。

    試算表對這件事的壓力跟文件不一樣。工作表名稱、表頭那一列、短標籤,是全形標點與罕用字最常出現的地方,而客戶名單裡的某一個姓名就可能是常用字集以外的字。實測真實的繁體中文文件大約每五份有一份會用到至少一個 Big5 次常用字,而用到的時候通常只有一兩個字,還常常出現在人名裡。那正是「印一個問號」絕對不能接受的情況,所以偵測到的時候我們會改抓擴充字集。

    數字用的是你的試算表存下來的格式化字串,所以千分位、貨幣符號、百分比與日期格式都會照你設定的樣子出現,而不是原始值。數值儲存格靠右對齊,第一列當表頭並加上底色,儲存格底色會保留。其他樣式 —— 個別字型、逐格框線、設定格式化的條件 —— 不會。

    沒有任何上傳,以及這件事對試算表特別值錢的原因

    試算表是大家最不想交出去的那一類檔案。薪資、客戶名單、報價、還沒公布的數字、病歷或學籍資料 —— 這些就是 .xlsx 的日常內容,而為了把它變成 PDF 就上傳到一台陌生的伺服器,是一筆很差的交易。在這裡,檔案由瀏覽器讀進來、在同一個分頁裡轉換、PDF 在記憶體裡產生。過程中沒有任何一個請求含著你的資料,所以沒有保留期限需要你信任,也沒有一個可能被誤傳出去的連結。

    你可以在一分鐘內自己確認:打開開發人員工具、切到「網路」分頁、轉一次檔案,然後看它請求了什麼。這個頁面、它的程式碼,以及需要時的那份中文字型。沒有別的。本站送出的安全性政策把連線限制在自己的來源,所以就算程式想把你的工作簿送出去,瀏覽器也會擋下來。

    我們用的試算表解析器是 SheetJS,版本釘在 0.20.3,而且檔案本體隨站一起放,不是建置時去套件庫抓。發布在 npm 上的版本比較舊,帶著兩個沒有修補的高風險漏洞,而且我們是實際重現過而不是只讀公告:一個用一段特製的註解污染 JavaScript 的原型,另一個讓一個 262 KB 的檔案把分頁凍結四秒半。兩者都在任何試算表解析器都會走到的路徑上。我們放的這個版本兩個都修好了,而它的雜湊值記錄在專案裡,位元組可以被驗證。

    常見問題

    我的檔案那一格有公式,為什麼印出來是空的?

    因為那個檔案裡沒有存下那個公式的結果,而我們不算公式。在那裡印一個 0 看起來很合理,但那是錯的。用 Excel 或 Google Sheets 把檔案開起來再存一次,結果就會寫進去,下次轉就看得到了。

    試算表裡的圖片會轉出來嗎?

    這一版不會。儲存格的文字與數字全部保留。如果圖片超過檔案的一半,這一頁會在你轉之前就告訴你結果會嚴重不完整。

    我的表很寬,會怎樣?

    會橫向切成好幾疊,跟 Excel 列印寬表時的做法一樣。這一頁會指名是哪張工作表、切成幾疊,不會有任何東西安靜消失。

    可以轉 .xls 嗎?

    不行 —— .xls 是舊的二進位格式。請用 Excel、LibreOffice 或 Google Sheets 開起來另存成 .xlsx。含巨集的 .xlsm 可以接受,巨集會被忽略,不影響輸出。

    我的試算表會被上傳嗎?

    不會。它在你的瀏覽器分頁裡被讀取與轉換。轉檔時盯著開發人員工具的「網路」分頁看 —— 你的檔案不會出現在任何請求裡,而且本站的安全性政策也會擋掉這種請求。

    顏色與字型會保留嗎?

    儲存格底色與數字格式會保留、表頭那一列會加底色、數字靠右對齊。個別儲存格的字型、框線與設定格式化的條件在這一版不會帶過去。