VBA/excel宏-在值列表中查找字符串的一部分,然后返回该值



这里是第一篇文章,如果我违反了任何礼仪,请道歉。如果缺少什么,请告诉我,这样我就可以在需要时编辑我的帖子。

我目前正在开发一个Excel宏,它使我能够将交互式pdf表单导入Excel,并读取表单中写入的数据。我在互联网上找到的大部分脚本都是零碎的,这只是我目前无法解决的一个特定问题。

我的pdf中有一个文本字段,我需要将其一分为二,并将新值保存在两个单独的单元格中。到目前为止还不是什么大问题,但格式可能会有所不同,具体取决于输入的数据,所以仅仅在一定数量的字符之后剪切它是行不通的。此外,用户输入数据的质量可能并不总是相同(例如,有时在字符串的两个部分之间使用连字符,使用下划线或根本不使用分隔符)。不幸的是,我不能给pdf表单中的文本字段一个严格的格式规则,因为格式可能会有所不同。我也不能只为字符串的每个部分在pdf文件中分离表单字段。易用性应该是pdf用户的一方,而不是我的一方。。。

现在,数据是什么样子的:
ABC-1234
BCD-0123
A1B-12A

正如你所看到的,没有一个明确的模式。请注意,如前所述,连字符可能不存在或被下划线取代。我在这里添加它是为了向您展示两个子数据集的分离(让我们将它们称为"数据A",表示左边的所有数据,将"数据B"表示右边的所有数据)。

好东西!我知道数据A可能具有的所有潜在价值。然后,数据B应该被单独存储在另一个单元中。我的第一个想法是使用InStr,但这可能不是最优雅的解决方案。数据A可以是大约130个不同值中的一个,该值也经常增长。我的excel文件也有一个";"辅助片";,我在其中存储了一些信息,例如下拉菜单或截止日期等。我也可以在这里存储潜在的数据a候选人列表。

那么我到底需要什么呢?一种查看字符串、将其与子字符串列表(数据A,例如使用excel工作表中的列作为数据源)进行比较并将匹配项存储在单元格A1中的方法。然后从原始字符串中去掉该值,这样只剩下数据B(此时我可以去掉任何连字符或下划线),并将该值存储在单元格A2中。

示例:
我的导入数据可能如下所示:BER1234
将其与我的匹配候选列表进行比较,其中包括"BER">
单元格A1=";BER">
Cell A2=(字符串减去匹配项)1234

导入数据:BERA59
在我的候选列表中匹配:BERA
A1="BERA">
A2=";59〃

导入数据:P9CD-1009A
匹配:P9CD
A1="P9CD">
A2=";1009A〃

等等。

我可能可以通过一大块if/else和许多InStr比较来做到这一点。问题是,每当我需要添加一个新的匹配候选者时,我都必须重新进行编码。如果我能在候选列表的底部添加值,让宏发挥它的魔力,这会让我的生活变得更轻松。

我很想在这里发布一段我迄今为止所做的代码,不幸的是,我真的不知道从哪里开始。我不希望有一段现成的代码,我可以通过复制和粘贴在我的宏中。如果我不能理解代码,我通常会寻求另一种解决方案。否则,如果有什么东西坏了,我自己也无法修复,我真的不喜欢这种方法。不过,如果能给我一些关于哪些函数和变量类型的指针,我将不胜感激。也许我可以拼凑出我认为应该是什么样子,并在那一步之后寻求更多帮助。

我的经验水平:有点初学者,但不是完全初学者。我对事物是如何运作的有基本的了解,但我不是"流利的";在任何编程语言中。我知道我想做什么,然后通常会把我在互联网上找到的不同解决方案拼凑起来,让它发挥作用。到目前为止还不错,不过这一次对我来说有点虚幻。非常感谢您的帮助。如前所述,如果有任何遗漏或不清楚的地方,我很乐意尝试更新这篇文章。

有了这些建议,我在一定程度上做到了这一点:

Dim wb As Workbook: Set wb = ThisWorkbook
Dim LastRow As Long
Dim x As Integer
Dim Remover As String
Dim CatNo As String
Dim Matches As Integer

With Sheets("MenuData")
LastRow = .Range("o" & .Rows.Count).End(xlUp).Row
End With
LastRow = LastRow - 4
Matches = 0

For x = 1 To LastRow
If InStr(AlbumCode1, wb.Sheets("MenuData").Range("O" & x + 4).Value) <> 0 Then
Matches = Matches + 1
Range(ColCatalog & (ImportCell.Row)).Value = wb.Sheets("MenuData").Range("O" & x + 4).Value
Remover = wb.Sheets("MenuData").Range("O" & x + 4).Value
CatNo = Replace(AlbumCode1, Remover, "")
Range(ColCatNo & (ImportCell.Row)).Value = CatNo
End If

Next

MsgBox Matches & (" Matches")

我所做的是计算行和子行4,因为我的候选列表从第4行开始。然后对每个x进行循环。我在宏的一开始就将所有Colxxx变量声明为Const。ImportCell也在其他地方声明,并按照我导入的其余数据的预期工作。我的"移除器";只是设置为匹配的值,然后用于将其从存储在AlbumCode1中的原始字符串中剥离(也在宏的开头声明)。也许完全没有必要这样做。

到目前为止,它是有效的。不过,我的候选人可能是这样的:
BER
BERA

如果我导入像";BERA12342";我将得到两个匹配项(这里的MsgBox用于检查我的代码的作用,稍后将被删除)。由于候选BERA在我的源列表中位于候选BER之后,所以它工作得很好;匹配";只覆盖第一个。如果他们的顺序不同,我会得到一个错误的匹配。有没有办法总是只得到一场比赛?还是我必须确保源列表以某种方式排序?

我想您在Excel文件中有候选列表。如果是这样的话,你可以在你的候选列表的范围内为每个循环使用一个

要获得完整的候选列表,即使它在两次执行之间增长,也可以使用第一个单元格作为起点,并使用toDown()方法找到最后一个单元格。

我不记得它的确切名称,但我以前用过,你可以通过录制宏并使用Ctrl+Down快捷方式找到它。

有了这两个单元格,您就有了候选人列表的范围。

尝试使用该公式来检查单元格是否包含字符串:

=IF(IFERROR(FIND("字符串",A2,1),0)+IFERROR;0;如果"真"FALSE")来源:https://best-excel-tutorial.com/59-tips-and-tricks/600-search-for-string-in-column

然后过滤掉它们,并编写一个for循环以继续前进。

最新更新