ラベル GoogleAppsScript の投稿を表示しています。 すべての投稿を表示
ラベル GoogleAppsScript の投稿を表示しています。 すべての投稿を表示

2015年8月31日月曜日

Googleドライブの不要なファイルを自動で削除してみる 【自動削除編】

こんにちは、井下です。

前回からかなり間が空きましたが、引き続きGoogleドライブから不要なファイルを自動で削除してみます。

参考:前回→Googleドライブの不要なファイルを自動で削除してみる 【リストアップ編】

方法としては、以下の手順になります。
  1. "最終更新日から一定の日にちが経過しているファイル"を削除対象候補として、スプレッドシートにリストアップする
  2. 削除対象を確定する(手動で行います)
  3. 確定させたリストを基に、削除対象のファイルを全て削除する
手順1については前回実装・説明したので、今回は手順2について実装・説明します。
ただ、今回は手順1で実装した内容についてパフォーマンスの改善と、手順2で利用するカラムの追加を行っているのでご注意ください。
NAME_COLUMN = 0;
OWNER_COLUMN = 1;
MAIL_COLUMN = 2
LAST_UPDATED_COLUMN = 3;
ID_COLUMN = 4;

START_ROW = 1
START_COLUMN = 1

// 手順1
// 不要と思われるファイル(最終更新日から一定の日にちが経過したファイル)をリストアップする
function listup() {
  var DATE_OFFSET = 10;
  var sheet = SpreadsheetApp.getActiveSheet();

  var nowDate = new Date();
  var baseDate = dateFormat(new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate() - DATE_OFFSET));

  var files = DriveApp.searchFiles('modifiedDate <= "' + baseDate + '"');

  var values = [['ファイル名', 'オーナー', 'オーナー(メールアドレス)', '最終更新日', 'ファイルID']];

  var row = 1;

  while(files.hasNext()){
    var file = files.next();
    var owner = file.getOwner();
    values[row] = [];
    values[row][NAME_COLUMN] = "=HYPERLINK(\"" + file.getUrl() + "\",\"" + file.getName() + "\")";
    values[row][OWNER_COLUMN] = owner.getName();
    values[row][MAIL_COLUMN] = owner.getEmail();
    values[row][LAST_UPDATED_COLUMN] = file.getLastUpdated();
    values[row][ID_COLUMN] = file.getId();
    row++;
  }

  sheet.getRange(START_ROW, START_COLUMN, values.length, values[0].length).setValues(values);
}

// 手順3
// 手順1でリストアップしたファイルを削除する(自分がオーナーでないファイルは、マイドライブから表示しなくするだけ)
function trash() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var lastRow = sheet.getLastRow();
  var values = sheet.getRange(START_ROW, START_COLUMN, lastRow, ID_COLUMN + 1).getValues();

  for(var index = 1; index < lastRow; index++){
    if(values[index].join('') == ""){
      continue;
    }
 
    var owner = values[index][MAIL_COLUMN];
    var file = DriveApp.getFileById(values[index][ID_COLUMN]);
 
    // マイドライブから表示されないようにする
    DriveApp.removeFile(file);

    if(owner == Session.getActiveUser().getEmail()){
      // 自分がオーナーのファイルはゴミ箱に移動する
      file.setTrashed(true);
    }
  }
}

function dateFormat(date) {
  return date.getFullYear() + '-' + ('0' + (date.getMonth() + 1) ).slice(-2) + '-' + ('0' + date.getDate()).slice(-2);
}

前回から不要なファイルを削除するために、trashメソッドを追加しています。

trachメソッドはシートに書き込まれたファイルを参照し、自分がオーナーのファイルはゴミ箱へ移動します。
また、オーナーに関係なく、シートに書き込まれているファイルは全てマイドライブから表示されないようにします。
※ あくまでマイドライブから表示されなくなるだけで、ファイル自体は削除されません。

運用方法としては、次のようになると考えています。
  1. listupメソッドによって最新更新日から一定期間以上経過したファイルをリストアップする(手動でlistupを起動 or トリガーによって定期的に自動起動)
  2. リストアップされたファイルを確認し、削除したくないファイル名が記載された行を削除する(ここは手動で行います)
  3. trashメソッドによってリストアップされたファイルを全て削除する(手動でtrashを起動 or トリガーによって定期的に自動起動)
listupメソッドはトリガーで自動起動しても問題ありませんが、trashメソッドは人の目によるリストのチェックが事前にあるものと想定しているので、トリガーによる自動起動はご注意ください。

なお、最悪誤って削除してしまった場合も、ゴミ箱に移動しているだけなので、数日間は元に戻すことができます。

Google Driveの整理にご利用ください。

2015年7月30日木曜日

Googleドライブの不要なファイルを自動で削除してみる 【リストアップ編】

こんにちは、井下です。

いよいよ高校野球の甲子園出場校が揃ってきましたね。
野球をやっていたわけではありませんが、一発勝負ならではの真剣みが伝わってきて、毎年時間があれば何となく見てしまいます。


ところで、みなさんはGoogleドライブはご利用でしょうか? "とりあえずのファイル共有"くらいの意識から手軽に使えるストレージサービスです。スプレッドシートを作成したり、保存されているスプレッドを開く場所と言えば、もっと分かりやすいかもしれませんね。

