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
Это возвращает то, что осталось (вот 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 .