• ベストアンサー

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

cj_moverの回答

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

#7-9です。 > すみませんが、このご回答への補足ではありません。 > If InStr(StrConv(Cells(i, "B"), vbNarrow), "B") > 0 Or _ > InStr(StrConv(Cells(i, "B"), vbNarrow), "G") > 0 Then > をLike演算子でやってみました。 ... > もっと早くなりました。 > Likeの使い方、あってますでしょうか? Like 演算子の使い方はバッチリです。自信持っていいですよ。 速さを意識しての書換えということでしたら、 「同じ記述を繰り返さない」為に変数の使い方を工夫しましょう。   StrConv(Cells(i, "B"), vbNarrow) という記述の内、特に   Cells(i, "B") のようなセル参照には時間が掛かるもの、 という意識を持つようにすると、効率的な記述が出来るようになります。 (InStrと比べて)"もっと早くなりました。"という結果の違いも 実はセル参照の数の違いが原因であって、構文の問題ではないですね。 試しに以上説明のように変数の扱いだけ書き換えてみましたが、 こちらのダミーデータでは、#9補足欄のマクロをさらに4割ほど時短できました。 もし興味あるようでしたら、InStr版の方も第一引数に文字列型変数を指定するように書ければ、 セルの文字列値を全桁ループするよりは1~2割速くなる筈です。 その他の記述については、かなりのレベルで書けていると思います。 Like 演算子(というよりパターンマッチング全般)は、比較的処理が遅いので、 Like "*[BG]####*"の代りにIsNumeric()とLen()を組み合わせて、 同等の仕様を実現するのも(試してませんが)有望と思いますが、 記述を複雑にするよりは、Like 演算子の「シンプルに書ける」特長を活かした方が いいのかも知れませんね。 以下、#9補足欄のマクロについて変数の扱いだけ書き換えたものです。 ' ' ================================================== Sub ReSample3TEST() Dim i As Long, k As Long, buf As String, str As String, time1 As Single time1 = Timer   Application.ScreenUpdating = False   For i = 1 To Cells(Rows.Count, "B").End(xlUp).Row     buf = StrConv(Cells(i, "B"), vbNarrow)     If buf Like "*[BG]####*" Then       For k = 1 To Len(Cells(i, "B"))         str = Mid$(buf, k, 5)         If str Like "[BG]####" Then           Cells(i, "D") = str           Exit For         End If       Next k     End If   Next i   Application.ScreenUpdating = True MsgBox Format(Timer - time1, "0.0000秒") End Sub ' ' ================================================== 蛇足ですが、#9の配列変数版についてです。 (特に明言されていませんが多分) 1つにセルに付き1つの対象文字列を取り出せば十分、 という条件のようなので、それに合わせて ほぼ#9補足欄のマクロ同等の仕様で書き直しておきます。 今すぐは解らなくても構いませんし、見送って貰っていいと思いますが、 速さの為の方法として配列変数は結構有力なので、 いつか何かの参考になればと思っています。 (NMin()関数は#9のままです) ' ' ==========配列変数版============================== Sub Re8819211j1stTerm() Dim mtxS() Dim mtxP() Dim sTmp As String Dim s As String Dim nUBY As Long Dim nPB As Long Dim nPG As Long Dim nPos As Long Dim i As Long Dim t As Single: t = Timer   mtxS = Range("B1:B" & Cells(Rows.Count, "B").End(xlUp).Row).Value ' 元データを二次元配列として取得◆セル範囲を指定   nUBY = UBound(mtxS) ' 行数(YSize)を取得   ReDim mtxP(1 To nUBY, 1 To 1) ' 出力用二次元配列を元データの行数*1列としてリサイズ   For i = 1 To nUBY ' 行(Y)方向にインクリメント     sTmp = StrConv(mtxS(i, 1), vbNarrow) ' 各セルの値     Do ' Doループ("B"、"G"が見つからなくなるまで文字列の桁位置を検索)       nPB = InStr(nPos + 1, sTmp, "B") ' "B"が見つかる桁位置       nPG = InStr(nPos + 1, sTmp, "G") ' "G"が見つかる桁位置       nPos = NMin(nPB, nPG) ' "B"、"G"の内先に見つかった桁位置       If nPos Then ' "B"、"G"の何れかが見つかったならば         s = Mid$(sTmp, nPos, 5)         If s Like "[BG]####" Then ' "B"、"G"に続く4桁が数字文字列ならば           mtxP(i, 1) = s ' マッチした文字列を出力用二次元配列に格納         End If       Else ' "B"、"G"が見つからないなら         Exit Do ' Doループを抜け次のセルへ       End If     Loop   Next i   Application.ScreenUpdating = False '  Application.Calculation = xlCalculationManual   Cells(1, "K").Resize(nUBY, 1).Value = mtxP ' 出力用二次元配列をサイズを合わせたセル範囲に出力   Application.ScreenUpdating = True '  Application.Calculation = xlCalculationAutomatic '  Erase mtxS(), mtxP() MsgBox "j1stTerm:" & Format(Timer - t, "0.0000秒") End Sub ' ' ==================================================

emaxemax
質問者

お礼

Sub ReSample3TEST() 素晴らしく早いです。 内容もよく理解できますので助かります。 ありがとうございました。 そして配列変数版、これは驚異的な早さですね! 1万件が0.0625秒! これは配列を使わない手はないですね。 Sub Sample4TEST() Dim i As Long, x As Long, k As Long, str As String, buf As String, time1 As Single Dim myW, myX time1 = Timer x = Cells(Rows.Count, "B").End(xlUp).Row myW = Range(Cells(1, "B"), Cells(x, "B")).Value ReDim myX(1 To x) For i = 1 To x buf = StrConv(myW(i, 1), vbNarrow) If buf Like "*[BG]####*" Then For k = 1 To Len(myW(i, 1)) str = Mid$(buf, k, 5) If str Like "[BG]####" Then myX(i) = str Exit For End If Next k End If Next i Application.ScreenUpdating = False Range("D1").Resize(x, 1).Value = Application.Transpose(myX) Application.ScreenUpdating = True MsgBox Format(Timer - time1, "0.0000秒") End Sub としてみました。 これも0.0625秒でした。今回もたくさんたくさんありがとうございました!

関連する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」と表示 このような対応が出来る関数を調べたのですが分かりませんでした。 ご教示のほど、よろしくお願いします。