Вернуть два значения из скрипта Google Apps doGet (e) - PullRequest
0 голосов
/ 11 июля 2020

Я пытаюсь создать пользовательское веб-приложение в формате pdf на Google Apps Script, заменяя значения в моем шаблоне Google Document. Я генерирую числа в функции 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, и документ? Я знаю, что упускаю кое-что простое.

1 Ответ

1 голос
/ 11 июля 2020

Часть 1. Python

Вы должны быть осторожны с контрактом publi c ваших функций, особенно при разработке на нескольких языках. Давайте рассмотрим go шаг за шагом и посмотрим, почему возникает ошибка.

Во-первых, объект Response имеет свойство content, которое является «содержимым ответа в байтах» , Все идет нормально. Затем метод write принимает "либо в строку (в текстовом режиме), либо в байтовый объект (в двоичном режиме)" . Наконец, попытка прочитать значение по индексу из типа данных bytes приводит к int (поскольку байт является целым числом).

Все вышеперечисленное приводит к полученной вами ошибке. write ожидалось bytes или str, но получил int. Вы можете использовать метод json или свойство text для Response вместо того, чтобы работать непосредственно с данными JSON, точная реализация зависит от вас.

Часть 2. Скрипт Google Apps

Даже если вы исправите клиент, проблемы с вашим веб-приложением все равно будут. Во-первых, вы не можете вернуть несколько значений из функции в JavaScript. Хотя, как уже упоминалось, поведение оператора запятой может заставить вас думать, что это разрешено. Проблема в том, что будет возвращен только последний аргумент , чтобы продемонстрировать:

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

console.log(test());

Во-вторых, вы должны либо вернуть TextOutput, либо HtmlOutput из doGet или doPost функция триггера, чтобы получить правильный ответ (ваш ответ был правильным случайно).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...