☰
Excel/WPS表格调用HTTP API:VBA网络函数库落地实践
2026/10/24 1:28:57 网站建设 项目流程

简介:面向需要在 Excel、WPS 中调用网络接口的办公自动化用户与 VBA 开发者,这套网络函数库配套工具聚焦表格软件与 HTTP 请求、数据回传、接口更新等场景,帮助把本地表格扩展为可与网络服务交互的数据处理入口。压缩包共 67 个文件、约 55.44MB,包含 31 个 dll 运行库、10 个 xml 配置/文档、7 个 js 浏览器扩展脚本,以及 xlsx 示例表、json 配置、html 页面和 exe 更新工具等,覆盖库文件、示例与辅助组件。已有 2574 人学习下载,说明其在 Excel/WPS 联网取数与函数库集成方面具有一定参考价值。包内还提供公式大全、快递查询、翻译工具等表格示例和安装卸载说明,便于读者了解函数调用方式、接口配置与常见排错思路,适合用来搭建表格联网取数、批量查询和自动化更新的实践环境。

1. 从一天粘两百行,到在单元格里敲一条函数

对账那天,某开发者把内部报价接口的返回结果复制进表格,一行一行粘,粘到第 87 行时发现接口字段改了顺序,前面全白干。数据在接口里,人在表格里,中间隔着一双手——这就是表格类工作最普遍的损耗。这份网络函数库要压掉的就是这段距离:它把 HTTP 请求、URL 编码、JSON 取值封装成一批单元格函数,装进 Excel 或 WPS 表格之后,敲一条=NET_GET(...)就能把远端数据落到格子里,不用导出、不用中转文件、不用每天重复粘贴。它适合天天和接口数据打交道、又不想写完整程序的人:做报表的、做运营核对的、给业务方维护小工具的。前提是你得接受一个问题——表格不是浏览器,它的计算模型和网络请求天然别扭,后面几章大半篇幅都在处理这个别扭。

2. 选型:为什么把网络函数库压在 VBA 加 ServerXMLHTTP 上

在表格里取网络数据,能走的路不止一条,但每条的能力边界差别很大。选型选错了,后面调参数、调刷新、调并发全是白费功夫,所以先把四条常见路径摊开对比,再说清楚这份库为什么这么分层。

2.1 四条落地路径的边界对比

路径额外依赖WPS 表格可用性刷新粒度主要限制
内置查询(Web.Contents 一类)无版本间差异明显,需现场验证整表刷新请求头、鉴权签名、POST 表单定制空间小
JS 加载项(Office.js 一类)需部署加载项清单走各自插件体系,不通用任务窗格内手动触发不能像普通函数那样在任意单元格里被引用
Python 外部进程(xlwings 一类)需装 Python 与解释器支持有限脚本驱动分发成本高,业务方机器上装不上去就废了
VBA + MSXML2.ServerXMLHTTP无(WPS 需装 VBA 组件)可用,需单独装宏组件单元格级或批量级都能控制同步阻塞、无原生 JSON、不能改别的单元格

对绝大多数“我只要在这一列出个数”的场景,最后一行是唯一同时满足“业务方机器零安装”和“能在任意单元格里当函数用”的。这也是这份库的立足点:它不是要替代数据仓库,而是把最后一百米的取数动作塞回表格里。

选 ServerXMLHTTP 而不是更常见的MSXML2.XMLHTTP,理由很实在:前者有setTimeouts,能把解析、连接、发送、接收四段超时分开设;后者只有一个整体超时,接口一慢就整表卡死,你还不知道卡在哪一段。WinHttp.WinHttpRequest.5.1也是备选,超时同样分段,但它默认不读系统的网络出口配置,企业内网环境里经常要额外调SetProxy,多一层心智负担。我的习惯是默认 ServerXMLHTTP,遇到 TLS 握手异常再切 WinHttp 做对照测试。

