MS Access 2010,Excel 2010,Windows Server 2008 R2 64位:工作簿类的SaveAs方法失败

使用的服务:MS Access 2010,Excel 2010,Windows Server 2008 R2(64位)

在我们的MS Access数据库中,我们编写了一个将查询导出为.xlsx格式并将其保存在networking驱动器上的进程。 它使用这个语法:

objxl.ActiveWorkbook.SaveAs filename, FileFormat:=xlOpenXMLWorkbook 

 xlWBk.SaveAs filename, FileFormat:=xlOpenXMLWorkbook 

其中objxl被声明为:

 Private objxl As Object 

并通过以下方式打开文件:

 Dim xlWBk As Object If objxl Is Nothing Then Set objxl = CreateObject("Excel.Application") End If If Dir(sourceFile) = vbNullString Then Set xlWBk = objxl.Workbooks.Add Else Set xlWBk = objxl.Workbooks.Open(sourceFile) blnFileExists = True End If 

当我们手动运行它时,这段代码工作正常。 我相当有信心,代码是正确的,但我在这里发布,以防万一。

但是,我们需要自动化这个数据库,这样我们就可以通过计划的任务从一个账户运行,即使账户没有login(这个账户拥有pipe理权限等),也可以运行。 不幸的是,当像这样运行程序的时候,我们在日志中得到这个错误:

 "SaveAs method of Workbook class failed." 

我们已经证实,这不是一个networking读/写的问题(它写的各种其他文件,如.txt和.pdf,只是很好的networking驱动器,这个问题似乎本地化到Excel)。

我们已经按照这个post尝试了一个修复: https : //stackoverflow.com/a/1090864/5239568

但似乎没有任何工作到目前为止。

终于搞定了。 这是什么工作,以防万一未来有这个相同的错误。

我们添加了两个文件夹:

 C:\Windows\System32\config\systemprofile\Desktop C:\Windows\SysWOW64\config\systemprofile\Desktop 

我的第一个build议是检查自动运行的Excel加载项,尤其是公司安全文档分类/版权声明脚本。

您的下一个可疑位置受信任的位置 ,我在其他位置的“ 受信任位置”下提到了这个位置:误导性错误消息的来源 。

这是主要的犯罪嫌疑人,因为“受信任的地点”是一个安全设置,可以阻止脚本和自动化的COM对象,而不是手动操作。 或者至less不是所有的 “用户都在场”手动操作。 所以你不会通过手动重现错误来捕捉它 – 而且你可能会发现你的debugging尝试会给出不一致的结果。

您可以在任何Microsoft Office应用程序的“文件”菜单下将选项设置为可信位置; 信托中心; 受信任的位置 – 但这是用户特定的,您可能无法为任何人(或其他)运行您的应用程序。 所以这应该给你一个关于自动化的提示:

VBA代码设置可信地点:

Public Sub TrustThisFolder(Optional FolderPath As String, _                           Optional TrustSubfolders As Boolean = True, _                           Optional TrustNetworkFolders As Boolean = False, _                           Optional sDescription As String) 
' Add a folder to the 'Trusted Locations' list so that your project's VBA can ' open Excel files without raising errors like "Office has detected a problem ' with this file. To help protect your computer this file cannot be opened."
' Ths function has been implemented to fail silently on error: if you suspect ' that users don't have permission to assign 'Trusted Location' status in all ' locations, reformulate this as a function returning True or False

' This should be used with caution: although I regard Microsoft's rationale ' for 'Trusted Locations' to be flawed (in this specific case, perverse and ' worse than ineffective) bypassing a security feature is never a good idea ' without letting the users know what they are doing, and offering a choice
' You are strongly advised to keep the confirmation dialogue, unless you've ' run into something stupid - like refusing to open files in the user's own ' local temp folder - which is what we're dealing with here, in basExcelSQL

' Author:
' Nigel Heffernan January 2015 http:\Excellerando.blogspot.com
' ' Based on code published by Daniel Pineault in DevHut.net on June 23, 2010: ' www.devhut.net\2010\06\23\vbscript-createset-trusted-location-using-vbscript\
' **** **** **** **** THIS CODE IS IN THE PUBLIC DOMAIN **** **** **** ****
' This code has been widely published, and at least one of the sites carrying ' it (and derived works) asserts that it is subject to an open-source license, ' which explicitly forbids us from asserting ownership, copyright, or other ' intellectual property rights, or attempting to impose restrictive commercial ' secrecy terms on its use, re-use, or publication. Take care to label this ' this code, and segregate it from proprietary source code, or other material ' with embedded business process information which should be kept private.

' UNIT TESTING:
' ' 1: Reinstate the commented-out line 'Debug.Print sSubKey & vbTab & sPath ' 2: Open the Immediate Window and run this command: ' TrustThisFolder "Z:\", True, True, "The user's home directory" ' 3: If "Z:\" is already in the list, choose another folder ' 4: Repeat step 2 or 3: the folder should be listed in the debug output ' 5: If it isn't listed, disable the error-handler and record any errors

On Error GoTo ErrSub

