Exécuter des fonctions avec l'API Apps Script

L'API Google Apps Script fournit un Méthode scripts.run qui exécute à distance une fonction Apps Script spécifiée. Vous pouvez utiliser cette méthode dans une application appelante pour exécuter une fonction dans l'un de vos projets de script ; à distance et de recevoir une réponse.

Conditions requises

Vous devez satisfaire aux exigences suivantes pour qu'une application appelante puisse utiliser la scripts.run . Vous devez :

  • Déployez le projet de script en tant qu'exécutable d'API. Vous pouvez déployer, annuler et redéployer des projets selon les besoins.

  • Fournissez un jeton OAuth correctement défini pour l'exécution. Ce jeton OAuth doit couvrir tous les champs d'application. utilisés par le script, et pas seulement ceux utilisés par la fonction appelée. Consultez le la liste complète des champs d'application des autorisations ; dans la référence de la méthode.

  • Assurez-vous que le script et le protocole OAuth2 de l'application appelante Google Cloud partagent un projet Google Cloud commun. Le projet Cloud doit être un projet Cloud standard. les projets par défaut créés pour les projets Apps Script sont insuffisants. Vous pouvez utiliser un nouveau projet Cloud standard ou un projet existant.

  • Activer l'API Google Apps Script dans le projet Cloud.

La méthode scripts.run

scripts.run requiert des informations d'identification clés pour s'exécuter:

Vous pouvez éventuellement configurer votre script pour qu'il s'exécute en mode développement. Ce mode s'exécute avec la dernière version enregistrée du projet de script. et non sur la dernière version déployée. Pour ce faire, définissez Booléen devMode dans corps de la requête à true. Seul le propriétaire du script peut l'exécuter en mode Développement.

Gérer les types de données de paramètre

Utiliser l'API Apps Script Méthode scripts.run implique généralement d'envoyer des données à Apps Script sous forme de paramètres de fonction et de récupérer les données sous forme de valeurs renvoyées par une fonction. L'API peut seulement prendre et renvoyer valeurs avec des types de base: chaînes, tableaux, objets, nombres et booléens. Ces sont similaires aux types de base en JavaScript. Plus complexe Des objets Apps Script tels que Document ou Sheet ne peuvent pas être transmis dans ou à partir du projet de script par l'API.

Lorsque votre application appelante est écrite dans un langage à type fort, tel que Java, il transmet les paramètres sous la forme d'une liste ou d'un tableau d'objets génériques correspondant à ces types de base. Dans de nombreux cas, vous pouvez appliquer des pour chaque type de conversion. Par exemple, une fonction qui prend un nombre peut recevoir un objet Java Double, Integer ou Long en tant que sans manipulation supplémentaire.

Lorsque l'API renvoie la réponse de la fonction, vous devez souvent caster a renvoyé une valeur au type approprié avant de pouvoir l'utiliser. Voici quelques exemples Exemples basés sur Java:

  • Les nombres renvoyés par l'API à une application Java arrivent sous la forme java.math.BigDecimal. Vous devrez peut-être la convertir en Doubles ou int selon vos besoins.
  • Si la fonction Apps Script renvoie un tableau de chaînes, une application Java convertit la réponse en un objet List<String>:

    List<String> mylist = (List<String>)(op.getResponse().get("result"));
    
  • Si vous souhaitez renvoyer un tableau de Bytes, cela peut s'avérer utile pour encoder le tableau sous forme de chaîne base64 dans la fonction Apps Script et renvoyez cette chaîne à la place:

    return Utilities.base64Encode(myByteArray); // returns a String.
    

Les exemples de code ci-dessous montrent comment à interpréter la réponse de l'API.

Procédure générale

Vous trouverez ci-dessous la procédure générale d'utilisation de l'API Apps Script. pour exécuter des fonctions Apps Script:

Étape 1: Configurez le projet Cloud commun

Votre script et l'application appelante doivent partager le même Google Cloud. Ce projet Cloud peut être un projet existant ou un nouveau projet créé à cette fin. Une fois que vous avez créé un projet Cloud, vous devez changer de projet de script pour l'utiliser.

Étape 2: Déployez le script en tant qu'exécutable d'API

  1. Ouvrez le projet Apps Script contenant les fonctions que vous souhaitez utiliser.
  2. En haut à droite, cliquez sur Déployer &gt; Nouveau déploiement.
  3. Dans la boîte de dialogue qui s'affiche, cliquez sur Activer les types de déploiement . &gt; Exécutable d'API.
  4. Dans la colonne "Qui a accès ?", sélectionnez les utilisateurs sont autorisés à appeler les fonctions du script à l'aide de l'API Apps Script.
  5. Cliquez sur Déployer.

Étape 3: Configurez l'application appelante

