首页 > 解决方案 > 与表格列表相比,MS Access 从长文本字段中提取多个匹配的文本字符串

问题描述

问题:查询无法提取在长文本字段中找到的所有受限词。它从 ~100 个值的表列中获取受限制的单词。

样本数据

表:带有长文本字段的 RecipeTable:RecipeText

RecipeText 字段的示例内容:将大头菜、韭菜、胡萝卜和卷心菜添加到 Instant Pot®。密封并在高压下煮4分钟。快速释放蒸汽。将牛腩切成薄片穿过谷物,然后转移到盘子里。把蔬菜放在肉周围,撒上欧芹,配上酸奶油、辣根和芥末。

期望的结果: 想要将 RecipeText 字段与表中此短文本字段 RestrictedItem 中的每个值进行比较:RestrictedTable。

RestrictedTable.RestrictedItem 包含 100 个值。假设这个练习包含 6 个:牛奶、烘焙、勺子、胡萝卜、芥末和蒸汽。

查询将在单个记录中以无特定顺序查找这些匹配的单词:carrots mustard steam

我试过这个如何在带有微软访问权限的备忘录字段中查找单词

结果:在长文本字段中找到许多匹配项中的一项。

期望结果:查找在长文本字符串中提取的所有匹配词。重复和通配符很好。区分大小写不好。

示例尝试:

SELECT a.Adjectives, b.Content
FROM A, B
WHERE b.Content Like "*" & a.[adjectives] & "*"

LIKE 和之后是我认为问题所在。我试过使用 %、括号、空格等无济于事。

我的变成了这样:

SELECT RecipeTable.RecipeText, RestrictedTable.RestrictedItem
FROM RecipeTable, RestrictedTable
WHERE RecipeTable.RecipeText LIKE  "*" & RestrictedTable.RestrictedItem & "*";

笔记:

  1. 我可以找到很多建议来查找单个单词,但不能将整个表格列与一个字段进行比较。
  2. 而且,有很多建议可以找到第一个子字符串或第 n 个位置,但我想要所有匹配的子字符串。不是位置,我担心应用修剪等会减慢搜索 100 个单词和修剪每个单词的速度。
  3. 我很好地将其作为我的表单上包含 RecipeText 字段的计算字段。
  4. 制作一个按钮来启动查询以将 RecipeText 字段与 RestrictedTable.RestrictedItem 列表进行比较并在同一表单上填写一个空字段 RestrictedFound 也很好。

标签: sqlvbams-access

解决方案


下面的代码是查找备注字段中所有受限单词的两种方法。虽然这一切都可以在没有暂存/工作表的情况下以编程方式完成,但我建议使用临时或永久表通过 VBA 中的拆分功能从备忘录字段中提取单词(在考虑标点符号和其他数据清理之后)。

在将备注字段中的单词拆分为一个数组后,可以将它们插入到一个单独的表中,其中包含对 RecipeTable 的外键引用。如果需要,这可以是临时表或永久表,并且可以是工作流过程的一部分。可以将 PendingReview 之类的字段添加到 RecipeTable 以处理新记录,然后将其标记为 false,这样它们就不会被再次处理。

将单词添加到另一个表后,可以通过外键将其连接到 RecipeTable,并且您应该拥有所有受限单词的匹配项。

获得信息后,您可以存储统计信息并从临时表中丢弃工作记录或删除工作记录,直到再次运行该过程。

您可以在 VBA 中使用受限单词的字典查找来完成所有操作,即查询受限单词表,添加到字典中,然后循环匹配备忘录字段中的每个单词与小写或不区分大小写的比较,但这可能需要尽管。

下面的第一个代码片段

如果您想要编译时检查,那么您必须参考 Microsoft Scripting Runtime 我的路径是 C:\Windows\SysWOW64\scrrun.dll

Dim dic as Dictionary
Dim memoField as string
Dim words() as String
Dim matchCnt as Integer
'Other variables I didnt declare

'Code to populate dictionary
'Do Until rstRestricted.EOF
'  dic.add LCase$(rst("restrictedWord")), 0
'  rstRestricted.MoveNext
'Loop
'rstRestricted.Close
'Set rstRestricted = Nothing

Set rst = New adodb.Recordset
rst.Open "SELECT [MemoField] FROM RecipeTable;"
lngRowCnt = CLng(rst.RecordCount) - 1
For x = 0 to lngRowCnt
   memoField = LCase$(Nz(rst("MemoField")))
   'Replace punctuation like commas, periods
   'memoField = Replace(memoField, ",","")

   'Now split after data scrubbed
   words = Split(memoField, " ")
   intWordCnt = UBound(words)
   For z = 0 to intWordCnt
      If LenB(words(z)) <> 0 Then
          If dic.Exists(words(z) = True Then
              matchCnt = dic(words(z))
              dic(words(z)) = matchCnt + 1
          End If
      End If
   Next z
Next x

Dim WordKeys() as Variant
Dim y as Integer
Dim restrictedWord as string
Dim wordCnt as Integer

WordKeys = dic.Keys
For y = 0 to UBound(WordKeys) '-1
     restrictedWord = CStr(WordKeys(y))
     wordCnt = CInt(WordKeys(restrictedWord))
     'code to save or display stats
Next y

rst.Close
Set rst = Nothing
Set conn = Nothing

我只需将所有单词拆分到一个工作表中,并索引单词字段,然后对受限单词的计数进行聚合。

第二个代码片段

'Option Explicit 
Dim sql as String
Dim memoDelimitedData() as String
'Other variables declared

'Code to open Recordset table for recipe and also code to open 
'Work table with adOpenDynamic (SELECT * from WorkTable)

'loop through records to be processed
'Split Field (May need variant instead of array.  My Access VBA is rusty)
 words = Split(memoField, " ")
 intWordCnt = UBound(words)
 For x = 0 to intWordCnt
    With rstWorkTable
      .AddNew
      !Word = words(x)
      !ForeignKeyIdToRecipeTable = intForeignKeyId
      .Update
    End With
 Next x 

然后,当您添加了工作表记录时,您可以加入 RecipeTable 和 RestrictedTable。

因此,从备忘录字段构建一个分隔单词的工作表。将外键引用到配方表,然后通过 RestrictedItem 将 RestrictedTable 连接到 WorkTable。

如果需要,这可以是对生成表或临时表永久表的查询。等等

所以像这样的东西会给你匹配,你的受限表中的任何单词:

SELECT RecipeTable.RecipeText, RestrictedTable.RestrictedItem
FROM RecipeTable
  INNER JOIN WorkTable ON
   RecipeTable.Id = WorkTable.RecipeTableId
  INNER JOIN RestrictedTable ON
   WorkTable.ForeignKeyIdToRecipeTable = RestrictedTable.RestrictedItem

MS 访问拆分功能

那时,您可以进行计数、求和和其他数据。

对不起,我以为我有示例代码,但我找不到。很多个月前,我不得不在大学里使用 VBA 和 Access(字数统计/排名分配)做这样的事情,但我找不到。现在我会用带有数字表、XML/JSON 功能或全文搜索功能的 SQL Server 来做这种事情。

如果您需要限制在 MS Access 中的工作,希望这可以帮助您指明正确的方向。

如果您不习惯使用 ADODB 或 DAO 记录集,您可以使用外键和单词构建一个 CSV 分隔文件,然后将该文件导入工作表。


推荐阅读