【问题标题】:extract specific set of digits from random strings in EXCEL VBA从 EXCEL VBA 中的随机字符串中提取特定的数字集
【发布时间】:2018-09-03 04:21:24
【问题描述】:

免责声明-我的情况是具体的,在我的情况下,我的代码有效,因为我知道模式。

我到处都在寻找答案,但我尝试的代码并不完全符合我的要求,如果您正在寻找一组数字,这就是我的解决方案。
就我而言,我正在寻找 7 位数字,从数字 1 开始,在一个带有随机字符串的列中,一些字符串具有其他一些没有的数字。

数字会出现在“1XXXXXX”、“PXXXXXXXX”、“PXXXXXXXXX”这三个场景中(因为有斜线,所以数字比较多)。

以下是字符串的示例:

9797 P/O1743061 465347  Hermann Schatte Earl Lowe          
9797 Po 1743071 404440  Claude Gaudette Jose Luis Lopez     
9817 1822037    463889  Jean Caron  Mickelly Blaise 

我的代码

Sub getnum()

'i don't use explicit so i didn't declare everything
Dim stlen As String
Dim i As Integer
Dim arra() As String
Dim arran() As String

Orig.AutoFilterMode = False
Call BeginMacro

LastRow = Orig.Cells(Rows.Count, 1).End(xlUp).Row
Orig.Range("J2:J" & LastRow).Clear

'loop though column
For n = 2 To LastRow
    celref = Orig.Cells(n, 4).Value
    'split string on white spaces
    arra() = Split(celref, " ")
    'turn string to multiple strings
    For counter = LBound(arra) To UBound(arra)
        strin = arra(counter)

        'remove white spaces from string
        storage = Trim(strin)
        lenof = Len(storage)

        'if string has 9 characthers, check for conditions
        If lenof = 9 Then
            'position of first and last charachter
            somstr = Mid(storage, 1, 1)
            somot = Mid(storage, 9, 1) 

            If somstr = "P" Or somstr = "p" And IsNumeric(somot) = True Then
                'removes Po or PO and keeps only 7 digits
                storage = Right(storage, 7)
                'stores in column J
                Orig.Cells(n, 10).Value = storage
            End If

        ElseIf lenof = 10 Then
            somstr = Mid(storage, 1, 1)
            somot = Mid(storage, 10, 1)

            'other conditions
            If somstr = "P" Or somstr = "p" And IsNumeric(somot) = True Then
                'removes Po or PO and keeps only 7 digits
                storage = Right(storage, 7)
                'stores in column J
                Orig.Cells(n, 10).Value = storage
            End If
        End If

        'eliminate comma within
        arran() = Split(storage, ",")

        If Orig.Cells(n, 10).Value <> storage Then
            For counter2 = LBound(arran) To UBound(arran)
                strin2 = arran(counter2)
                storage2 = Trim(strin2)

                'final condition if is 7 digits and starts with 1
                If IsNumeric(storage2) = True And Len(storage2) = 7 Then
                    car = Mid(storage2, 1, 1)

                    If car = 1 Then
                        'stores in columns J at specific position
                        Orig.Cells(n, 10).Value = storage2
                    End If
                Else
         If isnumeric(orig.cells(n,10).value) =true and _ 
             len(orig.cells(n,10).value = 7 then
                        orig.cells(n,10).value = orig.cells(n,10).value 
                        else
                    Orig.Cells(n, 10).Value = "no po# in D"
                End If
            Next counter2
        End If
    Next counter
Next n

Call EndMacro

End Sub

【问题讨论】:

  • 请看here
  • 您可以使用RegEx对象,查找7位数字Pattern = "\d{7}"
  • 正则表达式需要引用外部库,让你心烦意乱,而且非常慢。在真正的数据库中,您将享受数十万条记录:)
  • @MarY 我说得对,所有三种场景模式都有领先空间吗?可能是 Chr(160) 还是不是?
  • @ user6698332 在这种特定情况下,我不需要 PO 或 Po ,通过单独隔离 'p' 或 'P',我得到了所有情况,我不会写一些我不需要的东西......最后,代码有效,我使用了它,并得到了我需要的所有数字。但这是非常具体的。如果你使用它,你需要检查你的字符串中的限制。

标签: string vba excel digits


【解决方案1】:

您可以使用 RegEx 以所需格式提取数字。

请试一试...

Function Get10DigitNumber(ByVal Str As String) As String    
Dim RE As Object
Set RE = CreateObject("VBScript.RegExp")
With RE
   .Global = False
   .Pattern = "1\d{6}"
End With
If RE.test(Str) Then
    Get10DigitNumber = RE.Execute(Str)(0)
End If
End Function