Googleドライブには容量制限がありますが、スプレッドシートやGoogleドキュメントなど、Googleの提供するサービスであれば、容量制限に関係なく、いくらでも作成することができます。

そのため、気が付いたら不要なファイルが大量に作成されている… なんてことも出てきます。(Googleの提供するサービスであれば)容量制限には関係ないとはいえ、不要なファイルがいくつもあるのはあまり良い気持ちにはなりません。


そこで、今回と次回はGoogle Apps Scriptを使って、不要なファイルを削除(※)してみようと思います。
なお、"不要なファイル"かの判断を自動で行うことは難しいので、"最終更新日から一定の日付が経過しているファイル"を"不要かもしれないファイル"とします。"不要かもしれないファイル"から人が見て確認したうえで、本当に"不要なファイル"だけを削除します。

(※)厳密にはゴミ箱への移動を行い、完全に削除はしません。Google Apps Scriptの仕様上、完全に削除することができないためです。また、オーナーが自分でない場合はゴミ箱への移動もできないため、厳密に言えば"オーナーが自分で、不要なファイルをゴミ箱へ移動する"となります。

方法としては、次の手順を踏みます。

  1. "最終更新日から一定の日付が経過しているファイル"をスプレッドシートにリストアップする(不要かもしれないファイルの一覧作成)
  2. リストアップされたファイル名から、不要なファイルのみを削除する

今回は手順の1を実装・説明します。
手順の2は次回実装・説明する予定です。

2015年7月23日木曜日

Googleカレンダーを元にした作業実績を作成する

こんにちは、井下です。

いよいよ近所の公園でもセミの声が聞こえてきましたが、みなさんの周りはいかがでしょうか?
通勤ルートに小学校があるのですが、彼らは夏休みを満喫中なんですよね。なんとも羨ましい…。

さて、今回は前回予告していた通り、Googleカレンダーを元にして、作業実績を作成します。

イメージ図(前回のものを再掲)



Googleのサービスの関係は下記の図のようになります。



では、実現したコードを見てみましょう。
HOUR_MILLISECOND = 60 * 60 * 1000;
DATE_MILLISECOND = 24 * HOUR_MILLISECOND;

function run() {
  // 出力先スプレッドシートとシートの設定
  var SSHEET_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  var SHEET_NAME = "YYYYY"

  // 出力先スプレッドシートのシートを取得
  var sheet = SpreadsheetApp.openById(SSHEET_ID).getSheetByName(SHEET_NAME);

  // 日付範囲の設定
  var DATE_TERM = 5;
  var startDate = new Date("2015/7/20");
  var endDate = new Date(startDate.getTime() + DATE_TERM * DATE_MILLISECOND);

  // デフォルト(初期表示)されるカレンダーを選択
  var cal = CalendarApp.getDefaultCalendar();

  // カレンダーのイベントを取得
  var events = cal.getEvents(startDate, endDate);

  var row = 0;
  var column = 0;
  var works = [""];
  var result = [[""]];

  for(var index in events) {
    // イベントの名前、作業時間、実施日を取得
    var title = events[index].getTitle();
    var workTime = getWorkTime(events[index]);
    var targetDate = getTargetDate(events[index]);
 
    // イベントの名前がループ中に出てきたかを確認
    row = works.indexOf(title);
 
    // イベントの名前がループ中初めて出てきた場合
    if(row == -1){
      row = works.length;
      result[row] = [];
      result[row][0] = title;
   
      works.push(title);
    }
 
    // イベントの実施日がループ中初めて出てきた場合
    if(index == 0 || targetDate != getTargetDate(events[index - 1])){
      column++;
      result[0][column] = targetDate;
    }

    result[row][column] = result[row][column] == null ? workTime : workTime + result[row][column];
  }

  sheet.clear();

  // 1行目(日付表示の行)の取得・書き込み
  var header =  getDateRow(result[0]);
  sheet.getRange(1, 1, 1, header.length).setValues(new Array(header));

  // 2行目以降の取得・書き込み
  for(var sRow = 1; sRow < result.length; sRow++) {
    var writeRow = getWriteRow(result[sRow]);
    sheet.getRange(sRow + 1, 1, 1, writeRow.length).setValues(new Array(writeRow));
  }
}

function getDateRow(arrray){
  var dateRow = arrray;
  dateRow.splice(1, 0, "合計");

  return dateRow;
}

function getWriteRow(arrray){
  var writeRow = replaceArrayNull(arrray);
  var totalWorkTime = getTotalWorkTime(arrray);
  writeRow.splice(1, 0, totalWorkTime);

  return writeRow;
}

function replaceArrayNull(arrray){
  for(var index = 0; index < arrray.length; index++){
    if(arrray[index] == null){
      arrray[index] = "";
    }
  }
  return arrray;
}

function getTotalWorkTime(arrray){
  var total = 0;

  for(var index = 0; index < arrray.length; index++){
    if(isFinite(arrray[index]) && arrray[index] != ""){
      total += arrray[index];
    }
  }
  return total;
}

function getWorkTime(event){
  return (event.getEndTime() - event.getStartTime()) / HOUR_MILLISECOND;
}

