2

カレンダーを自動生成したい

前回のつづき。

あ、そうそう、このカレンダーはAdobe Illustrator CSで作っております(と、ワザとらしい前振り)。

カレンダー、特に一年見渡すタイプのものは、4月始まりが嬉しい、という時もありますよね。というわけで、ちょっと気が早いですが4月始まりバージョン。

calendar200804-03.pdf

でも、折り返しの6月に、さらに一年先を見越した計画を立てたくなるかもしれません。そんなあなたに、6月始まりバージョン。

calendar200806-05.pdf

ここらで、イラレ(をはじめとしたグラフィックソフト)でカレンダーを作ったことがある人なら、「コイツは何を七面倒くさいことを延々とやっておるのか」とお思いのことでしょう。いちいち、祭日(特に春分の日とか)をチェックして、色をつけて……。ワタクシも、過去に「カレンダーを自作しよう」、と思ったことが何度かあるのですが、元のテキストを用意したり、用意できたとしても祭日に対する細かい装飾を「ミスなく施す」のが激しく面倒だったり、ということで投げ出してしまったことが何度かあります。

そーなんです。実は、このカレンダーはイラレをJavaScriptで制御して、自動生成しているんですね。開始年はもちろん、開始月を指定すれば、それに応じたカレンダーを生成します。12月始まりのカレンダー、とかもカンタンに作れます。

このネタのベースになっているのは、昨年、デジクリで連載されていた

■クリエイター手抜きプロジェクト[105]Illustrator CS/CS2編 一年分のカレンダーを自動生成する(1)/古籏一浩 : 日刊デジタルクリエイターズ

コレです。「クリエイター手抜きプロジェクト」シリーズ。コレを、自分好みにカスタマイズする、ということをちまちまやっていたんですねー。コアのロジックはほぼそのままですが、新規にドキュメントを作ったり、書体や級数、色を要素ごとにこまかく指定できるようにしたり、ドキュメントのどセンターに表示されるように計算したり、年をまたいだ分岐を付け加えたり……と、かなり自分好み設定になっています。

ということで、せっかくなのでソース公開(あちこちツギハギで恥ずかしいことこの上ないんですが)。

イラレ使いの人で、年間カレンダーを作りたい方はご参考になれば。書体をいじるだけでも、しばらく遊べると思いますんで。月ごとのカレンダーをレイヤーに分けて作って行く、とか、日めくりカレンダーを(俺様の素敵な名言集を添えて)自作する、とか、いろいろ応用が効きそうなんで、気が向いたらもう少し引っ張るかもしれません。(でも多分やらない)

[javascript]
// Calendar Script for Adobe Illustrator CS
//
// http://blog.dgcr.com/mt/dgcr/archives/20061023140200.html をかなり参考にしているので、
// ご利用・改変・再配布の際にはご配慮ください。

//初期値いろいろ(長さ系の単位はすべてピクセル)

//ドキュメントサイズを決定
var docX = 1280;
var docY = 854;

// ベースのフォントサイズ;
var fontSize = 10;

//1日あたりの幅
var calDX = 26;
var calDY = 26;

//1月あたりのブロックの幅(「s(日曜)」から「s(日曜)」まで)
var blockX = 200;
var blockY = 250;

//カレンダーの最初の表示位置
var baseX = (docX – ( blockX * 5 ) – (calDX * 6 ))/2 ;
var baseY = 500;

//複数年にまたがるかどうかのフラグ
var yearTimes = 0;

//
docObj = documents.add(DocumentColorSpace.RGB,docX,docY);

function setColor(r,g,b)
{
var tmpColor = new RGBColor();
tmpColor.red = r;
tmpColor.green = g;
tmpColor.blue = b;
return tmpColor;
}

pObj = docObj.pathItems.rectangle(0,0,1280,-854);
pObj.fillColor = setColor(255,255,255);
pObj.stroked = false;

txtColor = new RGBColor();

docObj = activeDocument;

