2013-11-03 96 views
22

我試圖讓一個Excel宏,這將使我在Excel中下列功能的工作簿中的SQL查詢:在Excel表執行使用VBA宏

=SQL("SELECT heading_1 FROM Table1 WHERE heading_2='foo'") 

讓我搜索(甚至插入)數據在我的工作簿的表中使用SQL查詢。

這是我迄今所做的:

Sub SQL() 

Dim cn As ADODB.Connection 
Dim rs As ADODB.Recordset 

strFile = ThisWorkbook.FullName 
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile _ 
& ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"";" 

Set cn = CreateObject("ADODB.Connection") 
Set rs = CreateObject("ADODB.Recordset") 

cn.Open strCon 

strSQL = "SELECT * FROM [Sheet1$A1:G3]" 

rs.Open strSQL, cn 

Debug.Print rs.GetString 

End Sub 

我的腳本可以像硬編碼範圍魅力,如一個在上面的代碼片段。它也適用於靜態命名範圍。

但是,它不適用於對我來說最重要的動態命名範圍或表名。

最近我已經找到答案的,這傢伙是從同一個痛苦的痛苦: http://www.ozgrid.com/forum/showthread.php?t=72973

幫助的人?

編輯

我迄今熟這個,然後我可以在我的SQL查詢中使用所產生的名字。限制是我需要知道表格是在哪張紙上。我們可以做些什麼嗎?

Function getAddress() 

    myAddress = Replace(Sheets("Sheet1").Range("Table1").address, "$", "") 
    myAddress = "[Sheet1$" & myAddress & "]" 

    getAddress = myAddress 

End Function 

謝謝!

+0

也許它不會有很大的區別,但我認爲自定義函數必須是一個函數(而不是一個子)。此外,在自定義函數的結尾處,您應該有類似於SQL = theAnswerToDisplayInCell' 但這可能與您的問題無關。 –

+0

@JakeB。你是絕對正確的,謝謝。 –

回答

10

您可以做的一件事就是獲取動態命名範圍的地址,並將其用作SQL字符串中的輸入。喜歡的東西:

Sheets("shtName").range("namedRangeName").Address 

這將吐出的地址字符串,像$A$1:$A$8

編輯:

正如我說我下面的評論,你可以動態地得到完整的地址(包括並直接使用它或解析表名以備後用:

ActiveWorkbook.Names.Item("namedRangeName").RefersToLocal 

哪個res在像=Sheet1!$C$1:$C$4這樣的字符串中。因此,對於你上面的代碼示例,您的SQL語句可能是

strRangeAddress = Mid(ActiveWorkbook.Names.Item("namedRangeName").RefersToLocal,2) 

strSQL = "SELECT * FROM [strRangeAddress]" 
+0

任何機會,我們可以做到這一點沒有表名作爲輸入? 人不是一個真正的無賴,你不能只使用該表的名稱與ADODB連接? VBA是相當薄弱的,但我必須遵守企業界的規則:) –

+1

假設你知道命名範圍的名稱(如果你不這樣做的話會擊敗目的),你可以使用它來代替.Address:當我使用'strRangeAddress = Mid(ActiveWorkbook.Names.Item(「namedRangeName」)。RefersToLocal'時會吐出一個字符串,例如'= Sheet1!$ C $ 1:$ C $ 4' –

+0

當我使用'strRangeAddress = Mid(ActiveWorkbook.Names.Item(「namedRangeName」 ).RefersToLocal,2)'並運行strSQL我得到一個錯誤消息'Sheet1!$ C $ 1:$ C $ 4不是一個有效的名字。誰能幫我? –

2

我是一個初學者在別人的代碼修修補補所以請手下留情,並進一步糾正我的錯誤。我想你的代碼,並與VBA幫助,我下面的工作發揮:

Function currAddressTest(dataRangeTest As Range) As String 

    currAddressTest = ActiveSheet.Name & "$" & dataRangeTest.Address(False, False) 

End Function 

當我選擇我的功能數據源的說法,它變成工作表Sheet1 $ A1:G3格式。如果excel將其更改爲我公式中的Table1 [#All]引用,該函數仍可正常工作

然後我在函數中使用它(嘗試播放並添加另一個參數以注入WHERE ...

Function SQL(dataRange As Range, CritA As String) 

Dim cn As ADODB.Connection 
Dim rs As ADODB.Recordset 
Dim currAddress As String 



currAddress = ActiveSheet.Name & "$" & dataRange.Address(False, False) 

strFile = ThisWorkbook.FullName 
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile _ 
& ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"";" 

Set cn = CreateObject("ADODB.Connection") 
Set rs = CreateObject("ADODB.Recordset") 

cn.Open strCon 


strSQL = "SELECT * FROM [" & currAddress & "]" & _ 
     "WHERE [A] = '" & CritA & "' " & _ 
     "ORDER BY 1 ASC" 

rs.Open strSQL, cn 

SQL = rs.GetString 

End Function 

希望你的功能有更進一步的發展,我覺得它非常有用。祝你今天愉快!

8
Public Function GetRange(ByVal sListName As String) As String 

Dim oListObject As ListObject 
Dim wb As Workbook 
Dim ws As Worksheet 

Set wb = ThisWorkbook 

For Each ws In wb.Sheets 
    For Each oListObject In ws.ListObjects 
     If oListObject.Name = sListName Then 
      GetRange = "[" & ws.Name & "$" & Replace(oListObject.Range.Address, "$", "") & "]" 
     Exit Function 
     End If 
    Next oListObject 
Next ws 


End Function 

在SQL使用這樣

sSQL = "Select * from " & GetRange("NameOfTable") & "" 
+0

這個答案的要點是地址應該看起來像這樣「Sheet1 $ A1:X10」。 1)在工作表名稱和範圍之間加上$,2)在範圍內本身沒有$。這在第一個最受歡迎的答案中是缺失的。 –

+0

順便說一句,將範圍名稱放入括號** [] **也非常重要。 '「Select * from [Sheet1 $ A1:A200]」' –

1

只是回答你問題的第二部分,關於得到的片,其中一個表的名稱:

Dim name as String 

name = Range("Table1").Worksheet.Name 

編輯:

爲了使事情更清楚:有人建議使用Sheet對象上的Range。在這種情況下,你不需要;可以使用表格的名稱獲取表格所在的範圍;這個名字在整本書中都有提供。所以,單獨調用Range就行得通。

-1

嗨最近調查了這一點,如果你把一個後綴中的Excel

曾引用命名錶(列表對象)的問題表格名稱上的'$'全部在世界上都很好

Sub testSQL() 

    Dim cn As ADODB.Connection 
    Dim rs As ADODB.Recordset 

    ' Declare variables 
    strFile = ThisWorkbook.FullName 

    ' construct connection string 
    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile _ 
    & ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"";" 

    ' create connection and recordset objects 
    Set cn = CreateObject("ADODB.Connection") 
    Set rs = CreateObject("ADODB.Recordset") 

    ' open connection 
    cn.Open strCon 

    ' construct SQL query 
    strSQL = "SELECT * FROM [TableName$] where [ColumnHeader] = 'wibble';" 

    ' execute SQL query 
    rs.Open strSQL, cn 

    Debug.Print rs.GetString 

    ' close connection 
    rs.Close 
    cn.Close 
    Set rs = Nothing 
    Set cn = Nothing 
End Sub 
+0

OP已經將'$'附加到'TableName' ...'SELECT * FROM [Sheet1 $ A1:G3]「'這不是問題這裏。 – Bugs

+0

但我沒有使用工作表名稱只是在Excel中設置的實際表名稱,沒有$查詢抱怨說它無法找到對象'TableName'與$它返回數據 – MikeL

+0

以下,我有一些混合使用實際列標題名稱得到'沒有爲一個或多個必需參數給出的值'消息的結果,但使用[F1]格式的索引列1 [F2]列2等工作起來就像一個魅力 – MikeL

1

基於Joan-Diego Rodriguez的Jordi方法和一些Jacek Kotowski代碼的例程 - 該函數將活動工作簿的任何表名轉換爲SQL查詢的可用地址。

MikeL的注意事項:添加「[#All]」包括避免報告問題的標題。

Function getAddress(byVal sTableName as String) as String 

    With Range(sTableName & "[#All]") 
     getAddress= "[" & .Parent.Name & "$" & .Address(False, False) & "]" 
    End With 

End Function 
+0

這需要12行從上面的答案代碼,並重構到3.工作做得很好 – pheeper