提示:这三者都是系统自带的 COM 组件,不需要随库分发 DLL。换个 HTTP 引擎只改传输层一个函数,上层函数签名不动——这是分层设计最直接的收益。

2.2 四层结构:传输、编码、解析、函数

这份库内部拆成四层,每层只干一件事,出问题时能快速定位是哪一层在捣乱。

传输层负责建立请求、设超时、发出去、拿回字节。它对外只暴露一个NET_Send(method, url, headers, body, timeoutMs),返回原始响应文本加状态码。这一层不关心返回的是 JSON 还是 CSV,也不做任何业务判断。

编码层处理 URL 编码、Base64、常见摘要。表格里拼 URL 最容易翻车的地方就是参数里带空格、中文、&、+,不编码直接拼,服务端收到的就是被截断的参数。这一层提供NET_UrlEncode、NET_B64Encode这类纯函数,可以单独在单元格里调用验证。

解析层把 JSON 文本变成可取路径的结构。VBA 没有原生 JSON,32 位环境常见的ScriptControl在 64 位 Office 上直接不可用——这是老代码迁移时最经典的一刀,必须自己写解析或引入纯 VBA 解析器。

函数层就是暴露给单元格的那批 UDF,负责把上面三层的返回值整理成表格能显示的东西:字符串、数字、数组,以及一个可读的错误串。

2.3 返回值约定:错误为什么不用抛异常

单元格函数抛出运行时错误,整列会变成#VALUE!,而#VALUE!不告诉你到底是超时、404 还是 JSON 路径写错了。所以这份库定了一条硬规矩:任何失败都不抛错,统一返回以ERR:开头的字符串,同时在模块级变量里留一份最近一次的错误详情,供NET_LastError()读取。

比如接口返回 401,单元格里显示ERR:HTTP401;JSON 里找不到路径,显示ERR:PATH;连接超时,显示ERR:TIMEOUT。好处是你对这一列做筛选,一眼就能看出失败集中在哪一类,而不是对着一片红色三角猜。坏处是它污染了数据类型——本来是数字的字段变成了字符串,后续求和会算错。我的处理办法是另配一个NET_IsErr()判断函数,在汇总列里先做一次过滤。这个取舍不优雅,但在表格这个环境里是最省排查成本的。

3. 装进去:Excel 与 WPS 两条落地路径

库拿到手是一组.bas模块文件。别急着全导,先按“能跑通一个请求”为目标走一遍最小路径,跑通了再全量导入。下面以 Excel 为主线,WPS 的差异单独放在 3.3。

3.1 Excel 端:模块导入、宏权限与加载项封装

第一步是让宏能跑。文件 → 选项 → 信任中心 → 宏设置,选“禁用所有宏,并发出通知”,不要选“启用所有宏”——后者在任何一台共享电脑上都是隐患。打开文件时顶部会出现黄色提示条,点“启用内容”。

第二步导入模块。按Alt + F11打开编辑器,右键工程 → 导入文件,选择库里的modHttp.bas、modJson.bas、modFunc.bas。导入后如果提示“子过程或函数未定义”,八成是少导了某个依赖模块,按报错名字补齐即可。

第三步验证引用。这份库只用晚期绑定(CreateObject),不需要在“工具 → 引用”里勾选任何东西。晚期绑定的代价是没有智能提示、拼错对象名要到运行时才报错,收益是换机器不用重新配引用——给业务方分发时这个收益远大于代价。

第四步封装成加载项。确认能跑之后,另存为.xlam(Excel 加载项格式),放到默认加载项目录,在“开发工具 → Excel 加载项”里勾上。之后任何工作簿打开都能直接调用这些函数,不用每次导模块。

注意:.xlam里的 UDF 一旦被单元格引用,函数名前会自动带上加载项名做前缀,比如函数库.xlam!NET_GET。分发前把加载项文件名固定下来,别中途改名,否则所有引用过它的表格全部失效。

3.2 第一个能跑的请求:先别碰 JSON

