2013-09-04 13 views
139

Czy istnieje skuteczny sposób identyfikacji ostatniego dopasowania znak/ciąg w ciągu znaków przy użyciu funkcji podstawowych? To znaczy. nie ostatni znak/ciąg z ciąg, ale pozycja ostatniego wystąpienia znaku/ciągu znaków w ciągu. Search i find oba działają od lewej do prawej, więc nie mogę myśleć, jak zastosować bez długiego algorytmu rekursywnego. I this solution wydaje się teraz przestarzałe.Excel: dopasowanie ostatniego znaku/ciągu w ciągu znaków

+3

Bo chcę położenie ostatniej instancji na przykład Kropka "." w napisie "one.two.three.four" – geotheory

+6

Zabawne, jak błędna lektura pytania zjednoczy się w głosowaniu – geotheory

+1

Powiedziałbym, spójrz na to z innej perspektywy, oznacza to, że inni ludzie również nie rozumieli co masz na myśli na twoje pytanie i tak się domyśliłem, że sugestia była właściwym rozwiązaniem ...Nawet wybrana odpowiedź zaczęła się od słowa "Myślę, że rozumiem, co masz na myśli" ... Nie krytyki, ale raczej prośby o ułatwienie odpowiedzi na pytania, które pomogą ludziom łatwiej odpowiedzieć. –

Odpowiedz

265

Myślę, że rozumiem co masz na myśli. Powiedzmy na przykład chcesz najbardziej po prawej \ w następujący ciąg (który jest przechowywany w komórce A1):

dysk: \ Folder \ podkatalog \ nazwa_pliku.ext

Aby uzyskać pozycję ostatniego \ , należy użyć następującego wzoru:

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

to nam mówi prawym najbardziej \ jest znakiem 24. czyni to poprzez patrząc na „@” i zastąpienie bardzo ostatnio „\” z „@”. Określa on ostatnią za pomocą

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

W tym scenariuszu podciąg jest po prostu „\”, który ma długość 1, więc można zostawić poza podział na końcu i po prostu użyć:

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

teraz możemy używać, aby uzyskać ścieżkę folderu:

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

Oto ścieżka folderu bez tylnego \

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

i uzyskać tylko nazwę pliku:

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

Jednak tutaj jest alternatywna wersja postawienie wszystkiego na prawo od ostatniej instancji szczególnym charakterze. Tak chętnie sam przykład, byłoby to również powrót nazwę pliku:

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

przędzenie głowy; spinnning głowy; kręcenie głową; "ok - nie chcesz tego używać bez zrozumienia go, więc ... uh huh, ok, uh huh ... czekaj co? tak! naprawdę to geniusz Czuję się pewnie, że nie pomyślałbym o tym za kilka godzin jeśli nie dni lub tygodnie! " - +1, niestety, ponieważ +5 lub +10 jest trudne do zrobienia samemu --- jeśli-utknąłeś-wyjaśnienie: (używając przykładu) 'SUBSTITUTE' wszystkie (3) wystąpienia' '\' 'with nothing (skróć długość ciągu o 3) -> że' '\' '(the 3rd) jest ostatnim; zastąp to czymś wyjątkowym i 'ZNAJDŹ' pozycję tej wyjątkowej postaci ... niesamowitej ... dzięki! –

+3

