今日は、オリジナル関数を作成します。
というのも、変則的な計算をする必要が出てきたからです。
下の表を見てください。

開始日から終了日までの日数を計算したいのです。
ただし、
1.開始日も含める。
2.ひと月を30日として計算する。
という制約があるのです。
普通に求めるには、DATEDIF関数を使います。
=DATEDIF(B3,C3,"D")
と入力すれば、答えが出てきます。
これが正しい答えなのですが、今回の制約を満たしてはいません。
そこで、ExcelVBAを使って、ユーザー定義関数を作ります。
その名も!DateDiffSpecial関数です!(・・・|)
結果として、下のようになります。

ポイントは、「ひと月を30日として計算する」です。
たとえば12月は31日あります。また、2月は28日であったり29日であったりします。(閏年ですよ)
考え方は、いろいろあるでしょうが、今回は、以下のように攻めます。

つまり、開始日と終了日が同じ月なのか、1月だけ違うのか、それとももっと離れているのか、
この3つに分けて考えれば答えが出そうです。
その際、ひと月が30日になるように工夫をします。
さっそく、コーディングに入りましょう。
エクセルを起動したら、Altキーを押しながらF11キーを押して、VisualBasicEditorを表示します。
「挿入」→「標準モジュール」とクリックします。
表示されたモジュールにコードを記述しましょう。
オリジナル関数は、Public Function [関数名](引数1,引数2,・・・)As データ型
と書き始めます。
最後のデータ型は、この関数の戻り値(答え)のデータ型を指定するものです。
コードの中に 「 関数名 = 値 」を書くことによって、関数の答えとなります。
以下のように書いてみましょう。
Public Function DateDiffSpecial(ByVal startDay As Date, _
ByVal endDay As Date) As Integer
' 2つの日付の差を取得する。ただし、1か月を30日として計算
If startDay > endDay Then
'引数設定ミスは、0を返す
DateDiffSpecial = 0
Exit Function
End If
'終了日が末日かどうかをフラグに代入
Dim IsMatsujitsu As Boolean
If Day(endDay) = Day(DateSerial(Year(endDay), Month(endDay) + 1, 1) - 1) Then
IsMatsujitsu = True
Else
IsMatsujitsu = False
End If
Dim Ans As Integer
Ans = 0
Dim a As Integer
'開始日と終了日の月数の差を取得
a = DateDiff("M", startDay, endDay)
Select Case a
Case 0
If IsMatsujitsu Then
Ans = 30 - Day(startDay) + 1
Else
Ans = Day(endDay) - Day(startDay) + 1
End If
Case 1
Ans = 30 - Day(startDay) + 1
If IsMatsujitsu Then
Ans = Ans + 30
Else
Ans = Ans + Day(endDay)
End If
Case Is >= 2
Ans = 30 - Day(startDay) + 1
Ans = Ans + (a - 1) * 30
If IsMatsujitsu Then
Ans = Ans + 30
Else
Ans = Ans + Day(endDay)
End If
End Select
DateDiffSpecial = Ans
End Function
画像も載せておきます。

条件分岐の方法として Select Case 構文と使う方法と、IF構文を使う方法がありますが、
今回は、その両方を使っています。
つまり、Select Case 構文で、大きく3つの条件分岐を設定し、
その中で、さらに30日になるようにIF構文で条件分岐をしています。
ゆっくりと読んでいくと、ロジックを理解できるでしょう。
なお、If IsMatsujitsu Then というのは、
If IsMatsujitsu = True Then
と同様の意味となります。= True は、省略可能なのです。
また、DateDiff関数は、エクセルのワークシート関数ではなく、VBAが持っている関数です。
引数の順番が異なりますので注意が必要です。
もうひとつ、末日の日を抜き出したい場合は、
Day関数の引数に、翌月1日-1 という値を指定すればいいのです。
翌月1日の前日は、その月の末日になるからです。
この関数を用いるには、答えを出したいセルに「=DateDiffSpecial(B3,C3)」と入力するだけです。

10月30日と11月1日の2日間ということで、答えは2となります。
セルの値を下のように変更してみます。

9月30日と10月1日の2日間ということで、やはり、答えは2となりますね。
えっ?なぜこんなややこしいことをしているのかって?
確かに無意味に見えるかもしれませんが、実は、あるソフトを制作するためにどうしても必要な機能なのです。
次回は、その一部をご紹介できるかもしれません。
それでは、また。
だい
というのも、変則的な計算をする必要が出てきたからです。
下の表を見てください。

