Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel VBA:从字母数字中获取数值_Vba_Excel - Fatal编程技术网

Excel VBA:从字母数字中获取数值

Excel VBA:从字母数字中获取数值,vba,excel,Vba,Excel,我有一列(a列)有字母数字文本,我想读它并把它写回另一列(C列)。代码是 Sub getnumber() 'Define Variable Dim anicode As Variant Dim n As Long Dim lastrowdata As Long 'Data Location Sheets("Sheet1").Activate lastrowdata = range("A2").end(xlDown).Row - 1 'Redefine Array ReDim anicode

我有一列(a列)有字母数字文本,我想读它并把它写回另一列(C列)。代码是

Sub getnumber()

'Define Variable
Dim anicode As Variant
Dim n As Long
Dim lastrowdata As Long

'Data Location
Sheets("Sheet1").Activate
lastrowdata = range("A2").end(xlDown).Row - 1

'Redefine Array
ReDim anicode(lastrowdata)

'Read Data
For n = 1 To lastrowdata
  anicode(n) = Sheets("Sheet1").Cells(1 + n, 1)
Next n

'Altering Data
For n = 1 To lastrowdata
  If IsNumeric(anicode(n)) Then
     anicode(n) = NumericOnly
  Else
  End If
Next n

'Write Data
For n = 1 To lastrowdata
  Sheets("Sheet1").Cells(1 + n, 3) = anicode(n)
Next n

End Sub
我被困在
修改数据
部分,我只想从文本中获取值。我是VBA新手,目前只知道IsNumeric函数。
在A列中,数据是字母数字的,并且是随机的,其中可能有破折号(-)或空格(),甚至可能与S2或X4等字母混淆。数据可能只是数字(因为数据长~8k,并且将不断增长)

例如,;在A栏中,我有

R1-Adapa S2
R2-Adapa S2
R3-Omis 14
R4-189
在C列中,我只想要数字

R1-002
R2-002
R3-014
R4-189
如果您对我的问题或代码有任何可能的功能或意见,我们将不胜感激。感谢stackoverflow.com使用我提出的:

=LEFT(A1,3)&TEXT(MID(SUMPRODUCT(MID(0&A1,LARGE(INDEX(ISNUMBER(--MID(A1,ROW(INDIRECT("1:"&LEN(A1))),1))*ROW(INDIRECT("1:"&LEN(A1))),0),ROW(INDIRECT("1:"&LEN(A1))))+1,1)*10^ROW(INDIRECT("1:"&LEN(A1)))/10),2,LEN(A1)),"000")
这为我提供了所提供示例的预期结果。

使用我得出的结果:

=LEFT(A1,3)&TEXT(MID(SUMPRODUCT(MID(0&A1,LARGE(INDEX(ISNUMBER(--MID(A1,ROW(INDIRECT("1:"&LEN(A1))),1))*ROW(INDIRECT("1:"&LEN(A1))),0),ROW(INDIRECT("1:"&LEN(A1))))+1,1)*10^ROW(INDIRECT("1:"&LEN(A1)))/10),2,LEN(A1)),"000")

这为我提供了所提供示例的预期结果。

为了完成此任务,您需要添加其他函数,这将使代码更简单、更清晰:

首先,函数只从给定字符串中提取数字:

Function OnlyNumbers(word As String) As String
    Dim i As Long, ascIdx As Long
    OnlyNumbers = ""
    For i = 1 To Len(word)
        'if it's letter then append it to a returned word
        If IsNumeric(Mid(word, i, 1)) Then
            OnlyNumbers = OnlyNumbers + Mid(word, i, 1)
        End If
    Next
End Function
其次,我们需要一个函数,在我们需要的情况下,该函数将添加前导零:

Function LeadingZeros(word As String, outputLength As Long) As String
    Dim i As Long
    LeadingZeros = ""
    For i = 1 To outputLength - Len(word)
        LeadingZeros = LeadingZeros + "0"
    Next
    LeadingZeros = LeadingZeros + word
End Function
最后,我们编写了一个sub,用于复制:

