回答箱 No.147-3: 町内会夜警カレンダーを作りたい
        ◆ 質問箱 No.147 質問者: 西村 重幸  2004年05月 268号 P.14
            ◆ 質問箱 目次へ
No.147-3   町内会夜警カレンダーを作りたい 回答者
  高橋 周助
2004年08月
271号 P.18
 質問箱No.147を題材に、ひとりブレーンストーミングをした成果の、第3弾をお届けします。コマンド等の使い方について、同じ題材でも、これだけ多彩な考え方が出来る、という例示に挑戦してみたかったためです。

□■□ 第三回答例の特徴
  1.  カレンダーを作る対象年の入力に、Select文を使いました。あらかじめオートに書き込んである年の中からしか選択できないので、正当性検査が一つ不要になりました。
  2.  班番号の決定ルールを考えてみると、スタート日から数えて7日間が1班から始まり、次の7日間は2班から始まり、・・・、最後の7日間は7班から始まるので、全体で7×7=49日で一巡します。その後はまた元に戻るので、この49通りの順序をあらかじめ1回だけ表に作っておいて、この表から各日付に該当する班番号を読み取るようにしました。
     これの良い点は、班番号を算出する計算式が分からない場合とか、全くランダムな順序の場合でも応用が利いて、手入力でこの表を作っておきさえすれば良い、ということです。
     この表は、手作業で作って構わないのですが、プログラムを動かす都合上、一桁でも/一文字でも狂うと、エラーになる恐れがあるので、オートの中に組み込みました。原理が解れば、どのように変更してもかまいません。
  3.  今回は、質問箱 No.148への回答(来月投稿予定)への布石にもなっています。ひとつは、派遣要員順序の指定方法に、上記(2)の方法を使う予定です。もう一つは、七曜表に派遣要員名を書き込めるように、各週とも1行余計に空行を設けました。また列幅も、8桁の名前が書き込めるように、広く取りました。結果として、全体の七曜表が縦横とも、一回り大きくなりました。
  4. 七曜表への記入時に、書き込み先の行番号・列番号を、計算によって算出しました。

□■□ 使い方
  1.  実行すると、Select文の窓が開くので、カレンダーを作りたい年を選択してください。
  2.  最終結果は、「WK4」バインダーの1〜12ページに登録されます。
  3.  4個のバインダー「WK1」・「WK2」・「WK3」・「WK4」を使います。同名のバインダーが存在していても、いなくてもかまいませんが、上書きしてしまうので、大切なデータであれば、退避してから実行してください。

<夜警班番号_3>
        STEP OFF;  CLOSE;                   /*前歴の影響を消しておく*/
/****** A.条件設定 **************************************************/
    /*====== A-1. カレンダーを作りたい年============================*/
        SELECT [10,10],"対象年",X5,"2004","2005","2006","2007","2008";
          LET Z15=DCML(X5)+2003;                    /*対象年(西暦)*/
          LET Z16=Z15*10000+101;                        /*元日の日付*/
    /*====== A-2.スタートの条件 ====================================*/
        LET Z11=2004;                               /*夜警スタート年*/
        LET Z12=5;                                  /*夜警スタート月*/
        LET Z13=30;                                 /*夜警スタート日*/
    /*====== A-3.条件の正当性検査 ==================================*/
$検査:  LET Z14=DATE(Z11*10000+Z12*100+Z13,1,0);  /*スタート日の日付*/
          IF ERR(0)=0 THEN GOTO $B;
        DISP OPEN,[10,10],"スタート日は存在しません。";
        INPUT [10,12],"了解したらリターンキーを押して下さい。",V1;
        GOTO $終;                                           /*出口へ*/
/****** B.七曜表の空表を作成 ****************************************/
$B:     SET;S;M;1;256;;Y;                        /*横桁数256桁に設定*/
        O;夜警七曜表(空);4*14;;日;;月;;火;;水;;木;;金;;土;ESC;
        CF;2/4/6/8/10/12/14;8;
        CS;M;C1=C1;;A;WK1/D;               /*バインダー「WK1」を作成*/
        IR;S;H;18;                                  /*空行を18行挿入*/
        DRL/C;R;7/10/13/16/19;                        /*横罫線を引く*/
              C;1/3/5/7/9/11/13;  C;N;  ESC;          /*縦罫線を引く*/
        ATR;P;L;A;                            /*全列に左詰属性を設定*/
        P;WK1/1;ESC;                           /*「WK1」の1頁に保存*/
/******* C.班番号順序表作成 *****************************************/
        SET;S;M;1;36;;Y;                          /*横桁数36桁に設定*/
        O;班番号順序;4;順序;6;班番号;ESC;
        IR;S;H;7;                                  /*7行の空行を挿入*/
        NUM;M;C;@班番号 ;H;1;1;ESC;      /*1班から始まる班順列を記入*/
        CPA;M;Y;                            /*サブバッファにもコピー*/
        FOR X5=2 TO 7;                /*2〜7班から始まる班順列を記入*/
          ROLL;@班番号 ;A;+1;                    /*上方向に1行ロール*/
          S;  CPR;SA;T+1;  S;                 /*サブバッファにコピー*/
        NEXT;  S;
        NUM;M;C;@順序 ;H;0;1;                 /*順序列列に順序を記入*/
        CS;M;C1=C1;;A;WK2/D; /*WK2バインダーの有無に関係なく保存可能*/
