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?

LINCRAFTAdvent Calendar 2023

Day 19

テキストファイルをスプレッドシートにアップロードする

Last updated at Posted at 2023-12-18

Agenda

  • はじめに
  • やりたいこと
  • どう実現するか
  • 実装
  • できた
  • さいごに

はじめに

O84です。
Excel(スプレッドシート)方眼紙にソースコードを貼り付ける機会、稀によくありますよね?
この記事ではアドカレ1日目で扱った内容の逆で、ファイルのアップロード処理を実装します。

やりたいこと

  1. ダイアログからファイルを受け取る
  2. ファイルを整形してスプレッドシートに反映する

どう実現するか

クライアント側でのファイル受付は適当にやる1 2
google.script.runを使ってファイルをサーバに渡す3
受け取ったファイルを任意の形式でスプレッドシートに反映する

実装

クライアント側

upload.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script type="text/javascript">
      async function uploadFiles() {
        const uploadFilesElement = document.getElementById("uploadFiles");
        const readFiles = [];
        for (let file of uploadFilesElement.files) {
          readFiles.push(
            readFile(file).then(function(file) {
              google.script.run
                .withSuccessHandler()
                .withFailureHandler()
                .file2Sheet(file);
            })
          );
        }
        await Promise.all(readFiles);
      }

      function readFile(file) {
        return new Promise((resolve) => {
          const reader = new FileReader();
          reader.onload = () => {
            resolve({
              name: file.name,
              data: reader.result
            });
          }
          reader.readAsText(file);
        });
      }
    </script>
  </head>
  <body>
    <div>
      <input type="file" id="uploadFiles" multiple>
    </div>
    <div>
      <button onclick="uploadFiles()">アップロードする</button>
    </div>
  </body>
</html>

サーバ側

main.js
function onOpen() {
  const ui = SpreadsheetApp.getUi();
  const menu = ui.createMenu('変換ツール');
  menu.addItem('ファイルアップロード', 'upload');
  menu.addToUi();
}

function upload() {
  const html = HtmlService.createTemplateFromFile('upload')
    .evaluate()
    .setWidth(510)
    .setHeight(400);
  SpreadsheetApp.getUi()
    .showModalDialog(html, 'ファイルをDrag&Dropしてください');
}

function file2Sheet(file) {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  
  // 同じ名前のシートが無かったら新しく作る
  let targetSheet = spreadsheet.getSheetByName(file.name);
  if (targetSheet == null) {
    targetSheet = spreadsheet.insertSheet();
    targetSheet.setName(file.name);
  } else {
    targetSheet.clearContents();
  }

  // なんやかんやしてシートに反映する
  file.data.split("\n").map((row, index) => {
    const cols = row.split("  ");
    targetSheet.getRange(index + 1, 1, 1, cols.length)
      .setValues([cols]);
  });
}

できた

image.png

google.script.runを並列で実行したらどうなるんだろ~?と思って試したら普通に動いたのでそのままにしている

一度に大量のファイルを送りつけると"シート[0-9]+_conflict[0-9]+"って名前のシートが生えてくるが、勝手に解決してくれるのでヨシ!

約20KBのファイルを30件同時に投げても問題なく動作したことを確認済み

さいごに

一緒に働く仲間を募集中です!

リンクラフト株式会社では、組織拡大に伴い積極的な採用活動を行っています。
少しでも興味がある方はぜひご連絡ください。

▽会社ホームページ
https://lincraft.co.jp/

▽SNS
X (旧Twitter)
Instagram
Facebook

▽ご応募はこちらより
https://lincraft.co.jp/recruit

※カジュアル面談も受付中です。ご希望の方はHPのお問い合わせフォームよりご連絡ください。

  1. input type="file" (Mozilla)

  2. jsでファイルの情報を参照する (Mozilla)

  3. google.script.run (Google Workspace)

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?