• 締切済み

[VBA]SpecialCellsが利かない?

選択範囲で定数(数値)が含まれているセルを表示する自作関数を 作成したいと考えていますがうまく動いてくれません。 以下のサンプルコードを実行すると選択した範囲全てが表示されてしまいます。 初心者で申し訳ないですがご教示下さい。 ■ 標準モジュールソース --------------------------------------- Function SAMPLE(SelectRange) For Each c In SelectRange.SpecialCells(xlCellTypeConstants, xlNumbers) MsgBox c.Value Next End Function --------------------------------------- → 再現方法:A1に「1」と入力して、B1セルに「=SAMPLE(A1:A2)」と入力 よろしくお願いします。

みんなの回答

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.2

ご提示のコードでは再現されますが、下記コードはCell.Countは1を与え、MsgBoxも一回しか表示されません。正常動作です。 理屈は分かりませんが、ユーザー定義関数内でMsgBoxという行為に無理があるのではないでしょうか。 Sub test() Dim c As Range Debug.Print Range("A1:A2").SpecialCells(xlCellTypeConstants, xlNumbers).Cells.Count For Each c In Range("A1:A2").SpecialCells(xlCellTypeConstants, xlNumbers) MsgBox c.Value Next End Sub ところで、A列全体を対象にしたときとても遅いという件について試してみました。 Private Declare Function GetTickCount Lib "kernel32" () As Long Sub test2() Dim c As Range Dim cnt As Long Dim myVal As Variant Dim buf As Variant Dim startTime As Long Dim i As Long myVal = 1 For Each c In Columns(1).Cells If c.Value = myVal Then cnt = cnt + 1 Next c Debug.Print "Cellにアクセス", GetTickCount - startTime, cnt startTime = GetTickCount cnt = 0 buf = Columns(1).Value For i = 1 To UBound(buf, 1) 'xl2010なので 1048576 行 If buf(i, 1) = myVal Then cnt = cnt + 1 Next i Debug.Print "配列に入れてアクセス", GetTickCount - startTime, cnt End Sub 結果 時間の単位はmsecです。 Cellにアクセス 11625412 1 配列に入れてアクセス 94 1 Cellにアクセス 11628891 1 配列に入れてアクセス 78 1 速度差15万倍という結果でした。 ご参考まで。

noname#203218
noname#203218
回答No.1

指定セル範囲の最初の数値セルデータを取得したいのであれば下記方法で可能だと思います。 (文字列データは取得しません。) ご参考まで。 Function SAMPLE(myRng As Range) As Double Dim c As Range On Error Resume Next Application.Volatile 'セルが空白でなく、かつセルデータが数値である場合データ取得 For Each c In myRng If c.Value <> Empty And IsNumeric(c.Value) Then SAMPLE = c.Value Exit For End If Next End Function

wansui
質問者

補足

早急な対応有難うございます。 わざわざサンプルコードまでご教示頂きましたが残念ながら 希望の仕様とは異なるものでした。 具体的にやりたい事は、フィルタ結果から任意数値の出現回数をカウントしたいです。 (COUNTIFとSUBTOTALを合わせたもの) ただ、上記仕様を簡単に実現すると -------------------------------------------------------- Function SAMPLE(SelectRange As Range, Val As Integer) For Each c In SelectRange If c.Value = Val Then Cnt = Cnt + 1 Next SAMPLE = Cnt End Function -------------------------------------------------------- となりますが、この場合仮に式が「=SAMPLE(A:A,1)」(A列全セルの"1"をカウント)の場合 とてつもなく時間がかかるため、可視セル且つ定数(数値)のみのセルで処理を 行いたいと考えています。 補足ですいませんが、何が意見等ございましたら 回答頂ければ幸いです。お忙しい中すいません。