Dim sKeyPath As String
Dim oRegistry As Object Dim sSubKey As String Dim oSubKeys ' type not specified. After it's populated, it can be iterated Dim oSubKey ' type not specified.
Dim bSubFolders As Boolean Dim bNetworkLocation As Boolean
Dim iTrustNetwork As Long Dim bTempFolder As Long
Dim sMsg As String Dim sPath As String Dim sDate As String Dim sDesc As String Dim i As Long
Const HKEY_CURRENT_USER = &H80000001
bSubFolders = True bNetworkLocation = False
If FolderPath = "" Then
FolderPath = FSO.GetSpecialFolder(2).Path If sDescription = "" Then sDescription = "The user's local temp folder" End If
bTempFolder = True
End If
If Right(FolderPath, 1) <> "\" Then FolderPath = FolderPath & "\" End If

sKeyPath = "" sKeyPath = sKeyPath & "SOFTWARE\Microsoft\Office\" sKeyPath = sKeyPath & Application.Version sKeyPath = sKeyPath & "\Excel\Security\Trusted Locations\"

Set oRegistry = GetObject("winmgmts:\.\root\default:StdRegProv") ' Note: not the usual \root\cimv2 for WMI scripting: the StdRegProv isn't in that folder
oRegistry.EnumKey HKEY_CURRENT_USER, sKeyPath, oSubKeys

Public Sub TrustThisFolder(Optional FolderPath As String, _ Optional TrustSubfolders As Boolean = True, _ Optional TrustNetworkFolders As Boolean = False, _ Optional sDescription As String)
' Add a folder to the 'Trusted Locations' list so that your project's VBA can ' open Excel files without raising errors like "Office has detected a problem ' with this file. To help protect your computer this file cannot be opened."
' Ths function has been implemented to fail silently on error: if you suspect ' that users don't have permission to assign 'Trusted Location' status in all ' locations, reformulate this as a function returning True or False

' This should be used with caution: although I regard Microsoft's rationale ' for 'Trusted Locations' to be flawed (in this specific case, perverse and ' worse than ineffective) bypassing a security feature is never a good idea ' without letting the users know what they are doing, and offering a choice
' You are strongly advised to keep the confirmation dialogue, unless you've ' run into something stupid - like refusing to open files in the user's own ' local temp folder - which is what we're dealing with here, in basExcelSQL

' Author:
' Nigel Heffernan January 2015 http:\Excellerando.blogspot.com
' ' Based on code published by Daniel Pineault in DevHut.net on June 23, 2010: ' www.devhut.net\2010\06\23\vbscript-createset-trusted-location-using-vbscript\
' **** **** **** **** THIS CODE IS IN THE PUBLIC DOMAIN **** **** **** ****
' This code has been widely published, and at least one of the sites carrying ' it (and derived works) asserts that it is subject to an open-source license, ' which explicitly forbids us from asserting ownership, copyright, or other ' intellectual property rights, or attempting to impose restrictive commercial ' secrecy terms on its use, re-use, or publication. Take care to label this ' this code, and segregate it from proprietary source code, or other material ' with embedded business process information which should be kept private.

' UNIT TESTING:
' ' 1: Reinstate the commented-out line 'Debug.Print sSubKey & vbTab & sPath ' 2: Open the Immediate Window and run this command: ' TrustThisFolder "Z:\", True, True, "The user's home directory" ' 3: If "Z:\" is already in the list, choose another folder ' 4: Repeat step 2 or 3: the folder should be listed in the debug output ' 5: If it isn't listed, disable the error-handler and record any errors

On Error GoTo ErrSub

Dim sKeyPath As String
Dim oRegistry As Object Dim sSubKey As String Dim oSubKeys ' type not specified. After it's populated, it can be iterated Dim oSubKey ' type not specified.
Dim bSubFolders As Boolean Dim bNetworkLocation As Boolean
Dim iTrustNetwork As Long Dim bTempFolder As Long
Dim sMsg As String Dim sPath As String Dim sDate As String Dim sDesc As String Dim i As Long
Const HKEY_CURRENT_USER = &H80000001
bSubFolders = True bNetworkLocation = False
If FolderPath = "" Then
FolderPath = FSO.GetSpecialFolder(2).Path If sDescription = "" Then sDescription = "The user's local temp folder" End If
bTempFolder = True
End If
If Right(FolderPath, 1) <> "\" Then FolderPath = FolderPath & "\" End If

sKeyPath = "" sKeyPath = sKeyPath & "SOFTWARE\Microsoft\Office\" sKeyPath = sKeyPath & Application.Version sKeyPath = sKeyPath & "\Excel\Security\Trusted Locations\"

Set oRegistry = GetObject("winmgmts:\.\root\default:StdRegProv") ' Note: not the usual \root\cimv2 for WMI scripting: the StdRegProv isn't in that folder
oRegistry.EnumKey HKEY_CURRENT_USER, sKeyPath, oSubKeys

