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

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

Ответ 1

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

Диск:\Папка\подпапка\FileName.Ext

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

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

Это говорит нам, что right-most\находится в символе 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)))

Ответ 2

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

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

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

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

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

Ответ 3

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

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

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

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

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

Ответ 4

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

Уверен, что принятая формула 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, "\"))

Ответ 5

Просто придумал это решение, не нужно 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"

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

Ответ 6

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

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

Строка (в ячейке A1): "One.two.three.four"

Формула

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

Результат: 14

Во-первых,

ROW($1:$99)

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

Далее

MID(A1,ROW($1:$99),1)

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

Далее

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

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

Последний,

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

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

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

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

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

Варианты:

=MAX((MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1)=".")*ROW(OFFSET($A$1,,,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:$99),1)=".",ROW($1:$99)),2) determines the 2nd occurrence of the match

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

=MAX(IF(MID(I16,ROW($1:$99),2)=".t",ROW($1:$99))) 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!

Ответ 7

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

Найти, что

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

=FIND(B1,A1)-1

Ответ 8

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

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

Ответ 9

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

Добавьте функцию в VBA в WorkBook, Worksheet или VBA Module

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

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

=lastsegment(B1,"/")

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

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

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

Ответ 11

Cell A1 = find/the/position/of/the last slash

Простой способ сделать это - перевернуть текст, а затем найти первый слэш как обычно. Теперь вы можете получить длину полного текста минус это число.

Вот так:

=LEN(A1)-FIND("/",REVERSETEXT(A1),1)+1

Это возвращает 21, позиция последнего /