はじめに
長期休業(夏休み・冬休み)の動静表作成、まだExcelで枠線を引いて作っていませんか?
「期間が変わるたびに行を削除したり追加したり…」「職員の異動があるたびに名簿を直して…」という作業は、今日で終わりにしましょう。
今回ご紹介するのは、**「学校ごとの設定(期間や名簿)を入力してボタンを押すだけ」**で、その学校専用の動静表システムを一発作成できるツールです。
プログラミング(GAS)を使いますが、難しい知識はゼロで大丈夫。コードをコピペするだけで、明日から自校で使えます。
このツールのすごいところ
- どんな期間でも一発作成:日付を入れるだけで、夏休み(40日)でも冬休み(14日)でも、土日色付け済みの表が自動生成されます。
- 自校仕様にカスタマイズ:職員数、職名、使う記号(○、出張、年休など)は、設定シートに書き込むだけで自由に反映されます。
- 全員同時入力&未入力チェック:クラウド(Googleスプレッドシート)なので、職員室全員で同時に入力でき、未入力者の数も自動表示されます。
- 個人印刷も対応:名前を選ぶだけで、自分だけの予定表が表示・印刷できる機能付き。


このシステムでできること
- 自動作成機能:開始日と終了日を入れるだけで、その日数分の表を一瞬で作成(夏休み40日でも冬休み14日でも自動対応)。
- 入力の効率化:記号(○、年休、出張など)はプルダウンで選択。記号の凡例も自動表示。
- 全員同時編集:1つのシートを全員で共有。他の先生の動きもリアルタイムで分かります。
- 未入力チェック:「あと何人入力していないか」が自動表示されるので、管理職のチェックが楽になります。
- 個人印刷対応:自分の名前を選ぶだけで、自分専用の予定表が表示され、そのまま印刷できます。
作成手順(所要時間:約15分)
ステップ1:土台となる「設定」シートを作る(ここが一番大事!)
まず、Googleスプレッドシートを新規作成し、シート名を**「設定」に変更します。
このシートが「設計図」**になります。ご自身の学校に合わせて、以下の通りに入力してください。

- B1セル:表のタイトル(例:令和7年度 冬季休業動静表)
- B2〜B3セル:開始日と終了日を入力
- A列・B列(5行目〜):職名と氏名を入力(人数分だけ縦にズラッと書いてください)
- C列・D列(5行目〜):使いたい記号とその意味を入力(例:C列に「年」、D列に「年休」)
ポイントここに入力した内容が、そのままシステムに読み込まれます。「ウチの学校は『日直』がある」「『副校長』がいる」など、自由に書き換えてOKです!
ステップ2:プログラムをコピペする

