我已经做了很长一段时间了,我似乎无法弄明白。我正在尝试在excel中创建一个查询,该查询结合了excel表和数据库中的信息。我可以分别做他们每个人没问题。
以下是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
我想加入这些,因为数据库查询中有大约140,000个订单项,我只关心数据库中“item_id”字段与“Customer:”字段匹配的实例。 我只是无法弄清楚如何加入他们两个。我非常感谢你的帮助。
这是代码,我只是试图引入一个变量,它给出了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
答案 0 :(得分:1)
Yikes ......其中一些代码是......让我们称之为独一无二。但我不会提问,我们暂时处理您要问的问题。
目标是检查长项目字符串,这样您只需要一个Sql命令来获取数据。但是字符串必须是少于165个字符的块。
正如我之前提到的,这是一种草率的方式,但如果他们为了开发目的而将您从SQL数据库中锁定,这种方法将起作用:
您可以将Item字符串拆分为多个字符串,每个字符串少于165个字符。然后,您可以在SQL中使用OR
语句,将IN
函数用于包含数据的每个Item字符串。
首先,在您的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
然后,您可以进行处理以构建“项目”字符串。我假设它的逗号分隔如下:
Items = "'123456','234567'"
构建完成后,您可以:
' 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
然后,在将项目列表拆分为足够小的变量后,可以构建一个唯一的SQL字符串(称为SQLText)并插入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"
现在,String SQLText将包含您要发送到服务器的完整SQL代码。如果要验证字符串是否正确,可以执行此消息框:
MsgBox SQLText
您需要再做一次修改。当您调用数据库时,需要将变量SQLText放入commandtext数组(代替旧代码):
' 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
希望有所帮助:)
答案 1 :(得分:0)
运行Excel查询。
循环遍历结果集并构建OR条件列表,例如item_id ='ABC'或item_id ='PQR'等。
不使用IN条件,而是在单个大字符串中使用(巨大的)OR条件列表。
将此OR条件列表与查询的其余部分连接为数据库查询的Criterion。
虽然IN短语的长度可能有限制,但完整SQL语句的长度可能为higher。
当然,如果没有。将要出现在您的查询中的客户太大,这将有意想不到的问题,具体取决于它的大小。