Excel (VBA)

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

 
(Windows 10 Home : Excel 2016)
同じ日付かを確認する方法について
投稿日時: 17/07/24 15:08:57
投稿者: Dellcasio

 
A列には、日付と時刻   B列には、日付のみ
 
IF条件式で、A列とB列を比較して、同じ日付かを確認
したいのですが、どの関数を使って比較すれば
よいのか、調べてもよくわかりませんでした。
 
ご指導宜しくお願い致します。
 
 
 
 
  A列            B列
2017/07/19 17:29:33   、2017/07/20
2017/07/19 17:32:57    2017/07/20
2017/07/19 17:38:29    2017/07/20
 
 
 

回答
投稿日時: 17/07/24 15:48:57
投稿者: 半平太

関数の質問ですよね? (ここはVBA板ですよ。ま、VBAでも同じ事ですけど))
 
日付部分(=整数部分)を取り出して比較する↓
 
 =INT(A1)=B1

回答
投稿日時: 17/07/24 15:54:19
投稿者: mattuwan44

ども^^
 
ぱっと、思いついたのは、
日付と時間の値っていうのは内部的には、
日付が整数で、時間が小数で表されるから、
値の中から小数をバッサリ落してやれば、
日付同士として比較できますね。
 

Sub test()
    Dim c As Range
    
    For Each c In Range("A1:A3")
        If Int(c.Value2) = c.Offset(, 1).Value2 Then
            MsgBox c.Row & "行目: " & True
        Else
            MsgBox c.Row & "行目: " & False
        End If
    Next
End Sub

 
また、セルの見た目の文字をDateValue関数で日付に直してもいけそう。
Sub test2()
    Dim c As Range
    
    For Each c In Range("A1:A3")
        If DateValue(c.Text) = DateValue(c.Offset(, 1).Text) Then
            MsgBox c.Row & "行目: " & True
        Else
            MsgBox c.Row & "行目: " & False
        End If
    Next
End Sub

 
あぁ、関数ならDateDiff関数が使えそうですね。
 
Sub test3()
    Dim c As Range
    Dim flg As Boolean
    
    For Each c In Range("A1:A4")
        flg = DateDiff("d", c.Value, c.Offset(, 1).Value)
        MsgBox c.Row & "行目: " & Not flg
    Next
End Sub

 

投稿日時: 17/07/24 18:43:04
投稿者: Dellcasio

mattuwan44 さんの引用:
ども^^
 
ぱっと、思いついたのは、
日付と時間の値っていうのは内部的には、
日付が整数で、時間が小数で表されるから、
値の中から小数をバッサリ落してやれば、
日付同士として比較できますね。
 
Sub test()
    Dim c As Range
    
    For Each c In Range("A1:A3")
        If Int(c.Value2) = c.Offset(, 1).Value2 Then
            MsgBox c.Row & "行目: " & True
        Else
            MsgBox c.Row & "行目: " & False
        End If
    Next
End Sub

 
また、セルの見た目の文字をDateValue関数で日付に直してもいけそう。
Sub test2()
    Dim c As Range
    
    For Each c In Range("A1:A3")
        If DateValue(c.Text) = DateValue(c.Offset(, 1).Text) Then
            MsgBox c.Row & "行目: " & True
        Else
            MsgBox c.Row & "行目: " & False
        End If
    Next
End Sub

 
あぁ、関数ならDateDiff関数が使えそうですね。
 
Sub test3()
    Dim c As Range
    Dim flg As Boolean
    
    For Each c In Range("A1:A4")
        flg = DateDiff("d", c.Value, c.Offset(, 1).Value)
        MsgBox c.Row & "行目: " & Not flg
    Next
End Sub

 

 
 mattuwan44 さん
 
ご回答ありがとうございます。
 
VBAの初心者なので、
 For Each c In Range("A1:A3")のコードが分かりません。
 
もしよろしければ、
 
For j = 2 To 10
If Worksheets("売上伝票").Cells(j, 1).Value =
 
の様な、For i = 2 to 10
  
を使えるコードで書いて
頂けないでしょうか、
 
よろしくお願い致します。

回答
投稿日時: 17/07/24 21:49:39
投稿者: simple

基本的な知識をきちんと抑えることをお勧めします。
 

Excelでは
・日付を整数で管理し、
・時刻は小数部分で管理します。

・日付は1900/1/1  を 1で始め、
        1900/1/2  を 2
        1900/1/3  を 3
        ・・・・  ・・・
        2017/7/24   42940という整数で保持しています。
       (表示にあたって日付形式にしているだけで、値は整数です)
・時刻は、
        0   が 0:00分
        0.5 が12:00分
  一日の時刻を0から1までの小数で保持しています。
