[[20040105195022]] 『VBA:Autofilterメソッドの引数Criteria』(KAMIYA) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『VBA:Autofilterメソッドの引数Criteria』(KAMIYA)
 こんにちは。今回は表題の件でどうにもわからない現象があるので
 相談させていただきます。お願いします。
 まず、コードを提示します。(関係部分だけ抜粋)

 Sub ピッキングリスト作成V1()
 Dim MYSHEET As Worksheet
 Dim HSHEET As Worksheet
 Dim MYDATE As Date

 Set MYSHEET = Worksheets("RECORD")
 Set HSHEET = Worksheets("配分書")

 MYDATE = HSHEET.Range("B2").Value
 MYSHEET.Cells.AutoFilter Field:=2, Criteria1:=MYDATE
 '------
 '以下略
 '------
 End Sub

 RECORDシートはおおむね次のようになっています。
   A   B   C
  ID  日付 店舗 以下注文情報

 配分書シートはRECORDシートからリストを抽出するために用意したシートで、
 B2に特定日付のリストを作成するための日付が入るようになっています。
 つまり、RECORDシートのB列(シリアル日付)について
 配分書シートのB2の値(シリアル日付)でフィルタをかけるのが意図です。

 さて、本題ですが、上記のコードが動かないという話ではありません。
 自宅(Win XP/Excel2000SR1)で作った上記コードはちゃんと機能しました。

 が、会社(Win98/Excel2000SR1)で同じテストデータで上記を実行すると
 フィルタ後のデータがなし、つまりレコード全てが非表示になってしまいます。

 試行錯誤の結果、会社の環境では下記のように変更することで
 動作することがわかりました。

 Sub ピッキングリスト作成V2()
 Dim MYSHEET As Worksheet
 Dim HSHEET As Worksheet
 Dim MYDATE As String'←【Dateより変更】

 Set MYSHEET = Worksheets("RECORD")
 Set HSHEET = Worksheets("配分書")

 MYDATE = Format(HSHEET.Range("B2").Value, "yyyy/mm/dd")
 '↑【MYDATE = HSHEET.Range("B2").Valueより変更】

 MYSHEET.Cells.AutoFilter Field:=2, Criteria1:=MYDATE
 '------
 '以下略
 '------
 End Sub

 が、今度は自宅では「ピッキングリスト作成V2」が逆にうまくフィルタが
 かからなくなってしまいました。会社でだけ使用するので実用上問題はありませんが、
 「このような現象がおきる原因」
 「この現象を解消する対策」
 をご存知でしたらお教え願いたいと思います。


 テストデータが同一だという前提だと、XPと98という違いしか
 目に付かない。
 XPと98の違いでなにか原因がないかというように誘導されているようにも
 思えますけど、実際、テストデータは同じなんですか?

 自宅で入力、テストしたものを、会社にFDとかで持っていって
 試したらダメだったってこと?
 それとも自宅は自宅でテストデータを入力し、会社は会社で同じような
 テストデータを入力して試したらダメだったってこと?

 もし前者なら、デバッグでMYDATEに取得したデータを自宅と会社で比較して
 見てみたいところですけど...

 オートフィルタは表示形式に影響されるけど、そのへんはどうなんでしょう?
 (ramrun)

 ↓は97、2000でも同様です。

 [XL2002] 表示形式に年号データが入っていないとオートフィルタ オプションの結果が不正
