乐于分享
好东西不私藏

Excel VBA 调 Windows API:把系统能力借过来用

Excel VBA 调 Windows API:把系统能力借过来用

有些事,Excel 自己做起来会绕很远。比如查一个 .csv 到底会被哪个程序打开,导出报表前看默认打印机端口,根据屏幕尺寸调整工具窗体,把上次导出的目录记下来。

我一般会让 VBA 去问 Windows。

说白了,Windows API 就是 Windows 暴露出来的一批系统函数。它们放在 DLL 里,比如 user32.dllshell32.dllkernel32.dlladvapi32.dll。VBA 要调用这些函数,得先用 Declare 写一条声明,告诉 VBA:函数在哪里、叫什么、参数怎么传、返回值怎么接。

这篇我用自己的案例重写一遍。你会看到这些内容:API 声明怎么看,PtrSafe 和 LongPtr 怎么用,#If VBA7 Then 为什么会出现,VBE 里 #Else 下面变红怎么处理,还有文件关联、默认打印机、屏幕信息、注册表读写这些常用场景。

API 声明像一张调用说明书

VBA 调 Windows API,最关键的一步就是声明。

我会把 Declare 看成一张调用说明书。Excel 读到这行以后,才知道要去哪个 DLL 找函数,函数在 DLL 里的名字是什么,要传几个参数,返回值用什么类型接。

一个声明大概长这样:

  • 1
  • 2
  • 3
  • 4
  • 5