L'application appelante doit activer l'API Apps Script et établir OAuth des identifiants avant de pouvoir être utilisée. Vous devez avoir accès au projet Cloud pour ce faire.

  1. Configurez le projet Cloud que votre application appelante et votre script utilisent. Pour ce faire, procédez comme suit:
    1. Activez l'API Apps Script dans le projet Cloud.
    2. Configurer l'écran de consentement OAuth
    3. Créer des identifiants OAuth
  2. Ouvrez le projet de script et, à gauche, cliquez sur Overview (Aperçu) .
  3. Sous Champs d'application OAuth du projet, enregistrez tous les champs d'application requis par le script.
  4. Dans le code de l'application appelante, générez un jeton d'accès OAuth de script. pour l'appel d'API. Il ne s'agit pas d'un jeton utilisé par l'API, mais d'un jeton requis par le script lors de son exécution. Il doit être créé à l'aide du l'ID client du projet Cloud et les champs d'application de script que vous avez enregistrés.

    Les bibliothèques clientes Google peuvent considérablement à créer ce jeton et à gérer OAuth pour l'application, ce qui vous permet généralement de créer des "identifiants" de niveau supérieur objet à l'aide des champs d'application du script. Consultez le Guides de démarrage rapide de l'API Apps Script : exemples de la création d'un objet Credentials à partir d'une liste de champs d'application.

Étape 4: Envoyez la requête script.run

Une fois l'application appelante configurée, vous pouvez effectuer Appels scripts.run. Chaque API comprend les étapes suivantes:

  1. créer une requête API ; à l'aide de l'ID de script, du nom de la fonction paramètres.
  2. Créer la scripts.run et incluez le jeton OAuth de script que vous avez créé (si vous utilisez une requête POST de base) ou utilisez un objet credentials. que vous avez compilées avec les champs d'application des scripts.
  3. Autorisez l'exécution du script. Les scripts peuvent prendre jusqu'à six minutes d'exécution. Votre application doit donc permettre cela.
  4. Une fois l'opération terminée, la fonction de script peut renvoyer une valeur, que l'API est renvoyée à l'application si la valeur correspond à un type pris en charge.

Vous trouverez des exemples d'appels d'API script.run ci-dessous.

Exemples de requêtes API

Les exemples suivants montrent comment effectuer une requête d'exécution d'API Apps Script dans dans différents langages, en appelant une fonction Apps Script pour afficher une liste de des dossiers du répertoire racine de l'utilisateur. ID de script du projet Apps Script contenant la fonction exécutée doit être spécifié au format ENTER_YOUR_SCRIPT_ID_HERE Ces exemples reposent sur les bibliothèques clientes des API Google pour leurs langues.

Script cible

La fonction de ce script utilise l'API Drive.

Vous devez activer l'API Drive dans le qui héberge le script.

En outre, les applications appelantes doivent envoyer des identifiants OAuth incluant le champ d'application Drive suivant:

  • https://www.googleapis.com/auth/drive

Les exemples d'application présentés ici utilisent les bibliothèques clientes Google pour créer d'identifiants pour OAuth utilisant ce champ d'application.

/**
 * Return the set of folder names contained in the user's root folder as an
 * object (with folder IDs as keys).
 * @return {Object} A set of folder names keyed by folder ID.
 */
function getFoldersUnderRoot() {
  const root = DriveApp.getRootFolder();
  const folders = root.getFolders();
  const folderSet = {};
  while (folders.hasNext()) {
    const folder = folders.next();
    folderSet[folder.getId()] = folder.getName();
  }
  return folderSet;
}

Java


/**
 * Create a HttpRequestInitializer from the given one, except set
 * the HTTP read timeout to be longer than the default (to allow
 * called scripts time to execute).
 *
 * @param {HttpRequestInitializer} requestInitializer the initializer
 *                                 to copy and adjust; typically a Credential object.
 * @return an initializer with an extended read timeout.
 */
private static HttpRequestInitializer setHttpTimeout(
    final HttpRequestInitializer requestInitializer) {
  return new HttpRequestInitializer() {
    @Override
    public void initialize(HttpRequest httpRequest) throws IOException {
      requestInitializer.initialize(httpRequest);
      // This allows the API to call (and avoid timing out on)
      // functions that take up to 6 minutes to complete (the maximum
      // allowed script run time), plus a little overhead.
      httpRequest.setReadTimeout(380000);
    }
  };
}

/**
 * Build and return an authorized Script client service.
 *
 * @param {Credential} credential an authorized Credential object
 * @return an authorized Script client service
 */
public static Script getScriptService() throws IOException {
  Credential credential = authorize();
  return new Script.Builder(
      HTTP_TRANSPORT, JSON_FACTORY, setHttpTimeout(credential))
      .setApplicationName(APPLICATION_NAME)
      .build();
}