http://support.microsoft.com/default.aspx?scid=kb;ja;405324&Product=xlw2kINT


 ramrunさん、いつもお世話になっています。
 お手数おかけします。
 将来的に複数のマシンで使う可能性もあり、
 マシンによってコードが違うなんてことがないように
 念のため相談させてもらいました。

 テストデータも含めてファイルはまったくの同一状態でした。
 フィルタをかける側の表示形式は「yyyy/mm/dd」です。

 MYDATEに格納した日付データは(自動データヒントで確認)当初、
 自宅→「2004/01/10」
 会社→「04/01/10」と表示され、
 Windowsのシステム日付表示形式の違いであると推測し
 「yy/MM/dd」→「yyyy/MM/dd」へ修正しリトライしましたが結果は同じでした。

 なによりも、同じデータ、同じファイル、同じExcelヴァージョンにもかかわらず、
 Date型変数で動いていたものがString型変数にしないと
 所期の動作を果たさないというのがなんとも不思議なところです。
 こうなるとOSとアプリの「相性」も「疑わしい」のであえてOSも記載しました。

 オートフィルタの動作をマクロで記録しても、同じ動作を期待できない
 という話は聞いたことはあるので、オートフィルタそのものがあまり
 安定していない機能なのかもしれません。

 幸い自宅のマシンはノートなので

 変数の格納状況やセルデータとの比較。
 Variant型で格納したらどうなるか。

 なんかも一応やってみます。
 もし結果がでたらこちらからも報告するようにします。
 ありがとうございました。
 (KAMIYA)


 XPと98では、日付でフィルタすると結果が異なることがあります。
 同じブックを使ってもXPでは抽出できても、98で抽出できないといった現象がありました。

 非常に困った現象です・・・
  (INA)


 そうなんだ。
 でも、そうだとするとVBAだから変な動作〜 ではなく、
 まさにOSの仕様ということになるね。

 コントロールパネルの[地域と言語]の設定で、日付を定義するところがあるけど
 XPと98で、そこの違いはありませんか?

 (ramrun)一休み〜

 ramrunさん ありがとうございます。
 自宅に帰ったら確認してみます。

  (INA)

 ramrunさん、INAさん、いろいろヒントありがとうございます。
 最終的には書きのようなコードにすることでWinXP、Win2K、Win98の各OSで
 所期の動作をするようになりました。

 Sub ピッキングリスト作成V3()
 Dim MYSHEET As Worksheet
 Dim HSHEET As Worksheet
 Dim MYDATE As Date

 Set MYSHEET = Worksheets("RECORD")
 Set HSHEET = Worksheets("配分書")

 MYDATE = HSHEET.Range("B2").Value
 MYSHEET.Cells.AutoFilter Field:=2, Criteria1:="=" & MYDATE
 '------
 '以下略
 '------
 End Sub

 98で[地域と言語]の設定がyy/MM/ddではうまく働きませんでした。
 また、ramrunさんの表示形式のヒントでフィルタをかける列の表示形式を調べたところ、(間抜けな話ですが)yyyy/m/dとyyyy/mm/ddが混在していました。
 つまり、XPの場合はその状態でもフィルタが利いていたことになります。

 結果をまとめてみます。

 それから、実際の動作を比較してみてフィルタ時にセルの日付データで
 98では・・・「表示」をテキストと見てCriteria1と比較?
       そのためDate型ではうまくフィルタできない?
 XP、2K・・・「内容」をシリアル値と見てCriteria1と比較
       Criteria1がString型の場合はシリアル値と厳密に区別
       ただし比較演算子のついた日付文字列ならシリアル値の比較として処理
       Criteria1がDate型なら表示形式に関係なくシリアル値同士として比較

 と、以上のことが推測できそうです。
 OSによって動作が異なるとは思っていなかったので、ちょっと慌ててしまいましたが、
 おかげさまでなんとか格好のつくものができそうです。

 お付き合いいただいたramrunさん、INAさんありがとうございました。
 (もし、追加情報あればお願いします。)
 (KAMIYA)


 98の言語設定がXPと違っていました。
 後ほど、98の設定を直して試してみます。

 わたしも便乗して勉強になりました。
 みなさん、ありがとうございました。

  (INA)


 よく読むとKAMIYAさんがいってるWindowsシステムのって、
 地域と言語のところのことだったんですね。
 気づいてませんでした(汗)。

 結局、98がダメってことなのかな?

 XPではシステムがyyyy/MM/ddだと、MYDATEに取得したときに2004/01/10
 システムがyy/MM/ddだと、MYDATEに取得したときに04/01/10
 というように変化するのを確認したけど、 98では変化しないってことでいいのかな?
 それともMYDATEは変化するけど、検索結果は変わらなかったってことなのかな?

 ちなみに推測のXP、2Kがシリアル値としてみているなら、実際シリアル値を
 入れても大丈夫ということでいいの?

 ついでにVariant型はどうなったの?

 (ramrun)

 ちょっと気になったんで、自分の環境、WinXPのExcel2000で確認しました。

 フィルタに使用するセルには 2004/1/10 と入力。
 こちらは1月10日と表示させておく。

 フィルタをかける表のほうは 2004/01/10 と表示するように表示形式を設定。

 Date型の MYDATE を宣言し、Debug.Printで内容をチェック。
 システムが yyyy/MM/dd だと MYDATE には 2004/01/10 が格納される。
 システムが yy/MM/dd だと MYDATE には 04/01/10 が格納される。
 Criteria1:=MYDATE すると、実際に Criteria1 に格納されるのは
 どちらも 1/10/2004 になる(m/d/yyyy)。
 2004/01/10 と1/10/2004 を比較して、検索されなかった。

 つぎに MYDATE をString型に変更する。
 システムが yyyy/MM/dd だと MYDATE には 2004/01/10 が格納される。
 システムが yy/MM/dd だと MYDATE には 04/01/10 が格納される。
 ここまではいっしょ。
 Criteria1:=MYDATE すると、実際に Criteria1 に格納されるのは
 システムが yyyy/MM/dd の場合は 2004/01/10
 システムが yy/MM/dd の場合は 04/01/10
 ようはシステムの表示形式のままが Criteria1 に格納された。
 システムが yyyy/MM/dd の方は 2004/01/10 と 2004/01/10 で同一となり検索できた。

 ちなみにVariant型を使うとシリアル値になってしまい
 Criteria1:=MYDATE ではまったくダメだった。

 結果
 フィルタに使用するデータは1月10日と表示形式をしていたが、
 MYDATEに格納されたときにはシステムの表示形式で格納される。
 これはDate型もString型も同じ。

 Date型は Criteria1 に格納された時点でなぜか m/d/yyyy になる。
 String型はシステムの表示形式のままが Criteria1 に格納される。

 そしてシステムの表示形式が yyyy/MM/dd で、
 フィルタをかける表の日付の表示形式も yyyy/mm/dd のときは検索できるが
 システムをyy/MM/ddに変更すると検索できなくなる。

 KAMIYAさんのDate型で Criteria1:="=" & MYDATE とする方法は
 String型で受けたときと同じ結果になった。
 ようはシステムをyy/MM/ddに変更すると検索できなくなる。

 うちのWinXPのExcel2000ではこんな感じでした。
 KAMIYAさんとこと違うみたい...
 (ramrun)

 ramrunさん、ありがとうございます。

 そうですね、ちょっと違うみたいですね。
 この件に関してはもう少し調べてみたいのですが、
 連休まで仕事のほうで手が離せないので、多少時間がかかります。
 それから、シリアル値とDate型データはよく考えると意味が違いますよね。
 取り違えていたみたいです。そこも踏まえてチェックします。
 フィルタの成功/不成功はフィルタの対象となる列の表示形式も
 影響しているようなので、そこら辺もじっくり。

 でも、 システムの[地域と言語]設定は影響大きいみたいです。
 そういえば、98は2000年以前のリリース・・・なるほど、です。
 (KAMIYA)

 一応、不完全ながらもテスト結果です。
 (Win2000のマシンがしばらくお出かけのためこちらはテストできませんでした。)
 変数に格納されている値がどうなるかよりも、実際にフィルタにかかるかどうか
 を中心にやってみました。
 下記結果一覧
