Excel: последнее совпадение символов / строк в строке

есть ли эффективный способ определить последнее совпадение символов / строк в строке с помощью базовых функций? Т. е. не последний символ / строка of строка, но позиция последнего вхождения символа / строки на строку. Search и find оба работают слева направо, поэтому я не могу думать, как применять без длительного рекурсивного алгоритма. И данное решение теперь кажется устаревшим.

10 ответов


Я понимаю что ты имеешь в виду. Предположим, например, вы хотите, чтобы самый правый \ в следующей строке (которая хранится в ячейке A1):

Диск:\Папка\Подпапка\Имя Файла.доб

чтобы получить позицию последнего \, вы должны использовать эту формулу:

=FIND("@",SUBSTITUTE(A1,"\","@",(LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))/LEN("\")))

это говорит нам, что самый правый \ находится в символе 24. Он делает это, ища "@" и заменяя самый последний "\" на "@". Он определяет последний, используя

(len(string)-len(substitute(string, substring, "")))\len(substring)

в этом сценарии подстрока просто"\", которая имеет длину 1, поэтому вы можете оставить деление в конце и просто использовать:

=FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))

теперь мы можем использовать это, чтобы получить путь к папке:

=LEFT(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))))

вот путь к папке без трейлинга \

=LEFT(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))-1)

и получить только имя файла:

=MID(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))+1,LEN(A1))

однако, вот альтернативная версия получения всего справа от последнего экземпляра определенного характер. Таким образом, используя наш же пример, это также вернет имя файла:

=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))

как насчет создания пользовательской функции и использования ее в вашей формуле? VBA имеет встроенную функцию,InStrRev, что делает именно то, что вы ищете.

поместите это в новый модуль:

Function RSearch(str As String, find As String)
    RSearch = InStrRev(str, find)
End Function

и ваша функция будет выглядеть так (предполагая, что исходная строка находится в B1):

=LEFT(B1,RSearch(B1,"\"))

tigeravatar и Жан-Франсуа Корбетт предложили использовать эту формулу для генерации строки справа от последнего вхождения символа"\"

=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))

Если символ, используемый в качестве разделителя, - пробел,"", то формула должна быть изменена на:

=SUBSTITUTE(RIGHT(SUBSTITUTE(A1," ",REPT("{",LEN(A1))),LEN(A1))),"{","")

нет необходимости упоминать, символ " {"может быть заменен любым символом, который не" обычно " встречается в тексте для обработки.


Вы можете использовать эту функцию я создал, чтобы найти последнее вхождение строки в строку.

конечно, принятая формула Excel работает, но это слишком сложно читать и использовать. В какой-то момент Вы должны вырваться на более мелкие куски, чтобы он был доступен для обслуживания. Моя функция ниже читаема, но это не имеет значения, потому что вы вызываете ее в Формуле, используя именованные параметры. Это упрощает его использование.

Public Function FindLastCharOccurence(fromText As String, searchChar As String) As Integer
Dim lastOccur As Integer
lastOccur = -1
Dim i As Integer
i = 0
For i = Len(fromText) To 1 Step -1
    If Mid(fromText, i, 1) = searchChar Then
        lastOccur = i
        Exit For
    End If
Next i

FindLastCharOccurence = lastOccur
End Function

Я использую его так:

