我在一个项目中有一段代码,可以将数据从一个工作表读入一个记录表。记录表代码有密码保护。
为了测试,我简化了代码,如下所示:
Option Explicit
Sub sTest()
Dim dbtmp As DAO.Database
Set dbtmp = OpenDatabase(Application.ActiveWorkbook.FullName, False, True, _
"Excel 8.0;HDR=Yes")
dbtmp.Close
Set dbtmp = Nothing
End Sub
字符串
每当我从Userform运行这段代码时,在关闭Excel后,我会被提示输入VBAProject密码。我猜,根据工作簿中模块的数量,我必须取消至少两次。
我已经打破了我的头在这个最后一个星期,阅读每一个帖子在网上我可以找到,但没有找到一个解决方案。
7条答案
按热度按时间9udxz4iz1#
我在一个打开Excel文件的Outlook项目中遇到过同样的问题,所以与其他人的猜测相反,它与数据库(ADO或DAO)技术没有直接关系。
关于Microsoft Knowledge Database:
症状
运行宏(该宏将包含受密码保护的VBA项目的工作簿的引用传递到ActiveX动态链接库(DLL))后,当Excel退出时,系统会提示您输入VBA项目密码。
原因
如果ActiveX DLL未正确释放对包含受密码保护的PLAN项目的工作簿的引用,则会发生此问题。
当对象之间存在循环引用,并且当Excel关闭时,如果对象保留对受保护工作簿的引用,则会出现密码提示时,通常会出现此问题。
范例:objectA存储对objectB的引用,objectB存储对objectA的引用。除非显式地
set objectA.ReferenceToB = Nothing
或objectB.ReferenceToA = Nothing
,否则这两个对象不会被销毁。由于我无法通过在我的计算机上运行您的代码来复制症状,我猜您已经修改了Stackoverflow的代码,以消除问题,例如通过在过程范围内重新定义公共变量。
y3bcpkx12#
这是一个间歇性地困扰我自己的Excel插件为少数客户的问题。我已经在我的在线文档中记录了这个问题:VB Password Prompt。
在为一个客户处理一个特定的情况时,我想出了一个解决方案。我不知道它是否只适用于他的情况(只适用于我的机器),或者它是否适用于更广泛的情况。
在Workbook_BeforeClose事件的末尾插入行“ThisWorkbook.Saved = True”:
字符串
如果有人有机会尝试这个,你可以让我知道它是否对你和/或你的客户有帮助。
aor9mmx13#
DAO不是从Excel文件中阅读数据的好平台。
实际上,所有可用的Microsoft数据库驱动程序技术都不是这样的-它们都有一些内存泄漏,而较旧的技术会创建Excel.exe的隐藏示例-因此VBA项目中的任何内容(例如,缺少的库或调用非编译代码的事件)都将引发某种错误,使Excel认为您正在尝试访问代码。
下面是一些使用ADODB的代码,ADODB是一种较新的数据库技术,可以解决DAO的任何特定问题。
我还没来得及把所有与您的请求无关的内容都去掉--抱歉,内容太多了!--但是,保留所有这些可选的连接字符串可能对您很有帮助:遇到此类问题的任何人都需要稍微考虑一下,并通过反复试验找出哪种技术是有效的:
'strConnect = "ODBC;DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" _
' & "ReadOnly=1;DBQ=" & Chr(34) & SourceFile & Chr(34) & ";" _
' & ";Extended Properties=" &Chr(34) & "HDR=No;IMEX=1;MaxScanRows=0" & Chr(34) & ";"
'strConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Chr(34) & SourceFile & _
' Chr(34) & ";Extended Properties=" & Chr(34) & "Excel 8.0;" & strHeaders _
' & ";IMEX=1;MaxScanRows=0" & Chr(34) & ";"
strConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Chr(34) & SourceFile & _
Chr(34) & ";Persist Security Info=True;Extended Properties=" & _
Chr(34) & "Excel 8.0;" & strHeaders & ";IMEX=1;MaxScanRows=0" & Chr(34) & ";"
strConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Chr(34) & SourceFile & _
Chr(34) & ";Persist Security Info=True;Extended Properties=" & Chr(34) & _
"Excel 12.0 Xml;" & strHeaders & ";IMEX=1;MaxScanRows=0" & Chr(34) & ";"
'strConnect = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" & _
' "ReadOnly=1;DBQ=" & SourceFile & ";" & Chr(34) & SourceFile & Chr(34) & ";" & _
' ";Extended Properties=" & Chr(34) & "Excel 12.0;" & strHeaders & _
' ";IMEX=1;MaxScanRows=0" & Chr(34) & ";"
strConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Chr(34) & SourceFile & _
Chr(34) & ";Persist Security Info=True;Extended Properties=" & Chr(34) _
& "Excel 12.0 Macro;" & strHeaders & ";IMEX=1;MaxScanRows=0" & Chr(34) & ";"
'strConnect = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" & "ReadOnly=1; _
' DBQ=" & SourceFile & ";" & Chr(34) & SourceFile & Chr(34) & ";" & _
' ";Extended Properties=" & Chr(34) & "Excel 12.0;" & strHeaders & _
' ";IMEX=1;MaxScanRows=0" & Chr(34) & ";"
' This ACE driver is unstable on xlsb files... But it's more likely to return a result, if you don't mind crashes:
strConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Chr(34) & SourceFile & Chr(34) & _
";Persist Security Info=True;Extended Properties=" & Chr(34) & "Excel 12.0;" & _
strHeaders & ";IMEX=1;MaxScanRows=0" & Chr(34) & ";"
'SetTypeGuessRows
timeStart = VBA.Timer
Set objConnect = New ADODB.Connection
With objConnect
.ConnectionTimeout = TIMEOUT
.CommandTimeout = TIMEOUT
.Mode = adModeRead
End With
Set rst = New ADODB.Recordset
timeStart = VBA.Timer
If rst.State = 1 Then
End If
Set rst = Nothing
objConnect.Close
objConnect.Errors.Clear
Set objConnect = Nothing
Set rst = New ADODB.Recordset
rst.CursorLocation = adUseClient
rst.StayInSync = False
rst.Open CacheFile ', , adOpenStatic, adLockReadOnly, adCmdFile
StatusMessage = rst.RecordCount
Set FetchRecordsetFromWorkbook = rst
Set rst = Nothing
objConnect.Close
Set objConnect = Nothing
If (bFileIsOpen = False) And (FileIsOpen(SourceFile) = True) Then
For i = 1 To Application.Workbooks.Count
If Application.Workbooks(i).Name = Filename(SourceFile) Then
Application.Workbooks(i).Close False
Exit For
End If
Next i
End If
Exit Function
StatusMessage = ""
StatusMessage = StatusMessage & ""
If InStr(Err.Description, "not a valid name") Then
StatusMessage = StatusMessage & "Cannot read the data from your file: "
StatusMessage = StatusMessage & vbCrLf & vbCrLf
StatusMessage = StatusMessage & Err.Description
StatusMessage = StatusMessage & vbCrLf & vbCrLf
StatusMessage = StatusMessage & "It's possible that the file has been locked, _
but the most likely explanation is that the file _
doesn't contain the named sheet or range you're _
trying to read: check that you've saved the _
correct range name with the correct file name."
StatusMessage = StatusMessage & vbCrLf & vbCrLf
StatusMessage = StatusMessage & "If this error persists, please contact the Support team."
MsgBox StatusMessage, vbCritical, APP_NAME & ": data access error:"
StatusMessage = "#ERROR " & StatusMessage
ElseIf InStr(Err.Description, "Could not find the object '& SourceRange") Then
StatusMessage = StatusMessage & ""
StatusMessage = StatusMessage & ""
StatusMessage = StatusMessage & ""
MsgBox Err.Description & vbCrLf & vbCrLf & "Please contact the Support team. _
This error probably means that source _
file is locked, or that the wrong file _
has been saved here: " & vbCrLf & vbCrLf & _
strPathFull, vbCritical, APP_NAME & ": file data error:"
StatusMessage = "#ERROR " & StatusMessage
ElseIf InStr(Err.Description, "Permission Denied") Then
StatusMessage = StatusMessage & "Cannot open the file: "
StatusMessage = StatusMessage & vbCrLf & vbCrLf
StatusMessage = StatusMessage & vbTab & Chr(34) & strPathFull & Chr(34)
StatusMessage = StatusMessage & vbCrLf & vbCrLf
StatusMessage = StatusMessage & "Another user probably has this file open. _
Please wait a few minutes, and try again. _
If this error persists, please contact Desktop team."
MsgBox StatusMessage, vbCritical, APP_NAME & ": file access error:"
StatusMessage = "#ERROR " & StatusMessage
Else
StatusMessage = StatusMessage & "#ERROR " & Err.Number & ": " & Err.Description
MsgBox StatusMessage, vbCritical, APP_NAME & ": file data error:"
End If
Resume ExitSub
型
如果您在“_”拆分行周围遇到换行符问题,请深表歉意。
您还需要常量'APP_NAME'的声明:
型
和“Sleep”函数的VBA API声明:
型
在Microsoft Excel上运行SQL最好被认为是一件坏事:是的,SQL是迄今为止处理大量表格数据的最佳工具;但不,Microsoft不会很快修复这些内存泄漏。在雷德蒙,没有人对你试图在那里做什么感兴趣--当你可以购买一份MS-Access或SQL Server并将你的数据移植过来时,没有人感兴趣。
但是,如果您没有自己的SQL Server,而且在其他人的电子表格(或电子表格,复数形式)中有大量数据,那么这仍然是最好的解决方案。
So here's a Horrible Hack to read Excel with SQL的一个。
该条的副标题如下:
这是一个警示故事,讲述了开发人员不应该看到或做的事情,其中有商业逻辑的失败、变通办法和更坏的办法、预算精灵、商业分析师以及在电梯大厅寻求奇迹般治愈的淋巴结核朝圣者。
......你应该把它当作一个警告,告诉你将要面对的是什么:一场漫长而痛苦的代码争论,去做一些你可能本应该用其他方法去做的事情。
7tofc5zh4#
魔法!发送.xlsm附件到电子邮件。发送电子邮件给自己并下载附件。启动,启用Internet接收的内容,启用宏执行。问题消失。
hkmswyz65#
我认为退出Excel时出现的密码输入窗口只发生在规格较低的计算机上。
的数据
字符串
s1ag04yj6#
如
Miqi180
所述,当没有正确清除对工作簿的引用时会出现此问题;请参阅Microsoft Knowledge Database安装Office加载项时也可能发生此问题。存在一些已知问题:
6tdlim6h7#
在“引用”窗口中取消选中“OLE自动化”:
的数据