离线 · 无上传 · 浏览器本地完成Offline · no uploads · runs in the browser
TXT 转 Excel——离线、文本得是 JSON 数组、不上传TXT to Excel offline — the text must be a JSON array
这条链是四步,前两步决定了它能不能成立:`txt>html` 把整个文件按字符包进一个 `<pre>`(只转义 `&`、`<`、`>`,换行写成 `<br>`,文档标题取文件名的主干(去掉扩展名),没有名字时是 `converted`),**不解释任何记号**——`#` 就是 `#`,粘进去的 HTML 只会是显示出来的字符;`html>json` 发现文档里没有表格,就退一步把**第一个** `<pre>` 的文字当 JSON 解析。所以这一步真正要的条件是「文本本身是一段合法 JSON」,而且是**数组**:中间那步是对象的话,第三步 `json>csv` 会报「JSON 内容必须是包含数据的数组才能转换为 CSV」。两个细节值得知道:`<br>` 对 `textContent` 不贡献字符,所以你文件里的换行到取回时已经没了——JSON 语法不依赖换行,照常解析,但你手工排的版式不会带着走;回退只看第一个 `<pre>`,如果它排在真正的 JSON 块之前,就会解析失败而不是跳过去找。第三步摊成表:列是所有记录键名的并集,某条记录缺的键留空格,没有键可挂的元素写进合成的 `_value` 列而不是丢掉,产物开头带 UTF-8 BOM。第四步 `csv>xlsx` 才是决定工作簿形态的地方:读 CSV 用 `raw: true`,SheetJS 的推断器碰不到数据,随后只有一道规则把该是数字的格子还回去——十进制形状、`String(Number(x)) === x` 逐字节回得来、有效数字不超过 15 位;16 位以上刻意留在文本:那条规则的上限就是 15 位有效数字(仓库里按位数量过 30 万个整数的回写命中率,16 位起只剩 94.5%)。仍是文本的格子再加公式护栏,并把数字格式钉成文本(写出的那一格是内置格式号 49)。还有一条得说在前头:如果你的文本里存的是超长整数(比如 26 位账号),`JSON.parse` 那一刻它就已经是双精度值了,这条链保住的是**解析之后**的样子,超过 15 位有效数字就落在文本里——所以你看到的是那个双精度值自己的最短十进制写法,并且被当作文本存下——不是悄悄四舍五入过的数字。编码判定在第一步做:先按 BOM 与 NUL 的奇偶形状认 UTF-16,再依次试严格的 UTF-8、GB18030、GBK,四种都不像文本就明确报错。全程离线,只有 storage 权限。Four steps, and the first two decide whether the route can run at all: `txt>html` wraps the whole file character by character into a `<pre>` (only `&`, `<` and `>` are escaped, newlines become `<br>`, and the document title is the file’s basename with the extension dropped, or `converted` when there is none), **interpreting no markup** — a `#` stays a `#`, and HTML pasted into the text shows up as characters; `html>json`, finding no table in that document, falls back to parsing the text of the **first** `<pre>` as JSON. So the real condition is “the text itself is valid JSON”, and an **array** at that: if the middle step yields an object, `json>csv` reports “JSON must be an array containing data to convert to CSV”. Two details worth knowing: `<br>` contributes nothing to `textContent`, so the line breaks in your file are gone by the time the text is read back — JSON does not depend on them, so it still parses, but your own layout does not travel; and the fallback reads only the first `<pre>`, so a non-JSON block ahead of the real one fails the parse instead of being skipped past. The third step spreads the array into a table: columns are the union of every record’s keys, a key a record lacks becomes a blank cell, elements with no keys go into a synthetic `_value` column rather than being dropped, and the file starts with a UTF-8 BOM. The fourth, `csv>xlsx`, is what shapes the workbook: the CSV is read with `raw: true`, so SheetJS’s inferrer never touches the data, and one rule alone returns a number type — decimal shape, `String(Number(x)) === x` giving the exact characters back, at most 15 significant digits. Sixteen and above stay text deliberately: the rule itself stops at 15 significant digits, measured in this repo over 300 000 sampled integers per digit length (94.5% survive at 16). Cells still holding text get the formula guard and a pinned text format (that cell carries the built-in format id 49). One caveat stated up front: if your text stores very long integers (a 26-digit account, say), `JSON.parse` has already turned it into a double, and this chain preserves what came **after** the parse — past 15 significant digits it lands in text, so what you see is that double’s own shortest decimal text, kept as a text cell, rather than a silently rounded number. Encoding is settled in the first step: UTF-16 from its BOM or NUL parity, then strict UTF-8, GB18030 and GBK in order, with an outright error when the bytes are not text at all. Everything runs offline on the storage permission.
这条链路怎么走How the route runs
纯文本 (TXT)plain text (TXT) HTMLHTML JSONJSON CSVCSV Excel (.xlsx)Excel (.xlsx)
共 4 步,由扩展的路径搜索自动选出,中间产物不落盘。4 steps, chosen by the extension's own path search; intermediate results never touch the disk.
会保留什么What carries over
- 值按文件里写下的字符进工作簿:`raw: true` 加「逐字节回得来才成数」,`00424` 不缩成 `424`、`2024-01-05` 不变序列号Values enter the workbook as the characters in the file: `raw: true` plus the round-trip rule, so `00424` does not shrink and `2024-01-05` is not a serial
- 16 位以上的编号留在文本并钉住文本格式(内置格式号 49),15 位以内一律不受影响Identifiers of 16 digits or more stay text pinned to a text format (the built-in format id 49); nothing at or below 15 digits is touched
- 记录形状不齐也能落表:列是键名并集,缺的键留空格,没有键的元素进合成的 `_value` 列Untidy records still land: columns are the union of keys, missing keys become blank cells and keyless elements go into a synthetic `_value` column
- 编码逐条严格解:UTF-16(BOM 或 NUL 形状)、UTF-8、GB18030、GBK,都不像文本就报错而不是产出乱码Encoding is decoded strictly one candidate at a time — UTF-16 by BOM or NUL shape, then UTF-8, GB18030 and GBK — and unreadable bytes fail rather than turning into mojibake
如实说明的限制What it does not do
- 文本得是一段合法 JSON **数组**:普通文字、日志、以竖线或制表符排的“伪表”都会明确报错,这条链不会替你造列The text has to be valid JSON **array**: prose, logs and pseudo-tables laid out with pipes or tabs fail outright — this chain will not invent columns for you
- 是 JSON 但是对象(顶层 `{}`)也一样过不了第三道闸:报「JSON 内容必须是包含数据的数组才能转换为 CSV」JSON that is an object at the top level fails the same gate, with “JSON must be an array containing data to convert to CSV”
- 回退读的就是那一个 `<pre>`:里面不是合法 JSON 就解析失败;`[]` 与 `[{}]` 也报错,不给只有表头的空表The fallback reads that single `<pre>`, so anything in it which is not valid JSON fails the parse; `[]` and `[{}]` also fail rather than producing a header-only sheet
- 换行不带着走:`<br>` 不进 `textContent`,所以你写的缩进与空行不会出现在工作簿里(JSON 语法不依赖它们)Line breaks do not travel: `<br>` leaves no trace in `textContent`, so your indentation and blank lines are not reproduced in the workbook (JSON does not need them)
- 超长整数按解析后的双精度值处理:超过 15 位有效数字留在文本,看得见的是近似值而不是原串的每一位Huge integers are handled as the double they become at parse time: past 15 significant digits they stay text, so what you see is an honest approximation rather than every digit of the original
实操提示Working with it
- 只要一份文本表格:TXT→CSV 是同一条链的前三步,产物是带 BOM 的 CSVFor a text table instead of a workbook: TXT to CSV is this chain minus the last step, ending in a BOM’d CSV
- 文本其实是逐行记录:这条链帮不上,请先按能明确分隔的方式存成 CSV 再转For line-oriented records, this chain cannot help: save with an explicit delimiter as CSV first, then convert
- 要的是把 JSON 变得可读:TXT→JSON 或 JSON→HTML,一个重排缩进、一个给可折叠的树视图To make the JSON readable: TXT to JSON re-indents it, and JSON to HTML turns it into a collapsible tree
常见问题Questions people actually ask
我的 txt 是每行一条记录,为什么不按行切成表格?My txt has one record per line — why not split it into rows?
因为这条路不推断分隔符:同一个文件里可能是制表符、连续空格、逗号或竖线,没有一条规则能对所有 txt 都对,而猜错的代价是整列错位、还报成功。这条路只认自带结构的数据,也就是 JSON 数组;其他文本请先用明确分隔符存成 CSV,再走 CSV→Excel。Because this route infers no delimiter: the same file might use tabs, runs of spaces, commas or pipes, no rule holds for all text, and a wrong guess shifts every column while still reporting success. This route reads data that arrives structured, i.e. a JSON array; otherwise save with an explicit delimiter as CSV and take CSV to Excel.
为什么我的 JSON 存成 txt 转成功了,数字却和原来不一样?My JSON saved as txt converted fine — why do the numbers differ?
差异出在 JSON 解析那一步,而不是这条链的后面:`JSON.parse` 把所有数字都读成双精度值,超过 15 位有效数字本来就存不下。链子在最后一步按「字节能逐字回来」判定,所以这类长值会以文本形态留在表里,看得见而不是被悄悄改掉。要每一位都保住,请在源文件里把它写成字符串。The difference is made at the parse, not later: `JSON.parse` reads every number as a double, and past 15 significant digits there is nowhere to put them. The final step then applies its round-trip rule, so such long values stay text — visible rather than silently altered. To keep every digit, write the value as a string in the source.
一份很大的 JSON 数组会出多大工作簿?How big a workbook does a large JSON array make?
一条记录一行,行列数由所有记录键名的并集决定;这份产物只有一张工作表,表名沿用读取 CSV 时得到的那一个。要分页看,请先用文本处理切成几份,各转一次——这条链一次只写一张表。One row per record, and the column count is the union of every record’s keys; the artifact is a single worksheet named whatever the CSV read produced. To work through it in parts, split the text and convert each — this route writes one sheet at a time.
不需要账号,也不需要联网:装好扩展后点图标,在新标签页里打开工作台,文件从磁盘直接选。No account and no network: install the extension, click its icon, and the workbench opens in a new tab reading straight off your disk.
从 Chrome 应用商店安装Install from the Chrome Web Store 安装步骤Install steps GitHub 源码Source on GitHub