• ベストアンサー

【VBA】 このコードを最適化してください

a1セルに入力した文字列をb15セルに反映するのですが、 数字が含まれている場合はそれを削除し、そのうえで左端のスペースも削除したものを反映する場合、 Range("b15").Value = Range("a1") For i = 0 To 9 Range("b15").Value = Replace(Range("b15"), i, "") Next i Range("b15").Value = LTrim(Range("b15")) というコードを使っているのですが、冗長な気がします。 何かもっとスマートなやり方はありますか?

質問者が選んだベストアンサー

  • ベストアンサー
  • mt2008
  • ベストアンサー率52% (885/1701)
回答No.3

基本的にはこのままでも良いと思いますが、B15セルの値を何度も置換するよりは一度変数に代入して置換とTrimを行い、その結果をB15セルに入れる方が良いと思います。 Sub test()   Dim sText As String   sText = Range("a1")   For i = 0 To 9     sText = Replace(sText, i, "")   Next i   Range("b15").Value = LTrim(sText) End Sub 回数が多くなるとスピードはだいぶ違います。

rihitomo
質問者

お礼

ありがとうございます。代入する方法でやってみたいと思います。

その他の回答 (3)

回答No.4

>何かもっとスマートなやり方はありますか? ここの「スマート」という意味は、「冗長な」の反対で、つまり、数字を総当りで削除する方法が、「スマート」ではないとおっしゃっているようです。ただ、0~9までですから、その程度は仕方がないような気がします。「最適化」という意味は、コーディングの書法のことで、最適化する部分は、ほとんどありません。 以下は、正規表現で数字だけ抜く「.Replace(tmp, "")」というコードならば、正味、3行でもいいわけです。しかし、総当りに対して、はたして、おっしゃっている「スマート」と言えるか、私には自信がありません。 '// Sub Test3()  Dim Matches As Object  Dim tmp As Variant  With CreateObject("VBScript.RegExp")   .Pattern = "\d" '数字 LTrim指定のため [\s\d]は使えない   .Global = True    tmp = Range("A1").Value    tmp = LTrim(tmp)    tmp = StrConv(tmp, vbNarrow) '全角があったら半角にする    If .Test(tmp) Then '該当するか検査     Range("B15").Value = .Replace(tmp, "") '数字を抜く    End If  End With End Sub

rihitomo
質問者

お礼

ありがとうございます。VBAを始めたばかりで正規表現を使うやり方は全く知りませんでした。 これから勉強してみたいと思います。

  • matyu1003
  • ベストアンサー率42% (257/598)
回答No.2

No.1です。 失礼しました。私の例だと元の文字列の先頭が数字で、且つその後ろにスペースがある場合場合はスペースが残ってしまいますね。なので、質問者さんのとおりで良いのでは?と思います。 "1 abc 1a"だと 私のマクロでは " abc a"となり、期待した結果になりません。 "1abc1a" とか " abc1a" なら私のマクロでも期待した結果になります。

  • matyu1003
  • ベストアンサー率42% (257/598)
回答No.1

Replaceより先にLTrimをしたほうがReplaceする文字列が短くなるのでベンチマークでも出ないほどですが早くなるのと、LTrimを先にするとその結果をいきなりb15に書き込めるのでこんな感じで。 Range("b15").Value = LTrim(Range("a1").Value) For i = 0 To 9 Range("b15").Value = Replace(Range("b15").Value, i, "") Next i

