夜雨聆风学习资料网

ARTICLE · 1126245

VBA 发送企业微信群机器人消息:让 Excel 数据自己飞进群里

VBA 发送企业微信群机器人消息:让 Excel 数据自己飞进群里

VBA 发送企业微信群机器人消息:让 Excel 数据自己飞进群里

报表做完还得手动截图发群——这是很多人的日常。其实企业微信群自带一个「机器人」,给它一个网址,任何程序都能往里发消息。这一篇我们就用 VBA 打通这条线:Excel 里的数据,算完自动飞进群里,还能 @ 到具体的人、带颜色标识重点,全程不需要服务器、不需要企业认证、不花一分钱。

一、学习目标

  • 掌握企业微信群机器人的 Webhook 机制:一个网址 = 一个发消息的通道。
  • 掌握 VBA 用 WinHttp 发 POST 请求,并解决中文 UTF-8 编码这个必踩的坑。
  • 做出日报自动推送:读表 → 拼消息 → 发送 → 判断成功失败 → 每天定时自动跑。

二、知识点精讲

1. 三分钟拿到你的 Webhook 地址

企业微信群里点右上角 → 群机器人 → 添加机器人 → 起个名字(比如「数据小助手」)→ 复制它给出的 Webhook 地址:

https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa

后面那一长串 key 就是你的钥匙。拿到这个地址,任何能发 HTTP 请求的程序都能往这个群发消息——这就是机器人最简单的原理。

⚠️ 安全提醒(官方明确强调):这个地址等于群里的"发言权",谁拿到都能发垃圾消息。不要分享到 GitHub、博客等公开地方。 本篇代码里我们把它放在标准模块顶部的常量里,或者读单元格,别硬编码到要分享的文件里。

2. 消息类型与硬性限制

企业微信群机器人支持七八种消息类型,最常用的三种:

类型
用途
长度上限
支持 @人
支持颜色
text
 文本
纯文字通知
2048 字节
✅ 支持
❌
markdown
富文本(标题、加粗、引用、颜色)
4096 字节
✅ 支持
✅ 3 种
markdown_v2
标准 Markdown(支持表格)
4096 字节
❌
❌

还有 image(图片,base64 编码前不超过 2MB)、news(图文,1~8 条)、file(文件,需先上传拿 media_id)等。

三个必须记住的数字:

  • 文本消息 2048 字节、markdown 4096 字节——注意是字节不是字符,一个中文占 3 字节,所以文本消息实际大概只能放 680 个汉字;
  • 每个机器人每分钟最多发 20 条,超了返回错误码 45009 被限流;
  • 消息是单向的:机器人只能发,不能收,也删不掉已发出的消息。

3. markdown 支持哪些语法(这是最容易踩的坑)

企业微信的 markdown 只支持一个语法子集,比通用的 Markdown 少很多:

# 标题(1~6 级,# 与文字之间要有空格)**加粗**[链接文字](https://example.com)`行内代码`> 引用文字<font color="info">绿色</font><font color="comment">灰色</font><font color="warning">橙红色</font>

重点:markdown 类型不支持表格、不支持图片、不支持列表的自动编号。 想要表格必须用 markdown_v2——但 markdown_v2 又不支持颜色和 @人。

结论:想发数据表格就用 markdown_v2,想发带颜色的告警就用 markdown,两者不能兼得。日常工作里绝大多数通知场景,用带颜色的 markdown 效果更好。

4. VBA 的第一个坑:UTF-8 编码

这是本篇最关键的技术点。VBA 里的字符串是 Unicode,而企业微信接口只接受 UTF-8 编码的字节流。直接 Send 字符串,中文必然乱码或直接报错。

标准解法是用 ADODB.Stream 做一次编码转换。但这里还藏着一个更隐蔽的坑:

ADODB.Stream 以 UTF-8 写入时会自动加上 3 个字节的 BOM 头(EF BB BF)。 这 3 个字节会让企业微信的 JSON 解析器一头雾水,返回"无效的 JSON"或 93000 错误——代码看起来完全没问题,就是不成功。

唯一的解法:读字节时跳过前 3 个字节。

