space ocr
指南文章价格文档
convert

把扫描版PDF转成Excel:表格导成CSV,告别乱码

扫描版PDF是图片,无法复制,贴到Excel还会乱码、明细被挤进一个单元格。把PDF拖进space-ocr,各页会自动转成图片,先定义好列,每页就成为一行,并导出为UTF-8 BOM的CSV——用Excel打开也不乱码,导入freee、MoneyForward、弥生也很顺。失败不计费。

8 分钟阅读· 2026-08-31

打开一份扫描的发票或收据PDF,你第一时间就会发现 ── 没法复制。想选中文字却拖不动,连一个数字都拾不起来。原因很简单:扫描版PDF不是表格数据,而是「拍下了表格的一张图片」。在人眼里它是一行行、一列列、还有合计,可对计算机来说,那只是一堆像素。

于是很多人接下来的做法都一样:打开Excel,对着PDF一行一行手动录入;或者硬着头皮复制粘贴,结果呢 ── 中文/日文变成 譁�蟄怜喧 一样的乱码,明细整段挤进一个单元格,版式彻底乱掉。如果你是搜「扫描PDF转Excel」「PDF表格转CSV」「Excel乱码 解决」找到这篇文章的,那痛点八成就在这儿 ── 你想要的,无非是列对齐、能导进财务软件的数据而已。

结论:不用手动录入,也不用复制粘贴

你要做的,就是把PDF直接拖进 space-ocr 的应用。应用会自动把每一页转成图片,再把页面里的值读成带名字的字段。只要一次性定好列(往来单位、日期、合计、明细……),就能做到一页=一行,逐行堆进表格,最后导出成CSV

关键就在这个CSV:它带 UTF-8 BOM,所以在Excel里双击打开也不会乱码。明细不会挤进一个单元格,而是规规矩矩地拆成各自的行和列。语言由引擎自动判别,无需你手动指定。

为什么扫描件没法「直接」进Excel

纸张被扫描的那一刻,文件内容就和照片一样,是位图(栅格图像)。里面没有嵌入文字信息,所以Excel的「获取数据」或复制粘贴都没法把它当表格读出来。因此要分两步:

  1. 读图并结构化(每一页 → 一行带名字的字段)
  2. 把这些行写成CSV(用Excel能顺利打开的格式)

在 space-ocr 的应用里,你把PDF丢进去,它会先把每一页自动转成图片(PNG)再做OCR。所以你这边不用自己把页面切成图片 ── 拖进PDF就行。难点在第①步「读取」,把这一步做准,正是根除乱码和明细挤压的捷径。

从原图 → 抽取表格:扫描件变成「列」

你拖进去的文档,值不再是一堵文字墙,而是带名字的列。列可以自己定义,也可以让引擎来提议(调用 API 时用 fields 声明,或传 autoFields: true 让它提议)。来看一张扫描件是怎么变成带标签的一行的。

把文档拖进去,值就落进带名字的字段 ── 这就是将来排进Excel的那「一行」。

对于有重复行的文档(发票的品目、收据的商品),可以在 array 类型的字段里声明子列。这样页面上的每一行都会变成各自独立的一行,在Excel里就能直接求和 ── 这正是「明细挤进一个单元格」问题的解法。明细怎么搭,读取发票、送货单并转成Excel 里讲得更细。

日期和金额这类列,还可以在 type 里声明标量类型(date / number / integer)。data.values 里保留的仍是票面上印着的原样写法2026年3月31日1,200,000),另外会多出一层 data.normalized,里面是确定性解析后的值 ── 日期为 ISO 格式,金额是能直接参与计算的数字。解析不了的叶子返回 null,原因写在 data.cells[路径].normalized.error,同时以 type_mismatch 进入 data.review.flagged。类型声明不会传给模型,所以它不会改变识别结果本身 ── 改变的是:在进 Excel 或财务软件之前,你另外拿到一份能直接计算的值。

POST /ocr/fields → 请求体(声明列=结构示例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "image": "https://example.com/scan-invoice-p01.png",
  "imageType": "url",
  "fields": [
    { "name": "vendor",       "type": "string" },
    { "name": "invoice_date", "type": "date" },
    { "name": "total",        "type": "number" },
    {
      "name": "line_items", "type": "array",
      "children": [
        { "name": "description", "type": "string" },
        { "name": "unit_price",  "type": "number" },
        { "name": "qty",         "type": "integer" }
      ]
    }
  ]
}
✓ Verified

坐标不是AI凭想象编出来的。 语言模型返回的只是值的文本,以及「用了哪些词元(token)」这类提示,并不返回框本身。引擎会先把这个值的文字,与视觉OCR在页面上实际检测到的符号逐字符比对(以字符级比对为主的路径),再把框放到真实的像素位置上。比对跑过的值会留下一个匹配率作为依据(evidence.match_ratio ── 这个值的文字有多少比例真的在页面上找到了)。如果模型返回了词元提示,有时会用它来覆盖部分字段的位置,但在重复行里提示可能张冠李戴,所以不会照单全收,而是通过列聚类和行一致性检查来验证和校正。要点不是「AI不会错」,而是比对得上的值会留下依据,比对不上的值本身就会浮到待核对清单里(定不下位置就是 nobox,文字对不上就是 text_mismatch)。坐标会同时返回 boxxmin / ymin / xmax / ymax)和跟随页面倾斜的四点 quad,两者都是 0〜1000 归一化(不是像素)。

导入前先抽查

在送进Excel或财务软件之前,你可以当场核对读取结果。把鼠标移到某个值上,原始扫描图里对应的位置会高亮,不用通读整份文档,视线一下就能落到那儿。