開始日から終了日までの日数を計算したいのです。
ただし、
1.開始日も含める。
2.ひと月を30日として計算する。
という制約があるのです。
普通に求めるには、DATEDIF関数を使います。
=DATEDIF(B3,C3,"D")
と入力すれば、答えが出てきます。
これが正しい答えなのですが、今回の制約を満たしてはいません。
そこで、ExcelVBAを使って、ユーザー定義関数を作ります。
その名も!DateDiffSpecial関数です!(・・・|)
結果として、下のようになります。

ポイントは、「ひと月を30日として計算する」です。
たとえば12月は31日あります。また、2月は28日であったり29日であったりします。(閏年ですよ)
考え方は、いろいろあるでしょうが、今回は、以下のように攻めます。

つまり、開始日と終了日が同じ月なのか、1月だけ違うのか、それとももっと離れているのか、
この3つに分けて考えれば答えが出そうです。
その際、ひと月が30日になるように工夫をします。
さっそく、コーディングに入りましょう。
エクセルを起動したら、Altキーを押しながらF11キーを押して、VisualBasicEditorを表示します。
「挿入」→「標準モジュール」とクリックします。
表示されたモジュールにコードを記述しましょう。
オリジナル関数は、Public Function [関数名](引数1,引数2,・・・)As データ型
と書き始めます。
最後のデータ型は、この関数の戻り値(答え)のデータ型を指定するものです。
コードの中に 「 関数名 = 値 」を書くことによって、関数の答えとなります。
以下のように書いてみましょう。
Public Function DateDiffSpecial(ByVal startDay As Date, _
ByVal endDay As Date) As Integer
' 2つの日付の差を取得する。ただし、1か月を30日として計算
If startDay > endDay Then
'引数設定ミスは、0を返す
DateDiffSpecial = 0
Exit Function
End If
'終了日が末日かどうかをフラグに代入
Dim IsMatsujitsu As Boolean
If Day(endDay) = Day(DateSerial(Year(endDay), Month(endDay) + 1, 1) - 1) Then
IsMatsujitsu = True
Else
IsMatsujitsu = False
End If
Dim Ans As Integer
Ans = 0
Dim a As Integer
'開始日と終了日の月数の差を取得
a = DateDiff("M", startDay, endDay)
Select Case a
Case 0
If IsMatsujitsu Then
Ans = 30 - Day(startDay) + 1
Else
Ans = Day(endDay) - Day(startDay) + 1
End If
Case 1
Ans = 30 - Day(startDay) + 1
If IsMatsujitsu Then
Ans = Ans + 30
Else
Ans = Ans + Day(endDay)
End If
Case Is >= 2
Ans = 30 - Day(startDay) + 1
Ans = Ans + (a - 1) * 30
If IsMatsujitsu Then
Ans = Ans + 30
Else
Ans = Ans + Day(endDay)
End If
End Select
DateDiffSpecial = Ans
End Function
画像も載せておきます。

条件分岐の方法として Select Case 構文と使う方法と、IF構文を使う方法がありますが、
今回は、その両方を使っています。
つまり、Select Case 構文で、大きく3つの条件分岐を設定し、
その中で、さらに30日になるようにIF構文で条件分岐をしています。
ゆっくりと読んでいくと、ロジックを理解できるでしょう。
なお、If IsMatsujitsu Then というのは、
If IsMatsujitsu = True Then
と同様の意味となります。= True は、省略可能なのです。
また、DateDiff関数は、エクセルのワークシート関数ではなく、VBAが持っている関数です。
引数の順番が異なりますので注意が必要です。
もうひとつ、末日の日を抜き出したい場合は、
Day関数の引数に、翌月1日-1 という値を指定すればいいのです。
翌月1日の前日は、その月の末日になるからです。
この関数を用いるには、答えを出したいセルに「=DateDiffSpecial(B3,C3)」と入力するだけです。

10月30日と11月1日の2日間ということで、答えは2となります。
セルの値を下のように変更してみます。

9月30日と10月1日の2日間ということで、やはり、答えは2となりますね。
えっ?なぜこんなややこしいことをしているのかって?
確かに無意味に見えるかもしれませんが、実は、あるソフトを制作するためにどうしても必要な機能なのです。
次回は、その一部をご紹介できるかもしれません。
それでは、また。
だい
いつもお世話になっております。
記事を参考にさせていただきました。
応援ポチッ
今後もよろしくお願いします。
応援ありがとうございます。