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

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

ただいまの
回答率

90.32%

【GAS】マイドライブにあるスプレッドシートをExcelに変換して、対象者へ自動でメールを送信する方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 6,281

TS8332

score 11

【やりたいこと】
マイドライブにある指定のスプレッドシートを毎日指定の時間になったら、Excel形式へと変換して対象者へとメールを自動送信する方法を実現させたいと考えております。

【これまでに】
https://teratail.com/questions/16326
上記のteratailが似たような事をやっているのではないかと思い試していますが上手くいきません。 私のやり方が間違っているのかも分からない状態です。

メールはうまく発行できるのですが、何も添付されていない状態です。
そもそも使い方が間違っているのでしょうか・・・・。

何か良い方法がありましたらご教示いただければ幸いです。 
宜しくお願いいたします。

【参考コード】

function sendMail_Excel2() {
  // フォルダ、ファイル関係
  var targetFolderIds = ["folder1", "folder2", "folder3", "folder4", "folder5"];
  var targetFolder;
  var folderName;
  var objFiles;
  var objFile;
  var fileName;
  var key;

  // メール関係
  var mailto = "@gmail.com";
  var subject = "[GoogleDrive]定期バックアップ(" + Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + ")";
  var body = "";

  // その他
  var nowDate = Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd');
  var fetchUrl;
  var fetchOpt = {
    "headers" : { Authorization: "Bearer " + ScriptApp.getOAuthToken() },
    "muteHttpExceptions" : true
  };

  var xlsxName;
  var attachmentFiles = new Array();

  try
  {
    for (var i = 0; i < targetFolderIds.length; i++) {
      // Idから対象フォルダを取得
      targetFolder = DriveApp.getFolderById(targetFolderIds[i]);
      folderName = targetFolder.getName();
      body = body + folderName + "\n";

      // 対象フォルダ以下のSpreadsheetを取得
      objFiles = targetFolder.getFilesByType(MimeType.GOOGLE_SHEETS);

      while (objFiles.hasNext()) {
        objFile = objFiles.next();
        key = objFile.getId();
        fileName = objFile.getName();
        body = body + " - " + fileName + "\n";

        xlsxName = fileName + "_" + nowDate + ".xlsx";
        fetchUrl = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + key + "&amp;exportFormat=xlsx";
        attachmentFiles.push(UrlFetchApp.fetch(fetchUrl, fetchOpt).getBlob().setName(xlsxName));
      }
    }
  }
  catch(e){
    subject = "ERROR:" + subject;
    body = "エラー : " + e.message;
  }

  // メール送信
  MailApp.sendEmail(mailto, subject, body, {attachments:attachmentFiles});
}

【うまく動作しないコード】
上記参考コードの内、ファイルIDとメールアドレスさえ修正しておけば、
スプレッドシートがExcel形式に変換されて、添付メールとなって送る事が出来ると思ったのですが・・・・・。
すみません。GASに触れる事が今回初めてなもので。

