2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GASを使って日常の任意行為のログをGoogleSpreadSheetに保存しよう 作成編

Last updated at Posted at 2022-01-04

##追記

1/5
 chromeだとform要素にsubmitがなくてもエンターキーでsubmitされてしまう?ようなので入力フォームを修正しました。
 前ので作っちゃった人で困ってる人は現時点でのlog.htmlで更新してみてください。

##何?

  • 非エンジニア向け
  • 無料で
  • 日常行為のログをつけよう

です。
さっそくやりましょう。

##作ろう
###0.前提条件

  • GoogleDriveを知っている
  • アカウントも持っている
  • GoogleSpreadSheetを操作できる

あたりが前提条件になります。わからない人は頑張りましょう。

###1.準備
####新規シートの作成

GoogleDriveの任意の場所にログ保存用の新規スプレッドシートを作成してください。
その後、そのスプレッドシートに「ログ」「タグ」シートを作成してください。

image.png
左下がこうなっていればOKです。

####「ログ」シートの見出し
ログシートには左からタイムスタンプ、タイトル、作者、URL、メタデータ、タグ、タグ、タグ‥‥‥と記録されます。
なので見出しをつけると見やすいかもしれません。(つけなくてもいいです。)
image.png
例えばこうですね。

###2.コードのコピペ
さて、動作するコードをコピペで作っていきます。
まず、スプレッドシートの上にある「拡張機能」から、「Apps Script」を選びましょう。
image.png
こういうのが開きますね。
今コード.gsを開いているのですが、そこに以下のコードを上書きしてください。

コード.gs
const SpreadSheetID = "<SheetID>";
const LogSheetName = "ログ";
const TagCloudSheetName = "タグ";

const TimeZone = "Asia/Tokyo";
const TimeFormat = "yyyy/MM/dd HH:mm:ss";

function doGet(e) {
  if(SpreadSheetID === "" || SpreadSheetID === "<SheetID>"){
    const output = ContentService.createTextOutput();
    output.setMimeType(ContentService.MimeType.TEXT);
    output.setContent("エラー\nSpreadSheetIDを登録してください。\nGoogleSpreadSheetを作成し、シートを追加して「ログ」「タグ」シートを作成してください。\nその後、URL内のID部分をコピーして <SheetID> 部分にコピーしてください。\n");
    return output;
  }
  const logHtmlTemplate = HtmlService.createTemplateFromFile("log");
  const registedTags = getRegistedTags();
  let datalistInnerHTML = "";
  for(const tag of registedTags){
    datalistInnerHTML += '<option value="' + tag + '">\n';
  }
  logHtmlTemplate.tagdatalist = datalistInnerHTML;

  return logHtmlTemplate.evaluate();
}

function registFormdata(formdata){
  let tags = [];
  for(let i = 1;;i+=1){
    if(formdata["tag" + i]){
      tags.push(formdata["tag" + i]);
    }
    else{
      break;
    }
  }
  registLog(new Date(),formdata.title,formdata.author,formdata.url,tags,formdata.meta);
}

function registLog(date,title,author,url,tags,meta){
  const row = [
    Utilities.formatDate(date, TimeZone, TimeFormat),
    title,
    author,
    url,
    meta
  ].concat(tags);
  const sheet = SpreadsheetApp.openById(SpreadSheetID).getSheetByName(LogSheetName);

  const range = sheet.getRange(sheet.getLastRow() + 1,1,1,row.length);
  range.setNumberFormat("@");

  range.setValues([row]);
  //sheet.appendRow(row);

  registTags(tags);
}
function registTags(tags){
  const sheet = SpreadsheetApp.openById(SpreadSheetID).getSheetByName(TagCloudSheetName);
  let tagcloud = [];
  if(sheet.getLastRow() > 1){
    tagcloud = sheet.getRange(1, 1, sheet.getLastRow()).getValues();
  }
  for(const tag of tags){
    if(!tagcloud.includes(tag)){
      tagcloud.push(tag)
    }
  }
  let setrangedata = [];
  for(const tag of tagcloud){
    setrangedata.push([tag]);
  }
  if(tagcloud.length > 0){
    const range = sheet.getRange(1,1,setrangedata.length,1);
    range.setNumberFormat("@");
    range.setValues(setrangedata);
  }
}
function getRegistedTags(){
  const sheet = SpreadsheetApp.openById(SpreadSheetID).getSheetByName(TagCloudSheetName);
  let tagcloud = [];
  if(sheet.getLastRow() > 1){
    tagcloud = sheet.getRange(1, 1, sheet.getLastRow()).getValues();
  }
  return tagcloud;
}

しましたね。
そうしたら、一行目にある"<SheetID>"を設定します。
さっきのスプレッドシートに戻ってください。
image.png
URLにある「/d/XXXXXXXXXXXXXX/edit」の「XXXXXXXXXXXXXX」部分をすべてコピーします。
これがシートIDです。
"<SheetID>"を"XXXXXXXXXXXXXX"に上書きします。
image.png
こうですね。
コード.gsは以上です。

そうしたら、次にログを入力する画面をコピペします。
「ファイル」の横にある+をクリックしてください。
そしてHTMLを選択します。
image.png
こうです。
「log」と名前をつけてください。
image.png
こうです。
「log.html」となれば成功です。喜びましょう。
そして以下のhtmlを上書きコピペしてください。

