コモノExtendScript100本ノック

超初心者のDTPオペレーターが週にひとつスクリプトを書くブログ

058.【Id】年月を指定してカレンダーを作る

挙動

f:id:haraguai_is_bad:20191128144826p:plain:w300

  1. 実行するとウィンドウが立ち上がるので、年と月を入力して実行ボタンを押す。
  2. カレンダーに記載する日付(先月の末日~今月~来月の頭)の配列が生成される。
  3. 新規ドキュメントが作成される。
  4. 必要な段落・文字・セル・表スタイルが作成される。
  5. テキストフレームが作成され、「○年○月」と記入される。
  6. 同フレーム内に表が作成される。
  7. 表に日付が記入される。
  8. ヘッダー(曜日)行が追加される。
  9. スタイルがあてがわれる。
  10. 完了。あとは手動でスタイルを整える。

f:id:haraguai_is_bad:20191128171534p:plain:w500

コード

//@targetengine "createCalender"

// ウィンドウを作成
var dialog = new Window("dialog");
dialog.text = "カレンダー作成";

var group1 = dialog.add("group");
group1.orientation = "row";

var edittext1 = group1.add("edittext");
var s = [50, 25];
edittext1.preferredSize = s;
var statictext1 = group1.add("statictext").text = "年";
var edittext2 = group1.add("edittext");
edittext2.preferredSize = s;
var statictext2 = group1.add("statictext").text = "月のカレンダーを作成します。";
var button1 = dialog.add("button")
button1.text = "実行";
button1.onClick = function() {
    dialog.close(1);
}
var dlgResult = dialog.show();
if (dlgResult !== 1) {
    alert("中断しました");
    exit();
}

// 日付の配列を作成
var myYear = parseInt(edittext1.text);
var myMonth = parseInt(edittext2.text) - 1; // monthは0はじまり
if (!myYear || !myMonth || myYear < 1 || myMonth < 1 || myMonth > 12) {
    alert("適切な値を入力してください");
    exit();
}

var list = [];

// 前月末分を取得
var startDate = new Date(myYear, myMonth, 1);
var lastCnt = startDate.getDay(); // 前月末の日数に等しい
for (var i = 0; i < lastCnt; i++) {
    var l = new Date(myYear, myMonth, 0 - i);
    var tmp = {
        year: myYear,
        month: (myMonth - 1) + 1,
        date: l.getDate(),
        day: l.getDay(),
        holiday: undefined
    }
    list.push(tmp)
}
list.reverse();

// 今月分を取得
var daysCnt = new Date(myYear, myMonth + 1, 0).getDate(); // 今月の日数
for (var i = 1; i <= daysCnt; i++) {
    var tmp = {
        year: myYear,
        month: myMonth + 1,
        date: i,
        day: new Date(myYear, myMonth, i).getDay(),
        holiday: undefined
    }
    list.push(tmp)
}

// 来月頭分を取得
var nextCnt = 35 - list.length;
for (var i = 1; i <= nextCnt; i++) {
    var tmp = {
        year: myYear,
        month: (myMonth + 1) + 1,
        date: i,
        day: new Date(myYear, myMonth + 1, i).getDay(),
        holiday: undefined
    }
    list.push(tmp);
}


// 新規ドキュメント作成
var doc = app.documents.add();

// 段落スタイル作成
var titleStyle = doc.paragraphStyles.add({
    name: "タイトル"
});
var headerStyle = doc.paragraphStyles.add({
    name: "ヘッダー"
});
var monthStyle = doc.paragraphStyles.add({
    name: "今月"
});
var monthStyle2 = doc.paragraphStyles.add({
    name: "先月来月",
    fillTint: 40
});