不必逐个复核。引擎会给自己没读顺的值打上待核对标记,从这些开始看就行。在应用里,被标记的单元格会着色,理由(text_mismatchmissing 等)显示在气泡里;通过 API 拿到的是同一份清单 data.review.flagged,每一项都带着路径和理由数组 ── 要核对的条数就是这份清单的长度。它不靠一个固定的分数阈值来卡。

把鼠标悬到字段上和原扫描件对照 ── 在导进表格之前就抓出读错的地方。

导出Excel能打开的CSV

值都没问题后,把表格导出成CSV。表头一行排着列名,array 字段会展开成 列名.子列名,重复的明细拆进子行。文件带 UTF-8 BOM ── 正是这一点,让Excel只要双击就能正确打开中文、日文、韩文。你手动改过的单元格,会在导出时覆盖原来的OCR值并体现出来。

一键导出 UTF-8 BOM 的CSV ── 双击后Excel就以列对齐的行打开。

用Excel打开很简单 ── 双击那个 .csv 就行。有了BOM,Excel会自动识别成UTF-8,既不用走文本导入向导,也不会乱码。如果你需要原生工作簿,从这里另存为 → .xlsx 即可。

要直接拿去财务软件也一样,出口都是这个CSV。freee、Money Forward、弥生等,用各自的CSV导入功能读进去就行(不是官方API的自动对接,而是导入CSV文件)。只把收据导成CSV的流程,把收据转成CSV 里单独整理了。

批量处理:用API跑大量扫描件

想把一整个扫描件文件夹都处理掉时,先建一张带列结构的表格,再往里上传页面图片。每张图片都会按这套结构读取、作为行追加进去,最后能导成一份CSV。请求/响应的具体格式,见 API文档

把扫描页图片上传到表格
1
2
3
4
5
6
curl -X POST https://api.space-ocr.com/upload \
  -H "Authorization: Bearer $SPACE_OCR_API_KEY" \
  -F "path=/請求書 2026" \
  -F "files=@scan-p01.png" \
  -F "files=@scan-p02.png" \
  -F "wait=true"
Why it matters

价格很清楚。 每 1 点数 $0.05 按量计费,每月 100点数免费额度(无需信用卡),面向团队的固定套餐 Pro $39/月。而且 识别失败的那部分不计费 ── 没出结果就不收钱。导出CSV在免费额度和按量计费下需 1 点数(同一份数据再次下载免费),Starter 和 Pro 则下载免费。费用一目了然,可以先拿手头的扫描件试一试再决定。

把扫描版PDF转成Excel的步骤

  1. 把PDF拖进应用
    把扫描版PDF拖进 space-ocr 的应用。应用会先把每一页自动转成图片(PNG)再做OCR,所以你不用自己把页面切成图片。
  2. 定好列(结构)
    用自己的字段定义或自动提议,定好往来单位、日期、合计等列。把日期声明成 date、金额声明成 number 这样的标量类型,就会在 data.normalized 里多一份确定性解析后的值。像发票品目这种重复的明细,在 array 类型里声明子列,每一行就会变成各自独立的一行。
  3. 抽查各个值
    把鼠标悬到字段上,原扫描件的对应位置会高亮。引擎没读顺的值会带着待核对标记和理由(如 text_mismatch、missing)返回,先从这些看起,不必逐个复核。
  4. 导出CSV
    把表格导出成CSV。文件带 UTF-8 BOM,array 的明细会展开进子行,你手动改过的地方会覆盖原来的OCR值并体现出来。
  5. 用Excel或财务软件打开
    双击CSV,Excel会把BOM识别成UTF-8,中文/日文不乱码,以列对齐的行打开。需要原生格式就另存为 .xlsx。要导入 freee、Money Forward、弥生,则用各软件的CSV导入功能读进去。
支持中文/日文的扫描件吗?
支持。语言由引擎自动判别,无需手动指定。一套引擎同时处理日文、韩文、中文、英文。手机拍的照片,会在 EXIF 旋转已经落到像素上的状态下读取;引擎不做倾斜校正,所以文档拍歪时,返回的 quad 坐标会跟着那个倾斜走。
是直接支持PDF,还是要先转成图片?
应用直接支持PDF。把PDF拖进去后,每一页会先自动转成图片(PNG)再做OCR,所以你不用手动把页面切成图片。另外,如果是直接调用公开API,输入需是位图(JPEG、PNG、GIF、BMP、TIFF、WebP)。
导出的CSV,用Excel打开中文/日文会乱码吗?
不会。CSV是带 UTF-8 BOM 导出的。这正是让Excel自动判别编码的关键,只要双击,中文、日文、韩文就会进入正确的列。不用走文本导入向导。
能导入 freee、Money Forward、弥生吗?
导出的是Excel能打开的CSV,所以是用各财务软件自带的CSV导入功能读进去。这不是官方API的自动对接,而是导入CSV文件。列名和明细的展开,可以在表格那一侧整理好再导出。
怎么确认准确度?个人信息安全吗?
返回的每个值都会带上它在页面上的位置(box,以及跟随倾斜的 quad)和比对依据。把鼠标悬到字段上,原扫描件的对应位置会高亮,可以直接和原件对照。需要再看一眼的值,会连同理由一起进入待核对清单(API 里是 data.review.flagged),连位置没能定下来的值也在其中,所以不用逐个用眼睛过。个人信息方面,公开 API 的 POST /ocr/* 不保存图片;上传到应用空间里的图片,删除时会连同保存的原图一起删除。费用方面,识别失败的部分不计费。
相关文章