Excel (VBA)

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

 
(Windows 10全般 : Excel 2016)
AdvancedFilter 結果
投稿日時: 21/12/14 15:37:31
投稿者: f85ux

こんにちは、AdvancedFilter について質問します。
 
コピー元データ"テーブル1[氏名]"の1行目の値と同じ値が必ず1件抽出されてしまいます。
記述部分は以下の通りです、ご対応よろしくお願いいたします。
 
Range("テーブル1[氏名]").AdvancedFilter _
            Action:=xlFilterCopy, _
            CopyToRange:=Range("T8"), _
            Unique:=True

回答
投稿日時: 21/12/14 18:52:00
投稿者: simple

簡単な例を挙げて、
・こうなると想定しているが、
・実際はこうなってしまう、
という説明をしていただけますか。
行番号、列番号がわかるものでお願いします。
 
# 想像することはあるのですが、明確な例で議論したほうがよいと思いますので。

回答
投稿日時: 21/12/14 18:57:31
投稿者: sk

引用:
Range("テーブル1[氏名]").AdvancedFilter _
            Action:=xlFilterCopy, _
            CopyToRange:=Range("T8"), _
            Unique:=True

Range("テーブル1[氏名]").AdvancedFilter _
            Action:=xlFilterCopy, _
            CriteriaRange:="", _
            CopyToRange:=Range("T8"), _
            Unique:=True
 
----------------------------------------------------------
 
[氏名]列に含まれている全ての値を、重複データがない形で
T8 以下のセル範囲に複写しようとされているのであれば、
以上のようになさればよろしいのではないかと。
 
引用:
コピー元データ"テーブル1[氏名]"の1行目の値と同じ値が
必ず1件抽出されてしまいます。

(「データ行の 1 行目」であるとして)上記のステートメントより
先に実行された AdvancedFilter における抽出条件がそのように
指定されていたからではないでしょうか。

投稿日時: 21/12/14 20:31:37
投稿者: f85ux

skさま、simpleさま
早々のご対応ありがとうございます。
 
大変申し訳ございません、現在職場外におり、お二人のご意見を直ちに検証することができません。
検証結果のご報告はもうしばらくお待ちください。
 
それからskさまご指摘の、

引用:
(「データ行の 1 行目」であるとして)上記のステートメントより
先に実行された AdvancedFilter における抽出条件がそのように
指定されていたからではないでしょうか。

 
ですが、このシートではこの命令以外に実行するものが無いので、
現在の私の能力では、「先に実行された〜」は存在しないように思うところです。
 
ひとまずご連絡させていただきます。

投稿日時: 21/12/14 22:35:43
投稿者: f85ux

追加投稿いたします。
skさまご指摘の「CriteriaRange:="", _」
記述してみましたが、結果は最初の質問時と同様でした。
 
ただ今回1点気づいたことがありまして、
マクロ実行後、T8セルの名前が「Extract」となっており、
少しネットで調べたところ、ここを解決しないといけないのかな、
と思っております。
「名前の管理」にて「Extract」を削除しても同様でした。
 
 
simpleさまご指摘への返答です。
このような形でよろしいでしょうか?
 
  A   B   C    T
7 No  氏名      氏名
-----------------------------
8    タヌキ    タヌキ
9    青木     青木
10   青木     まぐろ
11   まぐろ    タヌキ
12   タヌキ    いわし
13   いわし    ロケット
14   まぐろ
15   タヌキ 
16   ロケット
 
以上です、ご対応よろしくお願いいたします。

回答
投稿日時: 21/12/14 23:01:18
投稿者: simple

再掲します。

引用:
・こうなると想定しているが、
・実際はこうなってしまう、
という説明をしていただけますか。

回答
投稿日時: 21/12/14 23:34:26
投稿者: simple

今の書き方だと、
B8,T8のタヌキが項目見出しとみなされるからです。
 
T7に「氏名」が入力されているなら、

    Range("テーブル1[[#All],[氏名]]").AdvancedFilter Action:=xlFilterCopy, _
        CopyToRange :=Range("T7"), Unique:=True
