【问题标题】:VBA replace a string EXCEL 2019VBA替换字符串EXCEL 2019
【发布时间】:2021-06-05 21:23:26
【问题描述】:

我无法提取给定地址单元格的邮政编码,如下所示:

“108, avenue du Grand Sud 37 170 CHAMBRAY les TOURS”。

我用过:

=RECHERCHE(9^9;--("0"&STXT(A2;MIN(CHERCHE({0.1.2.3.4.5.6.7.8.9};A2&"0 123456789"));LIGNE($1:$100))))

这有时有效,有时与地址开头的街道编号无关(此处为“108”)。

问题在于模式“37 170”的空间。我想删除模式中的空白。有没有一种正则表达式方法来搜索这个模式“## ###”,然后删除这个有毒的空格?

谢谢你的诡计。

我试过这段代码:

Function toto(r, Optional u = 0)
Application.Volatile
Dim i%, j%, adr$, cp$, loca$, x
  x = Split(r)
  For i = 0 To UBound(x)
    If x(i) Like "#####" Then Exit For
  Next
  If i > UBound(x) Then
    adr = r.Value 'facultatif
  Else
    cp = x(i)
    For j = 0 To i - 1: adr = adr & x(j) & " ": Next
    adr = Left$(adr, Len(adr) + (Len(adr) > 1))
    For j = i + 1 To UBound(x): loca = loca & x(j) & " ": Next
    loca = Left$(loca, Len(loca) + (Len(loca) > 1))
  End If
  x = Array(adr, cp, loca)
  If 0 < u And u < 4 Then toto = x(u - 1) Else toto = x
End Function

上面的代码适用于拆分地址,包括街道号码、邮政编码和城市名称。但当邮政编码为## ### = 2 位整数 - 空格 - 3 位整数时,它不起作用。

编辑: 2021 年 6 月 1 日

由于我的问题似乎不够清楚,让我们改写一下:

给定一个 Excel 工作表,其中包含 A 列的每个单元格,从 A1 到 A10000,完成这样的地址:

“2 rue Rene cassin Centre Commercial Châlon 2 Sud 71 100 CHALON SUR SAONE” 或者这个: "15, Rue Emile Schwoerer 68 000 COLMAR"

其中“71 100”和“68 000”是格式不正确的邮政编码,因为前 2 个数字和最后 3 个数字之间有多余的空格。

我需要拆分Ai单元格内容才能获得:

  • 在单元格 Bi 中:文本(街道等)位于“错误”邮政编码的前 2 个数字之前的左侧,
  • 在单元格 Ci 中:具有正确格式的邮政编码(“71100”而不是“71 100”),
  • 在单元格 Di 中:邮政编码后的文本(城市名称)。

是一种围绕邮政编码的左右提取。

上面我贴的代码不起作用。

为了获得正确的邮政编码格式,我尝试了正则表达式以下功能:

Function FindReplaceRegex(rng As Range, reg_exp As String, replace As String)
    Set myRegExp = New RegExp
    myRegExp.IgnoreCase = False
    myRegExp.Global = True
    myRegExp.Pattern = reg_exp
    
    FindReplaceRegex = myRegExp.replace(rng.Value, replace)
End Function

但我无法确定正确的正则表达式模式以消除邮政编码中的空格。 PEH 给了我以下模式:

(.*)([0-9]{2} ?[0-9]{3})(.*)

在使用该功能时,我尝试通过以下方式定义替换模式:

(.*)([0-9]{2}[0-9]{3})(.*)

但这行不通。希望这能澄清我的问题。

欢迎任何想法。谢谢

【问题讨论】:

  • 这只是 VBA 或 Excel 工作簿格式吗?

标签: excel vba excel-formula


【解决方案1】:

如果这些输入字符串始终具有相同的模式,请尝试:

=CONCAT(FILTERXML("<t><s>"&SUBSTITUTE(A1," ","</s><s>")&"</s></t>","//s[.*0=0]"))

根据您的需要/边缘情况,您可以添加更多 xpath 表达式。

【讨论】:

  • 您好 Amiga500,感谢您的帖子。我会测试它并让你知道
  • 您好 JvdV,感谢您调整公式。似乎工作。我会测试它并反馈给你。
  • 嗨 Amiga500,我已将您的代码插入到工作表中(而不是模块中),但没有任何反应。
  • 是否可以只删除模式“## ###”中的这个 d..d 空格:始终将 5 位数字分成 2 组,并将其替换为“#### #" ?我试图深入研究正则表达式方法。它不是那么简单,而且在 Excel 2019 中似乎不能很好地工作,至少在我的电脑上是这样。
  • 通过乘法识别数字项的一种非常棘手的方法(例如检查节点内容是否 x 0 = 0),喜欢它:-)