/**
 * Interpret an error response returned by the API and return a String
 * summary.
 *
 * @param {Operation} op the Operation returning an error response
 * @return summary of error response, or null if Operation returned no
 * error
 */
public static String getScriptError(Operation op) {
  if (op.getError() == null) {
    return null;
  }

  // Extract the first (and only) set of error details and cast as a Map.
  // The values of this map are the script's 'errorMessage' and
  // 'errorType', and an array of stack trace elements (which also need to
  // be cast as Maps).
  Map<String, Object> detail = op.getError().getDetails().get(0);
  List<Map<String, Object>> stacktrace =
      (List<Map<String, Object>>) detail.get("scriptStackTraceElements");

  java.lang.StringBuilder sb =
      new StringBuilder("\nScript error message: ");
  sb.append(detail.get("errorMessage"));
  sb.append("\nScript error type: ");
  sb.append(detail.get("errorType"));

  if (stacktrace != null) {
    // There may not be a stacktrace if the script didn't start
    // executing.
    sb.append("\nScript error stacktrace:");
    for (Map<String, Object> elem : stacktrace) {
      sb.append("\n  ");
      sb.append(elem.get("function"));
      sb.append(":");
      sb.append(elem.get("lineNumber"));
    }
  }
  sb.append("\n");
  return sb.toString();
}

public static void main(String[] args) throws IOException {
  // ID of the script to call. Acquire this from the Apps Script editor,
  // under Publish > Deploy as API executable.
  String scriptId = "ENTER_YOUR_SCRIPT_ID_HERE";
  Script service = getScriptService();

  // Create an execution request object.
  ExecutionRequest request = new ExecutionRequest()
      .setFunction("getFoldersUnderRoot");

  try {
    // Make the API request.
    Operation op =
        service.scripts().run(scriptId, request).execute();

    // Print results of request.
    if (op.getError() != null) {
      // The API executed, but the script returned an error.
      System.out.println(getScriptError(op));
    } else {
      // The result provided by the API needs to be cast into
      // the correct type, based upon what types the Apps
      // Script function returns. Here, the function returns
      // an Apps Script Object with String keys and values,
      // so must be cast into a Java Map (folderSet).
      Map<String, String> folderSet =
          (Map<String, String>) (op.getResponse().get("result"));
      if (folderSet.size() == 0) {
        System.out.println("No folders returned!");
      } else {
        System.out.println("Folders under your root folder:");
        for (String id : folderSet.keySet()) {
          System.out.printf(
              "\t%s (%s)\n", folderSet.get(id), id);
        }
      }
    }
  } catch (GoogleJsonResponseException e) {
    // The API encountered a problem before the script was called.
    e.printStackTrace(System.out);
  }
}

JavaScript

/**
 * Load the API and make an API call.  Display the results on the screen.
 */
function callScriptFunction() {
  const scriptId = '<ENTER_YOUR_SCRIPT_ID_HERE>';

  // Call the Apps Script API run method
  //   'scriptId' is the URL parameter that states what script to run
  //   'resource' describes the run request body (with the function name
  //              to execute)
  try {
    gapi.client.script.scripts.run({
      'scriptId': scriptId,
      'resource': {
        'function': 'getFoldersUnderRoot',
      },
    }).then(function(resp) {
      const result = resp.result;
      if (result.error && result.error.status) {
        // The API encountered a problem before the script
        // started executing.
        appendPre('Error calling API:');
        appendPre(JSON.stringify(result, null, 2));
      } else if (result.error) {
        // The API executed, but the script returned an error.

        // Extract the first (and only) set of error details.
        // The values of this object are the script's 'errorMessage' and
        // 'errorType', and an array of stack trace elements.
        const error = result.error.details[0];
        appendPre('Script error message: ' + error.errorMessage);

        if (error.scriptStackTraceElements) {
          // There may not be a stacktrace if the script didn't start
          // executing.
          appendPre('Script error stacktrace:');
          for (let i = 0; i < error.scriptStackTraceElements.length; i++) {
            const trace = error.scriptStackTraceElements[i];
            appendPre('\t' + trace.function + ':' + trace.lineNumber);
          }
        }
      } else {
        // The structure of the result will depend upon what the Apps
        // Script function returns. Here, the function returns an Apps
        // Script Object with String keys and values, and so the result
        // is treated as a JavaScript object (folderSet).

        const folderSet = result.response.result;
        if (Object.keys(folderSet).length == 0) {
          appendPre('No folders returned!');
        } else {
          appendPre('Folders under your root folder:');
          Object.keys(folderSet).forEach(function(id) {
            appendPre('\t' + folderSet[id] + ' (' + id + ')');
          });
        }
      }
    });
  } catch (err) {
    document.getElementById('content').innerText = err.message;
    return;
  }
}

Node.js

/**
 * Call an Apps Script function to list the folders in the user's root Drive
 * folder.
 *
 */
async function callAppsScript() {
  const scriptId = '1xGOh6wCm7hlIVSVPKm0y_dL-YqetspS5DEVmMzaxd_6AAvI-_u8DSgBT';

  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const script = google.script({version: 'v1', auth});

  try {
    // Make the API request. The request object is included here as 'resource'.
    const resp = await script.scripts.run({
      auth: auth,
      resource: {
        function: 'getFoldersUnderRoot',
      },
      scriptId: scriptId,
    });
    if (resp.error) {
      // The API executed, but the script returned an error.

      // Extract the first (and only) set of error details. The values of this
      // object are the script's 'errorMessage' and 'errorType', and an array
      // of stack trace elements.
      const error = resp.error.details[0];
      console.log('Script error message: ' + error.errorMessage);
      console.log('Script error stacktrace:');

      if (error.scriptStackTraceElements) {
        // There may not be a stacktrace if the script didn't start executing.
        for (let i = 0; i < error.scriptStackTraceElements.length; i++) {
          const trace = error.scriptStackTraceElements[i];
          console.log('\t%s: %s', trace.function, trace.lineNumber);
        }
      }
    } else {
      // The structure of the result will depend upon what the Apps Script
      // function returns. Here, the function returns an Apps Script Object
      // with String keys and values, and so the result is treated as a
      // Node.js object (folderSet).
      const folderSet = resp.response.result;
      if (Object.keys(folderSet).length == 0) {
        console.log('No folders returned!');
      } else {
        console.log('Folders under your root folder:');
        Object.keys(folderSet).forEach(function(id) {
          console.log('\t%s (%s)', folderSet[id], id);
        });
      }
    }
  } catch (err) {
    // TODO(developer) - Handle error
    throw err;
  }
}

Python

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def main():
  """Runs the sample."""
  # pylint: disable=maybe-no-member
  script_id = "1VFBDoJFy6yb9z7-luOwRv3fCmeNOzILPnR4QVmR0bGJ7gQ3QMPpCW-yt"

  creds, _ = google.auth.default()
  service = build("script", "v1", credentials=creds)

  # Create an execution request object.
  request = {"function": "getFoldersUnderRoot"}

  try:
    # Make the API request.
    response = service.scripts().run(scriptId=script_id, body=request).execute()
    if "error" in response:
      # The API executed, but the script returned an error.
      # Extract the first (and only) set of error details. The values of
      # this object are the script's 'errorMessage' and 'errorType', and
      # a list of stack trace elements.
      error = response["error"]["details"][0]
      print(f"Script error message: {0}.{format(error['errorMessage'])}")

      if "scriptStackTraceElements" in error:
        # There may not be a stacktrace if the script didn't start
        # executing.
        print("Script error stacktrace:")
        for trace in error["scriptStackTraceElements"]:
          print(f"\t{0}: {1}.{format(trace['function'], trace['lineNumber'])}")
    else:
      # The structure of the result depends upon what the Apps Script
      # function returns. Here, the function returns an Apps Script
      # Object with String keys and values, and so the result is
      # treated as a Python dictionary (folder_set).
      folder_set = response["response"].get("result", {})
      if not folder_set:
        print("No folders returned!")
      else:
        print("Folders under your root folder:")
        for folder_id, folder in folder_set.items():
          print(f"\t{0} ({1}).{format(folder, folder_id)}")

  except HttpError as error:
    # The API encountered a problem before the script started executing.
    print(f"An error occurred: {error}")
    print(error.content)


if __name__ == "__main__":
  main()

Limites

L'API Apps Script présente plusieurs limites:

  1. Un projet Cloud commun. Le script appelé et les l'application appelante doit partager un projet Cloud. Le projet Cloud doit être standard Cloud project (Projet Cloud standard) les projets par défaut créés pour les projets Apps Script sont insuffisants. La un projet Cloud standard peut être un nouveau projet ou un projet existant.

  2. Types de paramètres et de renvois de base. L'API ne peut ni transmettre, ni renvoyer Des objets spécifiques à Apps Script (tels que Documents, Blobs Agendas Fichiers Drive, etc.) vers application. Seuls les types de base tels que les chaînes, les tableaux, les objets, les nombres et des valeurs booléennes peuvent être transmises et renvoyées.

  3. Champs d'application OAuth L'API ne peut exécuter que des scripts ayant au moins un champ d'application obligatoire. Cela signifie que vous ne pouvez pas utiliser l'API pour appeler un script qui ne nécessite pas d'autorisation d'un ou de plusieurs services.

  4. Aucun déclencheur. L'API ne peut pas créer de scripts Apps Script. déclencheurs.