とする必要があります。
フィルタオプションは「見出し」が命です。

回答
投稿日時: 21/12/15 06:26:17
投稿者: simple

もう少し丁寧に書くと次のとおりです。
(1)あなたの示したコード

Range("テーブル1[氏名]").AdvancedFilter _
            Action:=xlFilterCopy, _
            CopyToRange:=Range("T8"), _
            Unique:=True
これをテーブルを使わずに書くと、
Range("B8:B16").AdvancedFilter _
            Action:=xlFilterCopy, _
            CopyToRange:=Range("T8"), _
            Unique:=True
としていることになります。
 
フィルタオプションでは、見出しを必ずつけることになっているので、
・最初のセル B8(タヌキ)が見出しと解釈されます。
・フィルタ結果は、T8以降に書き出されますが、
  T8は最初はブランクになっているので、
  この場合は、見出し+本体が T8以下に書き込まれます。
  ・T8 は見出しとしての「タヌキ」
  ・T11 は重複を排したデータとしての「タヌキ」です。
  (タヌキは2匹いますが意味が違います)
 
(2)一方で、私が提示したコードをテーブルを使わずに書けば、
 
Range("B7:B16").AdvancedFilter _
            Action:=xlFilterCopy, _
            CopyToRange:=Range("T7"), _
            Unique:=True
となりますが、
  ・元データは、B7:B16です。
    B7が見出しとみなされます。
  ・フィルタ結果は、T7:T13に書き込まれます。
  ・フィルタ結果のうち、"T7の見出し(氏名)にマッチした元データの列"の結果が
    T列8行目以降に書き込まれます。
   (このケースでは元データが1列しかないですが、
     複数あった場合は、このうち"T7で指定した見出しに対応した列"の結果が書き込まれます)
 
このように、フィルタオプションでは、
「見出し」が重要な位置を占めていますので、それなりに注意が必要です。

回答
投稿日時: 21/12/15 08:43:59
投稿者: mattuwan44

他の方の回答と重複する部分がありますが、書いてみます。
 
>Range("テーブル1[氏名]")
 
こう書いてセル範囲を指定すると、
タイトル行は除かれてテーブルのデータ部分のセル範囲を指定するということになります。
 
一方で、
AdvancedFilter(フィルターオプションの機能)は、
シート上のセル範囲の1行目がタイトル行であるという前提のもとに処理をします。
 
なので、今の書き方では、
Range("テーブル1[氏名]")というセル範囲の1行目がフィルターオプションのタイトル行になってしまってます。
 
フィルターオプションを使うことが前提ならば、こんな感じでしょうか?
 

Sub test2()
    ActiveSheet.ListObjects("テーブル1").ListColumns("氏名").Range.AdvancedFilter _
            Action:=xlFilterCopy, _
            CopyToRange:=Range("T7"), _
            Unique:=True
End Sub

 
当然T7にはタイトル行(氏名)が入っていることが前提です。
 
逆に、タイトル行はどうでもよいので、ユニークな(唯一無二な)値だけを取得できればよいなら、
単にコピペして、重複データの削除の機能(RemoveDuplicatesメソッド)を使うとよいです。
 
Sub Macro2()
    Range("テーブル1[氏名]").Copy Range("T8")
    Range("T8").CurrentRegion.RemoveDuplicates Columns:=1, Header:=xlNo
End Sub

投稿日時: 21/12/15 21:05:01
投稿者: f85ux

simpleさま、mattuwan44さま
 
ご連絡が遅れまして大変申し訳ありませんでした。
再度のご教授大変ありがとうございました。
今回お二人の示してくださった指示の通りに従い、やっと望む結果を得られました。
 
しかし、今回お二人から教えていただいたおかげで、
AdvancedFilter使用時、テーブル項目行の扱い方について初めて知るところとなりました。
重ね重ねお礼申し上げます。
 
これにて当掲示板閉鎖させていただきます。
ありがとうございました。