http://ryusendo.no-ip.com/cgi-bin/upload/img/up0011.xls

 なお、表の「表示形式」はフィルタをかけるレコード側の表示形式です。
 が、納得いかないことに、ramrunさんの書いているように、
 最初に起こった現象(String型にしてXPで実行不可)が再現できません。
 他に設定を変更したかもしれませんが、ちょっと思い出せない。

 リンクファイルをご覧になるとわかりますが、
 AutoFilterの引数Criteriaに日付を利用する時

 String型の変数を利用したほうがOSの影響を受けにくい
 フィルタをかけるレコードの表示形式にかなり左右される

 そして、意外なのはXPのDate型とVariant型の変数でフィルタをかける時で、
 システム日付と表示形式がまったくマッチしていなくても検索してくれている。
 ???確かなんだろーか?書いているうちに自信なくなってきました。
 でも一番最初がこの状態[XP 表示形式yyyy/m/d Date型 システム日付yyyy/MM/dd]なんで
 間違いないと思うのですが・・・。
 (KAMIYA)


 同じこと確認してみました。
 うちのWinXP、Excel2000でも同様の結果です。

 うちのXPで、Date型、またはVariant型のmydateの場合、
 mydateに格納される日付はシステムの表示形式ですが、
 Criteria1:=mydateとしたときに、Criteria1にはm/d/yyyyの形式で
 4/9/2004が格納されます。

 ようはDate型もしくはVariant型の変数を使用した場合、
 システムの表示形式が何であろうとCriteria1に格納されるのは
 m/d/yyyyでした。

 そして分かったことは、XPの場合
 yyyy/m/d = m/d/yyyyとして処理されること。

 だから実際、Criteria1にはm/d/yyyyが格納されるが
 フィルタをかける表の日付がyyyy/m/dでもm/d/yyyyでも抽出できる。

 例外なのはこの表示形式だけで、ほかの例では
 yy/m/d ≠ m/d/yyのようになった。

 基本的に表示形式を文字列としてみて同一でないと抽出できないということで、
 Criteria1に格納された文字列 = フィルタをかける表の日付の表示形式上の文字列
 ということのようです。

 98のCriteria1がどうなるのかが気になりますが、
 あらかじめ表の日付列の表示形式を統一し、mydateをその表示形式にして
 Criteria1に渡してやれば、OSに依存しないフィルタがかけられると思います。
 (ramrun)

 Sub SampleMacro()
 Dim mydate As Date
 Dim myformat As Variant

 mydate = Range("h1").Value
 myformat = Range("b3").NumberFormat

 Range(Range("b3"), Range("b3").End(xlDown)).NumberFormat = Range   ("b3").NumberFormat

 Selection.AutoFilter Field:=2, Criteria1:=Format(mydate, myformat)
 End Sub


 返答遅くなり申し訳ありません。
 連休前でばたばたしていて、書き込みがあったのに
 気がつきませんでした。
 ramrunさん、改めての確認、ありがとうございます。

 実はこの二日間は98マシンが他のオペレーターに占領されていて、
 まとまった確認時間が取れなかったのです。
 が、表側と同じ表示形式での文字列で引数を渡せば双方での動作は
 間違いないようなので、ご指摘のとおり、

 「Criteria1には文字列で格納する」
 「MYDATEに格納した日付を表の表示形式に合わせた文字列で引数に渡す」
 「表の側の日付の表示形式をマクロで都度整形する」

 という方針でコード修正していきます。

 ところで、ramrunさんは
 >Criteria1にはm/d/yyyyの形式で 4/9/2004が格納されます。
 これはどのように確認してるのでしょう。
 Debug.Print でCriteria1を指定してもイミディエイトには
 空白しか返ってこないし・・・
 やり方が悪いのでしょうか。それとも他の方法が?

 お手を煩わせついでに教えていただけないでしょうか。
 (KAMIYA)


 失礼しました。
 なんだかDebug.PrintでCriteria1を確認したように
 文章から読み取れますね(汗)。

 Criteria1はまずマクロでフィルタをかけた後に
 実際にオートフィルタでフィルタがかかった状態になるわけですが、
 そこでオートフィルタのオプションを確認すると設定されているデータが
 m/d/yyyyになっているということです。

 あと、たとえばSheet2のA1の値をmydateに格納してフィルタをかける場合、
 A1がどんな表示形式でもmydateに格納されるのはシステムの表示形式なのに
 Debug.Print Sheet2.Range("A1").NumberFormat で確認すると
 m/d/yyyyになってます。

 (ramrun)

 >そこでオートフィルタのオプションを確認すると設定されているデータが
 なるほど〜〜。そこまでは気がまわりませんでした。
 実はその後のコードでオートフィルタを解除していたので、
 実行後にオプションの確認のしようがなかったのでした。
 確かにオプションに検索結果が残りますね。

 なんだか大掛かりになってしまい、お手数をおかけしました。
 オートフィルタへの日付の指定の仕方が確認できて大満足です。
 ramrunさん、 INAさん、ご協力ありがとうございました!!
 (KAMIYA)

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.