・2017/7/24の12:00は 42940.5 という実数で保持されています。

 
そうした知識があれば、
2017/07/19 17:29:33 の整数だけをとりだし、
それと 2017/07/20に対応する整数とを比較すればよいとわかるはずです。
 
すでに指摘がありましたが、
ワークシート関数であれば、
INT(A1) で整数部分を取り出し、
これと B1(これは整数です。表示は時刻表示になってはいますが)
を比較するのです。
 
コードは、上記のことが理解できれば、
自ずと今までの知識で対応できるはずです。
トライしてください。
簡単な繰り返しですから、他人に頼らなくても、必ずできるはずです。
 
 
---------------------------------------------------
なお、
【時刻をAMとPMに分けたい】
http://www.moug.net/faq/viewtopic.php?t=75978
での議論も、上のことが理解できていれば、簡単に対応できたはずです。
 
最初、時刻の話をしていたのに、途中で日付を付け加えてきたのですが、
それは整数部分を除けば、時刻の話に還元できたはずです。
 
Format(Range("A1").Value, "AM/PM") という関数の適用例を覚えるのも
一つの知識に違いありませんが、それは単独の知識です。
 
日付、時刻がどう管理されているかの知識のほうが、
より基本的な話で、しかも応用が利く知識だと思っています。
是非、よく理解するようにしてください。

回答
投稿日時: 17/07/27 20:53:58
投稿者: mattuwan44

ども^^;
パソコンの前になかなか座れなかった^^;
すみません。
 
>を使えるコードで書いて
>頂けないでしょうか、

 

Sub test0()
    Dim ixRow As Long
    
    For ixRow = 2 To 10
        Set c = Worksheets("売上伝票").Cells(ixRow, "A")
        If Int(Worksheets("売上伝票").Cells(ixRow, "A").Value2) = Worksheets("売上伝票").Cells(ixRow, "A").Offset(, 1).Value2 Then
            MsgBox Worksheets("売上伝票").Cells(ixRow, "A").Row & "行目: " & True
        Else
            MsgBox Worksheets("売上伝票").Cells(ixRow, "A").Row & "行目: " & False
        End If
    Next
End Sub

こういうことかな?
でも、同じ文言が出てきてますね。
これだと、対象のシート名が変わったときにたくさんの箇所を書き直さないといけません。
こういう時は変数を使います。
 
Sub test1()
    Dim c As Range
    Dim ixRow As Long
    
    For ixRow = 2 To 10
        Set c = Worksheets("売上伝票").Cells(ixRow, "A")
        If Int(c.Value2) = c.Offset(, 1).Value2 Then
            MsgBox c.Row & "行目: " & True
        Else
            MsgBox c.Row & "行目: " & False
        End If
    Next
End Sub

これだと、対象のシートが変わっても1か所だけ直せばいいです。
こういう変数の使い方をぜび覚えてください。
このとき、変数「c」には、セルそのものが入っています。
つまり、所属するシートや行番号、フォント名や塗りつぶしの色、
セルを形づくるすべての要素が入ってます。
なのでその情報群から行番号が欲しければ、
c.Row
として個別の要素を取り出します。
 
それから、Cellsプロパティですが、個別のセルを指定するプロパティと認識されていますが、
Cellsと複数形ですよね?
これは、セルの集まりの中のどのセルかという意味です。
つまり、
Cells(3,5)
は、アクティブなシートを構成するセル達の中の3行目の5列目という意味です。
 
For Each 〜 ステートメントですが、
 
これは、コレクション(=集合体=集まり)の各要素に対して、
一連の手続き(≒命令)を繰り返し実行する命令文です。
 
For Each c In Range("A1:A3")
セル範囲(A1:A3)を構成するセルの集合のうちの各要素(各セル)それぞれに
というような意味になると思います。
 
「わからない」で思考を止めずに、ぜひ色々考えて、色々調べて、
新しい言葉をどんどん覚えてください。
 
For 〜 Next
よりFor Each 〜 Nextのほうが若干処理速度が速くなるようです。
いろいろな表現方法を覚えるのも悪くないと思います。
 
参考URL>>
http://www.eurus.dti.ne.jp/~Yoneyama/Excel/vba/vba_for_next.html
http://officetanaka.net/excel/vba/variable/11.htm
http://www.relief.jp/docs/excel-vba-test-object-variables.html

回答
投稿日時: 17/07/28 07:11:25
投稿者: simple

# 他のかたの発言と重複していますが、折角書いてしまったのでそのまま投稿します。
# ご了承ください。
 

     A列     B列
1行    1       2
2      1       1
3      1       3

があったとき、同じ事をマクロで作成できますよね。
繰り返しについて学習したのなら、書けるはずです。
手も足も出ないなら、テキストを最初から復習して下さい。
例えば、以下のように書いてもいいでしょう。
Sub test()
    Dim k As Long
    For k = 1 To 3
        If Cells(k, 1).Value <> Cells(k, 2).Value Then
            Cells(k, 3).Value = "不一致"
        End If
    Next
End Sub

A列が日付+時刻、B列が日付だけのデータであれば、
        If Cells(k, 1).Value <> Cells(k, 2).Value Then
を      If Int(Cells(k, 1).Value) <> Cells(k, 2).Value Then
に変更するだけです。

---------------------
なお、mattuwan44 さんの回答コメントのなかに、
Value2プロパティが示されています。
これを使うことで、日付+時刻 の「シリアル値」を取得することができます。
https://www.moug.net/tech/exvba/0050148.html
を参考にしてください。
 
また、
> For Each c In Range("A1:A3")のコードが分かりません
とのことですが、よく使われるコードですから、
>初心者なので
などと言っていずに、勉強してください。
 
Sub test2()
    Dim r  As Range
    For Each r In Range("A1:A3")
        If Int(r.Value) <> r.Offset(, 1).Value Then
            r.Offset(, 2).Value = "不一致"
        End If
    Next
End Sub
などと使います。
# 細かいミスがあったので、昨晩の投稿をやり直しました。

回答
投稿日時: 17/08/05 12:59:54
投稿者: simple

http://www.moug.net/faq/viewtopic.php?t=76055
を閉じられてしまったので、こちらのスレッドとは無関係で恐縮ですが、
コメントします。
 
「P列の文字がO列に含まれているかをチェツクしたい 」の件です。
 
プロシージャの名前は別として、
 
@貴方の提示されたコード

If InStr(Range("O" & j).Value, Range("P" & j).Value) > 0 Then 
も、
A上手く言ったというコード
Range("Q2").Resize(MaxRow - 1).Formula = "=IF(COUNTIF(O2,""*""&P2&""*"")>0,""OK"","""")" 
も、いずれも「O列の文字列の中に、P列の文字列があるか」を見ています。
通常の文字列を対象にしている限り、@もAも同じ結果が得られるはずです。
 
 
>コードがO列とP列が逆になっていたようです。
などということはありません。
余りテキトーなことでお茶を濁さないでいただきたい。
 
エラーになるとすれば、元のセルの値がエラー値になっているのでしょう。
エラー値に対する文字列操作はできませんから。
 
「エラーになったときの文字列を提示してください」と申し上げているんですがねえ。
ご自分で起こした質問なのに、解決しようとする意欲が見られないのはとても残念。
面倒なんですか?
 
また、
     O列    P列
     1000      1
などという数値の場合、Instrは文字列として考えるので含まれると判定されます。
COUNTIFを使った数式では含まれると認識されません。
元々
O列(りんご、パン、オレンジ)  P列(パン)
といった文字列の話をしているんだろうから、それを数値に当てはめる方がおかしい。
 
-------------------------
前のスレッド(このスレッドです)もそうだが、
回答者もそれなりに時間を使います。
余りテキトーな受け答えしないようにしていただきたいですな。
 
>前スレは消えてしまったので対応ができませんでした。
などというのもそう。
7月に投稿したものなんだから、最終書込から6ヶ月先までは残っていますよ。

投稿日時: 17/08/06 00:36:19
投稿者: Dellcasio

simple さんの引用:
http://www.moug.net/faq/viewtopic.php?t=76055
を閉じられてしまったので、こちらのスレッドとは無関係で恐縮ですが、
コメントします。
 
「P列の文字がO列に含まれているかをチェツクしたい 」の件です。
 
プロシージャの名前は別として、
 
@貴方の提示されたコード
If InStr(Range("O" & j).Value, Range("P" & j).Value) > 0 Then 
も、
A上手く言ったというコード
Range("Q2").Resize(MaxRow - 1).Formula = "=IF(COUNTIF(O2,""*""&P2&""*"")>0,""OK"","""")" 
も、いずれも「O列の文字列の中に、P列の文字列があるか」を見ています。
通常の文字列を対象にしている限り、@もAも同じ結果が得られるはずです。
 
 
>コードがO列とP列が逆になっていたようです。
などということはありません。
余りテキトーなことでお茶を濁さないでいただきたい。
 
エラーになるとすれば、元のセルの値がエラー値になっているのでしょう。
エラー値に対する文字列操作はできませんから。
 
「エラーになったときの文字列を提示してください」と申し上げているんですがねえ。
ご自分で起こした質問なのに、解決しようとする意欲が見られないのはとても残念。
面倒なんですか?
 
また、
     O列    P列
     1000      1
などという数値の場合、Instrは文字列として考えるので含まれると判定されます。
COUNTIFを使った数式では含まれると認識されません。
元々
O列(りんご、パン、オレンジ)  P列(パン)
といった文字列の話をしているんだろうから、それを数値に当てはめる方がおかしい。
 