Sub CopySpecial()
    Dim ws As Worksheet, lastRow As Long, i As Long, hyphenIdx As Long
    'always set reference to main sheet, so you can use it in range references
    Set ws = Sheets("Arkusz1")
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    For i = 1 To lastRow
        code = Cells(i, 1).Value
        hyphenIdx = InStr(1, code, "-")
        'set the text formatting, so leading zeroes won't be truncated
        Cells(i, 3).NumberFormat = "@"
        If hyphenIdx = 0 Then
            Cells(i, 3).Value = LeadingZeros(OnlyNumbers(Cells(i, 1).Value), 3)
        Else
            Cells(i, 3).Value = Mid(code, 1, hyphenIdx) + LeadingZeros(OnlyNumbers(Mid(code, hyphenIdx + 1)), 3)
        End If
    Next

End Sub

为了完成这项任务,您需要添加其他功能,这将使代码更简单、更清晰:

首先,函数只从给定字符串中提取数字:

Function OnlyNumbers(word As String) As String
    Dim i As Long, ascIdx As Long
    OnlyNumbers = ""
    For i = 1 To Len(word)
        'if it's letter then append it to a returned word
        If IsNumeric(Mid(word, i, 1)) Then
            OnlyNumbers = OnlyNumbers + Mid(word, i, 1)
        End If
    Next
End Function
其次,我们需要一个函数,在我们需要的情况下,该函数将添加前导零:

Function LeadingZeros(word As String, outputLength As Long) As String
    Dim i As Long
    LeadingZeros = ""
    For i = 1 To outputLength - Len(word)
        LeadingZeros = LeadingZeros + "0"
    Next
    LeadingZeros = LeadingZeros + word
End Function
最后,我们编写了一个sub,用于复制:

Sub CopySpecial()
    Dim ws As Worksheet, lastRow As Long, i As Long, hyphenIdx As Long
    'always set reference to main sheet, so you can use it in range references
    Set ws = Sheets("Arkusz1")
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    For i = 1 To lastRow
        code = Cells(i, 1).Value
        hyphenIdx = InStr(1, code, "-")
        'set the text formatting, so leading zeroes won't be truncated
        Cells(i, 3).NumberFormat = "@"
        If hyphenIdx = 0 Then
            Cells(i, 3).Value = LeadingZeros(OnlyNumbers(Cells(i, 1).Value), 3)
        Else
            Cells(i, 3).Value = Mid(code, 1, hyphenIdx) + LeadingZeros(OnlyNumbers(Mid(code, hyphenIdx + 1)), 3)
        End If
    Next

End Sub
也可以使用以下数组公式(CTRL+SHIFT+ENTER)

=文本(最大值(中间(“&A3,行($A$1:$A$99),列($A$1:$CU$1))+0,0)),“000”)

注意:公式限制为99个字符,但如果存在超过99个字符的单元格,则可以轻松扩展为99个字符

也可以使用以下数组公式(CTRL+SHIFT+ENTER)

=文本(最大值(中间(“&A3,行($A$1:$A$99),列($A$1:$CU$1))+0,0)),“000”)

注意:公式限制为99个字符,但如果存在超过99个字符的单元格,则可以轻松扩展为99个字符


我会用不同的方法来处理宏

  • 将原始数据读入vba宏以加快处理速度
  • 使用正则表达式获取字符串的相关部分
  • 格式化终端数字,使其具有适当数量的前导零
  • 将结果写入另一个VBA数组——同样是为了提高速度
  • 将结果写回工作表并格式化
  • 根据需要格式化结果
例如:

Option Explicit
Sub getnumber()
    Dim wsSrc As Worksheet
    Dim vSrc As Variant, vRes As Variant
    Dim rRes As Range
    Dim I As Long

Set wsSrc = Worksheets("sheet1")
With wsSrc

'set results area
    Set rRes = .Cells(1, 3)

'Read data into array for faster processing
    vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With

'create results array
ReDim vRes(1 To UBound(vSrc), 1 To 1)

'Fill vres with the converted data
For I = 1 To UBound(vRes, 1)
    vRes(I, 1) = reFormat(vSrc(I, 1))
Next I