最小验证不要求解析,只看通不通。新建模块,贴下面这段:

' 最小可用版:同步 GET,返回响应正文或 ERR: 开头的错误串 Public Function NET_GET(ByVal url As String, _ Optional ByVal timeoutMs As Long = 8000) As String Dim http As Object On Error GoTo fail Set http = CreateObject("MSXML2.ServerXMLHTTP.6.0") ' 四段超时:解析、连接、发送、接收,单位毫秒 http.setTimeouts timeoutMs \ 4, timeoutMs \ 4, timeoutMs \ 2, timeoutMs http.Open "GET", url, False ' 第三个参数 False = 同步 http.setRequestHeader "Accept", "application/json" http.Send If http.Status >= 200 And http.Status < 300 Then NET_GET = http.responseText Else NET_GET = "ERR:HTTP" & http.Status End If Exit Function fail: NET_GET = "ERR:" & Err.Number & " " & Err.Description End Function

这段代码的关键不在语法,在三个参数。False是同步开关,UDF 里必须是同步,异步回调在表格环境里没有可靠的落地位置;setTimeouts的四段值我按 1:1:2:4 分配,连接段给得比接收段短,因为连不上再等也没用,而服务端算得慢是常态;Accept头对某些网关是必需的,不带会被直接拒。

贴完按Ctrl + G打开立即窗口,敲?NET_GET("https://example.test/api/ping")回车。立即窗口能跑通,再回单元格里写=NET_GET("https://example.test/api/ping")。两步分开做,是为了区分“代码问题”和“表格计算问题”——这两类故障的排查路径完全不同。

3.3 WPS 表格:VBA 组件与宏安全两道门

WPS 表格的差异集中在一件事上:VBA 支持默认没装。打开文件如果宏按钮是灰的,或者按Alt + F11没反应,说明缺 VBA 组件,需要在设置里的“开发工具”相关入口安装一次。装完之后,MSXML2.ServerXMLHTTP.6.0这类系统 COM 对象通常可用,但个别精简环境下会缺组件,CreateObject直接报“ActiveX 部件不能创建对象”。

遇到这个报错,先在立即窗口敲?CreateObject("MSXML2.ServerXMLHTTP.6.0").Status试一下;如果这里就挂了,说明不是代码问题,是环境问题,换WinHttp.WinHttpRequest.5.1试试能不能创建,两个都不行就只能换机器或换方案。

第二道门是宏安全策略,新版环境对宏的拦截更紧,需要把文件所在目录加进受信任位置,否则每次打开都要手工放行,业务方会烦。

新版 WPS 还提供 JS 宏入口,思路和 VBA 一致——发请求、取返回、写单元格,只是语法换成 JavaScript。它适合交付给不接受宏的老环境,但接口在不同版本间有差异,落地方案我一般仍以 VBA 为主,JS 宏作为备选。写的时候注意:写单元格那一句必须放在请求成功之后,且要判断目标格子是否已被合并或锁定,否则会中断整个宏。

// JS 宏示意:发一次请求并把结果写到当前单元格 async function main() { const r = await fetch("https://example.test/api/ping", { method: "GET", headers: { "Accept": "application/json" } }); const t = await r.text(); // 具体写入 API 随版本变化,先取当前选区再赋值更稳妥 Selection.Value2 = t; } // 注意:不同版本 API 名称不一致,落地前以本机宏编辑器里的对象浏览器为准

4. 参数调优:超时、重试、JSON 取值与缓存

能跑通只是起点。真正决定这套库好不好用的,是四个参数:超时怎么分、重试怎么退、JSON 路径怎么写、缓存什么时候失效。这四件事任何一个没处理,用户都会觉得“这函数时灵时不灵”,然后放弃。

4.1 传输层:分段超时与退避重试

