ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

VBA 模拟键盘鼠标操作与窗口激活:TaoToken 统一 Key 配置实战

VBA 模拟键盘鼠标操作与窗口激活:TaoToken 统一 Key 配置实战 1. 从一次真实的 VBA 自动化需求说起VBA 模拟键盘鼠标操作与窗口激活本质上是让 Excel 宏或 Word 宏具备「操作其他程序」的能力。你可能会遇到这样的场景每天要从某个内部系统导出报表系统只提供桌面客户端没有 API或者需要批量把数据填进一个老旧的录入工具那个工具连导入功能都没有。这时候 Shell 启动外部程序、AppActivate 激活目标窗口、再用 SendKeys 和 mouse_event 模拟键盘鼠标就是最直接的解法。这套方案适合谁适合已经会用 VBA 写基础宏、但卡在「怎么让宏去点别的窗口」这一步的办公自动化开发者。它不需要你懂 C 或驱动开发只要理解 Windows 窗口句柄、焦点、消息队列这几个概念就能跑通。我试过在财务对账、批量打印、数据搬运这几类任务里用这套组合实测下来最关键的难点不在代码本身而在窗口激活的时机控制和权限环境。这篇文章会先讲清楚 Shell 和 AppActivate 的配合逻辑然后给出 TaoToken 统一 Key/API 通道的 config.toml 骨架与 settings.json 配置片段让需要调用大模型做文本处理或决策的环节也能纳入同一条通道。接着演示一次可复制的窗口激活加按键发送验证动作最后把常见的报错和排查路径列出来。你跟着做能在本地快速跑通整个流程。2. TaoToken 前置统一 Key 与 API 通道准备在 VBA 里做窗口自动化很多时候不只是「按键」还需要在按键前后调用模型做内容生成、格式判断或异常识别。比如把一段文本发给模型做摘要再把摘要粘贴进目标窗口。这时候如果每个模型都单独配 Key、单独改 endpoint维护成本会很高。TaoToken 的思路是提供一个统一的 API 通道你用同一个 Key 就能切换不同模型配置集中在一个文件里。先到官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 了解通道能力然后进控制台创建 API Key。API 基地址是 https://taotoken.net/api 注意这个地址不加 UTM 参数直接用于程序请求。Key 创建入口在 https://taotoken.net/api-keys 建议按项目建不同 Key方便后续排查是哪个脚本在调用。拿到 Key 之后本地配置分两块一块是给命令行工具或 SDK 用的 config.toml一块是给编辑器或插件用的 settings.json。下面给出骨架你按自己的模型名和参数替换即可。2.1 config.toml 骨架# TaoToken 统一通道配置骨架 # 适用于命令行工具、SDK、脚本调用 [default] api_base https://taotoken.net/api api_key sk-你的Key timeout 60 [models] # 对话与文本处理 chat_model claude-sonnet # 代码补全与长上下文 code_model claude-code # 轻量判断任务 fast_model gpt-4o-mini [retry] max_attempts 3 backoff_seconds 2这个骨架里 api_base 固定指向 TaoToken 的 API 地址api_key 换成你在控制台生成的那串。models 段按用途分了三类实际调用时用哪类就填哪类。retry 段是给网络抖动准备的VBA 里调用 HTTP 接口时也建议做重试。2.2 settings.json 配置片段{ taotoken: { apiBase: https://taotoken.net/api, apiKey: sk-你的Key, defaultModel: claude-sonnet, models: { chat: claude-sonnet, code: claude-code, fast: gpt-4o-mini }, requestOptions: { timeout: 60000, maxRetries: 3 } } }settings.json 适合编辑器插件或带配置文件的客户端读取。两个文件里的 Key 是同一个模型名按你实际开通的填。如果你只是做纯窗口自动化、暂时不调模型这两块可以先放着等需要文本处理时再接入。3. 可复制配置Shell 启动、AppActivate 激活与键鼠模拟这一节是核心操作部分。先讲 Shell 的第二个参数怎么选再讲 AppActivate 的两种传参方式最后把 mouse_event 和 SendKeys 的组合写成一个可运行的 Sub。3.1 Shell 第二个参数对照Shell 的第一个参数是程序路径或命令第二个参数决定窗口显示状态和焦点。下面这张表直接对照常数值和效果常数值描述焦点行为vbHide (0)窗口隐藏焦点传给隐藏窗口vbNormalFocus (1)正常大小窗口获得焦点vbMinimizedFocus (2)最小化为图符图符获得焦点vbMaximizedFocus (3)最大化窗口获得焦点vbNormalNoFocus (4)恢复最近大小位置当前活动窗口不变vbMinimizedNoFocus (6)最小化为图符当前活动窗口不变做自动化时如果你希望启动后立刻能 SendKeys用 1 或 3如果你只是后台启动、稍后再激活用 4 或 6 避免抢焦点。Shell 的返回值是进程 ID这个 ID 要存下来后面 AppActivate 会用到。3.2 AppActivate 的两种传参AppActivate 可以接受窗口标题字符串也可以接受 Shell 返回的进程 ID。用标题的好处是能激活本来就打开的窗口坏处是标题可能变化或被截断。用进程 ID 的好处是精确但只能激活 VBA 自己用 Shell 启动并拿到返回值的窗口。 方式一按标题激活 AppActivate 1.txt - 记事本 方式二按 Shell 返回值激活 Dim pid As Double pid Shell(notepad, 1) AppActivate pid, False第二个参数 False 表示不等待激活完成就继续执行。实际用的时候建议配合 Application.Wait 给窗口一点时间否则 SendKeys 可能发到错误的窗口。3.3 完整的窗口激活加按键发送验证下面这段代码打开三个记事本各写一点内容然后按打开顺序关闭且不保存。你可以直接复制到 VBA 模块里运行。Option Explicit 声明鼠标事件与光标位置 API Public Declare Sub mouse_event Lib user32 (ByVal dwFlags As Long, _ ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long) Public Declare Function GetCursorPos Lib user32 (lpPoint As POINTAPI) As Long Public Declare Function SetCursorPos Lib user32 (ByVal x As Long, ByVal y As Long) As Long Public Const MOUSEEVENTF_MOVE H1 Public Const MOUSEEVENTF_LEFTDOWN H2 Public Const MOUSEEVENTF_LEFTUP H4 Public Const MOUSEEVENTF_RIGHTDOWN H8 Public Const MOUSEEVENTF_RIGHTUP H10 Public Const MOUSEEVENTF_ABSOLUTE H8000 Type POINTAPI x As Long y As Long End Type 验证动作打开三个记事本写入内容按顺序关闭不保存 Sub testAppActivate() Dim windowCodeList As New Collection Dim i As Variant Dim pid As Double 启动三个记事本并记录进程 ID For i 1 To 3 pid Shell(notepad, 1) Application.Wait (Now TimeValue(0:00:01)) Application.SendKeys 窗口 i 的内容 windowCodeList.Add pid Debug.Print 启动进程 ID: pid Next i 按打开顺序激活并关闭 For Each i In windowCodeList Debug.Print 激活进程 ID: i AppActivate i, False Application.Wait (Now TimeValue(0:00:01)) AltF4 关闭窗口 Application.SendKeys %{f4} Application.Wait (Now TimeValue(0:00:01)) 按 N 不保存 Application.SendKeys n Application.Wait (Now TimeValue(0:00:01)) Next i MsgBox 三个记事本已按顺序关闭且未保存 End Sub 鼠标点击验证在当前位置左键双击 Sub testMouseClick() Dim Cp As POINTAPI GetCursorPos Cp SetCursorPos Cp.x, Cp.y Dim i As Integer For i 1 To 2 mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 Application.Wait (Now TimeValue(0:00:01)) Next i Application.SendKeys abc Application.Wait (Now TimeValue(0:00:01)) Application.SendKeys ^s End Sub运行 testAppActivate 时你会看到三个记事本依次打开、写入内容、然后被 AltF4 关闭并选择不保存。Debug.Print 会在立即窗口输出进程 ID方便你对照。testMouseClick 则是在当前光标位置双击然后输入 abc 并 CtrlS 保存适合验证鼠标事件是否生效。4. 验证请求与成功结果跑完上面的代码怎么确认真的成功了看三个地方。第一立即窗口的 Debug.Print 输出。正常情况你会看到三行「启动进程 ID」和三行「激活进程 ID」数字一一对应。如果某个进程 ID 激活失败AppActivate 会抛错你能立刻定位是哪个窗口出了问题。第二记事本的实际行为。三个窗口应该按打开顺序依次被关闭每次关闭时弹出「是否保存」对话框然后被 SendKeys n 选择不保存。如果某个窗口没被关闭说明 AppActivate 没找到它或者焦点被其他窗口抢走了。第三鼠标点击验证。运行 testMouseClick 后当前光标位置应该出现双击效果然后输入 abc。如果你在记事本里运行会看到 abc 被输入CtrlS 触发保存对话框。如果你需要把模型调用也串进来可以在写入内容前先请求 TaoToken 的模型对话接口把返回文本用 SendKeys 发出去。模型对话入口在 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 你可以先用它验证 Key 和通道是否正常再接入 VBA 的 HTTP 请求。5. 本篇常见错排查5.1 AppActivate 报错「找不到窗口」最常见的原因是窗口标题不匹配或进程 ID 失效。用标题激活时标题必须和任务栏显示的完全一致包括空格和连字符。用进程 ID 激活时确认 Shell 返回值是 Double 类型并且窗口还没被关闭。如果窗口启动慢AppActivate 执行时窗口还没创建就会报错。解决办法是在 Shell 之后加 Application.Wait 等待一到两秒。5.2 SendKeys 发到了错误的窗口SendKeys 是发给当前活动窗口的如果 AppActivate 没成功按键就发到别处了。排查方法是每次 SendKeys 前先确认 AppActivate 的返回值或者用 AppActivate 的第二个参数设为 True 等待激活完成。另外如果目标程序以管理员权限运行而 VBA 宿主不是管理员SendKeys 会被 UIPI 机制拦截表现为按键无效但不报错。这种情况需要让 VBA 宿主和目标程序在同一权限级别运行。5.3 mouse_event 点击位置不对mouse_event 的坐标是屏幕绝对坐标不是窗口相对坐标。如果你用 SetCursorPos 设置了位置再调用 mouse_event点击会发生在设置的位置。但如果你用了 MOUSEEVENTF_ABSOLUTE 标志坐标需要归一化到 0 到 65535 范围。建议先用 GetCursorPos 拿到当前位置再决定是否移动。另外高 DPI 缩放下坐标可能偏移需要在系统设置里确认缩放比例。5.4 Shell 启动的程序没有窗口有些程序启动后不显示窗口或者窗口标题为空。这时候 AppActivate 用标题找不到用进程 ID 也可能因为窗口句柄未就绪而失败。可以先用任务管理器确认进程是否真的在运行再用 Spy 或类似工具查看窗口句柄。如果程序本身是后台服务那就不适合用 AppActivate应该考虑其他集成方式。5.5 模型调用返回 401 或超时如果你在 VBA 里通过 HTTP 调用 TaoToken 接口返回 401 说明 Key 不对或没带上。检查 config.toml 或 settings.json 里的 api_key 是否和 https://taotoken.net/api-keys 里创建的一致。超时的话把 timeout 调大或者检查网络是否能访问 https://taotoken.net/api 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有各语言的请求示例可以对照排查。6. 继续跑通你的自动化流程窗口激活和键鼠模拟跑通之后下一步通常是把重复操作封装成可复用的函数加上错误处理和日志。如果你要做的是长期运行的编码或 Agent 任务建议把模型调用统一走 TaoToken 的 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 这样 Key 和通道管理集中在一处换模型不用改代码。实际用的时候我习惯把每个自动化步骤的进程 ID 和窗口标题记到一张隐藏工作表里出错时能快速回溯是哪一步的窗口没激活。另外SendKeys 的字符串里如果包含特殊字符比如加号、百分号、波浪号需要用大括号转义否则会被解释成功能键。这些细节在批量操作时特别容易踩坑建议先在测试环境跑几轮再上生产。
返回列表