st.Position = 3     ' 跳过 UTF-8 BOM,这一行是整个教程的命门

三、实战案例

案例 1(简单):发出第一条消息

先把三个基础零件备好:UTF-8 转字节、JSON 转义、发送函数。这三个函数后面所有案例都会反复用。

完整代码(标准模块 m企业微信):

Option Explicit' ⚠️ 把这里换成你自己的机器人 KEY(只填 key= 后面那一串)Public Const 机器人KEY As String = "693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa"' ========== 零件一:字符串转 UTF-8 字节数组 ==========Private Function UTF8字节(文本 As String) As Byte()    Dim st As Object    Set st = CreateObject("ADODB.Stream")    st.Type = 2                     ' adTypeText    st.Charset = "utf-8"    st.Open    st.WriteText 文本    st.Position = 0    st.Type = 1                     ' adTypeBinary    st.Position = 3                 ' 跳过 UTF-8 BOM(EF BB BF),否则接口报错    UTF8字节 = st.Read    st.Close    Set st = NothingEnd Function' ========== 零件二:JSON 字符串转义 ==========Public Function JSON转义(s As String) As String    Dim r As String    r = Replace(s, "\", "\\")       ' 反斜杠必须第一个替换    r = Replace(r, """", "\""")    r = Replace(r, vbCrLf, "\n")    r = Replace(r, vbCr, "\n")    r = Replace(r, vbLf, "\n")    r = Replace(r, vbTab, "\t")    JSON转义 = rEnd Function' ========== 零件三:真正发送 ==========Public Function 发送企业微信(消息JSON As String) As String    Dim http As Object    Dim 地址 As String    地址 = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" & 机器人KEY    Set http = CreateObject("WinHttp.WinHttpRequest.5.1")    http.Open "POST", 地址, False    http.setRequestHeader "Content-Type", "application/json; charset=utf-8"    http.SetTimeouts 5000, 5000, 10000, 10000   ' 连接/发送/接收超时(毫秒)    http.Send UTF8字节(消息JSON)    发送企业微信 = 字节转文本(http.ResponseBody)    Set http = NothingEnd Function' ========== 辅助:响应字节转文本(避免返回中文乱码)==========Private Function 字节转文本(数据 As Variant) As String    Dim st As Object    Set st = CreateObject("ADODB.Stream")    st.Type = 1    st.Open    st.Write 数据    st.Position = 0    st.Type = 2    st.Charset = "utf-8"    字节转文本 = st.ReadText    st.Close    Set st = NothingEnd Function' ========== 案例 1:发送纯文本 ==========Sub 发送文本消息()    Dim 内容 As String, 返回 As String    内容 = "【VBA 测试】Excel 数据小助手已上线,时间为 " & Format(Now, "yyyy-mm-dd hh:nn:ss")    返回 = 发送企业微信("{""msgtype"":""text"",""text"":{""content"":""" & _                        JSON转义(内容) & """}}")    If InStr(返回, """errcode"":0") > 0 Then        MsgBox "发送成功!去群里看看。", vbInformation    Else        MsgBox "发送失败:" & 返回, vbCritical    End IfEnd Sub

操作步骤:

  1. 在企业微信群里加好机器人,复制 Webhook 地址,把 key= 后面那串填到 机器人KEY 常量里。
  2. Alt + F11 打开 VBE,插入标准模块,把模块名改成 m企业微信,粘贴上面全部代码。
  3. Alt + F8 运行 发送文本消息。
  4. 群里立刻收到消息,Excel 弹窗提示「发送成功」。

三个新手必踩的坑:① 直接 Send 字符串 → 中文乱码,必须走 UTF8字节;② 忘了 st.Position = 3 → 接口报错,因为 BOM 头混进了 JSON;③ JSON 里的双引号在 VBA 里要写成两个"",这是 VBA 的转义规则。

案例 2(中等):发一条带颜色的漂亮通知

纯文本太单调。换用 markdown 类型,加上标题、引用和三种颜色,一眼看出重点;再配上 @ 人,让该看的人立刻收到。

完整代码(追加到同一模块):

' ========== 组装 markdown 消息体 ==========Public Function 拼Markdown(内容 As String) As String    拼Markdown = "{""msgtype"":""markdown"",""markdown"":{""content"":""" & _                 JSON转义(内容) & """}}"End Function' ========== 案例 2-1:带颜色的 markdown 通知 ==========Sub 发送彩色通知()    Dim 内容 As String, 返回 As String    ' 注意:内容里的换行用 vbLf,经 JSON转义 后会变成 \n    内容 = "## 今日数据汇总" & vbLf & _           "> 销售额:<font color=""warning"">128,600 元</font>" & vbLf & _           "> 订单数:<font color=""info"">356 单</font>" & vbLf & _           "> 库存预警:<font color=""comment"">3 项待处理</font>" & vbLf & _           "> 环比昨日:<font color=""info"">+12.4%</font>" & vbLf & vbLf & _           "详情请查看共享盘 `\\server\报表\日报.xlsx`"    返回 = 发送企业微信(拼Markdown(内容))    Debug.Print 返回        ' 在「立即窗口」看接口返回    MsgBox "已发送,返回:" & 返回, vbInformationEnd Sub' ========== 案例 2-2:文本消息 + @指定人(按手机号)==========Sub 发送并艾特人()    Dim 内容 As String, 返回 As String    内容 = "【紧急】库存低于安全线,请立即安排补货。"    ' mentioned_mobile_list 填对方手机号,@all 表示全员    返回 = 发送企业微信("{""msgtype"":""text"",""text"":{""content"":""" & _                        JSON转义(内容) & """,""mentioned_mobile_list"":[""13800001111"",""@all""]}}")    MsgBox "返回:" & 返回, vbInformationEnd Sub

操作步骤:

  1. 把代码追加到 m企业微信 模块(拼Markdown 是 Public,案例 3 还要用)。
  2. 运行 发送彩色通知 → 群里收到一条带标题、四行引用、橙红/绿/灰三色的通知卡片。
  3. 把 发送并艾特人 里的手机号改成同事的(或留 @all),运行后群成员会收到提醒。

关于颜色的用法:warning(橙红)标异常和金额、info(绿)标正常和增长、comment(灰)标次要说明。一条消息里颜色别超过三种,否则重点就没了。另外注意:markdown 类型不支持表格,想发数据表格得改用 markdown_v2,但它不支持颜色和 @人。

案例 3(实用):Excel 日报自动推送(含错误处理与定时)

最实用的场景来了:表格里放好当天数据,VBA 自动读出来、拼成消息发进群,并且能判断成功失败、能定时自动跑。

第一步:准备数据区

在 日报数据 工作表里按这样放(B 列放值):

A
B
日期
2026-10-05
销售额
128600
订单数
356
库存预警
3 项
环比
+12.4%

第二步:完整代码

' ========== 估算 UTF-8 字节数(用于长度保护)==========Public Function 字节长度(s As String) As Long    On Error GoTo 空文本    字节长度 = UBound(UTF8字节(s)) + 1    Exit Function空文本:    字节长度 = 0End Function' ========== 案例 3:推送销售日报 ==========Sub 推送销售日报()    Dim ws As Worksheet    Dim 日期 As String, 销售额 As Double, 订单数 As Long, 预警 As String, 环比 As String    Dim 内容 As String, 返回 As String    ' 1) 读数据(表不存在就直接挡掉,不让代码崩)    On Error Resume Next    Set ws = ThisWorkbook.Worksheets("日报数据")    On Error GoTo 0    If ws Is Nothing Then        MsgBox "找不到「日报数据」工作表。", vbExclamation        Exit Sub    End If    日期 = ws.Range("B1").Text    销售额 = Val(ws.Range("B2").Value)    订单数 = CLng(Val(ws.Range("B3").Value))    预警 = ws.Range("B4").Text    环比 = ws.Range("B5").Text    ' 2) 拼 markdown    内容 = "## " & 日期 & " 销售日报" & vbLf & _           "> 销售额:<font color=""warning"">" & Format(销售额, "#,##0") & " 元</font>" & vbLf & _           "> 订单数:<font color=""info"">" & 订单数 & " 单</font>" & vbLf & _           "> 库存预警:<font color=""comment"">" & 预警 & "</font>" & vbLf & _           "> 环比昨日:<font color=""info"">" & 环比 & "</font>" & vbLf & vbLf & _           "报送人:数据小助手"    ' 3) 长度保护:markdown 上限 4096 字节    If 字节长度(内容) > 4096 Then        MsgBox "消息内容 " & 字节长度(内容) & " 字节,超过 4096 上限,请精简后再发。", vbExclamation        Exit Sub    End If    ' 4) 发送并判断结果    返回 = 发送企业微信(拼Markdown(内容))    If InStr(返回, """errcode"":0") > 0 Then        MsgBox "日报推送成功!", vbInformation    ElseIf InStr(返回, "45009") > 0 Then        MsgBox "发送太频繁了(每分钟最多 20 条),请等一分钟再试。", vbExclamation    ElseIf InStr(返回, "93000") > 0 Then        MsgBox "Webhook 地址无效,请检查机器人 KEY 是否复制完整。", vbCritical    Else        MsgBox "推送失败,接口返回:" & vbCrLf & 返回, vbCritical    End IfEnd Sub' ========== 定时:每天 9:00 自动推送 ==========Sub 安排每日推送()    Dim 目标时间 As Date    目标时间 = Date + TimeValue("09:00:00")    If 目标时间 <= Now Then 目标时间 = 目标时间 + 1     ' 今天已过 9:00,排到明天    Application.OnTime 目标时间, "推送销售日报"    MsgBox "已排定下一次推送:" & Format(目标时间, "yyyy-mm-dd hh:nn"), vbInformationEnd Sub

第三步:让定时任务开机自动排上(ThisWorkbook 代码模块)

Private Sub Workbook_Open()    ' 打开文件时把今天的推送排上,过程末尾会重排明天    Call 安排每日推送End Sub

操作步骤:

  1. 建好「日报数据」表,按上面的表格填数据。
  2. 把案例 3 的代码追加到 m企业微信,安排每日推送 粘进标准模块。
  3. 双击 VBE 左侧 ThisWorkbook,粘贴 Workbook_Open。
  4. 先手动跑一次 推送销售日报 → 群里收到日报,Excel 弹「日报推送成功!」。
  5. 保存为 .xlsm 并保持文件打开(OnTime 需要工作簿处于打开状态),到点自动推送。

三个工程细节:① 先判断表是否存在再读值,避免文件换版本就报错;② Val() 读数字能兼容单元格里混了文本的情况;③ 发完一条要重排下一天的定时(把 Call 安排每日推送 加在 推送销售日报 末尾即可),否则只有今天发一条——OnTime 只响一次,不循环。

四、本篇小结

  • 原理极简:一个 Webhook 网址就是一个发消息通道,VBA 用 WinHttp 发个 POST 就完事。
  • 编码是关键:必须转 UTF-8 字节,且跳过 ADODB.Stream 自动加的 3 字节 BOM,否则必失败。
  • 类型要选对:要颜色和 @人用 markdown(不支持表格),要发数据表格用 markdown_v2(不支持颜色和 @人)。
  • 限制记心间:文本 2048 字节、markdown 4096 字节、每分钟最多 20 条,错误码 0 成功 / 93000 地址无效 / 45009 太频繁。
  • 安全第一:Webhook 地址等同群里的发言权,绝不公开。

把这篇和前面的定时任务、报表生成串起来,你就能做出「算完自动发、出问题自动报警」的完整闭环——早上到公司,报表已经在群里了。

五、进阶方向

  • 发图片:把图表截图转 base64(配 md5)用 image 类型发送,适合发趋势图;
  • 发文件:先调 upload_media 上传拿到 media_id,再用 file 类型把 Excel 报表本体发进群;
  • 多群分发:把多个群的 Webhook 存进一张配置表,循环发送,一次通知所有相关群;
  • 配合告警场景:库存低于安全线、销售额异常波动时自动触发,用 warning 颜色 + @负责人,让问题不过夜。

相关学习资料