先说重试。网络抖动导致单次失败是常态,但如果无脑重试三次,一个已经挂掉的接口会让每个单元格多等三倍时间,整表计算从 30 秒变成 90 秒。所以重试要带条件:只对连接失败、超时、5xx 重试,4xx 一律不重试(参数错了重试一万次也没用),且每次间隔递增。

' 带条件重试的发送核心 Public Function NET_SendRaw(ByVal method As String, ByVal url As String, _ ByVal body As String, ByVal timeoutMs As Long, _ Optional ByVal retries As Long = 2) As Object Dim http As Object, attempt As Long, wait As Long For attempt = 0 To retries On Error Resume Next Set http = CreateObject("MSXML2.ServerXMLHTTP.6.0") If Err.Number <> 0 Then Set NET_SendRaw = Nothing Exit Function End If On Error GoTo 0 http.setTimeouts timeoutMs \ 4, timeoutMs \ 4, timeoutMs \ 2, timeoutMs http.Open method, url, False http.setRequestHeader "Content-Type", "application/json;charset=utf-8" If Len(body) > 0 Then http.Send body Else http.Send If http.Status >= 200 And http.Status < 300 Then Set NET_SendRaw = http Exit Function ElseIf http.Status >= 400 And http.Status < 500 Then Exit For ' 4xx 不重试,直接退出循环 End If wait = 300 * (attempt + 1) ' 300ms、600ms 递增 SleepMs wait Next attempt Set NET_SendRaw = Nothing End Function ' 64 位与 32 位都需 PtrSafe,缺了会在 64 位环境直接编译失败 Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMs As Long) Public Sub SleepMs(ByVal ms As Long) Sleep ms End Sub

三个参数值得单独说。retries = 2意味着最多发三次,配合递增等待,最坏情况多花 900 毫秒,可接受;如果接口本身要跑 5 秒以上,这个值应该降到 0,把等待留给主请求。timeoutMs \ 4的分割策略在小文件上没问题,但表单类接口首包慢,接收段要给足。SleepMs这是我自己包的一层,原因是Declare语句必须放在模块顶部,不能让业务代码到处写Declare,而且 64 位环境漏掉PtrSafe会在编译期就挂,报错信息还很难懂。

注意:Sleep会冻结当前线程,在 UDF 里调用就是冻结 Excel 界面。单次调用几十毫秒看不出来,但如果一列有 200 个单元格、每个都重试两次,累计阻塞能达到十几秒,用户会以为程序崩了。所以重试次数在“单元格函数”场景下要保守,批量场景再放宽。

4.2 JSON 解析:不依赖 ScriptControl 的写法

JSON 解析是 64 位环境绕不过去的坎。老的ScriptControl方案在 64 位 Office 上无法创建,必须自己写。下面是一个精简的递归下降解析器,只依赖Scripting.Dictionary和Collection,两者在 Excel 和 WPS 里都能创建。

' 入口:把 JSON 文本解析成 Dictionary/Collection/基本类型 Public Function NET_JsonParse(ByVal s As String) As Variant Dim i As Long: i = 1 NET_JsonParse = JP_Val(s, i) End Function Private Function JP_Val(ByRef s As String, ByRef i As Long) As Variant Dim c As String: JP_Skip s, i c = Mid$(s, i, 1) Select Case c Case "{": Set JP_Val = JP_Obj(s, i) Case "[": Set JP_Val = JP_Arr(s, i) Case """": JP_Val = JP_Str(s, i) Case "t": i = i + 4: JP_Val = True Case "f": i = i + 5: JP_Val = False Case "n": i = i + 4: JP_Val = Null Case Else: JP_Val = JP_Num(s, i) End Select End Function Private Sub JP_Skip(ByRef s As String, ByRef i As Long) Do While i <= Len(s) Select Case Mid$(s, i, 1) Case " ", vbTab, vbCr, vbLf: i = i + 1 Case Else: Exit Do End Select Loop End Sub Private Function JP_Obj(ByRef s As String, ByRef i As Long) As Object Dim d As Object, k As String, v As Variant Set d = CreateObject("Scripting.Dictionary") i = i + 1 Do JP_Skip s, i If Mid$(s, i, 1) = "}" Then i = i + 1: Exit Do If Mid$(s, i, 1) = "," Then i = i + 1 JP_Skip s, i If Mid$(s, i, 1) <> """" Then Exit Do ' 容错:结构坏了就收手 k = JP_Str(s, i) JP_Skip s, i If Mid$(s, i, 1) = ":" Then i = i + 1 v = JP_Val(s, i) If IsObject(v) Then Set d(k) = v Else d(k) = v Loop Set JP_Obj = d End Function Private Function JP_Arr(ByRef s As String, ByRef i As Long) As Collection Dim c As Collection, v As Variant Set c = New Collection i = i + 1 Do JP_Skip s, i If Mid$(s, i, 1) = "]" Then i = i + 1: Exit Do If Mid$(s, i, 1) = "," Then i = i + 1 v = JP_Val(s, i) If IsObject(v) Then c.Add v Else c.Add v Loop Set JP_Arr = c End Function

