Excel VBAについて
Excel VBAについて教えて頂きたいのですが、
Sub test()
Dim lastrow, r, i As Long
Dim sh1, sh2 As String
Dim ws As Worksheet
lastrow = Cells(Rows.count, "D").End(xlUp).row
For r = 7 To lastrow '7
For i = 1 To lastrow '4
sh1 = ActiveSheet.Cells(r, 4)
ActiveSheet.Cells(r, 20) = _
Application.CountIfs(Sheets(sh1).Range("D:D"), Range("H3") & Range("I3"), Sheets(sh1).Range("K:K"), "<=3") _
/ Application.CountIf(Sheets(sh1).Range("D:D"), Range("H3") & Range("I3"))
ActiveSheet.Cells(r, 21) = _
Application.CountIfs(Sheets(sh1).Range("C:C"), Range("F3"), Sheets(sh1).Range("K:K"), "<=3") _
/ Application.CountIf(Sheets(sh1).Range("C:C"), Range("F3"))
ActiveSheet.Cells(r, 22) = _
Application.CountIfs(Sheets(sh1).Range("E:E"), Range("K3"), Sheets(sh1).Range("K:K"), "<=3") _
/ Application.CountIf(Sheets(sh1).Range("E:E"), Range("K3"))
Sheets(sh1).Range("A3:R3").AutoFilter Field:=4, Criteria1:=Range("H3") & Range("I3")
ActiveSheet.Cells(r, 15) = Application.Subtotal(105, Sheets(sh1).Range("O:O"))
Sheets(sh1).Range("A3:R3").AutoFilter Field:=4, Criteria1:=Range("H3") & Range("I3") - 200
ActiveSheet.Cells(r, 18) = Application.Subtotal(105, Sheets(sh1).Range("O:O"))
Sheets(sh1).Range("A3:R3").AutoFilter Field:=4, Criteria1:=Range("H3") & Range("I3") + 200
ActiveSheet.Cells(r, 19) = Application.Subtotal(105, Sheets(sh1).Range("O:O"))
For Each ws In Worksheets
ws.AutoFilterMode = False
Next
Next
Next
End Sub
このコードは
ActiveSheetで実行すると
D列の7行目から最終行までに入力されている名前のシート(名前=シートがあります)
その、シートの参照先で
C,D,E列がcountif関数を利用して
O列がSubtotal関数を利用しています。
このコードでもやりやいことは実行できるのですが、
時間がかかりすぎてしまいます。
約20件あり約2分ほどかかります。パソコンによっては倍ほど時間がかかるかもです。
そこでなのですが、
もっと処理のスピードを上げたいのですが、
可能でしょうか?
可能ならそのやり方をご教示ください。
よろしくお願い致します。
お礼
imogasi様、ご回答ありがとうございます。 まずは私の質問の仕方が悪く、気分を害したようで申し訳ございません。 >なぜDSUM関数なのか? >余談だが、VBAでやるなら(泥臭いが)繰り返し加算方法が標準だろう. 方法がなければ、for文で回すことを検討しましたが、 短い文で表記できるのならばその方が分かりやすいかと考えたことが今回の経緯です。 ※EXCELですので、もし私以外の方(EXCELはよく扱っているがVBAはさほど理解していない場合も可能性として考える)が解析にあたった場合、シート関数のような記述であれば、for文で回す処理よりかは分かりやすいかとも考えた結果です。 >関数でやるならSUMIFSではないか? >むつかしい関数に注目して分からないからといって大勢の >読者を煩わさなくてもい良いだろう。 これは、私自身がEXCEL関数の知識が乏しく、そもそもSUMIFS関数すらも知らなく、もちろんDSum関数も知らなかったのですが、検索して最初に見つけたのがDSum関数でしたので、この関数について掘り下げて調査を進めていたものです。 「大勢の読者を煩わ」すつもりは全くなく、わざわざ難しい表現をしたいとも思っておりません。 今回SUMIFS関数というものがあるということ、そしてこちらの方がDSum関数よりも一般的に知られているということを教えていただきまして、ありがとうございました。 日付の処理については、おっしゃる通り日付型だと扱いにくいため、 数字8桁で持つようにしています。 >>ACCESSのDSUM関数のような記述ができませんでしょうか? >エクセルの方からの発想の方が普通だろう。 普通の発想ができず、申し訳ございませんでした。 ですが私のように、ACCESS(VBA)の方がEXCELよりも多く扱っている人間が、いろんな背景を考慮した上で今回のような質問をさせていただくこともあることをご理解いただきたいと思います。 このことを記載しておけばよかったと反省いたしました。 ご提示していただいた「EVALUATE」メソッドは、質問を出した後に見つけまして、こちらも試してみていたところでした。 ですがやはり、条件の指定の部分を、 「セル範囲を指定」(条件値はセルに入力する必要がある)から 「条件式に変える」(セルに条件値を入力せずに、VBAで生成する) という方法に変換するのが全く思い当たらず、ずっとWeb検索しており、for文を覚悟したところでした。 教えていただいたSumIfs関数だと条件指定の方法が「セル範囲(条件値が入力されているセルが範囲に含まれるように範囲選択)」ではなく、条件値を指定してできるようでしたので、とりあえず固定値で、 x = Application.SumIfs(Range(Cells(4, "C"), Cells(15, "C")), _ Range(Cells(4, "A"), Cells(15, "A")), ">=20151001", _ Range(Cells(4, "A"), Cells(15, "A")), "<=20151002", _ Range(Cells(4, "B"), Cells(15, "B")), "01") と指定することで正しく結果が得られましたので、 後は条件値を変数て指定するように手直しして対応したいと思います。 大変ありがとうございました。