To jest sprytne. Po prostu musisz się wystrzegać, że komórka nie zawiera już znaku "@", w przeciwnym razie będziesz musiał użyć czegoś innego. Możesz sprawdzić używając '= ISNUMBER (SEARCH (" @ ", A1))', [zgodnie z propozycją @ gwin003] (http://stackoverflow.com/questions/18617175/excel-check-if-a-cell-contains -a-podciąg). – geotheory

+2

Twoja ostatnia opcja wyodrębniania wszystkiego na prawo od ostatniego wystąpienia jest bardzo doceniana, ponieważ przez większość czasu szukałem "ostatniego wystąpienia ciągu x w ciągu y", moim celem końcowym było naprawdę wszystko. prawo do tego ostatniego wystąpienia. – SSilk

3

Można użyć tej funkcji stworzyłem aby znaleźć ostatnią instancję ciąg wewnątrz łańcucha.

Pewnie przyjęta formuła programu Excel działa, ale jest zbyt trudna do odczytania i użycia. W pewnym momencie musisz się rozpaść na mniejsze kawałki, aby można je było utrzymać. Moja funkcja poniżej jest czytelna, ale nie ma to znaczenia, ponieważ wywołujesz ją w formule przy użyciu nazwanych parametrów. To sprawia, że ​​korzystanie z niego jest proste.

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 

używam go tak:

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

Jak na temat tworzenia i korzystania z funkcji niestandardowej, że w formule? VBA ma wbudowaną funkcję, InStrRev, która dokładnie to, czego szukasz.

umieścić to w nowym module:

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

A twoja funkcja będzie wyglądać następująco (przy założeniu, oryginalny łańcuch jest w B1):

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

To bardzo proste, ale działające rozwiązanie .Jeśli możesz użyć VBA w swoim projekcie, użyj tego. –

0

prosty sposób to zrobić w VBA jest:

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

tigeravatar i Jean-Francois Corbett zasugerowali, aby użyć tej formuły do ​​wygenerowania ciągu znaków z prawej ostatnie wystąpienie znaku "\"

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

Jeśli znak używany jako separator jest przestrzeń, "", wówczas formuła musi zostać zmienione na:

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

Nie trzeba wspomnieć, The " {"Postać może być zastąpiona dowolną postacią, która" normalnie "nie występuje w tekście do przetworzenia.

1

Jestem trochę spóźniony na imprezę, ale może to może pomóc. Link w pytaniu miał podobną formułę, ale moja używa instrukcji IF(), aby pozbyć się błędów.

Jeśli nie boisz się Ctrl + Shift + Enter, możesz całkiem dobrze wykorzystać formułę tablicową.

łańcuch znaków (na komórki A1) "one.two.three.four"

Wzór:

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

Wynik: 14

pierwsze

ROW($1:$99) 

zwraca tablicę liczb całkowitych od 1 do 99: {1,2,3,4,...,98,99}.

Następnie

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

zwraca tablicę ciągów 1 długości występujących w ciągu docelowym, a następnie zwraca puste ciągi po długości łańcucha cel został osiągnięty: {"o","n","e",".",..."u","r","","",""...}

Dalej,

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

porównuje każdy element w tablicy z łańcuchem "." i zwraca albo indeks znaku w łańcuchu czy fałsz: {FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

ostatni

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

Zwraca maksymalną wartość tablicy: 14

zalet tego wzoru jest to, że jest krótki , stosunkowo łatwe do zrozumienia i nie wymaga żadnych unikalnych znaków.

Wadami są wymagane użycie kombinacji Ctrl + Shift + Enter i ograniczenie długości łańcucha. Można to obrobić przy wariacji pokazanej poniżej, ale ta odmiana wykorzystuje funkcję PRZESUNIĘCIE(), która jest funkcją lotną (odczyt: wolna).

Nie wiem, jaka jest szybkość tej formuły w porównaniu do innych.

Wariacje:

=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! 
3

Wystarczy wymyślił tego rozwiązania, bez VBA potrzebne;

Znajdź ostatni występ "_" w moim przykładzie;

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

Objaśnienie od wewnątrz;

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" 

Mam nadzieję, że było to pomocne.

1

Biorąc pod uwagę część komentarza dokonanej przez @SSilkmój koniec bramki naprawdę było dostać wszystko na prawo od tego ostatniego wystąpienia alternatywne podejście z bardzo prostego wzoru jest skopiować kolumnę (słownie A) ciągów a na kopii (powiedzmy w kolumnie B) zastosowanie Znajdź i zamień. Na przykład biorąc przykład: Drive:\Folder\SubFolder\Filename.ext

Find what

ta zwraca co pozostaje (tutaj Filename.ext) po ostatniej instancji bez względu na postać jest wybrana (tutaj \), który jest czasami cel i tak ułatwia znalezienie pozycję ostatni taki znak z krótkiej formuły takie jak:

=FIND(B1,A1)-1 
0

bardzo późno do partii, ale proste rozwiązanie jest przy użyciu VBA, aby utworzyć funkcję niestandardową.

Dodaj funkcję VBA w skoroszycie arkusza lub modułu VBA

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

Wtedy formuła komórka

=lastsegment(B1,"/") 

w komórce i ciąg do przeszukania w komórce B1 będzie wypełnij komórkę tekstem kończącym ostatni "/" z komórki B1. Brak limitu długości, żadnych niejasnych formuł. Jedynym minusem, jaki mogę sobie wyobrazić, jest potrzeba skoroszytu z obsługą makr.

Dowolną funkcję VBA użytkownika można wywołać w ten sposób, aby zwrócić wartość do formuły komórki, w tym jako parametr wbudowanej funkcji programu Excel.

Jeśli zamierzasz korzystać z funkcji mocno będziemy chcieli sprawdzić przypadku, gdy znak nie jest w łańcuchu, a następnie ciąg jest pusty, itp

Powiązane problemy