這個頁面的程式碼沒跑起來。

直接從資料夾裡開啟 index.html,瀏覽器會攔下 JavaScript 模組,於是你選好一份 PDF之後,頁面不會有任何反應。改用 http 把這個資料夾提供出去:

powershell -ExecutionPolicy Bypass -File serve.ps1

然後開啟 http://localhost:8080/。

PDF 轉 CSV 裡面的每一張表,對帳單也算在內

把 PDF 裡的每一張表都找出來,變成表格軟體打得開的一行一行。

語言: 繁體中文
檢視原始碼
你的檔案不會上傳。這裡根本沒有伺服器。

你選的那份 PDF,是在這臺機器的記憶體裡開啟、讀取的,用的是從這個地址發來的程式碼,CSV 也是這樣寫出來的。這裡根本沒有能做上傳的東西,這一頁的另一頭也沒有伺服器可以接收。表格裡寫的東西,不管是帳號、餘額、一串收款方還是客戶的報價,都留在這個分頁裡。

即時檢查: 檢查中…

離線: 檢查中…

別聽我們說。開啟開發者工具,盯著網路面板,然後轉一份 PDF。沒有任何一條請求帶著某一頁、某一行、某個數字或者檔名。或者乾脆斷網,照樣能轉。

1 選一份 PDF

2 核對它讀出來的內容

PDF 看起來像裝著表格,其實沒有:它裝的是落在紙面各個位置上的文字,那幾道欄是沒人印過的空白。所以下面每一張表都是推出來的,不是讀出來的。要是其中一張帶著餘額,表格上面那一行就是工具在核對自己的結果,每一行都拿上一行來證明。

3 把 CSV 拿走

以 Markdown 檢視

怎麼把 PDF 裡的表格轉成 CSV

  1. 選一份 PDF。一次一份。瀏覽器直接從你的硬碟上把它讀進來,而且是整份都讀完再決定任何事,因為這份檔案寫的是 1.240,00 還是 1,240.00、日期是哪一種順序,都是關於這份檔案的事實,不是關於某一頁的。
  2. 看看它找出來的那些表。每一頁上的每一張表,各有各的欄位,頁面上印了表頭的地方就用它自己的表頭。跨兩個小節或者兩頁、表頭相同的一張表算一張,中間不會重複表頭。折到第二行的單元格會並回它那一行。合計、小計和標籤,都按它們在頁面上的樣子作為行出來。
  3. 挑一張,或者全要。表不止一張的時候,表格上方那個選項決定哪些進 CSV:全部一張接一張,或者只要你來找的那一張。要是某張錶帶著餘額,表格上方那一行會說每一行是不是都對上了。帶年份的日期寫成 YYYY-MM-DD,金額是帶正負號的普通數字;沒有年份的日期原樣保留,因為它屬於哪一年只能靠猜。
  4. 把 CSV 拿走。它按 RFC 4180 寫,該加的引號都加,行尾是 CRLF,編碼是帶位元組序標記的 UTF-8,這樣 Excel 開啟它的時候貨幣符號還是貨幣符號,而不會變成一串字母。所有表放在一個檔案裡的時候,每張表保留自己的表頭行,表與表之間空一行。做出它來沒有上傳過任何東西。

說得更細的版本

Is it safe to upload a bank statement? A statement is every payee, every amount and your balance in one file. Here is what a converter receives, what the careful ones do with it, and how to tell whether the upload needed to happen at all.

常見問題

PDF 裡根本沒有表格,它怎麼找出表格來?

從文字落在哪裡看出來。一頁紙先在旁邊有一欄小字的地方被分開;這一欄小字跟表格裡的一欄分得開,是因為表格的單元格恰好落在同一條基線上,而小字只是碰巧挨在旁邊。然後每一塊從上往下走,在標題和空白處切成一段一段,每一段的欄位,就是好幾行都認同一個單元格在那裡開始或者結束的位置。欄位相同的幾段會重新拼成一張表。這裡沒有按銀行或者按表單分的模板,所以也不存在哪種版式它沒學過。

它只能處理對帳單嗎?

不是。它一開始是個對帳單轉換工具,後來改成找出一份檔案裡的每一張表,因為頭一份真正拿來試的對帳單隻有兩筆交易,卻有另外五張表,一個只要交易的工具在上面什麼都沒找到。發票、價目表、時刻表、成績和報告,同樣都是表格。對帳單多出來的是餘額,只要有,工具就拿它核對每一行。

