ロゴ(青) Excel/VBA Tips ロゴ(緑)

Tips02: あぁ〜 [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 』です。
   (A) (B)
(1) 日付 曜日
(2) 2002/11/28 =A2
もしくは、B2セルの式を「 =TEXT(A2, "aaa") 」として、表示形式(書式)を『標準』です。

結果的には問題ないんだから「それがどうした、構わないだろ!」
と言われれば、それまでですが‥‥‥
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 解説図を追加 )
           

           



 Home   Back Page   Next Page

ロゴ(ゴールド)   ロゴ(ゴールド)

角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved.