【 Excel のセル上では、表計算ソフト:Lotus1-2-3 との互換性を維持する為に、赤字の範囲の日付表示が1日ズレています 】
シリアル値(0)⇒ 1899/12/30(土) … セル上での表示[ 1900/ 1/ 0(土) ] ※ 空セル("")は日付として扱う場合はゼロ扱いです
シリアル値(1)⇒ 1899/12/31(日) … セル上での表示[ 1900/ 1/ 1(日) ]
シリアル値(2)⇒ 1900/ 1/ 1(月) … セル上での表示[ 1900/ 1/ 2(月) ]
:
シリアル値(59)⇒ 1900/ 2/27(火) … セル上での表示[ 1900/ 2/28(火) ]
シリアル値(60)⇒ 1900/ 2/28(水) … セル上での表示[ 1900/ 2/29(水) ] ※ 1900年は平年です
シリアル値(61)⇒ 1900/ 3/ 1(木) … セル上での表示[ 1900/ 3/ 1(木) ]
表示形式: "yyyy/m/d(aaa)"
ここに載せたのは、私がモーグで回答した内容です。
http://www2.moug.net/cgi-bin/mdboard.cgi?exopr+ML2002110806
------------------------------------------------------------------------------
実は、昔は私も同じ勘違いをしていましたが‥‥‥
しかもQ&Aの回答で間違った解釈の方を教えていた時期もあったりして‥‥‥<(_ _)>
よく見かける、曜日名の表示の方法で
(A) (B) (1) 日付 曜日 (2) 2002/11/28 =WEEKDAY(A2) ⇒ 木曜
として、B列の表示形式(書式)を『 aaa または aaaa 』というのがあります。
[ =TEXT(WEEKDAY(A2), "aaa") ] という式も、これと同様の考え方で使われています。
しかし、書式文字[aaa] は1〜7に対応して"日"〜"土"を表示するものではありません。
書式文字[aaa]を
[ =CHOOSE(曜日値, "日", "月", ‥‥‥, "土") ]
という仕組みだろうという感覚で使っているのだと思いますが、本当はシリアル値に対する曜日を
編集表示するものであり、
[ =CHOOSE(WEEKDAY(日付), "日", "月",‥‥‥, "土") ]
という意味です。
「ん?何が違うんだ、同じじゃないか!」と思う方、ごもっとも。
確かに[WEEKDAY(日付)=曜日値]ですから同じように見えますが、『引数』に何を持って来るかが
違うんです。上の方は、1〜7という曜日の数値そのものを渡します。下の方では、日付(シリアル値)
を渡しています。
↑の例では、WEEKDAY関数の結果である1〜7という数値を『シリアル値が1〜7』にあたる日付
(1899/12/31〜1900/1/6)と解釈して、[1899/12/31〜1900/1/6]の曜日を編集表示
[ =CHOOSE(WEEKDAY(WEEKDAY(A2)), "日", "月", ‥‥‥, "土") ]
という意味合いになります。
こう見れば、WEEKDAYが二重になっていて「確かに変だ!」と納得できるでしょう。
(補足) 『WEEKDAY関数の結果(1〜7)で CHOOSE関数(日〜土)を使う』 という事自体は間違っていません。
したがって、
[ =CHOOSE(曜日値, "日", "月", ‥‥‥, "土") ]
[ =CHOOSE(WEEKDAY(日付), "日", "月",‥‥‥, "土") ]
という式そのものは何ら問題はありません(正しい使い方です)。
「おかしい」 というのは 【WEEKDAY と 書式"aaa" を組み合わせて使う】事です。
この例で、正しく曜日が出て来るのは、偶々「シリアル値'1'の日付が日曜日」なので結果オーライと
なったに過ぎません。この間違った使い方は、元々は Microsoft がヘルプ上で、この間違った使い方
を「例」として紹介していた為に広がってしまったものです。
つまり、正しい方法は、下記でB列の表示形式(書式)を『 aaa または aaaa 』です。
もしくは、B2セルの式を「 =TEXT(A2, "aaa") 」として、表示形式(書式)を『標準』です。
(A) (B) (1) 日付 曜日 (2) 2002/11/28 =A2
結果的には問題ないんだから「それがどうした、構わないだろ!」
と言われれば、それまでですが‥‥‥
B2セルに表示される曜日は『2002/11/28 の曜日』ではなく、『シリアル値'5'の日付(1900/1/4)の曜日』
である事を理解するべきです。
でも、[ツール/オプション/計算方法/1904年システム]にチェックを入れると、シリアル値[1]に対応する
日付は[1904/1/2(土)]になりますから、この場合は全く違う結果になります。
なお、セル上で1〜7を日付に変換すると[1900/1/1〜1/7]になりますが、これはエクセル固有の
「MS流仕様」によるものです。[1900/1/1]は日曜日ではなく、月曜日です。
VBAでは正しく[1899/12/31〜1900/1/6]と解釈します。
日付 =WEEKDAY(A1) =TEXT(B1,"yyyy/m/d(aaa)") ↓ ↓ ↓ (A) (B) (C) (D) (E) (1) 2002/11/24 1 日 1900/ 1/ 1(日) 1899/12/31(日) (2) 2002/11/25 2 月 1900/ 1/ 2(月) 1900/ 1/ 1(月) (3) 2002/11/26 3 火 1900/ 1/ 3(火) 1900/ 1/ 2(火) (4) 2002/11/27 4 水 1900/ 1/ 4(水) 1900/ 1/ 3(水) (5) 2002/11/28 5 木 1900/ 1/ 5(木) 1900/ 1/ 4(木) (6) 2002/11/29 6 金 1900/ 1/ 6(金) 1900/ 1/ 5(金) (7) 2002/11/30 7 土 1900/ 1/ 7(土) 1900/ 1/ 6(土) ↑ ↑ =B1で書式[aaa] VBAでFormat(Range("B1"),"yyyy/m/d(aaa)")
書式[aaa]の処理自体は、セル上でも、ズレに影響される事なく、正しい日付に対して求められて
います。その為にセル上では"1900/1/1(日)"という組み合わせ的には変な編集結果になります。
このズレは、セル上の評価では[1900/2/29]という実際には存在しない日付を挟み込んでいる
為に起こるものであり、[1900/3/1, シリアル値=61]以降ではズレは無くなります。
シリアル値 VBAでFormat(Range("A1"),"yyyy/m/d(aaa)") ↓ ↓ 59 1900/ 2/28(火) 1900/ 2/27(火) 60 1900/ 2/29(水) 1900/ 2/28(水) (*)1900年は閏年ではありません 61 1900/ 3/ 1(木) 1900/ 3/ 1(木) 62 1900/ 3/ 2(金) 1900/ 3/ 2(金) 63 1900/ 3/ 3(土) 1900/ 3/ 3(土) ↑ =TEXT(A1,"yyyy/m/d(aaa)")
[ ここへのリンク ]
(参考) Microsoft サポート技術情報
[XL2000] Excel2000は1900年が閏年であるという誤った認識をします。
https://support.microsoft.com/ja-jp/kb/214326
[XL2002] WEEKDAY関数で1900年3月1日より前の正しい曜日が返らない
https://support.microsoft.com/ja-jp/kb/106339
このサポート技術情報の中では、『曜日の方が正しく求められない』と解説してい
ますが、MSの技術陣も混乱しているんですね。上記の対応を見て貰えば判るように、
(1) シリアル値に対する、WEEKDAY関数の結果(1〜7)、および[aaa]書式による
『曜日名』は正しく求まっています。(2) ズレているのは、セル上で「シリアル値」を『日付編集文字』で表示する時に起
こっています。Lotus1-2-3との互換性を保たせる為、日付編集する際、[シリア
ル値:60]を存在しない日付[1900/2/29]に割り当てる必要に迫られ、結果とし
て、シリアル値が1〜59の日付については、セル上での表記が1日分だけ後に
ズレてしまっています。(3) VBAの方は、元々がVisualBasic の仕様が受け継がれており、VBに由来する
言語仕様部分についてはエクセルとは無縁ですから、「Lotus1-2-3との互換」
という縛りに影響される事も無く、正しい処理がされています。
といった解釈の方が正しいと思っています。エクセルシート上で
1900/2/27(月)
1900/2/28(火)
という「日付 : 曜日」の対応表を作って確認しようとすると、
人の目にはどうしても
『日付に対する曜日が違う』 という風にしか映りません
から、無理からぬ事とはいえ、症状の分析が甘いと言わざるを得ませんね(開発元
技術者なんですから)。
[ ここへのリンク ] (
2008/ 7/29 解説図を追加 )
|
||
角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved. |