log.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <form id="logform" onsubmit="return false;">
        <table>
            <tbody>
                <tr>
                    <th>Title</th>
                    <td>
                      <input type="text" name="title">
                    </td>
                </tr>
                <tr>
                    <th>Author</th>
                    <td>
                      <input type="text" name="author">
                    </td>
                </tr>
                <tr>
                    <th>URL</th>
                    <td>
                      <input type="url" name="url">
                    </td>
                </tr>
                <tr>
                    <th>Meta</th>
                    <td>
                      <textarea name="meta"></textarea>
                    </td>
                </tr>
                <tr id="tags">
                    <th>Tags</th>
                    <td id="tagarea">
                    </td>
                </tr>
                <tr>
                    <th>   
                    </th>
                    <td>
                      <input list="tagdatalist" type="text" id="taginput">
                      <datalist id="tagdatalist">
                        <?=tagdatalist?>
                      </datalist>
                      <button onclick="addtag();">追加</button>
                    </td>
                </tr>
            </tbody>
        </table>
        <input type="button" id="sendbutton" name="send" onclick="onSendClick();" value="登録する">
        <div hidden id="hiddenformdiv"></div>
    </form>
    <script>
      let tags = [];
      const addtag = () => {
        const taginput = document.getElementById("taginput");
        if(taginput.value){
          tags.push(taginput.value);
          taginput.value = "";
          drawTags();
        }
      }
      const drawTags = () => {
        const tagarea = document.getElementById("tagarea");
        tagarea.innerHTML = "";
        tags.forEach((tag)=>{
          const tagelement = document.createElement("div");
          tagelement.innerHTML = tag;
          tagelement.classList.add("taglabel");
          tagarea.appendChild(tagelement);
        });
      }
      const onSendClick = () => {
        const tagarea = document.getElementById("tagarea");
        const hiddenformdiv = document.getElementById("hiddenformdiv");
        tags.forEach((element,index)=>{
          const hidden = document.createElement("input");
          hidden.type = "hidden"
          hidden.name = "tag" + (index + 1);
          hidden.value = element;
          hiddenformdiv.appendChild(hidden);
        });

        document.getElementById("sendbutton").disabled = true;
        google.script.run.withSuccessHandler(succeedAlert).registFormdata(document.getElementById("logform"));
      }
      const succeedAlert = (result) => {
        window.alert("登録しました");
        document.getElementById("sendbutton").disabled = false;
        const hiddenformdiv = document.getElementById("hiddenformdiv");
        hiddenformdiv.innerHTML = "";
      }
    </script>
  </body>
</html>

しましたね。
おめでとう。コピペは終了です。
最後にセーブしてください。
Ctrl+Sか、左上のフロッピーとか言う知らん機械のマークです。
image.png
コード.gsとlog.htmlの左のオレンジ色がなくなればOKです。
image.png

###3.デプロイ
続いてデプロイします。
Webアプリにします。
Apps Scriptの画面の右上、「デプロイ▼」をクリックします。
そして「新しいデプロイ」を開きます。
image.png
開きましたね。
「種類の選択」の左の歯車をクリックし、「ウェブアプリ」を選択します。
image.png
そして設定はデフォルトのまま青い「デプロイ」をクリックします。
しばらく待つとスプレッドシートへのアクセス許可が出てくるので、許可します。
image.png
承認すると出てくるウインドウで「スプレッドシートを作成したアカウント」を選択し、「詳細を表示」から「無題のプロジェクト(安全ではないページ)に移動」をクリックします。
以下、私のメールアドレスが出ますがここは自分のアドレスが出るはずです。
image.png
その後出てくるウインドウではスプレッドシートを書き換える危いスクリプトだよって言われるので「許可」をクリックします。
image.png
めんどくさいですね。
元の画面に戻るので、しばらく待ちます。

最終的にこんなのが出るはずです。
image.png
お疲れさまでした。
このURLがアプリのURLです。保存しておいてください。

##ログを記録する
アプリのURLを開くと、こんな画面になるはずです。
image.png
ここに適宜入力して「登録する」を押すと、押した時点のタイムスタンプでログが登録されます。

##何に使うの?
読書記録とかにすれば良いんじゃないでしょうか?

ちなみにMetaは「何か」「ログ内容ではないが記録するもの」とかそういった感じの意味合いです。多分。
雰囲気でやってるので聞かないでください。

##記録を見たい
例えば「一日ごとにログ回数を見たい」場合、
1.別のシートに=TEXT('ログ'!A1,"yyyy/mm/dd")とかで転写するとyyyy/mm/dd形式で日時のみで転写できます。
image.png
2.適当な列に2022/01/01からオートフィルして日付を作成して、
3.隣に=COUNTIF(A:A,C1)みたいな式でオートフィルして数える
image.png
とかすればいいんじゃないですかね?
あるいはGASで表示用のページを作ることもできます。(いつか書くかもしれません。)

##改造編
もしかしたら他記事で

  • 記録内容を増やしたい
  • グラフとかタグ絞り込みログ回数とか表示するページが欲しい

とか書くかもしれません。
書かないかもしれません。

##何に使うの?
読書記録とか食事記録とかじゃないですか?

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?