Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : 指定なし)
「フィルターがかかった状態で選択している行数を取得」について
投稿日時: 23/06/08 15:38:38
投稿者: hatena
投稿者のウェブサイトに移動

https://www.moug.net/faq/viewtopic.php?t=82299
 
上記質問ですが、
回答を準備しているうちに解決済みになってしまいましたが、
提示の方法では非表示の行もカウントしてしまうはずですので、
ご希望とはちがうのでは。
 
下記でどうでしょう。サンプルでテストした限りではうまく計算できてます。
 

Public Sub Test()
    Dim r As Range

    Set r = Selection.SpecialCells(xlCellTypeVisible).EntireRow
    Debug.Print r.Cells.Count / Columns.Count
   
End Sub

 
やっていることは、
選択範囲(Selection)の表示されているセル(SpecialCells(xlCellTypeVisible))の行全体を取得する。
その範囲のセル数÷列数で、行数を計算する。

回答
投稿日時: 23/06/08 17:19:33
投稿者: Suzu

行番号を選択すると、希望と異なる値になってしまいますね。
 
当方の考え方だと、行番号を選択しても 大丈夫でしたが
同じ Row で 異なる Column のセルを選ぶと、欲しい値になりませんでした。
 
対象の EntireRow を、Unionで受けて、その Rangeコレクションの 各Areasの Rows.Count を・・

Sub Test2()
  Dim rng1 As Range
  Dim rng2 As Range
  Dim i As Long

  With Range("A3").CurrentRegion.Offset(1, 0)
    With .Resize(.Rows.Count - 1)
      For Each rng1 In Application.Intersect(Selection, .SpecialCells(xlCellTypeVisible)).Areas
        If rng2 Is Nothing Then
          Set rng2 = rng1.EntireRow
        Else
          Set rng2 = Application.Union(rng2, rng1.EntireRow)
        End If
      Next
    End With
  End With

  For Each rng1 In rng2.Areas
    i = rng1.Rows.Count + i
  Next
  MsgBox i
End Sub

 
確かに求める事は出来ますが。。。なんか・・汚い・・

投稿日時: 23/06/08 19:45:24
投稿者: hatena
投稿者のウェブサイトに移動

> 行番号を選択すると、希望と異なる値になってしまいますね。
 
当方のサンプルでは正確な数字がでているようにですが。
「行番号を選択」とは「行番号をクリックして行全体を選択」という意味ですよね。
 
> 同じ Row で 異なる Column のセルを選ぶと、欲しい値になりませんでした。
 
こちらは当方のコードでもそうでしたので、改良してみました。
 

Public Sub Test()
    Dim r As Range

    Set r = Intersect(Selection.SpecialCells(xlCellTypeVisible).EntireRow, Cells)
    Debug.Print r.Cells.Count / Columns.Count
End Sub

回答
投稿日時: 23/06/09 08:14:17
投稿者: simple

スレッドが開かれましたので、場をお借りして補足説明します。
 
https://www.moug.net/tech/exvba/0150043.html
という紹介した記事は使えなかったでしょうか。

Sub Sample()
    Dim Count As Long
    Range("A1").AutoFilter Field:=4, _
        Criteria1:="マスター会員"  '「マスター会員」を抽出
    Count = WorksheetFunction.Subtotal(3, Range("A1").CurrentRegion.Columns(1))
    MsgBox Count - 1 & " 件です。"
End Sub

いや、そんなフィルターじゃないから、といった理由で使えないと判断したのでしょうか。
残念ですね。
pointは、
Count = WorksheetFunction.Subtotal(3, Range("A1").CurrentRegion.Columns(1))
のようにSUBTOTALワークシート関数が使えるという点です。
 
【補足】
その記事には、
> VBAでワークシート関数を利用するには、WorksheetFunctionオブジェクトを使います。
> SUBTOTAL関数は、第1引数に 3 を指定すると、データの個数を返します。

とあります。
SUBTOTAL関数のヘルプによれば、
| 第1引数に 3 を指定すると、非表示のものも含んだ COUNTA
| 第1引数に 103 を指定すると、非表示のものを除いた COUNTA

が計算されます。
しかし、オートフィルタの場合は、
3でも103でも表示されたものだけが対象になります。(オートフィルタの特殊性)
(素直に103を使わないのは、3でも同じ結果が得られることを知らないのでは?
  と批判されるのを懸念したものでしょうか。わかる気もしますww。)
 
なお、オートフィルタやフィルタオプションではなく、手動で行を非表示した場合には、
ヘルプの説明どおり、
第1引数に 103 を指定しなければ、表示されたものだけを対象にできません。

投稿日時: 23/06/09 11:08:47
投稿者: hatena
投稿者のウェブサイトに移動

simpleさん、
そのコードは表範囲でフィルターがかかっている場合、表範囲で表示されている行数を取得するものですね。
 
「フィルターがかかった状態で選択している行数を取得」とは、
フィルターがかかった状態でセル選択した場合、表示されていて、かつ、選択された部分の行数を取得するのだと私は解釈しました。
質問者のコードでもSelectionを使っていることからもそう思われます。
 

回答
投稿日時: 23/06/09 12:10:05
投稿者: simple

ご指摘ありがとうございました。そうかもしれません。
# 私のは即効テクニックの補足としてご覧ください。
随分凝った要望なんですね、私には目的がにわかには理解できませんでした。

MsgBox WorksheetFunction.Subtotal(3, Intersect(Selection.EntireRow, Columns(1)))
というのが考えつきます。

回答
投稿日時: 23/06/09 12:22:43
投稿者: Suzu

そうですね!!
 
Selection に対し、SpecialCellsを使えば良いのですね! 頭がカタくて逆に笑えてきますww
 
 
 
確認はしていませんが、処理時間としては、SubTotalを 使った方が速そうですね。
 
Intersect を使う必要があるかどうか。
 
ユーザーの範囲選択 において、
 複数範囲を選択する事があるのか によって使い分ければ良いでしょうね。
 
当方からは以上でした。

回答
投稿日時: 23/06/09 13:16:41
投稿者: sk

hatena さんの引用:
Public Sub Test()
    Dim r As Range
 
    Set r = Selection.SpecialCells(xlCellTypeVisible).EntireRow
    Debug.Print r.Cells.Count / Columns.Count
    
End Sub

選択中のブックの保存形式が .xlsx や .xlsm ファイルである場合、
ある列がまるごと選択されている状態で実行すればオーバーフローが発生しますね。

投稿日時: 23/06/09 14:18:55
投稿者: hatena
投稿者のウェブサイトに移動

> ある列がまるごと選択されている状態で実行すればオーバーフローが発生しますね。
 
たしかに。
よく考えたら下記でいいですね。
 

Public Sub Test()
    Dim r As Range

    Set r = Intersect(Selection.SpecialCells(xlCellTypeVisible).EntireRow, Columns(1))
    Debug.Print r.Cells.Count
End Sub

投稿日時: 23/06/09 14:22:27
投稿者: hatena
投稿者のウェブサイトに移動

simpleさんのコードが一番シンプルですね。
 
質問者さんも見てなさそうなので、しばらくしたら閉じます。

投稿日時: 23/06/09 21:05:17
投稿者: hatena
投稿者のウェブサイトに移動

閉じます。