関連するQ&A

  • VBAのコード forを使用した処理

    おはようございます。 どうしてもコードが思いつかないので質問させていただきます。 やりたいこと 例 A1~A5セルにランダムに『今日』や『明日』の文字が入っている として B1セルに『1』、B2セルに『2』、B3セルに『3』Bセルに『4』 とそれぞれ数字が入力されているとします。 例えばもし A2セルとA4セルに『今日』という文字が有れば、C1セルに B2セルの値とB4セルの値を足したものを反映させたいのですが どうしてもfor文を使用すると最後の数字 (このパターンだとB4の数字を張り付けられるだけになります。) どうしたらSUM関数みたいに連続してB2とB4セルの値を 足せるようなコードをかけるのでしょうか? すいませんが下記にコードを記載します。 出来ましたらこうしたらうまく計算できるよ! というコードを記載していただけないでしょうか? 宜しくお願い致します。 Sub test() Dim i As Long For i = 1 To 5 If Cells(i, "A").Value = "今日" Then Range("C1") = Cells(i, "A") ←ここの処理コードが間違っていますよね End If Next i End Sub

  • VBA教えてください

    VBA初心者です やりたい事 B70セルから文字を探し B70~B20セルに文字が入っている場合 文字が入っている一つ下のセルを選択しA1セルの文字を反映する 例、B50セルに文字が入っていたらB51セルにA1セルの文字を入れる ということをしたいです 考えたコード Sub test() Dim a As Variant Dim i As Long For i = 70 To 20 Step -1 If Len(Cells(i, "B").Value) > 0 Then Cells(i, "B").Offset(1, 0).Value = range("A1") End If next i End Sub このコードだと B40セル文字有り B41セルにA1セルの文字反映 B50セル文字有り B51セルにA1セルの文字反映という風に 複数反映してしまいます 私が実現したいのは B40セルに文字があろうが B50セルに文字が有ればB51セルだけにA1セルの文字を反映させる という形にしたいのです。(下から処理したい) 分かる人いればコードを書いてほしいです。 宜しくお願いします。 説明不足で有れば捕捉しますm(ーー)m

  • VBA教えて下さい

    for nextの使い方がわかりません 変数を使用し条件に当てはまる数値だけ 処理するといった内容です 考えたコード sub test() dim a as variant dim b as variant dim i as variant with workbooks("book1").activesheet set a =.range("A5") set b =.range("B5") end with with workbooks("book2").activesheet for i = 80 to 110 if a = cells(i,1) then b.value = cells(i,2) end if next i end sub このコードにてやりたい事は まず、book1の今開いてるシートを参照し A5セル、B5セルをセットし (例えばA5は2と入力している B5セルは10000と入力している) 次に、book2の今開いてるシートを参照し もし、1行目の80~110どれかのセルの数字が 変数aと同じ値ならば (A行80~110行のセルの数字2があれば 例えば85列) 変数bの数字を2行目の80~110に条件に当てはまるセルに移す (B行85列にB5セルの値10000を移す) ()の部分は例えで書いてます 読みにくかったら無視でお願いしますm(__)m 指定の仕方など間違ってると思うので コードを書いてくれると助かります 回答お願いしますm(__)m

  • VBAのコードについて質問です

    独学でエクセルVBAの初心者です。 定尺の鋼材から一定の長さのものが何本切り出せるかを調べるプログラムを作りたいです。 ネットで調べたところカッティングストック問題というものすごい難しいサイトに当たりましたが、 そのような難しいものではなく単純に同じ長さのものを切っていき、必要本数が取れたら次の長さを 切っていくというものを作りたいと思います(最終的に定尺何本必要か知りたい)。 まだまだ始めたばかりなのですが、do while文でorを使ったのですが反映されません。 なぜなのでしょうか? iが3になった時点で引くのを止めたいのですが止まりません教えてください。 Sub Test() Worksheets("Sheet1").Cells(1, 2).Value = 5500 Worksheets("Sheet1").Cells(2, 2).Value = 1000 Worksheets("Sheet1").Cells(3, 2).Value = Range("B1").Value Dim i i = 0 Do While Range("B3").Value > Range("B2").Value Or Range("B4").Value = 3 i = i + 1                           ↑この部分 Range("B3").Value = Range("B3").Value - Range("B2").Value Loop Worksheets("Sheet1").Cells(3, 2).Value = Range("B3").Value Worksheets("Sheet1").Cells(4, 2).Value = i End Sub

  • VBA 結合されているセルのオートフィル

    先程同じような質問をしてしまい すいませんが 結合されているセルのオートフィルのやり方が今一つわかりません でしたので質問させていただきます。 やりたいこと A列・・・A1セル『1』A2セル『2』・・・A10セル『10』と 数字が入っています。 BとC列・・・結合されており B1C1セル『1000』B2C2セル『1100』と数字が入っています。 F1セル・・・1~10までの数字が入っています。 処理内容 F1セルに『5』と数字が入っている場合 B5C5セルを選択後、数字が入っているB2C2セルまで移動します。 そのあと、B5C5セルではなく B4C4セルまで『1100』とオートフィルしたいのですが 可能でしょうか。 それともこのような処理をしたい場合オートフィルをするのは 間違っているのでしょうか? すいませんがコード記載していますので 回答宜しくお願い致します。 コード Sub Macro1() Dim a As Variant Dim i As Variant Dim RSta As Long Set a = Range("F1") '検索値'例えば5と入力したら For i = 1 To 10 If a.Value = Cells(i, 1).Value Then 'F1セルに5と入力されA5セルの数字が5なら If Cells(i, 2) = "" Then 'B5セルの値が何もなければ RSta = Cells(i, 2).End(xlUp).Row 'ここでBとCセルの結合されているセルの数字が入っている 一番上のセルを選択し Range("B" & RSta, "C" & RSta).AutoFill Destination:=Range("B" & RSta, "C"), Type:=xlFillCopy 'このコードが間違っているらしくうまくできません。ここでBとCの結合されているセル2行目から4行目までをオートフィル(数字のコピーのみを実施したい) End If End If Next i End Sub

  • VBA For Eachでセル内の文字列を一個ずつ取り出すには

    エクセル2000です。 たとえばA1セル内の文字列を一個ずつ取り出す場合、 Sub test01() For i = 1 To Len(Range("A1").Value) Cells(i, "B").Value = Range("A1").Characters(i, 1).Text Next End Sub このように最初から最後の文字まで何番目で指定することはわかるのですが、これをFor Each で回すにはどうしたらよいでしょうか? (⌒o⌒)? お教えください。 Sub test02() For Each ch In Range("A1").Characters i = i + 1 Cells(i, "B").Value = ch Next End Sub ではエラーになります。

  • 連続データのVBAの質問

    お世話になります。 Private Sub Worksheet_Change(ByVal Target As Range) Dim i As Long, k As Long, myNum As Long If Not Intersect(Target, Range("C1,B9:B39")) Is Nothing And Target.Count = 1 Then Application.EnableEvents = False With Target If .Column = 3 Then myNum = WorksheetFunction.Max(Range("B9:B39")) If IsDate(.Value) Then For i = 9 To 39 If Cells(i, "A").Value = "" Then Cells(i, "B").Value = "" Else Cells(i, "B") = myNum + i - 8 End If Next i End If Else i = .Row If .Value = "" Then Range(Cells(i + 1, "B"), Cells(39, "B")).ClearContents Else For k = i + 1 To 39 If Cells(k, "A").Value = "" Then Cells(k, "B").Value = "" Else Cells(k, "B") = Cells(k - 1, "B") + 1 End If Next k End If End If End With Application.EnableEvents = True ElseIf Not Intersect(Target, Range("R8:R38")) Is Nothing Then Application.EnableEvents = False Range(Cells(Target.Row, 18), Cells(39, 18)).Value = Target.Value Application.EnableEvents = True End If End Sub これはセルC1に年月を表記させ、そのC1セルの年月を変更した場合B9~B39のセルが自動で連続データの数字を記入し、B9~B39のどこかのセルを空白にすると、そのセル以降も空白になります。 そしてR8~R38は、指定範囲のセルに数字を入力したら、そのセル以降の指定した範囲のセルに同じ数字を自動入力するVBAです。 そこで質問ですが、質問した現在は2013年12月ですが、日本時間の現在の年月以前の年月(今で言うと2013年11月以前)をC1に記入した場合はB9~B39の連続データの数字が切り替わらない様にするには、どうすれば宜しいでしょうか?

  • 連続データのVBAの質問

    お世話になります。 Private Sub Worksheet_Change(ByVal Target As Range) Dim i As Long, k As Long, myNum As Long If Range("C1") <= Date - Day(Date) Then Exit Sub If Not Intersect(Target, Range("C1,B9:B39")) Is Nothing And Target.Count = 1 Then Application.EnableEvents = False With Target If .Column = 3 Then myNum = WorksheetFunction.Max(Range("B9:B39")) If IsDate(.Value) Then For i = 9 To 39 If Cells(i, "A").Value = "" Then Cells(i, "B").Value = "" Else Cells(i, "B") = myNum + i - 8 End If Next i End If Else i = .Row If .Value = "" Then Range(Cells(i + 1, "B"), Cells(39, "B")).ClearContents Else For k = i + 1 To 39 If Cells(k, "A").Value = "" Then Cells(k, "B").Value = "" Else Cells(k, "B") = Cells(k - 1, "B") + 1 End If Next k End If End If End With Application.EnableEvents = True ElseIf Not Intersect(Target, Range("R8:R38")) Is Nothing Then Application.EnableEvents = False Range(Cells(Target.Row, 18), Cells(39, 18)).Value = Target.Value Application.EnableEvents = True End If End Sub これはセルC1に年月を表記させ、そのC1セルの年月を変更した場合B9~B39のセルが自動で連続データの数字を記入し、B9~B39のどこかのセルを空白にすると、そのセル以降も空白になります。 そこで質問ですが、例えばB14の数字を消すとB15~39まで空白のセルになります。そして、B20に1と入力するとB21~39に連続データの数字が自動記入されます。 そしてC1の年月を次の月に更新した際は、B39で示された数字以降の連続データをB9に表示させるには、どうすれば良いでしょうか?

  • VBAの処理を軽くしたい

    各行ごとに5回セルを参照した結果を吐き出すプログラムを作成しています。 200行前後の処理が必要なのですが、現在のコードではあまりにも処理が重くなっています。 とにかく処理を軽くしたいのですが、どのような方法が考えられるでしょうか? 初心者なのでコードも含めてご教示頂けたら幸いです。 Sub test(b, c, d) Dim i1, i2 As Long Dim A1 As String  For i1=0 To Cells(Rows.Count, 1).End(xlUp).Row For i2 = 0 To 5 If Range(b).offset(i1, i2).Value = "x1" Or Range(c).offset(i1, i2).Value = "x1" Then A1 = "XXX" ElseIf Range(b).offset(i1, i2).Value = Range(c).offset(i1, i2).Value Then A1 = "YYY" Else A1 = "ZZZ" End If Range(d).offset(i1, i2).Value = A1 Next i2 Next i1 End Sub

  • VBA 文字列に関して

    現在 A22のセルに入力された文字列をボタンを押せば ばらばらにしてA22のセルから順番に入れるマクロを作りました (例)A22のセルに ”こんにちわ”の文字列が入っている場合 ボタン押下   ↓ A22のセル⇒こ B22のセル⇒ん C22のセル⇒に D22のセル⇒ち E22のセル⇒わ になる。 不思議なことに数字を16文字以上いれてボタンを押し文字を分離すると入力していない文字、数字が入ってしまいます。 数字だけこういう現象が発生してしまいます。 例えば "1111111111111111"と入力して文字を分離した場合 1.11111111111111E+15と個々のセルに格納されます。 原因がわかる方、教えて頂けないでしょうか? 以下がコードです。宜しくお願い致します。 Private Sub CommandButton1_Click()   Dim one As String   Dim myString As String   myString = Cells(22, 1)   numString = Len(Cells(22, 1))   If Len(myString) <= 50 Then    For i = 1 To Len(Range("A22").Value)      one = String(1, myString)      Cells(22, i) = one      myString = Replace(myString, one, "", 1, 1, vbTextCompare)    Next i   End If End Sub

専門家に質問してみよう