Excel: последнее совпадение символов и строк в строке
есть ли эффективный способ определить последнее совпадение символа / строки в строке с помощью базовых функций? Т. е. не последний символ / строка на строка, но позиция последнего вхождения символа/строки на строку. Search и find оба работают слева-направо, поэтому я не могу думать, как применить без длительных рекурсивный алгоритм. И данное решение теперь кажется устаревшим.
10 ответов:
Я думаю, что понимаю, что вы имеете в виду. Допустим, например, вы хотите самый правый \ в следующей строке (которая хранится в ячейке A1):
Диск:\Папка\Подпапка\Имя Файла.ext
чтобы получить позицию последнего \, вы бы использовали эту формулу:
=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) применить найти и заменить. Например, взяв пример: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 может быть простым и быстрым решением см.: использование флэш-заливки в Excel .

Comments