やりたいこと
Googleスプレッドシートにて作成した日別のスケジュールをGoogle Calendarへイベント追加するスクリプトを組みました。
javascriptは触り始めたばかりなのですが、時間を扱っている部分がどうにも冗長だなと思っています。この辺りの簡素な書き方があれば教えて頂けたら嬉しいです。
実装したのはスプレッドシートで当日のスケジュールを立ててそれを指定のカレンダーに転記するという内容です。
表は
開始時間 | 終了時間 | Todo |
---|---|---|
9:00 | 9:30 | text |
このような表が続くイメージです。
流れとしては
- new Date()で当日の日付等の情報を取得し、それぞれtYやtMなどの西暦や月に分ける。
- スプレッドシートの9:00 ~ 9:30などの部分の時間と分をsHやeMなどの変数に代入。(getValue()で抜き出すと1899年などになってしまった為、getHours()で数字だけ抜いてます)
- new Date()から取得したtYや、スプレッドシートから取得したsHを元にイベントの日時情報を構成しカレンダーにイベントを作成する
function myFunction() {
var title, description;
var sH,sM,eH,eM;
var today = new Date();
var tY = today.getFullYear();
var tM = today.getMonth();
var tD = today.getDate();
var sheet = SpreadsheetApp.getActiveSheet();
var objCalendar = CalendarApp.getCalendarById('カレンダーID');
for (var i = 2; i <= sheet.getLastRow(); i++) {
if (sheet.getRange(i, 3).getValue() != ""){
title = sheet.getRange(i, 6).getValue();
sH = sheet.getRange(i, 1).getValue().getHours();
sM = sheet.getRange(i, 1).getValue().getMinutes();
eH = sheet.getRange(i, 2).getValue().getHours();
eM = sheet.getRange(i, 2).getValue().getMinutes();
description = sheet.getRange(i, 4).getValue();
objCalendar.createEvent(title,
new Date( tY, tM, tD , sH, sM ),
new Date( tY, tM, tD , eH, eM ),
{description:description});
}
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
冗長とまでは思いませんでしたが、一つしか使用していない変数が不要なので削除してみました。
また、「カレンダーID」を直接指定していたり、今日(today)を直接指定している点が汎用性にかけた為、引数を利用する形にしてみました。
function myCalendar (calendarId /* [, year, month, day] */) {
var today = new Date();
var argumentsLength = arguments.length;
var year = argumentsLength > 2 ? arguments[1] : today.getFullYear();
var month = argumentsLength > 3 ? arguments[2] : today.getMonth();
var day = argumentsLength > 4 ? arguments[3] : today.getDate();
var sheet = SpreadsheetApp.getActiveSheet();
var getRange = sheet.getRange.bind(sheet);
var objCalendar = CalendarApp.getCalendarById(calendarId);
for (var i = 2, len = sheet.getLastRow() + 1, sheetDate1, sheetDate2; i < len; i++) {
if (getRange(i, 3).getValue() != ""){
sheetDate1 = getRange(i, 1).getValue();
sheetDate2 = getRange(i, 2).getValue();
objCalendar.createEvent(getRange(i, 6).getValue(),
new Date( year, month, day , sheetDate1.getHours(), sheetDate1.getMinutes() ),
new Date( year, month, day , sheetDate2.getHours(), sheetDate2.getMinutes() ),
{description: getRange(i, 4).getValue()}
);
}
}
}
Re: i-bunta さん
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
「時間を扱っている部分がどうにも冗長」という質問への回答ではないのですが、今のコードだとAPIの呼び出し回数が多いです。
本のコードだと1ループで19回のSpreadSheetのAPIを使用していますが、getValuesで一気に配列に読み込んでから処理するとよいです。
カレンダーへの登録であればそれほど数が多くないと思いますが参考にしてください。カレンダーへの登録処理は削除しています。
var gasheet = "******************";
function test(){
var title, description;
var sH,sM,eH,eM;
var today = new Date();
var tY = today.getFullYear();
var tM = today.getMonth();
var tD = today.getDate();
var ss = SpreadsheetApp.openById(gasheet);
var sheet = ss.getSheetByName("シート1");
var table = sheet.getRange(2,1,sheet.getLastRow()-1,6).getValues();
table.forEach(function(values){
if( values[2] != ""){ // C列
title = values[5]; // F列
sH = values[0].getHours(); // A列
sM = values[0].getMinutes(); // A列
eH = values[1].getHours(); // B列
eM = values[1].getMinutes(); // B列
description = values[3]; // D列
}
});
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/01/31 13:40
ただ、
var year = argumentsLength > 2 arguments[1] : today.getFullYear();
で「ステートメントの前に;がありません」というエラーが出てしまいました...
いまいちargumentsの使い方がわからず今ググって見ています。
またカレンダーIDは
function myCalendar (calendarId /* [, year, month, day] */)
のcalendarId に入れる形ですよね?
スクリプトをいじれない方もゼロから触る可能性があるので、セル内にcalendarId を入力する箇所を用意しそこから参照しようかと思いましたのでここは自分でやってみようと思います。
何はともあれご回答ありがとうございます!
2017/01/31 13:47 編集
ついでに getRange の呼び出し回数が比較的多かったので sheet.getRange.bind(sheet) で this 束縛してみました。
仮引数部の year, month, day をコメントアウトすれば arguments は不要ですが、その場合は myCalendar.length === 4 になってしまう(第四引数まで必須を明示する)のであえて arguments で参照するようにしています。
カレンダーIDは第一引数で指定する認識で合っています。