2017-08-16 7 views
0

私はかなり長い間この問題に取り組んできました。私はエクセルテーブルとデータベースからの情報を組み合わせたエクセルでクエリを作成しようとしています。私はそれぞれ別々に問題なく処理することができます。ここでExcelテーブルとSQLデータベースの両方からデータを取得するVBAクエリ

は、ExcelクエリのVBAコードです:

Sub ExcelQuery() 
' 
    Range("Table_Query_from_Excel_Files5[[#Headers],[Customer:]]").Select 
    With Selection.ListObject.QueryTable 
     .Connection = Array(Array("ODBC;DSN=Excel Files;DBQ=Z:\OEM Office\Trevor Weinrich\Projects\BOM Template 2.0\BOM template 2017-08-16 1.xlsm;DefaultDir=Z:\OEM Office\Trevor Weinrich\Projects\BOM Template 2.0;DriverId=1046;MaxBufferSize=2048;PageTimeout=5;")) 
     .CommandText = Array(_ 
     "SELECT `BOM$`.`Customer:`" & Chr(13) & "" & Chr(10) & "FROM `BOM$` `BOM$`" & Chr(13) & "" & Chr(10) & "WHERE (`BOM$`.`Customer:` Is Not Null)" _ 
     ) 
     .Refresh BackgroundQuery:=False 
    End With 
' 
End Sub 

そしてここでは、データベースクエリのためのVBAコードです:

Sub DatabaseQuery() 
' 
    With Selection.ListObject.QueryTable 
     .Connection = _ 
     "ODBC;DSN=OEM;Description=OEM;UID=trevor.weinrich;Trusted_Connection=Yes;APP=Microsoft Office 2016;WSID=DFP-OEM-0913-A;DATABASE=OEM" 
     .CommandText = Array(_ 
     "SELECT DISTINCT p21_view_item_uom.item_id, p21_view_item_uom.unit_of_measure, p21_view_item_uom.purchasing_unit" & Chr(13) & "" & Chr(10) & "FROM OEM.dbo.p21_view_item_uom p21_view_item_uom" & Chr(13) & "" & Chr(10) & "WHERE (p21_view_item_uom.delete_flag=" _ 
     , "'N')" & Chr(13) & "" & Chr(10) & "ORDER BY p21_view_item_uom.item_id") 
     .Refresh BackgroundQuery:=False 
    End With 
' 
End Sub 

14万があるので、私は一緒にこれらに参加したいですデータベースの「item_id」フィールドと「Customer:」フィールドが一致するインスタンスのみが対象です。 私はちょうどそれらの2つを結合する方法を把握することができません。私は大いに助けに感謝します。ここで

は、私はちょうど165個の文字の後に私にエラーを与える変数に引っ張るしようとしているコードです:

Sub Update_Item_Tables() 
' 
' UOM_Update Macro 
' 
Dim Items As String 
Items = Sheets("UOM").Range("K1").Value 

    Sheets("UOM").Visible = True 
    Sheets("UOM").Select 
    Range("Table_Query_from_OEM[[#Headers],[item_id]]").Select 
    With Selection.ListObject.QueryTable 
     .Connection = _ 
     "ODBC;DSN=OEM;Description=OEM;UID=trevor.weinrich;Trusted_Connection=Yes;APP=Microsoft Office 2016;WSID=DFP-OEM-0913-A;DATABASE=OEM" 
     .CommandText = Array(_ 
     "SELECT DISTINCT p21_view_item_uom.item_id, p21_view_item_uom.unit_of_measure, p21_view_item_uom.purchasing_unit" & Chr(13) & "" & Chr(10) & _ 
     "FROM OEM.dbo.p21_view_item_uom p21_view_item_uom" & Chr(13) & "" & Chr(10) & _ 
     "WHERE (p21_view_item_uom.item_id In (" _ 
     , _ 
     "" & Items & ")) AND (p21_view_item_uom.delete_flag='N')" & Chr(13) & "" & Chr(10) & _ 
     "ORDER BY p21_view_item_uom.purchasing_unit DESC" _ 
     ) 
     .Refresh BackgroundQuery:=False 
    End With 

End Sub 
+1

役立つことクエリは、データベースとExcelの両方に同時に適用されます。ただし、各クエリのデータを別々のDataTableに取得し、結果をマージできます。 – vintastic

+3

ExcelのデータをSQLのテーブルに挿入し、アプリケーションに参加しようとするよりも、そこに参加する方が良いかもしれません。 –

+0

私は実際にSQLにデータを挿入することについて何も知らない。私が引っ張っているデータは私の会社のMRPシステムからです。 – TWeinrich

答えて

0

は、Excelのクエリを実行します。

結果セットをループし、item_id = 'ABC'またはitem_id = 'PQR'などのOR条件のリストを作成します。

IN条件を使用する代わりに、1つの大きな文字列にOR条件の(巨大な)リストを使用します。

このOR条件のリストを残りのクエリと連結して、データベースクエリの条件として連結します。

IN句の長さに制限がありますが、完全なSQL文の長さはhigherです。

