表計算ソフトで時間計算、日数計算をするための7つのレッスン 第5回
■■Lesson 5
「さらなる応用 more than one way.」
[ここで学ぶ関数 EDATE() EOMONTH() TIMEVALUE() DATEVALUE() MAX() ]
■ 年・月・日・時・分・秒を単位とする加減算
◆加減算の基本
特定の日付(セルB13 に入っている値とする)の100日後の日付を求めるなら、Lesson 4 までに習った関数を用いて、
=DATE(YEAR(B13),MONTH(B13),DAY(B13)+100)
のような方法が使える。
これはもちろん、年、月、時、分、秒 についても応用可能。
が、日付は一日を「1」とするシリアル値なので、「日」にかぎってはたんに、
=B13+100
とすればよい。
(さきほどの例とは異なり、この場合、時刻の情報が含まれていれば保存される)
また、
時、分、秒の加減算の場合なは、
Lesson 4 で学んだ変換方法を応用して、
たとえば「7時間後」であれば、
=B13+7/24
といった書き方もできるが、
=B13+"7:00”
のように日付文字列を直接、算術記号で結んでもよい。分・秒も含んだ加減算の場合はこちらのほうが単純に記述できる。
そして、たとえば B5 に「2019/12/5」のような日付情報が、B6 に「9:35」のような時間情報が入っている場合、「2019/12/5 9:35」のような日付時間情報を得るには、単純に
=B5+B6
のようにすればよい。
◆ 月・年の加減算
月の場合、たとえば、「B13に入っている日付の7ヶ月後の日付を求める」なら
=DATE(YEAR(B13),MONTH(B13)+7,DAY(B13))
でもよいが、「〜カ月後の日付」を求める EDATE() 関数を使うこともできる。
たとえば、上記の例であれば、多くの場合、以下のやり方でも同じ結果を返す。
(時刻に関するデータは切り捨て)
=EDATE(B13,7)
年の場合、たとえば「5年後の日付を求める」なら、
=DATE(YEAR(B13)+5,MONTH(B13),DAY(B13))
=EDATE(B13,12*5)
といった方法が考えられる。
ただし、月末付近の日付を扱う場合、EDATE() の結果は、DATE() の第2引数を加減算した場合の結果と異なる場合がある。
たとえば、
=EDATE("2014/8/31",1) --- 2014/9/30
=DATE(2014,8+1,31) --- 2014/10/1
「月末の日付であれば返り値も月末に」したいといった場合は EDATE() を使うほうがよい。
応用:
D9 に生年月日を入れると、これから訪れる直近の誕生日を返す関数を作成するとする。
「今日」が今年の誕生日以前か以後かで場合分けして、以下のような方法が使える。
=IF(TODAY()<DATE(YEAR(TODAY()),MONTH(D9),DAY(D9)),DATE(YEAR(TODAY()),MONTH(D9),DAY(D9)),DATE(YEAR(TODAY())+1,MONTH(D9),DAY(D9)))
これは、Lesson 4 で紹介したDATEDIF() を使って以下のように書くことも可能。
(「今日時点での年齢」+1 を誕生年に足すことで
「西暦何年の誕生日か」を求めている)
=DATE(YEAR(D9)+DATEDIF(D9,TODAY(),"Y")+1,MONTH(D9),DAY(D9))
さらに、EDATE() を使うと以下のようになる。
=EDATE(D9,(DATEDIF(D9,TODAY(),"Y")+1)*12)
■ 「月末」の扱い:閏年などの判定
特定の日付(セルB2に入力されたシリアル値とする)の月末の日付を返すなら、
=DATE(YEAR(B2),MONTH(B2)+1,0)
といった表現が可能。(「次の月」の第0日 = その月の月末 )
これは、以下のように EOMONTH() 関数を使っても同じ結果を返す。
=EOMONTH(B2,0)
さらに、該当する月に含まれる日数(その月が大の月か小の月か。2月なら28日か29日か)を求めるなら、
=DAY(DATE(YEAR(B2),MONTH(B2)+1,0))
または、
=DAY(EOMONTH(B2,0))
となる。
EOMONTH() 関数の第2引数には第1引数の「何ヶ月後か」を入力する。
たとえば、「翌々月の10日」なら、
=EOMONTH(B2,1)+10
これはもちろん、以下の関数と同じ結果を返す。
=DATE(YEAR(B2),MONTH(B2)+2,10)
応用:
今年が閏年かどうかを返す関数
=IF(DAY(EOMONTH(DATE(YEAR(TODAY()),2,1),0))=29,"今年は閏年","今年は閏年ではない")
「セルC5に入力した任意の年(西暦)が閏年かどうかを返す」ならもちろん、
=IF(DAY(EOMONTH(DATE(C5,2,1),0))=29,"閏年","閏年ではない")
…だが、ここでは 2月の末日 = 3月0日 であることを利用して、それぞれ以下のようにするほうが簡単に記述できる。
=IF(DAY(DATE(YEAR(TODAY()),3,0))=29,"今年は閏年","今年は閏年でない")
=IF(DAY(DATE(C5,3,0))=29,"閏年","閏年ではない")
また、「セルE1に入力した日付からその1年後の日付までの日数(365日か366日か)」を返す関数は
=EDATE(E1,12)-E1
これは、端数(時間)が含まれないならば
=DATE(YEAR(E1)+1,MONTH(E1),DAY(E1))-E1
でも、同じ。
■発展:条件付きの合計 [ SUMIFS() SUMPRODUCT() ]
B列(B5〜B35)に日付(シリアル値)が入力されており、C列(C5〜C35)にその日付に対応する売上高が入力されているシートで、特定の日付(A3にシリアル値で入力)に対応する月(暦日)の売上の合計を求める数式を作りなさい。
答え:
=SUMIFS(C5:C35,B5:B35,">="&EOMONTH(A3,-1)+1,B5:B35,"<"&EOMONTH(A3,0)+1)
または、
=SUMPRODUCT((B5:B35>=EOMONTH(A3,-1)+1)*(B5:B35<EOMONTH(A3,0)+1),C5:C35)
SUMPRODUCT() を使った場合はさらに、
=SUMPRODUCT((YEAR(B5:B35)=YEAR(A3))*(MONTH(B5:B35)=MONTH(A3)),C5:C35)
のような表現も可能。
補足A:
このような場合、いわゆる作業列を使う方法もある。
この場合、たとえばD5に、
=YEAR(B5)
と入力してこれをD35までフィルし、E5に、
=MONTH(B5)
と入力してE35までフィルしたうえで、
=SUMIFS(C5:C35,D5:D35,YEAR(A3),E5:E35,MONTH(A3))
または、
=SUMPRODUCT((D5:D35=YEAR(A3))*(E5:E35=MONTH(A3)),C5:C35)
とすると同様の結果が得られる。
あるいは、
D5に、
=IF(AND(YEAR(B5)=YEAR($A$3),MONTH(B5)=MONTH($A$3)),C5,0)
と入力してD35までフィルすれば、
単純に、
=SUM(D5:D35)
で同様の計算ができる。
補足B:
毎月15日を締め日とし、シリアル値A3 が含まれる月度(16日〜翌月15日)の売上の合計を作る……なら
A4:=IF(DAY(A3)<16,DATE(YEAR(A3),MONTH(A3)-1,15),DATE(YEAR(A3),MONTH(A3),15))
A5:=IF(DAY(A3)<16,DATE(YEAR(A3),MONTH(A3),16),DATE(YEAR(A3),MONTH(A3)+1,16))
として、
=SUMIFS(C5:C35,B5:B35,">"&A4,B5:B35,"<"&A5)
または、
=SUMPRODUCT((B5:B35>A4)*(B5:B35<A5),C5:C35)
とすればよい。
■ TIMEVALUE() DATEVALUE()
時刻表記や日付表記を明示的に数値(シリアル値)として扱う場合、TIMEVALUE()、DATEVALUE()関数を使う。
=TIMEVALUE("12:34")
=DATEVALUE("2014/7/15")
eg) 8:30 以前の出勤は「8:30」出社だとみなす
(それ以後の出勤なら出勤時刻をそのまま返す)、なら
=IF(D3<TIMEVALUE("8:30"),TIME(8,30,0),D3)
ちなみにこれは、与えられた引数のうちの最大値を返す MAX() 関数を用いて、
=MAX(D3,TIMEVALUE("8:30"))
でも同じ。
eg) 退社時刻(C4に入っているとする)を30分単位でまるめ(切り捨て)る、ただし、その「単位時間まであと5分以内」である場合は逆に切り上げる、なら、
=IF(CEILING(C4,"0:30")-C4>TIMEVALUE("0:05"),
FLOOR(C4,"0:30"),CEILING(C4,"0:30"))
この記事が気に入ったらサポートをしてみませんか?