=RIGHT(A2, LEN(A2) - FindLastCharOccurence(A2, "\"))

просто придумал это решение, не требуется VBA;

найдите последнее появление " _ " в моем примере;

=IFERROR(FIND(CHAR(1);SUBSTITUTE(A1;"_";CHAR(1);LEN(A1)-LEN(SUBSTITUTE(A1;"_";"")));0)

пояснил изнанку;

SUBSTITUTE(A1;"_";"") => replace "_" by spaces
LEN( *above* ) => count the chars
LEN(A1)- *above*  => indicates amount of chars replaced (= occurrences of "_")
SUBSTITUTE(A1;"_";CHAR(1); *above* ) => replace the Nth occurence of "_" by CHAR(1) (Nth = amount of chars replaced = the last one)
FIND(CHAR(1); *above* ) => Find the CHAR(1), being the last (replaced) occurance of "_" in our case
IFERROR( *above* ;"0") => in case no chars were found, return "0"

надеюсь, это было полезно.


я немного опаздываю на вечеринку, но, возможно, это может помочь. Ссылка в вопросе имела аналогичную формулу, но моя использует оператор IF (), чтобы избавиться от ошибок.

если вы не боитесь Ctrl + Shift+Enter, вы можете довольно хорошо работать с формулой массива.

строка (в ячейке A1): "один.два.три.четыре"

Формула:

{=MAX(IF(MID(A1,ROW(:),1)=".",ROW(:)))}  use Ctrl+Shift+Enter

результат: 14

во-первых,

ROW(:)

возвращает массив целых чисел из 1 до 99: {1,2,3,4,...,98,99}.

далее

MID(A1,ROW(:),1)

возвращает массив строк длиной 1, найденных в целевой строке, а затем возвращает пустые строки после достижения длины целевой строки:{"o","n","e",".",..."u","r","","",""...}

далее

IF(MID(I16,ROW(:),1)=".",ROW(:))

сравнивает каждый элемент массива в строку "."и возвращает либо индекс символа в строке, либо FALSE:{FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

последние,

=MAX(IF(MID(I16,ROW(:),1)=".",ROW(:)))

возвращает максимальное значение массив: 14

преимущества этой формулы в том, что она короткая, относительно проста в понимании и не требует каких-либо уникальных символов.

недостатками являются обязательное использование Ctrl+Shift+Enter и ограничение длины строки. Это можно обойти с помощью варианта, показанного ниже, но этот вариант использует функцию OFFSET (), которая является изменчивой (читать: медленной) функцией.

не уверен, что скорость этой формулы по сравнению с другими.

варианты:

=MAX((MID(A1,ROW(OFFSET($A,,,LEN(A1))),1)=".")*ROW(OFFSET($A,,,LEN(A1)))) works the same way, but you don't have to worry about the length of the string

=SMALL(IF(MID(A1,ROW(:),1)=".",ROW(:)),2) determines the 2nd occurrence of the match

=LARGE(IF(MID(A1,ROW(:),1)=".",ROW(:)),2) determines the 2nd-to-last occurrence of the match

=MAX(IF(MID(I16,ROW(:),2)=".t",ROW(:))) matches a 2-character string **Make sure you change the last argument of the MID() function to the number of characters in the string you wish to match!

учитывая часть комментария @SSilk моей конечной целью действительно было получить все справа от этого последнего события альтернативный подход, с очень простой формулой, чтобы скопировать столбец (скажем A) строк и на копии (скажем, ColumnB) применить Find и Replace. Например, возьмем пример:Drive:\Folder\SubFolder\Filename.ext

Find what

Это возвращает то, что осталось (вот Filename.ext) после последнего экземпляра какой бы персонаж ни был выбран (здесь \), который иногда является целью в любом случае и облегчает поиск позиции последнего такого символа с короткой формулой, такой как:

=FIND(B1,A1)-1

простой способ сделать это в VBA:

YourText = "c:\excel\text.txt"
xString = Mid(YourText, 2 + Len(YourText) - InStr(StrReverse(YourText), "\" ))

очень поздно на вечеринку, но простое решение использует VBA для создания пользовательской функции.

добавьте функцию в VBA в книге, листе или модуле VBA

Function LastSegment(S, C)
    LastSegment = Right(S, Len(S) - InStrRev(S, C))
End Function

тогда формула ячейки

=lastsegment(B1,"/")

в ячейке и строка для поиска в ячейке B1 заполнит ячейку текстом, завершающим последний " / " из ячейки B1. Никаких ограничений по длине, никаких непонятных формул. Единственный недостаток, который я могу думать, - это необходимость макроса с поддержкой рабочая тетрадь.

любая пользовательская функция VBA может быть вызвана таким образом, чтобы вернуть значение в Формулу ячейки, в том числе в качестве параметра встроенной функции Excel.

Если вы собираетесь использовать функцию сильно, вы захотите проверить случай, когда символ не находится в строке, тогда строка пуста и т. д.


в более новых версиях Excel (2013 и выше) flash fill может быть простым и быстрым решением см.:использование Flash Fill в Excel .