web-dev-qa-db-ja.com

更新時のExcelデータ接続エラー

解決済み!解決策については以下を参照してください!

私はExcel2010で複数に接続しています、個別ピボットテーブルデータ接続を介してExcelから2010データベースにアクセスします。

すべての接続を更新すると、最後の更新が失敗します。順序は関係ありません。手動で別の順序で更新しました。同じエラーです。

ただし、数回更新してから保存して閉じてから、最後に戻って更新すれば、まったく問題ありません。

保存して閉じるとリセットされる、ある種のメモリキャップに達していると私は信じるようになります。

VBAを介してその効果を再現できますか実際に保存/閉じることなくこの問題に対するより良い解決策はありますか?

エラーメッセージ-これらの3つはこの順序でポップアップします:

  • クエリが実行されなかったか、データベーステーブルを開くことができませんでした。
  • データの取得に問題があります。
  • 接続を使用するピボットテーブル、キューブ関数、またはスライサーが更新に失敗しました。

現在のコード

Private Sub CommandButton1_Click()
On Error GoTo ErrHndlr

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.StatusBar = "Refreshing Data - Please Be Patient"

ActiveWorkbook.Connections("Connection_1").Refresh
ActiveWorkbook.Connections("Connection_2").Refresh
ActiveWorkbook.Connections("Connection_3").Refresh

Application.Calculation = xlCalculationAutomatic
Application.StatusBar = "Ready"
[LastUpdated].Value = FormatDateTime(Now, vbGeneralDate)
Application.ScreenUpdating = True
Exit Sub

ErrHndlr:
  Application.StatusBar = "Ready"
  Application.Calculation = xlCalculationAutomatic
  Application.ScreenUpdating = True
  [LastUpdated].Value = "Update Error"
  Exit Sub

End Sub

接続文字列

Provider=Microsoft.ACE.OLEDB.12.0
;User ID=Admin
;Data Source=C:\Folders\Database_1.accdb
;Mode=Share Deny None
;Extended Properties=""
;Jet OLEDB:System database=""
;Jet OLEDB:Registry Path=""
;Jet OLEDB:Engine Type=6
;Jet OLEDB:Database Locking Mode=0
;Jet OLEDB:Global Partial Bulk Ops=2
;Jet OLEDB:Global Bulk Transactions=1
;Jet OLEDB:New Database Password=""
;Jet OLEDB:Create System Database=False
;Jet OLEDB:Encrypt Database=False
;Jet OLEDB:Don't Copy Locale on Compact=False
;Jet OLEDB:Compact Without Replica Repair=False
;Jet OLEDB:SFP=False
;Jet OLEDB:Support Complex Data=False
;Jet OLEDB:Bypass UserInfo Validation=False

試みられた解決策

  • バックグラウンドリフレッシュを無効にする-すでに無効になっています
  • 自動回復を無効にする(メモリを節約するため)
  • 「スタックを元に戻す」をクリアします(メモリを節約するため)
  • 'DoEvents'は、各更新が完了するまでコードの実行を遅らせ、以下を変更します。

この

ActiveWorkbook.Connections("Connection_1").Refresh

With ActiveWorkbook.Connections("Connection_1")
  Select Case .Type
    Case xlConnectionTypeODBC
      With .ODBCConnection
        .Refresh
        Do While .Refreshing
          DoEvents
        Loop
      End With
    Case xlConnectionTypeOLEDB
      With .OLEDBConnection
        .Refresh
        Do While .Refreshing
          DoEvents
        Loop
      End With
    Case Else
      .Refresh
  End Select
End With

解決策!

ちなみに、このコードで更新したくない接続がいくつか追加され、更新したい接続を指定するための単純なロジックがいくつか追加されました。ここでのこのコードは、ブック内のすべての接続を更新するために機能します。

Dim i As Integer
Dim awc As WorkbookConnection
Dim c As OLEDBConnection

Set awc = ActiveWorkbook.Connections.Item(i)
Set c = awc.OLEDBConnection
c.EnableRefresh = True
c.BackgroundQuery = False
c.Reconnect
c.Refresh
awc.Refresh
c.MaintainConnection = False
Next i

なぜこれが機能するのか、詳細はわかりません。これにより、Excelが自己制限を乗り越えることができます。誰かがもっとよく知っているなら、もっと聞きたいです!

9
Aaron Contreras

これは完全な答えではありませんが、デバッグを支援する試みであり、解決策にたどり着くことができれば幸いです。

Connectionsをデバッグすることで、この問題を解決できると思います。上記のRefreshコード(およびDoEventsへの置き換え)を次のSubに置き換えてみてください。まず、更新の間にダイアログを表示すると問題が解決する可能性があります(問題が同時更新である場合など)。次に、実行するたびに、何も変更されていないことを注意深く確認します。発見や情報があれば報告してください。それでもエラーが発生する場合は、コードをステップ実行して、エラーが発生した行を報告してください。

