迁移至M365后Excel VBA宏报Runtime error '380',可否尝试指定代码?
解决M365中VBA脚本控件Runtime error '380'问题
问题背景
Excel 2016中正常运行的VBA宏文件,在M365桌面版执行SC.Language = "VBScript"语句时触发Runtime error '380': A script engine for the specified language can not be created,调整信任中心宏配置后问题仍存在,询问是否可通过CreateObjectx86代码解决。
可行方案分析
你提供的CreateObjectx86调用思路是可行的,但需先确保该自定义函数已正确定义——因为M365默认是64位版本,而MSScriptControl.ScriptControl是32位COM组件,无法直接通过标准CreateObject调用,需通过32位兼容方式加载。
完整实现步骤
确认M365版本
打开Excel→文件→账户→关于Excel,检查是否为64位版本(若为32位,直接使用Set S = CreateObject("MSScriptControl.ScriptControl")即可)。添加
CreateObjectx86函数
在VBA模块中插入以下代码,用于创建32位COM对象:Private Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, ByVal lpProcName As String) As LongPtr Private Declare PtrSafe Function CoCreateInstance Lib "ole32.dll" ( _ ByVal rclsid As LongPtr, _ ByVal pUnkOuter As LongPtr, _ ByVal dwClsContext As Long, _ ByVal riid As LongPtr, _ ByRef ppv As LongPtr) As Long Private Const CLSCTX_INPROC_SERVER = 1 Private Const IID_IDispatch As String = "{00020400-0000-0000-C000-000000000046}" Function CreateObjectx86(ByVal ProgID As String) As Object Dim hMod As LongPtr, pfn As LongPtr Dim clsid As LongPtr, iid As LongPtr Dim obj As LongPtr ' 加载32位oleaut32.dll(仅64位Excel有效) hMod = LoadLibrary("C:\Windows\SysWOW64\oleaut32.dll") pfn = GetProcAddress(hMod, "CLSIDFromProgID") If pfn = 0 Then GoTo Cleanup ' 获取ProgID对应的CLSID Call CallWindowProcPtr(pfn, StrPtr(ProgID), clsid) If clsid = 0 Then GoTo Cleanup ' 获取IDispatch接口IID Call CallWindowProcPtr(GetProcAddress(hMod, "IIDFromString"), StrPtr(IID_IDispatch), iid) If iid = 0 Then GoTo Cleanup ' 创建32位COM对象 If CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, iid, obj) = 0 Then Set CreateObjectx86 = ObjPtrToObject(obj) End If Cleanup: If hMod <> 0 Then Call FreeLibrary(hMod) End Function Private Function CallWindowProcPtr(ByVal lpPrevWndFunc As LongPtr, ByVal hWnd As LongPtr, ByVal Msg As LongPtr, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr CallWindowProcPtr = CallWindowProc(lpPrevWndFunc, hWnd, Msg, wParam, lParam) End Function Private Function ObjPtrToObject(ByVal objPtr As LongPtr) As Object Dim obj As Object CopyMemory obj, objPtr, 8 Set ObjPtrToObject = obj CopyMemory obj, 0&, 8 End Function Private Declare PtrSafe Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As LongPtr, ByVal hWnd As LongPtr, ByVal Msg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr) Private Declare PtrSafe Function FreeLibrary Lib "kernel32" (ByVal hLibModule As LongPtr) As Long修改原宏代码
将原创建ScriptControl的代码替换为:Dim S As Object Set S = CreateObjectx86("MSScriptControl.ScriptControl") S.Language = "VBScript" ' 后续原有脚本操作代码保持不变
替代方案(避免依赖32位组件)
若上述方式仍存在兼容性问题,建议将依赖MSScriptControl的逻辑转换为原生VBA实现,或使用64位兼容的组件(如Microsoft Scripting Runtime)。例如,若只是执行简单脚本逻辑,可直接用VBA代码重写,无需调用外部脚本引擎。
注意事项
- 确保M365信任该宏文件,信任中心设置需允许宏运行(仅在信任文件的前提下开启)。
- 保存文件为
.xlsm格式,确保宏功能已启用。 - 32位M365无需使用
CreateObjectx86,直接调用CreateObject("MSScriptControl.ScriptControl")即可。
内容的提问来源于stack exchange,提问作者Lisander
相关产品推荐
相关产品推荐

