質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.54%

  • JavaScript

    16337questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Google Apps Script

    830questions

    Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Google apps Script使用の簡易申請フォーム、TypeErrorについて

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 78

bigi_bigi

score 0

 前提・実現したいこと

Google apps Scriptを使用して簡易休日申請ワークフローを作成したい。
ソースコードはエラーになっておらず、実行すると多数のエラーが出ています。

 発生している問題・エラーメッセージ

1、doPost    TypeError: undefined からプロパティ「shonin」を読み取れません。(行 3、ファイル「doPost」)    formSubmit
2、sendMail    TypeError: undefined のメソッド「forEach」を呼び出せません。(行 73、ファイル「doPost」)    formSubmit
3、doGet    TypeError: undefined からプロパティ「row」を読み取れません。(行 4、ファイル「doGet」)    formSubmit
4、headerKeys    TypeError: オブジェクト [object Object] で関数 getRange が見つかりません。(行 17、ファイル「getUser」)    formSubmit
5、rowToHash    TypeError: オブジェクト [object Object] で関数 forEach が見つかりません。(行 22、ファイル「getUser」)    formSubmit

 該当のソースコード

function getUserBy(key, value){
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sh = spreadsheet.getSheetByName('users');
  var values = sh.getDataRange().getValues();
  var keys = headerKeys(sh);

  for (var i = 0; i < values.length; i++) {
    var row = values[i];
    row = rowToHash(row, keys); 
    if (row[key] == value) {
      return row;
    }
  }
}
// ヘッダ行を取得
function headerKeys(sh) {
  return sh.getRange(1,1,1, sh.getLastColumn()).getValues()[0];
}
//行の情報をオブジェクトに変換
function rowToHash(array, keys) {
  var hash = {};
  array.forEach(function(value, i) {
    hash[keys[i]] = value;
  })
  return hash;
  console.log(e);
}
var URL = "https://script.google.com/a/ウェブアプリとして公開したこのソースのURL/exec";
var sheetName = "answers";

function sendFormMail(e){

  // 追加行
  var row = e.range.getRow(); 
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName(sheetName);

  var name = e.namedValues["氏名"];
  var user = getUserBy("name", name);

  // 承認者
  var authorizer= getUserBy("id", user['authorizer_id']);
  var address = authorizer['mail'];

  var cols = ["タイムスタンプ","氏名","申請日","休暇取得開始日","休暇取得終了日","休暇種類","理由/備考"];
  var body="";
  cols.forEach(function(col){
    body += col;
    body += ":"
    body += e.namedValues[col];
    body += "\n";
  });


  body += "url:"
  body += URL;
  body += "?row=" + row;
  body += "&name=" + encodeURI(authorizer['name']);

  MailApp.sendEmail(address,"休暇申請",body);
  console.log(e);
}
// 承認ページ表示時
function doGet(e) {
  //必要な値を画面に持たせておく
  var row = e.parameter.row;
  var name = e.parameter.name;
  var html = HtmlService.createTemplateFromFile("shonin");
  html.row = row;
  html.name = name;
  html.url = URL;
  html.method = "get";
  return html.evaluate();
  console.log(e);
}
function doPost(e) {

  var shonin = e.parameter.shonin;
  var row = e.parameter.row;
  var name = e.parameter.name;

  // シートに承認を記入
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName(sheetName);
  var values = sheet.getDataRange().getValues();

  var rowData = values[row-1];
  var idx = rowData.length;

  var status = "";
  var timestamp = Utilities.formatDate( new Date(), 'Asia/Tokyo', 'yyyy/MM/dd hh:mm:ss');

  var cur = -1;
  rowData.some(function(col,i){
    if (!col){//空の列を取得
      idx = i;
      return true;
    }
  });
  idx++;

  if (shonin == 1) {
    status = "承認";
  } else {
    status = "却下";
  }

  sheet.getRange(1, idx).setValue("状態");
  sheet.getRange(row, idx).setValue(status);
  idx++;

  sheet.getRange(1, idx).setValue("承認者");
  sheet.getRange(row, idx).setValue(name);
  idx++;

  sheet.getRange(1, idx).setValue("処理日次");
  sheet.getRange(row, idx).setValue(timestamp);

  // 承認者をメールに記載するため再取得
  values = sheet.getDataRange().getValues();

  if (shonin == 1) {

    // 次の承認者をさがす
    var user = getUserBy("name", name);
    Logger.log(user);

    var authorizer_id = user['authorizer_id'];

    if (authorizer_id) {//上位承認者がいる場合
      // 次の承認者にメール送信
      var authorizer = getUserBy("id", authorizer_id);
        sendMail(values, row, authorizer, true);
    }
  } else {
    // 申請者にメール送信
    var name = sheet.getRange(row, 2).getValue();
    var user = getUserBy("name", name);
    sendMail(values, row, user, false);
  }
  var html = HtmlService.createTemplateFromFile("complete");
  return html.evaluate();
}

