基本関数を使用して文字列内の最後の文字/文字列の一致を識別する効率的な方法はありますか?すなわち最後の文字/文字列of文字列ではなく、文字/文字列の最後の出現位置in文字列。 Search
とfind
はどちらも左から右に動作するので、長い再帰的アルゴリズムなしでは適用方法を考えることができません。そして この解決策 は今や時代遅れに見えます。
私はあなたが何を意味しているのかわかります。たとえば、次の文字列(セルA1に格納されている)の右端の\が必要だとします。
ドライブ:\ Folder\SubFolder\Filename.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とJean-FrançoisCorbettは、この式を使って、最後に出現した "\"の文字列の右側に文字列を生成することを提案しました。
=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"
これが役に立ったことを願っています。
@SSilkによって作られたコメントの一部を考えると、私の最終目標は本当に最後の出現の右側にすべてを入れることでした非常に単純な式による代替アプローチは列をコピーすることです(A
と言う)文字列の)とそのコピー(ColumnBなど)には、検索と置換を適用します。例えば、Drive:\Folder\SubFolder\Filename.ext
という例を考えます。
これは、選択された文字の最後のインスタンス(ここではFilename.ext
)の後に残っているもの(ここでは\
)を返します。これは、とにかく目的であり、最後のそのような文字の位置の検索を容易にします。
=FIND(B1,A1)-1
私はパーティーに少し遅れますが、多分これは助けになるかもしれません。問題のリンクは同様の公式を持っていました、しかし私のものはエラーを取り除くために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の使用と文字列長の制限です。これは以下に示すバリエーションで回避できますが、そのバリエーションは揮発性(read:slow)関数である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!
パーティーにはとても遅れましたが、簡単な解決策はVBAを使ってカスタム関数を作成することです。
WorkBook、Worksheet、またはVBAモジュールのVBAに関数を追加します。
Function LastSegment(S, C)
LastSegment = Right(S, Len(S) - InStrRev(S, C))
End Function
それからセル式
=lastsegment(B1,"/")
セル内で検索し、セルB1で検索する文字列は、セルB1の最後の「/」の末尾のテキストでセルに入力されます。長さの制限なし、あいまいな式なし。私が考えることができる唯一の欠点は、マクロ対応のワークブックが必要だということです。
ユーザーのVBA関数をこの方法で呼び出すと、組み込みのExcel関数のパラメータとして含めて、セル式に値を返すことができます。
もしあなたがこの関数をひどく使うつもりなら、文字が文字列の中にない場合をチェックしたいでしょう、そして文字列は空白などです.
セルA1 = find/the/position/of/the last slash
それを行う簡単な方法は、テキストを逆にして、通常どおり最初のスラッシュを見つけることです。これで、全文の長さからこの数値を引いた長さを取得できます。
そのようです:
=LEN(A1)-FIND("/",REVERSETEXT(A1),1)+1
これは、最後の/の位置である21を返します
新しいバージョンのExcel(2013以上)では、フラッシュフィルは簡単で素早い解決策になるでしょう: Excelでのフラッシュフィルの使用 。
VBAでこれを実行する簡単な方法は次のとおりです。
YourText = "c:\Excel\text.txt"
xString = Mid(YourText, 2 + Len(YourText) - InStr(StrReverse(YourText), "\" ))