VBA-提取字符串的特定部分

时间:2018-10-09 13:25:05

标签: excel vba excel-vba

我对VBA还是很陌生,但总体而言不是编程。我试图在VBA中创建一个宏,以将电话名称列表的型号名称格式化为可管理的格式。例如。我想要以下名称:

  

P10,12.9厘米(5.1英寸),4 GB,64 GB,20 MP

要设置为

  

P10 5.1英寸64 GB

我已经成功使用SplitMid提取了格式化名称的前两个元素。

这是我前两个部分的代码:

'First part of format
firstPart = Trim(Split(modelName, ",")(0))
Debug.Print formattedModelName

'Second part of format
openPos = InStr(modelName, "(")
closePos = InStr(modelName, ")")

secondPart = Mid(modelName, openPos + 1, closePos - openPos - 1)

我的问题是如何提取64 GB而不是4 GB。 我尝试遍历所有字符并保存最后5个字符,以查看它们是否与我想要的匹配。但是必须有更好的方法。

我将不胜感激, 非常感谢

编辑

这是输入和输出的另一个示例: 输入:

  

iPhone iPhone SE,10,2厘米(4“),640 x 1136像素,16 GB,12 MP,iOS 9,排序,Grå

预期输出:

  

iPhone iPhone SE 4“ 16 GB

6 个答案:

答案 0 :(得分:4)

尝试

Option Explicit

Function oneTwoThree(str As String)

    Dim vals As Variant

    vals = Split(str, ",")

    oneTwoThree = Join(Array(vals(0), _
                             Split(Split(vals(2), "(")(1), ")")(0), _
                             Trim(vals(4 + (InStr(1, vals(4), "gb", vbTextCompare) = 0)))), " ")

End Function

enter image description here

答案 1 :(得分:4)

如何使用RegEx提取值并使用最后一个值。只需添加对库的引用:“ Microsoft VBScript正则表达式5.5”。然后,您可以执行此操作。

Option Explicit

Public Function xx()
Dim modelName As String
Dim firstPart As String
Dim Pattern As String
Dim GBString As String
Dim regEx As New RegExp
Dim finalName As String
Dim matches As MatchCollection

Let modelName = "P10, 12,9 cm (5.1""), 4 GB, 64 GB, 20 MP"
firstPart = Trim(Split(modelName, ",")(0))


With regEx
    .Global = True
    .IgnoreCase = True
    .Pattern = "[0-9]+ GB"
End With

Set matches = regEx.Execute(modelName)

If matches.Count > 0 Then
    GBString = matches(matches.Count)
Else
    GBString = "<unknown GB>"
End If

finalName = firstPart + GBString

End Function

答案 2 :(得分:2)

尝试下一段代码:

Dim modelName As String: modelName = "P10, 12,9 cm (5.1""), 4 GB, 64 GB, 20 MP"
Dim data() As String: data = Split(modelName, ",")
Dim firstPart As String
Dim secondPart As String
Dim thirdPart As String

firstPart = Trim(data(0))
secondPart = Trim(Replace(Mid(data(2), InStr(data(2), "(") + 1), ")", ""))
thirdPart = Trim(data(4))


MsgBox firstPart & " " & secondPart & " " & thirdPart

