Excel (VBA)

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

 
(Windows 10 Home : Excel 2016)
日付のセルであることのみを検出
投稿日時: 19/08/16 23:33:06
投稿者: m1chael_m4ll

VBAで特定の日付を検出するのであれば

WorksheetFunction.Match(CLng(CDate("2019/8/5")), Range("A1:A10"), 0) 
というような形でいいと思うのですが、
 
検索する日付が変動し、なおかつその日付がいつなのかわからない場合
「日付の入っているセル」であるということはどのように検索すればいいでしょうか?
 
.Findを使えば日付を文字列として扱えるので
"*/*/*"
のようなワイルドカードで検索ができると聞いたのですが、それと同時に
1..Findの場合全く同じ処理を2回実行したときにも結果が変わってしまうことがある。あるいは存在しているのに値が返ってこない場合がある
2..Findは(関数での検索に比べて)すごく遅い
3.指定範囲を上から検索して一番初めに検出したセルを知りたい場合 .FindよりもMatch関数のほうが圧倒的におすすめ
とも聞きました。
 
場合によっては1行目から10行目よりもずっと広範囲に検索することもあるので、
Math関数を利用して、
何らかの日付(シリアル値)が入っているセルは○行目にある
という検索
ができたらと考えました。
 
もちろん、聞きかじっただけの知識なのでFindのほうが確実、別の関数のほうが適しているというものがあればそちらでもいいのですが・・・

回答
投稿日時: 19/08/17 09:22:04
投稿者: simple

日付のセルの書式は統一されているのでしょうか?
もし統一されていれば、書式を指定してFindを使う手がありますね。
 
ちなみに、Worksheetfunction.Matchだと、
・特定の数値か
・ワイルドカードとしては文字列を検索することになるので、
うまくいかないのではないですか?
 
ひとつひとつのセルについてIsDate関数でチェックしていく手もありますね。
まずは、「日付」の定義をもう少し詳しく書いてもらうとよいと思います。
単にserial値であれば、43694も日付となりますか?

投稿日時: 19/08/17 10:18:32
投稿者: m1chael_m4ll

日付セルの書式は統一してあります。
仮に日付が2019年の8月5日であれば、

Cells(1, 1).Value = "2019/8/5"
Cells(1, 1).NumberFormatLocal = "m月d日"

という感じです。
 
実を言うと
任意に選んだ日付とシートの「ある列」にあらかじめ存在する日付とを比較し、
「あらかじめ存在する日付」より「任意の日付」の方が大きいときに特定の処理をすることを考えています。
 
あらかじめ存在する日付は昇順には並んでいますが、日付のセルと日付のセルの間には別の文字列のセルなども存在しています。
 
A 12月2日
Bりんご
C4月25日
D2月2日
Eバナナ
 
のような形です。
 
そのため、
列の上から順に検索をかけ、
Do loop Until 任意の日付 > あらかじめ存在する日付
という条件でMatch関数の検索範囲引数を「列の一番上から最後まで」→「1つ目の日付セルの1つ下の行から最後まで」→「2つ目の日付セルの1つ下の行から最後まで」と繰り返すごとに狭めていくように設定しました。
我ながらすごく遠回しな表現であるような気はしているのですが、
「あらかじめ存在する日付」の数も日時も不定なため、1つ検証してダメなら次、ダメなら次とループを回すしかないのかなと思っております。

回答
投稿日時: 19/08/17 10:45:23
投稿者: simple

そうですか、書式は統一されているなら比較的容易ではないですか?
 
(1)
If r.NumberFormatLocal = "m""月""d""日""" Then
といった形でセル毎に判定していってもよいでしょうし、
(2)
Findを使って書式指定の検索を繰り返すかです。
マクロ記録を採ってみると参考コードが得られます。
引数は省略しないほうがよいと思います。
 
実験していませんが、たぶん(2)のほうが早い気がしますけど、
大した差ではないかもしれません。
コーディングに手間がかかるのは(2)かもしれません。

投稿日時: 19/08/17 13:16:11
投稿者: m1chael_m4ll

(2)は確かにコーディングが大変そうということもあり、
暫定的にForで(1)セルごとに検証して割り出すことに成功しました。
 
ありがとうございます。
日付に関してはやたらとその特性が煩雑で苦労しましたが、「りんご」「バナナ」などとても日付とは判断できない値と日付のみしかセルがなかったため、IsDate関数でも大丈夫そうですね。
ちなみに、検証はしていませんが30行ほどのセルを取り出して検証したところ、読み込み中カーソルになるほどの時間がかかるわけではありませんでした。
 
純粋に日付とはいっても現在の時刻を割り出すわけでもないのでString型で処理ができたら楽なのに・・