Excel'de bana aşağıdaki fonksiyonu verecek bir excel makrosu yapmaya çalışıyorum:
=SQL("SELECT heading_1 FROM Table1 WHERE heading_2='foo'")
SQL sorgularını kullanarak Çalışma Kitabımdaki Tablolarda veri aramama (ve hatta belki de eklememe) izin veriyor.
Şimdiye kadar yaptığım şey bu:
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
Komut dosyam, yukarıdaki kod parçasında olduğu gibi sabit kodlanmış aralıklarla bir cazibe gibi çalışır. Ayrıca statik adlandırılmış aralıklarla da çok iyi çalışır.
Ancak, benim için en önemli olan dinamik adlandırılmış aralıklar veya TABLO ADLARI ile çalışmaz.
Bulabildiğim en yakın cevap aynı dertten muzdarip bu adam: http://www.ozgrid.com/forum/showthread.php?t=72973
Yardım edecek kimse yok mu?
Edit
Bunu şimdiye kadar pişirdim, daha sonra SQL sorgularımda ortaya çıkan adı kullanabilirim. Sınırlama şu ki, tabloların hangi sayfada olduğunu bilmem gerekiyor. Bu konuda bir şey yapabilir miyiz?
Function getAddress()
myAddress = Replace(Sheets("Sheet1").Range("Table1").address, "$", "")
myAddress = "[Sheet1$" & myAddress & "]"
getAddress = myAddress
End Function
Teşekkürler!
Yapabileceğiniz bir şey, dinamik adlandırılmış aralığın adresini almak ve bunu SQL dizenizde girdi olarak kullanmaktır. Şunun gibi bir şey:
Sheets("shtName").range("namedRangeName").Address
Bu da $A$1:$A$8
gibi bir adres dizesi çıkaracaktır.
Düzenle:
Aşağıdaki yorumumda da belirttiğim gibi, tam adresi (sayfa adı dahil) dinamik olarak alabilir ve doğrudan kullanabilir ya da daha sonra kullanmak üzere sayfa adını ayrıştırabilirsiniz:
ActiveWorkbook.Names.Item("namedRangeName").RefersToLocal
Bu da =Sheet1!$C$1:$C$4
gibi bir dizeyle sonuçlanır. Yani yukarıdaki kod örneğiniz için SQL ifadeniz şöyle olabilir
strRangeAddress = Mid(ActiveWorkbook.Names.Item("namedRangeName").RefersToLocal,2)
strSQL = "SELECT * FROM [strRangeAddress]"
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'inizde şu şekilde kullanın
sSQL = "Select * from " & GetRange("NameOfTable") & ""
Başkasının kodu üzerinde çalışan bir acemiyim, bu yüzden lütfen hoşgörülü olun ve hatalarımı düzeltin. Kodunuzu denedim ve VBA yardımı ile oynadım Aşağıdakiler bende çalıştı:
Function currAddressTest(dataRangeTest As Range) As String
currAddressTest = ActiveSheet.Name & "$" & dataRangeTest.Address(False, False)
End Function
İşlevim için veri kaynağı bağımsız değişkenini seçtiğimde, Sayfa1$A1:G3 biçimine dönüştürülüyor. Excel formülümde bunu Tablo1[#Tüm] başvurusu olarak değiştirirse, işlev yine de düzgün çalışır
Daha sonra bunu işlevinizde kullandım (oynamaya ve WHERE'e enjekte edilecek başka bir argüman eklemeye çalıştım...
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
Umarım işleviniz daha da gelişir, çok faydalı buluyorum. İyi günler dilerim!