简体   繁体   English

EXCEL VBA如何使用函数和拆分从字符串中提取整数

[英]EXCEL VBA how to use functions and split to extract integer from string

I'm working on a piece of code to extract the nominal size of a pipeline from it's tagname. 我正在编写一段代码,以从其标记名中提取管道的标称大小。 For example: LP-50-00XX-0000-000. 例如:LP-50-00XX-0000-000。 The 50 would be it's nominal size (2") which I would like to extract. I know I could do it like this: 50是我要提取的标称尺寸(2“)。我知道我可以这样做:

TagnameArray() = Split("L-P-50-00XX-0000-000", "-")
DNSize = TagnameArray(2)

But I would like it to be a function because it's a small part of my whole macro and I don't need it for all the plants I'm working on just this one. 但是我希望它是一个函数,因为它只是我整个宏的一小部分,对于我正在开发的所有植物,我都不需要它。 My current code is: 我当前的代码是:

Sub WBDA_XXX()
Dim a As Range, b As Range
Dim TagnameArray() As String
Dim DNMaat As String
Dim DN As String

Set a = Selection

For Each b In a.Rows
    IntRow = b.Row
    TagnameArray() = Split(Cells(IntRow, 2).Value, "-")
    DN = DNMaat(IntRow, TagnameArray())
    Cells(IntRow, 3).Value = DN
Next b
End Sub



Function DNMaat(IntRow As Integer, TagnameArray() As String) As Integer
    For i = LBound(TagnameArray()) To UBound(TagnameArray())
        If IsNumeric(TagnameArray(i)) = True Then
            DNMaat = TagnameArray(i)
            Exit For
        End If
    Next i
End Function

However this code gives me a matrix expected error which I don't know how to resolve. 但是,这段代码给了我一个矩阵预期的错误,我不知道该如何解决。 I would also like to use the nominal size in further calculations so it will have to be converted to an integer after extracting it from the tagname. 我还想在进一步的计算中使用标称大小,因此从标记名中提取出来后必须将其转换为整数。 Does anyone see where I made a mistake in my code? 有人看到我的代码在哪里出错吗?

This is easy enough to do with a split, and a little help from the 'Like' evaluation. 这很容易进行拆分,并且从“ Like”评估中获得了一些帮助。

A bit of background on 'Like' - It will return TRUE or FALSE based on whether an input variable matches a given pattern. 有点像“赞”的背景-根据输入变量是否匹配给定的模式,它将返回TRUE或FALSE。 In the pattern [AZ] means it can be any uppercase letter between A and Z, and # means any number. 模式[AZ]表示它可以是A和Z之间的任何大写字母,而#表示任何数字。

The code: 编码:

' Function declared to return variant strictly for returning a Null string or a Long
Public Function PipeSize(ByVal TagName As String) As Variant
    ' If TagName doesn't meet the tag formatting requirements, return a null string
    If Not TagName Like "[A-Z]-[A-Z]-##-##[A-Z]-####-###" Then
        PipeSize = vbNullString
        Exit Function
    End If

    ' This will hold our split pipecodes
    Dim PipeCodes As Variant
    PipeCodes = Split(TagName, "-")

    ' Return the code in position 2 (Split returns a 0 based array by default)
    PipeSize = PipeCodes(2)
End Function

You will want to consider changing the return type of the function depending on your needs. 您将需要考虑根据需要更改函数的返回类型。 It will return a null string if the input tag doesnt match the pattern, otherwise it returns a long (number). 如果输入标签与模式不匹配,它将返回一个空字符串,否则它将返回一个long(数字)。 You can change it to return a string if needed, or you can write a second function to interpret the number to it's length. 您可以根据需要将其更改为返回字符串,也可以编写第二个函数以将数字解释为其长度。

Here's a refactored version of your code that finds just the first numeric tag. 这是代码的重构版本,仅查找第一个数字标记。 I cleaned up your code a bit, and I think I found the bug as well. 我对您的代码进行了一些整理,并且我也发现了该错误。 You were declaring DNMAAT as a String but also calling it as a Function . 您将DNMAAT声明为String但也将其称为Function This was likely causing your Array expected error. 这很可能导致您的Array预期错误。

Here's the code: 这是代码:

' Don't use underscores '_' in names. These hold special value in VBA.
Sub WBDAXXX()
    Dim a As Range, b As Range
    Dim IntRow As Long

    Set a = Selection

    For Each b In a.Rows
        IntRow = b.Row
        ' No need to a middleman here. I directly pass the split values
        ' since the middleman was only used for the function. Same goes for cutting DN.
        ' Also, be sure to qualify these 'Cells' ranges. Relying on implicit
        ' Activesheet is dangerous and unpredictable.
        Cells(IntRow, 3).value = DNMaat(Split(Cells(IntRow, 2).value, "-"))

    Next b
End Sub

' By telling the function to expect a normal variant, we can input any
' value we like. This can be dangerous if you dont anticipate the errors
' caused by Variants. Thus, I check for Arrayness on the first line and 
' exit the function if an input value will cause an issue.
Function DNMaat(TagnameArray As Variant) As Long
    If Not IsArray(TagnameArray) Then Exit Function

    Dim i As Long
    For i = LBound(TagnameArray) To UBound(TagnameArray)
        If IsNumeric(TagnameArray(i)) = True Then
            DNMaat = TagnameArray(i)
            Exit Function
        End If
    Next i
End Function

The error matrix expected is thrown by the compiler because you have defined DNMaat twice: Once as string variable and once as a function. 由于您定义了DNMaat两次,因此编译器matrix expected抛出matrix expected的错误matrix expected :一次作为字符串变量,一次作为函数。 Remove the definition as variable. 删除定义作为变量。

Another thing: Your function will return an integer, but you assigning it to a string (and this string is used just to write the result into a cell). 另一件事:函数将返回一个整数,但您将其分配给一个字符串(该字符串仅用于将结果写入单元格)。 Get rid of the variable DN and assign it directly: 摆脱变量DN并直接分配它:

Cells(IntRow, 3).Value = DNMaat(IntRow, TagnameArray())

Plus the global advice to use option explicit to enforce definition of all used variables and to define a variable holding a row/column number always as long and not as integer 加上全局建议,使用option explicit使用option explicit来强制定义所有使用的变量,并定义一个变量,该变量始终保持行/列号的long而不是integer

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM