Update: Taking advantage of Web Apps with Google Apps Script

“Taking advantage of Web Apps with Google Apps Script” was updated. A section of “How to use dev mode from outside” was added.

  • When you deploy Web Apps, you can see the link labeled latest code. The link is like https://script.google.com/macros/s/###/dev. When you access to the link of latest code using your browser under you login to Google, you can access to Web Apps with the dev mode. But if you want to access to Web Apps with the dev mode from outside, there are no documents for the method. Here, it introduces such method.

You can check this at https://github.com/tanaikech/taking-advantage-of-Web-Apps-with-google-apps-script.

Opening Dialog Box during Calculation and Retrieving Calculated Result using Google Apps Script

Gists

  1. When it starts a calculation, open a dialog box.
  2. When the calculation is finished, close the dialog and retrieve the calculated result.

This is a sample script for achieving above flow. This sample script supposes to use the container-bound script of Spreadsheet. When you use this, please run the function of run().

Sample script:

function doSomething(e) {

  // Scripts for calculating.

  Utilities.sleep(3000); // This is a sample wait time.
  var data = "data";
  main({result: data});
}

function openDialogue() {
  var html = "<script>google.script.run.withSuccessHandler(function() {google.script.host.close()}).doSomething();</script>";
  var h = HtmlService.createHtmlOutput(html);
  SpreadsheetApp.getUi().showModalDialog(h, "Sample");
}

function main(e) {
  if ("result" in e) return e.result;
  openDialogue(e);
}

// Please run this function.
function run() {
  var res = main({});
    Logger.log(res);
}

Note:

  • This can be also used for the sidebar and other Google Docs.

Closing Existing Sidebar using Google Apps Script

Gists

This is a sample script for closing the existing sidebar using Google Apps Script. When the sidebar is opened, in order to close the sidebar, the sidebar can be closed by running google.script.host.close() with the script of sidebar. This is the general case.

If you want to close the opened sidebar, such functions are not prepared. So I thought this workaround. The flow of this workaround is as follows.

Updated ggsrun to v171

ggsrun was updated to v.1.7.1

  • v1.7.1 (December 30, 2018)
    1. A bug was removed.
      • When a project is downloaded and zipped, there was a case that “createdTime” and “modifiedTime” of the project cannot be retrieved by Apps Script API. This was modified.

You can check ggsrun at https://github.com/tanaikech/ggsrun.

Uploading Multiple Files From Local To Google Drive using Google Apps Script

Gists

This is a sample script for uploading multiple files from local PC to Google Drive using Google Apps Script. The dialog, sidebar and Web Apps can be used as the GUI interface.

Sample 1

In this sample, the following flow is run.

  1. Select files at browser.
  2. Upload the files every file.
  3. Save each file in Google Drive.

When you use this, please copy and paste the Google Apps Script and HTML to the script editor, and run the HTML using the dialog, sidebar and Web Apps.

Summarizing Slides as Thumbnails

Gists

This is a sample script for summarizing Slides as thumbnails. For example, it supposes a Slides including 15 pages. When this script is run, it summarizes 6 pages to one page as images. I created this because there are no methods for directly achieving this. This is useful for myself. If this is also useful for you, I’m glad.

The flow of this workaround is as follows.

Flow:

  1. Copy the original Slides file as a temporary file.
  2. Retrieve images of all slides.
    • When the Slides file is exported to PNG file, the top page is exported as PNG file. I used this.
  3. Put and arrange the retrieved images to the temporary file.
    • When the image is inserted to a slide, retrieve the size and change the size, then put the image to the calculated position.

Sample script 1:

function myFunction() {
  // Please set these parameters
  var id = "### file ID ###"; // file ID of original Slides
  var col = 3; // Number of columns
  var row = 2; // Number of rows
  var wsize = 200; // Size of width of each image (pixels)
  var sep = 5; // Space of each image (pexels)


  // Create temporary file
  var originalFile = DriveApp.getFileById(id);
  var tempFile = originalFile.makeCopy();
  var idt = tempFile.getId();
  
  // Retrieve slides as images
  var s = SlidesApp.openById(idt);
  var slides = s.getSlides();
  var accessToken = ScriptApp.getOAuthToken();
  var baseUrl = "https://docs.google.com/presentation/d/" + idt + "/export/";
  var url = baseUrl + "png?access_token=" + accessToken;
  var blobs = slides.map(function(e) {
    var blob = UrlFetchApp.fetch(url).getBlob();
    slides[0].remove();
    s.saveAndClose();
    s = SlidesApp.openById(idt);
    slides = s.getSlides();
    return blob;
  });

  // Put images 
  var ph = s.getPageHeight();
  var pw = s.getPageWidth();
  var leftOffset = (pw - ((wsize * col) + (sep * (col - 1)))) / 2;
  if (leftOffset < 0) throw new Error("Images are sticking out from a slide.");
  var len = col * row;
  var loops = Math.ceil(blobs.length / (col * row));
  for (var loop = 0; loop < loops; loop++) {
    var ns = s.insertSlide(loop);
    var topOffset, top;
    var left = leftOffset;
    for (var i = len * loop; i < len + (len * loop); i++) {
      if (i === blobs.length) break;
      var image = ns.insertImage(blobs[i]);
      var w = image.getWidth();
      var h = image.getHeight();
      var hsize = h * wsize / w;
      if (i === 0 || i % len === 0) {
        topOffset = (ph - ((hsize * row) + sep)) / 2;
        if (topOffset < 0) throw new Error("Images are sticking out from a slide.");
        top = topOffset;
      }
      image.setWidth(wsize).setHeight(hsize).setTop(top).setLeft(left).getObjectId();
      if (i === col - 1 + (loop * len)) {
        top = topOffset + hsize + sep;
        left = leftOffset;
      } else {
        left += wsize + sep;
      }
    }
  }
  s.saveAndClose();
}

Sample script 2:

When you use this script, please enable Slides API at API console.

Updated goodls to v122

  • v1.2.2 (December 12, 2018)

    1. When files are downloaded from a specific folder, it got to be able to select mimeType. By this, files with the specific mimeType in the specific folder can be retrieved. For this, I updated the go library go-getfilelist.
      • $ goodls -u [URL] -key [APIkey] -m "application/pdf,image/png"

The detail information and how to get this are https://github.com/tanaikech/goodls.

Retrieving Access Token using Service Account by Google's OAuth2 package for Golang

Gists

This is a sample golang script for retrieving access token using Service Account of Google by Google’s OAuth2 package.

The script without using Google’s OAuth2 package is here.

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "os"

    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "golang.org/x/oauth2/jwt"
)

func serviceAccount(credentialFile string) (*oauth2.Token, error) {
    b, err := ioutil.ReadFile(credentialFile)
    if err != nil {
        return nil, err
    }
    var c = struct {
        Email      string `json:"client_email"`
        PrivateKey string `json:"private_key"`
    }{}
    json.Unmarshal(b, &c)
    config := &jwt.Config{
        Email:      c.Email,
        PrivateKey: []byte(c.PrivateKey),
        Scopes: []string{
            "https://www.googleapis.com/auth/drive.metadata.readonly",
        },
        TokenURL: google.JWTTokenURL,
    }
    token, err := config.TokenSource(oauth2.NoContext).Token()
    if err != nil {
        return nil, err
    }
    return token, nil
}

func main() {
    token, err := serviceAccount("credentials.json") // Please set here
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println(res)
}