質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

2回答

4124閲覧

vba 時刻の検索をしたい。

cheese0609

総合スコア1

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2021/07/11 02:02

編集2021/07/11 04:56

前提・実現したいこと

Excelのvbaで、「ユーザフォームのリストボックスで選択された日付と時刻をsheet2で検索(行または列番号の取得)する」ということをしたいです。
多くの時刻は検索できるのですが、特定の時刻だけ検索できず、理由と解決方法が知りたいです。
vba始めて1週間の初心者なので、詳しく教えていただけると助かります。
よろしくお願いします。
以下、コードと詳しい説明です。

具体的には、
リストボックスの値【日付,時刻,ID,セルのaddress,選択されたlistboxのindex】を配列に格納し、それを引数(num2)とした関数を作っています。
そして、num2(0)の日付(令和3年7月5日のような表記)とnum(1)の時刻(12:00のような表記)はString型だと思うので、CDateで変換し、match関数で検索するということをしています。
日付は、7月5日からエンドレスに作成してあり、時刻は、12:10~16:00まで10分刻みで作成しています。
検索したい箇所は、それぞれ日付(7月5日のような表記)はsheet2の9行目、時刻(12:00のような表記)はsheet2のC列(9~80行)です。
sheet2の時刻9行~80行は、「12:10, 12:10, 12:10, 12:20, 12:20, 12:20, ・・・, 16:00, 16:00, 16:00」というように同じ時刻を3回ずつ表記してあり、初めにmatchした値(行番号)を取得できれば良いです。
作ったプログラムでは何故か、「12:20, 13:10, 13:50, 14,40, 15,20」の時刻だけ検索できません。他の時刻は検索できます。
日付も検索出来ています。(日付はエンドレスの為、全て検索できるのか不安です。)

以下がコードになります。

発生している問題・エラーメッセージ

エラーメッセージは表示されていません。

該当のソースコード

vba

1Private Function del_func2(num2)'num2は配列で、「日付, 時刻, ID, セルのaddress(sheet1), 選択されたlistboxのindex」 2 Dim sht_2, sht_1 As Worksheet 3 Dim msg2 4 Set sht_1 = Sheets(1) 5 Set sht_2 = Sheets(2) 6 sht_2.Activate'ここでsheet2を作業できるようにしています。 7 '################################### 8 '# 日付の行検索 9 '################################### 10 Dim row_num As Variant 11 On Error Resume Next 12 row_num = WorksheetFunction.Match(CLng(CDate(num2(0))), Rows(Cells(1, 1).End(xlDown).Row + 1), 0) '日付の列を格納sheet2 13 On Error GoTo 0 14 If row_num = 0 Then 15 MsgBox "sheet2に日付がなく、" & vbCrLf & "削除出来ませんでした。" & vbCrLf & "プログラムを強制終了します。" 16 sht_1.Activate 17 End 18 End If 19 '################################### 20 '# 時間の行検索 21 '################################### 22 Dim col_time 23 On Error Resume Next 24 col_time = Application.WorksheetFunction.Match(CDbl(CDate(num2(1))), Range("C9:C80"), 0) '時刻の行を格納sheet2 25 On Error GoTo 0 26 If col_time = 0 Then 27 MsgBox "sheet2に時間がなく、" & vbCrLf & "削除出来ませんでした。" & vbCrLf & "プログラムを強制終了します。" 28 sht_1.Activate 29 End 30 End If 31 'MsgBox col_time 32End Function

試したこと

