スプレッドシートで書類作成を自動化する【GAS】

2020年6月26日

見積書とか、請求書とかを想定したツール。

Googleスプレッドシートで、Google Apps Scriptを使用。

スポンサーリンク

Googleスプレッドシート

ダウンロードリンクを使う。

Googleドライブのファイルダウンロード直リンクのつくりかた

こんな感じのテーブルを想定。

実行の様子

1.作成ボタンクリック

2.ドロップダウンリストで選択して、見積書 or 請求書を選択して、作成ボタンクリック

3.会社名とかの情報が挿入された見積書がGoogleドライブ上に保存されて、かつダウンロードされる

という感じ。

参考:
https://orihubon.com/2014/06/17/convert-row-array-to-hash-in-google-apps-script/
https://www.hop-step-engineering.com/googleappsscript/showmodaldialog/

コード

以下5つのファイルを用意。

create_document.gs

function EditDocument(number, template_id){
  const COPY_DEST_FOLDER_ID = CopyDestFolderId();
  var file_id = CopyTemplateFile(number, template_id, COPY_DEST_FOLDER_ID);
  var doc = DocumentApp.openById(file_id);
  var body = doc.getBody();

  var targetList;
  var list = Datalist();
  
  // 選択された番号のデータを取得
  for(var i = 0; i < list.length; i++){
    if(list[i]["番号"] == number){
      targetList = list[i];
      break;
    }
  }

  // 挿入する情報
  var name = (targetList["会社名"] == "")? targetList["名前"] : targetList["会社名"] + "\n" + targetList["名前"];
  var price = targetList["金額"];
  var quantity = targetList["数量"];
  var total = targetList["合計"];
  
  // 置換してダウンロードリンク生成
  body.replaceText("{name}", name).replaceText("{number}", number).replaceText("{price}", price).replaceText("{quantity}", quantity).replaceText("{total}", total);
  var downloadLink = "https://docs.google.com/document/d/" + file_id + "/export?format=doc";
  
  return downloadLink;
}


function CopyTemplateFile(num, file_id, folder_id){
  var templateFile = DriveApp.getFileById(file_id);
  var outputFolder = DriveApp.getFolderById(folder_id);
  var outputFileName = num + "_" + templateFile.getName();
  
  // テンプレートファイルをコピー
  templateFile.makeCopy(outputFileName, outputFolder);
  
  // コピー先のファイル一覧取得、コピーできていたらファイルIDを返す
  var files = DriveApp.getFolderById(folder_id).getFiles();
  
  for(var i = 0; files.hasNext(); i++){
    var file = files.next();
    if(file.getName() == outputFileName){
      return file.getId();
    }
  }
  return "";
}


function Datalist(){
  var list = [];
  var sheet = SpreadsheetObj();
  
  for(var i = 0; i < sheet.values.length; i++){
    var row = sheet.values[i];
    row = RowToHash(row, sheet.keys);
    list.push(row);
  }
  return list;
}


function ShowDialog(){
  // dialog.html をもとにHTMLファイルを生成
  // evaluate() は dialog.html 内の GAS を実行するため( <?= => の箇所)
  var html = HtmlService.createTemplateFromFile("dialog").evaluate();
  
  // 上記HTMLファイルをダイアログ出力
  SpreadsheetApp.getUi().showModalDialog(html, "ファイルダウンロード");
}


function SpreadsheetObj(){
  // 今開いているスプレッドシートを読み込み
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();

  // ヘッダーとデータ部分を読み取り
  var keys = HeaderKeys(sheet);
  var data = sheet.getRange(3, 1, sheet.getLastRow()-2, sheet.getLastColumn());
  // 値と背景色を取得
  var values = data.getValues();

  // Dictionaryのキーとデータを返す
  var obj = new Object();
  obj.keys = keys;
  obj.values = values;
  return obj;
}


/**
* returns keys located at top of spreadsheet 
*
* @param {sheet} sh Sheet class
* @return {array} array of keys
*/
function HeaderKeys(sh) {
  return sh.getRange(2,1,1, sh.getLastColumn()).getValues()[0];
}

/**
* Convert a row to key-value hash according to keys input parameter
*
* @param {array} array
* @param {array} keys
* @return {array} key-value mapped
*/
function RowToHash(array, keys) {
  var hash = {};
  array.forEach(function(value, i) {
    hash[keys[i]] = value;
  })
  return hash;
}

dialog.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('css').getContent(); ?>    
  </head>
  <body>
  <!---->
  <form name="dialog">
    <select name="numberList">
    <option>---選択してください---</option>
    <?
      var data = Datalist();
      for(var i = 0; i < data.length; i++){
        output.append('<option>' + data[i]["番号"] + '</option>');
      }
    ?>
    </select>
  <?
    const TEMPLATES = Templates();
    for(var i = 0; i < TEMPLATES.length; i++){
      output.append('<p>\n<label>\n');
      output.append('<input type="radio" name="documents" value=' + TEMPLATES[i]["id"] + '>' + TEMPLATES[i]["name"] + '<br>');
      output.append('</label>\n</p>\n');
    }
  ?>
  <div id="output"></div>
  <a id="download" class="square_btn" href="#" onclick="OnButtonClick()">作成</a>
  </form>
  <?!= HtmlService.createHtmlOutputFromFile('js').getContent(); ?>
  </body>
</html>

js.html

<script type="text/javascript" language="javascript">
function OnButtonClick(){
  var target = document.getElementById("output");
  var num = document.dialog.numberList.value;
  var radio = document.dialog.documents;
  
  for(var i = 0; i < radio.length; i++){
    if(radio[i].checked){
      target.innerText = num + "を作成中…";

      google.script.run.withSuccessHandler(DownloadFile).EditDocument(num, radio[i].value);
      function DownloadFile(link){
        window.location.href = link;
        target.innerText = "作成完了しました。ダウンロードします。"
        window.close();
      }
    }
  }
}
</script>

css.html

<style>
select{
  height: 30px;
  width: 200px;
}
.square_btn{
  position: absolute;
  right: 0;
  bottom: 4px;
  display: inline-block;
  padding: 0.5em 1em;
  text-decoration: none;
  background: #668ad8;/*ボタン色*/
  color: #FFF;
  border-bottom: solid 4px #627295;
  border-radius: 3px;
  }
.square_btn:active {/*ボタンを押したとき*/
  -ms-transform: translateY(4px);
  -webkit-transform: translateY(4px);
  transform: translateY(4px);/*下に動く*/
  border-bottom: none;/*線を消す*/
}
</style>

env.gs

/*
* テンプレートファイルの名前とファイルIDを記載。
* nameはモーダルウィンドウに表示される名前。
* idはコピー対象のファイルID。
*/
function Template(){
  const TEMPLATES = [{"name":"", "id":""}
          , {"name":"", "id":""}];
  return TEMPLATES;
}

/*
* テンプレートのコピー先のフォルダーIDを記載。
*/
function CopyDestFolderId(){
  const COPY_DEST_FOLDER_ID = "";
  return COPY_DEST_FOLDER_ID;
}
ninki_glog_ranking
ブログランキング・にほんブログ村へ

スポンサーリンク