function getTargetDate(event){
  var sourceDate = event.getStartTime();
  return (sourceDate.getMonth() + 1) + "/" + sourceDate.getDate();
}

赤字部分は実行環境に応じて必ず書き換えてください。
なお、"SSHEET_ID"には出力先として指定するスプレッドシートのIDを指定し、そのスプレッドシートのどのシートに出力するかを、"SHEET_NAME"(こちらはシート名)に指定します。
青字部分は実行時の都合に応じて書き換えてください。
カレンダーから抜き出す情報の開始日を"startDate"に指定し、開始日から何日分を取得するかを"DATE_TERM"に指定します。

実際に次のようなカレンダーに対して実行すると…

こんな感じに出力されました。


カレンダーの画像が小さくて分かりづらいですが、同じ作業が別の日にあった場合、行は1つに統一するようになっています。(具体的には"打ち合わせ"が7/21と7/24にあるところと、"開発"が7/22と7/24にあるところです)

なお、イベントが1つもない日(上記の図で言えば7/23)は、列が作成されない仕様なので、その点は注意してください。
他に注意するべき仕様として、終日の予定は24時間としてカウントします。

全ての予定と実績をGoogleカレンダーに書き込んでいる方は稀だと思いますが、日常的にGoogleカレンダーを業務で利用している方は、本当の作業実績を作成するための一助としてご利用ください。

2015年7月16日木曜日

Google App ScriptでGoogleカレンダーの情報を抜き出してみる

こんにちは、井下です。

これまでGoogle Apps Scriptからの連携として、主にスプレッドシートやFusion Tables、Google Analyticsについてご紹介してきましたが、今回はGoogleカレンダーとの連携方法についてご紹介しようと思います。

GoogleカレンダーはGoogleから提供されるサービスの中でも比較的利用されていると思います。業務で利用されている方も少なくないのではないでしょうか?


では、早速Google Apps Scriptのプロジェクトを起動し、次のコードを実行してみてください。
function myFunction() {
  var cal = CalendarApp.getDefaultCalendar();
  var startDate = new Date("2015/7/13");
  var endDate = new Date("2015/7/18");
  var events = cal.getEvents(startDate, endDate);

  for(var index in events) {
    Logger.log(events[index].getTitle());
    Logger.log(events[index].getStartTime());
    Logger.log(events[index].getEndTime());
  }
}
※1 Google Apps Scriptのプロジェクト作成方法は過去のブログ("Google Apps Scriptを使う準備"のあたり)をご参照ください。
※2 "startDate"および"endDate"は、取得したい日付の範囲に応じて変更してください。

実行が終わったら、ログを確認してみましょう。

指定した期間内でスケジュールしていた予定の名前、予定の開始日時、予定の終了日時が出てきています。

コードの中身を簡単に説明すると、1行目の"var cal = CalendarApp.getDefaultCalendar()"で連携先のカレンダーを指定しています。"getDefaultCalendar"とあるように、ユーザのデフォルトのカレンダー(Googleカレンダーを開いたとき、最初に開いているカレンダー)を連携先にしています。
ちなみにカレンダーのIDやカレンダーの名前と言った情報を元に、他のカレンダーを連携先に指定することもできます。その場合は"getDefaultCalendar"に代わって、別のメソッドを利用することになりますが、今回は割愛します。気になる方は、Google Apps Scriptのリファレンスをご参照ください。

5行目の"var events = cal.getEvents(startDate, endDate);"で、実際にカレンダーに入っている予定の情報を全て取得しています。(あくまで"startDate"~"endDate"の範囲内のですが)

そして7~11行目で取得した予定の情報から、予定の名前、予定の開始日時、予定の終了日時をログに出力させています。


もちろん、"予定の情報"は予定の名前以外に、様々な情報を持っています。予定の開始時刻や終了時刻、自分以外の予定の参加者(ゲスト)、予定に書いた説明など、"予定"として作成したときに入力したデータなら、取得することが可能です。

逆にGoogle Apps Scriptを使って、予定の情報を書き換えることもできます。取得に比べると用途が限られそうですが、自動で予定を入れたい場合などに使えるでしょうか。


今回は触り程度でしたが、次回はGoogleカレンダーの情報を元に、作業の実績時間を表にして、スプレッドシートへ出力してみようと考えています。

イメージ図

企業に勤めている方は、何の作業にどれだけ時間を使ったか、報告を求められることが多いと思いますが、(Googleカレンダーに予定と実績を入れておくことで)後から時間を計算する手間を省くことを目標にします。

2015年7月9日木曜日

Google AnalyticsのデータをGoogle Apps Scriptを使ってSpreadsheetに出力する(自動化対応・条件追加等)

こんにちは、井下です。

前回はGoogle Apps Scriptを利用して、Google AnalyticsのデータをSpreadsheetに出力してみました。

これで画面上からは見られなかった、3つ以上のディメンションで絞り込んだデータを見られるようになりましたが、前回のサンプルコードのままだと少し不便なところがあります。

例えば…
  • データ取得範囲を決める開始日・終了日が固定値なので、自動で実行しても意味がない
  • 出力先が常に同じシートなので、実行するたびに上書きされてしまう
  • ヘッダーがないので、ぱっと見てどの行が何のデータなのか分かりづらい
  • 検索キーワードが"not set"になっているデータなど、不要なデータは出力させないようにしたい