CDbl(CDate(num2(1))とRange("C9:C80")の型と表記の判定を行いました。
型は両方Double型(vartypeで確認出力5)で、表記は「12:00」のような表記(msgboxで目視で確認)でした。
一応、「CDbl(CDate(num2(1)) is Range(対応するセル)」と「CDbl(CDate(num2(1)) is Range(対応するセル)」を行いましたがどちらもFALSEでした。

補足情報(FW/ツールのバージョンなど)

ユーザーフォームのリストボックスはこんな感じです。
num2(0)に日付
num2(1)に時刻
num2(2)にID
num2(3)に選択されたIDが位置するsheet1のaddress(画像では非表示)
num2(4)に選択されたリストボックスのindex(画像では非表示)
ユーザフォームのリストボックス

sheet2はこのような表示になっています。
sheet2

説明下手で申し訳ございませんが、何卒よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hatena19

2021/07/11 02:58

On Error Resume Next の行をコメントアウトして実行してみてくだいさい。 それでエラーが出たらそのエラーメッセージを追記してください。
hatena19

2021/07/11 03:05

あと、Range("C9:C80") の書式設定はどうなってますか。
cheese0609

2021/07/11 03:06

ご連絡ありがとうございます。 検索できない特定の時刻のみ、 「WorksheetFunctionクラスのMatchプロパティを取得できません。」 とエラーが出ます。
cheese0609

2021/07/11 03:08

Range("C9:C80") の書式設定について、書式設定は「時刻の13:30」というものを設定しています
guest

回答2

0

ベストアンサー

検証してみました。

提示の画像のようにシートに時刻を入力して、
下記のコードを実行。

vba

1 2'C12セルの値 12:20 3Debug.Print Range("C12") = CDbl(CDate("12:20")) 4'結果はFalse 5 6'C21セルの値 12:50 7Debug.Print Range("C21") = CDbl(CDate("12:50")) 8'結果はTrue

同様に「12:20, 13:10, 13:50, 14,40, 15,20」の時刻でも試してみましたが、Falseになりました。

CDblで倍精度浮動小数点数に変換してますが、浮動小数点数には誤差がつきものですので、厳密な比較には向かないというのはプログラミングのあるあるです。

Match関数では日付/時刻型では検索できないのでCDblでの変換は必須なので、Match関数はあきらめてループで処理するぐらいしかなさそうです。あるいはFindメソッドでもいけるかも。

Findメソッドのコード例

vba

1 '################################### 2 '# 時間の行検索 3 '################################### 4 Dim rng As Range 5 set rng = Range("C9:C80").Find(CDate(num2(1))) 6 If Rng Is Nothing Then 7 MsgBox "sheet2に時間がなく、" & vbCrLf & "削除出来ませんでした。" & vbCrLf & "プログラムを強制終了します。" 8 sht_1.Activate 9 Exit Function 'Endで強制終了は危険なのでExitに変更 10 End If

ループ処理で検索する方法のコード例

vba

1 Dim rng As Range, flg As Boolean 2 For Each rng In Range("C9:C24") 3 If Format(rng.Value, "hh:mm") = "12:30" Then 4 flg = True 5 Exit For 6 End If 7 Next 8 If flg = False Then 9 MsgBox "sheet2に時間がなく、" & vbCrLf & "削除出来ませんでした。" & vbCrLf & "プログラムを強制終了します。" 10 sht_1.Activate 11 Exit Function 12 End If

投稿2021/07/11 04:13

編集2021/07/11 05:40
hatena19

総合スコア34064

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cheese0609

2021/07/11 04:45

hatena19様 回答ありがとうございます。 Match関数は諦めようと思います。 そして、Findメソッドですが、以前試したところこちらでも時刻の検索は出来ないように思えます。 ご提示頂きましたFindメソッドのコード例で試してみても、検索出来ませんでした。 rng is nothingの処理が実行されてしまいます。 時刻検索自体出来ないのでしょうか・・・?
cheese0609

2021/07/11 04:52

すみません。 説明不足でした。 Findメソッドでは前回の検索条件が適応されてしまう(?)ようなので、 ①ご指摘頂いたコード ➁Find(CDate(num2(1)), LookIn:=xlValues, LookAt:=xlPart) ③Find(CDate(num2(1)), LookIn:=xlValues, LookAt:=xlWhole) の3つで試しました。 どれも、rng is nothingの処理になってしまいました。
hatena19

2021/07/11 05:28

Find(num2(1), LookIn:=xlValues, LookAt:=xlWhole) だとどうでしょう。
cheese0609

2021/07/11 05:35

hatena19様 何度もありがとうございます。 Find(num2(1), LookIn:=xlValues, LookAt:=xlWhole) で検索することができました。 また、色々試していたところ、 Find(Format(CDate(num2(1)), "hh:mm"), LookIn:=xlValues, LookAt:=xlWhole) でも検索できました。 色々とありがとうございました。 このシステムは、地元の病院でコロナワクチンの予約システムとして使用させて頂きます。 本当に、ありがとうございました。
hatena19

2021/07/11 05:38

うまくいってよかったですね。 参考までに、ループで検索する方法も追記しておきました。
cheese0609

2021/07/11 05:42

とても参考になります。 ありがとうございました。
guest

0

確証はありませんが、シートの時間をオートフィルで埋めたのであれば、一度各セルで[F2][Enter]とするといいかもしれません。

それか、いっそのこと、シートの「時間」の列の書式を文字列にするのはどうでしょう。

投稿2021/07/11 06:21

jinoji

総合スコア4592

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問