function sendMail(values, row, user, approved){
  var rowData = values[row-1];
  var body="";
  rowData.forEach(function(col,idx){
    if (!col) return true;
    var key = values[0][idx];
    body += key;
    body += ":";
    if (['申請日','休暇取得開始日','休暇取得終了日'].indexOf(key) > -1) {
      body += Utilities.formatDate( col, 'Asia/Tokyo', 'yyyy年M月d日');
    } else if (['処理日時'].indexOf(key) > -1) {
      body += Utilities.formatDate( col, 'Asia/Tokyo', 'yyyy年MM月dd日 hh:mm:ss');
    } else {
      body += col;
    }
    body += "\n";
  });

  body += "url:"
  body += URL;
  body += "?row=" + row;
  body += "&name=" + encodeURI(user['name']);

  var address = user['mail'];
  var title = approved ? "休暇申請" : "休暇申請が却下されました";
  MailApp.sendEmail(address, title, body);
  console.log(e);
}
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
    table, td, th {
      border-collapse: collapse;
      padding: 0px;

      border: 1px black solid;
    }
    td {
          margin: 5px;
    }
    </style>
  </head>
  <body>
    <h1>休暇申請承認</h1>
    <? var html = ''; ?>
    <? var json = getRowData(row); ?>
    <table>
    <? for(key in json){    ?>
    <? if (!json[key]) break; ?>
    <tr>
        <td><?= key ?></td>
        <? if (['申請日','休暇取得開始日','休暇取得終了日'].indexOf(key) > -1) { ?>
                <td><?= Utilities.formatDate( json[key], 'Asia/Tokyo', 'yyyy年M月d日'); ?></td>
        <? } else { ?>
                <td><?= json[key] ?></td>
        <? } ?>
    </tr>
    <? } ?>
    </table>
    <form action="<?= url ?>" method="post">
      <input type="radio" name="shonin" value="1" checked="checked">承認
      <input type="radio" name="shonin" value="0">却下
      <input type="hidden" name="row" value="<?= row ?>">
      <input type="hidden" name="name" value="<?= name ?>">
      <input type="submit" value="送信">
    </form>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    処理が完了しました
  </body>
</html>

 試したこと

APIライブラリの追加(スクリプトエディタ、クラウドプラットフォーム両方)

 補足情報(FW/ツールのバージョンなど)

まだ業界に入って2ヶ月くらいで、解説サイトなどの文言も把握できていなくて逐一検索したりしながら手探りで行っています。
googleフォームで入力した情報をスプレッドシートへ保存。
(スプレッドシートにはデータ保存のanswersシートと、従業員情報のusersシートが2枚あります。)usersの情報を元に承認権限のあるもの(authorizer_id)にメールを送ってそのメールを開くと承認画面、と動かしたいのですが上記エラーで承認画面が開けません。

https://qiita.com/kwgch/items/e2f666806503af4bb695
https://gist.github.com/kwgch/942595bca5c7668fe3b97c86eed171d9

こちらを拝見して実装したので、コードは誤りはないと思うのですがなぜエラーが出るのか全く分かりません。お力添えいただけたら嬉しいです。なにとぞよろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • papinianus

    2018/09/28 18:12

    エラーが出ているのは、パラメータが正常に指定されていないからです((e)が渡されていない)。どのように実行したときに、どのエラーがでるか、操作とエラーを対応付けてください。また処理の流れをかいてください。多分sendformmailがきっかけじゃないかと思うのですが、urlは正常に作れていますか?webアプリケーションは最新バージョンに更新しなおしていますか?

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.54%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    16337questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Google Apps Script

    830questions

    Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。