今回は上記の4点について、修正を行ったサンプルを書いていきます。


ちなみに、前回書いたサンプルコードはこちらです。
function analytics() {
  var PROFILE_ID = "ga:zzzzzzzz";

  var metrics = "ga:sessions, ga:percentNewSessions, ga:newVisits";
  var optArgs = {
    'dimensions': 'ga:keyword, ga:region, ga:networkDomain',
  };
  var startDate = "2015-06-01";
  var endDate = "2015-06-29";

  var ga = Analytics.Data.Ga.get(PROFILE_ID, startDate, endDate, metrics, optArgs).rows;
  var sheet = SpreadsheetApp.getActiveSheet();

  sheet.getRange(1, 1, ga.length, ga[0].length).setValues(ga);
}
※赤字部分は変更必須、青字部分は任意の値に変更する前提です


修正1 開始日・終了日を可変にする

Google AnalyticsとGoogle Apps Scriptの連携させる意義として、定期実行における自動化ができることを前回挙げています。
そのためにはデータの取得範囲の開始日・終了日を実行日に応じて可変にすることと、Google Apps Scriptのトリガー機能の設定が必要になります。

まず、下記のサンプルコードによって、開始日・終了日を実行日に応じて可変にします。
function analytics() {
  var PROFILE_ID = "ga:zzzzzzzz";
  var START_DATE_OFFSET = 8;
  var END_DATE_OFFSET = 1;

  var metrics = "ga:sessions, ga:percentNewSessions, ga:newVisits";
  var optArgs = {
    'dimensions': 'ga:keyword, ga:region, ga:networkDomain',
  };

  var nowDate = new Date();
  var startDate = dateFormat(new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate() - START_DATE_OFFSET));
  var endDate = dateFormat(new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate() - END_DATE_OFFSET));

  var ga = Analytics.Data.Ga.get(PROFILE_ID, startDate, endDate, metrics, optArgs).rows;
  var sheet = SpreadsheetApp.getActiveSheet();

  sheet.getRange(1, 1, ga.length, ga[0].length).setValues(ga);
}

function dateFormat(date) {
  return date.getFullYear() + '-' + ('0' + (date.getMonth() + 1) ).slice(-2) + '-' + ('0' + date.getDate()).slice(-2);
}
サンプルコードでは、「1週間分のデータを抽出」する例としています。

なお、データの日付範囲を変更したい場合は、"START_DATE_OFFSET"および"END_DATE_OFFSET"の値を変更してください。
"START_DATE_OFFSET"は日付範囲の開始日が実行日の何日前か、"END_DATE_OFFSET"は日付範囲の終了日が実行日の何日前かを決めています。

修正2 実行タイミングの自動化

次にトリガー機能の設定です。
Google Apps Scriptには定期実行や、特定の動作がされたときのみ実行するトリガー機能が用意されています。

トリガー機能の設定はGoogle Apps Scriptの[リソース]>[現状のプロジェクトのトリガー]から行います。


最初は何も設定されていないので、ダイアログに表示されているリンクをクリックして設定画面を開きます。

2015年7月3日金曜日

Google AnalyticsのデータをGoogle Apps Scriptを使ってSpreadsheetに出力する

はじめに

こんにちは、井下です。

本ブログでは過去に数回、Google AnalyticsとGoogle Apps Scriptの連携について触れていますが、顧みてみると実装方法についてあまり説明していませんでした。そこで、今回はGoogle AnalyticsとGoogle Apps Scriptの連携させる際の実装方法について、具体的なコードを交えて説明していきます。

また、初歩的な手順についても説明していきますので、Google Analyticsを使ってるけど、Google Apps Scriptって難しそうで分からない、という方もご参考ください。

ちなみに…。
Google AnalyticsとGoogle Apps Scriptの連携させる意義ですが、大きく2つあると考えています。

  1. 定期的にデータを出力させることで、計測したいデータの推移をすぐ見られるようにする
  2. 3つ以上のディメンションを組み合わせたデータを分析したい

1つ目は計測したいデータが決まっていて、なおかつ分析手法も確立されている状態で、データだけ定期的に欲しいというパターンですね。手動でもデータを取ることはできますが、決まりきったデータの取得はやはり自動化したいものです。

2つ目はGoogle Analyticsの仕様が絡んでくるお話です。
Google Analyticsを利用している方はご存じだと思いますが、Google Analyticsはメインとなっている指標(プライマリディメンション)に、もう一つの指標(セカンダリディメンション)を絡めて、細分化したデータを見ることができるようになっています。

例えば、下図はプライマリディメンションに"キーワード"(オーガニック検索キーワード)、セカンダリディメンションに"地域"を選択しています。つまり、ブラウザからの検索キーワードごとに、どの地域(日本であれば都道府県レベル)からの参照が多いのかが分かるデータが表示されています。

では、さらにどんなユーザが参照しているのかの手がかりとして、"ネットワークドメイン"を指標として細分化したデータが見たくなります。が…。

