【问题标题】:Return two values from Google Apps Script doGet(e)从 Google Apps 脚本 doGet(e) 返回两个值
【发布时间】:2020-10-31 22:56:05
【问题描述】:

我正在尝试在 Google Apps 脚本上创建一个自定义 pdf 网络应用程序,将值替换到我的模板 Google 文档中。我在 numGenerator 函数中生成数字,我也想返回这些数字以供以后在我的 python 文件中使用。

function numGenerator(digits){
   let listOfNums = [];
   const powerOfTen = Math.pow(10, digits);
   
   //Addition
   for (i=0; i<6; i++) {
     let num = getRandomNumber(0, powerOfTen);
     sendToList(num, listOfNums);
   }
   //Subtraction
   for (i=6; i<14; i+=2) {
     let num1 = getRandomNumber(0, powerOfTen);
     let num2 = getRandomNumber(num1, powerOfTen);
     sendToList(num2, listOfNums);
     sendToList(num1, listOfNums);
   }
   //Multiplication
   for (i=14; i<22; i+=2) {
     let num1 = getRandomNumber(2, (powerOfTen/10));
     let num2 = getRandomNumber(2, 20);
     sendToList(num1, listOfNums);
     sendToList(num2, listOfNums);
   }
   //Division
   for (i=22; i<30; i+=2) {
     let num2 = getRandomNumber(2, (powerOfTen/10));
     let num1 = getRandomNumber(2, (num2/10));     
     sendToList(num1*num2, listOfNums);
     sendToList(num2, listOfNums);
   }
   return listOfNums;
 }

function createDocument(doc_id, digits) {
  const listOfNums = numGenerator(digits)
  var TEMPLATE_ID = '#########';  // Google Doc template
  var documentId = DriveApp.getFileById(TEMPLATE_ID).makeCopy().getId();
  
  drivedoc = DriveApp.getFileById(documentId);
  drivedoc.setName("Mental Math Starter Exercise" + doc_id); // Copy created
  
  doc = DocumentApp.openById(documentId);
  
  var body = doc.getBody();
  
  body.replaceText('<ID>', doc_id);
  body.replaceText('<digits>', digits)
  
  for (i=1; i<=30; i++){
    body.replaceText('<num' + i + '>', listOfNums[i-1])  // Generated numbers inserted
  }
  
  drivedoc.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);

  return [listOfNums, "https://docs.google.com/document/d/" + documentId + "/export?format=pdf"]; // This might be a problem
}

function doGet(e) {
  var invoice_id = e.parameter.invoice_id; // fetches parameters
  var digits = e.parameter.digits // fetches parameters
  var url = createDocument(invoice_id, digits); // url should be a list here
  return (url[0], ContentService.createTextOutput(url[1])); //Should have returned the listOfNums and the document here
}

在我尝试从函数返回两个值之前,以下 Python 代码运行良好,下载了自定义工作表。

import requests
import random
from PyPDF2 import PdfFileMerger
import os

url = "https://script.google.com/macros/s/AKfycbyWXUQkpxyxDtj8lsOZtdaCBqRJUMZ1f9jXOFaTN82HtGIMIFc/exec?invoice_id={" \
      "}&digits={}"

def createPDF(digits):

    merger = PdfFileMerger()

    for digit in digits:
        id_num = random.randint(0, 10000)
        print("processing ", id_num, digit)
        docURL = requests.get(url.format(id_num, digit))
        print("file generated")
        document = requests.get(docURL.content)
        print("file downloaded")
        listOfNums = document.content[0]
        with open("worksheet{}.pdf".format(id_num), "wb") as f:
            f.write(document.content[1])
            # merger.append(response.content)
        merger.append("worksheet{}.pdf".format(id_num))
        os.remove("worksheet{}.pdf".format(id_num))

    merger.write("result.pdf")
    merger.close()
    print("Worksheet bundle downloaded")

但是,现在我尝试同时访问文档和 listOfNums,我收到以下错误:

  File "/Users/vkhanna/PycharmProjects/MachineLearning/pdfRequest.py", line 22, in createPDF
    f.write(document.content[1])
TypeError: a bytes-like object is required, not 'int'

如何成功返回 listOfNums 和文档?我知道我错过了一些简单的东西。

【问题讨论】:

  • 您不能从 JavaScript 中的函数返回多个值,顺便说一句(除非在数组或对象中)。 ContentService.createTextOutput(url[1]) 因此永远不会返回。
  • @OlegValter 是的。但只返回最后一项。所以url[0] 永远不会返回。见comma operator
  • 另外document.content 是以“字节”为单位的响应。无法访问[0],[1],好像是数组或列表
  • @TheMaster - 我的错,我一直忘记逗号运算符实际上返回了一些东西......
  • @TheMaster - 不过我会调查一下 - 只是像往常一样需要一些时间

标签: javascript python google-apps-script web-applications


【解决方案1】:

第 1 部分。Python

您应该注意函数的公共契约,尤其是在使用多种语言进行开发时。让我们一步一步来看看为什么会发生错误。

首先,Response 对象有一个content 属性,即"content of the response, in bytes",到目前为止一切正常。接下来,write 方法接受"either to a string (in text mode) or a bytes object (in binary mode)"。最后,尝试从bytes 数据类型中按索引读取值会导致int(因为字节是整数)。

以上所有结果都会导致您收到错误。 write 预期 bytesstr,但得到了 int。您可以使用 json 方法或 Responsetext 属性直接处理 JSON 数据,具体实现取决于您。


第 2 部分。Google Apps 脚本

即使您修复了客户端,您的 Web 应用程序仍然存在问题。首先,您不能通过 JavaScript 中的函数return multiple values。尽管如前所述,comma operator 的行为可能会诱使您认为这是允许的。问题是只有最后一个参数会被返回,来演示:

const test = () => {
    const u = 1, l = 2;
    return u, l;
};

console.log(test());

其次,您应该从doGetdoPost 触发函数返回TextOutputHtmlOutput 以获得正确的响应(您的响应是偶然正确的)。

【讨论】:

  • 我可以稍后再讨论这些问题,但这应该可以帮助您入门 - 至少修复客户端代码(在与作为后端服务的 Web 应用程序通信方面)应该可以解决眼前的问题(你现在不需要listOfNums
猜你喜欢
  • 2016-12-14
  • 2021-05-26
  • 2012-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多