【问题标题】:Excel Mid Find Find, looking right to leftExcel Mid Find 查找,从右到左
【发布时间】:2016-09-21 17:39:23
【问题描述】:

我希望从长的非结构化文本中解析出一段特定的文本。我要捕捉的部分总是有一个“x”,左右两边都是整数。

这是我的公式:

=IFERROR(SUBSTITUTE(RIGHT(LEFT(G2,FIND("x",G2)-1),FIND("_",G2)-3)&MID(G2,FIND("x",G2),FIND("_",G2)-2),"_",""),"1x1")

另一个版本我尝试用 OR 语句处理空格(这不起作用)

=IFERROR(SUBSTITUTE(RIGHT(LEFT(G4,FIND("x",G4)-1),FIND(OR("_"," "),G4)-3)&MID(G4,FIND("x",G4),FIND("_",G4)-2),"_",""),"1x1")

原始文本 - 我的公式的结果 - 期望的结果

Q1-Q4_Year_Source_Type_P_LongName_300x250_Target_Server 300x250 300x250
Q1-Q4_Year_Client_Client Year_Type_P_LongName_1600x1000_Site_Server 600x100 1600x1000
02.04 Search Sponsorship - 728x90   1x1 728x90
Some Website_300x600 ROS Display    ebsite300x600 ROS Di    300x600

理想情况下,如果我可以让 MID 公式 MID(G2,FIND("x",G2),FIND("_",G2)-2) 从右到左而不是从左到右读取,我想我的状态会很好。

谢谢。

【问题讨论】:

  • 我知道您正在使用公式,但是 VBA 解决方案可以吗?

标签: excel parsing text find


【解决方案1】:

有一个从字符串中提取数字的标准公式(有很多变体):-

=LOOKUP(99^99,--("0"&MID(A1,MIN(SEARCH({0,1,2,3,4,5,6,7,8,9},A1&"0123456789")),ROW($1:$15))))

所以您可以使用它从“x”左侧的几个字符开始,然后从“x”本身开始。建议对这些使用辅助单元格以避免公式过长,因此如果您的原始字符串在 A1 中:-

=mid(A1,find("x",A1)-5,999)   in B1

=mid(A1,find("x",A1),999)     in C1

那么对于 D1 中的第一个数字

=LOOKUP(99^99,--("0"&MID(B1,MIN(SEARCH({0,1,2,3,4,5,6,7,8,9},B1&"0123456789")),ROW($1:$15))))

对于 E1 中的第二个数字

=LOOKUP(99^99,--("0"&MID(C1,MIN(SEARCH({0,1,2,3,4,5,6,7,8,9},C1&"0123456789")),ROW($1:$15))))

并将它们连接在一起:-

=D1&"x"&E1

【讨论】:

    【解决方案2】:

    这是一个复杂的公式

    • 将字符串拆分为单个单词的数组,由spaceunderscore 分隔
    • 查找与模式nnnxnnn 匹配的单词,该模式定义为:
      • 以数字开头
      • 后跟小写 x(如果 x 可能是任何一种情况,请在下面的公式中将 FIND 替换为 SEARCH
      • 以数字结尾
    • 该函数将返回字符串中与该模式匹配的最后一个单词。

    公式包括几个“子公式”

    我们将字符串按spaceunderscore 拆分成一个单词数组:

    =TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99))
    

    在上面SEQ是一个命名公式:(Formulas ► Define Name

        =IF((ROW(INDEX(Sheet1!$1:$65536,1,1):INDEX(Sheet1!$1:$65536,255,1))-1)*99=0,1,(ROW(INDEX(Sheet1!$1:$65536,1,1):INDEX(Sheet1!$1:$65536,255,1))-1)*99)
    

    该公式生成一系列数字1,99,198,297, ...,这为第一个公式中的MID 函数提供了一个很好的起点。

    然后我们使用 LEFT 和 MID 函数来查找包含 x 并且在 x 之前和之后有数字的单词

    ISNUMBER(-LEFT(TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)),FIND("x",TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))-1))
    
    ISNUMBER(-MID(TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)),FIND("x",TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))+1,99)))
    

    将这两个公式相乘将返回一个由 0 和 1 组成的数组,表示匹配或不匹配模式的单词。

    1/(...)
    

    然后将返回一个包含1DIV/0 错误的数组。

    使用LOOKUP 的向量形式将返回我们的字符串数组中的值,该值与我们的模式匹配数组中的匹配位置相同。

    =LOOKUP(2,1/(ISNUMBER(-LEFT(TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)),FIND("x",TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))-1))*ISNUMBER(-MID(TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)),FIND("x",TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))+1,99))),TRIM(MID(SUBSTITUTE(SUBSTITUTE(A1,"_"," ")," ",REPT(" ",99)),SEQ,99)))
    

    我会注意到,使用 VBA 和正则表达式,相同的模式可以表示为 \d+x\d+

    用户定义的函数可以用来完成同样的事情,一旦你流利了,只需要一小部分时间来设计;

    Option Explicit
    Function ExtractMeasure(S As String) As String
        Dim RE As Object, MC As Object
    
    Set RE = CreateObject("vbscript.regexp")
    With RE
        .Pattern = "\d+x\d+"
        .Global = False
        .ignorecase = False 'Case Sensitive
        If .test(S) = True Then
            Set MC = .Execute(S)
            ExtractMeasure = MC(0)
        End If
    End With
    End Function
    

    【讨论】:

      【解决方案3】:

      在这种情况下,最好在EXCEL中使用正则表达式。在EXCEL中使用正则表达式请参考下面的帖子。但是,您必须为此使用 VBA。 How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-24
        • 1970-01-01
        • 2011-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-11
        • 2022-01-18
        相关资源
        最近更新 更多