/******* D.班番号決定 ***********************************************/
    /*====== D-1.年間データ書き込み用空表を作成 ====================*/
        SET;S;M;1;38;;Y;                          /*横桁数38桁に設定*/
        O;夜警班番号;6;No.;15;年月日;2;曜;6;班番号;5;年;3;月;;ESC;
        ATR;N;D;@年月日 ;                 /*年月日列に日付属性を設定*/
        IR;S;H;370;                              /*370行の空行を挿入*/
    /*====== D-2.各列を完成 ========================================*/
        NUM;M;C;@年月日 ;H;%Z16;1;        /*年月日列に日付連番を記入*/
        CAL;@年月日 MOD 7=@曜 ;               /*曜列に曜日連番を記入*/
        LET Z1=DATE(Z14,Z16);     /*スタート日から元日までの経過日数*/
        NUM;M;C;@No. ;H;%Z1;1;                   /*No.列に番号を記入*/
        CAL/C;DF0;@No. MOD 49=@No. ;         /*No.列に順序番号を算出*/
          ROUND(DATE(@年月日 )/10000,-1,0)=@年 ;    /*年列に年を記入*/
          ROUND((DATE(@年月日 ) MOD 10000)/100,-1,0)=@月 ;ESC;
                                                    /*月列に月を記入*/
        CAM;M;WK2;@No. ;;@順序 ;
          @No. ;@年月日 ;@曜 ;S@班番号 ;@年 ;@月 ;;WK3/D;
                        /*「WK2」から班番号を読み取って「WK3」に保存*/
/******* E.月別処理 *************************************************/
    /*===== E-1.最終結果保存用バインダー12頁分を確保 ===============*/
        IF NAME(3,"WK4")=0 THEN GOTO $頁確保;  BIND;D;WK4;Y;
$頁確保:CLM;ダミー;Y;  MB;WK4;;  MP;WK4;11;;
    /*===== E-2.月毎の処理12ヵ月分を繰り返す =======================*/
        FOR X1=1 TO 12;
          IF Z15=Z11 AND DCML(X1)<Z12 THEN CONTINUE;
                                          /*スタート月以前はスキップ*/
       /*--- E-2-a.当月の条件を計算 --------------------------------*/
          LET Z22=Z15*10000+DCML(X1)*100+1;       /*当該月1日の日付*/
          LET Z23=DATENUM(Z22);               /*当該月1日の日付連番*/
          LET Z24=Z23 MOD 7;                      /*当該月1日の曜日*/
       /*--- E-2-b.当該月のデータのみ抽出して加工 ------------------*/
          CS;WK3;@年 =%Z15;@月 =%X1;;A;;    /*当該月のデータのみ抽出*/
          INFO;S;256;                            /*横桁数256桁に変更*/
          IC;S;N;3;日;                                  /*日列を追加*/
          NUM;M;C;@日 ;H;1;1;                 /*日列に暦の日付を記入*/
          IF Z24=0 THEN GOTO $第何週;  /*当該月1日が日曜ならスキップ*/
          IR;S;H;%Z24;/*始めの行が日曜日に相当するようにダミー行挿入*/
$第何週:  NUM;M;C;@No. ;H;0;1;                   /*No.列に連番を記入*/
          CAL;DF0;@No. /7+1=@No. ;                  /*第何週かを記入*/
          IF Z24=0 THEN GOTO $E-2-c;/*行挿入していなかったらスキップ*/
          DR;H,H+%Z24-1;Y;                  /*挿入したダミー行を削除*/
       /*--- E-2-c.七曜表へ書き込み --------------------------------*/
$E-2-c:   S;                          /*当該月データをサブバッファへ*/
          G;WK1/1;                          /*七曜表の空表を読み込む*/
          CT;%Z15年%X1月_夜警カレンダー;            /*タイトルを変更*/
          FOR X2={H} TO {T};
            LET X5=IVAL({X2,@No. })*4;      /*日付の書き込み先行番号*/
            LET X6=IVAL({X2,@曜 })*3+2;     /*日付の書き込み先列番号*/
            LET [X5,X6]={X2,@日 };                      /*日付を記入*/
            IF DATE(DATEVAL({X2,@年月日 }))<Z14 THEN CONTINUE;
                                          /*スタート日以前はスキップ*/
            LET X5=X5+1;                  /*班番号の書き込み先行番号*/
            LET X6=X6+1;                  /*班番号の書き込み先列番号*/
            LET [X5,X6]={X2,@班番号 }+"班";             /*班番号記入*/
          NEXT;
       /*--- E-2-d.当該ページへ登録 --------------------------------*/
          P;WK4/%X1;ESC;                 /*「WK4」の当該ページに登録*/
        NEXT;
/******* Z.終 *******************************************************/
$終:    STEP OFF;  CLOSE;  STOP;          /*前歴の影響を消して、終了*/

回答箱のプログラムがプログラム集に収録されています。


このページのTOPへ戻る