• ベストアンサー

countif/sumifのようなVBA関数

himajin100000の回答

回答No.1

ワークシート関数を再利用せよ、という話で、シートを新たに作ってよければこう・・・ Sub Count1() Dim newWorksheet As Excel.Worksheet 'やむを得ず暗黙の型変換。なんかCTypeの第二引数に指定出来ず。 'というか、CTypeのヘルプが出ないってことは、VBAにはないのかなぁ Set newWorksheet = ActiveWorkbook.Worksheets.Add() Dim a(5) As Integer Dim i As Integer a(0) = 7 a(1) = 4 a(2) = 1 a(3) = 5 a(4) = 3 a(5) = 6 For i = 0 To UBound(a) newWorksheet.Cells(i + 1, 1).Value = a(i) Next MsgBox (Excel.WorksheetFunction.CountIf(newWorksheet.Range(newWorksheet.Cells(1, 1), newWorksheet.Cells(UBound(a) + 1, 1)), ">5")) Application.DisplayAlerts = False ActiveWorkbook.Worksheets(ActiveWorkBook.Worksheets.Count).Delete Application.DisplayAlerts = True End Sub 同様にこう。共通する部分は一緒にして省いても良し。 Sub Sum1() Dim newWorksheet As Excel.Worksheet 'やむを得ず暗黙の型変換。なんかCTypeの第二引数に指定出来ず。 'というか、CTypeのヘルプが出ないってことは、VBAにはないのかなぁ Set newWorksheet = ActiveWorkbook.Worksheets.Add() Dim a(5) As Integer Dim i As Integer a(0) = 7 a(1) = 4 a(2) = 1 a(3) = 5 a(4) = 3 a(5) = 6 For i = 0 To UBound(a) newWorksheet.Cells(i + 1, 1).Value = a(i) Next MsgBox (Excel.WorksheetFunction.SumIf(newWorksheet.Range(newWorksheet.Cells(1, 1), newWorksheet.Cells(UBound(a) + 1, 1)), ">5")) Application.DisplayAlerts = False ActiveWorkbook.Worksheets(ActiveWorkBook.Worksheets.Count).Delete Application.DisplayAlerts = True End Sub ====================== 後はこれらを他のサブルーチンから呼び出せば良い ******************** そういうことをするな、という話であれば自分で作るしかない。 ここからの話は俺の作り方の都合上難度が上昇します。 自信がなくなったら引き返した方が無難。もっと簡単にも作れるんだが、VB.NETに憧れて汎用性を持たせてみたかった。本当はGenericsが欲しかった…。 ******************** 挿入->クラスモジュール プロジェクトエクスプローラでこのモジュールを選択した状態で プロパティウィンドウから (オブジェクト名)をCollectionUtilに書き換える。 以後いくつかクラスモジュールを追加するので '各クラスモジュールのオブジェクト名をClass XXXとか書いてあるXXXに書き換えて欲しい 'Class CollectionUtil Option Explicit Public Static Function ConvertFromArray(arr() As Integer) As Collection Dim retval As New Collection Dim i As Integer For i = 0 To UBound(arr) retval.Add (arr(i)) Next Set ConvertFromArray = retval End Function Public Static Sub ConvertToArray(x As Collection, ByRef retval() As Integer) Dim i As Integer ReDim retval(x.Count - 1) For i = 0 To x.Count - 1 retval(i) = x.Item(i + 1) Next End Sub Public Static Function FindAll(c As Collection, f As IFilter) As Collection Dim retval As Collection Dim i As Integer Set retval = New Collection For i = 1 To c.Count If f.isMatch(c.Item(i)) Then retval.Add (c.Item(i)) End If Next Set FindAll = retval End Function Public Static Function Sum(c As Collection) As Integer Dim retval As Integer Dim i As Integer For i = 1 To c.Count retval = retval + CInt(c.Item(i)) Next Sum = retval End Function =========== 'Class IFilter Option Explicit Public Function isMatch(x As Integer) As Boolean isMatch = True End Function ============= 'Class MyLargerFilter Option Explicit Implements IFilter Private threshold As Integer Public Sub Class_initialize() End Sub Public Sub SetThreshold(x As Integer) threshold = x End Sub Public Function IFilter_isMatch(x As Integer) As Boolean If CInt(x) > threshold Then IFilter_isMatch = True Else IFilter_isMatch = False End If End Function ============== 標準モジュールに戻って・・・例によって共通部分は単独で出来るように一応書いただけで省いても構わない Sub Sum2() Dim a(5) As Integer Dim b() As Integer Dim source As Collection Dim destination As Collection Dim Filter As MyLargerFilter Dim CollectionUtil1 As New CollectionUtil a(0) = 7 a(1) = 4 a(2) = 1 a(3) = 5 a(4) = 3 a(5) = 6 Set Filter = New MyLargerFilter Filter.SetThreshold (5) Set source = CollectionUtil1.ConvertFromArray(a) Set destination = CollectionUtil1.FindAll(source, Filter) MsgBox (CollectionUtil1.Sum(destination)) End Sub Sub Count2() Dim a(5) As Integer Dim b() As Integer Dim source As Collection Dim destination As Collection Dim Filter As MyLargerFilter Dim CollectionUtil1 As New CollectionUtil a(0) = 7 a(1) = 4 a(2) = 1 a(3) = 5 a(4) = 3 a(5) = 6 Set Filter = New MyLargerFilter Filter.SetThreshold (5) Set source = CollectionUtil1.ConvertFromArray(a) Set destination = CollectionUtil1.FindAll(source, Filter) CollectionUtil1.ConvertToArray destination, b MsgBox (UBound(b) + 1) End Sub あとはその二つを 標準モジュールの Sub Main() Call Count2 Call Sum2 End Sub ってところから呼び出してみる。 結果→2 13