function sendMail_Excel2() {
  // フォルダ、ファイル関係
  var targetFolderIds = [”対象のスプレッドシートのファイルIDを入力"];
  var targetFolder;
  var folderName;
  var objFiles;
  var objFile;
  var fileName;
  var key;

  // メール関係
  var mailto = "自分のメールアドレスを入力@gmail.com";
  var subject = "[GoogleDrive]定期バックアップ(" + Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + ")";
  var body = "";

  // その他
  var nowDate = Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd');
  var fetchUrl;
  var fetchOpt = {
    "headers" : { Authorization: "Bearer " + ScriptApp.getOAuthToken() },
    "muteHttpExceptions" : true
  };

  var xlsxName;
  var attachmentFiles = new Array();

  try
  {
    for (var i = 0; i < targetFolderIds.length; i++) {
      // Idから対象フォルダを取得
      targetFolder = DriveApp.getFolderById(targetFolderIds[i]);
      folderName = targetFolder.getName();
      body = body + folderName + "\n";

      // 対象フォルダ以下のSpreadsheetを取得
      objFiles = targetFolder.getFilesByType(MimeType.GOOGLE_SHEETS);

      while (objFiles.hasNext()) {
        objFile = objFiles.next();
        key = objFile.getId();
        fileName = objFile.getName();
        body = body + " - " + fileName + "\n";

        xlsxName = fileName + "_" + nowDate + ".xlsx";
        fetchUrl = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + key + "&amp;exportFormat=xlsx";
        attachmentFiles.push(UrlFetchApp.fetch(fetchUrl, fetchOpt).getBlob().setName(xlsxName));
      }
    }
  }
  catch(e){
    subject = "ERROR:" + subject;
    body = "エラー : " + e.message;
  }

  // メール送信
  MailApp.sendEmail(mailto, subject, body, {attachments:attachmentFiles});
}

sgr-2様のアドバイス後下記の通り修正を行い、
添付のあるメールを送る事までは出来ましたが、
添付されたExcelには、データはなく開く事もできませんでした。
もしかしたらでもなく、まだ余計なコードを書いてしまっているのかもしれません。

function sendMail_Excel() {
// フォルダ、ファイル関係
var targetFileId = ["スプレッドシートのファイルID"];
var targetFolder;
var folderName;
var objFiles;
var objFile;
var fileName;
var key;

// メール関係
var mailto = "自分のアドレス@gmail.com";
var subject = "[GoogleDrive]定期バックアップ(" + Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + ")";
var body = "";

// その他
var nowDate = Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd');
var fetchUrl;
var fetchOpt = {
"headers" : { Authorization: "Bearer " + ScriptApp.getOAuthToken() },
"muteHttpExceptions" : true
};

var xlsxName;
var attachmentFiles = new Array();

// 添付するファイルの名前を指定
xlsxName = "付けたい名前.xlsx";

try
{
fetchUrl = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + targetFileId + "&amp;exportFormat=xlsx";
attachmentFiles.push(UrlFetchApp.fetch(fetchUrl, fetchOpt).getBlob().setName(xlsxName));
}
catch(e){
subject = "ERROR:" + subject;
body = "エラー : " + e.message;
}

// メール送信
MailApp.sendEmail(mailto, subject, body, {attachments:attachmentFiles});
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2016/08/09 00:02

    具体的にコードを質問文に追記いただいたほうが回答を得られやすいと思います。

    キャンセル

  • asahina_dev

    2016/08/09 00:04

    そのうまく言ってないコードを貼り付けようもちろんコードブロック付きでね

    キャンセル

  • TS8332

    2016/08/09 00:37

    Kei344様・asahina_dev様 早速の質問へのアドバイスありがとうございます。
    それでは、アドバイス通りにコードを質問事項に書き込ませていただきます。

    キャンセル

  • kei344

    2016/08/09 00:46 編集

    コードはasahina_devさんのおっしゃるように、コードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「</>」ボタンを押すとコードブロックになります。

    キャンセル

回答 1

checkベストアンサー

0

TS8332さん
こんばんは。

「うまく動作しないコード」見せて頂きました。
参考頂いたコード側ですが、以下のように書いている通り
対象スプレッドシートについてフォルダ指示の形式をとっています。

var targetFolderIds = ["フォルダのID",...]

対して、うまく動作しないコードの側では

var targetFolderIds = ["対象のスプレッドシートのファイルIDを入力"];


のように記述している事から、「直接スプレッドシートを指示する」が
実現したい事になるでしょうか?

であるとすれば。の前提になりますが、参考頂いたコードの処理には
不要な部分が出てきてしまい、それがそのまま残っていて
「ファイルのIDに対してフォルダ絡みの処理をさせようとしている」
が直接的な原因になるかと思います。

具体的には、以下が該当します。

// 先ず、フォルダでループを回している(29行目から)
for (var i = 0; i < targetFolderIds.length; i++) {
    targetFolder = DriveApp.getFolderById(targetFolderIds[i]); // ←躓くはず


// フォルダに属する(タグ付けされた)スプレッドシートを列挙している(35行目から)
objFiles = targetFolder.getFilesByType(MimeType.GOOGLE_SHEETS);
while (objFiles.hasNext()) {
    objFile = objFiles.next();
    key = objFile.getId();
    (省略)
}

ご質問頂いている文面からですと、送信対象のスプレッドシートが1つなのか複数なのかが分かりませんが、仮に1つならループはまったく必要なく、以下のように書けると思います。(主要部分のみ)

// 対象がファイルなので、targetFolderIdsは変更しておきますね。
var targetFileId = "対象スプレッドシートのID";

// 添付するファイルの名前を指定
xlsxName = "付けたい名前.xlsx";

try
{
    fetchUrl = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + targetFileId + "&amp;exportFormat=xlsx";
    attachmentFiles.push(UrlFetchApp.fetch(fetchUrl, fetchOpt).getBlob().setName(xlsxName));
}
catch(e){
    // 省略
}

// メールの送信
MailApp.sendEmail(mailto, subject, body, {attachments:attachmentFiles});


実際に動作の確認までは出来ていないのですが、大丈夫ではないかと思います。。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/24 16:57

    sgr-2様 
    御連絡が遅れてしまい申し訳ございません。
    アドバイスどおりスクリプト修正後、処理を実行した処、マイドライブよりスプレッドシートをExcel形式に変換して添付メールを送る事は成功し、問題となっていた添付のファイルを開けない問題も解決されました。 ありがとうございます。
    しかし、一部Google関数を使用しており、その内『IMPORTRANGE』を使用しているセルのみ結果がエラーとなっている箇所があります。
    当然の結果ではあるのですが、マイドライブから対象のファイルをメールへと添付する際に、データの形式を全て値に変える方法などもご教授いただけると、問題解決に至れるかと思います。
    また、可能であればの話しではありますが、データの形式を値に変えるのは、指定のセル範囲のみでお願いします。

    キャンセル

  • 2016/08/25 13:58

    こんにちは。
    先ずは、Excel形式で添付して正常に開く事が出来るようになったとの事、良かったです。

    一括で式(IMPORTRANGE等)を結果の値(Value)に置き換える方法については、すいませんが私には分かりません。(存在するかどうかのレベルから)

    少々泥臭くなりますが、例えば以下のように書いて指定セルの「値」「式」を取得できますので、それを利用する手はあると思います。
    ---
    var ss = SpreadsheetApp.openById(targetFileId);
    var sheet = ss.getActiveSheet(); // 仮にアクティブシートを対象
    var range = sheet.getRange("A1"); // 仮にA1セルを対象

    var value = range.getValue(); // 値
    var formula = range.getFormula(); // 式
    // 確認用にログへ
    Logger.log(value);
    Logger.log(formula);
    ---

    オリジナルのセルの値を上書きしてはいけないと思いますので、
    (a)添付前に対象スプレッドシートの複製を作成し、複製したファイルのセルの値を上書き(getValueの結果で上書き)して、これを添付する
    (b)オリジナルのスプレッドシートにExport用のシートを追加し、メール送信のタイミングでExport用シートの値を最新の値に更新する(オリジナルシート側のgetValueの結果でExport用シート側のセルの値を上書き)
    等が方法として考えられると思います。


    (a)の方法なら
    ・添付対象となるスプレッドシートに複数のシートが存在する場合に(b)より楽
    ・メール送信(スクリプトが実行される)のタイミングで、複製を作成して送信後に複製を破棄する
    (b)の方法なら
    ・単一シートなら、Export用にシートを1つ追加するだけ(複数ならその数必要になる)
    ・都度、複製の作成と破棄が必要ない
    ・Export用シートのみでxlsxファイルを作って、オリジナル側のシート(エラーのあるセルが存在)を除外する

    キャンセル

  • 2016/08/25 15:37

    sgr-2様
    アドバイスありがとうございました。
    上記、アドバイスを元に色々と試させていただきます。
    なお、今回の質問はあくまでもGoogleドライブに保存されたスプレッドシートを、Excelの添付ファイルにしてスクリプトエディタのトリガーを使って自動送信であった為、問題は解決として、sgr-2様の回答をベストアンサーとして登録させていただきます。
    ありがとうございました。

    キャンセル

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

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

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

  • トップ
  • Excelに関する質問
  • 【GAS】マイドライブにあるスプレッドシートをExcelに変換して、対象者へ自動でメールを送信する方法