// 文字スタイル作成
var sunSwatch = app.activeDocument.colors.add({
    name: "日曜祝日",
    model: ColorModel.PROCESS,
    space: ColorSpace.CMYK,
    colorValue: [0, 100, 100, 0]
});
var satSwatch = app.activeDocument.colors.add({
    name: "土曜",
    model: ColorModel.PROCESS,
    space: ColorSpace.CMYK,
    colorValue: [100, 0, 0, 0]
});
var sunStyle = doc.characterStyles.add({
    name: "日曜祝日",
    fillColor: sunSwatch
});
var satStyle = doc.characterStyles.add({
    name: "土曜",
    fillColor: satSwatch
});

// セルスタイル作成
var headerCellStyle = doc.cellStyles.add({
    name: "ヘッダー",
    appliedParagraphStyle: headerStyle
});
var dateCellStyle = doc.cellStyles.add({
    name: "日付",
    appliedParagraphStyle: monthStyle
});

// 表スタイル作成
var calenderTblStyle = doc.tableStyles.add({
    name: "カレンダー",
    headerRegionCellStyle: headerCellStyle,
    bodyRegionCellStyle: dateCellStyle
})

// 表作成
var tf = doc.pages[0].textFrames.add();
tf.geometricBounds = [0, 0, 297, 210];
tf.contents = myYear + "年" + (myMonth + 1) + "月\r";
tf.paragraphs[0].applyParagraphStyle(titleStyle);
var tbl = tf.tables.add(LocationOptions.AT_END, tf, {
    appliedTableStyle: calenderTblStyle
});
tbl.columnCount = 7;
tbl.bodyRowCount = 5;
tbl.cells.everyItem().height = "10mm";
tbl.cells.everyItem().width = "10mm";

for (var i = 0; i < list.length; i++) {
  if (i<35) {
    tbl.cells[i].contents = list[i].date.toString();
    } else {
      tbl.cells[i-7].contents = tbl.cells[i-7].contents + "\r\u0008" + list[i].date.toString();
      tbl.cells[i-7].topRightDiagonalLine = true;
      }
}

tbl.rows.add(LocationOptions.AT_BEGINNING, tbl.rows[0]);
var days = ["日", "月", "火", "水", "木", "金", "土"];
for (var i = 0; i < 7; i++) {
    tbl.cells[i].contents = days[i];
}
tbl.rows[0].height = "5mm";

// スタイル適用
tbl.columns[0].cells.everyItem().paragraphs.everyItem().appliedCharacterStyle = sunStyle;
tbl.columns[6].cells.everyItem().paragraphs.everyItem().appliedCharacterStyle = satStyle;
tbl.rows[0].cells.everyItem().paragraphs[0].appliedCharacterStyle = doc.characterStyles[0]; // ヘッダー行は文字スタイルを外す
tbl.rows[0].rowType = RowTypes.HEADER_ROW;
tbl.rows[0].cells.everyItem().clearCellStyleOverrides();
for (var i = 0; i < lastCnt; i++) {
    tbl.rows[1].cells[i].paragraphs[0].applyParagraphStyle(monthStyle2);
}
for (var i = 0; i < nextCnt; i++) {
    tbl.rows[5].cells[6 - i].paragraphs[0].applyParagraphStyle(monthStyle2);
}

alert("完了しました");

メモ

分かったこと

Dateオブジェクトでは年・日付・曜日と月でインデックスの扱いが異なる(という言い方が適切かどうか…)。
月は0始まりでカウントされるため、実際の月よりマイナス1して考える必要がある。
例えば2019年11月29日について処理を行う場合、

var myDate = new Date(2019, (11-1), 29);

とする。

分からなかったこと

#target "indesign"

こうすると、CC 2019とCS6がインストールされているPCで何故かCS6が起動してしまう。
(最後にインストールしたのはCC 2019の方)

積み残し

・祝日を追加するオプション
祝日の場合、日付の下に祝日名を入れたい。
GoogleカレンダーAPIを利用できないかなあ。
参考:https://qiita.com/kamatama_41/items/be40e05524530920a9d9

六曜を追加するオプション
・一括で1年分のカレンダーを作成するオプション

参考