もちろん、クエリに表示される顧客の数が多すぎると、その規模によって予期しない問題が発生します。

1

イーグルス...そのコードの一部は...それをユニークと呼ぶことにしましょう。しかし、私は質問をしません。あなたが今質問している問題にちょうど対処できます。

目的は、データを取得するために1つのSqlコマンドが必要なので、長いItems文字列をチェックすることです。しかし、文字列は165文字未満の塊である必要があります。

私は前に述べたように、これはそれを行うためのずさんな方法ですが、彼らはあなたが開発目的のために、あなたのSQLデータベースからロックアウトされている場合は、このアプローチは動作します:

あなたが複数にあなたの項目の文字列を分割することができますそれぞれ165文字未満の文字列。次に、SQLにORステートメントを使用して、データを持つ各Item文字列にIN関数を使用できます。

まず、あなたのVBAで、あなたがする必要があります。

'Delcare your Variables 

Dim SQLText As String 
Dim Items2 As String 
Dim Items3 As String 
Dim boolItemFlag2 As Boolean 
Dim boolItemFlag3 As Boolean 
Dim i As Integer 

' Initialize Variables 

boolItemFlag2 = False 
boolItemFlag3 = False 

次に、あなたはあなたの「アイテム」の文字列を構築するためにあなたの処理を行うことができます。することができます、あなたのアイテムのリストがそれぞれ十分に小さい変数に分割した後、次に

' Get your Items list and check for length over 164 

If Not IsNull(Len(Items)) Then 
    If Len(Items) > 164 Then 
     boolItemFlag2 = True 
     i = 0 

     ' Find last comma delimiter before the cut off of 164 

     While (Mid(Items, 164 - i, 1) <> ",") 
     i = i + 1 
     Wend 

     ' Set Items2 to everything after the last comma (before pos 164). Then Left Trim away possible spaces. 

     Items2 = LTrim(Mid(Items, 164 - i + 1, Len(Items) - 164 + i)) 

     ' Reset Items to everything up to that comma we found but not including it. 

     Items = Left(Items, 164 - i - 1) 

     ' Your Item list is now split into 2 different string variables 

    End If 
End If 

If Not IsNull(Len(Items2)) Then 
    If Len(Items2) > 164 Then 
     boolItemFlag3 = True 
     ' Use the same logic above to split Items2 into the Items3 variable. 
     ' You may need to duplicate again for Items4 etc if your Item List is huge. 
     ' If you'd need beyond Items5, I'd probably go back to the two query approach. 
     ' But it's your choice. 
    End If 
End If 

Items = "'123456','234567'" 

それが組み込まれている後にすることができます:私はそれがコンマはこのような何かを区切りだと仮定しています(SQLTEXTと呼ばれる)のユニークなSQL文字列を構築し、データを持っている項目の文字列が含まれるようにOR文を挿入します。

' Build your SQL String Here (after you have determined how many item strings you have) 

SQLText = "SELECT DISTINCT p21_view_item_uom.item_id, p21_view_item_uom.unit_of_measure, p21_view_item_uom.purchasing_unit" & Chr(13) & "" & Chr(10) & _ 
    "FROM OEM.dbo.p21_view_item_uom p21_view_item_uom" & Chr(13) & "" & Chr(10) & _ 
    "WHERE (p21_view_item_uom.item_id In (" _ 
    & _     ' <-- I changed your comma into an & because I have no clue... 
    "" & Items & ")" 

If boolItemFlag2 Then ' Add this OR statement if Items2 has data 
    SQLText = SQLText & " OR p21_view_item_uom.item_id In (" & Items2 & ")" 
End If 

If boolItemFlag3 Then ' Add this OR statement if Items3 has data 
    SQLText = SQLText & " OR p21_view_item_uom.item_id In (" & Items3 & ")" 
End If 

' Add more OR statements if you have Item lists beyond 3. 

' Now tack on your remaining SQL code: 

SQLText = SQLText & ") AND (p21_view_item_uom.delete_flag='N')" & Chr(13) & "" & Chr(10) & _ 
    "ORDER BY p21_view_item_uom.purchasing_unit DESC" 

今、文字列SQLTEXTは、あなたの完全なを持っていますSQLコードをサーバーに送信します。文字列が正しいことを確認する場合は、このメッセージボックスを実行できます。

MsgBox SQLText 

さらに修正する必要があります。あなたがデータベースを呼び出すとき、あなたは(あなたの古いコードの代わりに)CommandTextを配列に変数SQLTEXTを配置する必要があります。

' Now you can put your SQLText variable into your ODBC call: 

With Selection.ListObject.QueryTable 
    .Connection = _ 
"ODBC;DSN=OEM;Description=OEM;UID=trevor.weinrich;Trusted_Connection=Yes;APP=Microsoft Office 2016;WSID=DFP-OEM-0913-A;DATABASE=OEM" 
    .CommandText = Array(SQLText) 
    .Refresh BackgroundQuery:=False 
End With 

希望私はあなたが作成できるとは思わない:)

関連する問題