Google Analyticsの画面からでは、セカンダリディメンション以降のディメンションを設定してデータを細分化することができません。(2015年7月時点)
この仕様は詳細な分析をしたい人にとって、意外と大きい落とし穴になっているのではないでしょうか?

ただし、その仕様はあくまで画面上からの操作に限られるようで、実はGoogle AnalyticsとGoogle Apps Scriptを連携させることで、3つ以上のディメンションを組み合わせたデータを出力させることができます。
セカンダリディメンションまでだと、分析し足りない!と考えている方は、Google Apps Scriptを学ぶ価値が大いにあるということです。


以降は実際にGoogle AnalyticsとGoogle Apps Scriptを連携させる手順について説明します。
以前も書いた内容&前提の準備が含まれていますので、ご存知の方はページ中段までお進みください。

手順は以降の順に説明していきます。

Google Apps Scriptを使う準備
Google Apps ScriptからGoogle Analyticsを使う準備
Google AnalyticsのデータをGoogle Apps Scriptで取得する

2015年4月23日木曜日

Fusion Tables×Google Apps Script (マッピング編2) ~Google Analyticsのデータをインプットに、Fusion Tablesでマッピングする~

こんにちは、井下です。

少し間が空いてしまいましたが、今回の内容は前回予告していた通り、Google Analytics・Fusion Tables・Google Apps Scriptの3つを組み合せ、Google AnalyticsのデータをFusion Tablesに持ってきて、マッピングをできるようにしてみます。

なお、次回からはFusion Tables以外の話を書くつもりです。
気が付けばFusion Tables関連で6回もやっていました。ゴールをどこにしようか迷っていたとかじゃありませんよ。

ちなみに今まで書いた内容はこちら


実装したい内容の手動実行
実装を行う前に、具体的にどんなことを行おうとしているのかを、手動で実演してみます。
実装内容だけ知りたいという方は、ページ下部まで進んでください。

今回、実現したいことは、「Google Analyticsのデータを都道府県別に色分けできる状態にしたマップを作成する」ことの自動化です。

それを手動で行おうとすると、次のような手順を踏むことになります。
  1. Google Analyticsから地域別のデータをFusion Tablesに移行する
  2. 移行したデータの入ったテーブルと、都道府県名+都道府県の領域の情報が入ったテーブルをマージする
なお、"都道府県名+都道府県の領域の情報が入ったテーブル"に関しては、前回のブログに書いてありますので、詳細についてはそちらご参照ください。


まず、Google Analyticsから地域別のデータを表示します。
なお、例として利用しているデータは"国"に"Japan"を指定しているので、都道府県別のデータが表示されています。


Google Analyticsのエクスポート機能を使ってFusion Tablesへ移行したいのですが、Google Analyticsから直接Fusion Tablesへはエクスポートできません。
代替手段として、一度スプレッドシートへエクスポートし、Fusion Tablesからスプレッドシートのデータをインポートします。

なお、Google Analyticsは表示されている1ページ分のデータしかエクスポートしてくれないので、表示行数を調整して、欲しいデータが入るようにしておきましょう。



スプレッドシートへのエクスポートを選択すると、確認画面が開きます。問題がなければ"はい。データをインポートします"を選択します。


エクスポートに成功したので、作成されたスプレッドシートを確認してみます。


次はスプレッドシートのデータをFusion Tablesにインポートします。
Fusion Tablesの新規作成から"Google Spreadsheets"を選択し、先ほど作成したスプレッドシートをインポート対象にします。


スプレッドシートからインポートする場合、何行目をカラムとして見なすかを選択します。


スプレッドシートでは6行目にカラム名が記入されていたので、"6"を選択しました。


テーブル名などを新規作成前に設定できますが、特に変更せずに"Finish"を選択します。


これでようやくGoogle Analyticsから、Fusion Tablesへデータを移行することができました。


ただし、前回説明したように、この状態では都道府県ごとのマッピングはできません。都道府県ごとの境界がどこからどこなのかを、レコードごとに与えなければなりません。

都道府県ごとの境界のデータを持つテーブルは前回作成していますが、境界のデータを1レコードずつ入力するのは非常に手間がかかるので、できれば避けたいところです。

そこでFusion Tablesのマージ機能を利用します。
Fusion Tablesのマージ機能を一般的なDBで言うなら、"結合ビューの作成"と言えるでしょうか。

今回はGoogle Analyticsからエクスポートしたテーブルをベースに、都道府県の境界データを持ったテーブルをマージしてみます。

マージ機能を使うには、"File"メニューの中段下あたりにある"Merge"を選択します。


マージする対象のテーブルを選択する画面が開くので、都道府県の境界データを持った"Japan"テーブルを選択します。(前回作成していたテーブルで、デフォルトで用意されているわけではないので注意)


テーブルを選択すると、2つのテーブルから、それぞれカラムを選択する画面が開きます。
ここで選択したカラム同士で、合致するデータがあるレコードのみ表示するビューを作成することになります。


それぞれ都道府県名が入ったカラムを選択してみましたが、ここで1つ問題が発生しました。
Google Analyticsからエクスポートしたテーブルでは、都道府県名の後ろに"Prefecture"が付いていることがありますが、もう片方のテーブルではそういった文字列は付いていません。

このままではカラム同士のデータ合致判定が思った通りに機能してくれません。


仕方がないので、どちらかのデータを修正します。
手早く修正するために、Google Analyticsからエクスポートしたスプレッドシートの" Prefecture"を一斉置換で削除し、新しくテーブルを作成することにします。
(Fusion Tablesだと1つずつしかレコードを修正できず、SQLの発行もGoogle Apps Scriptなど外部実装を介さなくてはできないので、少し時間がかかります)



データを修正したテーブルで改めてマージをしてみます。互いに都道府県名の入ったカラムを選択します。


次にどのカラムを表示するのかを選択します。Google Analyticsのカラムはとりあえず全て表示させておきますが、もう片方のテーブルで欲しいカラムは、都道府県の境界データを持ったカラムだけなので、それ以外のカラムのチェックを外します。


これでMergeを選択すると、設定した条件のビューが作成されます。


Google Analyticsからエクスポートしたテーブルをベースとして、都道府県の境界データの入ったカラムが追加されています。(一番右のカラム)


このビューのマップ表示をしてみると、まだ数値ごとの色分けこそされていませんが、都道府県が赤で塗られています。(赤で塗られていないところは、データが存在しないことを示しています)
ここまで来れば、後はどのカラムを色分けの基準にするか、どんな値ごとに色分けするかを設定するだけです。




ここまでかなり長くなりましたが、やりたいことのイメージとしては、Google Analyticsのデータをインプットとして、日本地図に色が塗られているテーブルを、ひと月ごとに自動作成してくれる実装です。



実装による自動化
手動で行った手順を元に実装していきます。ただし、手動とは違ってわざわざスプレッドシートに一度エクスポートする必要はありません。また、手動で修正していた都道府県名の" Prefecture"の削除も内部処理で一括して行います。

2015年3月19日木曜日

Fusion Tables×Google Apps Script (マッピング編)

こんにちは。井下です。

今回はFusion Tables最大の特徴と言えるマッピングについて書きます。
点でなく、地域の境界でのマッピングについても取り扱います。

点のマッピング
Fusion Tablesを取り上げた最初の記事に、下の画像のようなマッピングを行いました。

このFusion Tablesに入っているデータは都道府県名と人口の数値だけが入っているシンプルなものですが、特別な操作をしなくともマッピングされていました。

ただし、種も仕掛けもなく、都道府県名を位置情報として認識しているわけではありません。
Fusion Tablesのカラムには"Location"という型があり、その型で定義されているカラムの値は位置情報として認識します。
そして、Fusion Tablesでは"東京"や"大阪"など、特定の地名を"Location"として定義したカラムに入れると、その文字から点で表せる位置情報に変換してくれるようになっています。

そのため、特に意識せずとも都道府県を点で表示したマッピングがされていたのです。


お手軽にマッピングができる素晴らしい機能ですが、やはりマッピングするのであれば、地域の境界ごとに色分けしてみたいですね。


地域の境界ごとのマッピング
"Location"に入れられるデータは、地名の文字列だけではなく、"KML"という形式のデータを挿入することができます。この"KML"という形式のデータが、地域の境界を表すデータとして機能します。
そのため、地域ごとで区分したマッピングをするには、大まかに以下の手順を踏むことになります。

2015年3月12日木曜日

Fusion Tables×Google Apps Script (Webアプリケーション作成編2)

こんにちは、井下です。

前々回はFusion TablesのAPIを利用して、自前のWebアプリケーションからFusion Tablesへデータを追加したり、参照できるようにしました。
今回はそこから拡張して、操作の対象となるテーブルを選択できるようにしたり、テーブル自体を削除できるように実装していきます。

実装内容
今回は全て説明していると長くなってしまうので、Fusion Tables APIの利用における部分を中心に、コードを元に説明していきます。

2015年2月18日水曜日

Fusion Tables×Google Apps Script (Webアプリケーション作成編1)

こんにちは、井下です。

個人的に冬⇒春は寒気⇒花粉のコンボで毎年苦しめられるのですが、みなさんはいかがでしょうか。
早く夏来ないかなぁ…。


前回はGoogle Apps ScriptでFusion Tables APIを利用するところまで書きましたが、
今回と次回でWebアプリケーション化を行い、それ以降は速度の検証や
マッピング機能について詳細に書いていく予定です。

実装する内容
繰り返しになりますが、前回はテーブルから"SELECT"で値を参照し、"INSERT"で値の挿入を行いました。
今回はそのWebアプリケーション化ということですが、Fusion TablesだからAPIの使い方が変わるような部分はありません。

実際のコードを以下の通りです。

fusionTableAPI.gs(サーバサイドの処理)
function doGet() {
  var output = HtmlService.createTemplateFromFile('select');
  return output.evaluate();
}

function select(){
  var tableId = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
  var sql = 'SELECT name, value FROM ' + tableId;
  var res = FusionTables.Query.sql(sql);
  
  return res.rows;
}

function insert(form){
  var tableId = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
  var name = form.name;
  var value = form.value;

  var sql = 'INSERT INTO ' + tableId + '(name, value) VALUES (\'' + name + '\'' + ',' + value + ')';
  var res = FusionTables.Query.sql(sql);
  
  return 'データを追加しました'
}

function getPageHtml(page){
  var output = HtmlService.createTemplateFromFile(page);
  return output.evaluate().getContent();
}

select.html("SELECT"による結果表示画面)
<script>
  function transitionPage(resultHtml) {
    var outputDiv = document.getElementById('html');
    outputDiv.innerHTML = resultHtml;
  }
  
  function onSuccess(message){
    alert(message);
  }
</script>  

<div id="html">
<h2>データ一覧</h2>
<form>
  <p><input type="button" value="データ追加" onclick="google.script.run.withSuccessHandler(transitionPage).getPageHtml('insert')"></p>
<table border=1>
<?
  var datas = select();
  for(var data in datas){
    output.append('<tr><td>' + datas[data][0] + '</td>');
    output.append('<td>' + datas[data][1] + '</td></tr>');
  }
?>
</table>
</form>
</div>

insert.html("INSERT"による入力画面)
<div id="html">
<h2>データ追加</h2>
<form>
  <p><input type="button" value="データ追加" onclick="google.script.run.withSuccessHandler(onSuccess).insert(this.parentNode)">
  <input type="button" value="データ一覧" onclick="google.script.run.withSuccessHandler(transitionPage).getPageHtml('select')"></p>
  <table border=1>
    <tr>
      <th>都市名</th>
      <th>人口</th>
    </tr>
    <tr>
      <td><input type="text" name="name"></td>
      <td><input type="text" name="value"></td>
    </tr>
  </table>
</form>
</div>

赤字、青字の部分はそれぞれ"SELECT"と"INSERT"のメソッド及び呼び出し箇所です。
特に通常のWebアプリケーションと変わりなく呼び出すことができます。

selectメソッドとinsertメソッドの中身が前回と変わっている点としては…
  • select:"select.html"で表示させやすいように、"res.rows"を返している(登録されているデータのみで構成された配列が返るようになります)
  • insert:SQL文内部で変数に対応するようになっている

若干前回と変わりはあるものの、Webアプリケーションにするうえでの表示の配慮や、変数への対応くらいの変更に収まっています。

緑字の部分は非同期で画面を切り替えるための処理を示しています。
Google Apps Scriptの難点としても挙げられますが、単純な<a href>などによる画面遷移ができないため、
ボタンをクリックされたら、対象のHTMLの情報を読み取り、中身を書き換えるようにしています。


では、画面での処理の流れを見てみましょう


select.htmlでFusion Tablesに登録されたデータを取得し、一覧表示します。
Webアプリケーションとして開いた場合、まずこの画面が開くようになっています。



上記のselect.htmlから"データ追加"をクリックすると、insert.htmlに画面が切り替わります。

入力フィールド2つに入力し、"データ追加"をクリックすることで、データが実際のFusion Tablesに入ります。


select.htmlに戻ると、先ほど入力したデータがそのまま入っています。

単純ではありますが、これでFusion TablesとGoogle Apps Scriptを用いてWebアプリケーションを作ることができました。

ただ、これでは流石に単純過ぎるので、次回もう少し機能を増やしたものを作ってみます。
例えば、自分が作ったテーブルから、参照するテーブルを選んだり、テーブル自体を作成・削除できるようにしたり…

主にFusion Tables APIの機能をもっと使ったものを作成する予定です。

2015年2月13日金曜日

Fusion Tables×Google Apps Script (Google Apps Script連携編)

こんにちは、井下です。

前回はFusion Tablesについてご紹介しましたが、
今回はGoogle Apps Scriptとの連携方法について書いていきます。

Google Apps ScriptでFusion Tablesを使う準備
Google Apps Scriptで早速Fusion Tablesを使ってバリバリ実装… と行きたいのですが、
実は現在(2015年2月)、Google Apps ScriptでFusion Tablesを使うには、
Fusion TablesのAPIを有効にしなくてはなりません。

設定は前回やったじゃないか!、と言われそうですが、前回の設定はドライブの設定です。
今回やろうとしている設定は、Google Apps Scriptの設定です。

ややこしいですが、前回の設定はドライブからFusion Tablesを作成するためで、
今回の設定はGoogle Apps ScriptからFusion Tablesを操作するために行います。


2015年2月6日金曜日

Fusion Tables×Google Apps Script (Fusion Tables利用編)

こんにちは。井下です。

寒さもそろそろ落ち着くかなと思っていましたが、東京にも雪が降ったりとまだまだ落ち着きそうにないですね。

今回は前回予告した通りにFusion Tablesについて取り上げます。

今回はFusion Tablesについての説明を主に書いていき、次回以降でGoogle Apps Scriptと連携してみようと考えています。

Fusion Tablesとは
簡単にまとめると、Googleが提供している地図情報と連携できるデータベース(正確に言うと、"データベース"はなく、テーブルでデータを管理するデータストア)です。
Googleの公式サイトでの説明はこちら

地図情報と連携できる点が特徴の1つなのですが、地図と連携せずにすぐに使えるデータベースとしても利用できます。

Googleから連携可能としているGoogleサービスは以下の4つです。
  • Maps API(地図情報の利用)
  • Chart Tools API(グラフの作成)
  • Google Drive Web APIs(Googleドライブの操作)
  • Google Apps Script