上面只给了主体骨架,字符串转义(\"、\n、\uXXXX)和数字边界判断按同样方式补两个小函数即可。这里要说明设计取舍:解析器对坏数据是“容错退出”而不是抛错,遇到结构不合法的位置直接结束循环,返回已解析的部分。表格场景里这比严格报错更有用——接口偶尔多返回一个字段,不该让整列数据全部作废。

取值的封装在函数层,用斜杠分隔的路径:

' 路径写法:/data/list/0/price 数字段表示数组下标 Public Function NET_JsonGet(ByVal json As Variant, ByVal path As String) As Variant Dim parts() As String, p As Variant, node As Variant, idx As Long node = json If Len(path) = 0 Or path = "/" Then NET_JsonGet = node: Exit Function parts = Split(Mid$(path, 2), "/") For Each p In parts If IsObject(node) Then If TypeName(node) = "Dictionary" Then If Not node.Exists(CStr(p)) Then NET_JsonGet = "ERR:PATH": Exit Function node = node(CStr(p)) Else idx = CLng(p) + 1 ' JSON 数组 0 起,Collection 1 起 If idx < 1 Or idx > node.Count Then NET_JsonGet = "ERR:PATH": Exit Function node = node(idx) End If Else NET_JsonGet = "ERR:PATH": Exit Function End If Next p If IsObject(node) Then NET_JsonGet = "ERR:OBJECT" ' 别把整个对象往单元格里怼 Else NET_JsonGet = node End If End Function

下标转换是这里最容易错的地方:JSON 数组从 0 开始,VBA 的Collection从 1 开始,中间不加 1 就会整体错位一格,而且错得很安静——返回的是相邻那条数据,看起来完全正常。这个坑我在真实项目里踩过一次,两条记录的金额差了一位,对账差了两千多块才发现。

4.3 缓存与刷新:Volatile 是毒药

Application.Volatile True看起来是解决“数据不更新”的银弹,实际是灾难。它让函数在每次重算时都重新执行,而 Excel 的重算触发极其频繁:改一个无关单元格、切个 sheet、按一下 F9,全都会触发。一列 100 个网络函数配上 Volatile,随便动一下就是 100 个请求打出去,接口方很快就会来找你。

正确做法是有意地缓存。用模块级Dictionary,以“方法 + URL + 请求体”拼成的键做索引,命中就直接返回,未命中才发请求。再加一个显式的刷新入口,让用户自己决定什么时候清缓存。

Private mCache As Object ' 带缓存的 GET 包装 Public Function NET_GetCached(ByVal url As String, _ Optional ByVal ttlSec As Long = 300) As String Dim key As String, nowSec As Long, rec As Variant If mCache Is Nothing Then Set mCache = CreateObject("Scripting.Dictionary") key = "GET|" & url nowSec = Int(Timer) ' 进程内计时,够用且不依赖系统时间格式 If mCache.Exists(key) Then rec = mCache(key) If nowSec - rec(1) < ttlSec Then NET_GetCached = rec(0) Exit Function End If End If NET_GetCached = NET_GET(url) mCache(key) = Array(NET_GetCached, nowSec) End Function ' 用户手动刷新:清空缓存后强制重算 Public Sub NET_ClearCache() If Not mCache Is Nothing Then mCache.RemoveAll Application.CalculateFull End Sub

ttlSec默认 300 秒是个经验值:比人工操作节奏长,比数据变化节奏短。缓存存在模块级变量里,工作簿一关就没了,不会留下陈旧数据。Timer返回的是当天秒数,跨零点会回绕,但 300 秒的 TTL 下这个边界基本碰不到,真要严谨可以用GetTickCount。

提示:NET_ClearCache里调了CalculateFull,会把整个工作簿重算一遍,包括其他无关的函数。工作簿大的时候这一下能卡好几秒,所以这个入口放在按钮上让用户主动点,别挂在Workbook_Open里。

5. 避坑与排查:六条踩过的坑

这套东西的失败模式很有规律,基本集中在两类:请求发不出去、结果落不进格子。下面六条按“现象 → 原因 → 解决”记,都是实际撞过的。

5.1 请求层:发不出去与收不对

坑一:HRESULT 0x80072EFD,连接被拒。

现象是函数稳定返回ERR:-2147012867,换个 URL 有时候又能通。原因通常不是网络断了,而是目标地址在服务端做了白名单,或者本机出口需要走企业内网的网络出口设置,而ServerXMLHTTP默认读系统配置、WinHttp默认不读,两者行为不一致。

解决分两步:先用WinHttp的SetProxy显式指定出口再试一次;如果换了引擎能通,说明确实是出口配置差异,把引擎选择做成函数参数而不是硬编码。如果两个引擎都连不上,用ping和telnet 端口确认链路,别再在 VBA 里绕。

坑二:接口返回 200,但内容是一堆问号或方块。

现象是中文全变乱码,英文正常。原因是响应头里没声明 charset,responseText按默认代码页解码,UTF-8 的中文就废了。

解决办法是改取responseBody(字节数组),自己按 UTF-8 转成字符串,绕开responseText的自动解码。另外请求侧也要显式带上charset=utf-8,两边都声明清楚,别指望对面猜。这个坑在对接自建接口时特别常见,因为自建接口经常懒得写Content-Type。

坑三:偶发超时,重试就过,但用户觉得函数“不靠谱”。

现象是同一批数据,第一次刷有几个格是ERR:TIMEOUT,再刷就好了。原因多半是首包慢——TLS 握手 + 服务端冷启动,第一个请求要两三秒,后面就快了,而超时设的是固定值。

解决是按“首个请求给长超时、后续给短超时”来分配,而不是全表一个值。实现上在传输层加个模块级标记,第一次调用用timeoutMs * 2,之后恢复默认。这个改动很小,但对用户观感的提升非常明显。

5.2 表格层:落不进格子与算不明白

坑四:整列变成#VALUE!,但立即窗口里同样的调用是好的。

现象很典型:函数单独跑没问题,一放进单元格就全红。原因是函数内部动了不该动的东西——读了别的单元格、改了工作表、弹了MsgBox。UDF 在计算期间对工作簿的写操作是被禁止的,一旦越界就整列报错。

解决是把所有“写”的动作从Function里彻底剥离,只保留“取值”。需要写回的场景改用Sub加按钮触发,第 6 章给的就是这种写法。这条边界没有例外,别想着绕。

坑五:一打开文件就发出几百个请求,接口方来投诉。

现象是文件刚打开,网络就炸了。原因是函数被设成了易失性,或者单元格里引用了NOW()、TODAY()这类每次重算都变的参数,导致整表反复重算。

解决是去掉Volatile,改用 4.3 的缓存方案,并且把会变的参数从函数入参里挪出去。如果确实需要“打开时刷新一次”,用一个Workbook_Open里调一次的Sub主动拉数据写值,别让单元格函数自己扛这个职责。

坑六:Excel 里正常,WPS 里报“子过程或函数未定义”。

现象是同一个文件两边表现不一致。原因通常是 WPS 侧的 VBA 组件没装全,或者用到了 WPS 未实现的少数对象方法;也有可能是 64 位与 32 位环境的Declare语句缺PtrSafe,在一边能编译、另一边直接挂。

解决顺序:先在 WPS 的宏编辑器里打开对应模块,看有没有编译期红字提示,编译错误比运行错误好定位得多;再检查所有Declare是否带PtrSafe;最后确认CreateObject的那几个 COM 组件在 WPS 环境里能创建。三步走完还不通,就老老实实降级到 VBA 的兼容子集,别用新语法糖。

6. 批量拉取与结果校验:一个按钮替代一百个单元格

单元格函数适合“零星取几个值”,不适合“一次拉两百行”。两百个单元格意味着两百次同步请求,即使有缓存也顶不住,而且用户全程看着界面卡死。真正干活的写法是Sub:读一列参数、循环发请求、把结果写回一列,中间加节流和失败收集。

' 批量拉取:A 列放参数,B 列写结果,C 列记错误 Public Sub NET_BatchFetch(ByVal urlTemplate As String, _ ByVal keyPath As String, _ ByVal valPath As String, _ Optional ByVal gapMs As Long = 120) Dim ws As Worksheet, lastRow As Long, r As Long Dim fullUrl As String, resp As String, jo As Variant, v As Variant Dim okCount As Long, errCount As Long Set ws = ActiveSheet lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row If lastRow < 2 Then Exit Sub Application.ScreenUpdating = False ' 循环里关掉重绘,速度快一个量级 For r = 2 To lastRow If Len(Trim$(ws.Cells(r, 1).Value)) = 0 Then GoTo nextRow fullUrl = Replace(urlTemplate, "{key}", NET_UrlEncode(CStr(ws.Cells(r, 1).Value))) resp = NET_GET(fullUrl, 10000) If Left$(resp, 4) = "ERR:" Then ws.Cells(r, 3).Value = resp errCount = errCount + 1 Else jo = NET_JsonParse(resp) v = NET_JsonGet(jo, valPath) If VarType(v) = vbString Then If Left$(CStr(v), 4) = "ERR:" Then ws.Cells(r, 3).Value = v errCount = errCount + 1 Else ws.Cells(r, 2).Value = v okCount = okCount + 1 End If Else ws.Cells(r, 2).Value = v okCount = okCount + 1 End If End If SleepMs gapMs ' 节流,别把接口打穿 nextRow: Next r Application.ScreenUpdating = True MsgBox "成功 " & okCount & " 条,失败 " & errCount & " 条", vbInformation End Sub

这段的关键是三个设计。urlTemplate用{key}占位而不是让用户自己拼,拼 URL 是错误率最高的环节,编码必须内置;gapMs默认 120 毫秒,两百条大约多花 24 秒,换来的是接口方不会限流,这个交换很值;ScreenUpdating关掉后,循环期间界面不重绘,实测能快出三到五成,不关的话每一行写入都会触发一次重绘。

写完一定要做结果校验,不能只看“跑完了”。我一般加两步:一是对 B 列做非空计数,和 A 列的非空计数比对,差值超过 5% 就说明有问题;二是随机抽三五条,拿原始返回文本人工核一遍字段路径。路径写错是最隐蔽的故障——函数不报错,返回的是相邻字段,看起来一切正常。

从那以后我每次交付这类工具,都会强制走一遍“小样本全流程”:先拿 10 行数据跑通,人工核对字段,再放开到全量。这个习惯救过我不止一次,因为字段错位在两百行里根本看不出来。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询