• ベストアンサー

エクセル2010で規則性のある文字列の取り出し

cj_moverの回答

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.7

こんにちは。お邪魔します。 また、回答(質問を閲覧することも)お休み中なのですが、 お気に入りのアバターをまたまた偶然見つけたので、参加してみます。 題意の細かい部分は確認してみないといけない点も幾つかありますが、 パッと見、の解釈で、2通り挙げてみます。 違っている点があればご指摘下さい。 マッチした位置情報に意味は無い前提ですが、 見つかる順番には意味があるのかも?ですね。 セルの中に複数マッチする場合も処理するように書いておいた方が 殆どコストも掛からないのでベターだと私も思います。 ("抜き出す"場合、こういうのは慣習というか慣例というか、、、。) 一万行程度なら1秒以内で済みますが、処理が速いやり方ではありません。 ' ' ==========簡易簡潔版============================== Sub Re8819211a() Dim c As Range Dim sTmp As String Dim nPos As Long Dim cn As Long   Application.ScreenUpdating = False   For Each c In Range("B1:B" & Cells(Rows.Count, "B").End(xlUp).Row) ' セル範囲を総当たりループ     sTmp = c ' セル値を文字列変数に '    nPos = 0     Do ' Doループ("B"、"G"が見つからなくなるまで文字列の桁位置を検索)       nPos = NaturalMin(InStr(nPos + 1, sTmp, "B"), InStr(nPos + 1, sTmp, "G")) ' 関数解説参照       If nPos Then ' "B"、"G"が見つかったならば         If Mid$(sTmp, nPos) Like "[BG]####*" Then ' "B"、"G"から始まり数字が4桁続く文字列ならば           cn = cn + 1 ' ヒット数送り           Cells(cn, "K") = Mid$(sTmp, nPos, 5) ' マッチした文字列を出力         End If       Else ' "B"、"G"が見つからないなら         Exit Do ' Doループを抜け次のセルへ       End If     Loop   Next '  Application.ScreenUpdating = True End Sub ' ' /// 2つの引数の内 最少の自然数(0以外の最少数)を返す。 ' ' /// 2つの引数の両方が0ならば0を返す。 Private Function NaturalMin(ByVal n1 As Long, ByVal n2 As Long) As Long   NaturalMin = Application.Min(n1, n2)   If NaturalMin = 0 Then NaturalMin = Application.Max(n1, n2) End Function ' ' ================================================== マッチした位置情報に意味は無い前提ですから、 セルひとつずつループするのではなく、 セル範囲(の内の有意な範囲)全体をひとつの文字列として読込んでから、 処理する方が効率的で速くなります。 正規表現を使うのが楽ですし、記述自体は簡潔になります。 出力の仕方もセルひとつずつ出すよりは、 出力用の二次元配列を一度で出す方が速くなります。 Application系の抑止などは必要に応じて適宜追加してください。 (EnableEventsやCalculation等々) オマケとして重複を除く場合の処理も書いてみました。 元データのセル範囲指定は(ひとつの連続範囲であれば)複数列でも構いません。 Range("B:B")のように列単位で大丈夫です。 ExcelのSUM関数のように、使ってない範囲は自動的に削ぎ落としてくれますので、、、。 ' ' ==========一連文字列・正規表現・配列変数 版=======(大量データ向き) Sub Re8819211c() Dim oData As Object ' As MSForms.DataObject Dim sSrc As String   Set oData = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") ' New DataObject   Range("B:B").Copy ' セル範囲(任意の列単位:複数列可)のコピーデータをクリップボードに   oData.GetFromClipboard ' クリップボードのコピーデータをDataObjectに   Application.CutCopyMode = 0 ' コピーモードをキャンセル   sSrc = oData.GetText ' (tab区切り)cr改行 セル範囲全体を 文字列値 として取得   Set oData = Nothing ' DataObject解放   sSrc = StrConv(sSrc, vbNarrow) ' 文字列値 半角を強制 'Debug.Print sSrc ' 確認用 Dim vPt ' 出力用二次元配列 Dim oRE As Object ' As VBScript_RegExp_55.RegExp (正規表現) Dim colM As Object ' As VBScript_RegExp_55.MatchCollection Dim oM As Object ' As VBScript_RegExp_55.Match Dim i As Long   Set oRE = CreateObject("VBScript.RegExp") ' RegExpをセット   oRE.Global = True ' RegExpのお約束   oRE.Pattern = "[GB]\d{4}" ' RegExpのマッチングパターン   Set colM = oRE.Execute(sSrc) ' RegExpのマッチング結果をコレクションとして取得   ReDim vP(1 To colM.Count, 0) ' 出力用二次元配列をリサイズ   For Each oM In colM ' RegExpのMatchCollectionを総当たりループ     i = i + 1 ' インデックス送り     vP(i, 0) = oM ' 出力用二次元配列にマッチング結果を格納   Next   Set colM = Nothing   Set oRE = Nothing ' ' ---------- 重複を除く場合は以下8行イキ ------ 'Dim oDict As Object ' As Scripting.Dictionary 'Dim v '  Set oDict = CreateObject("Scripting.Dictionary") ' Dictionaryをセット '  For Each v In vP ' 出力用二次元配列を総当たりループ '    oDict(v) = Empty ' Dictionaryに重複を除いたデータを格納 '  Next '  vP = Application.Transpose(oDict.Keys) ' 重複を除いたDictionaryのキー配列を行列変換したものを出力用二次元配列に '  Set oDict = Nothing ' ' ----------------------------------------------   Application.ScreenUpdating = False   Cells(1, "K").Resize(UBound(vP)).Value = vP ' セル範囲に出力用二次元配列を出力 '  Application.ScreenUpdating = True End Sub ' ' ================================================== 直接の返事が無いようなので、#1補足の問題について軽く触れてみます。 Like 演算子のパターンに用いるキャラクターセットの記法ですが、 (要するに "[" と "]" の間の書き方)  [BG} のように間に何も挟まない(区切らない)のが正解です。  [B G] や [B,G] は間違いで、それぞれ、半角スペースやカンマを拾ってしまいます。 #最近ベテラン回答者さんがうっかり書き間違えたのが広まってしまって(?) #半角スペースやカンマを挟むのが流行っているようですが、間違いは間違いです。 詳しいことは、Like 演算子のVBAヘルプで確認してください。 覚える必要がある約物は、? * # [ ] ! だけでいいです、 以上です。