对于oSubKeys中的每个oSubKey
sSubKey = CStr(oSubKey)
oRegistry.GetStringValue HKEY_CURRENT_USER,sKeyPath&“\”&sSubKey,“Path”,sPath
'Debug.Print sSubKey&vbTab&sPath
如果sPath = FolderPath那么
退出
万一
Next oSubKey
如果sPath <> FolderPath那么
如果bTempFolder = False那么
sMsg =“”
sMsg = sMsg&“Microsoft Office将不允许”&APP_NAME&“从此位置打开文件:”
sMsg = sMsg&vbCrLf&vbCrLf
sMsg = sMsg&vbTab&“'”&FolderPath&“'”
sMsg = sMsg&vbCrLf&vbCrLf
sMsg = sMsg&“您想将此文件夹添加到Microsoft Office的列表或受信任的位置吗?
select案例MsgBox(sMsg,vbQuestion + vbYesNo,APP_NAME&“:你信任来自这个位置的文件吗?”)
案例vbYes
“继续
Case Else'Else捕获取消行动以及明确的“否”
Err.Raise -559038737,APP_NAME&“:TrustThisFolder”,“用户select不将文件夹添加到”受信任位置“
Exit Sub'这是死的代码…除非error handling被绕过。 有一天,你会为此感谢我。
结束select
万一
如果是数字(replace(sSubKey,“位置”,“”))然后
i = CLng(Replace(sSubKey,“Location”,“”))+ 1
其他
我= UBound(oSubKeys)+ 1
万一
sSubKey =“Location”&CStr(i)
如果TrustNetworkFolders那么
iTrustNetwork = 1
oRegistry.GetDWordValue HKEY_CURRENT_USER,sKeyPath,“AllowNetworkLocations”,iTrustNetwork
如果iTrustNetwork = 0那么
oRegistry.SetDWordValue HKEY_CURRENT_USER,sKeyPath,“AllowNetworkLocations”,1
万一
万一
oRegistry.CreateKey HKEY_CURRENT_USER,sKeyPath&“\”&sSubKey
oRegistry.SetStringValue HKEY_CURRENT_USER,sKeyPath&“\”&sSubKey,“Path”,FolderPath
oRegistry.SetStringValue HKEY_CURRENT_USER,sKeyPath&“\”&sSubKey,“Description”,sDescription
oRegistry.SetDWordValue HKEY_CURRENT_USER,sKeyPath&“\”&sSubKey,“AllowSubFolders”,1
MsgPopup“成功添加了”&FolderPath&“到Microsoft Office可信文件夹列表。”,vbInformation,APP_NAME&“:Action confirmed。”,3
万一

ExitSub:
设置oRegistry = Nothing
退出小组
ErrSub:
恢复ExitSub
结束小组

请注意,此代码取决于用户干预以确认删除“可信位置”设置。 你可以删除对话框,但我希望你在做之前咨询你的系统pipe理员。

(注意:我使用'popup'对话框,在预设的时间间隔后自动消失,允许代码继续。询问你是否需要代码)

之后,它变得神秘。 这是我上次写的代码,我不得不使用一个单独的Excel.exe实例来打开一个文件:

With New Excel.Application 
.ShowStartupDialog = False .Visible = False .EnableCancelKey = xlDisabled .UserControl = False .Interactive = False .EnableEvents = False
.DisplayAlerts = False .AutomationSecurity = msoAutomationSecurityForceDisable
.Workbooks.Add ' Calculation property is not available if no workbooks are open If .Calculation <> xlCalculationManual Then .Calculation = xlCalculationManual End If
On Error Resume Next
For i = .Workbooks.Count To 1 Step -1 .Workbooks(i).Close False Next i

On Error Resume Next
For i = 1 To .AddIns.Count If .AddIns(i).IsOpen Then .AddIns(i).Installed = False End If Next i

For i = 1 To .COMAddIns.Count If .COMAddIns(1).progID Like "*Information*Classification*" Then ' no action Else .COMAddIns(i).Connect = False If Not .COMAddIns(i).Object Is Nothing Then .COMAddIns(i).Object.Close .COMAddIns(i).Object.Quit End If End If Next i
End With
With New Excel.Application
.ShowStartupDialog = False .Visible = False .EnableCancelKey = xlDisabled .UserControl = False .Interactive = False .EnableEvents = False
.DisplayAlerts = False .AutomationSecurity = msoAutomationSecurityForceDisable
.Workbooks.Add ' Calculation property is not available if no workbooks are open If .Calculation <> xlCalculationManual Then .Calculation = xlCalculationManual End If
On Error Resume Next
For i = .Workbooks.Count To 1 Step -1 .Workbooks(i).Close False Next i

On Error Resume Next
For i = 1 To .AddIns.Count If .AddIns(i).IsOpen Then .AddIns(i).Installed = False End If Next i

For i = 1 To .COMAddIns.Count If .COMAddIns(1).progID Like "*Information*Classification*" Then ' no action Else .COMAddIns(i).Connect = False If Not .COMAddIns(i).Object Is Nothing Then .COMAddIns(i).Object.Close .COMAddIns(i).Object.Quit End If End If Next i
End With

你会在那里注意到'On error Resume Next' :一些加载项不能被closures。

之后,这是月亮和人类牺牲的阶段。 或者,也许,快速浏览Stack Oveflow上的其他答案。