'Size the results range
Set rRes = rRes.Resize(rowsize:=UBound(vRes, 1))

'Clear the area and write the new data
With rRes
    .EntireColumn.Clear

   'In case a value is solely numeric, as in A5 of example
    .NumberFormat = "@"

    .Value = vRes
    .EntireColumn.AutoFit
    .Style = "Output"
End With

End Sub



Function reFormat(ByVal S As String) As String
    Dim RE As Object, MC As Object

Set RE = CreateObject("vbscript.regexp")
With RE
    .Global = True
    .MultiLine = True
    .Pattern = "(^\D\d+-)?\D*(\d+)"
    If .test(S) = True Then
        Set MC = .Execute(S)
        With MC(0)
            reFormat = .submatches(0) & Format(.submatches(1), "000")
        End With
    End If
End With

End Function

下面是正则表达式模式的简要说明:

(^\D\D+-)?\D*(\D+) 选项:区分大小写^$分线比赛

  • (^\D\D+-)?
    • ^
    • \D
    • \d+
      • +
    • -
  • \D*
    • *
  • (\d+)
    • \d+
      • +

使用

创建宏时,我会使用稍微不同的宏

  • 将原始数据读入vba宏以加快处理速度
  • 使用正则表达式获取字符串的相关部分
  • 格式化终端数字,使其具有适当数量的前导零
  • 将结果写入另一个VBA数组——同样是为了提高速度
  • 将结果写回工作表并格式化
  • 根据需要格式化结果
例如:

Option Explicit
Sub getnumber()
    Dim wsSrc As Worksheet
    Dim vSrc As Variant, vRes As Variant
    Dim rRes As Range
    Dim I As Long

Set wsSrc = Worksheets("sheet1")
With wsSrc

'set results area
    Set rRes = .Cells(1, 3)

'Read data into array for faster processing
    vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With

'create results array
ReDim vRes(1 To UBound(vSrc), 1 To 1)

'Fill vres with the converted data
For I = 1 To UBound(vRes, 1)
    vRes(I, 1) = reFormat(vSrc(I, 1))
Next I

'Size the results range
Set rRes = rRes.Resize(rowsize:=UBound(vRes, 1))

'Clear the area and write the new data
With rRes
    .EntireColumn.Clear

   'In case a value is solely numeric, as in A5 of example
    .NumberFormat = "@"

    .Value = vRes
    .EntireColumn.AutoFit
    .Style = "Output"
End With

End Sub



Function reFormat(ByVal S As String) As String
    Dim RE As Object, MC As Object

Set RE = CreateObject("vbscript.regexp")
With RE
    .Global = True
    .MultiLine = True
    .Pattern = "(^\D\d+-)?\D*(\d+)"
    If .test(S) = True Then
        Set MC = .Execute(S)
        With MC(0)
            reFormat = .submatches(0) & Format(.submatches(1), "000")
        End With
    End If
End With

End Function

下面是正则表达式模式的简要说明:

(^\D\D+-)?\D*(\D+) 选项:区分大小写^$分线比赛

  • (^\D\D+-)?
    • ^
    • \D
    • \d+
      • +
    • -
  • \D*
    • *
  • (\d+)
    • \d+
      • +

创建时使用

如果在一列中我们有Adapa S11或R1 Adapa S2500怎么办?@MichałTurczyn for Adapa S11将给出结果011。数据最多只有3位数字。但是,如果超过3,则为2500。但是,我确信该值最多只有3位。如果在列中有Adapa S11或R1 Adapa S2500会怎么样?Adapa S11的@MichałTurczyn将给出结果011。数据最多只有3位数字。但是,如果超过3,则为2500。但是,我确信该值最多只有3位。请原谅我的问题,我是否需要将函数添加到我的代码中或为答案创建新模块?我确实理解
函数
,但我没有理解您在
CopySpecial
@MohamadFaisal上的最后一部分。您可以将其全部放在一个模块中。请原谅我的问题,我需要将函数添加到我的代码中还是创建新模块来获得答案?我确实理解
函数
,但我没有理解你在
CopySpect
@MohamadFaisal上的最后一部分。你可以把它全部放在一个模块中。