GASで週間勤務シフトのテンプレートを作成
日別シフトをGASで作る
週間の勤務シフトをGASで作るコードです。
1度組み込んでおくと意外と使えます。
薄い黄色の部分だけ入力すれば自動計算設定となっています。
休憩時間は労働基準法を遵守して計算しています。
必要事項を入れたものが下の画像です。
印刷もA4に収まります。
GASとは
GASは簡単に言えばグーグルが提供しているプログラミング言語です。無料で利用できます。
シフト表のサンプルコード
GASをある程度知っている方…下のコードをコピペすれば完了です。
GASをあまりよく分からない方…コードの下に説明を詳しく入れています。ご参照ください。
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('カスタムメニュー') // メニューのタイトルを指定
.addItem('週間シフト', '週間シフト')
.addToUi(); // メニューをUIに追加
}
function 週間シフト() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheetNameBase = "週間シフト";
let sheetName = sheetNameBase + "1";
let sheetNumber = 1;
// 重複しないシート名を決定
while (ss.getSheetByName(sheetName) !== null) {
sheetNumber++;
sheetName = sheetNameBase + sheetNumber;
}
// 新しいシートを作成
const sheet = ss.insertSheet(sheetName);
// セルの初期設定
sheet.getRange("A1").setValue("週間シフト表").setFontWeight("bold");
sheet.getRange("H1").setValue("■パターン設定 ※終了時間が翌日2時の場合は26:00");
sheet.getRange("B2").setValue("開始日");
sheet.getRange("C2").setValue("終了日");
sheet.getRange("C3").setFormula('=IF(B3="", "", B3 + 6)');
// H2~Q2にパターン情報を入力
const patternHeaders = ["パターン", "開始時間", "終了時間", "必要休憩", "勤務時間",
"パターン", "開始時間", "終了時間", "必要休憩", "勤務時間"];
sheet.getRange("H2:Q2").setValues([patternHeaders]);
// A3~E6に各種入力セルを設定
sheet.getRange("A3").setValue("Week");
sheet.getRange("E1").setValue("■使い方");
sheet.getRange("E2").setValue("①この色のセルを入力").setBackground("#FFF2CC"); // 明るい黄色
sheet.getRange("F2").setBackground("#FFF2CC"); // 明るい黄色
sheet.getRange("E3").setValue("②週の開始日を入力 (例: 11/4)");
sheet.getRange("E4").setValue("③パターン設定を入力");
sheet.getRange("E5").setValue("④氏名入力");
sheet.getRange("E6").setValue("⑤シフトをプルダウン選択");
// A8に「日付」、B8に関数「=B3」を設定
sheet.getRange("A8").setValue("日付");
sheet.getRange("B8").setFormula("=B3");
// C8~H8に日付の連続設定をする関数を入力
for (let col = 3; col <= 8; col++) {
let cell = sheet.getRange(8, col);
let prevCell = sheet.getRange(8, col - 1);
cell.setFormula(`=if(${prevCell.getA1Notation()}="","",${prevCell.getA1Notation()}+1)`);
}
// A9に「曜日」、B9に曜日表示の関数を入力
sheet.getRange("A9").setValue("氏名");
sheet.getRange("B9").setFormula('=IF(B8="","",TEXT(B8,"dddd"))');
// C9~H9に曜日の関数を入力
for (let col = 3; col <= 8; col++) {
let cell = sheet.getRange(9, col);
let prevCell = sheet.getRange(8, col);
cell.setFormula(`=IF(${prevCell.getA1Notation()}="","",TEXT(${prevCell.getA1Notation()},"dddd"))`);
}
// I9:Q9に指定されたヘッダーを追加
const headerLabels = ["勤務時間", "勤務日数", "公休", "振替休日", "有給休暇", "届出欠勤", "育児休暇", "出張", "その他"];
sheet.getRange("I9:Q9").setValues([headerLabels]);
// H3:H6とM3:M6に指定された値を設定
const patternValuesH = [["A"], ["B"], ["C"], ["D"]];
const patternValuesM = [["E"], ["F"], ["G"], ["H"]];
sheet.getRange("H3:H6").setValues(patternValuesH);
sheet.getRange("M3:M6").setValues(patternValuesM);
// J3~J6とO3:O6の表示形式をhh:mmに設定
sheet.getRange("J3:J6").setNumberFormat("hh:mm");
sheet.getRange("O3:O6").setNumberFormat("hh:mm");
// K3~L6、P3~Q6の関数を追加
for (let row = 3; row <= 6; row++) {
sheet.getRange(`K${row}`).setFormula(`=IF(I${row}="","", IF(J${row}-I${row}>TIME(8,,), TIME(1,,), IF(J${row}-I${row}>TIME(6,,), TIME(,45,), 0)))`).setNumberFormat("hh:mm");
sheet.getRange(`L${row}`).setFormula(`=IF(I${row}="","", J${row}-I${row}-K${row})`).setNumberFormat("hh:mm");
sheet.getRange(`P${row}`).setFormula(`=IF(N${row}="","", IF(O${row}-N${row}>TIME(8,,), TIME(1,,), IF(O${row}-N${row}>TIME(6,,), TIME(,45,), 0)))`).setNumberFormat("hh:mm");
sheet.getRange(`Q${row}`).setFormula(`=IF(N${row}="","", O${row}-N${row}-P${row})`).setNumberFormat("hh:mm");
}
// I10:I30に関数を設定して、表示形式を経過時間に設定
for (let row = 10; row <= 30; row++) {
sheet.getRange(row, 9).setFormula(`=IF(A${row}="","",SUM(
COUNTIF($B${row}:$H${row},"A")*$L$3,
COUNTIF($B${row}:$H${row},"B")*$L$4,
COUNTIF($B${row}:$H${row},"C")*$L$5,
COUNTIF($B${row}:$H${row},"D")*$L$6,
COUNTIF($B${row}:$H${row},"E")*$Q$3,
COUNTIF($B${row}:$H${row},"F")*$Q$4,
COUNTIF($B${row}:$H${row},"G")*$Q$5,
COUNTIF($B${row}:$H${row},"H")*$Q$6
))`);
sheet.getRange(row, 9).setNumberFormat("[hh]:mm");
}
// J10:J30に関数を設定し、表示形式を0日に設定
for (let row = 10; row <= 30; row++) {
sheet.getRange(row, 10).setFormula(`=IF(A${row}="","", 7-SUM($L${row}:$Q${row})-K${row})`);
sheet.getRange(row, 10).setNumberFormat("0日");
}
// K10:Q30に指定の関数を設定し、表示形式を0日に設定
for (let row = 10; row <= 30; row++) {
for (let col = 11; col <= 17; col++) {
let headerCell = sheet.getRange(9, col);
let cell = sheet.getRange(row, col);
cell.setFormula(`=IF($A${row}="","", COUNTIF($B${row}:$H${row}, ${headerCell.getA1Notation()}))`);
cell.setNumberFormat("0日");
}
}
// B10:H30にプルダウン設定を追加
const dropdownValues = [
"A", "B", "C", "D", "E", "F", "G", "H",
"公休", "振替休日", "有給休暇", "届出欠勤", "育児休暇", "出張", "その他"
];
const dropdownRange = sheet.getRange("B10:H30");
const rule = SpreadsheetApp.newDataValidation()
.requireValueInList(dropdownValues)
.build();
dropdownRange.setDataValidation(rule);
// 条件付きフォーマットを設定
const rules = [
SpreadsheetApp.newConditionalFormatRule()
.whenTextEqualTo("公休")
.setBackground("#FFE6E6") // 薄いピンク
.setRanges([dropdownRange])
.build(),
SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied('=OR(B10="A", B10="B", B10="C", B10="D", B10="E", B10="F", B10="G", B10="H")')
.setBackground("#E0F7FA") // 薄いスカイブルー
.setRanges([dropdownRange])
.build(),
SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied('=AND(B10<>"公休", NOT(OR(B10="A", B10="B", B10="C", B10="D", B10="E", B10="F", B10="G", B10="H")), B10<>"")')
.setBackground("#E6F9E6") // 薄いライトグリーン
.setRanges([dropdownRange])
.build(),
SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied('=ISBLANK(B10)')
.setBackground("#FFFFFF") // 白
.setRanges([dropdownRange])
.build()
];
sheet.setConditionalFormatRules(rules);
// I3:J6、N3:O6に明るい黄色を設定
sheet.getRange("B3").setBackground("#FFF2CC");
sheet.getRange("A10:A30").setBackground("#FFF2CC");
sheet.getRange("I3:J6").setBackground("#FFF2CC");
sheet.getRange("N3:O6").setBackground("#FFF2CC");
// A31~A40に「計」、「A」、「B」、「C」、「D」、「E」、「F」、「G」、「H」、「I」を入力
const valuesA = [["計"], ["A"], ["B"], ["C"], ["D"], ["E"], ["F"], ["G"], ["H"]];
sheet.getRange("A31:A39").setValues(valuesA);
// B31:H31に関数を設定し、0名と表示
for (let col = 2; col <= 8; col++) { // BからH列
const range = sheet.getRange(31, col);
range.setFormula(`=IF(SUM(${String.fromCharCode(64 + col)}32:${String.fromCharCode(64 + col)}40)=0, "", SUM(${String.fromCharCode(64 + col)}32:${String.fromCharCode(64 + col)}40))`); // 合計を計算し、0の場合は空文字を表示
range.setNumberFormat('0"名"'); // カスタム数値形式で表示
}
// B32:H40に関数を設定し、0名と表示
for (let row = 32; row <= 39; row++) {
for (let col = 2; col <= 8; col++) { // BからH列
const range = sheet.getRange(row, col);
range.setFormula(`=IF(COUNTIF(${String.fromCharCode(64 + col)}$10:${String.fromCharCode(64 + col)}$30,$A${row})=0,"",COUNTIF(${String.fromCharCode(64 + col)}$10:${String.fromCharCode(64 + col)}$30,$A${row}))`);
range.setNumberFormat('0"名"'); // カスタム数値形式で表示
}
}
// セルの中央揃えを設定
sheet.getRange("B8:Q39").setHorizontalAlignment("center").setVerticalAlignment("middle");
// B列からQ列のセル幅を75ピクセルに設定
for (let col = 2; col <= 17; col++) { // BからQ列
sheet.setColumnWidth(col, 75);
}
}
GASの基本から
Dドライブにアクセスして、スプレッドシートを開きます。
拡張機能からAppScriptを選択します。
下のような画面が出てきたら、function myfunctionと書かれている部分をすべて消します。
次に上記のコードをすべて選択して貼り付けます。
保存を押し、実行を押します。
以下、赤印で囲んだところを選択
実行ログに実行完了と表示されたら、スプレッドシートを見て下さい。
カスタムメニューという項目が増えています。このファイルを開けば、次回以降も表示されます。他のファイルには影響はありません。
週間シフトを選択すれば出来上がりです。
この記事が気に入ったらサポートをしてみませんか?