Excel VBA-数据连接有时会以可视方式打开工作簿

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

当我打电话打开与另一个工作簿的连接时,该工作簿偶尔会在Excel中完全打开。我用这种方法提取了约15个数据集,但我无法识别模式。昨天,刷新是快速而无缝的,没有任何工作簿在Excel中可见地打开。今天,第1页(共2页)将在Excel中打开

由于我的用户使用Excel的经验各不相同,我希望消除这种可能令人困惑的行为

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引用。我仍有此行为。我已用代码更新了我的问题。我已对所有工作表引用进行了限定。我仍有此行为。