【问题标题】:VBA Access getting RowSource to find lookup valuesVBA Access 获取 RowSource 以查找查找值
【发布时间】:2013-08-21 20:50:48
【问题描述】:

这里是 VBA 新手(截至本次哀悼),

在 MS Access 中,我编写了一个测试函数,用于根据您传入的某些条件查找记录的值。

该功能似乎工作正常,除非在我正在搜索的列中有查找。

基本上它可能会返回“19”,而 19 对应于其他一些表值。

似乎该列的 RowSource 是我之后的内容,因此我可以进行第二次查询以找到真实值。

假设我知道列名,然后利用它来查找我之后的值,有人可以指出我找到 RowSource 的正确方向吗?

编辑:我似乎没有清楚地解释自己,这是我试图以编程方式获得的图片

【问题讨论】:

  • 不太确定我是否正确理解了您的问题,但我尝试了您的代码并且它有效。我想知道您的问题是否不在于您的 SELECT 实际上带回了不止一行,并为您提供了与您预期不同的值。你的recordSet 只会给你第一条记录。要移至下一个,您可以使用recordSet.MoveNext。尝试在查询中运行 SELECT,看看它是否只带回一行。如果是这样,请尝试更详细地解释问题。
  • 附带说明-如果没有任何结果,您将遇到麻烦-因此您还需要进行检查,例如If Not recordSet.EOF Then result = recordSet(column)
  • 我添加了图片来更清楚地解释 myslef 哈哈
  • 您指向的“RowSource”只是一个查询,用于填充打开该表时显示的组合框。我看不到 RowSource 将如何帮助您从函数中获取正确的值。在您的lookUpColumnValue 函数中,在sql = "SELECT... 行之后,请尝试添加另一行:MsgBox sql,并让我们知道您在运行代码时会显示什么SQL 语句。此外,尝试创建一个新查询并运行该 SQL 语句,并向我们展示结果。我认为这应该会有所帮助。
  • SELECT [FI - ROOM].[Main Space Category] ​​FROM [FI - ROOM] WHERE [FI - ROOM].[Room No] = [parm1] ----- 我认为我需要知道行源是什么,以便在运行此查询并获取数值后,我可以运行行源查询以获取它查找的字符串值。

标签: ms-access vba lookup-tables


【解决方案1】:

试试这个——我想我终于明白你为什么要寻找 RowSource——抱歉,我一开始没有“明白”它。您尝试提取的字段是描述表中的外键。

此函数应作为所有此类字段的通用解决方案(假设 RowSource 始终首先具有主键,然后是描述)。如果没有 RowSource,它只会拉取字段的值。

它基于您的原始代码,而不是 @ron 提出的更改,但它应该为您指明正确的方向。您应该修复它以使其参数化,并允许变体数据类型,正如 ron 建议的那样 (+1 ron)

顺便说一句,在 VBA 中使用 & 符号 (&) 将字符串连接在一起,以避免出现以下情况:abc = "1" + 1,其中 abc 现在等于 2 而不是“11”,如果这两个项目都可以本来是字符串。

Public Function lookUpColumnValue(Database As Database, column As String, table As String, lookUpColumn As String, lookUpValue As String) As String

    Dim sql As String
    Dim recordSet As DAO.recordSet
    Dim result As String

    lookUpColumnValue = "" 'Return a blank string if no result

    On Error Resume Next

    sql = "SELECT [" & table & "].[" & column & "] FROM [" & table & "] WHERE [" & table & "].[" & lookUpColumn & "] = '" & lookUpValue & "'"
    Set recordSet = Database.OpenRecordset(sql)

    If Not recordSet.EOF Then
        Dim td As DAO.TableDef

        'this gives your number - say, 19
        result = recordSet(column)

        Set td = Database.TableDefs(table)

        'Get the rowsource
        Dim p As DAO.Property
        For Each p In td.Fields(column).Properties
            If p.Name = "RowSource" Then
                RowSource = Replace(td.Fields(column).Properties("RowSource"), ";", "")
                Exit For
            End If
        Next

        If Not RowSource = "" Then
            Dim rs2 As DAO.recordSet
            Dim qd As DAO.QueryDef

            Set qd = Database.CreateQueryDef("", RowSource)
            Set rs2 = Database.OpenRecordset(RowSource)

            If rs2.EOF Then Exit Function

            PKField = rs2.Fields(0).Name

            rs2.Close
            qd.Close

            sql = "SELECT * FROM (" & RowSource & ") WHERE [" & PKField & "]=[KeyField?]"
            Set qd = Database.CreateQueryDef("", sql)
            qd.Parameters("KeyField?").Value = result

            Set rs2 = qd.OpenRecordset()

            If Not rs2.EOF Then
                'NOTE: This assumes your RowSource *always* has ID first, description 2nd.  This should usually be the case.
                lookUpColumnValue = rs2.Fields(1)
            End If
        Else
            'Return the field value if there is no RowSource
            lookUpColumnValue = recordSet.Fields(column)
        End If
    End If