【解决方案2】:

如果这是 VBA,我有一个解决方案(请原谅蹩脚的命名约定,我在等待 SQL 刷新时在工作中草草写下):

Sub test1()

a0 = Cells(1, 1)  'Get the text, in this case "108, avenue du Grand Sud 37 170 CHAMBRAY les TOURS"
aa = Replace(a0, ",", " ")  'Make all delimiters of same type, so removing commas, you may need to add more replace work here?
ab = Application.Trim(aa)  'Reduce all whitespace to single entries, i.e. " " rather than "  "
ac = Split(ab, " ", -1)  'Now split by that single whitespace entry

Dim txt()

i2 = 0
lastIsNumeric = False
For i1 = 0 To UBound(ac) - 1  'Step through each entry in our "split" list

    If IsNumeric(ac(i1)) = True And IsNumeric(ac(i1 + 1)) = True Then     
        'Two numbers back to back, join
        ReDim Preserve txt(i2)
        txt(i2) = ac(i1) + ac(i1 + 1)
        i2 = i2 + 1
        i1 = i1 + 1
    Else
        'Not two numbers back to back, don't join
        ReDim Preserve txt(i2)
        txt(i2) = ac(i1)
        i2 = i2 + 1
    
    End If

Next i1


If IsNumeric(ac(UBound(ac))) = False Then
    'Need to add last entry to txt()
    ReDim Preserve txt(UBound(txt) + 1)
    txt(UBound(txt)) = ac(UBound(ac))
End If

End Sub

编辑 2021-06-01: 以上将生成您地址中所有条目的列表(txt)。然后,您可以根据需要重新组装,或仅提取邮政编码。

如果你想要它作为一个函数,那么它会是:

Public Function getPostcode(a0)

aa = Replace(a0, ",", " ")
ab = Application.Trim(aa)
ac = Split(ab, " ", -1)

Dim txt()

i2 = 0
lastIsNumeric = False
For i1 = 0 To UBound(ac) - 1
    If IsNumeric(ac(i1)) = True And IsNumeric(ac(i1 + 1)) = True Then
        'Two numbers back to back, join
        ReDim Preserve txt(i2)
        txt(i2) = ac(i1) + ac(i1 + 1)
        i2 = i2 + 1
        i1 = i1 + 1
    Else
        'Not two numbers back to back, don't join
        ReDim Preserve txt(i2)
        txt(i2) = ac(i1)
        i2 = i2 + 1
    
    End If

Next i1


If IsNumeric(ac(UBound(ac))) = False Then
    'Need to add last entry to txt()
    ReDim Preserve txt(UBound(txt) + 1)
    txt(UBound(txt)) = ac(UBound(ac))
End If

'Re-assemble string for return
rtnTxt = ""
For i1 = 0 To UBound(txt)
    rtnTxt = rtnTxt & " " & txt(i1)
Next i1

getPostcode = rtnTxt

End Function

【讨论】:

  • 嗨装饰 - 它在这里工作。你如何使用它?您想将其用作函数还是子函数?
  • 现已编辑以添加可在工作表级别使用的函数。但我建议您着手使用 VBA - 这意味着您可以对其进行调整以提供您想要的东西,而不仅仅是在这里提出一个“黑匣子”解决方案。
  • 您好 Amiga500,感谢您的帖子。我很抱歉,我没有任何错误的意思。再次抱歉。我已经尝试了您提供的第一个子过程,但是当从工作表或从包含要在 A 列中清理的单元格的工作表模块(Excel 2019)启动时,它不起作用(没有任何反应)。该功能有效,但确实在我的示例中不返回城市:“CHAMBRAY les TOURS”。这就是我想说的。再次感谢您的贡献。
  • 嗨 Amiga500,我犯了一个错误:当地址包含一个城市名称时,它只计算 1 个单词,例如:“FAMILY VILLAGE 30, rue Amédée Gordini 87 000 LIMOGES”,该函数不返回城市名称“LIMOGES”。当城市名称像“CHAMBRAY les TOURS”中那样计数超过 1 个单词时,它就会起作用。
  • 我的错 - 它是一个逻辑漏洞 - 将更新解决方案。问题是我最初的解决方案是当第二个最后一个条目是数字时忽略最后一个条目 - 这是我的错误。如果它是数字,它应该只忽略最后一个条目。 (因为它已经加入到最后一个条目中)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-27
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-21
相关资源
最近更新 更多