您必须非常注意定界符数据子字符串。例如,如果您的主要文本是P10, 12 cm (5.1"), 4 GB, 64 GB, 20 MP,则该代码将不再起作用。假设您始终在数据元素之间使用逗号和空格,而可以改为:

Dim modelName As String: modelName = "P10, 12,9 cm (5.1""), 4 GB, 64 GB, 20 MP"
Dim data() As String: data = Split(modelName, ", ")
Dim firstPart As String
Dim secondPart As String
Dim thirdPart As String

firstPart = Trim(data(0))
secondPart = Trim(Replace(Mid(data(1), InStr(data(1), "(") + 1), ")", ""))
thirdPart = Trim(data(3))

MsgBox firstPart & " " & secondPart & " " & thirdPart

它将始终有效。

如果元素4 MB并不总是存在,请执行以下操作:

Dim modelName As String: modelName = "P10, 12,9 cm (5.1""), 4 GB, 64 GB, 20 MP"
Dim data() As String: data = Split(modelName, ", ")
Dim firstPart As String
Dim secondPart As String
Dim thirdPart As String

firstPart = Trim(data(0))
secondPart = Trim(Replace(Mid(data(1), InStr(data(1), "(") + 1), ")", ""))

Select Case InStr(modelName, "4 GB")
    Case 0
        thirdPart = Trim(data(2))
    Case Else
        thirdPart = Trim(data(3))
End Select

MsgBox firstPart & " " & secondPart & " " & thirdPart

更新:

我想现在我完全明白了你想要的。我用您在问题上给我们的三个示例尝试了下一个代码,该示例成功了(问题是我不知道您想要的是MD值之前的最后一个数据值。

Dim modelName As String
Dim data() As String
Dim firstPart As String
Dim secondPart As String
Dim thirdPart As String

modelName = "P10, 12,9 cm (5.1""), 4 GB, 64 GB, 20 MP"
data = Split(modelName, ", ")
firstPart = Trim(data(0))
secondPart = Trim(Replace(Mid(data(1), InStr(data(1), "(") + 1), ")", ""))
thirdPart = Trim(data(Application.Match("*MP", data, 0) - 2))

MsgBox firstPart & " " & secondPart & " " & thirdPart

您可以尝试

modelName = "P10, 12,9 cm (5.1""), 64 GB, 20 MP"

或搭配

modelName = "iPhone iPhone SE, 10,2 cm (4""), 640 x 1136 pixel, 16 GB, 12 MP, iOS 9, Sort, Grå"

它将始终为您提供答案。

答案 3 :(得分:2)

这是我制作的应该始终有效的功能。

为处理获取正确存储值的问题,它通过用逗号分隔的每个部分并寻找“ GB”,然后在这些部分之一中跟踪最大值,然后该最大值必须是存储值

Public Function FormatName(Inp As String) As String

    Dim ArrInp As Variant, i As Integer, Temp As String

    ArrInp = Split(Trim(Inp), ",")
    FormatName = ArrInp(0) & " " & Mid(Inp, InStr(Inp, "(") + 1, InStr(Inp, ")") - InStr(Inp, "(") - 1)

    For i = 1 To UBound(ArrInp)
        If InStr(UCase(ArrInp(i)), "GB") <> 0 And Val(ArrInp(i)) > a Then
            Temp = ArrInp(i)
        End If
    Next
    FormatName = FormatName & Temp

End Function

希望这会有所帮助。

答案 4 :(得分:2)

我参加聚会不晚!

我通过简单的公式方法进行了快速尝试,并提出了类似的方法,似乎可以使用当前的样本数据集。

如果您的文本在A1单元格中,请尝试使用以下公式提取相关信息,

enter image description here

enter image description here

  1. =LEFT(A1,(FIND(",",A1,1)-1))

  2. =MID(A1,SEARCH("(",A1)+1,SEARCH(")",A1)-SEARCH("(",A1)-1)

  3. =MAX(VALUE(MID(A1,FIND("GB",A1)-3,2)),VALUE(IFERROR(MID(A1,IFERROR(FIND("GB",A1,FIND("GB",A1)+1),0)-3,3),0)))&" GB"

答案 5 :(得分:1)

使用正则表达式:

假设:

  • 电话名从字符串的开头开始,以第一个逗号结束
  • 屏幕尺寸是第一个条目,它以可能为十进制的数字开头并以"
  • 结尾
  • 内存是最后条目,该条目以整数开头,以GB
  • 为此,我们将使用Replace方法

Option Explicit
Function phone(S As String) As String
    Dim RE As Object
    Const sPat As String = "^([^,]+).*?(\b[\d.]+"").*(\b\d+\s+GB).*"

Set RE = CreateObject("vbscript.regexp")
With RE
    .Pattern = sPat
    .Multiline = True
    phone = .Replace(S, "$1 $2 $3")
End With

End Function

enter image description here

正则表达式和替换模式的说明

^([^,]+).*?(\b[\d.]+").*(\b\d+\s+GB).*

选项:区分大小写; ^ $匹配行间的中断

$ 1 $ 2 $ 3

RegexBuddy创建