End Function

【讨论】:

  • 这几乎正是我要找的!我得到的唯一问题是我每次总是得到第一个描述条目。因此,例如,即使我的外键是 19,它总是会给我零值。我查看了您的代码,看看我是否能找到原因,并且看起来它应该是正确的,所以我想知道它的数据库设计是否它自己现在给了我这个价值。不过,它似乎确实遵循您的假设
  • 呃——你是对的。我没有根据外键过滤 RowSource。给我一点时间。
  • 应该可以。正如 Ron 所说,这个解决方案充其量只是 hackish。您确实应该使用 DLookup 之类的方法拨打 2 个电话 - 但我更愿意回答所提出的问题,而不是在没有要求时尝试教授“最佳实践”。无论如何,不​​要在你的生产代码中使用它。
  • 太棒了!这很棒!在旁注中,您对 ron 的评论是正确的,我使用的是外部数据库,因此 DLookup 无法工作(据我所知)。此外,我提前不知道我将使用我的代码的数据库是什么。所以我不会提前知道主键表。
  • 太棒了!不过,请确保您确实使用他的参数代码进行初始查找,因为当lookUpValue 类似于“Mike's Room”时,此代码将中断——因为刻度线 (')。我不想修改我的代码,因为这确实是他的贡献,我不想“窃取”它。
【解决方案2】:

如果我正确理解您的问题,我认为使用参数查询将解决您的问题。使用参数是一种很好的做法,因为它们将执行隐式数据类型转换并防止注入攻击。

注意在下面的函数中,我把lookupValue改成了Variant类型,它允许你向函数传递任何类型的值。

Public Function lookUpColumnValue( _
    database As DAO.database, _
    column As String, _
    table As String, _
    lookUpColumn As String, _
    lookUpValue As Variant) As String

    Dim sql As String
    Dim recordSet As DAO.recordSet
    Dim result As String
    Dim qd As QueryDef
    Set qd = database.CreateQueryDef("")
    sql = "SELECT [" + table + "].[" + column + "] FROM [" + table + "] " & _
          "WHERE [" + table + "].[" + lookUpColumn + "] = [parm1];"
    qd.sql = sql
    qd.Parameters![parm1] = lookUpValue
    Set recordSet = qd.OpenRecordset()

    result = recordSet(column)

编辑

    lookUpColumnValue = DLookup("Space Use Description", "Space Use Codes", result)


End Function

【讨论】:

  • 虽然这是一个非常棒的建议,它回答了我的一些不相关的问题,但恐怕这不是我要问的。如果我没有解释清楚,我很抱歉。想象一个数据库列,它具有与类别名称相对应的各种数字。除了该列链接到一个表,该表标识哪些名称对应于数字。然后访问数据库在列中显示名称而不是数字。我相信它被称为查找。我试图获取名称值,但我的函数只返回数字。
  • 哦,好吧,我想你要找的是 Dlookup() 函数:techonthenet.com/access/functions/domain/dlookup.php
  • 我添加了一张图片,以便更清楚地解释自己,Dlookup 功能仍然给了我之前收到的相同结果。谢谢!
  • 感谢您的澄清。我根据结果代码编辑了答案以返回“空间使用说明”。我无法对其进行测试,但我认为这就是您要寻找的。​​span>
  • 嗯,我想做的是通用化我的函数,这样无论我查询什么,它都会得到正确的值。您给我的空间使用描述示例假设我提前知道查找查询是什么,从技术上讲我知道,但我需要假装我不知道,这样当我转到另一个具有不同查找的列时查询它仍然能够处理它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-20
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多