emaxemax
質問者

お礼

cj_mover さん、いつもご丁寧にお教えいただきありがとうございます。 >マッチした位置情報に意味は無い前提ですから、 大変申し訳ありません。 わたしが、前提となる条件をきちんと書いておかなかったためお手間をとらせてしまいました。 どのセルにあるかも必要だったのです。 Like演算子の解説もとても勉強にになりました。 今回はとても急いでおり、すでにNo1,6の方のご回答をもとに実装のテストを行っております。 すみませんでした。

関連するQ&A

  • 文字列操作(ExcelのVBAですが)

    特定のExcelセル内にある文字列について、 例えば、 138.40.8.7 と入っている場合、 138.40.08.7 に、 35.9.1.6 と入っている場合、 35.09.01.6 にするVBA関数を作りたいのです。(セル関数でもかまわないですが) つまり、小数点で区切られている2番目と3番目の数字が 一桁の場合、頭に0を付けて、必ず二桁になるようにしたいわけです。 どなたか、ご教授くださいませ。 よろしくお願い致します。

  • (エクセル)表から1列の別表をつくりたい。

    表に入力されたものを1列に並び替えをしたいのです。(エクセル関数) エクセルの表から、セルに入力された情報を抜き出し、並び替えたいのですが、行き詰ってしまい質問させていただきます。 (やりたいこと) 添付資料のように、事業所ごとに購入した物品が日付ごとに入力されていきます。この表を一列で並び替えることを したいのですが、現状の表の形で1列に抜き出すやり方が思い浮かびません。ひとつずつリンクを設定していけばいいですが、 それですと、空白のセルができてしまうこともあり、空白を消すためにフィルタをやらなくてはいけず、なんとか関数でどうにかできないと質問させていただきました(つまり空白のセルは飛ばし、隙間のない1列の表に変換したいです)。 (試したこと) (1)vlookup関数を使うために、日付の横に検索列を作ってもみましたが、同じ行に複数の抜き出すべくものがあると、 if関数のネストをいれるにも「if(c5="","",vlookup(v5,b5:r10,2,fasle)」みたくやってみましたが、c5までは取り出せても、 d5,e5,f5・・・と右にずらしていく関数式が思い当たりません。 (2)種類、数量データ入力されている全てのセルの横に(1.2.3.4.5.6.7.8.9.・・・)と数字をいれて検索列をつくり、vlookupとmatch関数の 組み合わせも試しましたが、vlookup関数の性質上、複数列に検索値(「vlookup(検索値,範囲,列番号,検索の型)」)が存在しているとこれも出来ず。 説明が不十分な点もあると思いますが、よろしくお願いいたします。もし、VBAでなければ難しいとのことでしたら、どのようなVBAを組めばいいかもお願いいたします。

  • Excel 文字列にする関数

    エクセルが苦手なので教えてください! 選別番号で6桁の数字を使っているんですが、頭の数字が0から 始まるものがあり、セルに入力するとその選別番号だけ5桁に なってしまいます。 文字列にすればいいということだけはわかっているのですが、 すでに数字が入っている列に対して、関数を使って以下のような ことはできますか? (1)選別番号が5桁だったら、頭に0をつけて6桁にする、  かつ文字列にする (2)選別番号がすでに6桁だったら、そのまま文字列に変換 宜しくお願いします!

  • エクセル 関数 001 002と文字列で表示した

    お世話になります。 XP/ エクセル2003 使用です。 エクセルの関数で、 数字を3桁で数字を表示したく 下記のように関数を組みました。 (セルの書式は、文字列にしています) 001の場合  =IF(A1="","","001") とし、001が問題なく返ってきます。 次のセルに、002と連番を振っていきたいので  =IF(A2="","",B1+1) としましたが、   2  (002ではない) と返ってきます。(書式は文字列) 002、003、004・・・と続けていきたいのですが、 どのようにすればよろしいでしょうか? ご多用中恐れ入りますが、 よろしくお願いします。

  • エクセル2000 文字列の削除を関数でできますか?

    1132 相川 1133 小笠原 A列のセルに上のよう入力されています。 「1132 相川」 でひとつのセルです。 関数を用いて「半角4桁の数字部分」と「半角の空白」を削除したいと思います。 1132 相川 1133 小笠原   ↓ 相川 小笠原 つまり上のようにしたいのです。 お時間の許す方にご回答をお願いしたいと思います。

  • エクセルの質問です

    A列は空白 B列に商品をあらわ5桁のコードが入っています。 C列にも同じく商品を表す5桁のコードが入っているのですが、 B列のセルと隣り合ったセルには同じ数字が入っていません。 D列には取引先の会社名が入っています。     B1に入ってる5桁の数字と同じ数字が入っている C列のセルを探し、 そのセルの隣のD列の会社名をA1のセルに表示させたいのですが、 どう関数を組んだらいいのでしょうか? A   B    C   D     12345 12354 A社    12334 12345 B社    12443 12544 C社 上の表の場合B1とC2数字が同じなのでA1にB社と表示させたいのです。  

  • エクセル関数での文字列?の検索

     ある行に0から5の一桁の数字が28列並んでいて、  その中で1の次にすぐ0が続いているかどうか  (ふたつの隣接するセルが10かどうか)を調べる  関数はどうなりますか?

  • 文字列の途中の空白を除く、また、A列の桁数に応じてB列に異なる値を記入する方法

     初心者です。エクセル2000を使います。年は若くないです。  次のことで困っています。データが多いため、ひとつひとつを手で訂正できないのです。 1.セル内の文字列に含まれる空白(スペース)を除く方法   例えば、 東 いろは→→東いろは   空白を置換して除こうとしましたがうまくいきませんでした 2.A列の数字の桁数に応じて、B列に異なる数字を入れる方法。以前に教えていただいた方法+α が必要なのです。   A列の数字が 4桁 なら B列に 01を入力   A列の数字が 6桁 なら B列に 60を入力   A列の数字が 7桁 なら B列に 06を入力   A列の数字が 8桁 なら B列にA列の数字の上位2桁を入力 したいのです。前回次のような数式を教えてえていただきました。  =IF(LEN(A1)=4,"01",IF(LEN(A1)=6,"60",IF(LEN(A1)=7,"06",""))) 8桁のときの数式の組み立て(条件判断、表示の仕方)が分からず、困っています。教えて下さい。

  • 特定の列の最初にあるデーター抽出

    Sheet1のB5からB65までのセルにランダムで数字が入れてありますが必ずどのセルにも数字が入っているわけでは無く空白のセルも数字の入ったセルも混在しています。 この列の最後の数字をSheet2の任意のセルに抜き出すには、Lookup関数でできますが、列の最初の数字を抜き出すにはどのような関数で行えるのか教えてください。

  • エクセルで文字列の5桁目が9なら0に変更

    エクセル初心者です。 インターネットで調べてみたのですが、同様の質問にヒットしませんでしたので、教えてください。 A列に8桁の会員番号が文字列で表示されています。 この8桁のうち右側の5桁を関数(RIGHT(a8,5))でB列に抽出しています。 抽出された5桁の数字ですが、最上位桁が9の場合、0に変えたいのです。 A        B 01004567    04567  02015678    15678 03098765    98765 → 9を0に入替して「08765」と表示 このような対応が出来る関数を調べたのですが分かりませんでした。 ご教示のほど、よろしくお願いします。