lelion1000
質問者

お礼

ありがとうございます。

関連するQ&A

  • SUMIFとCOUNTIF

    今は会社で出勤表を作成しています。 そこである条件別(社員,アルバイト)の人達の公休の合計(公の文字)を求めたいのですが求めたいのは数値ではなくて”公”という値なのです。 =SUMIF(範囲,検索条件,合計範囲)では =SUMIF(A1:A10,"社員",C1:C10)とやりたいのですが 値は数値しか求められなくて文字はカウントできません。 =COUNTIF(範囲,検索条件)では =COUNTIF(C1:C10,"公") 指定範囲の部分がないので出来ませんでした。 そこで =SUMIF(A1:A10,"社員",COUNTIF(C1:C10,"公")) とやりましたが値は帰ってきませんでした。 どうすれがSUMIFで文字を算出するような、SUMIFとCOUNTIFを混ぜ合わせたような算出の仕方が出来るのでしょうか? マクロや文字を数値に置き換え、新しいワークシートを作成せずに関数で出来る方法を教えていただけませんか? よろしくお願い致します。

  • COUNTIF関数について

    タイトルの件についてご助言をお願いします。 エクセル表でいくつかシートがあって、例えば各シートの同じセル番号(例えば3枚のシートのA1のセルとして)にある”○”の数を集計したいとき、COUNTIF関数で次のように入力しました。 =COUNTIF(sheet1:sheet3!A1,"○") ところが、VALUEエラーが出て、集計してくれません。同じシート内でCOUNTIFで”○”の数を計算するのはすんなりできています。(例えば、=COUNTIF(A1:A5,"○"))この関数ではシートごとの集計はできないのでしょうか?ほかの関数を使うのでしょうか?集計する方法をご存知の方ご教示ください。

  • vbaの速度向上(sumif関数)

    エクセルvbaの速度を向上できないか、お知恵を貸していただきたく存じます。 以下のvba(sumif関数)をもっと速めたいです。何とかできないでしょうか。長い記載となり申し訳ないのですが、何卒よろしくお願い申し上げます。 myCnt7 = 2 Do Worksheets("●").Cells(myCnt7, 4).Value = WorksheetFunction.SumIf(Worksheets("◆").Range("B:R"), Worksheets("●").Cells(myCnt7, 3), Worksheets("◆").Range("R:R")) - WorksheetFunction.SumIf(Worksheets("★").Range("B:C"), Worksheets("●").Cells(myCnt7, 3), Worksheets("★").Range("C:C")) Worksheets("●").Cells(myCnt7, 7).Value = WorksheetFunction.SumIf(Worksheets("◆").Range("B:R"), Worksheets("●").Cells(myCnt7, 6), Worksheets("◆").Range("R:R")) - WorksheetFunction.SumIf(Worksheets("★").Range("B:C"), Worksheets("●").Cells(myCnt7, 6), Worksheets("★").Range("C:C")) Worksheets("●").Cells(myCnt7, 10).Value = WorksheetFunction.SumIf(Worksheets("◆").Range("B:R"), Worksheets("●").Cells(myCnt7, 9), Worksheets("◆").Range("R:R")) - WorksheetFunction.SumIf(Worksheets("★").Range("B:C"), Worksheets("●").Cells(myCnt7, 9), Worksheets("★").Range("C:C")) Loop While myCnt7 > 201 ※シート●のC列から3列ごとに、Sumifの検索条件があります。 ※シート●のD列から4列ごとに、Sumifの計算結果を出力させます。 ※計算対象シートは、シート◆とシート★の2つです。  シート◆のSumif合計から、シート★のSumif合計を差し引いています。  Sumifの条件自体は、どちらのシートも同じ(シート●)。 ※上記のSumif関数の記述は、3つですが、実際の記述は24あります。 ※すなわち、検索条件の組み合わせが24あり、201行分をmyCnt7でLoopさせて実行しています。

  • vbaでCountIf関数を使いたい(エクセル)

    A1セルにa-a-aがはいっています。 この場合aは3つですよね。 これをvbaで取得するコードを作っているのですがうまくできません。 Sub test() Dim myStr As String myStr = "a" MsgBox WorksheetFunction.CountIf(Cells(1, 1), "*" & myStr & "*") End Sub これをすると、なぜか1が返ってきます。 Aは3つあるのになぜ1が返るのでしょうか? A1にaaaaaを入れて実行しても1が返ります。

  • VBA ワークシート関数のエラー

    シートに数式を入れていたものを、VBAで値のみ入力しようと考えています。 そこで、.Cells(1,1) = WorksheetFunction.数式といった形のメソッドを試しています。 しかし、複雑な数式を記述するとエラーが出てしまいます。 成功 (iferrorというワークシート関数が1つ) Debug.Print WorksheetFunction.IfError(1 / .Cells(1, 5) + 1 / .Cells(1, 6) + 1 / .Cells(1, 7) - 1, "P") 失敗(ワークシート関数のifとcountifなど複数のものが数式に混入) Debug.Print WorksheetFunction.If(CountIf(Range("C17:D49"), Range("C29")) > 5, Range("C29"), Range("D29")) Countifの場所でエラーになります。このcountifを使えるようにするためには、どうすればよいのでしょうか? WorksheetFunction.if(WorksheetFunction.Countif(、、、、という書き方はダメでした。 数式が汚くてすみません。 宜しくお願いいたします。

  • countif関数の使い方について

    お世話になります。 下記の数式の{}がどういう風に計算されてるのか 教えてください。 A 1りんご 2りんご 3みかん 4りんご =SUM(COUNTIF(A1:A4,{"りんご","みかん"})) 自分なりに調べて配列数式?を意味してるということまでは分かったのですが どういう風にA1:A4と式が組まれてるのかがいまいちピンときません。。 またcountif関数がorやand関数と組み合わせできない理由も 配列が関係してるんでしょうか? 詳しい方よろしくお願いします。 ※当方エクセル初心者です

  • 「ワークシート関数」

    良くわからないのですが エクセルのワークシートで使う関数を「ワークシート関数」と言い、 VBAで使うワークシート関数を「WorksheetFunction関数」と言うのですか?

  • エクセルのCOUNTIF関数について

    エクセルのCOUNTIF関数について、というかCOUNTIF関数でよいのかどうかもよく分からないのですが、教えて下さい。 (1)まず、ワークシートのA列の1~100行目までの100マスを範囲として、数値を入力していくときに、仮に同じ数値を入力しようとしても、入力ができないようにしたいのです。 (2)次に、ワークシートのA列とC列のそれぞれ1~100行目までの合計200マスを範囲として、(1)と同じことをしたいのです。(つまりB列はとばして) (1)と(2)のようなことは可能でしょうか? お分かりの方がおられましたら、ぜひよろしくお願いします!

  • VBAのWorksheetFunctionの引数に配列を使いたい

    VBAにチャレンジし始めて、1ヶ月ほどの者です。 WorksheetFunctionの引数にVBAの配列を入れて計算させたいと思っています。 例えば、作業用の配列temp_arrayを定義し、temp_array()に格納した数字の平均値をWorksheetFunctionで求めるといったことです。 しかし、 Dim temp_array() As Variant Dim a As Double a = WorksheetFunction.Average(temp_array()) としても、 「実行時エラー'1004' WorksheetFunctionクラスのAverageプロパティーを取得できません」 というエラーで叱られます。 ネットで調べていると、Excelのワークシート関数には、引数として配列を扱えるものが多いとあったので、試してみています。 例えば、参考にしたのは下記のサイトの記述です。 http://www.clayhouse.jp/array/array03_d.htm もちろん、平均値を求めるぐらいなら、自分で関数をつくった方が早いのだとは思いますが、エクセルには色々な統計関数があるので、本当に配列として、WorksheetFunctionに簡単にわたせるなら、相当プログラムが楽でシンプルにできるなぁと思います。 もし、よくご存じの方がいたらアドバイスいただけませんでしょうか?

  • ワークシート関数とはどのことなのですか?

    【1】エクセルのワークシート上で使う=TODAY()などの関数 【2】VBAのCountなどのWorksheetFunction 【3】VBAのLENなどの関数 どれのことを俗に言う「ワークシート関数」と言うのでしょうか? VBAで使う【2】【3】のことですか?