摘要太長、一欄放不下的時候會怎麼樣?

它會被並回它那一行,而這正是大多數 PDF 轉 CSV 的結果沒法用的原因。只有一格文字、緊挨著某一行的一行,就是那一行的單元格的延續;如果它離下面那一行更近,就併到下面那一行裡,一段放在數值上方、太長而折行的標籤就是這麼印的。帶著不止一格、或者帶著數字的一行,是它自己的一行。

它到底怎麼可能知道我的對帳單讀對了沒有?

因為大多數對帳單都帶著餘額,而餘額是一次證明,不是裝飾。如果每一行上印著的餘額,確實等於上一行的餘額加上這一行的金額,那麼金額就讀對了、行就分對了,而且沒有哪一行被漏掉或者算了兩遍,因為上面任何一種錯誤,都會正好在出錯的那一行把鏈子打斷。工具在每一行上做這道減法,然後把結果告訴你。它找餘額那一欄用的也是同一道算術,而不是去讀表頭,所以一張能透過的表,必然意味著欄位也認對了。沒有餘額的表格沒法這樣核對,頁面也不會假裝核對過。

日期出錯了。03/04 是 3 月 4 日,不是 4 月 3 日。

改表格上方那個選項,全部立刻重算。純數字的日期確實有歧義,而工具是從這份檔案本身來定它,不是從你所在的地區:只要這份檔案裡任何一處的日期有大於 12 的那一位,僅這一行就把所有日期的順序定下來了,頁面也會說明這一點。當每一個日期都落在 12 號或者更早的時候,檔案裡沒有任何東西能把兩種順序分開,所以它會說的正是這件事,並且先按日在前來算,直到你另行指定。像信用卡對帳單那樣不帶年份印出來的日期,原樣保留。

掃描出來的 PDF 能用嗎?

不能,而且它會直說,而不是丟給你一個空檔案。掃描檔是一張照片:那些行是畫素,沒有可以對齊的文字。頁面接著會告訴你可以怎麼辦;如果是對帳單,頭一條建議正是大多數人會忽略的那條,幾乎每一家網上銀行都可以直接給你同一份對帳單的 CSV、OFX 或者 QIF,那既不用轉換,也比從任何一張圖裡讀出來更準確。

帶密碼的 PDF 它能開啟嗎?

不能,而且這是故意的。銀行會給很多對帳單上鎖,通常用出生日期或者帳號的後幾位。把這層保護取掉,跟讀出一張表是兩回事,所以工具會拒絕,並且指給你幾條不用把檔案交出去的路。最好的一條是本站的 PDF 解鎖工具:它在你自己的瀏覽器裡把密碼取下來,頁面上一個字都不改寫,所以文字會原樣落在它當初被印上去的位置。用 Chrome 或者 Edge 輸入密碼開啟再列印回 PDF,或者在 Mac 上用「預覽」匯出,也一樣可以。不要用別的那些說能替你解鎖的網站,那正是把這一頁存在的意義所要擋住的那份檔案傳上去。

我的 PDF 會被上傳到什麼地方嗎?

不會。檔案是你自己的瀏覽器在你自己的硬體上讀的,CSV 也是這樣寫出來的。這個工具沒有伺服器那一端,頁面的 Content-Security-Policy 列出了它可以聯絡的每一個地址,其中沒有一個屬於本站。最簡單的證明,是斷開網路,照樣轉一份 PDF。

CSV 開頭那個奇怪的字元是什麼?

那是位元組序標記,是故意留的。Windows 上的 Excel 讀一個沒有它的 CSV 時,會按系統的舊內碼表來解,於是一張以英鎊或者歐元記帳的表格,貨幣符號會變成一個字母。這個標記告訴它這是 UTF-8。所有要緊的讀取程式都會悄悄跳過它;嚴格到會把它顯示出來的解析器,會給你一個開頭帶著不可見字元的首列表頭,這就是這個取捨的代價。

有大小限制嗎?要錢嗎?

工具裡沒有寫死任何限制。限制是你自己的機器:檔案在讀的時候是放在記憶體裡的,幾百頁的量,一臺筆記本處理起來不會有怨言。它是免費的,不註冊、不登入,也沒有試用期。本站帶廣告,那是養活它的東西;廣告拿不到任何關於你檔案的內容。

斷網能用嗎?

能。把頁面載入一次,然後斷開網路,它照樣能用。這也是證明什麼都沒被上傳的最簡單的辦法:一個把你的檔案發出去轉換的工具,你一拔網線它就停了。