設計図ができたら、それを組み立てる「エンジン」を搭載します。
- メニューの [拡張機能] > [Apps Script] をクリック。
- コード入力画面の文字を全て消す。
- 以下のコードをすべてコピーして貼り付ける。
codeJavaScript
/* 学校用動静表自動作成システム */
function onOpen() {
SpreadsheetApp.getUi().createMenu('動静表メニュー')
.addItem('動静表システム作成・更新', 'createScheduleSheets')
.addToUi();
}
function createScheduleSheets() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const configSheet = ss.getSheetByName('設定');
if (!configSheet) { Browser.msgBox("「設定」シートが見つかりません。"); return; }
// 1. 設定データ取得
const title = configSheet.getRange('B1').getValue();
const startDate = new Date(configSheet.getRange('B2').getValue());
const endDate = new Date(configSheet.getRange('B3').getValue());
const lastRow = configSheet.getLastRow();
if (lastRow < 5) { Browser.msgBox("職員データがありません(5行目以降に入力してください)"); return; }
// 職員データ
const staffDataRaw = configSheet.getRange(5, 1, lastRow - 4, 2).getValues();
const validStaff = staffDataRaw.filter(row => row[1] !== "");
const staffNames = validStaff.map(r => r[1]);
// 記号と説明データの取得
const symbolRows = configSheet.getRange("C5:C").getValues().filter(String).length;
const symbolData = configSheet.getRange(5, 3, symbolRows, 2).getValues();
const symbols = symbolData.map(r => r[0]);
// 日付リスト生成
const dateList = [];
for (let d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) {
dateList.push(new Date(d));
}
const daysCount = dateList.length;
const dayMap = ['日', '月', '火', '水', '木', '金', '土'];
// 2. 「行事マスタ」作成
let eventSheet = ss.getSheetByName('行事マスタ');
if (!eventSheet) {
eventSheet = ss.insertSheet('行事マスタ');
eventSheet.getRange("A1:C1").setValues([['日付', '曜日', '主な行事']]).setBackground('#d9d9d9').setFontWeight('bold');
}
const eventData = dateList.map(date => [date, dayMap[date.getDay()]]);
eventSheet.getRange(2, 1, eventSheet.getLastRow(), 2).clearContent();
eventSheet.getRange(2, 1, daysCount, 2).setValues(eventData);
// 3. 「動静表」作成
let mainSheet = ss.getSheetByName('動静表');
if (mainSheet) {
if(Browser.msgBox('警告', '動静表を再作成します。入力済みのデータは初期化されますがよろしいですか?', Browser.Buttons.OK_CANCEL) == 'cancel') return;
mainSheet.clear();
} else {
mainSheet = ss.insertSheet('動静表');
}
// レイアウト構築
const hRow = 3; // ヘッダー
const dRow = 6; // データ開始
mainSheet.getRange(1, 1).setValue(title).setFontSize(16).setFontWeight('bold');
// 凡例表示(右上)
let legendCol = 6;
mainSheet.getRange(1, legendCol).setValue("【記号凡例】:").setFontWeight("bold").setHorizontalAlignment("right");
legendCol++;
symbolData.forEach(item => {
const text = item[0] + ":" + (item[1] ? item[1] : "");
mainSheet.getRange(1, legendCol).setValue(text).setFontSize(9)
.setBorder(true,true,true,true,true,true).setBackground('#f3f3f3').setHorizontalAlignment("center");
legendCol++;
});
mainSheet.getRange(hRow, 1, 1, 4).setValues([["月", "日", "曜日", "主な行事"]]);
mainSheet.getRange(dRow, 1).setFormula(`=ARRAYFORMULA(IF('行事マスタ'!A2:A${daysCount+1}="","",MONTH('行事マスタ'!A2:A${daysCount+1})))`);
mainSheet.getRange(dRow, 2).setFormula(`=ARRAYFORMULA(IF('行事マスタ'!A2:A${daysCount+1}="","",DAY('行事マスタ'!A2:A${daysCount+1})))`);
mainSheet.getRange(dRow, 3).setFormula(`=ARRAYFORMULA('行事マスタ'!B2:B${daysCount+1})`);
mainSheet.getRange(dRow, 4).setFormula(`=ARRAYFORMULA('行事マスタ'!C2:C${daysCount+1})`);
let col = 5;
validStaff.forEach(staff => {
// 未入力カウンター&枠組み
const checkRange = `R[${dRow-2}]C[0]:R[${dRow + daysCount - 3}]C[0]`;
mainSheet.getRange(2, col).setFormula(`=COUNTBLANK(${checkRange})&"未"`).setFontSize(8).setFontColor('red').setHorizontalAlignment('center');
mainSheet.getRange(3, col).setValue(staff[0]).setBackground('#efefef').mergeAcross().setHorizontalAlignment('center');
mainSheet.getRange(4, col).setValue(staff[1]).setFontWeight('bold').mergeAcross().setHorizontalAlignment('center');
mainSheet.getRange(5, col).setValue('午前').setHorizontalAlignment('center').setBorder(true,true,true,true,true,true);
mainSheet.getRange(5, col+1).setValue('午後').setHorizontalAlignment('center').setBorder(true,true,true,true,true,true);
const rule = SpreadsheetApp.newDataValidation().requireValueInList(symbols, true).setAllowInvalid(false).build();
mainSheet.getRange(dRow, col, daysCount, 2).setDataValidation(rule);
mainSheet.getRange(3, col, daysCount+3, 2).setBorder(true,true,true,true,true,true);
col += 2;
});
// デザイン調整(土日色付け等)
mainSheet.getRange(hRow, 1, 3, 4).setBackground('#d9d9d9').setFontWeight('bold').setBorder(true,true,true,true,true,true).setHorizontalAlignment('center').setVerticalAlignment('middle');
mainSheet.getRange(dRow, 1, daysCount, col-1).setBorder(true,true,true,true,true,true);
const days = eventData.map(r => r[1]);
for (let i = 0; i < days.length; i++) {
const r = dRow + i;
if (days[i] === '土') mainSheet.getRange(r, 1, 1, col-1).setBackground('#fce5cd');
if (days[i] === '日') mainSheet.getRange(r, 1, 1, col-1).setBackground('#f9cb9c');
}
mainSheet.setColumnWidth(4, 150);
mainSheet.setFrozenRows(5);
mainSheet.setFrozenColumns(4);
// 4. 「個人印刷」作成
let printSheet = ss.getSheetByName('個人印刷');
if (printSheet) printSheet.clear();
else printSheet = ss.insertSheet('個人印刷');
printSheet.getRange("A1").setValue("氏名選択:");
const nameRule = SpreadsheetApp.newDataValidation().requireValueInList(staffNames, true).build();
printSheet.getRange("B1").setDataValidation(nameRule).setValue(staffNames[0]).setBackground('#fff2cc').setBorder(true,true,true,true,true,true);
printSheet.getRange("C1").setValue("←名前を選択(入力は「動静表」で)").setFontColor("gray");
printSheet.getRange("A3").setValue(title + "(個人)").setFontSize(14).setFontWeight("bold");
printSheet.getRange("A5:E5").setValues([["月", "日", "曜日", "主な行事", "動静"]]).setBackground('#d9d9d9').setFontWeight('bold').setHorizontalAlignment('center');
printSheet.getRange(6, 1).setFormula(`=ARRAYFORMULA(MONTH('行事マスタ'!A2:A${daysCount+1}))`);
printSheet.getRange(6, 2).setFormula(`=ARRAYFORMULA(DAY('行事マスタ'!A2:A${daysCount+1}))`);
printSheet.getRange(6, 3).setFormula(`=ARRAYFORMULA('行事マスタ'!B2:B${daysCount+1})`);
printSheet.getRange(6, 4).setFormula(`=ARRAYFORMULA('行事マスタ'!C2:C${daysCount+1})`);
// 個人データ参照式
const f = `=ARRAYFORMULA(OFFSET('動静表'!$A$6, 0, MATCH($B$1, '動静表'!$4:$4, 0)-1, ${daysCount}, 1) & " / " & OFFSET('動静表'!$A$6, 0, MATCH($B$1, '動静表'!$4:$4, 0), ${daysCount}, 1))`;
printSheet.getRange(6, 5).setFormula(f);
printSheet.getRange(6, 1, daysCount, 5).setBorder(true,true,true,true,true,true).setHorizontalAlignment('center');
printSheet.setColumnWidth(4, 200); printSheet.setColumnWidth(5, 100);
// 凡例表示(個人用)
printSheet.getRange("G5").setValue("【記号凡例】").setFontWeight("bold");
printSheet.getRange("G5:H5").merge().setBackground('#efefef').setBorder(true,true,true,true,true,true).setHorizontalAlignment('center');
let pRow = 6;
symbolData.forEach(item => {
printSheet.getRange(pRow, 7).setValue(item[0]).setHorizontalAlignment('center').setBorder(true,true,true,true,true,true);
printSheet.getRange(pRow, 8).setValue(item[1]).setBorder(true,true,true,true,true,true);
pRow++;
});
printSheet.setColumnWidth(6, 20); printSheet.setColumnWidth(7, 40); printSheet.setColumnWidth(8, 120);
Browser.msgBox("作成完了!\n・「動静表」「個人印刷」「行事マスタ」が作成されました。\n・土日は自動で色付けされています。");
}
- 上部のフロッピーアイコン(保存)を押して保存します。
ステップ3:作成ボタンを押す(※初回のみ認証あり)
いよいよ作成です。「設定」シートの内容が正しいことを確認して実行しましょう。
- スプレッドシートに戻り、ブラウザを更新(F5)します。
- メニューに追加された [動静表メニュー] > [動静表システム作成・更新] をクリック。
- 【重要】初回のみ「認証」が必要です
- 「承認が必要です」→ [続行]
- アカウントを選択
- 「このアプリはGoogleによって確認されていません」→ 左下の [詳細] をクリック
- [(安全ではないページ)に移動] をクリック(※自作プログラムなのでこう出ますが安全です)
- [許可] をクリック
これで、設定シートの内容を読み取って、あなたの学校用の動静表が自動生成されます!
これでスクリプトが動き出し、シートが自動作成されます。
※2回目以降、この操作は不要です。
管理職(作成者)の運用ポイント

- 行事の入力:自動で作られる「行事マスタ」シートに入力すると、全員の表や個人表に反映されます。
- 配布前の最終確認:もし名簿や記号を間違えていても大丈夫。「設定」シートを直して、もう一度メニューから「作成・更新」を押せば、何度でも作り直せます。(※ただし、先生方が入力を始めた後に作り直すとデータが消えるので、配布前に確定させましょう!)
- 共有方法:スプレッドシート右上の「共有」から、職員全員に「編集者」としてリンクを送れば完了です。
最後に
このツールの最大の利点は、「設定」シートの日付を変えて実行し直すだけで、次の夏休み用シートも一瞬で作れることです。
一度仕組みを作ってしまえば、ずっと使い続けられます。ぜひご活用ください!
会員の方々はダウンロードできます
プロ・グループ会員の方はこちら
一般会員の方はここから
このスプレッドシートは、認証作業が必要です。





コメント