Есть ли эффективный способ идентифицировать последнее совпадение символов/строк в строке с использованием базовых функций? То есть а не последний символ/строка из строки, но позиция символа/строки в последнем случае в. Search
и find
работают слева направо, поэтому я не могу думать, как применять без длинного рекурсивного алгоритма. И это решение теперь кажется устаревшим.
Excel: последнее совпадение символов/строк в строке
Ответ 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.
Если вы собираетесь использовать эту функцию в большой степени, вам нужно будет проверить случай, когда символ не в строке, тогда строка пуста и т.д.
Ответ 10
В более новых версиях Excel (2013 и выше) флэш-заливка может быть простым и быстрым решением, см. Использование Flash Fill в Excel.
Ответ 11
Cell A1 = find/the/position/of/the last slash
Простой способ сделать это - перевернуть текст, а затем найти первый слэш как обычно. Теперь вы можете получить длину полного текста минус это число.
Вот так:
=LEN(A1)-FIND("/",REVERSETEXT(A1),1)+1
Это возвращает 21, позиция последнего /