function calendar(theYear__,theMonth__){
var wrtMonth= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
var wrtDate = new Array("S","M","T","W","T","F","S"); //曜日の表示文字列を定義

var yearCol = [153,153,153];
var monthCol = [64,64,64];
var weekCol = [0,84,71];

//■↓一週間分の色(赤輝度,青輝度,緑輝度)
var wrtColor= new Array([128,128,128],[26,26,26],[26,26,26],[26,26,26],[26,26,26],[26,26,26],[128,128,128]);
var special = new Array(3,21, 9,23, 1,1, 2,11, 4,29, 5,3, 5,4, 5,5, 11,3, 11,23, 12,23);
var specCnt = 15;
var specCol = [128,128,128]; // 休日の文字色
var theDate = new Date(); // 日付オブジェクトを生成
var monthNames = new Array("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"); //月の表示文字列を定義
specCnt = 13; // Happy Monday対策
if (theYear__){ // 年月が指定されていた場合は年月を再設定
theDate.setYear(theYear__); // 指定年を設定
theDate.setMonth(theMonth__-1); // 指定月を設定
}
theYear__ = theDate.getFullYear();
theMonth__= theDate.getMonth()+1;
// 閏年だったら2月を29日にする
if (((theYear__ % 4 == 0) && (theYear__ % 100 != 0)) || (theYear__ % 400 == 0)){
wrtMonth[2] = 29;
}
// 春分/秋分の日を求める(1980-2099まで)
special[1] = Math.floor(20.8431 + 0.242194 * (theYear__ – 1980)- Math.floor((theYear__ – 1980)/4));
special[3] = Math.floor(23.2488 + 0.242194 * (theYear__ – 1980)- Math.floor((theYear__ – 1980)/4));
theDate.setFullYear(theYear__); // 指定年を設定
theDate.setMonth(theMonth__-1); // 指定月を設定
theDate.setDate(1); // 日付を1日にし曜日を次の行で取得
var count = theDate.getDay();
var day = 0; // 曜日カウンタを0にする
var date = 1; // 日付を1日にする
var flag = false; // 休日&日曜日フラグ
var hFlag = false; // 休日フラグ
var xFlag = false; // 成人の日/体育の日
var i,j;
var week = 0; // 2000年からの体育の日と成人の日対策
calX = 0; //■カレンダーを表示する相対座標(X)
calY = 60; //■カレンダーを表示する相対座標(Y)
drawColor([0,0,0]); // 色の初期化

//年の描画。複数年にまたがるかどうかで処理を分岐
drawColor(yearCol);

if(yearTimes <1){

if( calMonthStart == 1){
write(theYear__, 1174, -200,146,"HelveticaNeue-Light",5,Justification.RIGHT); //お手持ちの、お好みの書体を指定してください
} else {
write(theYear__ + "–" + (theYear__+1), 1174, -200,146,"HelveticaNeue-Light",5,Justification.RIGHT); //お手持ちの、お好みの書体を指定してください
}

}
yearTimes++;

//月名の描画
drawColor(monthCol);
write(theMonth__, 0, 0,18); // 相対座標(0pt,0pt)に描画
write(monthNames[theMonth__-1], 20, 0,12,"Myriad-Roman",400,Justification.LEFT); // 相対座標(20pt,0pt)に描画

drawColor(weekCol);
for(i=0;i< 7;i++) {write(wrtDate[i], 0+i*calDX, 30, 10); } // 曜日書き出し

//日付の描画
flag = false; //デフォでfalseにしとく(休日が日曜日だった場合、trueに変える)

for(i=1;i<=wrtMonth[theMonth__]+count;i++){hFlag = false; // 休日だったらtrue
if (day >=count){
wrt = ""+date;
for(j=0; j< specCnt; j++){
if ((special[j*2] == theMonth__) && (special[j*2+1] == date)){
drawColor(specCol);
if ((day % 7) == 0) flag = true; // 休日が日曜日だったらtrue
hFlag = true; }
}
date++;
if ((day % 7) == 1) week++; // 月曜日の場合は週の数を増やす
}else{ wrt = " "; }
// 1月と7月と10月の休日処理(Happy Mondayの処理)
xFlag = false;
if ( ((theMonth__ == 1) || (theMonth__ == 10)) && (week== 2) && ((day % 7) == 1)) xFlag = true;
if ( ((theMonth__ == 7) || (theMonth__ == 9)) && (week== 3) && ((day % 7) == 1)) xFlag = true;
if (xFlag){ drawColor(specCol);
}else{
if ((hFlag == false) && flag == false) drawColor(wrtColor[day % 7]);
if (((day % 7) == 1) && flag == true) { drawColor(specCol); flag = false;}
}
//drawBox(calX, calY); //■枠を表示する部分。しない場合は行ごと削除
write(wrt, calX, calY); //fontSize明示せず
calX += calDX;
if (day % 7 == 6) { calX = 0; calY += calDY; }
day++; // 1日増やす
}

}// end of function calendar()