データベースということで、データの取得や保存もスプレッドシートよりも早いことも期待できますね。
スプレッドシートと比較して、どれくらい早くなるのかも検証しようと思います。


注意点としては、2015/2時点では試験運用として公開されているため、仕様が急激に変わる、制限がきつくなるなどが考えられます。

とはいえ、すぐにデータベースが使えるようになるというのは大きいメリットです。
新人研修などでデータベースを学習したいけど、データベースの導入で手間取るリスクがある人には嬉しいところです。

現状の利用方法としては、データベースの学習用・短期間での活用が現実的なところではないでしょうか。

Fusion Tablesを利用する準備
ここからは実際にFusion Tablesを使ってみる手順について、画像を交えて説明していきます。


2015年1月23日金曜日

Google Apps Script "getValues"のベストな範囲指定の模索

こんにちは、井下です。
今回もGoogle Apps Scriptについて書いていきます。

以前も書いたことがありますが、スプレッドシートの値を取得する場合は、
厳密に1つずつ取得するより、範囲を指定して1度に取得する方が早くなります。
※Google Apps Scriptの処理速度検証

極力getValueでなく、getValuesを使おうという話ですね。

ただし、取得できるのはN×Mの範囲しか指定できないので、
次みたいな場合はどう取得するのが一番早いんだろうとちょっと悩みませんか?(私だけ?)

※100×100のデータ中、セルが緑色の部分のデータ(A1~CV1、A2~A100、AN2~AN100)が欲しい

2015年1月7日水曜日

Google Apps Scriptで自動的に連絡先のグループを作りたい! その2

新年、明けましておめでとうございます。

引き続きA-AUTO 50を担当する井下です。

昨年の終わりごろ、初期型のPS3がYLOD(いわゆるソニータイマー)でお亡くなりになったので、
期待と不安を胸にPS4を買ってみましたが、意外とコンパクトなのですね。

ハードウェアとソフトウェアの進化の賜物なのでしょうけど、
限界まで進化したらどんなサイズになるんでしょうか。箱ティッシュくらいかな。

2014年12月9日火曜日

GoogleAppsScriptをさわってみた ~Sitesを使ってみる編~

~こんにちは!~


みなさま、お久しぶりです。
渡辺です。

前回はスプレッドシートを使ってLanguageのAPIを使ってみました。
(前回の記事はコチラから!⇒GoogleAppsScriptをさわってみた ~APIを使ってみる Language編~)


さて、今回は少し気分を変えてみたいと思います。


2014年12月2日火曜日

Google Apps Scriptで自動的に連絡先のグループを作りたい! その1

こんにちは、最近はA-AUTO 50のリモートライセンスで奔走している井下です。


唐突ですが、みなさんはGメールを複数人に送りたい場合はどうされていますか?
オートコンプリートを駆使して1人ずつ入力したり、過去に送信したメールの送信先からコピペをしたり、色々な方法があると思います。

ただ部署宛のような毎回送信先が同じで、それなりに頻度が高い場合は、Googleで用意されている「連絡先」でグループを利用されることが多いのではないでしょうか。

会社によっては、情報システム部門の方が用意&更新してくれいて、自分が意識せずとも使えるようになっているかもしれませんね。

ただ、個人でグループを利用しようと思っても、ちょっと面倒くさいなと感じてしまうところがあったり…。
日頃の送信先は大体決まっていますが、プロジェクトや用途によって微妙にメンバーの増減が発生するので、それを1つずつグループ作成していこうというモチベーションがいまいち湧いてきません。

そこで、こんな感じのシステムがあればなと妄想してみました。

自分の送信メールから、送信先の情報を取得して(だいたい最新1週間分くらい)、グループとして作成してくれるWebアプリ

前置きが長くなりましたが、今回と次回の2回で、メール・グループ作成のWebアプリを作っていこうと思います。


2014年11月18日火曜日

GoogleAppsScriptをさわってみた ~APIを使ってみる Language編~

~こんにちは!~

みなさま、お久しぶりです。
渡辺です。

前回は、スプレッドシートをつかってGmailのAPIを利用してみました。
(前回の記事はコチラから!⇒ GoogleAppsScriptをさわってみた)

今回も引き続き、スプレッドシートと他のAPIを連携させてみたいと思います!


2014年10月29日水曜日

Google Apps Scriptの処理速度検証

~はじめに~

 はじめまして。A-AUTO 50開発チームの井下と申します。

 A-AUTO50以外にも様々な技術の研究を行っており、
 ブログにはGoogle Apps Scriptを主な題材として投稿させていただきます。

 Google Apps Script自体については、こちらをご参照ください。


2014年10月27日月曜日

Google AnalyticsとGoogle Apps Scriptの連携

はじめまして、竹内です。
A-AUTO 50のWebサイト周りを担当しています。


A-AUTO 50ってなに?Webサイト?っていう人はこのページの右側にリンクがあるので、是非クリックしていってくださいw


今回は私も初めての投稿なので、A-AUTO 50関連の内容にしようと思います。
と言っても、Webサイト構築ではなくGoogle AnalyticsとGoogle Apps Scriptを使ったログの自動収集について。