那么如果你想在工作表本身上使用这个函数,假设你的字符串在 A2 中,试试这个...

=Get10DigitNumber(A2)

你可以像这样在另一个子程序/宏中使用这个函数...

Debug.Print Get10DigitNumber(<pass your string variable here>)

编辑功能:

Function Get10DigitNumber(ByVal Str As String) As String
Dim RE As Object, Matches As Object
Set RE = CreateObject("VBScript.RegExp")
With RE
   .Global = False
   .Pattern = "[Pp]?\/?[Oo]?(1\d{6})\b"
End With
If RE.test(Str) Then
    Set Matches = RE.Execute(Str)
    Get10DigitNumber = Matches(0).SubMatches(0)
End If
End Function

并使用 if 如上所述。

【讨论】:

  • 这几乎是完美的,它只需要解决,因为它也在数字示例 1181925567 中取数字,它将它变成 1925567,但在我的代码中,必须忽略它,因为它是另一个的一部分代码类型# 完全。对于这个宏,数字要么是独立的,要么前面有 PO、po、PO 或 P/O...
  • 我已编辑该函数,以便该函数仅提取一个以 1 开头的独立 7 位数字 OR 一个以 1 开头并以“PO”或“po”为前缀的七位数字或“采购订单”或“采购订单”。这就是你想要达到的目标吗?
【解决方案2】:

你可以试试这个

Option Explicit
Sub getnum()
    Dim position As Variant
    Dim cell As Range
    With  Worksheets("Orig") ' change it to your actual sheet name
        With Intersect(.UsedRange, Columns("J"))
            .Replace what:="P/O", replacement:="P/O ", lookat:=xlPart
            For Each cell In .Cells
                position = InStr(cell.Text, " 1")
                If position > 0 Then cell.Value = Mid(cell.Value, position + 1, 7)
            Next
        End With
    End With    
End Sub

【讨论】:

  • @MarY,有什么反馈吗?
  • 我试过了,但不起作用...它只完成了一半的工作,它确实检索了 7 位数字,但检索了带有破折号的 7 位数字的字符串,它忽略了 Pxxxxxxxx ,好吧从您的代码中可以明显看出它忽略了这一点。此外,但只是一个细节,我需要将数字转移到另一列,在我的代码中,我采用 D 列中的内容并在 J 列中显示结果。
【解决方案3】:

此代码粘贴两个公式,一个在 G 列中,一个在 J 列中)。第一个公式检查第 2 列单元格的第一个字符中是否有“P”,如果有“P”,它会提取字符串中的最后 7 个字符并将它们放在 G 列中。第二个公式检查是否有不是“P”,如果不是,则提取字符串中的最后 7 个字符并将它们放在 J 列中。

Sub Extract()
Dim ws As Worksheet
Dim lRow As Long

Set ws = ThisWorkbook.Sheets("Sheet3")
lRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

     ws.Range("G2:G" & lRow).Formula = "=IF(LEFT(B2)=""P"",(RIGHT(B2,7)),"""")"
     ws.Range("J2:J" & lRow).Formula = "=IF(LEFT(B2)<>""P"",(RIGHT(B2, 7)),"""")"

End Sub

【讨论】:

  • 这是您的代码给出的结果类型 060-428 0-B0391, 01-2018, 060-428 01-2018 0-B0478, 03-2018,所以根本不起作用!甚至部分没有。此外,您不能在 vba 中使用 1Row,当您在公式中使用它时会因为数字而混淆。
  • 抱歉,我以为您的示例在多个单元格中。它是“lRow”而不是“1Row”。
【解决方案4】:

在了解您在做什么之后,我认为这会起作用。任何反馈将不胜感激。

Dim cell As Range, LRow As Long
LRow = ActiveSheet.Cells(Rows.Count, 4).End(xlUp).Row

    For Each cell In Range("D2:D" & LRow)
        If cell.Value Like "*Po *" Then
            cell.Offset(0, 6).Value = Split(cell.Value, " ")(2)

        Else: cell.Offset(0, 6).Value = Split(cell.Value, " ")(1)

        End If
    Next cell

    For Each cell In Range("J2:J" & LRow)
        If Len(cell.Value) > 7 Then
            cell.Value = Right(cell.Value, 7)
        End If
    Next

【讨论】:

  • 你的代码给了我 4 个额外的集合,那是因为它们在其他数字中。但这帮助我看到我的代码有两个错误,我更正了,没有注意到我滥用了 mid 函数。找到最后一个数字。另外,改变了最后一个else,我在里面嵌入了antoher ...
猜你喜欢
  • 1970-01-01
  • 2017-03-14
  • 1970-01-01
  • 2016-05-07
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多