PrivateDeclare PtrSafe Function MessageBoxW Lib"user32" ( _ByVal hwnd As LongPtr, _ByVal lpText As LongPtr, _ByVal lpCaption As LongPtr, _ByVal uType AsLongAsLong

这里面每个词都有用:

写法
我怎么理解
Private
 / Public
控制这条声明给当前模块用,还是别的模块也能用
Declare Function
告诉 VBA:我要调用外部 DLL 里的函数
PtrSafe
告诉新版 VBA:这条 API 声明已经按 32/64 位检查过
Lib "user32"
函数所在的 DLL
Alias "xxx"
DLL 里的真实名字和 VBA 里的名字不一样时会用到
ByVal
 / ByRef
参数按值传,还是把变量地址交给函数改
As Long
 / As LongPtr
接普通数字,或接窗口句柄、指针、内存地址这类值

声明的位置也很重要。我的习惯是把 Option Explicit 放最上面,API 声明紧跟着放在标准模块顶部,常量再往下放,过程写在后面。

像这样:

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
OptionExplicit' 这里放 API 声明' 这里放常量PublicSub Demo()' 这里写业务代码EndSub

不要把 Declare 塞进 Sub 里面。这个位置错了,宏还没运行就会报编译错误。

先把 MessageBoxW 跑起来

新手练 Windows API,我建议从系统提示框开始。代码短,效果直观,出错也容易排查。

这个版本适合现在常见的 Excel 2016、2019、2021、Microsoft 365。它不写 #If,看起来更清楚。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
OptionExplicitPrivateDeclare PtrSafe Function MessageBoxW Lib"user32" ( _ByVal hwnd As LongPtr, _ByVal lpText As LongPtr, _ByVal lpCaption As LongPtr, _ByVal uType AsLongAsLongPrivateConst MB_OK AsLong = &H0PrivateConst MB_ICONINFORMATION AsLong = &H40PublicSub ApiHello()Dim msg AsStringDim title AsString    msg = "我从 VBA 调到了 Windows API"    title = "API 提醒"    MessageBoxW 0, StrPtr(msg), StrPtr(title), MB_OK Or MB_ICONINFORMATIONEndSub

使用方法很简单:

步骤
操作
保存文件
把工作簿保存成 .xlsm
打开编辑器
按 Alt + F11
插入模块
点菜单 插入 -> 模块
粘贴代码
把上面代码完整粘进去
运行宏
按 F5,或回到 Excel 按 Alt + F8 选择 ApiHello

跑起来以后,你会看到一个 Windows 风格的消息框。

这里有两个小点,我觉得一定要写进文章里。

MessageBoxW 结尾的 W 代表 Unicode 版本。中文标题、中文路径、中文文件名,优先考虑 W 版。StrPtr(msg) 的意思是把 VBA 字符串的地址传给 Windows API。

代码里的引号一定要用英文半角双引号。公众号编辑器、Word、某些笔记软件会把 "API 提醒" 变成中文弯引号。VBA 一看到弯引号,很容易直接报错。

看到 #If / #Else / #End If 别慌

很多人第一次看到下面这种写法,会被开头的 # 吓到:

  • 1
  • 2
  • 3
  • 4
  • 5
#If VBA7 Then' 新版 VBA 用这里#Else' 老版 VBA 用这里#EndIf

这叫条件编译指令。它是给编译器看的开关。

#If VBA7 Then 成立时,VBA 会用上面那段声明。#Else 下面那段是备用声明,给很老的 VBA 用。你在 VBE 里看到 #Else 下面变红,很多时候只是编辑器把当前不会参与编译的分支标红了。真正要看的是:ApiHello 能不能跑,消息框能不能弹出来。

还有一个容易混淆的地方:VBA7 说的是新版 VBA,Office 2010 之后基本都属于这个范围。它不等于 64 位。32 位 Office 也可能是 VBA7。需要判断真 64 位时,再看 Win64

如果你要把代码发给别人,想兼容老 Office,可以用下面这个版本。注意,简化版和兼容版二选一,别把两个 MessageBoxW 声明同时放到同一个模块里。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
OptionExplicit#If VBA7 ThenPrivateDeclare PtrSafe Function MessageBoxW Lib"user32" ( _ByVal hwnd As LongPtr, _ByVal lpText As LongPtr, _ByVal lpCaption As LongPtr, _ByVal uType AsLongAsLong#ElsePrivateDeclareFunction MessageBoxW Lib"user32" ( _ByVal hwnd AsLong, _ByVal lpText AsLong, _ByVal lpCaption AsLong, _ByVal uType AsLongAsLong#EndIfPrivateConst MB_OK AsLong = &H0PrivateConst MB_ICONINFORMATION AsLong = &H40PublicSub ApiHello()Dim msg AsStringDim title AsString    msg = "我从 VBA 调到了 Windows API"    title = "API 提醒"    MessageBoxW 0, StrPtr(msg), StrPtr(title), MB_OK Or MB_ICONINFORMATIONEndSub

我排查这类代码时,会按这个顺序看:

现象
我会怎么处理
#Else
 下方红色
先运行 Sub,能弹窗就不用管
整段声明报错
看声明有没有放在标准模块顶部
字符串报错
检查双引号有没有变成中文弯引号
PtrSafe
 报错
可能是很老的 Office,用兼容版里的 #Else 分支
Mac 上跑不动
这个是 Windows API,只给 Windows 版 Excel 用

32 位和 64 位,别把 Long 全改成 LongPtr

老 VBA 代码迁到 64 位 Office,最常见的问题就是 API 声明。

新版 VBA 需要 PtrSafe。窗口句柄、文件句柄、内存地址、字符串地址这类值,要用 LongPtr。普通数字、按钮类型、常量编号、长度、数量,很多时候还是 Long

我写代码时会记住一句话:LongPtr 给地址类的值用,Long 继续接普通整数。

比如 MessageBoxW 里:

  • 1
  • 2
  • 3
  • 4
ByVal hwnd As LongPtr       ' 窗口句柄ByVal lpText As LongPtr     ' 字符串地址ByVal lpCaption As LongPtr  ' 字符串地址ByVal uType AsLong' 按钮和图标类型

uType 只是样式编号,所以继续用 Long。这事看着小,实际很容易写错。

6 个案例,把用法串起来

下面这些案例都换成了新的写法。你可以按需复制,但我建议每次只拷一个案例到空模块里测试。多个案例放在一起时,同名常量和同名声明不要重复。

案例一:MessageBoxW 做连通测试

上面已经跑过 MessageBoxW。我在实际写工具时,也会用它做一个最小测试:确认 API 声明没问题,确认宏权限没问题,确认系统函数能被调用。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
PublicSub Demo_MessageBox()Dim msg AsStringDim title AsString    msg = "报表导出完成,可以检查文件了。"    title = "报表助手"    MessageBoxW 0, StrPtr(msg), StrPtr(title), MB_OK Or MB_ICONINFORMATIONEndSub

这个例子小,但把 DLL、函数、参数、返回值都跑了一遍。后面换成更复杂的 API,思路还是这几件事。

案例二:ShellExecuteW 打开文件夹或网页

ShellExecuteW 很适合做“交给 Windows 自己打开”的事。给它一个网址,系统会用默认浏览器打开。给它一个文件夹,会打开资源管理器。给它一个文件,会按系统关联打开。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
OptionExplicit#If VBA7 ThenPrivateDeclare PtrSafe Function ShellExecuteW Lib"shell32.dll" ( _ByVal hwnd As LongPtr, _ByVal lpOperation As LongPtr, _ByVal lpFile As LongPtr, _ByVal lpParameters As LongPtr, _ByVal lpDirectory As LongPtr, _ByVal nShowCmd AsLongAs LongPtr#ElsePrivateDeclareFunction ShellExecuteW Lib"shell32.dll" ( _ByVal hwnd AsLong, _ByVal lpOperation AsLong, _ByVal lpFile AsLong, _ByVal lpParameters AsLong, _ByVal lpDirectory AsLong, _ByVal nShowCmd AsLongAsLong#EndIfPrivateConst SW_SHOWNORMAL AsLong = 1PublicSub OpenCurrentWorkbookFolder()#If VBA7 ThenDim ret As LongPtr#ElseDim ret AsLong#EndIf    ret = ShellExecuteW(0, StrPtr("open"), _   StrPtr(ThisWorkbook.Path),0,0, SW_SHOWNORMAL)If ret <= 32Then        MsgBox "打开失败,返回值:" & ret, vbExclamationEndIfEndSubPublicSub OpenHelpPage()#If VBA7 ThenDim ret As LongPtr#ElseDim ret AsLong#EndIf    ret = ShellExecuteW(0, StrPtr("open"), _   StrPtr("https://example.com/excel-api-help"), _0,0, SW_SHOWNORMAL)EndSub

我一般会检查返回值。ShellExecuteW 返回值小于等于 32 时,多半表示失败。每个 API 的返回规则都要单独看,别靠猜。

案例三:只查 .csv 会被哪个程序打开

有时我不想真的打开文件,只想知道某种扩展名会交给哪个程序处理。比如 .csv 在一台电脑上可能交给 Excel,在另一台电脑上可能交给文本编辑器。

这里我用 AssocQueryStringW。它来自 shlwapi.dll,可以查询文件关联信息。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
OptionExplicit#If VBA7 ThenPrivateDeclare PtrSafe Function AssocQueryStringW Lib"shlwapi.dll" ( _ByVal flags AsLong, _ByVal assocStr AsLong, _ByVal pszAssoc As LongPtr, _ByVal pszExtra As LongPtr, _ByVal pszOut As LongPtr, _ByRef pcchOut AsLongAsLong#ElsePrivateDeclareFunction AssocQueryStringW Lib"shlwapi.dll" ( _ByVal flags AsLong, _ByVal assocStr AsLong, _ByVal pszAssoc AsLong, _ByVal pszExtra AsLong, _ByVal pszOut AsLong, _ByRef pcchOut AsLongAsLong#EndIfPrivateConst ASSOCSTR_EXECUTABLE AsLong = 2PrivateConst S_OK AsLong = 0PublicFunction AssociatedExe(ByVal extName AsStringAsStringDim buf AsStringDim cch AsLongDim p AsLong    cch = 520    buf = String$(cch, vbNullChar)If AssocQueryStringW(0, ASSOCSTR_EXECUTABLE, _   StrPtr(extName),0,StrPtr(buf),cch)=S_OK Then        p = InStr(buf, vbNullChar)Ifp>0ThenAssociatedExe=Left$(buf,p-1)EndIfEndFunctionPublicSub Demo_CsvAssociation()Dim exePath AsString    exePath = AssociatedExe(".csv")If Len(exePath) = 0Then        MsgBox "没查到 .csv 的关联程序。", vbExclamationElse        MsgBox ".csv 当前关联程序:" & vbCrLf & exePath, vbInformationEndIfEndSub

这个案例的关键在缓冲区。很多 Windows API 会让你准备一段字符串空间,函数把结果写进去。VBA 里常用 String$(长度, vbNullChar) 先占位,再用 InStr 找到结尾的空字符。

案例四:导出报表前做默认打印机检查

Excel 的 Application.ActivePrinter 能看到当前打印机文本,但驱动名和端口信息拆得不够细。GetProfileStringW 可以读取 Windows 配置里的 Windows / Device,内容通常长这样:

  • 1
打印机名称,驱动名称,端口

我会把它包装成“打印前检查卡”。导出 PDF、打印报表前跑一下,能少踩环境差异带来的坑。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
OptionExplicit#If VBA7 ThenPrivateDeclare PtrSafe Function GetProfileStringW Lib"kernel32" ( _ByVal lpAppName As LongPtr, _ByVal lpKeyName As LongPtr, _ByVal lpDefault As LongPtr, _ByVal lpReturnedString As LongPtr, _ByVal nSize AsLongAsLong#ElsePrivateDeclareFunction GetProfileStringW Lib"kernel32" ( _ByVal lpAppName AsLong, _ByVal lpKeyName AsLong, _ByVal lpDefault AsLong, _ByVal lpReturnedString AsLong, _ByVal nSize AsLongAsLong#EndIfPublicFunction DefaultPrinterCard() AsStringDim buf AsStringDim rawText AsStringDim parts() AsStringDim n AsLongDim p AsLong    buf = String$(512, vbNullChar)    n = GetProfileStringW(StrPtr("Windows"), StrPtr("Device"), _   StrPtr(""),StrPtr(buf), Len(buf))If n = 0ThenExitFunction    p = InStr(buf, vbNullChar)If p > 0Then        rawText = Left$(buf, p - 1)Else        rawText = bufEndIf    parts = Split(rawText, ",")If UBound(parts) >= 2Then   DefaultPrinterCard="打印机:"&Trim$(parts(0))&vbCrLf& _"驱动:"&Trim$(parts(1))&vbCrLf& _"端口:"&Trim$(parts(2))Else        DefaultPrinterCard = rawTextEndIfEndFunctionPublicSub CheckPrinterBeforeExport()Dim info AsString    info = DefaultPrinterCard()If Len(info) = 0Then        MsgBox "没读到默认打印机。", vbExclamationElse        MsgBox info, vbInformation, "打印前检查"EndIfEndSub

这个例子也提醒我:API 返回的结果不一定是对象,很多时候就是一段字符串。拿到以后要自己拆、自己清洗、自己展示。

案例五:把屏幕数量和尺寸写进工作表

做自动化报表时,同一份表在不同电脑上显示差异可能很大。GetSystemMetrics 可以读取主屏宽高、显示器数量、虚拟屏幕宽高。

多屏场景下,虚拟屏幕指的是 Windows 把几块屏幕拼在一起后的整体范围。这个信息对 UserForm 位置、仪表板展示、截图区域判断都挺有用。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
OptionExplicit#If VBA7 ThenPrivateDeclare PtrSafe Function GetSystemMetrics Lib"user32" ( _ByVal nIndex AsLongAsLong#ElsePrivateDeclareFunction GetSystemMetrics Lib"user32" ( _ByVal nIndex AsLongAsLong#EndIfPrivateConst SM_CXSCREEN AsLong = 0PrivateConst SM_CYSCREEN AsLong = 1PrivateConst SM_CXVIRTUALSCREEN AsLong = 78PrivateConst SM_CYVIRTUALSCREEN AsLong = 79PrivateConst SM_CMONITORS AsLong = 80PublicSub WriteScreenReport()With ActiveSheet        .Range("A1").Value = "项目"        .Range("B1").Value = "值"        .Range("A2").Value = "显示器数量"        .Range("B2").Value = GetSystemMetrics(SM_CMONITORS)        .Range("A3").Value = "主屏宽度"        .Range("B3").Value = GetSystemMetrics(SM_CXSCREEN)        .Range("A4").Value = "主屏高度"        .Range("B4").Value = GetSystemMetrics(SM_CYSCREEN)        .Range("A5").Value = "虚拟屏幕宽度"        .Range("B5").Value = GetSystemMetrics(SM_CXVIRTUALSCREEN)        .Range("A6").Value = "虚拟屏幕高度"        .Range("B6").Value = GetSystemMetrics(SM_CYVIRTUALSCREEN)        .Columns("A:B").AutoFitEndWithEndSub

我更喜欢把这些系统信息写到一个“环境检查”工作表里。以后别人说工具窗口显示异常,你就能先看屏幕数量和分辨率。

案例六:把上次导出目录存进注册表

很多 Windows 程序会把配置放在注册表里。VBA 也可以通过 advapi32.dll 读写。

我的习惯是只写当前用户范围,比如:

  • 1
HKEY_CURRENT_USER\Software\ExcelApiDemo

公司电脑上不要随便改 HKEY_LOCAL_MACHINE。系统级配置涉及权限,也可能影响别的软件。

常见根键可以这样理解:

根键
常见用途
HKEY_CLASSES_ROOT
文件类型、COM 类相关信息
HKEY_CURRENT_USER
当前用户自己的配置,做宏工具时我最常用
HKEY_LOCAL_MACHINE
整台机器级别配置,通常需要更高权限
HKEY_USERS
多个用户配置集合
HKEY_CURRENT_CONFIG
当前硬件配置相关信息

下面这个例子会把“上次导出目录”写到当前用户的注册表里,再读出来。代码有点长,因为注册表 API 要打开键、写值、查值、关闭键。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
OptionExplicit#If VBA7 ThenPrivateDeclare PtrSafe Function RegCreateKeyExW Lib"advapi32.dll" ( _ByVal hKey As LongPtr, _ByVal lpSubKey As LongPtr, _ByVal Reserved AsLong, _ByVal lpClass As LongPtr, _ByVal dwOptions AsLong, _ByVal samDesired AsLong, _ByVal lpSecurityAttributes As LongPtr, _ByRef phkResult As LongPtr, _ByRef lpdwDisposition AsLongAsLongPrivateDeclare PtrSafe Function RegOpenKeyExW Lib"advapi32.dll" ( _ByVal hKey As LongPtr, _ByVal lpSubKey As LongPtr, _ByVal ulOptions AsLong, _ByVal samDesired AsLong, _ByRef phkResult As LongPtr) AsLongPrivateDeclare PtrSafe Function RegSetValueExW Lib"advapi32.dll" ( _ByVal hKey As LongPtr, _ByVal lpValueName As LongPtr, _ByVal Reserved AsLong, _ByVal dwType AsLong, _ByVal lpData As LongPtr, _ByVal cbData AsLongAsLongPrivateDeclare PtrSafe Function RegQueryValueExW Lib"advapi32.dll" ( _ByVal hKey As LongPtr, _ByVal lpValueName As LongPtr, _ByVal lpReserved As LongPtr, _ByRef lpType AsLong, _ByVal lpData As LongPtr, _ByRef lpcbData AsLongAsLongPrivateDeclare PtrSafe Function RegCloseKey Lib"advapi32.dll" ( _ByVal hKey As LongPtr) AsLong#ElsePrivateDeclareFunction RegCreateKeyExW Lib"advapi32.dll" ( _ByVal hKey AsLong, _ByVal lpSubKey AsLong, _ByVal Reserved AsLong, _ByVal lpClass AsLong, _ByVal dwOptions AsLong, _ByVal samDesired AsLong, _ByVal lpSecurityAttributes AsLong, _ByRef phkResult AsLong, _ByRef lpdwDisposition AsLongAsLongPrivateDeclareFunction RegOpenKeyExW Lib"advapi32.dll" ( _ByVal hKey AsLong, _ByVal lpSubKey AsLong, _ByVal ulOptions AsLong, _ByVal samDesired AsLong, _ByRef phkResult AsLongAsLongPrivateDeclareFunction RegSetValueExW Lib"advapi32.dll" ( _ByVal hKey AsLong, _ByVal lpValueName AsLong, _ByVal Reserved AsLong, _ByVal dwType AsLong, _ByVal lpData AsLong, _ByVal cbData AsLongAsLongPrivateDeclareFunction RegQueryValueExW Lib"advapi32.dll" ( _ByVal hKey AsLong, _ByVal lpValueName AsLong, _ByVal lpReserved AsLong, _ByRef lpType AsLong, _ByVal lpData AsLong, _ByRef lpcbData AsLongAsLongPrivateDeclareFunction RegCloseKey Lib"advapi32.dll" ( _ByVal hKey AsLongAsLong#EndIfPrivateConst HKEY_CURRENT_USER AsLong = &H80000001PrivateConst KEY_READ AsLong = &H20019PrivateConst KEY_WRITE AsLong = &H20006PrivateConst REG_SZ AsLong = 1PrivateConst ERROR_SUCCESS AsLong = 0PrivateConst DEMO_SUB_KEY AsString = "Software\ExcelApiDemo"PrivateConst DEMO_VALUE_NAME AsString = "LastExportFolder"PublicFunction SaveLastExportFolder(ByVal folderPath AsStringAsBoolean#If VBA7 ThenDim hKey As LongPtr#ElseDim hKey AsLong#EndIfDim opened AsLongDim bytes AsLongDim subKey AsStringDim valueName AsString    subKey = DEMO_SUB_KEY    valueName = DEMO_VALUE_NAMEIf RegCreateKeyExW(HKEY_CURRENT_USER, StrPtr(subKey), 000, _   KEY_WRITE,0,hKey,opened)=ERROR_SUCCESS Then        bytes = (Len(folderPath) + 1) * 2        SaveLastExportFolder = (RegSetValueExW(hKey, StrPtr(valueName), 0, _   REG_SZ,StrPtr(folderPath),bytes)= ERROR_SUCCESS)        RegCloseKey hKeyEndIfEndFunctionPublicFunction ReadLastExportFolder() AsString#If VBA7 ThenDim hKey As LongPtr#ElseDim hKey AsLong#EndIfDim subKey AsStringDim valueName AsStringDim valueType AsLongDim bytes AsLongDim buf AsStringDim p AsLong    subKey = DEMO_SUB_KEY    valueName = DEMO_VALUE_NAMEIf RegOpenKeyExW(HKEY_CURRENT_USER, StrPtr(subKey), 0, _   KEY_READ,hKey)<>ERROR_SUCCESSThenExitFunctionIf RegQueryValueExW(hKey, StrPtr(valueName), 0, _   valueType,0,bytes)=ERROR_SUCCESS ThenIfvalueType=REG_SZAndbytes>2Then   buf=String$(bytes\2, vbNullChar)IfRegQueryValueExW(hKey,StrPtr(valueName),0, _   valueType,StrPtr(buf),bytes)=ERROR_SUCCESS Then   p=InStr(buf, vbNullChar)Ifp>0ThenReadLastExportFolder=Left$(buf,p-1)EndIfEndIfEndIf    RegCloseKey hKeyEndFunctionPublicSub Demo_SaveExportFolder()If SaveLastExportFolder(ThisWorkbook.Path) Then        MsgBox "已保存导出目录:" & vbCrLf & ReadLastExportFolder(), vbInformationElse        MsgBox "写入失败,请检查权限。", vbExclamationEndIfEndSub

注册表 API 里有几个函数我会固定记住:

函数
用途
RegCreateKeyExW
创建或打开一个键
RegOpenKeyExW
打开已有键
RegSetValueExW
写入一个值
RegQueryValueExW
读取一个值
RegCloseKey
关闭打开的键句柄

RegCloseKey 特别容易被忘掉。只要你打开了注册表键,做完就关掉。这和打开文件后要关闭文件句柄是一个道理。

只存自己的小设置,GetSetting / SaveSetting 更省事

如果我只是想保存自己宏的窗口位置、上次选择的目录、某个开关状态,会优先用 VBA 自带的 GetSetting 和 SaveSetting

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
OptionExplicitPublicSub Demo_BuiltInSetting()    SaveSetting "ExcelApiDemo""Export""LastFolder", ThisWorkbook.Path    MsgBox GetSetting("ExcelApiDemo""Export""LastFolder""")EndSub

它们写入的位置固定在这里:

  • 1
HKEY_CURRENT_USER\Software\VB and VBA Program Settings

想读写别的位置,还是要用注册表 API。只存自己宏的小配置,用内置函数会轻很多。

我写 Windows API 前会看这张表

检查点
我会怎么做
工作簿格式
保存成 .xlsm,并允许宏运行
运行环境
Windows 版 Excel,Mac 版不能用这些 Windows API
声明位置
放标准模块顶部,别放进 Sub 里面
#If
 红色
当前不用的备用分支可能变红,能运行就不用慌
引号
代码里的字符串用英文半角双引号
DLL 名
看清函数来自 user32shell32kernel32 还是 advapi32
A / W 版本
中文路径、中文标题优先考虑 W 版
字符串参数
W
 版常用 StrPtr(字符串) 传地址
指针和句柄
用 LongPtr
普通编号和数量
多数继续用 Long
返回值
每个 API 单独看规则,别靠猜
注册表权限
尽量只写 HKEY_CURRENT_USER 下自己的键
资源释放
打开的句柄要关,比如 RegCloseKey

Windows API 看起来吓人,其实拆开以后就是三件事:声明写对,参数传对,返回值判断对。

我觉得 VBA 最舒服的地方就在这里:Excel 负责表格和业务,Windows API 负责问系统要信息。文件关联、打印机、屏幕、注册表这些功能,不一定每天用,但做成工具以后,省下的麻烦会很多。

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-05-10 01:22:26 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/597920.html
  2. 运行时间 : 0.255703s [ 吞吐率:3.91req/s ] 内存消耗:4,852.72kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=270c8ae3dafff752c2ae952a69db686f
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.001077s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001750s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000753s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000664s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001494s ]
  6. SELECT * FROM `set` [ RunTime:0.000535s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001534s ]
  8. SELECT * FROM `article` WHERE `id` = 597920 LIMIT 1 [ RunTime:0.003788s ]
  9. UPDATE `article` SET `lasttime` = 1778347346 WHERE `id` = 597920 [ RunTime:0.001722s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000775s ]
  11. SELECT * FROM `article` WHERE `id` < 597920 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.006519s ]
  12. SELECT * FROM `article` WHERE `id` > 597920 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.007126s ]
  13. SELECT * FROM `article` WHERE `id` < 597920 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.026214s ]
  14. SELECT * FROM `article` WHERE `id` < 597920 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.005710s ]
  15. SELECT * FROM `article` WHERE `id` < 597920 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.027419s ]
0.257431s