-------------------------
前のスレッド(このスレッドです)もそうだが、
回答者もそれなりに時間を使います。
余りテキトーな受け答えしないようにしていただきたいですな。
 
>前スレは消えてしまったので対応ができませんでした。
などというのもそう。
7月に投稿したものなんだから、最終書込から6ヶ月先までは残っていますよ。

 
 
 
simple さん
前スレの回答には嘘はございません。
本当に感謝しております。
 
 
 
>>質問タイトル:  P列の文字がO列に含まれているかをチェツクしたい
>>プロシージャー名: Sub O列の文字がP列に含まれているかをチェツク()
 
>>どちらなんでしょうか?
 
前スレで上記のご指摘がありましたので、
P列とO列が逆になっているかを確かめました。
そして、コードのPとOを逆にしてコードを書いて、
テストをしましたが、結果はNGでした。
 
けれども、エクセルシートのP列(りんご、パン、オレンジ) 
とO列(パン)に書かれていいる文字を
P列に(パン)を、O列に(りんご、パン、オレンジ) 
を入れ替えてテストをした所、うまく出来ました。
 
以上のような感じで本当に問題が解決して
感謝しています。
 
 
明日からは、同じ日付かを確認する方法について
トライして参ります。
ご回答を頂いておりますので、それを検証して
なるべく自力で頑張るつもりです。
以上よろしくお願い致します。
 
 
 
 
 
 

投稿日時: 17/08/06 20:40:47
投稿者: Dellcasio

Dellcasio さんの引用:
simple さんの引用:
http://www.moug.net/faq/viewtopic.php?t=76055
を閉じられてしまったので、こちらのスレッドとは無関係で恐縮ですが、
コメントします。
 
「P列の文字がO列に含まれているかをチェツクしたい 」の件です。
 
プロシージャの名前は別として、
 
@貴方の提示されたコード
If InStr(Range("O" & j).Value, Range("P" & j).Value) > 0 Then 
も、
A上手く言ったというコード
Range("Q2").Resize(MaxRow - 1).Formula = "=IF(COUNTIF(O2,""*""&P2&""*"")>0,""OK"","""")" 
も、いずれも「O列の文字列の中に、P列の文字列があるか」を見ています。
通常の文字列を対象にしている限り、@もAも同じ結果が得られるはずです。
 
 
>コードがO列とP列が逆になっていたようです。
などということはありません。
余りテキトーなことでお茶を濁さないでいただきたい。
 
エラーになるとすれば、元のセルの値がエラー値になっているのでしょう。
エラー値に対する文字列操作はできませんから。
 
「エラーになったときの文字列を提示してください」と申し上げているんですがねえ。
ご自分で起こした質問なのに、解決しようとする意欲が見られないのはとても残念。
面倒なんですか?
 
また、
     O列    P列
     1000      1
などという数値の場合、Instrは文字列として考えるので含まれると判定されます。
COUNTIFを使った数式では含まれると認識されません。
元々
O列(りんご、パン、オレンジ)  P列(パン)
といった文字列の話をしているんだろうから、それを数値に当てはめる方がおかしい。
 
-------------------------
前のスレッド(このスレッドです)もそうだが、
回答者もそれなりに時間を使います。
余りテキトーな受け答えしないようにしていただきたいですな。
 
>前スレは消えてしまったので対応ができませんでした。
などというのもそう。
7月に投稿したものなんだから、最終書込から6ヶ月先までは残っていますよ。

 
 
 
simple さん
前スレの回答には嘘はございません。
本当に感謝しております。
 
 
 
>>質問タイトル:  P列の文字がO列に含まれているかをチェツクしたい
>>プロシージャー名: Sub O列の文字がP列に含まれているかをチェツク()
 
>>どちらなんでしょうか?
 
前スレで上記のご指摘がありましたので、
P列とO列が逆になっているかを確かめました。
そして、コードのPとOを逆にしてコードを書いて、
テストをしましたが、結果はNGでした。
 
けれども、エクセルシートのP列(りんご、パン、オレンジ) 
とO列(パン)に書かれていいる文字を
P列に(パン)を、O列に(りんご、パン、オレンジ) 
を入れ替えてテストをした所、うまく出来ました。
 
以上のような感じで本当に問題が解決して
感謝しています。
 
 
明日からは、同じ日付かを確認する方法について
トライして参ります。
ご回答を頂いておりますので、それを検証して
なるべく自力で頑張るつもりです。
以上よろしくお願い致します。
 
 
 
 
 
 

 
 
 
半平太さん、mattuwan44さん、simpleさん、
この度は、仕事が沢山あり、返信が遅れてしまいまして
申し訳ございませんでした。
皆様のお陰で問題が解決致しました。
本当にありがとうございました。