//function write(txt, x,y, fontSize){
function write(){
var textObj = docObj.textFrames.add();

var fontSize = 11;
var fontName = app.textFonts.getByName("Myriad-Roman");
var trackVal= 0;
var justification = Justification.CENTER;

switch (arguments.length) {
default:
case 7: var justification = arguments[6]; // 第7引数まであれば justification に代入
case 6: var trackVal = arguments[5]; // 第6引数まであれば trackVal に代入
case 5: var fontName = app.textFonts.getByName(arguments[4]);; // 第5引数まであれば fontName に代入
case 4: var fontSize = arguments[3]; // 第4引数まであれば fontSize に代入
case 3: y = arguments[2]; // 第3引数まであれば y に代入
case 2: x = arguments[1]; // 第2引数まであれば x に代入
case 1: txt = arguments[0]; // 第1引数まであれば arg1 に代入
case 0:
}

//テキストプロパティの指定
textObj.contents = txt;

for ( j = 0; j < textObj.contents.length; j++){
textObj.characters[j].size = fontSize;
textObj.characters[j].textFont = fontName;
textObj.characters[j].tracking = trackVal;
}

textObj.translate(baseX + x, baseY – y);
for (var i=0; i< textObj.characters.length; i++){
textObj.characters[i].fillColor = txtColor;

//ハイフンの色の処理
for ( j = 0; j < textObj.contents.length; j++){
extraColor = new RGBColor();
extraColor.red = 204;
extraColor.green = 204;
extraColor.blue = 204;
if(textObj.characters[j].contents == "-"){
textObj.characters[j].fillColor = extraColor;
}
}
}
textObj.paragraphs[0].justification = justification;
}

function drawColor(col){
txtColor.red = col[0];
txtColor.green = col[1];
txtColor.blue = col[2];
}
function setColor(r,g,b){
var tmpColor = new RGBColor();
tmpColor.red = r;
tmpColor.green = g; tmpColor.blue = b; return tmpColor;
}

//
calYear = prompt("作成する年を入れてください",2008);
calMonthStart = prompt("開始する月を入れてください",1);

storeX = baseX;
for (cy=0; cy< 2; cy++){ //■縦に2つ
for (cx=0; cx< 6; cx++){ //■横に6つ
calendar(calYear, calMonthStart);
baseX += blockX;
calMonthStart++;
}
baseX = storeX;
baseY -= blockY;
}
[/javascript]

あ、重箱の隅をえぐり倒すような話ですが、「enダーシ」がスクリプトからはどうしても呼び出せなかったので、コードでは「–」で代用しています。ここだけ自動化できなかった。。しくしく。

[2008-01-21追記]
上述のように、このコードは古籏さんが書かれたコードをかっぱいで作成されており、あまり美しくありません。特に学習サンプルとしては非常に不向きです。もし、本記事でJavaScriptによるDTP(等の)自動化に興味を持たれた方は、ぜひ

クリエイター手抜きプロジェクト

こちらをご参照ください。

関連してそうなエントリ

日高崇

2 Comments

  1. 「case 5」でエラーが出たのでコメントにして表示見てみました。
    とっても綺麗♪(*^_^*) カレンダーで、美しいもの見ると 気持ちが晴れ晴れしますぅ。

  2. コメント有難うございます。(そして2年越しに返事をしているという。。スミマセン。。)

    case 5でエラーということは第5引数、のフォントがうまいことマッチしないのでしょう。たぶんお手元の環境で「HelveticaNeue-Bold」が無い、のでしょうね。

    ま、コメントアウトしてしまうというのが一番現実的な気がしますが、101行目等にあるwrite()関数のところで、お手元にあるフォント名を入れていただくか、第5引数は飛ばして、後でイラレ上でフォントを指定するか、あたりですかね……。

Comments are closed.