Sub ShowDebugDialog()

   Dim x As Integer
   Dim i As Integer, j As Integer
   Dim awc As WorkbookConnection
   Dim c As OLEDBConnection

   For i = 1 To ActiveWorkbook.Connections.Count
   'For i = ActiveWorkbook.Connections.Count To 1 Step -1

      For j = 1 To ActiveWorkbook.Connections.Count
         Set awc = ActiveWorkbook.Connections.Item(j)
         Set c = awc.OLEDBConnection
         x = MsgBox("ConnectionName: " & awc.Name & vbCrLf & _
              "IsConnected: " & c.IsConnected & vbCrLf & _
              "BackgroundQuery: " & c.BackgroundQuery & vbCrLf & _
              "MaintainConnection: " & c.MaintainConnection & vbCrLf & _
              "RobustConnect: " & c.RobustConnect & vbCrLf & _
              "RefreshPeriod: " & c.RefreshPeriod & vbCrLf & _
              "Refreshing: " & c.Refreshing & vbCrLf & _
              "EnableRefresh: " & c.EnableRefresh & vbCrLf & _
              "Application: " & c.Application & vbCrLf & _
              "UseLocalConnection: " & c.UseLocalConnection _
              , vbOKOnly, "Debugging")
      Next j

      Set awc = ActiveWorkbook.Connections.Item(i)
      Set c = awc.OLEDBConnection
      c.EnableRefresh = True
      c.BackgroundQuery = False
      c.Reconnect
      c.Refresh
      awc.Refresh
      c.MaintainConnection = False
   Next i

End Sub

それでもエラーが発生する場合に回答できるその他の質問:

  • BackgroundQueryは常にfalseでしたか?
  • ダイアログの各セットの間に知覚可能な遅延がありましたか(Excelが更新の完了を待機していることを示します)、または最後のダイアログの直後にすべてが表示されましたか?
  • どのコード行で初期エラーが発生しますか?接続を逆の順序で更新すると(「ステップ-1」行のコメントを解除することにより)、同じ接続でエラーが発生しますか?
  • 接続を手動で更新できると言うとき、これは別のマクロを介してですか、それともデータ>>接続>>更新を介してですか?
  • 手動で「RefreshAll」を選択した場合、エラーはありますか?

すべての質問に申し訳ありませんが、このような厄介な接続エラーをデバッグするときは、すべてを考慮する必要があります。

2
ExactaBox

そのため、特定の時間にExcelブックを自動的に更新するVBAスクリプトを作成しようとしたときに同様のエラーが発生し、これを機能させるためにVBAスクリプトでいくつかのことを行いました。それらの1つはバックグラウンドリフレッシュを無効にするです。これは問題である可能性があり、接続プロパティに移動してバックグラウンドの更新を無効にすることで、簡単に無効にすることができます。

これは、このエラーが発生したときにVBAで行ったことですが、MSAccessデータベースでは使用していませんでした。 「ランナー」として使用したExcelワークブックが1冊あり、他のブックを1冊ずつ開いて、接続を更新しました。基本的に、pathextensionの変数があり、各ブックの名前を配列に入れて、配列をループしました。

パスと拡張子を組み合わせて、ファイルの完全なファイル名を取得しました。ループ内に表示されます。

これは私のループがどのように見えたかです:

For i = LBound(testArray) To UBound(testArray)
    Dim wb As Workbook
    Set wb = Workbooks.Open(path & testArray(i) & ext, 0, False)

    'Next I checked to see if the workbook was in protected view and allowed for editing.
    If Application.ProtectedViewWindows.Count > 0 Then
        Application.ActiveProtectedViewWindow.Edit
    End If

    'Now comes the part that I believe should help for your case
    wb.Connections(testArray(i) & "This is your connection name").OLEDBConnection.BackgroundQuery = False
    wb.RefreshAll
    wb.Connections(testArray(i) & "This is your connection name").OLEDBConnection.BackgroundQuery = True

    wb.SaveAs fileName:= "Thisbook.xlsx"
    wb.Close
Next i

接続名を取得するには、手動で何であるかを確認するなど、いくつかの方法があります。すべての接続名を手動で入力する必要がないように作成したかったので、接続名で見た固有のパターンを使用しました。

私の場合、それはbaseNameOfWorkbook & " POS Report"

バックグラウンドの更新が原因でエラーが発生している可能性があると思います。したがって、VBAでこれを行う必要がない場合は、接続プロパティに移動して無効にすることをお勧めします。

これが機能するかどうか教えてください。

3
Adjit

システムメモリをクリアするには、いつでも次のようなものを実行できます。

Sub ClearUndo()
Range("A1").Copy Range("A1")
End Sub

これにより、ピボットテーブルへのすべての更新を格納する元に戻すスタックがクリアされ、元に戻すことができます。参照の間にこれを行うと、メモリ使用量を制御し続けるのに役立つ場合があります。

Accessで役立つ解決策を考えていたので、以前の提案は無視してください。

0
pegicity

VBAを使用して、 activeworkbook 。connectionsオブジェクトを介して個別に更新を呼び出すことができます。このメソッドのいくつかの手がかりについては、 このStack Overflow post を参照してください。より原子論的なアプローチは、より良い洞察と制御を可能にするかもしれません。たとえば、すべての手順を実行したら、DoEventssolve 問題に挿入してみてください。

0
Smandoli