34

我正在尝试制作一个 excel 宏,它将在 Excel 中为我提供以下功能:

=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

谢谢!

4

8 回答 8

15

您可以做的一件事是获取动态命名范围的地址,并将其用作 SQL 字符串中的输入。就像是:

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

这会吐出一个地址字符串,比如$A$1:$A$8

编辑:

正如我在下面的评论中所说,您可以动态获取完整地址(包括工作表名称)并直接使用它或解析工作表名称以供以后使用:

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

这会产生一个字符串,如=Sheet1!$C$1:$C$4. 因此,对于上面的代码示例,您的 SQL 语句可能是

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

strSQL = "SELECT * FROM [strRangeAddress]"
于 2013-11-03T17:50:30.610 回答
9
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") & ""
于 2015-10-20T11:20:31.450 回答
6

以 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
于 2017-07-18T18:02:13.700 回答
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

希望您的功能进一步发展,我觉得它非常有用。祝你今天过得愉快!

于 2015-03-05T13:55:21.677 回答
2

只需回答有关获取表格所在工作表名称的问题的第二部分:

Dim name as String

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

编辑:

为了让事情更清楚:有人建议在 Sheet 对象上使用 Range 。在这种情况下,您不需要;可以使用表名获取表所在的范围;这个名字在整本书中都有。因此,单独调用 Range 效果很好。

于 2016-06-02T07:08:23.967 回答
0

只是想在此处添加,您可以将您的范围设为命名范围并在查询中使用它(如果每张工作表有一个表,则可以使用整个工作表)。

所以你可以使用:

SELECT * FROM MyNamedRange

或者

SELECT * FROM [Sheet1$]

当我在历史上所做的只是将所有表设置为命名范围并直接在查询中引用它们时,许多这些答案似乎都用于解析地址(也使其更清晰)。

在下面我更复杂的查询之一中,我引用的所有范围都是命名范围:

SELECT Unit_Type AS [Unit Type], COUNT(*) AS [Number of Units], SQFT, Deposit AS [Deposit{$}], Rent AS [Base Rent{$}], SUM(RENT) AS [Base Rent Total{$}], SUM(MR) AS [Market Rent Total{$}] FROM
(
    SELECT f1.Unit_Code, Unit_Type, SQFT, Rent, Deposit, SWITCH(MR IS NULL,Rent,MR IS NOT NULL,MR) AS MR FROM
    (   
        SELECT t2.Unit_Code, t2.Unit_Type, SQFT, Rent, Deposit FROM
        (
            SELECT DISTINCT Unit_Code, Unit_Type
            FROM CommUnits
            WHERE Unit_Code NOT LIKE "%WAIT%" AND Exclude=0
        ) t2
        LEFT JOIN
        (
            SELECT UnitType_Code, SQFT, Rent, Deposit
            FROM ResUnitTypes
        ) t1 ON (t1.UnitType_Code = t2.Unit_Type)
    ) f1
    LEFT JOIN
    (
        SELECT Unit_Code, SUM(Current_Charge) AS MR
        FROM ResUnitAmenities
        WHERE Unit_Code NOT LIKE "%WAIT%"
        GROUP BY Unit_Code
    ) f2 on (f1.Unit_Code = f2.Unit_Code)
)
GROUP BY Unit_Type, SQFT, Deposit, Rent
于 2022-02-25T15:49:09.487 回答
0

嗨,最近对此进行了调查,并且在引用 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
于 2017-04-10T12:43:27.893 回答
-3

找到了这个,它对我有用。

strSQL = "SELECT * FROM DataTable" 

'其中 DataTable 是命名范围

如何在 Excel 工作表中的命名范围上运行 SQL 语句?

于 2017-01-25T20:02:24.103 回答