Excel FindJobCode 的问题

我是 VBA 新手,我有一个如下代码可以在描述中找到一些工作编号。 但是,我有 3 个问题...

  1. 如果第一个字符是“s”、“m”等小写字母,则显示错误
  2. 我无法解决 Example3,结果会显示“M3045.67”,但我只需要“M3045.67”,不需要逗号
  3. 我不知道为什么它在 Example5 中的 Else 之后运行代码 Range("E2").Value = "Overhead" 失败

但是对于问题 3,我可以在添加第二个条件之前运行结果“开销”,有什么问题吗?请帮忙~~~谢谢。

附言解决上述问题后将添加循环......

Sub FindCode()
        
        'Example1 : G5012.123 Management Fee / Get Result = G5012.123
        'Example2 : G3045.67 Management Fee / Get Result = G3045.67
        'Example3 : M3045.67,S7066 Retenal Fee / Get Result = M3045.67,'Example4 : P9876-123A Car Park / Get Result = P9876
        'Example5 : A4 paper / Get result = Overehad
        
        'Criteria1 : 1st Character = G / S / M / P
        If Left(Range("A2"),1) = "G" Or Left(Range("A2"),1) = "S" Or Left(Range("A2"),1) = "M" Or Left(Range("A2"),1) = "P" Then
            'Criteria2 : 2nd-5th Character = Number only
            If Isnumeric(Mid(Range("A2"),2,4)) Then
                'Get string before "space"
                Range("E2").Value = Left(Range("A2"),InStr(1,Range("A2")," ") - 1)
        Else
                'If not beginning from Crit 1&2,show "Overhead"
                Range("E2").Value = "Overhead"
            End If
        End If
        
        'If start from "P",get first 5 string
        If Left(Range("A2"),1) = "P" And Isnumeric(Mid(Range("A2"),4)) Then
            Range("E2").Value = Left(Range("A2"),5)
        Else
        End If

End Sub
ynndf3236517 回答:Excel FindJobCode 的问题

下面的函数将提取作业编号并将其返回给调用它的过程。

