2016-08-05 103 views
0

Wenn ich einen Aufruf zum Öffnen einer Verbindung zu einer anderen Arbeitsmappe aufrufen, wird gelegentlich die Arbeitsmappe vollständig in Excel geöffnet. Ich habe ~ 15 Datensätze, die ich mit dieser Methode ziehe, und konnte kein Muster identifizieren. gestern war die Aktualisierung schnell und nahtlos und es wurden keine Arbeitsmappen sichtbar in Excel geöffnet. Heute öffnet 1 von 2 in Excel.Excel VBA - Datenverbindung öffnet Arbeitsmappe sichtbar manchmal

Da ich Benutzer mit unterschiedlicher Erfahrung mit Excel habe, möchte ich dieses möglicherweise verwirrende Verhalten beseitigen.

oCnC.Open "Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Data Source=" & Filename & ";Extended Properties=""Excel 12.0; HDR=YES;"";" 

Beispielcode:

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 

Update 1

Ah-ha! Ich habe ein Update.

Nach dem letzten Test hatte ich die Arbeitsmappe offen gelassen. Als ich nach ein paar Minuten wieder zum Computer kam, gab es eine Meldung, dass die Datei zur Bearbeitung zur Verfügung stand. Möglicherweise liegt das intermittierende Verhalten daran, dass die angeforderte Datei von einem anderen Benutzer geöffnet wurde. Ich testete diese Theorie, indem ich die Arbeitsmappe schloss und dann die Subroutine erneut ausführte und die Datei in der App nicht öffnete.

Update 2 Qualifizierte meine Blätter Referenzen. Das Problem ist noch nicht gelöst.

+0

diejenigen, die nicht die Arbeitsmappe Öffnen halten nicht Hinzufügen. Es hält nur den Benutzer davon ab, es zu sehen, bis der Code ausgeführt wurde. – ghangas

+0

Ihr Update scheint mit einem Problem verbunden zu sein, bei dem eine Abfrage nur auf Bereiche zugreifen kann, die über die Zeile 65536 hinausgehen, wenn ich die Arbeitsmappe als schreibgeschützt geöffnet habe UND kein anderer Benutzer sie geöffnet hat. Wenn eine dieser beiden Bedingungen nicht erfüllt ist, sagt es mir, dass der Bereich nicht existiert. Aber ich denke, die Antwort, die die Comintern gerade geschrieben hat, wird Ihr Problem lösen. (Mein Problem wird wahrscheinlich eine Microsoft-Lösung erfordern. :() – YowE3K

+0

@ YowE3K - Ich überschreite nicht 65535 Zeilen. Ich ziehe 55000 oder weniger in beiden Abfragen. – ghangas

Antwort

0

Neben dem Code-Review von @Comintern angeboten und @ YowE3K fand ich eine Lösung in den folgenden:

  1. meine Arbeitsmappe Qualifizieren und meine Blätter
  2. Bildschirmaktualisierung deaktivieren (so können die Benutzer Ich sehe meine Magie)
  3. Werfen Sie die Buchnamen in ein Wörterbuch, bevor ich mein Update mache und alle Extras schließen, die während des Updates geöffnet wurden.

    Application.ScreenUpdating = False 
    For i = 1 To Application.Workbooks.count 
    Set dBooks(Application.Workbooks(i).Name) = i 
    Next i 
    Application.ScreenUpdating = False 
    

-Code von Frage

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 
0

Die Frage ist hier (und anderswo sind Sie Sheets ohne Objekt Referenz verwendet):

Set ws = Sheets(i) 
ws.Visible = xlSheetVisible 

Sheets ist eine weltweite Sammlung der Anwendung, die Arbeitsmappe nicht, dass der Code ausgeführt wird von . sie ausdrücklich die Spur zu kommen all diese unqualifizierten Referenzen und macht:

Set ws = ThisWorkbook.Sheets(i) 

Sie sollen auch hier optionale Parameter übergeben:

'SheetExists(i) 
'...should be... 
SheetExists(i, ThisWorkbook) 

Ich vermute, den Grund, diese intermittierend ist, ist, dass Sie fangen Instanzen, bei denen die andere Arbeitsmappe für die ADO-Verbindung aktiv ist und Ihre Verweise nicht auf die Stelle verweisen, an der sie ausgeführt werden sollen.

+0

I habe meine Frage mit meinem Code aktualisiert. Ich habe alle meine Tabellenreferenzen qualifiziert. Ich bekomme immer noch dieses Verhalten. – ghangas