上传文件并将 link 传递到电子表格的活动单元格中

Upload file and past the link into active cell a spreadsheet

正在尝试制作脚本来上传文件并将下载文件的 link 粘贴到 google 电子表格的活动单元格中。

在模式 window 中单击“上传”后,文件未写入 Google 驱动器,因此,link 未写入单元格

Code.gs

function onOpen() {
  SpreadsheetApp.getUi()
      .createMenu('File')
      .addItem('Attach...', 'showForm')
      .addToUi();  
}

function showForm() {
  var html = HtmlService.createHtmlOutputFromFile('index');
  SpreadsheetApp.getUi().showModalDialog(html, 'Upload File');
}

function uploadFile(e) {
  var newFileName = e.fileName;
  var blob = e.file;
  var upFile = DriveApp.getFolderById('*FolderID*').createFile(blob).setName(newFileName);
  Logger.log(upFile);
  var fileUrl = upFile.getUrl();
  
  var formula = '=HYPERLINK("' + fileUrl + '","' + newFileName + '")';
  SpreadsheetApp.getActiveRange().setFormula( formula );
  return "Uploaded!";    
}

index.html

<!DOCTYPE html>
    <html>
      <head>
        <base target="_center">
        <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
      </head>
      <body>
      <form id="myForm" >
        Select File: <input type="file" name="file" accept="*" /><br>
        File name: <input type="text" name="fileName" /><br><br>
        <input type="button" value="Upload" onclick="upload(this.parentNode);" />
      </form>
      <script>
       window.onload=func1;
    
      function func1() {
       document.getElementById('myForm').addEventListener('submit', function(event) {
                event.preventDefault();
              });  
      }
    
       function upload(obj){
           google.script.run.withSuccessHandler(close).withFailureHandler(close).uploadFile(obj);
       }   
    
       function close(e) {
           console.log(e);
           google.script.host.close();
       }
    
      </script>
    </body>
    </html>

问题和解决方法:

2021 年 12 月 9 日,文件对象必须能够使用 V8 运行时从 Javascript 端解析到 Google Apps 脚本端。但是,在这种情况下,这只能用于 Web 应用程序。当前阶段侧边栏和对话框无法解析Javascript侧的文件对象。 我认为这就是您遇到问题的原因。所以,在现阶段,需要将文件对象作为字符串和字节数组发送给侧边栏和对话框。

在这种情况下,为了使用当前的解决方法实现您的目标,我想提出以下 2 种模式。

顺便说一下,我认为在您的 Google Apps 脚本中,错误发生在 SpreadsheetApp.getActiveCell().setFormula( formula );。因为SpreadsheetApp没有getActiveCell()的方法。在这种情况下,我认为 getActiveRange() 可能是合适的。

修改后的脚本:

本次修改,将文件对象转换为字节数组,并将数据发送到Google Apps Script端。

Google Apps 脚本端:

function showForm() {
  var html = HtmlService.createHtmlOutputFromFile('index');
  SpreadsheetApp.getUi().showModalDialog(html, 'Upload File');
}

function uploadFile(e) {
  var blob = Utilities.newBlob(...e);
  var upFile = DriveApp.getFolderById('*FolderID*').createFile(blob).setName(e[2]);
  Logger.log(upFile);
  var fileUrl = upFile.getUrl();
  var formula = '=HYPERLINK("' + fileUrl + '","' + e[2] + '")';
  SpreadsheetApp.getActiveRange().setFormula(formula);
  return "Uploaded!";
}

HTML & Javascript 边:

<!DOCTYPE html>
<html>

<head>
  <base target="_center">
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>

<body>
  <form id="myForm">
    Select File: <input type="file" name="file" accept="*" /><br>
    File name: <input type="text" name="fileName" /><br><br>
    <input type="button" value="Upload" onclick="upload(this.parentNode);" />
  </form>
  <script>
    window.onload = func1;

    function func1() {
      document.getElementById('myForm').addEventListener('submit', function(event) {
        event.preventDefault();
      });
    }

    function upload(obj) {
      const file = obj.file.files[0];

      // --- For your additional request, I modified below script.
      const extension = function(e) {
        const temp = e.split(".");
        return temp.length == 1 ? "" : temp.pop();
      }(file.name);
      const filename = `${obj.fileName.value}.${extension}`;
      // ---

      const fr = new FileReader();
      fr.onload = e => {
        const obj = [[...new Int8Array(e.target.result)], file.type, filename];
        google.script.run.withSuccessHandler(close).withFailureHandler(close).uploadFile(obj);
      };
      fr.readAsArrayBuffer(file);
    }

    function close(e) {
      console.log(e);
      google.script.host.close();
    }
  </script>
</body>

</html>

注:

  • 在你的脚本中,我认为修改后的脚本可能有点复杂。所以,我发布了修改后的脚本作为答案。

参考:

  • 相关线程。