関連するQ&A

  • エクセルVBA/SpecialCellsで特定文字列のセルを選択

    いつもお世話様です。 Sub test() ActiveSheet.Range("C1:C200").SpecialCells(xlCellTypeConstants).Select End Sub で検索範囲内の「定数」のセルをいっぺんに選択できますが、これを例えば、「AAA」という文字列のセルだけを一度に選択するにはどうすればいいでしょうか? (また、あるいは「123」という数値のセルの場合には?) よろしくお願いします。

  • VBA 範囲選択について

    複数のセルを選択してマクロを実行し、範囲選択の個数をMsgboxで表示したいです 例えばA1:B5、C6、D2:E3、を同時に範囲選択していたら「3個」のように表示 分かる方がいらっしゃるのであれば、回答をよろしくお願いします

  • EXCEL VBA 空白行を含んだ範囲選択

    EXCEL VBA超初心者です。 EXCELのVBAについての質問です。 以下のような、日ごとのお金の貸付、返済の一覧データがあります。 例 A B C D E 1 年  月 日 貸付  返済 2 2008 5 10 10000 3 2008 6 10      8000 4 2008 7 10 20000 5 2008 8 20      7000 ・データの行数は決まっていません。 ・最後の行が「貸付」で終わることもありますし 例のように「入金」で終わることもあります。 ・各データには必ず「年」「月」「日」が入力してあります。 VBAで、A2セルからE5セルを範囲選択するには どのように記述したらいいですか? ちなみに自分で色々と調べてみて Selection.SpecialCells(xlCellTypeConstants, 23).Select としたのですが それだと空白セル(例でいうとE2やD3セル)が選択されず とびとびになってしまいました。 ご教授お願いいたします!

  • エクセルVBAでの「値貼り付け、乗算」について

    あるセル範囲に一度に一定の数を乗ずるには、その一定の数が入力されたセルをコピーしてから、形式を選択して貼り付けで、値貼り付け、そして「乗算」を指定するのがもっとも効率的かと思います。 これをVBAで行う場合、以下のようなコードになるかと思います。 Sub test05() Dim z As Range Set z = ActiveCell.SpecialCells(xlLastCell).Offset(1) z.Value = 2 z.Copy On Error GoTo line Range("A1:H3000").SpecialCells(xlCellTypeConstants, 1).PasteSpecial Paste:=xlPasteValues, Operation:=xlMultiply On Error GoTo 0 Application.CutCopyMode = False z.Clear Set z = Nothing Exit Sub line: MsgBox "対象内に数値がありません。" End Sub 上記コードは正しく作動します。 質問は、「その一定の数が入力されたセルをコピーしてから」の部分を、他の方法で代用できないかということです。上記コードでは最終セルのひとつ下、SpecialCells(xlLastCell).Offset(1)を使用していますが、SpecialCells(xlLastCell).Offset(1)が存在しない場合も理論上はありえます。 わざわざセルに転記し、それをコピーする代わりに、コード内で乗じる数を指定できないのでしょうか?

  • Excel VBAにて、SpecialCells(xlCellTypeVisible) に関する質問

    Excel VBAにて、SpecialCells(xlCellTypeVisible) に関する質問です。 セル ("A1:B7")に表があります。 a b 1 1 1 1 2 2 2 2 3 3 3 3 下記のVBAにて、temp2の値が、1となります。これが分かりません。 当方、欲しいのは、オートフィルタ後の見えている行の数です。 temp1=6は、オートフィルタで、選択されたセルs+ヘッダの計6こということで理解しています。 temp3=2は、列の数として、合っています。 Sub Macro1() Dim aa As Range Set aa = Range("A1:B7") aa.AutoFilter Field:=2, Criteria1:="2" temp1 = aa.SpecialCells(xlCellTypeVisible).Cells.Count 'temp1=6 temp2 = aa.SpecialCells(xlCellTypeVisible).Rows.Count 'temp2=1 temp3 = aa.SpecialCells(xlCellTypeVisible).Columns.Count 'temp3=2 End Sub 考え方として、間違ってはいないと思うのですが、行の数を求めるには、どのようにすれば良いでしょうか?

  • Excel(SpecialCellsで文字列を探し式の設定)

    いつもお世話になっております 先日も質問させて頂きました お世話になり、ありがとうございました 新たな問題が出て、解決できません ご存知の方ご教授お願い致します A列内に数値型と文字列、式の入ったセルが混ざって10000件程度あります ActiveSheet.Range("A:A").SpecialCells(xlCellTypeConstants, xlTextValues).Select で文字列のセルを選択するとこまでは良いのですが、この後選択した文字列の セルに式を入れたいと思うのですが、うまくいきません もしご存知のかたいらっしゃいましたらご教授お願いします この考えは、セル内に文字列の数値が設定されていて オートカルクが出来ない為、数値型に変換しようと思い上記のような ことを考えております セルをWクリックすると数値にはなるのですが、件数が多い為マクロを 組もうと思いました

  • SelectionとSelectについて?(エクセルVBA)

    任意に範囲選択したセルのうち数式が定義されているセルのみを選択するマクロについて教えてください。 次のようにコードを書いて Sub TEST() ' MsgBox Selection.Address Selection.SpecialCells(xlCellTypeFormulas).Select End Sub 任意の複数のセルに数式を定義します。(配置はばらばらでも構いません) あるセル範囲を選択して上のコードを実行すると、次のような動作になります。 数式を定義したセル(以降、数式セル)を1つ以上と、数式の定義に関わらず別の1つ以上を含むセル範囲を選択した場合は、希望通りに数式セルが選択されます。 しかし、数式セルを一つだけ選択してコードを実行すると、シート全体で数式セルが選択されてしまいます。 ヘルプをみると、Selectionには、セルを選択しているときは、Range オブジェクトが返されます。とあり、SpecialCellsには、オブジェクトを返すメソッドです。指定された条件を満たしているすべてのセル (Range オブジェクト) を返します。とあります。 素人的には、Selection プロパティで返されるオブジェクトの種類は、何を選択するかによって異なります。の部分で、返されるオブジェクトが一つのセルを選択した場合は、オブジェクトがシートになってしまっているからだと推測します。しかし、複数のセルを結合したセルに数式を定義した場合で、一つの数式結合セルを選択して、MsgBox Selection.Addressと表示させると、Selectionは、複数のセルからなるセル範囲を返している様なメッセージが表示されるのに、次の行では、同じくシート全体が選択されてしまいます。 回避する方法ってないのでしょうか?教えて頂けないでしょうか?宜しくお願い致します。 また、説明が悪くてすみません。

  • Excel VBA 空白セルをチェックする方法

    こんばんは ある選択範囲でどれか1つのセルに空白があった場合 メッセージを表示させたいのですが、 リスト中に入力された範囲のすべてのセルをチェックしたいのです。 どのようにしたら良いのでしょうか。 A1~A3の範囲のみでしたら下記でよいのかな?と考えてみました。 VBA勉強中なのですが、なかなかうまくいきません。お力をお願い致します。 If IsEmpty(Range("a2:d2").Value) Then MsgBox "開始時刻が入力されていません。" Worksheets("Sheet1").Range("a2").Select

  • エクセルVBAでジャンプ(セル選択)?

    いつもお世話になっております。 エクセル(2000)の特定のセル選択の方法について教えてくださいませ。 Sub TEST01() Range("A1:A20").SpecialCells(xlCellTypeBlanks).Select End Sub これで、指定範囲内の空白セルをSelectできますね。 Sub TEST02() Range("A1:A20").SpecialCells(xlCellTypeFormulas, 1).Select End Sub これで、指定範囲内で、数式により数値が表示されたセルをSelectできますね。 質問1 では、指定範囲内で、数式により何も表示されないセルをSelectできますか? 空の文字列( ="" )だから、SpecialCells(xlCellTypeFormulas, 2)でSelectできますが、これでは他にも数式により文字が表示されたセルもSelectされてしまいます。 質問2 数値がマイナスのものだけをSelectする方法があるでしょうか? 別に、「ジャンプ」にはこだわりませんが、データ件数が多いので For NextでLoop 以外の方法をご教示いただけたら幸いです。

  • VBA MsgBOXでの処理分岐

    B列に抹消と入力したら別の列に抹消と記載する以下のマクロがありますが、 B列に抹消と入力したらMsgBoxで抹消しますか?と表示させたいです。 MsgBox関数を特定場所に挿入したのですが、うまくいかず、どこに挿入したらよろしいでしょうか。(オブジェクトが必要です。のエラーが出てしまう状況です。) Private Sub Worksheet_Change(ByVal Target As Excel.Range) Dim h As Range On Error Resume Next For Each h In Application.Intersect(Target, Range("B:B")) If h = "抹消" Then Cells(h.Row, "E").Resize(1, 7).SpecialCells(xlCellTypeConstants) = "抹消" End If Next End Sub

専門家に質問してみよう