1. VBA 解析 JSON 的真实痛点:为什么 Excel 自动化总卡在接口数据上
如果你用 Excel 做过接口数据自动化,大概率遇到过这个场景:调用一个天气、物流、地图或订单接口,返回一大串 JSON,粘到单元格里像一团乱麻,想取出distance、duration、status这种字段,用InStr、Mid、Split硬切字符串,字段一多就崩,嵌套一层就找不到北。这就是 VBA 解析 JSON 最典型的痛点——VBA 原生没有 JSON 解析器,而接口返回的数据几乎全是 JSON。
我试过用正则去抠字段,短平快的单层 JSON 还能凑合,一旦遇到data.route.paths[0].steps这种多层嵌套加数组的结构,正则表达式会写得又长又脆,接口字段顺序一变就全废。更麻烦的是,很多接口返回的 JSON 里还嵌着字符串形式的 JSON,比如某个字段本身是一段被转义的 JSON 文本,你得先解一层、再解一层,手工处理转义引号能把人逼疯。
刘永富老师的 VBA 插件(常见于API.JSON这个类模块)正好补上了这块短板。它把 JSON 解析封装成一个可以在 VBA 里直接New出来的对象,支持类似 JSONPath 的路径取值,$.data.route.paths[0].distance这样写就能直接拿到深层字段,数组用[0]下标,嵌套对象用点号一路走下去。对做 Excel 自动化、需要批量处理接口返回数据的人来说,这套东西的性价比很高:不用装额外运行库,纯 VBA 类模块导入即用,配合Debug.Print就能在立即窗口里验证取值对不对。
这篇文章面向的就是这类场景:你手上有一批接口返回的 JSON,想在 Excel 里自动解析、提取字段、写进表格,或者拿解析结果做后续计算。我会把插件加载、核心解析代码、嵌套数组处理、调试方法一步步拆开讲,同时说明怎么用 TaoToken 统一 Key 和 API 通道拿到稳定的测试数据,避免调试阶段被接口限流或鉴权问题打断。整篇按可跟做的步骤来,代码都能直接复制进 VBE 跑。
先说清楚适用人群:会一点 VBA、能打开 VBE、知道怎么插入模块,但对 JSON 解析没系统方法的人。如果你连Sub和Dim都没写过,建议先补一下 VBA 基础,否则后面调试会吃力。下面从插件准备开始。
2. TaoToken 前置准备:统一 Key 与 API 通道,给 VBA 调试供数据
在写解析代码之前,得先解决“数据从哪来”的问题。调试 JSON 解析最怕两件事:一是接口要鉴权,Key 散落在各个平台,换个接口就得换一套配置;二是调试阶段请求频繁,容易被限流,导致你分不清是代码错了还是接口拒了。我的做法是先用 TaoToken 把 Key 和 API 通道统一起来,VBA 里只认一个 Base URL 和一个 Key,测试数据从模型对话或接口文档里拿,调试链路就干净很多。
TaoToken 在这里的角色是统一的 API 接入层:你拿到一个 Key,配好 Base URL,就能通过同一套通道访问不同模型和接口能力。对 VBA 场景来说,最直接的用法是先用它生成或获取一段结构稳定的 JSON 测试数据,比如让模型返回一段带嵌套数组的 JSON,粘到 VBA 里练解析;等解析逻辑跑通,再换成真实业务接口。这样调试阶段不依赖具体业务系统的鉴权,出错也好定位。
具体操作上,你需要三样东西:API Key、Base URL、以及一个可用的 Model ID。Key 在控制台的 API Keys 页面创建,Base URL 用https://taotoken.net/api,Model ID 按你实际要调的模型填。这三件套在后面的配置片段里会反复出现,建议先记下来。
创建 Key 的入口在控制台,路径是 API Keys 管理页。拿到 Key 之后不要直接硬编码在 VBA 里,尤其是要发给别人用的宏,建议先放在一个隐藏工作表或环境变量里,代码里用变量读取。调试阶段图省事可以直接写在模块顶部的常量里,但上线前一定要挪走。
如果你只是想先拿一段 JSON 练手,可以直接用模型对话生成测试数据,比如让它返回一段包含data.route.paths[0].distance这种结构的 JSON。拿到之后粘进 VBA,配合刘永富老师的插件解析,验证路径取值是否正确。这一步不需要写 HTTP 请求,纯解析练习,能快速建立对路径语法的感觉。
等解析练熟了,再考虑在 VBA 里发 HTTP 请求拿真实数据。VBA 发请求常用MSXML2.XMLHTTP或WinHttp.WinHttpRequest.5.1,把 Base URL、Key、Model ID 填进请求头和请求体即可。这里不展开完整请求代码,重点是先把解析这关过了,因为大部分报错其实出在解析路径写错,而不是请求本身。
需要提醒的是,调试用的 Key 和正式业务的 Key 最好分开,避免调试期间的频繁请求影响正式额度。TaoToken 的控制台可以管理多个 Key,按用途区分,出问题也好排查。下面进入插件加载和核心代码部分。
3. 刘永富老师插件加载与可复制配置:JSON 解析核心代码片段
这一节是全文的技术核心。刘永富老师的 VBA JSON 插件通常以类模块形式提供,核心是API.JSON这个类。加载方式有两种:一是直接导入.cls文件,二是把类模块代码复制进 VBE 新建的类模块,并把类模块命名为JSON(注意命名要和代码里的New API.JSON对应,如果类模块在API命名空间下,就保持API.JSON的引用方式)。
导入步骤:打开 Excel,按Alt + F11进 VBE,右键工程 → 导入文件,选择插件提供的.cls文件。导入后左侧工程树里会出现对应的类模块。如果没有.cls文件,就新建类模块,把插件源码粘进去,然后在属性窗口把类模块名称改成JSON。如果你的工程里建了一个叫API的文件夹或命名空间,引用时写New API.JSON;如果直接放在工程根下,就写New JSON。这一点很多人第一次会踩坑,报“用户定义类型未定义”多半是命名没对上。
加载完成后,核心解析代码就三行起步:声明对象、Parse传入 JSON 字符串、用GetSingleValue按路径取值。下面这段可以直接复制进标准模块运行,JSON 用的是带嵌套数组的路线数据:
Sub ParseJsonDemo() Dim j As API.JSON Set j = New API.JSON Dim raw As String raw = "{'data':{'route':{'destination':'121.473701,31.230416','origin':'118.796877,32.060255','paths':[{'distance':296768,'duration':15060,'restriction':0,'steps':[],'strategy':'时间最短','toll_distance':266428,'tolls':262,'traffic_lights':56}]},'count':1},'errcode':0,'errdetail':null,'errmsg':'OK','ext':null}" j.Parse raw Debug.Print j.GetSingleValue("$.data.route.paths[0].distance") Debug.Print j.GetSingleValue("$.data.route.paths[0].duration") Debug.Print j.GetSingleValue("$.data.route.paths[0].strategy") Debug.Print j.GetSingleValue("$.data.route.paths") Debug.Print j.GetSingleValue("$.data.route.paths[0]") End Sub路径语法要点:$是根,点号进入对象,[0]进入数组取第一个元素。遇到中括号就是数组,必须带下标,比如paths[0];不带下标直接取paths,返回的是带中括号的数组字符串。这一点在调试时很关键:GetSingleValue("$.data.route.paths")返回[{...}],而GetSingleValue("$.data.route.paths[0]")返回{...},后者没有外层中括号,可以直接再Parse一次。
嵌套 JSON 字符串的处理是另一个高频需求。有些接口会把某个字段的值做成转义后的 JSON 字符串,比如paths[0]取出来是一段带双引号的文本。VBA 里双引号是字符串定界符,直接Parse会出错,需要先把双引号替换成单引号,再解析:
Sub ParseNestedJson() Dim j As API.JSON Set j = New API.JSON j.Parse "{'data':{'route':{'paths':[{'distance':296768,'duration':15060}]}}}" Dim inner As String inner = j.GetSingleValue("$.data.route.paths[0]") inner = Replace(inner, Chr(34), Chr(39)) Dim jj As New API.JSON jj.Parse inner Debug.Print jj.GetSingleValue("distance") Debug.Print jj.GetSingleValue("duration") Dim keys() As String Dim vals() As String keys = jj.Keys vals = jj.Values Dim i As Long For i = LBound(keys) To UBound(keys) Debug.Print keys(i) & " = " & vals(i) Next i End SubKeys和Values两个方法返回数组,配合循环可以遍历当前层所有字段,适合字段名不固定、需要动态处理的场景。注意Keys/Values返回的是当前解析层的键值,不会递归到深层,深层还是要靠路径逐层取。
如果你要在 VBA 里发请求拿数据,配置片段大致如下(以WinHttp为例,Key 和 Model ID 用占位符,实际替换):
Dim http As Object Set http = CreateObject("WinHttp.WinHttpRequest.5.1") http.Open "POST", "https://taotoken.net/api/v1/chat/completions", False http.setRequestHeader "Content-Type", "application/json" http.setRequestHeader "Authorization", "Bearer YOUR_API_KEY" http.Send "{""model"":""YOUR_MODEL_ID"",""messages"":[{""role"":""user"",""content"":""返回一段带嵌套数组的JSON""}]}" Debug.Print http.ResponseText三件套对应关系:Base URL 用https://taotoken.net/api,Key 填YOUR_API_KEY,Model ID 填YOUR_MODEL_ID。返回的ResponseText就是 JSON,直接丢给j.Parse即可。这样解析和取数就串起来了。
4. 验证请求与成功结果:Debug.Print 输出与字段核对
代码写完必须验证,否则你不知道路径写对没有。VBA 里最直接的验证手段是Debug.Print,输出到立即窗口(Ctrl + G打开)。跑上面第一段ParseJsonDemo,立即窗口应该依次输出:
296768 15060 时间最短 [{'distance':296768,'duration':15060,...}] {'distance':296768,'duration':15060,...}第一行296768是distance,第二行15060是duration,第三行是strategy的中文值。第四行带中括号,说明取的是数组整体;第五行不带中括号,说明取的是数组第一个元素对象。这五行输出能同时验证三件事:路径语法对不对、数组下标有没有生效、嵌套对象能不能继续解析。
如果输出是空的,先检查路径拼写。常见错误是漏了$或点号,比如写成data.route.paths[0].distance,少了根符号,插件可能返回空。另一个常见错误是数组下标越界,paths[1]在只有一个元素时取不到,返回空而不是报错,容易误判成解析失败。
验证嵌套解析那段ParseNestedJson,立即窗口应该输出296768、15060,然后遍历输出distance = 296768、duration = 15060。如果Replace那步没做,jj.Parse inner会报错或解析出空值,因为双引号在 VBA 字符串里是定界符,直接传进去语法就断了。
再进一步,把解析结果写进单元格验证。比如:
Sub WriteToSheet() Dim j As API.JSON Set j = New API.JSON j.Parse "{'data':{'route':{'paths':[{'distance':296768,'duration':15060}]}}}" Dim ws As Worksheet Set ws = ThisWorkbook.Sheets(1) ws.Range("A1").Value = j.GetSingleValue("$.data.route.paths[0].distance") ws.Range("A2").Value = j.GetSingleValue("$.data.route.paths[0].duration") End Sub跑完看 A1、A2 是不是 296768 和 15060。这一步能验证解析结果能不能正常参与 Excel 后续计算,比如拿distance做汇总、拿duration算平均耗时。如果单元格里出现的是带引号的字符串而不是数字,说明取出来的是文本,需要CLng或CDbl转换一下再写入。
验证通过的标准很简单:立即窗口输出和预期字段值一致,单元格写入正确,嵌套解析能拿到内层字段。三样都过,解析逻辑就算跑通了。接下来换成真实接口返回的 JSON,路径按实际结构调整即可。
5. 本篇常见报错排查:401、local proxy failed、reading choices、OAuth
调试阶段报错集中在几类,逐个对照排查。
401 Unauthorized:请求头里 Key 没带对,或者 Key 已失效。检查Authorization头是不是Bearer YOUR_API_KEY格式,中间有空格,Bearer 首字母大写。Key 本身去控制台确认没过期、没被删。VBA 里字符串拼接容易多空格少空格,"Bearer " & apiKey这种写法比手写整串更稳。
local proxy failed:这类报错通常出现在请求根本没发出去,或者本地网络环境拦截了。先确认 Base URL 写的是https://taotoken.net/api,没有多余斜杠或路径。再确认 VBA 用的 HTTP 组件能正常访问外网,WinHttp比XMLHTTP在某些环境更稳。如果公司网络有出口限制,换一台能正常访问的机器验证,排除环境因素。
reading choices 相关报错:这类多半出在解析响应结构时路径写错。模型返回的 JSON 结构是choices[0].message.content,如果你按data.route.paths的路径去取,自然取不到。先用Debug.Print http.ResponseText把原始响应打出来,看清结构再写路径。不要凭记忆猜字段名,接口返回的字段名大小写、下划线都可能和文档不一致。
OAuth 相关报错:如果你用的是需要 OAuth 的接口,VBA 里手工处理 token 刷新比较麻烦。调试阶段建议先用 API Key 方式,避开 OAuth 流程。等解析逻辑稳定了,再考虑接入 OAuth。TaoToken 的 Key 方式对 VBA 更友好,少一层鉴权复杂度。
用户定义类型未定义:类模块命名没对上。检查New API.JSON里的API和JSON是否和工程里的命名空间、类模块名一致。最省事的做法是类模块直接命名JSON,代码里写New JSON。
解析返回空但没报错:路径写错或数组下标越界。用GetSingleValue("$")先取根,确认解析本身成功;再逐层加路径,每加一层Debug.Print一次,定位到哪一层开始变空。
双引号转义问题:JSON 字符串里本身带双引号,VBA 字符串拼接时要用Chr(34)或双写""。嵌套解析前先Replace成单引号,再Parse。
排查顺序建议:先看原始响应有没有拿到,再看解析有没有成功,最后看路径取值对不对。三步分开验证,比一上来就盯着最终结果猜要快得多。
6. 从解析到落地:把 JSON 数据接进 Excel 自动化的实用建议
解析跑通之后,真正落地到 Excel 自动化还有几个细节值得注意。第一是字段类型转换,GetSingleValue返回的是字符串,数字字段写进单元格前用CDbl或CLng转一下,否则后续求和、排序会按文本处理,结果不对。第二是数组遍历,paths这种数组可能有多个元素,用For i = 0 To n配合paths[i]逐条取,不要假设只有一条。
第三是错误处理,接口返回的 JSON 里errcode不为 0 时,data可能为空,直接取深层路径会返回空值。先判断errcode,再决定要不要解析data,能避免很多无意义的空值排查。第四是 Key 管理,调试用的 Key 和正式 Key 分开,代码里不要硬编码,放在隐藏工作表或配置文件里读取。
如果你需要长期跑批量任务,建议把解析逻辑封装成一个函数,输入 JSON 字符串和路径,输出字段值,主流程只负责循环调用。这样换接口、改路径时只动一处,维护成本低。配合 TaoToken 的统一通道,测试数据和正式数据用同一套解析代码,切换时只改 Base URL 和 Key,解析部分不用动。
最后提醒一点:JSON 解析的路径语法是核心技能,$、点号、[0]这三个符号的组合能覆盖绝大多数结构。遇到新接口,先用Debug.Print把原始 JSON 打出来,对着结构写路径,比查文档猜字段快。解析这关过了,Excel 自动化处理接口数据就只剩循环和写表的体力活了。