Excel VBA-数据连接有时会以可视方式打开工作簿
当我打电话打开与另一个工作簿的连接时,该工作簿偶尔会在Excel中完全打开。我用这种方法提取了约15个数据集,但我无法识别模式。昨天,刷新是快速而无缝的,没有任何工作簿在Excel中可见地打开。今天,第1页(共2页)将在Excel中打开 由于我的用户使用Excel的经验各不相同,我希望消除这种可能令人困惑的行为Excel VBA-数据连接有时会以可视方式打开工作簿,vba,excel,oledb,Vba,Excel,Oledb,当我打电话打开与另一个工作簿的连接时,该工作簿偶尔会在Excel中完全打开。我用这种方法提取了约15个数据集,但我无法识别模式。昨天,刷新是快速而无缝的,没有任何工作簿在Excel中可见地打开。今天,第1页(共2页)将在Excel中打开 由于我的用户使用Excel的经验各不相同,我希望消除这种可能令人困惑的行为 oCnC.Open "Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Data Source=" & Filename & ";E
oCnC.Open "Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Data Source=" & Filename & ";Extended Properties=""Excel 12.0; HDR=YES;"";"
示例代码:
sub Caller
Set dTabs = New Dictionary
Set dTabs("Cerner") = New Dictionary
dTabs("Cerner")("Query") = "Select Field1, Field2 from [Sheet1$]"
dTabs("Cerner")("Hidden") = 1
Call GetMasterTables("\\\Files\File1.xlsx", dTabs)
dTabs.RemoveAll
Set dTabs = New Dictionary
Set dTabs("SER") = New Dictionary
dTabs("SER")("Query") = "Select [1],F75 from [Sheet1$]"
dTabs("SER")("Hidden") = 1
Call GetMasterTables("\\Files\File2.xlsx", dTabs)
dTabs.RemoveAll
(Cleanup)
End Sub
Private Sub GetMasterTables(Filename As String, dTabset As Dictionary, ByRef wb As Workbook)
Dim oCnC As Connection
Dim rsC As Recordset
Dim rsE As Recordset
Dim lo As ListObject
Dim rngHome As Range
Set oCnC = New Connection
Set rsC = New Recordset
Set rsE = New Recordset
Dim ws As Worksheet
oCnC.Open "Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Data Source=" & Filename & ";" & _
"Extended Properties=""Excel 12.0; HDR=YES;"";"
rsC.ActiveConnection = oCnC
For Each i In dTabset
If SheetExists(i, wb) Then
Set ws = wb.Sheets(i)
ws.Visible = xlSheetVisible
Else
Set ws = wb.Sheets.Add(, wb.Sheets(wb.Sheets.count))
ws.Name = i
ws.Visible = xlSheetVisible
End If
Set rngHome = ws.Range("A1")
If RangeExists("Table_" & Replace(i, "-", "_"), ws) Then
Set lo = ws.ListObjects("Table_" & Replace(i, "-", "_"))
lo.DataBodyRange.Delete
Else
Set lo = ws.ListObjects.Add(, , , xlYes, rngHome)
lo.Name = "Table_" & Replace(i, "-", "_")
lo.DisplayName = "Table_" & Replace(i, "-", "_")
End If
If dTabset(i).Exists("Query") Then
rsC.Source = dTabset(i)("Query")
Else
rsC.Source = "Select * from [" & i & "$]"
End If
rsC.Open
rsC.MoveFirst
ws.Range(lo.HeaderRowRange.Offset(1, 0).address).Value = "hi"
lo.DataBodyRange.CopyFromRecordset rsC
rsC.MoveFirst
For Each j In lo.HeaderRowRange.Cells
j.Value = rsC.Fields(j.Column - 1).Name
Next j
rsC.Close
If dTabset(i).Exists("Hidden") Then
ws.Visible = xlSheetHidden
Else
ws.Visible = xlSheetVisible
End If
Next i
End Sub
Function SheetExists(ByVal shtName As String, Optional wb As Workbook) As Boolean
Dim sht As Worksheet
If wb Is Nothing Then Set wb = ActiveWorkbook
On Error Resume Next
Set sht = wb.Sheets(shtName)
On Error GoTo 0
SheetExists = Not sht Is Nothing
End Function
Function RangeExists(ByVal rngName As String, Optional ws As Worksheet) As Boolean
Dim rng As ListObject
If ws Is Nothing Then Set ws = ActiveWorksheet
On Error Resume Next
Set rng = ws.ListObjects(rngName)
On Error GoTo 0
RangeExists = Not rng Is Nothing
End Function
更新1
啊哈!我有最新消息
上一次考试后,我没有打开工作簿。几分钟后,当我回到电脑前时,有一个提示,提示我该文件可以编辑。可能间歇性行为是由于请求的文件被其他用户打开。我通过关闭工作簿,然后重新运行sub来测试这一理论,但它没有在应用程序中打开文件
更新2
限定我的参考资料。问题仍在发生。问题就在这里(以及您在没有对象引用的情况下使用工作表的任何其他地方):
工作表
是应用程序的全局集合,而不是运行代码的工作簿。追踪所有这些不合格的参考资料并使其明确:
Set ws = ThisWorkbook.Sheets(i)
您还应在此处传递可选参数:
'SheetExists(i)
'...should be...
SheetExists(i, ThisWorkbook)
我猜这是间歇性的原因是,您正在捕获ADO连接激活了其他工作簿的实例,并且您的引用没有指向它们应该指向的位置。问题就在这里(以及您使用的任何其他没有对象引用的工作表的地方):
工作表
是应用程序的全局集合,而不是运行代码的工作簿。追踪所有这些不合格的参考资料并使其明确:
Set ws = ThisWorkbook.Sheets(i)
您还应在此处传递可选参数:
'SheetExists(i)
'...should be...
SheetExists(i, ThisWorkbook)
我猜这是间歇性的原因是,您正在捕获ADO连接激活了其他工作簿的实例,并且您的引用没有指向它们应该指向的位置。除了@Comintern和@YowE3K提供的代码审阅之外,我还发现了以下解决方案:
鉴定我的工作手册和工作表
关闭屏幕更新(这样用户就看不到我的魔术)
在我进行更新之前,将书名放入字典中,并关闭更新期间打开的所有附加功能
Application.ScreenUpdating = False
For i = 1 To Application.Workbooks.count
Set dBooks(Application.Workbooks(i).Name) = i
Next i
Application.ScreenUpdating = False
问题代码
For i = 1 To Application.Workbooks.count
If dBooks.Exists(Application.Workbooks(i).Name) Then
dBooks.Remove (Application.Workbooks(i).Name)
Else
dBooks(Application.Workbooks(i).Name) = i
End If
Next i
For Each bookname In dBooks
Application.Workbooks(bookname).Close (False)
Next
Application.ScreenUpdating = True
除了@Comintern和@YowE3K提供的代码审查外,我还发现了以下解决方案:
鉴定我的工作手册和工作表
关闭屏幕更新(这样用户就看不到我的魔术)
在我进行更新之前,将书名放入字典中,并关闭更新期间打开的所有附加功能
Application.ScreenUpdating = False
For i = 1 To Application.Workbooks.count
Set dBooks(Application.Workbooks(i).Name) = i
Next i
Application.ScreenUpdating = False
问题代码
For i = 1 To Application.Workbooks.count
If dBooks.Exists(Application.Workbooks(i).Name) Then
dBooks.Remove (Application.Workbooks(i).Name)
Else
dBooks(Application.Workbooks(i).Name) = i
End If
Next i
For Each bookname In dBooks
Application.Workbooks(bookname).Close (False)
Next
Application.ScreenUpdating = True
添加这些不会阻止工作簿打开。它只是让用户在代码运行之前看不到它打开。您的更新似乎与我遇到的问题有关,如果我以只读方式打开工作簿,而没有其他用户打开工作簿,则查询只能访问超出第65536行的范围。如果这两个条件中的任何一个不满足,它会告诉我范围不存在。但是我认为共产国际刚刚发布的答案会解决你的问题。(我的问题可能需要Microsoft解决方案。:()@YowE3K-我的行数不超过65535行。我在两个查询中的行数都不超过55000行。抱歉-我不是说您访问的行数超过了65536行(这不是范围内的行数,而是范围的位置)-只是您的问题与是否有其他用户(或您自己)有关正在同时使用查询的工作簿,并且ADO显示出不同的行为(如果是)。哦,是的。现在我正在跟踪您。我想可能就是这样,所以我一直在搜索连接字符串中的选项,以尝试强制执行我要找的行为。目前为止运气不好。添加这些选项不会阻止工作簿打开。它只会保持直到代码运行后,用户才看到工作簿打开。您的更新似乎与我遇到的问题有关,如果我以只读方式打开工作簿,并且没有其他用户打开工作簿,则查询只能访问超出第65536行的范围。如果这两个条件中的任何一个不满足,则会告诉我该范围不存在。但我认为共产国际刚刚发布的答案将解决您的问题。(我的问题可能需要Microsoft解决方案。:()@YowE3K-我没有超过65535行。我在两个查询中都使用了55000行或更少。抱歉-我不是说您访问了65536行以外的内容(这不是范围中的行数,而是范围的位置)-只是您的问题与是否有其他用户(或您自己)有关正在同时使用查询的工作簿,并且ADO显示出不同的行为(如果是)。哦,是的。现在我正在跟踪您。我认为可能就是这样,所以我一直在搜索连接字符串中的选项,以尝试强制执行我要找的行为。到目前为止运气不好。我已经用代码更新了我的问题。我已经验证了我所有的代码eets引用。我仍有此行为。我已用代码更新了我的问题。我已对所有工作表引用进行了限定。我仍有此行为。