Function JobCode(Cell As Range) As String
    ' 303
        
        'Example1 : G5012.123 Management Fee / Get Result = G5012.123
        'Example2 : G3045.67 Management Fee / Get Result = G3045.67
        'Example3 : M3045.67,S7066 Rental Fee / Get Result = M3045.67,'Example4 : P9876-123A Car Park / Get Result = P9876
        'Example5 : A4 paper / Get result = Overhead
        
        Dim Fun     As String           ' function return value
        Dim Txt     As String           ' Text to extract number from
        
        ' Minimize the number of times your code reads from the sheet because it's slow
        Txt = Cell.Value                ' actually,it's Cells(2,1)
        
        ' Criteria1 : 1st Character = G / S / M / P
        If InStr("GSMP",UCase(Left(Txt,1))) Then
            Txt = Split(Txt)(0)                     ' split on blank,take first element
            ' Criteria2 : 2nd-5th Character = Number only
            ' Isnumeric(Mid("A4",2,4)) = true
            If (Len(Txt) >= 5) And (IsNumeric(Mid(Txt,4))) Then
                Fun = Replace(Txt,","")
                Fun = Split(Fun,"-")(0)            ' discard "-123A" in example 4
            End If
        End If
        
        ' If no job number was extracted,show "Overhead"
        If Len(Fun) = 0 Then Fun = "Overhead"
        JobCode = Fun
End Function

作为函数而不是子函数的设置是此类搜索的典型特征。在我的试验中,我在 A2:A6 中有你的 5 个示例,并在循环中调用它们,在每个循环中为函数提供不同的单元格。很可能,这也是您钓鱼的目的。这是我用来测试的调用过程。

Sub Test_JobCode()
    ' 303
    
    Dim R   As Long
    
    For R = 2 To Cells(Rows.Count,"A").End(xlUp).Row
        ' I urge you not to use syntax for addressing ranges when addressing cells
        Debug.Print JobCode(Cells(R,"A"))          ' actually,1)
    Next R
End Sub

当然,除了 Debug.Print JobCode(Cells(R,"A")),您还可以使用 Cells(R,"B").Value = JobCode(Cells(R,"A"))

您的 Else 语句不起作用的原因是逻辑错误。如果不满足标准 1 和 2,但如果之前的所有努力都失败,则“开销”标题不适用,其含义稍宽。这与 Isnumeric(Mid("A4",4)) = True 的事实相结合,导致测试没有像您预期的那样失败。

粗略地说,代码首先检查第一个字母是否符合检查条目(如果不符合,则返回“Overhead”)。然后将文本拆分为单词,仅考虑第一个单词。如果它太短或非数字,则不会提取作业代码,导致下一步出现“开销”。如果此测试通过,则修改最终结果:删除尾随逗号(它存在)并删除任何附加连字符的内容(如果存在)。我不确定你真的想要这个。因此,您可以轻松删除该行。或者您可以在此时添加更多修改。

,

您尝试做的是 FAR 使用正则表达式匹配和替换更容易,因此我建议启用该函数库。这样做的最好消息是,您可以在 EXCEL 公式中调用这些函数,而根本不需要使用 Visual Basic for Applications。

启用正则表达式作为 Excel 函数:
步骤 1:在 VBA 中启用正则表达式库。

A. In the Visual Basic for Applications window (where you enter VBA code) find the Tools menu and
   select it,then select the References... entry in the sub-menu.
B. A dialogue box will appear listing the possible "Available References:" in alphabetical order.
   Scroll down to find the entry "Microsoft VBScript Regular Expressions 5.5".
C. Check the checkbox on that line and press the OK button.

第 2 步:创建函数调用。在 Visual Basic for Applications 窗口中选择 Insert..Module。然后将以下 VBA 代码粘贴到出现的空白窗口中:

'  Some function wrappers to make the VBScript RegExp reference Library useful in both VBA code and in Excel & Access formulas
'
Private rg As RegExp    'All of the input data to control the RegExp parsing
'  RegExp object contains 3 Boolean options that correspond to the 'i','g',and 'm' options in Unix-flavored regexp
'    IgnoreCase - pretty self-evident.  True means [A-Z] matches lowercase letters and vice versa,false means it won't
'    IsGlobal - True means after the first match has been processed,continue on from the current point in DataString and look to process more matches.  False means stop after first match is processed.
'    MultiLine - False means ^ and $ match only Start and End of DataString,True means they match embedded newlines.  This provides an option to process line-by-line when Global is true also.
'
'  Returns true/false: does DataString match pattern?  IsGlobal=True makes no sense here
Public Function RegExpMatch(DataString As String,Pattern As String,Optional IgnoreCase As Boolean = True,Optional IsGlobal As Boolean = False,Optional MultiLine As Boolean = False) As Boolean
If rg Is Nothing Then Set rg = New RegExp
rg.IgnoreCase = IgnoreCase
rg.Global = IsGlobal
rg.MultiLine = MultiLine
rg.Pattern = Pattern
RegExpMatch = rg.Test(DataString)
End Function
'
'  Find <pattern> in <DataString>,replace with <ReplacePattern>
'       Default IsGlobal=True means replace all matching occurrences.  Call with False to replace only first occurrence.
'
Public Function RegExpReplace(DataString As String,ReplacePattern As String,Optional IsGlobal As Boolean = True,Optional MultiLine As Boolean = False) As String
If rg Is Nothing Then Set rg = New RegExp
rg.IgnoreCase = IgnoreCase
rg.Global = IsGlobal
rg.MultiLine = MultiLine
rg.Pattern = Pattern
RegExpReplace = rg.Replace(DataString,ReplacePattern)
End Function

现在您可以在 Excel 公式中调用 RegExpMatch 和 RegExpReplace,我们可以开始考虑如何解决您的特定问题。要匹配,您的字符串必须以 G、S、M 或 P 开头。在 ^[GSMP] 的正则表达式代码中,向上箭头表示从开头开始,[GSMP] 表示接受下一个位置的 G、S、M 或 P。然后任何匹配的字符串接下来必须有许多数字。将其编码为 \d+,其中 \d 表示一个数字,+ 是一个修饰符,表示接受其中一个或多个。然后你可以有一个点后跟更多的数字,或者没有。这有点复杂 - 您将其编码为 (\.\d+)?因为点是正则表达式和\中的特殊字符。说接受文字点。后面跟着一个或多个数字的 \d+,但整个表达式都用括号括起来,后面跟着一个 ?,这意味着括号中的内容可以出现一次,也可以根本不出现。最后,是行的其余部分,我们并不真正关心其中的内容。我们将 .*$ 编码为零个或多个字符(任意),然后是行尾。这一切都以 ^[GSMP]\d+(\.\d+)?.*$ 的形式出现。

将该模式放入我们的 RegExpReplace 调用中:

=RegExpReplace(A2,"^([GSMP]\d+(\.\d+)?).*$","$1")

我们将感兴趣的部分包裹在括号中,因为作为替换模式的一部分的“$1”表示使用在第一组括号内找到的任何内容。这是Excel中使用的公式 enter image description here

这适用于您的所有示例,但最后一个是逻辑中的 else 子句。我们可以通过使用 RegExpMatch 测试模式是否匹配来解决这个问题:

=IF(regexpMatch(A2,"^([GSMP]\d+(\.\d+)?).*$"),RegExpReplace(A2,"$1"),"Overhead")

这给出了您正在寻找的结果,您还获得了一个强大的文本操作工具来解决未来的问题。 enter image description here

本文链接:https://www.f2er.com/3624.html

大家都在问