Gists

Abstract
This article demonstrates how to build an adaptive learning agent using Agent-to-User Interface (A2UI), Gemini, and Google Apps Script. We explore a system that generates personalized quizzes, tracks performance in Google Sheets, and dynamically adjusts difficulty to maximize learning efficiency within the Google Workspace ecosystem.
Introduction
A2UI (Agent-to-User Interface) represents a paradigm shift in how users interact with generative AI. Originally open-sourced by Google and implemented in TypeScript and Python Ref, A2UI becomes even more powerful when integrated with Google Apps Script (GAS). This combination enables seamless access to the Google Workspace ecosystem, transforming static documents into intelligent, agentic applications.
Gists

Abstract
This article explores A2UI (Agent-to-User Interface) using Google Apps Script and Gemini. By generating dynamic HTML via structured JSON, Gemini transforms Workspace into an “Agent Hub.” This recursive UI loop enables complex workflows where the AI builds the specific functional tools required to execute tasks directly.
Introduction: The Evolution of AI Interaction
The Official A2UI framework by Google marks a significant paradigm shift in how we interact with artificial intelligence. Short for Agent-to-User Interface, A2UI represents the evolution of Large Language Models (LLMs) from passive chatbots into active agents capable of designing their own functional interfaces. Building upon my previous research, A2UI for Google Apps Script and Bringing A2UI to Google Workspace with Gemini, I have refined this integration to support sophisticated, stateful workflows.
Gists

Abstract
This article explores implementing the Agent-to-User Interface (A2UI) protocol within Google Apps Script. It demonstrates utilizing Gemini’s structured output to render secure, dynamic, server-driven UIs—like booking forms and event lists—directly inside Google Sheets, streamlining workflows without complex external infrastructure.
Introduction
I recently published a sample implementation demonstrating how to bring the Agent-to-User Interface (A2UI) concepts to Google Apps Script (GAS). Ref
A2UI is an emerging open-standard protocol designed to enable AI agents to generate rich, interactive user interfaces that render natively across web, mobile, and desktop environments. Ref Unlike traditional approaches that often require executing arbitrary, high-risk code to generate UI on the fly, A2UI leverages a strict schema-based data format to describe UI components. This “secure-by-design” architecture effectively mitigates security risks like Cross-Site Scripting (XSS) while ensuring high performance and cross-platform consistency.
Gists

Abstract
The Gemini API now supports external file URLs, allowing developers to process data directly without uploading it first. This article demonstrates how to leverage this update to integrate Google Workspace resources—including Google Sheets, Docs, Slides, and Apps Script—into Gemini’s workflow, covering both public and secure private access methods.
Introduction
Recently, the limitations regarding inline file data in the Gemini API have been significantly updated Ref. The maximum file size has increased from 20 MB to 100 MB. Furthermore, external file URLs—both public and signed—can now be used directly as input.
Gists

Abstract
This article demonstrates how to implement Google’s A2UI (Agent-to-User Interface) using Google Apps Script (GAS). By porting official Python/TypeScript examples to GAS, we show how to create dynamic, AI-generated interfaces within Google Workspace, enabling flexible business automation and interactive user experiences without complex server infrastructure.
Introduction
Google recently released A2UI, a protocol designed for agent-driven interfaces. Ref A2UI enables AI agents to generate rich, interactive user interfaces that render natively across web, mobile, and desktop environments without executing arbitrary code.
Gists
Published: January 3, 2026
Author: Kanshi Tanaike
Abstract
Analyzing StackOverflow data (2008–2026) reveals a massive activity decline post-ChatGPT. Using Google Apps Script as a case study, this report quantifies the migration from human support to AI. We explore how the platform is pivoting from a help desk to a critical verification layer for AI-generated code to prevent model collapse.
Introduction
On StackOverflow, millions of developers engage in daily knowledge exchange, creating a historical repository of technological evolution. A prime example of this ecosystem is the google-apps-script tag. Having participated in this community for years, I have observed its threads evolve in tandem with Google’s platform updates.
Gists

Abstract
This article introduces a Google Apps Script-based Agent2Agent architecture to solve Tool Space Interference. While the provided demonstration utilizes a single server for testing purposes, the architecture is designed for distributed task execution. By running multiple category-specific A2A servers in parallel, users can achieve scalable, high-efficiency agent networks.
Introduction
As the Model Context Protocol (MCP) standardizes LLM connectivity, the Agent2Agent (A2A) paradigm is becoming essential for executing complex, multi-step tasks. However, integrating a high volume of tools often triggers “Tool Space Interference (TSI)"—a phenomenon where verbose metadata saturates context windows and degrades reasoning accuracy. Ref Ref Current industry guidelines suggest a “soft limit” of 20 functions per agent; exceeding this threshold frequently results in hallucinations and logic failures.
UtlApp was updated to v1.0.12.
You can see the detail information here https://github.com/tanaikech/UtlApp
Gists

Abstract
This article introduces a major update to gas-fakes enabling dynamic loading of Google Apps Script libraries. This enhancement allows developers to build modular, maintainable Model Context Protocol (MCP) servers. We demonstrate this by integrating sophisticated library-based tools with Gemini CLI and Google Antigravity for seamless Google Workspace automation.
Introduction
I recently published an article titled “Power of Google Apps Script: Building MCP Server Tools for Gemini CLI and Google Antigravity in Google Workspace Automation.” In that piece, I demonstrated how to bridge the Model Context Protocol (MCP) with Google Workspace by implementing an MCP server using Google Apps Script (GAS) and gas-fakes. This successfully established a communication channel for sophisticated AI agents—such as the Gemini CLI and Google Antigravity—to interact directly with Workspace data.
Gists

Abstract
This article demonstrates how to build Model Context Protocol (MCP) tools directly using Google Apps Script. By leveraging the gas-fakes CLI, developers can execute Google Apps Script locally to automate Google Workspace via Gemini CLI and Google Antigravity, streamlining development and eliminating the overhead of dynamic tool creation.
Introduction
With the rapid advancement of generative AI, ensuring the security of executing AI-generated scripts is of paramount importance to prevent arbitrary code execution vulnerabilities. Addressing this, I previously published a secure sandbox environment for Google Apps Script (GAS) known as gas-fakes, which emulates the Apps Script environment locally. Ref
Gists

Abstract
This article redefines Google Apps Script (GAS) as a central integration hub in the AI era. It introduces the forefront of Google Workspace automation, realized through the fusion of the Model Context Protocol (MCP), Agent2Agent (A2A), and the Gemini CLI ecosystem. I cover everything from data integration bridging local and cloud environments (RAG) and sandbox technologies for safely executing AI-generated GAS, to the coordination of autonomous agents on the newly released Google Antigravity. We will explore next-generation work styles and implementation methods where complex workflows are completed autonomously through simple natural language instructions.
Gists

Abstract
This article explores automating Google Workspace by integrating Google Antigravity and Gemini 3.0 with Model Context Protocol (MCP) servers. We demonstrate how to overcome tool limits and utilize custom extensions to enable AI agents to securely execute scripts, manage files, and perform RAG-based tasks using private data.
Introduction
Google Antigravity and Gemini 3.0 are ushering in a new era of “Agent-First” development, transforming how we interact with cloud environments. Ref A key component of this evolution is the integration of Model Context Protocol (MCP) servers. When connected to Antigravity, these servers empower the architecture to resolve complex, multi-step tasks by granting the AI direct, standardized access to external tools and proprietary data.
Gists

Abstract
This article demonstrates a cutting-edge workflow for Google Apps Script development using Google Antigravity and Gemini 3.0. By integrating gas-fakes via the Model Context Protocol (MCP), we establish an environment where autonomous agents can generate, unit-test, and execute cloud-based scripts locally, revolutionizing the standard GAS development lifecycle.
Introduction
Google Antigravity has officially been released. Ref This is a revolutionary “Agent-first” IDE powered by Gemini 3, designed to empower autonomous AI agents to plan, code, and verify tasks across the Editor, Terminal, and Browser. It is anticipated that this platform will trigger a paradigm shift in how we develop applications and auto-generate comprehensive documentation, moving the industry from simple code completion to fully agentic workflows.
Overview
TableApp is a Google Apps Script library for managing Tables on Google Sheets.
Description
Recently, a new feature “Tables” was introduced to Google Sheets. Tables allow users to group data into structured tables with headers, filtering, and specific data types. While these can be managed via the Google Sheets API (v4), constructing the raw JSON requests for operations like creating, updating, and managing tables can be complex.
This library, TableApp, creates an object-oriented wrapper around the Google Sheets API, making it easy to manage Tables directly within Google Apps Script.
Gists

Abstract
This article introduces “TableApp,” a Google Apps Script library designed to simplify managing Google Sheets Tables. It addresses the complexity of the native Sheets API, providing an intuitive interface for creating, updating, and manipulating tables. Sample scripts and installation guides are included to ensure easy implementation.
Introduction
The introduction of Tables in Google Sheets has significantly enhanced data management capabilities. While these tables can be managed via the Sheets API, the process is often complex and verbose. I previously discussed this in my article, Managing Tables on Google Sheets using Google Apps Script.
Gists

Abstract
This article demonstrates how to create a unified file search for Gemini, integrating disconnected local files and Google Workspace data. Using a Google Apps Script-powered extension, users can directly ingest data from Drive, Sheets, and Gmail, enabling a powerful, context-aware RAG system.
Introduction
1. The Challenge of Data Silos
In modern enterprises, data is fragmented. It lives on local machines, in Google Drive, within Google Sheets, and across countless emails. While the Gemini CLI excels at file searches, it traditionally requires manually downloading cloud files to a local environment before they can be used. This workflow is inefficient, error-prone, and creates unnecessary operational overhead, preventing the creation of a truly comprehensive knowledge base for Retrieval-Augmented Generation (RAG).
Gists

Abstract
This article guides you through establishing a modern, cloud-based development workflow for Google Apps Script. Learn to leverage Google Cloud and Firebase Studio with powerful tools like the Gemini CLI and gas-fakes to build, test, and deploy your automations with enhanced efficiency and security.
Introduction
Google Apps Script is primarily designed to be created in a cloud-based script editor and run on the cloud. However, using Google Apps Script on various cloud platforms opens up the possibility of wider application development due to its high compatibility with each platform’s features.
Gists

Abstract
This article explores the evolution of Google Apps Script (GAS) development, focusing on the powerful capabilities unlocked by the gas-fakes CLI. Discover how to seamlessly integrate your local development environment with GAS, enabling you to use local files, execute scripts without uploading, and build a more efficient, modern workflow.
Introduction
Google Apps Script is a versatile platform that continues to evolve. A significant leap forward in its development is the ability to work with GAS projects locally, a paradigm shift driven by Bruce McPherson’s gas-fakes. This tool, and the ecosystem it has inspired, are changing how developers approach GAS development.
GitHub

Abstract
This article introduces a powerful method for developing and testing Google Apps Script (GAS) locally. By leveraging the gas-fakes library, you can build a secure, local Model Context Protocol (MCP) server, enabling the creation of AI-powered tools for Google Workspace automation without deploying to the cloud.
Introduction
gas-fakes, developed by Bruce McPherson, is an innovative library that enables Google Apps Script (GAS) code to run directly in a local environment by substituting GAS classes and methods with their corresponding Google APIs.
Gists

Abstract
This document introduces a powerful integration of the gas-fakes CLI and a Gemini CLI extension, creating a secure and streamlined development workflow for Google Apps Script. This setup enables local testing of AI-generated scripts in a secure sandbox, preventing unintended access to your Google Drive, and provides a seamless transition to cloud deployment.
Introduction
The gas-fakes project by Bruce McPherson is a groundbreaking endeavor that recreates the Google Apps Script (GAS) execution environment on Node.js, enabling local testing and debugging. When Bruce invited me to join the project, I first started by understanding gas-fakes. The project enables local execution by converting GAS service calls (e.g., SpreadsheetApp.create()) into corresponding Google API requests.
I created a Gemini CLI extension as a GAS Development Kit. For this, I developed the CLI of gas-fakes.
Repository
https://github.com/tanaikech/gas-development-kit-extension
Installation
1. Install Gemini CLI
First, install the Gemini CLI using npm:
npm install -g @google/gemini-cli
Next, you will need to authorize the CLI. Follow the instructions provided in the official documentation.
2. Install Clasp
Even when Clasp is not installed, when gas-fakes is installed, you can run Google Apps Script in a sandbox using gas-fakes.
Gists

Abstract
This guide explores a powerful, next-level workflow for Google Apps Script (GAS) development by integrating Gemini CLI Extensions with Visual Studio Code (VSCode). This combination streamlines the entire development process, from script creation and local testing in a secure sandbox to deploying and managing projects, all within a unified and efficient environment.
Introduction
Visual Studio Code (VSCode) is widely recognized as a premier source code editor. The release of the Gemini CLI has dramatically transformed script development by bringing advanced AI capabilities directly into the terminal. In particular, combining Gemini CLI with VSCode creates a powerful development ecosystem, highly effective for languages typically executed locally, such as Python, Node.js, Go and so on. Beyond coding, this setup streamlines content creation, including articles and papers, by leveraging AI for drafting and editing. Ref For cloud-based Google Apps Script (GAS) development, the standard approach involves using VSCode alongside Clasp to manage projects locally. Ref Integrating Gemini CLI into this established workflow promises significant synergistic effects. A recent update has further expanded these possibilities by enabling Clasp to function experimentally as a Model Context Protocol (MCP) server, allowing LLMs to directly interact with GAS project structures. Ref Furthermore, to address security concerns when executing AI-generated GAS code, I have introduced a “fake sandbox” environment for safer testing. Ref and Ref With the recent release of Gemini CLI Extensions, which allow for custom AI tools and specialized workflows, combining these assets creates a vastly superior developer environment. In this article, I will introduce next-level Google Apps Script development by leveraging the combined power of Gemini CLI Extensions and VSCode.
Gists

Abstract
This guide offers a comprehensive walkthrough of the essential steps and key considerations for developing Gemini CLI extensions. It covers setting up a sample project, configuring the gemini-extension.json file, local testing, and automating dependency management with GitHub Actions, providing developers with the foundational knowledge to create their own custom tools.
Introduction
After the release of Gemini CLI Extensions, a growing community of users is developing a wide range of extensions to enhance their command-line workflows. Ref and Ref This trend is expected to continue and strengthen. As the ecosystem expands, knowing how to develop these extensions becomes increasingly valuable for users who want to create their own custom tools. Many useful articles for understanding Gemini CLI Extensions have already been published. In particular, the articles by Romin Irani are very helpful. Ref In this article, I would like to introduce the core parts I paid attention to when I developed my own extensions (Ref). I hope this article proves useful. As a sample tool in this article, the current time is returned using Node.js.
This Gemini CLI Extension simplifies Google Workspace automation. It installs a local Model Context Protocol (MCP) server that communicates with a powerful, securely authorized backend built on Google Apps Script Web Apps, overcoming previous complex setup and performance bottlenecks.
You can see the details at my repository.
https://github.com/tanaikech/ToolsForMCPServer-extension
Gists

Abstract
This project simplifies Google Workspace automation by using a Gemini CLI Extension. It installs a local Model Context Protocol (MCP) server that communicates with a powerful, securely authorized backend built on Google Apps Script Web Apps, overcoming previous complex setup and performance bottlenecks.
Introduction
In order to achieve Google Workspace Automation with seamless authorization and safety, I have published a Model Context Protocol (MCP) server built by Google Apps Script Web Apps. Ref This is very useful because Google Apps Script provides native, secure authorization for Google Workspace APIs like Gmail, Drive, and Calendar. However, there was a bottleneck in the complex installation and a long loading time of the MCP server. Recently, Gemini Extensions have been released. Ref By this, tools and MCP servers can be directly and easily installed from sources like GitHub repositories using a simple command. From this situation, I attempted to implement this simplified installation method on the MCP server built by Google Apps Script Web Apps.
Gists

Abstract
This article presents a method for optimizing Google Workspace automation by dynamically converting frequently used, AI-generated Google Apps Scripts into permanent, reusable tools. By integrating the Gemini CLI with a gas-fakes sandbox via an MCP server, we demonstrate how to securely add and manage these custom tools, reducing operational costs and improving efficiency.
Introduction
When using generative AI to create scripts, ensuring the secure execution of the generated code is critical. This is especially true for applications that manage cloud resources like Google Workspace, where it is paramount to prevent unintended data access or modification. The standard permission model for Google Apps Script often requires broad access, creating a significant security risk when running code from untrusted sources.
Gists

Abstract
This article introduces a method for securely executing AI-generated Google Apps Script. By implementing a “fake-sandbox” using the gas-fakes library as an MCP server, users can empower the Gemini CLI to safely automate Google Workspace tasks with granular, file-specific permissions, avoiding significant security risks.
Introduction
“Have you ever faced a task that isn’t part of your routine but is tedious to do manually, like, ‘I need to add a “[For Review]” prefix to the titles of all Google Docs in a specific folder this afternoon’? Or perhaps you’ve thought, ‘I want to use AI to work with my spreadsheets, but I’m concerned about the security implications of granting a tool full access to my Google Drive’?
Gists

Abstract
This guide explores a powerful workflow for generating articles and other content by integrating Gemini CLI, a Model Context Protocol (MCP) server, and Visual Studio Code (VSCode). Discover how to leverage this combination for efficient, context-aware content creation, modification, and distribution, complete with practical examples and prompts.
Introduction
The integration of Gemini CLI with Visual Studio Code (VSCode) creates a highly efficient and context-aware environment for developers and writers alike. This setup allows the AI-powered Gemini CLI to access the VSCode workspace, making it aware of open files and selected text to provide relevant and targeted suggestions. A key feature is the native in-editor diffing, which enables a side-by-side review and modification of AI-generated changes before acceptance, offering greater control over the final output.
Gists

Abstract
This article introduces a Node.js wrapper that dramatically reduces the startup time for the Gemini CLI when used with MCP servers built on Google Apps Script. This optimization enhances user experience by accelerating the initialization process, achieving a speed boost of approximately 15 times.
1. Introduction
The Model Context Protocol (MCP) is a vital open standard enabling AI agents to connect with external tools and data sources for complex, real-world tasks. To integrate the Gemini AI agent with Google Workspace, I developed two open-source tools: MCPApp, for managing the MCP server lifecycle, and ToolsForMCPServer, a suite of tools for interacting with services like Gmail and Drive. These are built with Google Apps Script for use with the Gemini CLI.
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
Gists

Abstract
This article demonstrates integrating Google Maps with natural language using the Gemini CLI and an MCP server. This powerful combination allows users to automate complex location-based tasks, such as route planning and information retrieval, through simple, intuitive text-based prompts.
Introduction
The Gemini CLI, when paired with Model Context Protocol (MCP) servers, is a powerful tool for integrating various applications with natural language. When the MCP servers are built using Google Apps Script Web Apps, it becomes easy to integrate Google Workspace and other Google APIs with seamless authorization. This concept has been explored in several articles, which you can find here: Ref, Ref, Ref, Ref, Ref, Ref, Ref. This article introduces the integration of Google Maps and natural language using the Gemini CLI with an MCP server.
Gists

Abstract
Generating Google Apps Script (GAS) with Gemini CLI from natural language introduces security risks due to broad permissions. This report investigates a “Fake-Sandbox” using the gas-fakes library, translating GAS calls into granularly-scoped API requests to securely execute scripts created from user prompts.
Introduction
1. Background: Generative AI and the Challenge of Secure Script Execution
The emergence of Generative AI now makes it possible to generate executable scripts directly from natural language instructions, particularly through interfaces like the Gemini CLI. For locally executable languages such as JavaScript (Node.js) and Python, code generated from a simple prompt can be run directly. However, Google Apps Script (GAS) presents a unique challenge as it operates within Google’s server-side infrastructure. Executing locally generated GAS code requires the remote invocation of a server-side function via the scripts.run method of the Apps Script API. This process highlights the critical need for a sandbox environment to manage permissions effectively and mitigate the risks associated with executing code generated from natural language, which can sometimes produce unintended or insecure outcomes.
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
Gists

Abstract
This report introduces a powerful method for automating Google Analytics tasks using the Gemini CLI and a custom MCP (Model Context Protocol) server built with Google Apps Script. This integration enables streamlined web page analysis through simple natural language commands, simplifying authorization and complex data retrieval workflows.
Introduction
Accessing and interpreting web analytics data often involves navigating complex interfaces and manual report generation. However, the emergence of natural language interfaces is changing this paradigm. Gemini CLI, when paired with MCP servers, allows users to orchestrate sophisticated, multi-step workflows using conversational commands. This creates a more intuitive and efficient way to interact with powerful services like Google Analytics.
Gists

Abstract
This document demonstrates a transformative method for unifying Google Workspace applications by using natural language. Through the integration of the Gemini CLI with MCP, this approach empowers users to intuitively manage Google Drive, Gmail, Google Calendar, Drive Activity, and Google People. Complex tasks and collaborative workflows are streamlined into simple, conversational text commands.
Introduction
In today’s dynamic, collaborative environments, managing document workflows, tracking changes, and coordinating team efforts can be fragmented and inefficient. This article introduces a powerful solution that unifies these processes by leveraging the Gemini CLI and MCP (Model Context Protocol). This integration breaks down the barriers between applications, allowing users to orchestrate complex tasks across Google Workspace with natural language prompts. Whether you’re finding a file in Drive, checking its comment history, retrieving contributor details from Contacts, and drafting a thank-you email in Gmail, these actions can now be executed from a single, conversational interface, dramatically boosting productivity.
Gists

Abstract
Automate Google Classroom management with natural language. This guide details using the Gemini CLI and an MCP server to streamline creating classes, managing assignments, and interacting with students.
Introduction
Unlock the power of natural language to command your Google Workspace. I’ve recently demonstrated how you can automate Google Workspace applications using simple, conversational commands through the Gemini CLI and the MCP (Model Context Protocol) server.
My previous reports detailed how to harness natural language for automating tasks in Google Sheets and Google Calendar:
MCPApp was updated to v2.0.7
-
v2.0.7 (August 6, 2025)
-
Starting with v2.0.7, you can now selectively enable or disable the LockService.
- By default, this library runs with the LockService enabled. To disable it, simply modify
return new MCPApp.mcpApp({ accessKey: "sample" }) to return new MCPApp.mcpApp({ accessKey: "sample", lock: false }).
- When the LockService is disabled (
lock: false), asynchronous requests from clients like the Gemini CLI may see an increase in processing speed. However, it’s important to note that the maximum number of concurrent requests must not exceed 30. Please use this option with caution.
You can see the detail information here https://github.com/tanaikech/MCPApp
-
v1.0.13 (August 1, 2025)
prompts/get was updated. And, 3 prompts were added.
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
MCPApp was updated to v2.0.6
-
v2.0.6 (August 1, 2025)
- “prompts/get” method was updated.
You can see the detail information here https://github.com/tanaikech/MCPApp
Gists
Abstract
This report provides a comprehensive overview of how to utilize prompts within the Gemini Command-Line Interface (CLI). Leveraging a Google Apps Script MCP server, we will explore practical examples, including roadmap generation, real-time weather inquiries, and Google Drive file searches. This enhanced document offers more in-depth explanations and a broader context to empower users in their understanding and application of these powerful features.
Introduction
The Model Context Protocol (MCP) establishes a standardized framework for servers to offer clients predefined, structured prompt templates. These user-controllable prompts, customizable with arguments, are engineered to streamline interactions with large language models. The Gemini CLI, starting with version v0.1.15, integrates support for these prompts, significantly expanding its capabilities.
-
v1.0.12 (July 31, 2025)
- At Gemini CLI v0.1.15,
prompts/list was called even when prompts wasn’t included in capabilities. This resulted in the error Error discovering prompts from gas_web_apps: MCP error -32001: Request timed out when prompts wasn’t returned for prompts/list. To resolve this, I updated ToolsForMCPServer to return an empty array for prompts, which eliminated the error. Consequently, with this update in v1.0.12, you can now set custom prompts and resources.
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
MCPApp was updated to v2.0.5
-
v2.0.5 (July 31, 2025)
- A bug was removed.
You can see the detail information here https://github.com/tanaikech/MCPApp
Gists

Abstract
This report demonstrates managing Google Calendar from the command line using Gemini CLI and an MCP server, enabling powerful, scriptable automation for your schedule.
Introduction
Following up on my previous report, “Next-Level Data Automation: Gemini CLI, Google Sheets, and MCP,” I’m excited to present the next installment in this series. My earlier report, published on Medium, detailed an innovative approach to managing Google Sheets through the powerful combination of Gemini CLI and an MCP server. Ref
-
v1.0.10 (July 26, 2025)
- When I updated Gemini CLI from v0.1.12 to v0.1.13, an issue related to the schema of MCP occurred. Ref So, as a workaround at the time, I updated this library. But when I updated Gemini CLI to v0.1.14, I confirmed that the previous schema could be used. So, I reimplemented the previous schema. By this, the request body for APIs can be directly generated using Gemini CLI v0.1.14.
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
-
v1.0.9 (July 24, 2025)
- The following 2 new tools were added.
- description_youtube: Describe a YouTube video by providing the URL.
- create_google_docs_from_markdown_on_google_drive: Create a Google Document from a markdown format.
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
-
v1.0.8 (July 23, 2025)
- An issue occurred when I updated Gemini CLI from v0.1.12 to v0.1.13. Ref Fortunately, Google is already aware of this issue, and I’m awaiting a resolution. In the meantime, I’ve received emails about it, so I’ve updated ToolsForMCPServer for Gemini CLI v0.1.13. The detailed updates are as follows: I confirmed that all tools in ToolsForMCPServer v1.0.8 worked when tested with Gemini CLI v0.1.13.
oneOf has been removed from the schema of each tool.
- Following this report, the request body is now generated on the MCP server side. Therefore, when using the tools
manage_google_docs_using_docs_api, manage_google_sheets_using_sheets_api, and manage_google_slides_using_slides_api, please use your API key for the Gemini API.
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
Gists

Abstract
Effortlessly generate API request bodies from natural language commands. This guide demonstrates using Gemini and Google Apps Script to streamline automation and accelerate development for Google Workspace APIs and beyond.
Introduction
In a recent article, “Managing Google Docs, Sheets, and Slides by Natural Language with Gemini CLI and MCP,” I showcased a powerful method for dynamically creating API request bodies using natural language. This approach, utilizing the Gemini CLI and a My Custom Proxy (MCP) server, allows users to manage Google Workspace applications with simple, human-readable commands. The core concept is that generating API request bodies directly from natural language within a script can dramatically streamline automation and development.
GeminiWithFiles was updated to v2.0.13
-
v2.0.13 (July 22, 2025)
responseJsonSchema was added.
- The default model was changed from
models/gemini-2.5-flash-preview-04-17 to models/gemini-2.5-flash.
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
-
v1.0.7 (July 19, 2025)
- Added a
getToolList method for retrieving all current tools in the library.
- Tools can be filtered using
enables or disables as an array argument for the getTools method. If enables is used, only the tools specified in the enables array will be used. If disables is used, all tools except those specified in the disables array will be used. If neither enables nor disables is used, all tools will be used.
You can see the detailed information here https://github.com/tanaikech/ToolsForMCPServer
Gists

Abstract
This report explores an optimized approach to integrating the Gemini CLI with Google Workspace via an MCP server. Traditionally, this process requires numerous custom tools, which increases development costs. We propose leveraging the inherent JSON schema requirements of the MCP server tools to directly construct request bodies for the batchUpdate methods of the Google Docs, Sheets, and Slides APIs. This approach aims to consolidate document management into just three core tools, significantly streamlining development and offering a scalable, cost-effective solution for Google Workspace automation and broader API integrations.
Gists

Abstract
This article explores the integration of the Gemini Command-Line Interface (CLI) with Google Sheets using the Model Context Protocol (MCP). It demonstrates how to leverage the open-source projects MCPApp and ToolsForMCPServer to create a bridge between the Gemini CLI and Google Workspace. This enables users to perform powerful data automation tasks, such as creating, reading, and modifying tables in Google Sheets directly from the command line, using natural language prompts. The article provides practical examples and sample prompts to illustrate the seamless workflow and potential for building sophisticated, AI-powered applications within the Google Cloud ecosystem.
Gists

Abstract
This report introduces ToolsForMCPServer, an enhanced Google Apps Script library that expands the capabilities of Gemini CLI. It showcases new tools that streamline complex workflows, with a special emphasis on facilitating seamless file content transfer and management between a user’s local environment and Google Drive.
Introduction
This report details significant enhancements to ToolsForMCPServer, a powerful Google Apps Script library designed to work in tandem with Gemini CLI. By integrating this library with a Model Context Protocol (MCP) server, the capabilities of Gemini CLI are dramatically expanded, especially in its interaction with Google Workspace services. This document will explore the core architecture that makes this possible, introduce the new tools available in the library, and demonstrate their power through practical examples that bridge the local command line with the cloud.
Gists

Abstract
This report details two methods for processing files using the Gemini CLI and a Google Apps Script MCP server: direct Base64 encoding and indirect transfer via the Google Drive API using ggsrun. The direct method proved ineffective due to token limits. The recommended approach, leveraging ggsrun, allows for efficient, scalable file transfers by using file IDs instead of embedding content within the prompt, enabling advanced automation capabilities.
Gists

Abstract
The Gemini CLI provides a powerful command-line interface for interacting with Google’s Gemini models. By leveraging the Model Context Protocol (MCP), the CLI can be extended with custom tools. This report explores the integration of the Gemini CLI with an MCP server built using Google Apps Script Web Apps. We demonstrate how this combination simplifies authorization for Google Workspace APIs (Gmail, Drive, Calendar, etc.), allowing Gemini to execute complex, multi-step tasks directly within the Google ecosystem. We provide setup instructions and several practical examples showcasing how this integration unlocks significant potential for automation and productivity enhancement.
Gists
Abstract
The Gemini CLI can be integrated with Google Workspace via Google Apps Script to securely access personal data, enabling powerful automations like email summaries and calendar management.
Introduction
The recently released Gemini CLI is a powerful command-line interface for interacting with Google’s Gemini models and cloud resources. Ref While powerful on its own, its utility can be significantly enhanced by connecting it to a user’s personal Google resources, such as Google Sheets, Docs, Slides, Gmail, and Calendar.

Description
I am thrilled to announce a significant update to the Taking Advantage of Web Apps with Google Apps Script repository! Now at Version 2.0.0, this comprehensive guide has been extensively revised and expanded to provide unparalleled insights and practical guidance for developers leveraging Google Apps Script Web Apps.
This major overhaul introduces a wealth of new and enhanced content, designed to empower you with a deeper understanding and more advanced capabilities.
Gists

Overview
Google Sheets now supports managing smart chips via its API, enabling retrieval and placement with Apps Script and other languages.
Description
Smart chips in Google Sheets and Docs are a powerful feature designed to enhance collaboration and information sharing. While there historically haven’t been built-in Google Apps Script methods to manage these chips, a workaround was previously developed to address this limitation (Ref).
However, Google has recently introduced direct methods for managing smart chips within the Google Sheets API (Ref). This report provides sample Google Apps Script code that demonstrates how to get and put smart chips on Google Sheets using these new API methods. Although these methods are currently exclusive to Google Sheets, their availability via the Sheets API means they can also be utilized with other programming languages, not just Google Apps Script. It will be anticipated that similar functionality will be extended to Google Docs in future updates.
Gists

Abstract
A new unified Google Apps Script now deploys both Model Context Protocol (MCP) and Agent2Agent (A2A) networks as a single server, streamlining AI model integration for Google Workspace users.
Introduction
The rapid growth of generative AI has led to increasing integration between AI models, exemplified by protocols like the Model Context Protocol (MCP) and Agent2Agent (A2A) Protocol. Recently, I released MCPApp and A2AApp, which establish the MCP and A2A networks using Google Apps Script. Ref and Ref This approach offers significant advantages for users of Google Workspace and Google APIs, as it enables seamless authorization and integration of these resources directly within the applications.
Gists

Abstract
This article announces that the Gemini API’s Python client library now supports “growing image” generation, a feature previously unavailable. Sample scripts for Python and Node.js are provided to demonstrate this new capability.
Introduction
I recently published an article, “Generate Growing Images using Gemini API,” which detailed a method for progressively generating images. At the time of publication, the official Python client library for the Gemini API lacked the necessary functionality to fully implement this feature, preventing Python users from easily replicating the “growing image” effect.
UtlApp was updated to v1.0.11.
You can see the detail information here https://github.com/tanaikech/UtlApp
UtlApp was updated to v1.0.10.
-
v1.0.10 (June 13, 2025)
- The method getMP3Tag was added.
You can see the detail information here https://github.com/tanaikech/UtlApp
UtlApp was updated to v1.0.9.
You can see the detail information here https://github.com/tanaikech/UtlApp
MCPApp was updated to v2.0.0
-
v2.0.0 (June 12, 2025)
- From v2.0.0, both the MCP client and the MCP server can be built by Google Apps Script.
You can see the detail information here https://github.com/tanaikech/MCPApp
Gists

Abstract
This report details an MCP network using Google Apps Script for both server and client, enabling automated, secure Gmail processing to boost efficiency.
Introduction
Recently, I published a report titled “Building Model Context Protocol (MCP) Server with Google Apps Script,” which you can find here. In that initial report, I demonstrated the feasibility of creating an MCP server using Google Apps Script, with Claude Desktop serving as the client.
Gists
Description
This script provides a simple example for generating Text-To-Speech (TTS) using the Gemini API within Google Apps Script. The Gemini API generates audio data in the audio/L16;codec=pcm;rate=24000 format, which is not directly playable. Since there’s no built-in method to convert this to a standard audio/wav format, this sample script includes a custom function to handle the conversion.
Limitations and Considerations
- The provided
convertL16ToWav_ function is specifically designed for the audio/L16;codec=pcm;rate=24000 MIME type. Using it with other audio formats will result in an error.
- The script uses a hardcoded WAV header. This header assumes specific audio parameters (e.g., sample rate, bit depth, number of channels) that match the Gemini API’s output for this format. If the Gemini API’s output format changes, this header might need adjustment.
Sample Script
Before running, replace "###" with your actual Gemini API key in the myFunction.
Gists

Abstract
For extensive Google Docs, manually converting straight to smart quotes is inefficient. This report offers an automated solution using Google Apps Script, saving time and effort.
Description
You might find yourself needing to convert straight quotes (both single and double) to smart quotes in Google Docs. For small documents with a limited number of quotes, this can be done manually with minimal effort. However, when dealing with extensive documents and numerous quotes, the manual process becomes time-consuming and inefficient. This report presents a solution to automate this conversion using Google Apps Script, significantly reducing the processing cost for larger projects.
MCPApp was updated to v1.0.2
-
v1.0.2 (May 29, 2025)
- From v1.0.2, in order to use MCPApp as a library, LockService is given.
You can see the detail information here https://github.com/tanaikech/MCPApp
A2AApp was updated to v2.0.1
-
v2.0.1 (May 29, 2025)
- From v2.0.1, A2AApp can also be used as a library. Ref
You can see the detail information here https://github.com/tanaikech/A2AApp
Gists

Abstract
This report details the Agent2Agent (A2A) network built with Google Apps Script’s Web Apps. It facilitates communication between diverse AI agents, overcoming platform limitations. Key improvements include parallel task execution with asynchronous processes and enhanced security through secure access token handling and user-specific Web App availability, demonstrating a robust and secure A2A implementation.
Introduction
This report details an updated implementation of Agent2Agent (A2A), an open protocol designed to enable communication and collaboration between diverse AI agents. The goal of A2A is to overcome limitations of isolated platforms, allowing AI agents to work together on complex tasks while maintaining their internal structures. I recently published a report titled “Building Agent2Agent (A2A) Server with Google Apps Script”. Ref This updated report focuses on successfully creating an A2A network using Google Apps Script’s Web Apps functionality.
GeminiWithFiles was updated to v2.0.10
-
v2.0.10 (May 21, 2025)
- Implemented the parallel function calling. Ref
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists

Abstract
Exploring Agent2Agent (A2A) protocol implementation in Google Apps Script seamlessly allows AI agents to access Google Workspace data and functions. This could enable complex workflows and automation, overcoming platform silos for integrated AI applications.
Introduction
Agent2Agent (A2A) is a proposed open protocol facilitating communication and collaboration among diverse AI agents, aiming to overcome platform silos and enable complex tasks while preserving agent opacity. This report examines the feasibility of implementing a core A2A server component using Google Apps Script within Google Workspace. Such an implementation could seamlessly allow AI agents to securely access and utilize data and functionalities across Google services like Docs, Sheets, and Gmail via a standardized protocol. This would enable sophisticated AI-powered workflows and automation directly linked to user data. A sample script demonstrates the technical potential despite the current lack of a dedicated Apps Script SDK for A2A. While acknowledging potential Apps Script limitations, such as execution time, this exploratory approach remains valuable for developing internal or user-centric AI applications and integrations within Google Workspace. A successful demonstration could potentially highlight the capabilities of Google Apps Script.
Gists

Abstract
Google Sheets API now supports programmatic table management (create, delete, modify) as of April 29, 2025. This eliminates previous workarounds and enables direct control, including with Apps Script.
Introduction
Google Sheets tables can now be managed programmatically via the Sheets API, a significant update officially released on April 29, 2025. Ref I learned about this important development from Martin Hawksey’s Apps Script Pulse newsletter. Ref I am very grateful to Martin for bringing this to light. This update introduces the ability to programmatically manage tables directly through the Sheets API, enabling operations such as creating, deleting, and modifying tables and their properties. Previously, programmatic interaction with Sheets tables was limited and often required using workarounds for even simple management tasks, as explored in my earlier reports Ref and Ref. With this official API support, more robust and direct control is now possible. In this report, I will introduce how to manage tables on Google Sheets using the Sheets API, with examples implemented using Google Apps Script. It is worth noting, of course, that the Sheets API can also be used with other programming languages besides Apps Script.
Gists
Abstract
This report details transferring image data via Model Context Protocol (MCP) from Google Apps Script server to a Python/Gemini client, extending capabilities for multimodal applications beyond text.
Introduction
Following up on my previous report, “Building Model Context Protocol (MCP) Server with Google Apps Script” (Ref), which detailed the transfer of text data between the MCP server and client, this new report focuses on extending the protocol to handle image data. It introduces a practical method for transferring image data efficiently from the Google Apps Script-based MCP server to an MCP client. In this implementation, the MCP client was built using Python and integrated with the Gemini model, allowing for the processing and utilization of the transferred image data alongside text, thereby enabling more complex, multimodal applications within the MCP framework.
Gists

Abstract
This text introduces the Model Context Protocol (MCP) for standardizing AI interaction with external systems. It explores the potential of using Google Apps Script (GAS) to host an MCP server, leveraging GAS’s integration with Google Workspace for data access. A sample script demonstrates feasibility, highlighting the current absence of an official GAS SDK. The work aims to foster understanding and encourage SDK development.
Introduction
Recently, the Model Context Protocol (MCP) has emerged as a standard protocol for connecting AI applications with third-party systems and data sources. Acting like a universal adapter or “USB-C for AI,” the MCP standardizes how AI models can dynamically discover and interact with external resources, tools, and context, often incorporating mechanisms for user consent and secure communication. The detailed specification of this protocol can be confirmed at the official site. Ref
Gists

Abstract
The report details a novel Gemini API method to analyze big data beyond AI context window limits, which was validated with Stack Overflow data for insights into Google Apps Script’s potential.
Introduction
Generative AI models face significant limitations when processing massive datasets, primarily due to the constraints imposed by their fixed context windows. Current methods thus struggle to analyze the entirety of big data within a single API call, preventing comprehensive analysis. To address this challenge, I have developed and published a detailed report presenting a novel approach using the Gemini API for comprehensive big data analysis, designed to operate effectively beyond typical model context window limits. Ref
GeminiWithFiles was updated to v2.0.6
-
v2.0.6 (April 23, 2025)
- A new method
countTokens was added. Ref When this method is used, you can count tokens of the request.
- This pull request was reflected. Ref
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists
Abstract
Learn how Gemini AI and Google Apps Script automate Google Slides generation. A developed application demonstrates this synergy, streamlining initial presentation drafting and showcasing AI’s automation potential within Google Workspace.
Introduction
The field of AI, particularly large language models like Google’s Gemini, is advancing rapidly. A powerful application of this technology involves integrating Gemini with Google Apps Script. Google Apps Script provides a seamless way to automate tasks across Google Workspace by natively handling authorization and interaction with services like Google Docs, Google Sheets, and Google Slides. By combining Gemini’s generative capabilities with Apps Script, sophisticated automations become accessible.
Gists

Abstract
Gemini and Google Apps Script automate project roadmap creation in Google Sheets, including Gantt charts, improving efficiency and agile planning.
Introduction
When initiating a new project, a comprehensive roadmap is crucial for successful execution. Previously, I meticulously crafted these roadmaps manually, a time-consuming process. However, leveraging the advanced capabilities of Google’s Gemini, I’ve significantly streamlined this workflow. Gemini now assists in generating detailed project roadmaps, enhancing efficiency and accuracy. To further automate this process, I developed a Google Apps Script that dynamically constructs these roadmaps directly within Google Sheets, complete with integrated Gantt charts. This script facilitates the rapid generation of diverse project roadmaps, enabling agile planning and adaptation for future endeavors. This report details the functionality and implementation of this script, demonstrating its potential to optimize project planning and visualization.
Gists

Description
This is a sample Google Apps Script designed to replace all instances of specific text within a Google Slides presentation, while simultaneously applying a desired text style. The built-in Presentation.replaceAllText() method within the Google Slides service is limited; it efficiently replaces text strings but lacks the functionality to modify text formatting during the replacement process. This limitation poses a challenge when aiming for styled text replacements. This report presents a detailed script solution that overcomes this constraint. The script iterates through all text elements within the slides, identifies matching text, and performs a replacement. Crucially, it also applies specified text formatting attributes, such as font, font size, color, and bold/italic settings, to the replaced text. This enhanced functionality allows users to maintain consistent and visually appealing presentations when automating text modifications. Furthermore, the script illustrates the use of TextRange methods for precise text manipulation and styling within Google Slides. This approach offers a more robust alternative to the standard replaceAllText() method, providing greater control over text replacement and formatting in Google Slides automation workflows.
Gists

Abstract
This report demonstrates the onSelectionChange simple trigger in Google Sheets by creating a slide puzzle. Selecting cells triggers script execution, enabling interactive gameplay.
Introduction
At Google Sheets, simple triggers can be used. When simple triggers are used, users can automatically run Google Apps Script based on actions in the spreadsheet. Among the simple triggers is onSelectionChange. This can automatically run a script when a cell is selected. In this report, as a simple sample script demonstrating the use of onSelectionChange, I created a slide puzzle in Google Sheets. The goal of the slide puzzle is to align the numbers by sliding them. Here, onSelectionChange is used to detect the selected number and slide it. The aim of this report is to learn about the simple trigger onSelectionChange.
Gists

Abstract
Gemini API now generates images via Flash Experimental and Imagen 3. This report introduces image evolution within conversations using Gemini API with Google Apps Script.
Introduction
Recently, image generation was supported in the Gemini API using Gemini 2.0 Flash Experimental and Imagen 3. I have already reported a simple sample script for generating images using the Gemini API with Google Apps Script. Ref In practice, you might want to evolve the generated images within a conversation. In this report, I would like to introduce a sample script demonstrating this using Google Apps Script.
GeminiWithFiles was updated to v2.0.5
-
v2.0.5 (March 19, 2025)
- A new method
chat was added. Ref When this method is used, you can generate content with Gemini API through the chat.
- The default model was changed from
models/gemini-1.5-flash-latest to models/gemini-2.0-flash.
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists

Abstract
This report presents a Google Apps Script for generating visualized cooking recipes with text and images using the Gemini API, leveraging its image generation capabilities.
Introduction
Recently, image generation was supported in the Gemini API using Gemini 2.0 Flash Experimental and Imagen 3. I have already reported a simple sample script for generating images using the Gemini API with Google Apps Script. Ref Google Apps Script seamlessly integrates with Google Docs, Sheets, and Slides. In this report, I would like to introduce a script for creating a recipe for cooking a dish, including texts and images, using the Gemini API with Google Apps Script.
Gists

Description
Recently, image generation was supported in the Gemini API using Gemini 2.0 Flash Experimental and Imagen 3. This report introduces simple sample scripts for generating images using the Gemini API with Google Apps Script. When images can be created using the Gemini API with Google Apps Script, Google Apps Script, which seamlessly integrates with Google Docs, Sheets, and Slides, becomes a powerful tool for creating and managing them, and the applications are infinite.
GeminiWithFiles was updated to v2.0.4
-
v2.0.4 (March 15, 2025)
- Property
generationConfig was added to the method geminiWithFiles. By this, you can use all properties for generationConfig. Ref You can see the sample scripts at “Use googleSearch for grounding” and “Generate image”.
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists
Description
Now, Google Docs and Google Sheets can insert smart chips. Smart chips are very useful for easily inserting information like users, maps, files, and so on. However, unfortunately, at the current stage, smart chips cannot be directly managed using Google Apps Script. Specifically, the information within smart chips cannot be directly retrieved by Google Apps Script. Although I believe this will be resolved in a future update, there might be cases where you want to retrieve information from smart chips using Google Apps Script. This report introduces a workaround for achieving this.
Gists
Description
This is a Google Apps Script for creating the tree structure from headings in Google Documents.

Usage
In order to test this script, please do the following steps.
1. Sample Document
Create a sample Document as follows.

2. Sample script
Open the script editor and copy and paste the following script.
In this script, Document service (DocumentApp) is used.
function sample1() {
const headTypes = [
"TITLE",
"HEADING1",
"HEADING2",
"HEADING3",
"HEADING4",
"HEADING5",
"HEADING6",
];
const body = DocumentApp.getActiveDocument().getBody();
const res = body
.getParagraphs()
.reduce((ar, p) => {
const idx = headTypes.indexOf(p.getHeading().toString());
if (idx > -1) {
ar.push(Array(idx).fill(" ").join("") + p.getText());
}
return ar;
}, [])
.join("\n");
console.log(res);
}
As another approach, the following script uses Docs API. Please enable Docs API at Advanced Google services. Ref
Gists

Description
This report introduces a sample script for changing the glyph colors of bullets in lists on Google Documents using Google Apps Script. Currently, there are no built-in methods for achieving this using either the Document service (DocumentApp) or the Docs API. However, this can be accomplished through a specific process. This report will introduce that process using Google Apps Script.
Principle
When the foreground color of the text within a list is changed using the Google Document service (DocumentApp), the bullet glyphs are not affected. However, when the foreground color of all text within a list is changed using the Google Docs API, the bullet glyphs are changed. This script leverages this behavior. The detailed process is as follows:
Gists
Published: March 9, 2025
Kanshi Tanaike
Introduction
On Stack Overflow, numerous users post questions and answers daily across various tags. These discussions, spanning a wide range of topics, provide valuable information and are highly beneficial. One such tag is “google-apps-script,” where I occasionally participate in discussions. Observing these threads over time, it’s evident that they evolve alongside updates to Google Apps Script, the technology at the core of the tag. This report aims to analyze this evolution as a trend within the “google-apps-script” tag. This trend encompasses changes in the number of questions, questioners, answerers, and associated tags. The evolution of the “google-apps-script” tag is closely linked to the development of Google Apps Script and its diverse applications.
Gists
Abstract
This report outlines a Google Apps Script solution for directly exporting web-published Google Docs to PDF. By circumventing limitations in published URLs, the script enables convenient PDF generation without manual intervention.
Introduction
Google Sheets and Google Docs offer the convenient feature of web publishing, providing readily accessible URLs for sharing. Ref
- Google Sheets:
https://docs.google.com/spreadsheets/d/e/2PACX-###/pubhtml
- Google Docs:
https://docs.google.com/document/d/e/2PACX-###/pub
These URLs utilize a unique ID (###) for each document. While Google Sheets supports direct PDF export by modifying the URL to https://docs.google.com/spreadsheets/d/e/2PACX-###/pub?output=pdf, a similar direct method for Google Docs is currently unavailable.
Gists

Abstract
A new library, MimeTypeApp, simplifies using Gmail messages and attachments with the Gemini API for tasks like text analysis. It converts unsupported formats for seamless integration with Google Apps Script and Gemini.
Introduction
Recently, I published MimeTypeApp, a Google Apps Script library that simplifies parsing Gmail messages, including attachments, for use with the Gemini API. Ref This library addresses a key challenge: Gmail attachments come in various MIME types, while the Gemini API currently only accepts a limited set for processing. MimeTypeApp bridges this gap by providing functions to convert unsupported MIME types to formats compatible with Gemini. With MimeTypeApp, you can streamline your workflows that involve parsing Gmail messages and their attachments for tasks like text extraction, summarization, or sentiment analysis using the Gemini API. This report introduces a sample script that demonstrates how to leverage MimeTypeApp to achieve this functionality. By leveraging Google Apps Script’s integration capabilities, MimeTypeApp allows you to create powerful applications that seamlessly connect Gmail, Spreadsheets (for storing results or extracted data), and the Gemini API.
Gists

Abstract
This is a Google Apps Script library for converting files from various MIME types to a specified target MIME type. The library accepts both file IDs and blobs as input values.
Introduction
Recently, I encountered a scenario where I needed to convert files of various MIME types to a specific target MIME type. While converting files with known source MIME types is relatively straightforward, the process becomes more complex when the source MIME type is unknown. To simplify this task, I developed a Google Apps Script solution that can effectively convert files of diverse MIME types to a desired target MIME type. The script can accept both file IDs and blobs as input values.
GeminiWithFiles was updated to v2.0.3
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists

Description
Recently, I reported on a workaround for effectively working with Google Sheets tables using Google Apps Script: Ref. This approach addressed limitations in directly retrieving table data and ranges within Apps Script. In this follow-up report, I’m excited to provide a sample script that leverages this workaround to export your valuable Google Sheets tables directly as PDF files. This functionality empowers you to easily share and distribute your data in a clear and universally accessible format.
Gists

Abstract
Google Sheets’ new Tables feature enhances data organization but lacks direct management via Apps Script. This report proposes a workaround solution using Apps Script until native support arrives.
Introduction
Google Sheets recently introduced a new feature called Tables. Ref Tables offer a powerful way to organize and manage your data by transforming unformatted ranges into structured datasets with automatic headers, filtering options, and data validation capabilities. This not only improves the readability and maintainability of your spreadsheets but also allows for seamless integration with existing Google Sheets functions.
Gists

Abstract
Google Apps Script offers Document service for basic document tasks and Google Docs API for advanced control, requiring more technical expertise. This report bridges the gap with sample scripts to unlock the API’s potential.
Introduction
Google Apps Script provides two powerful tools for managing Google Documents: the Document service (DocumentApp) and the Google Docs API. Ref, Ref While the Document service offers a user-friendly interface for common document manipulation tasks within Apps Script, it has limitations. The Google Docs API, on the other hand, grants finer-grained control over document elements and functionalities not readily available through the Document service.
Gists
Abstract
This report showcases a practical application of Google Apps Script, demonstrating how new JavaScript methods can be used to create a script that automatically transfers selected rows between sheets in a Google Sheet.
Introduction
JavaScript, a fundamental pillar of contemporary web development, has experienced a significant rise in popularity due to its versatility and widespread adoption. As JavaScript’s influence has expanded, so too has Google Apps Script, a cloud-based scripting language constructed on the V8 JavaScript engine. This evolution has led to the introduction of novel methods and features, thereby expanding the capabilities of developers working within the Google Workspace ecosystem.
Gists

Abstract
Gemini excels at text generation with RAG for large datasets, but smaller ones benefit from prompting or data upload. This report explores using Gemini 1.5 Flash/Pro with RAG on medium-sized, Google Spreadsheet-stored datasets for improved accuracy and effectiveness.
Introduction
Gemini’s text generation capabilities have seen significant advancements with the Retrieval-Augmented Generation (RAG). This approach excels for large datasets, where embedding data and querying the model leads to high-quality answers. However, for smaller datasets, directly including data in the prompt or an uploaded file can be more efficient. Ref
GeminiWithFiles was updated to v2.0.2
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists
Abstract
This report presents a method to train AI to effectively generate content from smaller, structured datasets using Python. Gemini’s token processing capabilities are leveraged to effectively utilize limited data, while techniques for interpreting CSV and JSON formats are explored.
Introduction
In the era of rapidly advancing artificial intelligence (AI), the ability to analyze and leverage large datasets is paramount. While RAG (Retrieval Augmented Generation) environments are often ideal for such tasks, there are scenarios where content generation needs to be achieved with smaller datasets.
Gists

Abstract
This report improves Gmail email labeling with Gemini API using JSON schema and leverages advancements in Gemini 1.5 Flash for faster processing.
Introduction
As Gemini continues to evolve, existing scripts utilizing its capabilities can be revisited to improve efficiency and accuracy. This includes the process of flexible labeling for Gmail emails using the Gemini API. I have previously explored this topic in two reports:
- December 19, 2023: Demonstrating Gmail label selection based solely on prompts. Ref
- January 30, 2024: Exploring label selection through both semantic search and function calls. Ref
This report introduces a new method for Gmail label selection using a JSON schema with response_mime_type: “application/json”. Thanks to Gemini’s advancements, content generation speed has significantly improved with the introduction of Gemini 1.5 Flash. Additionally, JSON schema allows for greater control over the output format. Recent research Ref suggests that this combination outperforms the previous approach using response_mime_type and response_schema separately.

Abstract
This post introduces a Google Apps Script solution that automates the creation, sharing, and monitoring of multiple Google Spreadsheets, providing a more efficient and streamlined approach to managing user data.
Introduction
I’ve often encountered requests from clients who need to manage multiple Google Spreadsheets for various users, often by copying a template spreadsheet. In these situations, I typically propose the following approach:
- Create a Template Spreadsheet: This spreadsheet serves as a blueprint, containing essential elements like custom functions implemented using Google Apps Script.
- Develop a Dashboard Spreadsheet: This centralized hub provides an overview of all user spreadsheets.
- Clone and Share Spreadsheets: For each user, a copy of the template spreadsheet is created and shared with them. The URLs of these individual spreadsheets are then recorded in the dashboard.
- Import Data Using IMPORTRANGE: The dashboard utilizes the IMPORTRANGE function to fetch data from individual user spreadsheets. This enables real-time updates on the dashboard as users edit their respective sheets.
While this manual process can be effective, it can become cumbersome and time-consuming, especially as the number of users and spreadsheets grows. To streamline this workflow and enhance efficiency, I’ve developed a Google Apps Script solution that automates many of these steps.
Gists
Abstract
This report presents a method to optimize AI-generated scripts for processing costs using Gemini and Google Apps Script. By incorporating external knowledge from sources like StackOverflow, we demonstrate the effective generation of efficient scripts that minimize overhead while maintaining desired outcomes. This approach can be considered a dynamic pseudo-RAG technique.
Introduction
The proliferation of generative AI, exemplified by Google Gemini, has led to a surge in AI-generated scripts. This trend is evident in the growing number of questions on platforms like StackOverflow that involve AI-generated scripts. While this indicates a significant improvement in AI performance, it’s crucial to note that AI-generated scripts may not always be optimized for processing costs, especially when the prompt fails to provide sufficient context.
UtlApp was updated to v1.0.7.
You can see the detail information here https://github.com/tanaikech/UtlApp
Gists
Abstract
A script using resumable upload with file streams is proposed to enhance file handling within the Gemini Generative AI API for Node.js. This script allows uploading from web URLs and local storage, efficiently handles large files, and offers potential reusability with other Google APIs.
Description
The @google/generative-ai library provides a powerful way to interact with the Gemini Generative AI API using Node.js. This enables developers to programmatically generate creative text formats, translate languages, write different kinds of creative content, and answer your questions in an informative way, all powered by Gemini’s advanced AI models. Ref
Gists
Abstract
This study proposes a workaround to address the Gemini API’s current inability to directly process web content from URLs. By utilizing Google Apps Script, the method extracts relevant information from a specified URL and feeds it into the API for summarization. This approach offers a solution for generating comprehensive summaries from web-based content until the API’s limitations are resolved.
Introduction
While Gemini API offers powerful text generation capabilities, it currently faces limitations in directly accessing and processing web content from URLs. When prompted to summarize an article at a specific URL like Summarize the article at the following URL. https://###, the API often returns an error message indicating its inability to retrieve the necessary information. This limitation arises from the API’s current design, which may not be equipped to handle web requests and parse HTML content.
Gists
Abstract
Linking a Google Apps Script project to a GCP project enables you to export logs from the Class console to Logs Explorer for simplified analysis and debugging. By overcoming the limitations of in-script logging methods, this report outlines a method for exporting logs using the Cloud Logging API with Google Apps Script.
Introduction
While developing applications with Google Apps Script, the Class console is a valuable tool for debugging individual components. Ref However, a key limitation exists: by default, Google Apps Script projects on Google Drive are not linked to Google Cloud Platform (GCP) projects. In this unlinked scenario, logs from the Class console are only visible within the script editor, requiring manual copying for export.
Gists
Overview
This sample script demonstrates uploading multiple files using split asynchronous processes with resumable upload. It leverages JavaScript and HTML within Google Spreadsheets.
Description
In my previous report, “Resumable Upload of Multiple Files with Asynchronous Process for Google Drive”, I presented an approach for uploading files asynchronously.
This script builds upon that concept, introducing a method for uploading multiple files with split asynchronous processes that utilize resumable upload.
Here’s the process breakdown:
Gists

Abstract
This report proposes a novel learning method using Gemini to automate Q&A generation, addressing the challenges of manual Q&A creation. By integrating with Google tools, this approach aims to enhance learning efficiency, accessibility, and personalization while reducing costs.
Introduction
Mastering a new subject often demands a significant time commitment. A proven strategy for efficient learning is through question-and-answer (Q&A) practice. This method typically involves constructing a dataset of pertinent Q&A pairs and subsequently engaging in repeated practice until desired proficiency levels are achieved. While platforms such as Google Forms and Google Apps Script can streamline the Q&A creation and evaluation process, the manual generation of Q&A data remains a time-consuming and expensive endeavor. Minimizing the operational costs associated with scripting is crucial for long-term sustainability.
GeminiWithFiles was updated to v2.0.1
-
v2.0.1 (August 4, 2024)
- From this version,
codeExecution can be used. Ref
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
UnlockSmartInvoiceManagementWithGeminiAPI was updated to v1.0.3.
-
v1.0.3 (August 3, 2024)
- On August 3, 2024, I upated GeminiWithFiles (https://github.com/tanaikech/GeminiWithFiles). In this version, PDF data can be processed with Gemini API without async/await. So, I updated UnlockSmartInvoiceManagementWithGeminiAPI.
You can see the detail information here https://github.com/tanaikech/UnlockSmartInvoiceManagementWithGeminiAPI
GeminiWithFiles was updated to v2.0.0
-
v2.0.0 (August 3, 2024)
- From this version, the following changes were made.
- PDF data can be directly used. Ref By this, PDFApp is not required to be used. By this, the script can be used without async/await.
- As the default,
functions: {} is used. So, the default function calling was removed. Because in the current stage, JSON output can be easily returned using a JSON schema and response_mime_type. Ref Ref
- The default model was changed from
models/gemini-1.5-pro-latest to models/gemini-1.5-flash-latest.
- The export values with
exportTotalTokens were changed. After v2.x.x, when this is true, the object usageMetadata including promptTokenCount, candidatesTokenCount, totalTokenCount is exported. At that time, the generated content and usageMetadata are returned as an object.
- After v2.x.x, the large files can be uploaded to Gemini. This is from this respository and this post.
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists

Abstract
Gemini API now enables direct PDF processing for content generation, eliminating image conversion and reducing costs. This report provides a sample script to demonstrate this new capability and its potential applications.
Introduction
Gemini API has recently introduced the ability to directly process PDF data for content generation, significantly enhancing its capabilities. Previously, to utilize PDF data for content creation, it was necessary to convert each PDF page into a separate image format. This time-consuming and resource-intensive process has been eliminated, resulting in substantially reduced processing costs.
Gists

Description
Great news for fans of both Google Docs and Markdown! Google Docs recently acquired the ability to export documents directly into the markdown format. Ref
This functionality extends beyond the user interface, with early indications suggesting the Google Drive API might also be capable of converting between Google Docs and Markdown. I confirmed that this could also be achieved by Drive API. This opens exciting possibilities for automated workflows.
UnlockSmartInvoiceManagementWithGeminiAPI was updated to v1.0.2.
-
v1.0.2 (July 23, 2024)
- On July 23, 2024, I noticed that PDF data could be directly parsed by Gemini API. It is considered that this is due to the update by the Google side. So, I updated
setBlobs([blob], true) to setBlobs([blob], false) of the method parseInvoiceByGemini_. By this modification, the PDF blob is directly used with Gemini API. Ref
You can see the detail information here https://github.com/tanaikech/UnlockSmartInvoiceManagementWithGeminiAPI
Gists

Abstract
Uploads in Google Apps Script are limited to 50 MB, hindering work with large datasets. This report introduces a script with uploadType=resumable to overcome this limit, enabling uploads over 50 MB to Gemini and other services.
Introduction
This report explores the limitations of data upload size using Google Apps Script and introduces a script to overcome these limitations. In the current stage, Gemini API can generate content using the uploaded data to Gemini. You can find more information on this in a previous report. Ref As mentioned in the report, Google Apps Script uses uploadType=multipart for uploading files. However, the maximum file size is limited to 5 MB with this method for Drive API. Ref While I confirmed that the Gemini API allows for uploading over about 20 MB with uploadType=multipart, Google Apps Script enforces a stricter 50 MB limit for both uploads and downloads. Ref This can be inconvenient when working with larger datasets, such as movie or text data, which often exceed this limit.
GeminiWithFiles was updated to v1.0.7.
-
v1.0.7 (July 4, 2024)
- From this version, when
doCountToken: true and exportTotalTokens: true are used in the object of the argument of geminiWithFiles, the total tokens are returned. In this case, the returned value is an object like {returnValue: "###", totalTokens: ###}. Ref
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
TriggerApp was updated to v1.0.3.
-
v1.0.3 (June 26, 2024)
- The calculation for increasing the month was modified.
- A new scenario 8 was added. In scenario 8, you can see how to use the month-end. Ref
You can see the detail information here https://github.com/tanaikech/TriggerApp
Gists
Abstract
This report provides a Google Apps Script to retrieve all files, including those within subfolders, for a designated folder. It addresses the challenges of retrieving files within deeply nested folder structures and obtaining complete file paths.
Introduction
Google Apps Script empowers developers to interact with Google Drive data programmatically, unlocking a wide range of functionalities. A core component of this interaction is the Drive service (DriveApp) and Drive API. These services provide programmatic control over files and folders within your Drive.
MoveFolder was updated to v1.0.1.
-
v1.0.1 (June 18, 2024)
- In the recent update on the Google side, it was found that in the current stage, when the other libraries are loaded from a library, an error like
We're sorry, a server error occurred while reading from storage. Error code NOT_FOUND occurs. So, from v1.0.1, the library of BatchRequest is included in this library.
You can see the detail information here https://github.com/tanaikech/MoveFolder
UnlockSmartInvoiceManagementWithGeminiAPI was updated to v1.0.1.
-
v1.0.1 (June 17, 2024)
- In order to easily customize the value of “jsonSchema” for generating content with Gemini API, I added it as a new sheet of “jsonSchema” sheet in the Spreadsheet. When you customize it, you can edit the cell “A1” of the “jsonSchema” sheet. By this, the script generates content with Gemini API using your customized JSON schema. The cell “A2” is the number of characters of “A1”.
You can see the detail information here https://github.com/tanaikech/UnlockSmartInvoiceManagementWithGeminiAPI
GeminiWithFiles was updated to v1.0.6.
-
v1.0.6 (June 15, 2024)
- Included the script of PDFApp in this library.
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists

You can see the presentation of this application at https://www.youtube.com/watch?v=Dc2WPQkovZE.
Abstract
This report describes an invoice processing application built with Google Apps Script. It leverages Gemini, a large language model, to automatically parse invoices received as email attachments and automates the process using time-driven triggers.
Introduction
The emergence of large language models (LLMs) like ChatGPT and Gemini has significantly impacted various aspects of our daily lives. One such example is their ability to automate tasks previously requiring manual effort. In my case, Gemini has streamlined the processing of invoices I receive as email attachments in PDF format.
GeminiWithFiles was updated to v1.0.5.
-
v1.0.5 (June 7, 2024)
- Spelling mistakes in the warning message were modified. The wait time for changing the value of state for the movie file is changed from 5 seconds to 10 seconds per cycle.
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles

Overview
This is a Google Apps Script library for moving a folder including files and folders on Google Drive.
Description
This library addresses a common challenge: efficiently moving folders, including their subfolders and files, between Google Drives. This encompasses both personal and shared drives using a script. While Google Drive offers straightforward methods for moving individual files between any drives, directly moving entire folders containing subfolders presents limitations, particularly when shared drives are involved. This script bridges that gap by providing a reliable Google Apps Script solution for such scenarios.
Gists

Abstract
This script automates moving a folder including files and folders between Google Drives (personal or shared) by recreating the folder structure and transferring files, overcoming limitations for shared drives.
Introduction
This report addresses a common challenge: efficiently moving folders, including their subfolders and files, between Google Drives, encompassing both personal and shared drives using a script. While Google Drive offers straightforward methods for moving individual files between any drives, directly moving entire folders containing subfolders presents limitations, particularly when shared drives are involved. This script bridges that gap by providing a reliable Google Apps Script solution for such scenarios.
FilesApp was updated to v1.1.4.
-
v1.1.4 (June 5, 2024)
- A bug for retrieving metadata from the shared drive was removed.
GitHub of FilesApp
My post was featured in the section “Community cuts” of “The overwhelmed person’s guide to Google Cloud: week of May 23”.
Gitst

Abstract
This report builds on prior work using Gemini 1.0 Pro to expand Google Apps Script error messages. It highlights how the script’s execution time limit created a bottleneck, but the introduction of Gemini 1.5 Flash eliminates this issue.
Introduction
After the release of the Gemini API, I previously reported on “Expanding Error Messages of Google Apps Script using Gemini Pro API with Google Apps Script”. Ref In that report, I utilized the Gemini 1.0 Pro model. While expanding error messages proved valuable for understanding script errors in detail, Google Apps Script currently has a maximum execution time of 6 minutes. Ref This meant that processing time for content generation by the Gemini API significantly impacted the total process time when dealing with large scripts, creating a bottleneck.
GeminiWithFiles was updated to v1.0.4.
-
v1.0.4 (May 29, 2024)
- Recently, when
model.countToken is used with the uploaded files, I confirmed that an error like You do not have permission to access the File ### or it may not exist. occurred. In order to handle this issue, I modified the library.
- In order to use the movie files for generateContent, I modified the library. Ref
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists
Abstract
Current Google Docs API documentation offers methods for working with existing lists but lacks instructions for creating nested lists in new documents. This report fills this gap, empowering developers and streamlining nested list creation using Google Apps Script (concepts applicable to other languages).
Introduction
The official Google Docs API documentation provides instructions for working with existing lists, including converting paragraphs to lists and removing bullets. However, it lacks guidance on creating nested lists within an empty document body. Ref
Gists

Abstract
Despite the improved Google Apps Script IDE launched in April 2022, challenges arise for HTML and Javascript development. The Script Editor’s built-in formatting for these languages proves insufficient, particularly for large Javascript codebases, potentially causing errors. This report proposes a solution to address this formatting issue and streamline development within the Script Editor.
Introduction
The Google Apps Script Integrated Development Environment (IDE) Script Editor received a significant update on April 13, 2022, transforming it into a more modern and streamlined development experience. Ref This enhanced IDE empowers developers to create custom solutions that extend the capabilities of Google Workspace applications for their organizations.
Gists

Abstract
The Gemini API traditionally required specific prompts for desired output formats. This report explores two new GenerationConfig properties: “response_mime_type” and “response_schema”. These allow developers to directly specify formats like JSON, enhancing control and predictability. We analyze and compare the effectiveness of both properties for controlling Gemini API output formats.
Introduction
One of the key challenges when working with the Gemini API is ensuring the output data is delivered in the format your application requires. Traditionally, the response format heavily relied on the specific prompt you provided. For example, retrieving data as a structured JSON object necessitated including a “Return JSON” prompt within your input text. This approach could be cumbersome and error-prone if the desired format wasn’t explicitly requested.
GeminiWithFiles was updated to v1.0.3.
-
v1.0.3 (May 17, 2024)
- Bugs were removed.
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
ImgApp was updated to v1.3.3.
- v1.3.3 (May 16, 2024)
In SlidesAppp.gs, added a script for checking whether Drive API and Slides API are enabled. Ref
You can see the detail information here https://github.com/tanaikech/ImgApp
Gists

Overview
This script checks if the desired API is enabled or disabled in the Advanced Google Services section of Google Apps Script.
Introduction
As of December 11, 2023, Drive API v3 became available for use in Advanced Google Services. Ref This means you can now choose between v2 and v3 in your scripts. However, when Drive API is enabled, version 3 is automatically selected. This caused compatibility issues with previously published libraries that relied on v2.
PDFApp was updated to v1.0.7.
-
v1.0.7 (May 15, 2024)
- The method of “addPageNumbers” was updated. Ref When a number is used to the property
x instead of “left”, “center”, and “right”, the inputted number is directly used.
You can see the detail information here https://github.com/tanaikech/PDFApp
PDFApp was updated to v1.0.6.
-
v1.0.6 (May 15, 2024)
- A new method of “addPageNumbers” was added. Ref This method adds the page numbers to each page of the PDF.
You can see the detail information here https://github.com/tanaikech/PDFApp
Gists

Description
This is a simple sample script for adding the page numbers to PDF data using Google Apps Script.
When you use this script, please copy and paste the following script to the script editor of Google Apps Script. And, please set the file ID of the PDF file.
Sample script
In this script, pdf-lib is used.
/**
* ### Description
* Add page numbers to PDF.
*
* @param {Object} blob PDF blob.
* @param {Object} pageFormat Format of page number.
* @returns {Blob} Updated PDF blob.
*/
async function addPageNumbers_(blob, pageFormat) {
if (blob.getContentType() != MimeType.PDF) {
throw new Error("Blob is not PDF.");
}
// Load pdf-lib
const cdnjs = "https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js";
eval(
UrlFetchApp.fetch(cdnjs)
.getContentText()
.replace(
/setTimeout\(.*?,.*?(\d*?)\)/g,
"Utilities.sleep($1);return t();"
)
);
const data = new Uint8Array(blob.getBytes());
const pdfData = await PDFLib.PDFDocument.load(data);
const pdfDoc = await PDFLib.PDFDocument.create();
(await pdfDoc.copyPages(pdfData, pdfData.getPageIndices())).forEach(
(page, i) => {
const { width } = page.getSize();
const obj = { center: width / 2, left: 20, right: width - 20 };
const pageFormatObj = { ...pageFormat };
pageFormatObj.x = obj[pageFormat.x];
page.drawText(`${i + 1}`, pageFormatObj);
pdfDoc.addPage(page);
}
);
const bytes = await pdfDoc.save();
return Utilities.newBlob(
[...new Int8Array(bytes)],
MimeType.PDF,
`new_${blob.getName()}`
);
}
// Please run this function.
function sample1() {
const fileId = "###"; // Please set the file ID of the PDF file.
const pdfBlob = DriveApp.getFileById(fileId).getBlob(); // Of course, you can directly give the PDF blob.
const pageFormat = { size: 10, x: "center", y: 10 };
addPageNumbers_(pdfBlob, pageFormat).then((newBlob) =>
DriveApp.createFile(newBlob)
);
}
// This function is a simple demonstration script.
function sample2() {
// Create a sample Google Document.
const tempDoc = DocumentApp.create("tempDoc");
const body = tempDoc.getBody();
for (let p = 0; p < 5; p++) {
body.appendParagraph(`sample text ${p + 1}`).appendPageBreak();
}
tempDoc.saveAndClose();
const pdfBlob = tempDoc.getBlob();
// Add page numbers.
const pageFormat = { size: 10, x: "center", y: 10 };
addPageNumbers_(pdfBlob, pageFormat).then((newBlob) =>
DriveApp.createFile(newBlob)
);
}
- When you run the function
sample1, the page numbers are added to the center of each page.
- When you run the function
sample2, a new Google Document is created including 5 pages. And, the page numbers are added to the center of each page.
- In this sample, a simple format like
{ size: 10, x: "center", y: 10 } is used for the page numbers. Here, the page numbers are put to only “left”, “center”, and “right” of the bottom of the page. But, there are various parameters in DrawTextOptions. Ref So, when you want to customize more, please modify the script.
Gists

Abstract
This report examines leveraging Gemini 1.5 API with Google Apps Script to automate sample input creation during script reverse engineering. Traditionally, this process is manual and time-consuming, especially for functions with numerous test cases. Gemini 1.5 API’s potential to streamline development by automating input generation is explored through applying reverse engineering techniques to Google Apps Script samples.
Introduction
With the release of Gemini 1.5 API, users gained the ability to process more complex data, opening doors for various application developments. This report explores the potential of using Gemini 1.5 API in conjunction with Google Apps Script to achieve reverse engineering for script development and improvement.
GeminiWithFiles was updated to v1.0.2.
-
v1.0.2 (May 7, 2024)
- For generating content,
parts was added. From this version, you can select one of q, jsonSchema, and parts.
- From this version,
systemInstruction can be used.
- In order to call the function call,
toolConfig was added to the request body.
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
UtlApp was updated to v1.0.6.
-
v1.0.6 (May 4, 2024)
- Methods of blobToDataUrl was added. When this method is used, the Blob data can be converted to the data URL.
You can see the detail information here https://github.com/tanaikech/UtlApp
Gists
Overview
This script demonstrates how to insert an animated GIF over cells in a Google Sheet using Google Apps Script.
Description
I recently received a request to create a Google Apps Script for inserting animated GIFs into cells on a Google Sheet. I previously published a sample script on my blog on June 6, 2017. Ref In that script, the animation GIF was inserted using a public link. This new script leverages data URLs, which simplifies the process for using GIFs stored in Google Drive. Since this approach might be helpful to others, I’m sharing it here.
GeminiWithFiles was updated to v1.0.1.
-
v1.0.1 (May 2, 2024)
response_mime_type got to be able to be used for controlling the output format. Ref
You can see the detail information here https://github.com/tanaikech/GeminiWithFiles
Gists

Abstract
This report explores controlling output formats for the Gemini API. Traditionally, prompts dictated the format. A new property, “response_mime_type”, allows specifying the format (e.g., JSON) directly. Testing confirms this property improves control over output format, especially for complex JSON schemas. The recommended approach is to combine a detailed JSON schema with “response_mime_type” for clear and consistent outputs.
Introduction
One of the key challenges when working with the Gemini API is ensuring the output data is in the format your application requires. Traditionally, the response format heavily relied on the specific prompt you provided. For example, retrieving data as a JSON object necessitated including a “Return JSON” prompt within your input text. This approach could be cumbersome and introduce potential errors if the desired format wasn’t explicitly requested.
Overview
This is a Google Apps Script library for Gemini API with files.
A new Google Apps Script library called GeminiWithFiles simplifies using Gemini, a large language model, to process unstructured data like images and PDFs. GeminiWithFiles can upload files, generate content, and create descriptions from multiple images at once. This significantly reduces workload and expands possibilities for using Gemini.
Description
Recently, Gemini, a large language model from Google AI, has brought new possibilities to various tasks by enabling the use of unstructured data as structured data. This is particularly significant because a vast amount of information exists in unstructured formats like text documents, images, and videos.
Gists

Abstract
A new Google Apps Script library, “GeminiWithFiles”, simplifies using the powerful Gemini 1.5 AI model. It lets users directly upload files for content generation or create descriptions for many images at once, making it much faster than prior methods. This is helpful for tasks involving large amounts of text or images.
Introduction
Recently, Gemini, a family of Google’s most capable AI models, has revolutionized various tasks by allowing unstructured data to be used as structured data. This breakthrough is particularly impactful for tasks involving large amounts of text or images.
RichTextAssistant was updated to v1.0.1.
-
v1.0.1 (April 22, 2024)
- From oshliaer’s report, a bug was removed. In the current stage, when RichTextValueBuilder is used, it seems that when
setTextStyle is used after setLinkUrl, the style of the hyperlink is removed while the link is kept. So, it is required to set setLinkUrl after setTextStyle.
You can see the detail information here https://github.com/tanaikech/RichTextAssistant
UtlApp was updated to v1.0.5.
-
v1.0.5 (April 16, 2024)
- Methods of consolidateA1Notations was added. When this method is used, the scattered A1Notations can be consolidated.
You can see the detail information here https://github.com/tanaikech/UtlApp
Gists

Abstract
Consolidate scattered cell references (A1Notation) in Google Sheets for efficiency. This script helps select cells by background color or update values/formats, overcoming limitations of large range lists.
Introduction
When working with Google Spreadsheets, there might be a scenario where you need to process scattered A1Notations (cell addresses in the format “A1”). This could involve selecting cells with specific background colors, updating cell values, or modifying cell formats.
UtlApp was updated to v1.0.4.
-
v1.0.4 (April 13, 2024)
- Updated the methods of convGridRangeToA1Notation. When the sheet name is not given, only the A1Notation is returned.
You can see the detail information here https://github.com/tanaikech/UtlApp
Gists

Abstract
The Gemini API generates different outputs depending on the prompts. This report explains how to use function calling in the new Gemini 1.5 API to control the output format (string, number, etc.) within a script during a chat session. This allows for more flexibility in using the Gemini API’s results.
Introduction
The appearance of Gemini has already brought a wave of innovation to various fields. When the Gemini API returns a response, the format of the response is highly dependent on the input text provided as a prompt. For instance, to retrieve the output value as a JSON object, you need to explicitly include a prompt like “Return JSON” within your input. However, there can be situations where the API doesn’t return the data in the desired format.
Gists

Overview
This Google Apps Script helps identify and analyze regions of colored cells in a Google Sheet.
Description
Recently, I encountered a situation where I needed to identify colored cell regions in Google Sheets. For instance, consider the following spreadsheet:

The region enclosed by the red cells (B2:D4) is a rectangle. In this case, the closed region can be easily identified using a simple script in Google Sheets. However, the region enclosed by the blue cells (H3, I2, J2,,,) is more complex. It consists of multiple disconnected cells that form a single shape. Identifying such irregular shapes using a script can be challenging.
Gists

Abstract
This report explores using Gemini, a new AI model, to parse invoices in Gmail attachments. Traditional text searching proved unreliable due to invoice format variations. Gemini’s capabilities can potentially overcome this inconsistency and improve invoice data extraction.
Introduction
After Gemini, a large language model from Google AI, has been released, it has the potential to be used for modifying various situations, including information extraction from documents. In my specific case, I work with invoices in PDF format. Until now, I relied on the direct search by a Google Apps Script to achieve this task. The script’s process involved:
Gists
Description
This script converts soft breaks to hard breaks in a Google Document using Google Apps Script.
Usage
Follow these steps:
1. Create a New Google Document
Create a new Google Document and open it.
Go to “View” -> “Show non-printing characters” in the top menu to see line breaks in the document body (as shown in the image below).
2. Sample Script
Copy and paste the following script into the script editor of your Google Document.
Gists

Abstract
This report addresses the challenge of appending values to specific columns in Google Sheets when columns have uneven last rows. It offers a Google Apps Script solution with a sample script and demonstration image, enabling efficient and flexible data manipulation.
Introduction
Google Apps Script is a versatile tool that allows for seamless management of various Google Workspace applications, including Docs, Sheets, Slides, Forms, and APIs. Its ability to automate tasks within Google Sheets is particularly powerful.
Gists

Abstract
A new large language model (LLM) called Gemini with an API is now available, allowing developers to analyze vast amounts of data. This report explores trends in Google Apps Script by using the Gemini 1.5 API to analyze questions on Stack Overflow.
Introduction
The release of the LLM model Gemini as an API on Vertex AI and Google AI Studio has opened a world of possibilities. Ref The Gemini API significantly expands the potential of various scripting languages, paving the way for diverse applications. Additionally, Gemini 1.5 has recently been released in AI Studio. Ref We can expect the Gemini 1.5 API to follow suit soon.
Gists

Abstract
The Gemini API allows the generating of text from uploaded files using Google Apps Script. It expands the potential of various scripting languages for diverse applications.
Introduction
With the release of the LLM model Gemini as an API on Vertex AI and Google AI Studio, a world of possibilities has opened up. Ref The Gemini API significantly expands the potential of various scripting languages and paves the way for diverse applications. Also, recently, Gemini 1.5 in AI Studio has been released. Ref In the near future, Gemini 1.5 API will be also released soon.
Gists
Abstract
Gemini API on Vertex AI/Studio unlocks new applications with data retrieval and content generation through function calls. This report explores using the API for reverse engineering with a sample interpreter in Google Apps Script.
Introduction
The recent release of the LLM model Gemini as an API on Vertex AI and Google AI Studio unlocks a vast potential for new applications and methodologies. It significantly expands capabilities across diverse situations, paving the way for groundbreaking applications. Notably, the Gemini API allows data retrieval and content generation through function calls. In my recent report, “Guide to Function Calling with Gemini and Google Apps Script”, I explore function calls as a launchpad for various applications. This report showcases reverse engineering using the Gemini API, with a sample interpreter for creating sample values from a given regex using Google Apps Script.
Gists
Abstract
This report presents a workaround for copying a sheet, including its charts, from Google Spreadsheet “A” to Google Spreadsheet “B” using Google Apps Script.
Description
In this report, I would like to introduce a workaround for the following goal:
- Copying a sheet including charts from Google Spreadsheet “A” to Google Spreadsheet “B” using a script.
In general, when Sheets API is used, all objects of the Spreadsheet can be copied easily. However, when I tested this, I noticed the following problems:
Overview
This is a Google Apps Script library for supporting to use Google APIs with Google Apps Script.
Description
There are numerous powerful Google APIs available today. Google Apps Script streamlines interacting with these APIs through a simplified authorization process. Additionally, advanced Google services integrate seamlessly with Apps Script, making Google APIs highly advantageous for users.
However, utilizing APIs beyond advanced Google services can be challenging for some users. Developing a simpler method for using various Google APIs would significantly increase their accessibility and empower a broader range of users to create diverse applications.
Gists

Abstract
Google offers powerful APIs but using them (except advanced services) can be complex. A new, simpler method would benefit developers creating diverse applications. To address this, I built a Google Apps Script library simplifying API access.
Description
There are numerous powerful Google APIs available today. Google Apps Script streamlines interacting with these APIs through a simplified authorization process. Additionally, advanced Google services integrate seamlessly with Apps Script, making Google APIs highly advantageous for users.
GitHub of OnedriveApp
Gists

Abstract
The Gemini API can now do semantic searches, going beyond content generation. This means it can understand the meaning of your search and provide better results, even if your words don’t exactly match the data. This report introduces the enhanced search capabilities of the Gemini API.
Introduction
The Gemini API expands its potential beyond content generation to encompass powerful semantic search capabilities. Searching existing data is crucial in various situations. However, before the introduction of generative AI, traditional search methods relied solely on keyword matching. Recent advancements in semantic search have introduced similarity search, allowing for a more nuanced understanding of queries. Combining this with the generative power of the Gemini API can significantly enhance the search results of existing data. This report explores the possibilities of enhanced search using the Gemini API.
CorporaApp was updated to v1.0.3.
-
v1.0.3 (March 6, 2024)
- New method of getChunk was added. When this method is used, you can retrieve a single chunk using the resource name of chunk.
You can see the detail information here https://github.com/tanaikech/CorporaApp
Gists

Abstract
Google Apps Script automates tasks like managing protections in Google Spreadsheets. These protections control user access to specific cells. While scripts exist for this purpose, users still encounter challenges, prompting this report. The report aims to introduce techniques for managing protections using sample scripts, helping users understand and implement this functionality.
Introduction
Google Apps Script is a powerful tool that enables seamless management of Google Documents, Spreadsheets, Slides, Forms, APIs, and more. It is particularly effective for automating tasks within Google Spreadsheets. Google Spreadsheets offer cell protection capabilities, allowing you to define editable areas for different collaborators. Google Apps Script can effectively manage these protections. While online resources like Stack Overflow often feature questions related to spreadsheet protection, this report aims to introduce practical techniques through sample scripts. This will help users understand how to manage Google Spreadsheet protections using Google Apps Script.
Gists

Abstract
The Gemini API enables both content generation and semantic search, managing data effectively. This report introduces a Gemini-powered similarity viewer for easy visualization of complex text similarity scores, using Google Spreadsheet and Apps Script.
Introduction
The Gemini API unlocks new possibilities, extending its capabilities beyond content generation to encompass semantic search. Within this context, the API excels at efficiently managing data within corpora. While semantic search provides valuable similarity scores (chunkRelevanceScore) for text pairs, interpreting these numerical values can be cumbersome. This report addresses this challenge by introducing a novel similarity viewer, built upon the powerful trio of Gemini API, Google Spreadsheet, and Google Apps Script. This user-friendly tool allows us to visually represent the similarity of texts, transforming numerical data into an intuitive and easily digestible format.
CorporaApp was updated to v1.0.2.
You can see the detail information here https://github.com/tanaikech/CorporaApp
Gists

Updated on April 26
From this X and this blog, it seems that in the current stage, this situation can be resolved using Sheets API. The sample script of Google Apps Script is as follows. Before you test this, please enable Sheets API at Advanced Google services.
function myFunction() {
// Please set your Spreadsheet ID.
const spreadsheetId = "###";
const requests = [{
updateSpreadsheetProperties: {
properties: { importFunctionsExternalUrlAccessAllowed: true },
fields: "importFunctionsExternalUrlAccessAllowed"
}
}];
Sheets.Spreadsheets.batchUpdate({ requests }, spreadsheetId);
}
As additional information, in this case, when importFunctionsExternalUrlAccessAllowed: true is modified to importFunctionsExternalUrlAccessAllowed: false, an error like Cannot set import functions external URL access allowed from true to false. occurs. It seems that when access is allowed once, this cannot be canceled.
Gists
Abstract
New Gemini API opens doors for developers to integrate its AI power into apps, potentially impacting education, healthcare, and business. The latest Gemini 1.5 brings even more features. This report showcases an image bot using Gemini as one example of its diverse applications. Showcasing its diverse application potential across various fields.
Introduction
The recent release of Gemini as an accessible API on Vertex AI and Google AI Studio empowers developers to integrate its vast capabilities into their applications, potentially revolutionizing fields like education, healthcare, and business. Adding even more powerful features with the recently announced Gemini 1.5, this tool promises even greater impact. Ref and Ref I believe Gemini significantly expands the potential for diverse applications across various fields. To showcase its potential, this report introduces an image bot using Gemini with Google Apps Script and Google Drive. This is just one example of the many compelling use cases developers can build with Gemini.
Gists
Abstract
Powerful AI tool Gemini’s API release (Vertex AI & Google AI Studio) opens doors for diverse applications. Its recent upgrade to version 1.5 boosts capabilities. This report demonstrates using simple Google Apps Script function calls to leverage Gemini’s power for both data retrieval and content generation.
Introduction
The recent release of the LLM model Gemini as an API on Vertex AI and Google AI Studio unlocks a world of possibilities. Ref Excitingly, Gemini 1.5 was just announced, further expanding its capabilities. Ref I believe Gemini significantly expands the potential in various situations and paves the way for diverse applications. Notably, the Gemini API can retrieve new data and generate content through function calls. In this report, I introduce the basic flow of function calling in the Gemini API using a simple Google Apps Script.
CorporaApp was updated to v1.0.1.
You can see the detail information here https://github.com/tanaikech/CorporaApp
Gists

Abstract
New “semantic search” features in Gemini API help find desired information within its corpora. While using these features with Google Apps Script was complex, a new library simplifies the process. This report proposes using this library with Gemini-generated content to automate template processes in Google Docs and Slides, creating a more flexible workflow.
Introduction
The semantic search opens up a new wind for finding the expected values. Recently, the APIs for managing corpora have been added to Gemini API. Ref When the corpora of Gemini API is used, the semantic search can be effectively achieved. Ref However, when the corpora are tried to be used with Google Apps Script, the script is complicated cumbersome. To address this challenge, I have created a library for managing the corpora using Google Apps Script. Ref With this library, managing corpora becomes effortless, requiring only straightforward scripts.
Gists

This is a sample script for converting a contact URL of “person/c###” to a resource name “people/c###” for People API using Google Apps Script.
When you open each contact at Contacts with your browser, you can see the URL like https://contacts.google.com/person/c###################.
Here, you might have a situation where you are required to retrieve the resource name for People API from this URL. But, in the current stage, person/c################### cannot be directly used as the resource name people/c###################. In this report, I would like to introduce a sample script for converting from person/c################### to people/c###################.
PDFApp was updated to v1.0.5.
You can see the detail information here https://github.com/tanaikech/PDFApp
PDFApp was updated to v1.0.4.
You can see the detail information here https://github.com/tanaikech/PDFApp
UtlApp was updated to v1.0.3.
You can see the detail information here https://github.com/tanaikech/UtlApp
Gists

Description
In the current stage, v1beta of Gemini API can use the corpora. Ref When the corpora are used, the values can be searched with the semantic search. In the current stage, 5 corpora can be created in a single project. And, each corpus can have 10,000 documents and 1,000,000 chunks. In this report, I would like to introduce a method for achieving the semantic search using the corpora with Google Apps Script.
DocsServiceApp was updated to v1.2.2
You can see the detail information here https://github.com/tanaikech/DocsServiceApp
Gists

Description
I have published “Flexible Labeling for Gmail using Gemini Pro API with Google Apps Script” on December 19, 2023. Today, I published “Categorization using Gemini Pro API with Google Apps Script”.
In this report, as part 2, I would like to introduce 2 sample scripts for flexible labeling for Gmail using the semantic search and the function calling of Gemini Pro API with Google Apps Script.
Usage
In order to test this script, please do the following flow.
Gists

Abstract
This report explores using the Gemini Pro API with Google Apps Script to achieve flexible data categorization.
Introduction
The recent release of the LLM model Gemini as an API on Vertex AI and Google AI Studio opens a world of possibilities. Ref and Ref I believe Gemini API significantly expands the potential of Google Apps Script and paves the way for diverse applications. In this report, I present the flexible categorization of data using Gemini Pro API with Google Apps Script.
UtlApp was updated to v1.0.2.
You can see the detail information here https://github.com/tanaikech/UtlApp
Gists

Abstract
Gemini API unlocks semantic search for Google Apps Script, boosting its power beyond automation. This report explores the result of attempting the semantic search using Gemini Pro API with Google Apps Script.
Introduction
The recent release of the LLM model Gemini as an API on Vertex AI and Google AI Studio opens a world of possibilities. Ref and Ref I believe Gemini API significantly expands the potential of Google Apps Script and paves the way for diverse applications. In this report, I present a result for attempting the semantic search using Gemini Pro API with Google Apps Script.
Gists

Abstract
Google Apps Script automates tasks (even offline) and builds web apps using spreadsheets as databases. This report presents a basic dining reservation system to illustrate key aspects of web app development with Apps Script, HTML, and Javascript.
Introduction
Google Apps Script is one of the powerful automation tools for achieving the automation process. When Google Apps Script can be used for the situation, even when users are away from their computers, automation can continue thanks to cloud computing. Also, Google Apps Script can manage Google Spreadsheet with Google Spreadsheet service and quickly deploy Web Apps with HTML and Javascript with minimal coding. Ref1 Ref2 When Google Spreadsheet is used as a database and the Web Apps are used as the user interface, various web applications can be created. In this report, in order to help understand the key aspects of building web applications with Google Apps Script, I would like to introduce a simple web application. Here, as a sample, the dining reservation system created by Google Apps Script, HTML, and Javascript is implemented as a web application.
Gists

Abstract
Google Apps Script is one of the strong tools with cloud computing, and it is very useful for various situations. Google Apps Script can be run by various methods. This report introduces how to execute Google Apps Script.
Recently, generative AI has given a lot of new users a chance to use Google Apps Script. If this report helps the users develop applications using Google Apps Script, I’m glad.
Gists
Published: January 6, 2024
Kanshi Tanaike
Introduction
At Stackoverflow, a lot of people post questions and answers to the questions every day. There are various tags in Stackoverflow. A lot of discussions are performed at each tag. Their discussions bring important information and are very useful for a lot of people. As one of the tags, there is “google-apps-script”. I sometimes discuss the questions with that tag. When we see the discussions, we notice that the discussions have changed and progressed over time, because “Google Apps Script” which is the origin of the tag is updated. This report thinks this change is the trend of the tag of “google-apps-script”. This trend includes the number of questions, questioners, answerers, and tags added to the tag of “google-apps-script”. The trend of the tag of “google-apps-script” is deeply related to the progression of Google Apps Script and the various applications for Google Apps Script.
Gists

Description
Recently, Microsoft Docs files (Word, Excel, and PowerPoint files) could be manually edited by opening it on Google Drive using the browser. This is good news for a lot of users. With this situation, the URLs of Microsoft Docs files were changed. For example, when a Microsoft Word file (DOCX) is opened on Google Drive with the browser, the URL is https://docs.google.com/document/d/###/edit. ### of this URL is the file ID of the DOCX file on Google Drive. This URL is the same as that of Google Document while the length of the file ID is different. From this situation, it might be guessed that the Document service of Google Apps Script might be able to be used for DOCX files.
Overview
This is a Google Apps Script library for using Microsoft Docs files (Word, Excel, and PowerPoint files) using Document service, Spreadsheet service, and Slides Service of Google Apps Script.

Description
Recently, Microsoft Docs files (Word, Excel, and PowerPoint files) could be manually edited by opening it on Google Drive using the browser. This is good news for a lot of users. With this situation, the URLs of Microsoft Docs files were changed. For example, when a Microsoft Word file (DOCX) is opened on Google Drive with the browser, the URL is https://docs.google.com/document/d/###/edit. ### of this URL is the file ID of the DOCX file on Google Drive. This URL is the same as that of Google Document while the length of the file ID is different. From this situation, it might be guessed that the Document service of Google Apps Script might be able to be used for DOCX files.
Gists
Description
On December 7, 2020, new IDE has been released. Ref This has been helping users develop various applications using Google Apps Script with the new IDE very much. When it develops scripts and applications using Google Apps Script with the new IDE, it is considered that the existence of JSDoc in the script will be helpful for both the developers and the client users, because it is reflected in the auto-completion. However, when I tried to add the built-in Class objects of Google Apps Script for returning an object using JSDoc, unfortunately, I’m worried that the detailed official documents related to JSDoc for Google Apps Script are few. Ref and Ref In this report, I would like to introduce a method for adding JSDoc for using auto-completion of the built-in Class objects to functions of Google Apps Script.
Gists
Description
When the generated text can be automatically inserted into the cursor position of Google Document, Google Spreadsheet, and Google Slide, it will be useful for users. This report introduces sample scripts for achieving this.
Sample scripts
Here, I would like to introduce 3 sample scripts for a Google Document, a Google Spreadsheet, and a Google Slide.
Create an API key
These sample scripts request Gemini Pro API using an API key. So, please create your API key.
Gists

Abstract
It is considered that when the current error message of Google Apps Script is expanded, it will be useful for a lot of users. This report introduces a sample script for expanding the error message of Google Apps Script using Gemini Pro API with Google Apps Script.
Introduction
The recent release of the LLM model Gemini as an API on Vertex AI and Google AI Studio opens a world of possibilities. Ref and Ref
Gists

Abstract
The release of Gemini API is expected to expand the future of Google Apps Script. This report introduces a sample script for flexible email labeling in Gmail using Gemini API with Google Apps Script.
Introduction
The recent release of the LLM model Gemini as an API on Vertex AI and Google AI Studio opens a world of possibilities. Ref and Ref I believe Gemini API significantly expands the potential of Google Apps Script and paves the way for diverse applications. In this report, I present a sample script for flexible email labeling in Gmail using Gemini Pro API with Google Apps Script.
Gists

Abstract
Gemini LLM, now a Vertex AI/Studio API, unlocks easy document summarization and image analysis via Google Apps Script. This report details an example script for automatically creating the description of the files on Google Drive and highlights seamless integration options with API keys.
Introduction
Recently, the LLM model Gemini has been released and is now available as an API on Vertex AI and Google AI Studio. Ref and Ref This report presents a simple Google Apps Script example for automatically creating descriptions of files on Google Drive using the Gemini Pro API. It is considered that when the description of files on Google Drive can be easily created, it will help users manage a lot of files.
Recently, when Drive API is enabled at Advanced Google services with the script editor, Drive API v3 is automatically used. In the official document, Drive API v3 has already been used. Ref In the current stage, the users can select V3 and V2.
When Drive API v3 is used with Advanced Google services, the following advantages can be considered.
- Drive API v3 can be used with only the scopes for Drive API without adding a scope
https://www.googleapis.com/auth/script.external_request.
- The files and folders can be searched by the search query of
createdTime. Ref
References:
Gists

Description
Google Documents can be managed by the Document service of Google Apps Script. Ref One day, you might have a situation in which you are required to manage the footnotes on Google Documents using Google Apps Script. There are several official documents related to the footnotes for Google Apps Script. Ref and Ref However, unfortunately, I’m worried that it might be difficult a little to understand the management of the footnotes from these documents. Actually, I saw some questions related to the footnotes on Google Documents at Stackoverflow. In this report, I would like to introduce a method for managing the footnotes on Google Documents using Google Apps Script.
Gists

Abstract
One day, you might have a situation where you are required to manage rich texts in Google Spreadsheet using Google Apps Script. In this report, I would like to introduce the basic technique for managing rich texts with Google Apps Script.
Introduction
At Google Spreadsheet, rich texts can be used as a cell value. The rich texts can be also managed by Google Apps Script. Ref When I saw the official document related to the rich texts with Google Apps Script, I’m worried that it might be difficult a little for users to manage the rich texts using Google Apps Script.
PDFApp was updated to v1.0.3.
You can see the detail information here https://github.com/tanaikech/PDFApp
Gists
Abstract
One day, you might have a situation where you are required to make users edit the protected cells using Google Apps Script. This report introduces a workaround for achieving this situation. The key factors for achieving this are as follows. 1. Run the script as the owner of Spreadsheet even when the script is run by a user. 2. In order to run the script as the owner, the installable triggers and the Web Apps are used.
Gists

Description
At Google Spreadsheet, custom functions created by Google Apps Script can be used. Ref When the custom function is used, the users can create a function for expanding the built-in functions for Spreadsheet. One day, you might have a situation for executing the custom function using an array. For example, under the situation that your custom function uses a single value instead of an array as the argument, when you want to use an array for each argument of the custom function, it is required to modify the original script of the custom function or the function calling the custom function. In this report, I would like to introduce a technique of array processing for the custom functions on Google Spreadsheets.
Gists
Description
At Google Spreadsheet, the cells can be merged as one cell. But, when the Spreadsheet including the merged cells is used with Google Apps Script, the script becomes a bit complicated. Also, I sometimes find some questions like this situation on Stackoverflow. In this report, I would like to introduce a technique for easily using the Spreadsheet including the merged cells with Google Apps Script.
Principle
Before it introduces the sample scripts, I would like to introduce the principle for using the Spreadsheet for the merged cells. You can understand the principle of this method from the following sample input and output images.
Gists
Abstract
One day, you might have a situation where you are required to make the shared users upload a file and text using a dialog or sidebar on Google Spreadsheet to your Google Drive and Spreadsheet without authorization by the users. This report introduces a solution for achieving this situation.
Introduction
Google Spreadsheet can run Javascript on a dialog and a sidebar. Ref These can be used as a strong tool for working on Spreadsheet. There might be a situation where you want to make the shared users input a value and upload a file without authorization of the scopes. In this report, I would like to introduce 2 patterns to achieve this goal.
Gists

Abstract
One day, you might have a situation where you are required to update a sheet using Google Apps Script when the cell values retrieved by IMPORTRANGE are changed. This report introduces a workaround for achieving this situation.
Introduction
Google Apps Script can be executed by several triggers. Ref When a cell in a Google Spreadsheet is manually edited, a function of Google Apps Script can be executed by detecting this edit. In most cases, the OnEdit trigger trigger of the simple trigger or the installable trigger is used. When the OnEdit trigger is used, a function can be executed by manually editing a cell. When the function is executed, the function can be run by giving the event object including the information about the edited cell.
Gists

Abstract
This report introduces the method for retrieving the Emoji reactions from the comments in Google Docs files (Google Documents, Google Slides, and Google Spreadsheets) using Google Apps Script.
Introduction
Recently, the Emoji reactions have been implemented in the comments on Google Docs files (Google Documents, Google Slides, and Google Spreadsheets). Ref With this implementation, the collaborative work has been higher. Here, it is considered that when the Emoji reactions can be retrieved from the Google Docs files, the statistics of the reactions will be also more useful for increasing collaboration. This report introduces a sample script for retrieving Comments including the Emoji reactions from Google Docs files.
Gists

Abstract
One day, you might have a situation where you are required to create a Web Apps with Google Apps Script and are required to load another HTML created by Javascript on the Web Apps. This report will help achieve such a situation.
Introduction
Google Apps Script can create Web Apps. Ref When you access the Web Apps using your browser, you can see the HTML. When your browser can run Javascript, you can see the HTML reflecting the Javascript. The Web Apps created by Google Apps Script is one of the important and useful cloud applications. About the Web Apps, you have a situation where it is required to insert another HTML to the current HTML. And, another HTML might be required to be created by Javascript including the HTML. However, it is difficult a little to find detailed information about this. This report introduces a simple sample script for achieving such a situation.
Gists

Abstract
One day, you might have a situation where it is required to run Google Apps Script using the service account. Unfortunately, in the current stage, Google Apps Script cannot be directly run with the service account because of the current specification. So, this report introduces a workaround for executing Google Apps Script using the service account.
Introduction
When you want to execute Google Apps Script from outside of Google, as the basic approach, it can be achieved by Google Apps Script API. Ref In order to use Google Apps Script, it is required to link the Google Apps Script project with the Google Cloud Platform project. Ref But, in the current stage, Google Apps Script can be executed by Google Apps Script API with only the access token obtained from OAuth2. Unfortunately, the access token obtained by the service account cannot used for executing Google Apps Script using Google Apps Script API. It seems that this is the current specification on the Google side. However, there might be a case that it is required to execute Google Apps Script using the service account. In this report, I would like to introduce a workaround for executing Google Apps Script using the service account. In this workaround, the Web Apps created by Google Apps Script is used. The Web Apps can be used for executing the preserved functions of doGet and doPost from outside of Google. Ref In this workaround, this Web Apps is used for executing the various functions.
You can see the detail information here https://github.com/tanaikech/HtmlFormApp
Gists

Abstract
This report introduces the method for managing the histories of the Google Apps Script project.
Description
On August 23, 2023, the project history has been implemented in the new IDE of Google Apps Script. Ref and Ref In the current stage, the users can see the history of the previously deployed script version. This is a very important implementation for a lot of developers.
Here, I remember the classic IDE. In the case of the classic IDE, the users had been able to see the previously saved script version regardless of the deployment and just the save of the script. This is not implemented in the new IDE. I would like to expect that this will be implemented in the future update.
Overview
This is a Google Apps Script library for managing the histories of the Google Apps Script project.

Description
On August 23, 2023, the project history has been implemented in the new IDE of Google Apps Script. Ref and Ref In the current stage, the users can see the history of the previously deployed script version. This is a very important implementation for a lot of developers.
Here, I remember the classic IDE. In the case of the classic IDE, the users had been able to see the previously saved script version regardless of the deployment and just the save of the script. This is not implemented in the new IDE. I would like to expect that this will be implemented in the future update.
Gists

Introduction
This is a report for taking advantage of the auto-completion of the script editor for Google Apps Script.
In the current stage, the auto-completion is implemented in the script editor of Google Apps Script. This auto-completion can be used for not only the built-in classes and methods but also the methods for Javascript. This helps develop scripts and applications very much. In the case of the built-in classes and methods and the methods for Javascript, you can see the detailed specifications of the documents like the official documents and developer.mozilla.org.
Gists

This is a sample script for copying the date object between Google Spreadsheets with the different time zones using Google Apps Script.
One day, you might have a situation in which it is required to copy the date object between Google Spreadsheets with the different time zones using Google Apps Script. In this post, I would like to introduce the sample scripts for achieving this.
Sample situation
Here, the sample situation is declared. In order to test the below scripts, please create 2 Google Spreadsheets.
Gists

This is a sample script for moving the selected cell to the top left on Google Spreadsheet to focus it using Google Apps Script.
One day, there might be a case where you are required to focus the specific cell on Google Spreadsheet to help edit cells. In this post, I would like to introduce a sample script for achieving this.
Sample script
Please copy and paste the following script to the script editor of Google Spreadsheet, and save the script.
Gists

At the Google Apps Script project, the values can be transferred from HTML to Google Apps Script using google.script.run with Javascript. In this case, unfortunately, the values of all types cannot be transferred. In the official document, it says as follows. Ref
Most types are legal, but not Date, Function, or DOM element besides form; see description
Legal parameters are JavaScript primitives like a Number, Boolean, String, or null, as well as JavaScript objects and arrays that are composed of primitives, objects, and arrays. A form element within the page is also legal as a parameter, but it must be the function’s only parameter. Requests fail if you attempt to pass a Date, Function, DOM element besides a form, or other prohibited type, including prohibited types inside objects or arrays. Objects that create circular references will also fail, and undefined fields within arrays become null. Note that an object passed to the server becomes a copy of the original. If a server function receives an object and changes its properties, the properties on the client are not affected.
PDFApp was updated to v1.0.2.
-
v1.0.2 (August 21, 2023)
- A new method of
insertHeaderFooter was added. Ref When this method is used, the custom header and footer can be added when a Google Spreadsheet is exported as PDF.
You can see the detail information here https://github.com/tanaikech/PDFApp
Gists

This is a sample script for adding header and footer to PDF using Google Apps Script.
In the current stage, when Google Spreadsheet is manually exported as a PDF file at “Print settings” on the UI of Spreadsheet, the custom header and footer can be added as shown in the following image.

But, unfortunately, in the current stage, this cannot be directly achieved by Google Apps Script. So, I created this sample script. This sample script uses pdf-lib of Javasscript library.
PDFApp was updated to v1.0.1.
-
v1.0.1 (August 18, 2023)
- About the method of “getMetadata”,
pageInfo is added to the retrieved metadata. By this, each page size can be obtained.
You can see the detail information here https://github.com/tanaikech/PDFApp
TriggerApp was updated to v1.0.1.
-
v1.0.1 (August 18, 2023)
- When
toDay is not used, there was a case that the next trigger is not installed. This bug was removed.
You can see the detail information here https://github.com/tanaikech/TriggerApp
Overview
This is a Google Apps Script library for managing PDFs.

Description
Google Apps Script is one of the most powerful tools for cloud computing. When Google Apps Script is used, the result can be obtained even when the user doesn’t stay in front of the PC and mobile phone by the triggers. One day, there might be a case where it is required to manage PDF data using Google Apps Script. The combination of Google Docs (Document, Spreadsheet, and Slide) and PDFs is useful for various situations. However, unfortunately, there are no built-in methods for directly managing PDFs using Google Apps Script. Fortunately, it seems that pdf-lib of the Javascript library can be used with Google Apps Script. By this, PDF data can be managed with Google Apps Script using this library. This Google Apps Script library manages PDFs by using it as a wrapper between Google Apps Script and pdf-lib.
Gists

Abstract
When PDF file can be managed with Google Apps Script, that will lead to the automation process on cloud. In this report, the method for cooking PDF over Google Apps Script.
Introduction
Google Apps Script is one of the strong tools for achieving the automation process. When Google Apps Script can be used for the situation, it can be processed with cloud computing. By this, the users are not required to stay on the desks with the PC. One day, there might be a case where you are required to manage PDF files using Google Apps Script. When PDF files can be managed with Google Apps Script, that will be very important for achieving the automation process. Unfortunately, there are no built-in methods for directly managing PDF data using Google Apps Script. Fortunately, after the V8 runtime has been released, several raw Javascript libraries could be used with Google Apps Script. pdf-lib is also one of them. When this is used, PDF data can be cooked over Google Apps Script. In this report, I would like to introduce achieving this using a Google Apps Script library.
Gists

Description
In this report, I would like to introduce a sample script for efficiently deleting rows by conditions on Google Spreadsheet using Google Apps Script. Recently, I had a situation for being required to achieve this situation. In my report, it has already known that when Sheets API is used, the rows can be efficiently deleted by a condition. Ref However, in that case, Sheets API couldn’t be used. Under this situation, I came up with a method. In this report, I would like to introduce this method.
My report “Easily Managing Time-Driven Triggers Using Google Apps Script” has been featured in “Community Spotlight” of Google Workspace Developer Newsletter on July 2023
https://developers.google.com/workspace/newsletters#expandable-2
Gists

This is a sample script for embedding the objects in PDF using Google Apps Script.
Recently, I had a situation where it is required to manage PDFs using Google Apps Script. At that time, I had a situation where it is required to embed objects of texts and images in PDF using Google Apps Script. So, I created the following Class with Google Apps Script. When this Class is used, the objects of texts and images can embed in PDF.
Gists

This is a sample script for creating PDF forms from a Google Slide template using Google Apps Script.
Recently, I had a situation where it is required to create a custom PDF form. In that case, I thought that when a PDF form can be created from a template, it might be useful. So, I created the following Class with Google Apps Script. When this Class is used, a custom PDF form can be easily created from a Google Slide as a template.
Gists

This is a sample script for retrieving and putting values for PDF Forms using Google Apps Script.
PDF can have the PDF Form for inputting the values in the PDF by the user. Ref Recently, I had a situation that required me to retrieve and put the values to the PDF Form using Google Apps Script. In order to achieve this, I created a Class object with Google Apps Script. That is as follows.
GitHub of OnedriveApp
Gists

This is a sample script for changing the order of pages in a PDF file using Google Apps Script.
Sample script
Before you run this script, please set the variables in the function main.
/**
* ### Description
* Changing order of pages in a PDF file.
*
* @param {Object} fileId is file ID of PDF file. newOrderOfpages is new order of pages. About "ignoreSkippedPages", if this is false, when the PDF has 5 pages and "newOrderOfpages" is "[3, 2]", the exported PDF file has 5 pages of 3, 2, 1, 4, 5. If this is true, when the PDF has 5 pages and "newOrderOfpages" is "[3, 2]", the exported PDF file has only 2 pages of 3 and 2.
* @return {void}
*/
async function changeOrderOfPDFPages_({
fileId,
newOrderOfpages,
ignoreSkippedPages,
}) {
// Load pdf-lib
const cdnjs = "https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js";
eval(UrlFetchApp.fetch(cdnjs).getContentText()); // Load pdf-lib
const setTimeout = function (f, t) {
Utilities.sleep(t);
return f();
};
const blob = DriveApp.getFileById(fileId).getBlob();
const pdfData = await PDFLib.PDFDocument.load(
new Uint8Array(blob.getBytes())
);
const numberOfPages = pdfData.getPageCount();
const maxPage = Math.max(...newOrderOfpages);
if (numberOfPages < maxPage || numberOfPages < newOrderOfpages.length) {
throw new Error(
"Maximum page in the order of pages is over than the maximum page of the original PDF file."
);
}
let skippedPages = [];
if (!ignoreSkippedPages && numberOfPages > newOrderOfpages.length) {
skippedPages = [...Array(numberOfPages)]
.map((_, i) => i + 1)
.filter((e) => !newOrderOfpages.includes(e));
}
const pdfDoc = await PDFLib.PDFDocument.create();
const pages = await pdfDoc.copyPages(
pdfData,
[...Array(numberOfPages)].map((_, i) => i)
);
[...newOrderOfpages, ...skippedPages].forEach((e) =>
pdfDoc.addPage(pages[e - 1])
);
const bytes = await pdfDoc.save();
return Utilities.newBlob(
[...new Int8Array(bytes)],
MimeType.PDF,
"sample.pdf"
);
}
function main() {
const fileId = "###"; // Please set a file ID of your a PDF file or a file ID of Google Docs files (Document, Spreadsheet, Slide).
const newOrderOfpages = [3, 1, 2, 5, 4]; // Please set new order of the pages in a PDF file. In this sample, the order of pages of the original PDF file is changed to 3, 1, 2, 5, 4.
const ignoreSkippedPages = false; // If this is false, when the PDF has 5 pages and "newOrderOfpages" is "[3, 2]", the exported PDF file has 5 pages of 3, 2, 1, 4, 5. If this is true, when the PDF has 5 pages and "newOrderOfpages" is "[3, 2]", the exported PDF file has only 2 pages of 3 and 2.
changeOrderOfPDFPages_({ fileId, newOrderOfpages, ignoreSkippedPages }).then(
(blob) => {
DriveApp.createFile(blob.setName("sample.pdf"));
}
);
}
When this script is run, a new PDF file is created with the new order of pages.
GitHub of OnedriveApp
Gists

Here, I would like to introduce a report for understanding the flow of the request to Web Apps created by Google Apps Script. There might be a case that various applications using the Web Apps are created and the Web Apps are used as the webhook. In that case, it is considered that when you have understood the flow of requests to the Web Apps, your goal might be able to be smoothly achieved. In this report, I would like to introduce the information about it.
Gists

This is a sample script for managing the metadata of PDF data using Google Apps Script.
There might be a case in that you want to retrieve and update the metadata of PDF data using Google Apps Script. In this post, I would like to introduce achieving this.
This is a Class ManagePdfMetadata. This Class is used for managing the metadata of PDF files using Google Apps Script. And, in this Class, a Javascript library of pdf-lib is used for managing the PDF metadata. This Javascript library is loaded in this Class.
Gists

This is a sample script for checking the overwrapped cells of multiple ranges on Google Spreadsheet using Google Apps Script.
When applications are developed, there might be a case that it is required to confirm whether 2 ranges on Google Spreadsheet are overwrapped. In this post, I would like to introduce a sample script for achieving this.
Method: getOverwrappedCells
The following script is a method of getOverwrappedCells. This is the main script of this post. This method returns the information about the overwrapped cells by inputting an array including the Class Range object. For example, as the default response, when each cell in “range1” and “range2” is overwrapped, true is returned. When { responseType: "list" } is used, the cell coordinates of the overwrapped cells are returned as an array.
Gists
This is a sample script for automatically refreshing the basic filter on Google Spreadsheet using Google Apps Script.
Description
A sample situation is as follows.

In this sample, the basic filter is set to columns “B” and “D”.
- Column “B”: When the checkbox is checked, the row is hidden.
- Column “D”: When the cell value is multiples of 3, the row is hidden. In this case, the custom function
=MOD(E2,3)<>0 is used.
For example, under the condition that the basic filter is set to columns “B” and “D”, even when a checkbox of “B3” is checked, unfortunately, the basic filter is not automatically refreshed. In this case, it is required to manually refresh it.
Overview
This is a Google Apps Script library for efficiently managing the time-driven triggers for executing Google Apps Script using Google Apps Script.

Description
Google Apps Script can execute with not only the manual operation but also several triggers. The time-driven trigger is one of them, and this is one of a lot of important functions. When the time-driven trigger is used, Google Apps Script can be automatically executed at the time you set without launching the user’s PC.
Gists

This is a sample script for exporting the specific pages from a PDF as a new PDF using Google Apps Script.
In this sample script, pdf-lib is used. In the current stage, it seems that this Javascript can be directly used with Google Apps Script.
Sample script
async function myFunction() {
// Retrieve PDF data.
const fileId = "###"; // Please set a file ID of your a PDF file or a file ID of Google Docs files (Document, Spreadsheet, Slide).
const pageNumbers = [2, 4]; // In this sample, 2 and 4 pages are exported as a PDF.
const blob = DriveApp.getFileById(fileId).getBlob();
// Merge PDFs.
const cdnjs = "https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js";
eval(UrlFetchApp.fetch(cdnjs).getContentText()); // Load pdf-lib
const setTimeout = function (f, t) {
Utilities.sleep(t);
return f();
};
const pdfDoc = await PDFLib.PDFDocument.create();
const pdfData = await PDFLib.PDFDocument.load(
new Uint8Array(blob.getBytes())
);
const pages = await pdfDoc.copyPages(
pdfData,
[...Array(pdfData.getPageCount())].map((_, i) => i)
);
pages.forEach((page, i) => {
if (pageNumbers.includes(i + 1)) {
pdfDoc.addPage(page);
}
});
const bytes = await pdfDoc.save();
// Create a PDF file.
DriveApp.createFile(
Utilities.newBlob([...new Int8Array(bytes)], MimeType.PDF, "sample.pdf")
);
}
Gists
This is a sample script for converting various images to PNG Format and JPEG format using Google Apps Script.
The flow of this sample script is as follows.
- Convert the file to PNG format by the thumbnail link.
- Convert PNG format to JPEG format if
outputFormat is “JPEG”.
- Create the image data in the JPEG format in the root folder as a file.
Sample script
Please set your file ID and output format.
Gists

This is a sample script for copying a Google Spreadsheet including a container-bound script by removing the container-bound script using Google Apps Script.
When you want to copy a Google Google Spreadsheet including a container-bound script by removing the container-bound script using Google Apps Script, this could be achieved by using “get” and “create” methods of Sheets API before. The sample script is as follows.
const obj = Sheets.Spreadsheets.get(
SpreadsheetApp.getActiveSpreadsheet().getId(),
{ fields: "namedRanges,properties,sheets" }
);
Sheets.Spreadsheets.create(obj);
But, in the current stage, I noticed that this cannot be used. Because, in the current stage, the smart chips are implemented. In this case, Sheets API cannot be retrieved them as an object by the current specification. So, I would like to introduce a sample script as the current workaround.
Gists
This is a sample script for notifying the new release of Google APIs and Google Apps Script with an email using Google Apps Script.
Recently, I published a sample script of “Retrieving Release Notes of Google Apps Script and Google APIs from RSS using Google Apps Script”. After this was published, I got an email that it wants to automatically notice the new release of Google APIs and Google Apps Script with an email. From this, I prepared a sample script as follows.
Gists
This is a sample script for managing the row height and the column width of a table on Google Slides using Google Apps Script.
In the current stage, Google Slides service (SlidesApp) cannot manage the row height and the column width of the table on Google Slides, while the table width and height can be managed. But, fortunately, when Google Slides API is used, this can be achieved.
In this post, I would like to introduce a sample script for managing the row height and the column width of a table on Google Slides using Google Apps Script.
Gists

This is a sample script for converting the relative reference to the absolute reference and vice versa of A1Notation on Google Spreadsheet using Google Apps Script.
Description
A1Notation is used in the cells on Google Spreadsheet.
As the 1st sample, it supposes that a formula of =A1 is put into a cell “B1”. Under this condition, when the cell “B1” is copied to “B2” and “C1”, the cells “B2” and “C1” have the formulas of =A2 and =B1, respectively. This is the relative reference.
Gists
This is a sample script for comparing the file contents of files on Google Drive using Google Apps Script.
Sample script
Before you use this script, please enable Drive API at Advanced Google services. And also, please set the file IDs you want to check whether the file contents of the files are the same.
function checkFiles_(f, checks = ["md5Checksum", "sha1Checksum", "sha256Checksum"]) {
files = f.map(id => DriveApp.getFileById(id));
const fields = [...checks, "id"].join(",");
const o = files.reduce((o, f) => {
const mimeType = f.getMimeType();
if (["FOLDR", "SHORTCUT"].some(m => mimeType == MimeType[m])) {
throw new Error("Folders cannot be checked.");
}
let obj;
if (mimeType.includes("application/vnd.google-apps")) {
const name = f.getName();
f.setName("temp");
Utilities.sleep(2000);
obj = Drive.Files.insert({ title: "temp", mimeType: MimeType.PDF }, f.getBlob(), { supportsAllDrives: true, fields });
f.setName(name);
Drive.Files.remove(obj.id); // If an error occurs, please use DriveApp.getFileById(obj.id).setTrashed(true);
} else {
obj = Drive.Files.get(f.getId(), { supportsAllDrives: true, fields });
}
checks.forEach(e => o[e] = o[e] ? [...o[e], obj[e]] : [obj[e]]);
return o;
}, {});
return Object.values(o).every(e => [...new Set(e)].length == 1);
}
// Please run this function.
function main() {
const file1 = "###fileId1###"; // Please set your file ID of file 1.
const file2 = "###fileId2###"; // Please set your file ID of file 2.
const check = checkFiles_([file1, file2]);
const res = `"${file1}" and "${file2}" are${
check ? " " : " not "
}the same data.`;
console.log(res);
}
Gists
This is a sample script for exporting Google Documents as HTML with the image hyperlinks using Google Apps Script.
Recently, it seems that the specification for exporting Google Documents as HTML data has been changed. When a Google Document are exported as HTML data before, the images in the Google Document were the image hyperlinks, which are publicly shared. But, in the current stage, when a Google Document is exported as HTML data, the images in the Google Document are the data URL (base64 data) of the images. I guess that this might be related to enhancing the security. When the Google Document is exported as a ZIP file, the HTML and images are separated. But, in this case, the images are required to be included in a specific folder like “/images”. I’m worried that this might bring another issue.
Gists
This is a sample script for retrieving the release notes of Google Apps Script and Google APIs from RSS using Google Apps Script.
Recently, the release notes of Google Apps Script and Google APIs have been published as RSS. By this, the data got to be able to be easily retrieved using XmlService of Google Apps Script. Knowing the latest release notes will be useful for developing the applications. So, I would like to introduce the sample script for retrieving this information.
Gists

This is a sample script for inserting the paragraphs with the checkboxes in Google Documents using Google Apps Script.
In the current stage, Google Documents can create paragraphs with checkboxes as the paragraph bullet. But, unfortunately, this cannot be created by the Google Document service (DocumentApp). Fortunately, it seems that this got to be able to be achieved by Google Docs API. In this post, I would like to introduce a sample script for this.
Overview
This is a Google Apps Script library for easily managing the template of Google Documents and Google Slides using Google Spreadsheet as a database using Google Apps Script.
Description
You might have situations where are required to create multiple Google Documents and Google Slides from the templates using Google Spreadsheet as a database with Google Apps Script. When the simple texts are replaced with the placeholders on the templates, this can be achieved by a simple script. However, there is the case that the images are required to be inserted into the templates. In this case, the script is complicated. The method for replacing the placeholders with the images is different between Google Documents and Google Slides. And, when I see questions on Stackoverflow, a lot of questions related to the template process using Google Documents and Google Slides can be seen. Furthermore, I personally have a lot of questions related to this from other users. From this situation, I thought that when managing the template process can be simply run, it will be useful for a lot of users. So, I created this library.
My report has been published at Champion Innovators Content Library and Google Cloud Medium publication.
If these reports will be useful, I’m glad.
Gists
Abstract
Recently, I felt a change like never before in the questions on Stackoverflow. In order to confirm this, in this report, the trend of “google-apps-script” tag on Stackoverflow in the first half (January 1st to June 1st) of 2023 has been investigated. From this report, in 2023 when the affection of COVID-19 has been reduced socially, the appreciable trend was confirmed to the questions including a tag of “google-apps-script”. It is guessed that the origin of this appreciable trend is due to AI chatbots. The appearance of AI chatbots might give us a phase of major change to the method for understanding the statistical data obtained from online sites.
Gists

Abstract
This report introduces the method for easily implementing HTML forms with a Google Spreadsheet as a database using Google Apps Script. There are 2 patterns for the HTML form using Google Apps Script. One is that an HTML form is put into the same Google Apps Script project. Another is that an HTML form is put to a different server from a Google Apps Script project. In this report, the methods for easily implementing both patterns are introduced using the sample scripts.
-
v1.0.1 (May 29, 2023)
- When multiple files are uploaded, each URL was set as the hyperlink.
You can see the detail information here https://github.com/tanaikech/HtmlFormApp
Gists

Abstract
In this report, the detailed specification of PropertiesService has been investigated. It is considered that knowing this specification will be useful for developing applications with Google Apps Script. As a result, it was found that the maximum key and value sizes are 524,287 bytes with a 1-byte key and 8,066 bytes, respectively. And also, it was found that the maximum size of PropertiesService is required to be considered with both the key and value sizes.
My report has been published at Champion Innovators Content Library and Google Cloud Medium publication.
If these reports will be useful, I’m glad.
Gists

This is a sample script for converting Google Spreadsheet to an HTML table using Google Apps Script.
There is the case that it is required to convert a sheet in a Google Spreadsheet to an HTML table. For example, there might be a situation that a sheet in a Google Spreadsheet is sent as an email including an HTML table. And, there might be a situation in which a sheet in a Google Spreadsheet is published to an HTML page including the converted HTML table. I have published the method for achieving this before. Ref But, in that case, the column width, the row height, merged cells, and the images in the cells couldn’t be used. When those are included in the script, the script becomes complicated. So, I couldn’t include it. But, recently, I have come up with a simple method for achieving this. In this post. I would like to introduce a sample script for converting a sheet in a Google Spreadsheet to HTML.
My report has been published at Champion Innovators Content Library and Google Cloud Medium publication.
If these reports will be useful, I’m glad.
Overview
This is a Google Apps Script library including useful scripts for supporting to development of applications by Google Apps Script. In the current stage, the 3 categories “For array processing”, “For binary processing”, and “For string processing” are included in this library.

Description
When I create applications using Google Apps Script, there are useful scripts for often use. At that time, I thought that when those scripts can be simply used, they will be useful not only to me but also to other users. From this motivation, I created a Google Apps Script library including those scripts. But, I have been using these useful scripts only in my development before.
Gists

This is a sample script for converting the values on Google Spreadsheet as unpivot (reverse pivot) using Google Apps Script.
Sample script 1:
const SAMPLE1 = ([[, ...header], ...values]) =>
header.flatMap((h, i) => values.map((t) => [h, t[0], t[i + 1]]));
- In the sample, the source data is “A1:D8”. And, a custom function of
=SAMPLE1(A1:D8) is put into “F1”.
- When this script is used, the result showing the above image (most left table to middle table) is obtained.
Sample script 2:
const SAMPLE2 = v => {
const [a, b, c] = v[0].map((_, c) => v.map(r => r[c]));
const ch = [...new Set(a)];
const rh = [...new Set(b)];
const size = rh.length;
const values = [...Array(Math.ceil(c.length / size))].map(_ => c.splice(0, size));
const temp = [[null, ...rh], ...values.map((vv, i) => [ch[i], ...vv])];
return temp[0].map((_, c) => temp.map(r => r[c]));
}
- In the sample, the source data is “F1:H21”. And, a custom function of
=SAMPLE2(F1:H21) is put into “J1”.
- When this script is used, the result showing the above image (middle table to most right table) is obtained.
Gists
Abstract
It has already been known that Google Apps Script is a strong tool for managing Google Spreadsheets. When the values are retrieved and/or put for Google Spreadsheet, there is a case that the discontinuous cells are required to be used. This report suggests the Best Practices for processing the discontinuous cells on Google Spreadsheet. From the results of process costs, it could understand the usefulness of using the discontinuous cells with low cost using Sheets API and Class RangeList of Spreadsheet service with Google Apps Script.
My report has been published at Champion Innovators Content Library.
If these reports will be useful, I’m glad.
Gists

These are sample scripts for putting an image into a cell of a Spreadsheet using Google Apps Script.
Sample 1
In this sample, the image is put into a cell using thumbnailLink retrieved by Drive API. So, when you test this, please enable Drive API at Advanced Google services. The image is put into cell “A1”.
function sample1() {
const fileId = "###"; // Please set the file ID of the PNG image file on Google Drive.
const url = Drive.Files.get(fileId).thumbnailLink.replace("=s220", "=s1000");
const image = SpreadsheetApp.newCellImage().setSourceUrl(url).build();
const range = SpreadsheetApp.getActiveSheet().getRange("A1");
range.setValue(image);
const value = range.getValue();
console.log(value.getUrl()); // ---> null
console.log(value.getContentUrl()); // --> Exception: Unexpected error while getting the method or property getContentUrl on object SpreadsheetApp.CellImage.
}
Sample 2
In this sample, the image is put into a cell using the data URL. The image is put into cell “A1”. In this case, I believe that when the data URL is used, this method will be able to be used for various situations.
Gists
This is a workaround for automatically installing the OnEdit trigger to the copied Google Spreadsheet using Google Apps Script.
The sample situation for this workaround is as follows.
- You have a Google Spreadsheet.
- Your Spreadsheet is shared with a user as the writer.
- Your Spreadsheet has a button for executing a script for copying the active Spreadsheet.
- Your Spreadsheet has a function
installedOnEdit for executing by the installable OnEdit trigger.
- You want to make the user copy the active Spreadsheet by clicking the button, and also, you want to automatically install the OnEdit trigger to
installedOnEdit for the copied Spreadsheet, simultaneously.
This method is from “Using OnEdit Trigger to Google Spreadsheet by Hiding Google Apps Script from Other Users (Author: me)” and “Using OnEdit trigger on Google Spreadsheet Created by Service Account (Author: me)”.
Gists

In this post, I would like to introduce a sample script for putting Time-based One-time Password (TOTP) value into Google Spreadsheet using Google Apps Script.
In this sample script, I used a Javascript library of https://github.com/hectorm/otpauth
. In the current stage, Google Apps Script can run with V8 runtime. By this, it seems that this library can be used with Google Apps Script.
Sample script
function myFunction() {
const secret = "ABCDEFGHIJKLMN23"; // Please set your secret here.
const n = 3; // Code is created 5 times every 30 seconds.
// Loading otpauth.umd.min.js (Ref: https://github.com/hectorm/otpauth)
const cdnjs =
"https://cdnjs.cloudflare.com/ajax/libs/otpauth/9.1.1/otpauth.umd.min.js";
eval(UrlFetchApp.fetch(cdnjs).getContentText());
const sheet = SpreadsheetApp.getActiveSheet();
let c = n;
while (c > 0) {
const now = new Date();
const code = new OTPAuth.TOTP({
secret,
algorithm: "SHA1",
digits: 6,
period: 30,
}).generate();
const [start, end] = [now, new Date(now.getTime() + 30000)].map((e) =>
Utilities.formatDate(e, Session.getScriptTimeZone(), "HH:mm:ss")
);
sheet.appendRow([code, `Limit: ${start} - ${end}`]);
SpreadsheetApp.flush();
c--;
if (c > 0) Utilities.sleep(30000);
}
sheet.appendRow(["Done."]);
}
Testing
When this script is run, the situation of the above demonstration is obtained.
Gists

In the current stage, Google Spreadsheet can use rich texts in cells. The rich texts can be also managed by Google Apps Script. But, I thought that creating a script for editing the existing rich text in the cell might be a bit complicated. Because, for example, in the current stage, when the text of the rich text of a cell is changed using a script, all text styles are cleared. In order to add and delete a text for the rich text in a cell, it is required to create a script while the current text style is kept. This is actually complicated. In this post, I would like to introduce the enriched management of rich text on Google Spreadsheet using Google Apps Script. In order to enrich the management of Rich Text using Google Apps Script, I created a library RichTextAssistant.

Overview
This is a GAS library for supporting editing RichText in Google Spreadsheet using Google Apps Script.
Description
There is RichTextApp in my published libraries. RichTextApp can be used mainly for converting RichText to Google Documents and vice versa. This library RichTextAssistant will support editing the rich text in Google Spreadsheets using Google Apps Script. Google Spreadsheet can use rich text as the cell value using Google Apps Script. But, I thought that when I created a script for editing the existing rich text in the cell, it might be a bit complicated. Because, for example, in the current stage, when the text of rich text of a cell is changed using a script, all text styles are cleared. In order to add and delete a text for the rich text in a cell, it is required to create a script while the current text style is kept. This is actually complicated. From this situation, when a script for supporting editing the rich text in a cell is published, it will be useful for a lot of users. So, I created it and published it as “RichTextAssistant” of a Google Apps Script library.
Gists

This is a sample script for the folder picker using jsTree with Google Apps Script and Javascript.
I have already published “File Picker using Google Apps Script and Javascript without 3rd party”. In this post, jsTree is used.
Usage
1. Install Google Apps Script library.
In this script, “FilesApp” of my Google Apps Script library is used. So, please install it. You can see how to install it at here.
Gists
When a value is searched from the 1-dimensional array and a 2-dimensional array, after V8 runtime could be used, I use JSON object, Set object, and Map Object. But, I had never measured the process cost of this situation. In this post, I would like to introduce the process cost for searching a value using a JSON object, Set object, and Map object converted from the 1-dimensional array and 2-dimensional array.
Gists

This is a sample script for importing Microsoft Excel (XLSX) data to Google Spreadsheet using a custom function with Google Apps Script.
Usage
1. Install SheetJS library.
Please copy the script of the SheetJS library from https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js, and paste the script to the script editor of Google Spreadsheet, and save the script.
In this case, I would like to recommend the following flow.
- Add a new script to the script editor. For example, the filename is
SheetJS.
- Copy and paste the script of https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js to the added script file, and save the script.
- Copy and paste the following sample script of the custom function to the other script file (It’s the default script file (
Code.gs)).
2. Prepare custom function.
Please copy and paste the following script to the script editor of Google Spreadsheet (this is the same Spreadsheet installed SheetJS library.) and save the script. And, please reopen Google Spreadsheet.
Gists
Updated on July 8, 2023
In the current stage, unfortunately, the built-in methods of Google Apps Script cannot directly retrieve the values from the XLSX data. From this situation, I have created DocsServiceApp. When this Google Apps Script library is used, the values are directly retrieved from XLSX data by parsing XML data of XLSX data.
Here, as another approach, I would like to introduce a sample script for directly retrieving the values from XLSX data using SheetJS with Google Apps Script. In the current stage, Google Apps Script can run with V8 runtime. By this, it seems that SheetJS can be used.
Gists

In Google Spreadsheet, when a single quote is added to the top letter of the cell value, the cell is used as the text value. About detecting this, I have already reported in this post in my blog. In this post, I would like to introduce a sample script for removing the single quote at the top character of the cell value.
Sample script:
function sample() {
const sheetName = "Sheet1"; // Please set your sheet name.
const range = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName(sheetName)
.getDataRange();
range
.createTextFinder("^'{1,}")
.useRegularExpression(true)
.replaceAllWith("");
range.setValues(range.getValues());
}
- In this script, for example,
'001, '''001, 'abc, and '''abc are converted to 1, 1, abc, and abc, respectively.
Reference:
Gists
This is a sample script for splitting the binary data with search data using Google Apps Script.
Sample script
/**
* Split byteArray by a search data.
* @param {Array} baseData Input byteArray of base data.
* @param {Array} searchData Input byteArray of search data using split.
* @return {Array} An array including byteArray.
*/
function splitByteArrayBySearchData_(baseData, searchData) {
if (!Array.isArray(baseData) || !Array.isArray(searchData)) {
throw new Error("Please give byte array.");
}
const search = searchData.join("");
const bLen = searchData.length;
const res = [];
let idx = 0;
do {
idx = baseData.findIndex(
(_, i, a) => [...Array(bLen)].map((_, j) => a[j + i]).join("") == search
);
if (idx != -1) {
res.push(baseData.splice(0, idx));
baseData.splice(0, bLen);
} else {
res.push(baseData.splice(0));
}
} while (idx != -1);
return res;
}
// Please run this function.
function main() {
const sampleString = "abc123def123ghi123jkl";
const splitValue = "123";
const res1 = splitByteArrayBySearchData(
...[sampleString, splitValue].map((e) => Utilities.newBlob(e).getBytes())
);
const res2 = res1.map((e) => Utilities.newBlob(e).getDataAsString());
console.log(res1); // [[97,98,99],[100,101,102],[103,104,105],[106,107,108]]
console.log(res2); // ["abc","def","ghi","jkl"]
}
-
When main() is run, the sample input values of "abc123def123ghi123jkl" is split by "123". And, [[97,98,99],[100,101,102],[103,104,105],[106,107,108]] is obtained. In this case, when [[97,98,99],[100,101,102],[103,104,105],[106,107,108]] is converted to the string for confirming the result value, it becomes ["abc","def","ghi","jkl"].
Gists
This is a sample script for exporting Google Docs files (Spreadsheets, Documents, and so on) in PDF format with batch requests using Google Apps Script.
I have published a report “Efficient File Management using Batch Requests with Google Apps Script”. In this report, I mentioned how to use the batch requests using Google Apps Script.
In this post, I would like to introduce the method for retrieving binary data using this method.
BatchRequest was updated to v1.2.1.
-
v1.2.1 (March 8, 2023)
- An option of
exportDataAsBlob was added to the request object to the method of EDo(). Ref When this option is used, the response values from the batch requests are returned as Blob. By this, for example, when you export Google Spreadsheet as PDF data using the batch requests, the PDF data can be retrieved as Blob.
Sample script using exportDataAsBlob
In this sample, the Spreadsheet and Document files are exported as PDF format using the batch requests. The exported PDF data is created as a PDF file to the root folder. When I answered this thread on Stackoverflow, when this option is added to this library, I thought that it might be useful for users.
Gists
This is a sample script for retrieving the total file sizes in the specific folder of Google Drive using Google Apps Script.
There is a case where you want to retrieve the total file sizes in the specific folder of Google Drive using Google Apps Script. In this post, I would like to introduce a sample script for achieving this.
Sample script
Before you use this script, please enable Drive API at Advanced Google services. And please install FilesApp of a Google Apps Script library.
Gists

This is a sample script for retrieving the start and end row numbers of the same values in a column on Google Spreadsheet using Google Apps Script.
There is a case in that I want to retrieve the rows of the same values in a column on Google Spreadsheet using Google Apps Script. In this post, I would like to introduce a simple sample script for achieving this.
Gists
Today, I discussed with Riël Notermans an issue with the HTML form with the input tab of type="file" with google.script.run. Through this discussion, the reason for this issue could be found. When you use the input tab of type="file" in the HTML form, and you want to send the file content with google.script.run, I thought that this post might be useful for other users. So, I posted it here.
Gists
This sample script decrypts the salted base64 data of finance.yahoo.com using Google Apps Script.
Recently, it seems that the specification of the key for decrypting the data has been changed on the server side, again. In this update, I looked for the logic for retrieving the key value. But, I cannot still find it. So, in this post, I would like to use a workaround discussed in this thread. In this thread, the valid keys are listed in a text file. Using this, I updated the script as follows.
Gists

This is a sample script for putting the values of all Spreadsheets in a folder to the master Spreadsheet with a low process cost using Google Apps Script.
There is a case in that I want to collect the values from multiple Spreadsheets and put the values into the master Spreadsheet. When this situation is achieved by Google Apps Script, as the general method, the values are required to be retrieved from each Spreadsheet in a loop. In the current stage, even when Sheets API is used, the values cannot be retrieved from multiple Spreadsheets by one API call. In this report, I would like to introduce the method for achieving this with the low process cost using Google Apps Script.
Gists
This is a workaround for retrieving the hyperlink from the cell of a number value using Google Apps Script.
As a sample situation, it supposes that a cell “A1” has a number value like 123, and a hyperlink of https://tanaikech.github.io is set to the cell. In order to retrieve the hyperlink from the cell, it is required to use the methods of getRichTextValue() and getRichTextValues(). But, in the current stage, when the cell value is a number value, when the RichText is retrieved by getRichTextValue(), null is returned. By this, unfortunately, the hyperlink of the cell cannot be retrieved. This has already been reported in the Google issue tracker. Ref
My report has been published at Champion Innovators Content Library.
If these reports will be useful, I’m glad.
Gists
This sample script decrypts the salted base64 data of finance.yahoo.com using Google Apps Script.
Recently, it seems that the specification of the key for decrypting the data has been changed at the server side. So. from this script, I updated the script as follows.
Sample script
function myFunction() {
// Load crypto-js.min.js.
const cdnjs =
"https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js";
eval(UrlFetchApp.fetch(cdnjs).getContentText());
// Retrieve HTML and retrieve salted base64.
const url = "https://finance.yahoo.com/quote/PGEN/press-releases"; // This is a sample URL.
const html = UrlFetchApp.fetch(url)
.getContentText()
.match(/root.App.main = ([\s\S\w]+?);\n/);
if (!html || html.length == 1) return;
const tempObj = JSON.parse(html[1].trim());
let obj;
if (
typeof tempObj.context.dispatcher.stores === "string" ||
tempObj.context.dispatcher.stores instanceof String
) {
// Decrypt the salted base64.
const key = [
...new Map(
Object.entries(tempObj)
.filter(([k]) => !["context", "plugins"].includes(k))
.splice(-4)
).values(),
].join("");
if (!key) {
throw new Error(
"Specification at the server side might be changed. Please check it."
);
}
obj = JSON.parse(
CryptoJS.enc.Utf8.stringify(
CryptoJS.AES.decrypt(tempObj.context.dispatcher.stores, key)
)
);
} else {
obj = tempObj.context.dispatcher.stores;
}
console.log(obj);
}
- About the value of
context.dispatcher.stores, this script can be used for both the salted base64 and the JSON object.
Note
- In this sample, in order to load
crypto-js, eval(UrlFetchApp.fetch(cdnjs).getContentText()) is used. But, if you don’t want to use it, you can also use this script by copying and pasting the script of https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js to the script editor of Google Apps Script. By this, the process cost can be reduced.
IMPORTANT
- I can confirm that this method can be used for the current situation (January 27, 2023). But, when the specification in the data and HTML is changed in the future update on the server side, this script might not be able to be used. Please be careful about this.
References
Gists
In the current stage, by the current specification, Google Apps Script cannot be directly run on Google Spreadsheet created by Service Account. But, there is a case in that we want to use the OnEdit trigger on the Spreadsheet that the service account is the owner. In this post, I would like to introduce the method for achieving this.
Recently, I published “Using OnEdit Trigger to Google Spreadsheet by Hiding Google Apps Script from Other Users”. Here, this method is used.
Gists

This is a method for using OnEdit Trigger to Google Spreadsheet by hiding Google Apps Script from other users.
A sample flow for achieving this is as follows.
Flow
1. Create a new Google Spreadsheet.
Please create a new Google Spreadsheet. In this flow, this Google Spreadsheet is used for testing the script. And, please copy the Spreadsheet ID. This spreadsheet ID is used.
In this case, even when Spreadsheet has no container-bound script, this goal can be achieved. Only the below standalone script can be used.
Gists

This is a sample script for checking and replacing a character of U+00A0 (no-break space) with U+0020 (space) as Unicode using Google Apps Script.
When I’m seeing the questions on Stackoverflow, I sometimes saw the situation that the script doesn’t work while the script is correct. In this case, there is the case that the reason is due to U+00A0 being used as the spaces. When U+00A0 is used as the spaces, Google Apps Script and formulas cannot be correctly run. I thought that when this information is published, it might be useful for a lot of users.
Gists
This is a sample script for setting the line space of paragraphs on Google Documents using Google Apps Script.
When the line space of a paragraph on Google Documents is manually set, you can do it as follows.

When it is set with Google Apps Script, the following script can be used.
function sample1() {
const doc = DocumentApp.getActiveDocument();
const body = doc.getBody();
const paragraph = body.appendParagraph(
"sample paragraph 1\nsample paragraph 2\nsample paragraph 3"
);
paragraph.setLineSpacing(2); // Double
}
When this script is run, the appended paragraphs have a line space of 2 (Double).
Gists

This is a sample script for opening and closing Google Forms on time using Google Apps Script.
In order to test this sample script, please do the following flow.
Usage
Please create a new Google Form and set your sample questions. And, please open the script editor of Google Form.
2. Prepare sample script.
Please copy and paste the following script to the script editor of Google Form. And, please set the values of start and end times you want.
Gists
This sample script decrypts the salted base64 data of finance.yahoo.com using Google Apps Script.
Recently, it seems that the specification of the key for decrypting the data has been changed at the server side. So. in this post, this post is updated. About this specification, I checked this thread.
Sample script
function myFunction() {
// Load crypto-js.min.js.
const cdnjs =
"https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js";
eval(UrlFetchApp.fetch(cdnjs).getContentText());
// Retrieve HTML and retrieve salted base64.
const url = "https://finance.yahoo.com/quote/PGEN/press-releases"; // This is a sample URL.
const html = UrlFetchApp.fetch(url)
.getContentText()
.match(/root.App.main = ([\s\S\w]+?);\n/);
if (!html || html.length == 1) return;
const tempObj = JSON.parse(html[1].trim());
let obj;
if (
typeof tempObj.context.dispatcher.stores === "string" ||
tempObj.context.dispatcher.stores instanceof String
) {
// Decrypt the salted base64.
var key = Object.entries(tempObj).find(
([k]) => !["context", "plugins"].includes(k)
)[1];
if (!key) {
throw new Error(
"Specification at the server side might be changed. Please check it."
);
}
obj = JSON.parse(
CryptoJS.enc.Utf8.stringify(
CryptoJS.AES.decrypt(tempObj.context.dispatcher.stores, key)
)
);
} else {
obj = tempObj.context.dispatcher.stores;
}
console.log(obj);
}
- About the value of
context.dispatcher.stores, this script can be used for both the salted base64 and the JSON object.
Note
- In this sample, in order to load
crypto-js, eval(UrlFetchApp.fetch(cdnjs).getContentText()) is used. But, if you don’t want to use it, you can also use this script by copying and pasting the script of https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js to the script editor of Google Apps Script. By this, the process cost can be reduced.
IMPORTANT
- I can confirm that this method can be used for the current situation (January 14, 2023). But, when the specification in the data and HTML is changed in the future update on the server side, this script might not be able to be used. Please be careful about this.
References
Gists

This is a sample script for converting all pages in a PDF file to PNG images using Google Apps Script.
I have already published “Merging Multiple PDF Files as a Single PDF File using Google Apps Script”. In this post, it was found that pdf-lib can be used with Google Apps Script. From this, in this post, I would like to propose a sample script for converting all pages in a PDF file to PNG images using Google Apps Script. This cannot be directly achieved with Google Apps Script. So, I thought that this might be useful for users.
Gists

This is a sample script for merging multiple PDF files as a single PDF file using Google Apps Script.
In this sample script, pdf-lib is used. In the current stage, it seems that this Javascript can be directly used with Google Apps Script.
Sample script 1
As a sample situation, please put multiple PDF files in your Google Drive. This sample merges those PDF files as a single PDF file.
Gists

This is a sample script for transferring the ownership of a file to another user using Google Apps Script.
In the current stage, about the consumer account (gmail.com) the specification for transferring the ownership of a file has been changed as follows. Ref
- The current owner initiates an ownership transfer by creating or updating the prospective new owner’s file permission. The permission must include these settings: role=writer, type=user, and pendingOwner=true. If the new owner is creating a permission for the prospective owner, an email notification is sent to the prospective new owner indicating that they’re being asked to assume ownership of the file.
- The new owner accepts the ownership transfer request by creating or updating their file permission. The permission must include these settings: role=owner and transferOwnership=true. If the new owner is creating a new permission, an email notification is sent to the previous owner indicating that ownership has been transferred.
When this flow is reflected in the sample script, it becomes as follows.
Gists
This is a sample script for retrieving the start and end of the month in a year using Google Apps Script and Javascript.
Sample script
function myFunction() {
const year = 2023; // Please set year you expect.
const res = [...Array(12)].map((_, i) =>
[0, 1].map((e) => new Date(year, i + e, 1 - e))
);
console.log(res);
console.log(res.map(([a, b]) => [a.toDateString(), b.toDateString()]));
}
Testing
https://jsfiddle.net/mLrhqwgo/
When this script is run, the following value is obtained with console.log(res.map(([a, b]) => [a.toDateString(), b.toDateString()])).
[
["Sun Jan 01 2023", "Tue Jan 31 2023"],
["Wed Feb 01 2023", "Tue Feb 28 2023"],
["Wed Mar 01 2023", "Fri Mar 31 2023"],
["Sat Apr 01 2023", "Sun Apr 30 2023"],
["Mon May 01 2023", "Wed May 31 2023"],
["Thu Jun 01 2023", "Fri Jun 30 2023"],
["Sat Jul 01 2023", "Mon Jul 31 2023"],
["Tue Aug 01 2023", "Thu Aug 31 2023"],
["Fri Sep 01 2023", "Sat Sep 30 2023"],
["Sun Oct 01 2023", "Tue Oct 31 2023"],
["Wed Nov 01 2023", "Thu Nov 30 2023"],
["Fri Dec 01 2023", "Sun Dec 31 2023"]
]
Gists
Published: January 3, 2023
Kanshi Tanaike
Introduction
At Stackoverflow, a lot of people post questions and answers to the questions every day. There are various tags in Stackoverflow. A lot of discussions are performed at each tag. Their discussions bring important information and are much useful for a lot of people. As one of the tags, there is “google-apps-script”. I sometimes discuss the questions with that tag. When we see the discussions, we can notice that the discussions are changed and progressed over time, because “Google Apps Script” which is the origin of the tag is updated. This report thinks this change is the trend of the tag of “google-apps-script”. This trend includes the number of questions, questioners, answerers, and tags added to the tag of “google-apps-script”. The trend of the tag of “google-apps-script” is deeply related to the progression of Google Apps Script and the various applications for Google Apps Script.
Gists
This is a simple sample script for filtering JSON objects using Google Apps Script.
In the current stage, V8 runtime can be used with Google Apps Script. By this, when you want to filter a JSON object, you can use the following sample script.
Sample script
In this sample script, obj is filtered by the value of the even number.
const obj = { key1: 1, key2: 2, key3: 3, key4: 4, key5: 5 };
const res = Object.fromEntries(
Object.entries(obj).filter(([, v]) => v % 2 == 0)
);
console.log(res); // {"key2":2,"key4":4}
-
When v % 2 == 0 is modified to v % 2 == 1, you can filter the JSON object with the odd number like {"key1":1,"key3":3,"key5":5}.
Gists
This sample script decrypts the salted base64 data of finance.yahoo.com using Google Apps Script.
Recently, when I saw the HTML of finance.yahoo.com, I noticed that the data is converted by the salted base64. In order to decrypt the data, it is required to use the key data. But, unfortunately, I couldn’t find the key data from the HTML. When I searched for it, I found this thread. From the thread, I could retrieve the key data. By this, I could a script for decrypting the salted base64.
Gists
This is a sample script for encrypting and decrypting with AES using crypto-js with Google Apps Script.
Unfortunately, in the current stage, Google Apps Script cannot encrypt and decrypt AES using the built-in functions. In this post, in order to achieve this, “crypto-js” is used from cdnjs.com ( https://cdnjs.com/libraries/crypto-js ). In the current stage, it seems that the main functions of crypto-js.min.js can be directly used with Google Apps Script. But, unfortunately, all functions cannot be used. Please be careful about this.
Gists

This is a sample script for rearranging columns on Google Spreadsheet using Google Apps Script.
Sample script
In this sample script, the initial columns of “header1”, “header2”, “header3”, “header4” and “header5” are rearranged to “header2”, “header5”, “header1”, “header4”, “header3”. This result can be seen at the above image.
As an important point, in this script, the header titles in the 1st row are used. Please be careful about this.
Gists

In this post, I would like to introduce 2 sample scripts for copying and deleting the dimension groups in Google Spreadsheet using Google Apps Script.
Unfortunately, in the current stage, all dimension groups cannot be copied by one action, and also, all dimension groups cannot be deleted by one action. In this post, these can be achieved using Google Apps Script.
These sample scripts use Sheets API. So, please enable Sheets API at Advanced Google services.
Gists
This report is a workaround for reflecting the latest Google Apps Script to the deployed Web Apps without redeploying.
Pattern 1
Of course, when the developer mode of https://script.google.com/macros/s/###/dev is used, the latest script can be used without redeploying.
But, in this case, only the permitted users can use it using the access token. when you want to achieve this using the endpoint of https://script.google.com/macros/s/###/exec without the access token, in order to reflect the latest script to Web Apps, it is required to redeploy. As another pattern, I would like to introduce a workaround for this situation.
Gists
This is a sample script for searching Gmail messages by Gmail Filters using Google Apps Script.
At Gmail, users can set the filter for the Emails. With this filter, users can filter the Emails of Gmail. But, when the users want to search by the installed filter using Google Apps Script, unfortunately, it seems that this cannot be directly achieved. For example, messages cannot be searched using a filter ID.
Gists
These are sample scripts for retrieving specific folders from Google Drive using Google Drive service (DriveApp) with Google Apps Script.
Retrieving folders in own Google Drive
const folders = DriveApp.searchFolders(
`'${Session.getActiveUser().getEmail()}' in owners and trashed=false`
);
const res = [];
while (folders.hasNext()) {
const folder = folders.next();
res.push(folder.getName());
}
console.log(res);
Retrieving folders in shared Drives
const folders = DriveApp.searchFolders(
`not '${Session.getActiveUser().getEmail()}' in owners and trashed=false`
);
const res = [];
while (folders.hasNext()) {
const folder = folders.next();
const owner = folder.getOwner();
if (owner === null) {
res.push(folder.getName());
}
}
console.log(res);
Retrieving folders of sharedWithMe
const folders = DriveApp.searchFolders(`sharedWithMe`);
const res = [];
while (folders.hasNext()) {
const folder = folders.next();
res.push(folder.getName());
}
console.log(res);
Gists

This is a workaround for converting a Gmail message to a PNG image using Google Apps Script.
Sample script
Please set the message ID of Gmail.
function myFunction() {
var id = "###"; // Please set your message ID of Gmail.
var message = GmailApp.getMessageById(id);
var date = Utilities.formatDate(
message.getDate(),
Session.getScriptTimeZone(),
"yyyy-MM-dd HH:mm:ss"
);
var from = message.getFrom();
var to = message.getTo();
var subject = message.getSubject();
var htmlBody = message.getBody();
var imageBlob = Charts.newTableChart()
.setDataTable(
Charts.newDataTable()
.addColumn(Charts.ColumnType.STRING, "")
.addRow([`<p style="font-size: 120%">Date: ${date}</p>`])
.addRow([`<p style="font-size: 120%">From: ${from}</p>`])
.addRow([`<p style="font-size: 120%">To: ${to}</p>`])
.addRow([`<p style="font-size: 120%">Subject: ${subject}</p>`])
.addRow([htmlBody])
.build()
)
.setOption("allowHtml", true)
.setDimensions(512, 512)
.build()
.getBlob();
DriveApp.createFile(imageBlob.setName("sample.png"));
}

My report has been featured by Google Workspace Developer Newsletter. Ref
The featured report is “Report: Implementing Pseudo 2FA for Web Apps using Google Apps Script”.
Gists

This is a simple sample script for uploading a video file on Google Drive to YouTube with the resumable upload using Google Apps Script.
When you want to upload a video file to YouTube using Google Apps Script, when YouTube API of Advanced Google services is used, the maximum file size is 5 MB, because, in this case, the video file is uploaded with multipart/form-data. When you want to use a video file with more file size using Google Apps Script, a resumable upload is required to be used. But, unfortunately, in the current stage, the methods of Google Apps Script for uploading large video files are not prepared. And also, when I saw the document of resumable upload on YouTube in the official document, I thought that it might be a bit complicated for understanding the resumable upload process. Ref So, in this post, I would like to introduce a simple sample script for uploading video data of more than 5 MB with the resumable upload using Google Apps Script. In this case, the video file is existing in Google Drive. The video file on Google Drive is uploaded to YouTube using Google Apps Script. When this sample script will help you understand the resumable upload of YouTube, I’m glad.
Gists
This is a workaround for detecting to edit Google Spreadsheet using Sheets API with the service account.
It has already been found that when Google Spreadsheet is edited using Sheets API, this can be detected by the installed OnChange trigger. For example, when a Spreadsheet is edited using Sheets API with the access token retrieved from your Google account, the event object of the installable OnChange trigger includes your email address and nickname. With this information, you can know the user who edited the Spreadsheet. However, when the Spreadsheet is edited using Sheets API with the access token retrieved from the service account, unfortunately, the email of the service account is not included in the event object of the OnChange event. It is considered that this is the current specification.
Gists

These are the sample scripts for using getBatchGet, batchUpdateContacts, batchDeleteContacts, batchCreateContacts of People API with Google Apps Script.
When the data is retrieved and put with People API, the process cost can be reduced by using batch requests. Fortunately, in the current stage, People API has native methods for using batch requests. Those are getBatchGet, batchCreateContacts, batchDeleteContacts, and batchUpdateContacts. In this post, I would like to introduce the sample scripts for using the batch requests of People API.
My report has been published at Champion Innovators Content Library.
If these reports will be useful, I’m glad.
Gists
This is a workaround for checking the existence of file ID in Google Drive without both the access token and API key.
When you want to check whether the file of the file ID is existing in Google Drive, generally, you might use Drive API and Drive service (DriveApp) of Google Apps Script. In this case, the scope of Drive API is required to be used. By this, the access token and the API key (in the case of publicly shared files) are required to be used. But, there might be a case that the available scopes are limited. In this post, I would like to introduce a workaround for checking the existence of file ID in Google Drive without both the access token and API key.
Gists
This is a workaround for retrieving the values and URLs from the smart chips inserted in Google Document using Google Apps Script.
Recently, the smart chips for Google Document are updated. Ref1 and Ref2 It is considered that this update will advance the collaboration for editing Document. So, there might a case that the information of the smart chips is required to be retrieved. Unfortunately, in the current stage, there are no methods for directly retrieving the information of the smart chips while the smart chips of DATE and PERSON can be retrieved. I believe that all smart chips will be able to be managed with Google Apps Script in the future update.
Gists
I have submitted a report of “Workaround: Putting Multiple Hyperlinks to a Cell using Sheets API” before. At that time, there are no direct methods for setting multiple hyperlinks to the part of text in a cell. But, recently, textFormatRuns was added to Sheets API. By this, multiple hyperlinks got to be able to be set to the part of text in a cell. In this report, I would like to introduce a sample script for this.
Gists

Abstract
In Google Apps Script, there is the Web Apps. When Web Apps is used, the users can execute Google Apps Script using HTML and Javascript. This can be applied to various applications. When the Web Apps is deployed with “Anyone”, anyone can access the Web Apps. And, there is the case that Web Apps deployed with “Anyone” is required to be used. Under this condition, when 2 Factor Authentication (2FA) can be implemented, it is considered that the security can be higher and it leads to giving various directions for the applications using Web Apps. In this report, I would like to introduce the method for implementing the pseud 2FA for Web Apps deployed with “Anyone” using Google Apps Script.
Gists
Unfortunately, in the current stage, in order to retrieve the file list using the created date, the search query of createdDate cannot be used with searchFiles method of DriveApp in Google Apps Script. This has already been reported at this issue tracker In this post, I would like to introduce a workaround for searching the files using the created date.
Issue and workaround
-
The parameter of “searchFiles” method of DriveApp uses the search query for Drive API v2. When I tested createdDate > '####-##-##' for “searchFiles” and “Files: list” of Drive API v2, I confirmed errors like Invalid argument: q and Invalid query occurred, respectively.
Gists

This is a sample script for updating Array1 with Array2 using Google Apps Script.
As a sample situation, there are 2 arrays (Array1 and Array2) of the 2-dimensional array. The sample situation can be seen in the above sample Spreadsheet.
- Conditions
- When the values of column “A” of Array2 are existing in column “A” of Array1, the rows of Array1 are updated by that of Array2.
- When the values of column “A” of Array2 are not existing in column “A” of Array1, the rows of Array2 are appended to Array1.
- When the values of column “A” of Array1 are not existing in column “A” of Array2, the rows of Array1 are deleted.
I sometimes see such questions on Stackoverflow. So, I thought that when this sample script is posted, it might be useful for users.
My report has been published on the Blog of Google Cloud.
Blog
Efficient File Management using Batch Requests with Google Apps Script


Gist
This is a sample script for retrieving the batch path for using the batch requests using Google Apps Script.
After August 12, 2020, in order to use batch requests, the batch path is required to be used to the endpoint of the batch requests. And, the batch path is sometimes updated. So, when a constant batch path has been continued to be used, this might lead to the reason for an error. In this sample script, the batch path is retrieved from Discovery API. By this, the latest batch path can be always obtained.
BatchRequest was updated to v1.2.0.
You can check this at https://github.com/tanaikech/BatchRequest.
Overview
This is a Google Apps Script library for supporting Document service, Docs API, Spreadsheet service, Sheets API, Slides service and Slides API. The aim of this library is to compensate the processes that they services cannot achieve.
DocsServiceApp was updated to v1.2.0

You can see the detail information here https://github.com/tanaikech/DocsServiceApp
Gists

This is a sample script for retrieving the named functions from Google Spreadsheet using Google Apps Script.
Recently, the named functions got to be able to be used in Google Spreadsheet. Ref When several named functions are added, I thought that I wanted to retrieve these functions using a script. But, unfortunately, in the current stage, it seems that there are no built-in methods (SpreadsheetApp and Sheets API) for directly retrieving the named functions. So, I created this sample script.
Overview
This is a Google Apps Script library for supporting Document service, Docs API, Spreadsheet service, Sheets API, Slides service and Slides API. The aim of this library is to compensate the processes that they services cannot achieve.
DocsServiceApp was updated to v1.1.0

You can see the detail information here https://github.com/tanaikech/DocsServiceApp
Gists

This is a sample script for showing the specific rows and columns in Google Spreadsheet using Google Apps Script.
When you export a Google Spreadsheet as a PDF file, you might have a case where you want to export the specific rows and columns in a sheet. In this post, I would like to introduce the sample script for achieving this.
Script
Please copy and paste the following scripts to the script editor of Google Spreadsheet.
Gists

These are sample scripts for removing the vertical borders of a table in Google Document using Google Apps Script.
Unfortunately, in the current stage, only the vertical borders cannot be removed from the table in Google Document using the Google Document service (DocumentApp). I believe that this might be resolved in the future update. But, in the current stage, when Google Docs API is used, this can be achieved. So, Google Docs API can be used as the current workaround. But, I thought that the combination of Google Document service (DocumentApp) and Google Docs API might be a bit complicated. So, I would like to introduce 3 sample scripts.
Gists
This is a sample script for retrying UrlFetchApp of Google Apps Script when an error occurs.
When the HTTP request is run using UrlFetchApp, there is a case that an error occurs in various situations. And, there is a case that when the request is run again, no error occurs. This sample script can automatically retry the requests using Google Apps Script.
Sample script
This is Class RetryFetch.
/**
* UrlFetchApp is run by retrying when an error occurs.
*/
class RetryFetch {
/**
* @param {string} url URL
* @param {object} params Object
* @param {number} numberOfRetr Number of retry when an error occurs with the HTTP request.
* @param {number} waitTime Wait time between the HTTP request.
* @return {UrlFetchApp.HTTPResponse}
*/
constructor(url, params = {}, numberOfRetry = 2, waitTime = 3) {
this.url = url;
if (!params.muteHttpExceptions) {
params.muteHttpExceptions = true;
}
this.params = params;
this.numberOfRetry = numberOfRetry;
this.waitTime = waitTime;
this.his = [];
}
fetch() {
const res = UrlFetchApp.fetch(this.url, this.params);
const statusCode = res.getResponseCode();
this.his.push({ date: new Date(), params: this.params, statusCode });
if (statusCode != 200 && this.numberOfRetry > 0) {
console.log(`Status code: ${statusCode}, Retry: ${this.numberOfRetry}`);
const idx = this.his.length - 1;
this.his[idx].responseHeader = res.getAllHeaders();
this.his[idx].error = res.getContentText();
this.numberOfRetry--;
Utilities.sleep(this.waitTime * 1000);
this.fetch();
} else if (this.numberOfRetry == 0) {
return null;
}
return res;
}
/**
* Return history of fetch requesting in this Class.
* @return {array} History.
*/
get history() {
return this.his;
}
}
This is a sample script for using Class RetryFetch.
Gists
This is a sample script for requesting with keeping cookies using Google Apps Script.
This might be similar to requests.Session" of Python. Ref
Sample script
This is Class SessionFetch.
/**
* UrlFetchApp is run by keeping Cookie.
*/
class SessionFetch {
constructor() {
this.cookie = "";
this.his = [];
}
/**
* Request URL.
* @param {string} url URL
* @param {object} params Object
* @return {UrlFetchApp.HTTPResponse}
*/
fetch(url, params = {}) {
if (this.cookie != "") {
if (!params.headers) {
params.headers = { Cookie: this.cookie };
} else if (!params.headers["Cookie"]) {
params.headers["Cookie"] = this.cookie;
}
}
this.his.push({ date: new Date(), url, params });
const res = UrlFetchApp.fetch(url, params);
this.cookie = res.getAllHeaders()["Set-Cookie"] || "";
return res;
}
/**
* Return history of fetch requesting in this Class.
* @return {array} History.
*/
get history() {
return this.his;
}
}
This is a sample script for using Class SessionFetch.
Gists
This is a sample script for retrieving the files of ‘Shared with Me’ in the specific folder using Google Apps Script.
In the current stage, when you transfer the ownership of your file on your Google Drive to another user and/or copy the file “Shared with me” to the specific folder on your Google Drive, the file becomes the shortcut file. Under this situation, when you want to retrieve the files of “Shared with me” in the specific folder, unfortunately, the following search query cannot be used.
Gists

These are sample scripts for achieving the full-text search of Google Apps Script projects using Google Apps Script. I have the case that I want to search a value from Google Apps Script projects using a Google Apps Script. In this post, I would like to introduce the sample scripts for achieving the full-text search of Google Apps Script projects.
1. Full-text search from all Google Apps Script Projects of standalone type in Google Drive
Before you use this script, please enable Drive API at Advanced Google services. In the case of the Google Apps Script projects of the standalone type, the full-text search can be achieved using Drive API as follows.
Gists
Kanshi Tanaike
Introduction
There is a maximum executing time for Google Apps Script (GAS). That is 6 minutes. And, in the case of the custom function and the simple trigger, it is 30 seconds. Ref So users always have to pay attention to reducing the process cost of the scripts. Especially, it is very important to know the process costs for the array processing, because array processing is often used for spreadsheets and Google APIs. I have already reported about the array processing at “Benchmark: Loop for Array Processing using Google Apps Script with V8” and “Search for Array Processing using Google Apps Script”. In this report, the process cost checking a value in a one-dimensional array using Google Apps Script has been investigated.

Following 3 reports have been published at Champion Innovators Content Library.
If these reports will be useful, I’m glad.
Gists

This is a sample script for converting the large images to Google Document by OCR using Google Apps Script.
When the image size, the image file size, the resolution of the image, and so on are large, an error like Request Too Large occurs. In this sample script, such the image can be converted to Google Document by reducing them.
Sample script
Please enable Drive API at Advanced Google services.
Gists

This is a sample script for detecting cells with the quote prefix in Google Spreadsheet using Google Apps Script.
For example, when a value is put to a cell by adding a single quote ' as the top character, the cell value is used as the string value. This is the current specification. Under this condition, when the cells with the value of the quote prefix are tried to be detected, unfortunately, in the current stage, it seems that there is no method for directly achieving this in the methods of Spreadsheet service (SpreadsheetApp).
Gists
This is a report related to the rule of item IDs for questions of Google Forms.
When the questions are created using the method of batchUpdate with Google Forms API, the created questions have the item IDs when the item IDs are not given in the request body. ( https://developers.google.com/forms/api/reference/rest/v1/forms#item ) For example, when you want to create a question and update the created question in one API call, it is required to include the custom item ID in the request body. But, it seems that in the current stage, the information of the item ID has never been published. So, in this report, I would like to consider the rule of item IDs of questions for Google Forms API.
Gists

Today, I found a question ( https://stackoverflow.com/q/73540735 ) in Stackoverflow by Max Makhrov. When I saw this question, I thought that this is a good raising question. In this question, it has reported that when the Spreadsheet includes the formulas of the large calculation, when a Google Apps Script is run during the calculation of the formulas is running, the processing time of the script becomes long.
I have also experienced this before. And, in that time, I noticed that there are differences in process costs for the methods of Google Apps Script under this condition.
Gists

This is a sample script for updating the same position on Google Document using Google Apps Script.
In this case, the named range is used. About the named range on Google Document, in the current stage, unfortunately, this cannot be used with the UI on Google Document. And, when I saw the official document of named range, I thought that this might be a bit difficult. Ref Ref So, I have created a Google Apps Script for managing the named range on Google Document. Ref In this post, I would like to introduce a sample script for updating the same position on Google Document using this GAS library.

My report has been published at Champion Innovators Content Library. The published report is Taking Advantage of Google Apps Script. If this report will be useful, I’m glad.
Gists

This is a sample script for high-efficiency finding and replacing many values in Google Spreadsheet with the low process cost using Google Apps Script.
When the various values are replaced in Google Spreadsheet using Google Apps Script, I’m worried about the process cost. So, in this report, I would like to introduce a sample script for high-efficiency achieving this.
As the result, using a sample situation, when the process cost of the sample script using Sheets API is compared with that of the sample script using Spreadsheet services (SpreadsheetApp), it was found that the above script using Sheets API could reduce the process cost by about 70 % from the script using Spreadsheet service.
Gists
This is a sample script for updating the destination sheet by the source sheet in Google Spreadsheet using Google Apps Script.
The sample situation is as follows.

Sample script
function myFunction() {
const sheetNames = ["Sheet1", "Sheet2"];
// Retrieve values from source and destination sheets.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [srcSheet, dstSheet] = sheetNames.map((s) => ss.getSheetByName(s));
const [srcValues, dstValues] = [srcSheet, dstSheet].map((s) =>
s.getDataRange().getValues()
);
// Create an array for updating the destination sheet.
const srcObj = srcValues.reduce((o, r) => ((o[r[0]] = r), o), {});
const values = [
...dstValues.map(([a, ...v]) => {
if (srcObj[a]) {
const temp = srcObj[a];
delete srcObj[a];
return temp;
}
return [a, ...v];
}),
...Object.values(srcObj),
];
// Update the destination sheet.
dstSheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
Gists

This is a sample script for detecting whether the specific cells on Google Spreadsheet are manually moved using Google Apps Script.
In this case, the named range, OnChange trigger, and PropertiesService are used.
Usage:
1. Create a named range.
As a sample, please create a named range to the cells “A2:B2” as “sampleNamedRange1”. Ref
2. Prepare sample script.
Please copy and paste the following script to the script editor of Spreadsheet. And, please install OnChange trigger to the function installedOnChange.
Gists

In this post, I would like to introduce the method for using RichTextValue with a custom function of Google Apps Script.
This sample is for this thread in Stackoverflow.
In this thread, the OP’s goal is as follows.
- Put a text to a cell. In this case, use a hyperlink in a part of the text.
- This is required to be achieved using a custom function.
In the current stage, in order to reflect the hyperlink in a part of the text, it is required to use setRichTextValue of Google Apps Script. In this case, this method cannot be used with the custom function. This is the current specification.
Gists

This is a sample script for retrieving icons of each mimeType on Google Drive using Google Apps Script.
Sample script
Sample list of mimeType is from this official document.
function getIcons() {
const iconSize = 256; // Pixels
const mimeTypes = [
"application/vnd.google-apps.audio",
"application/vnd.google-apps.document",
"application/vnd.google-apps.drive-sdk",
"application/vnd.google-apps.drawing",
"application/vnd.google-apps.file",
"application/vnd.google-apps.folder",
"application/vnd.google-apps.form",
"application/vnd.google-apps.fusiontable",
"application/vnd.google-apps.jam",
"application/vnd.google-apps.map",
"application/vnd.google-apps.photo",
"application/vnd.google-apps.presentation",
"application/vnd.google-apps.script",
"application/vnd.google-apps.shortcut",
"application/vnd.google-apps.site",
"application/vnd.google-apps.spreadsheet",
"application/vnd.google-apps.unknown",
"application/vnd.google-apps.video",
];
const imageUrls = mimeTypes.map(
(e) =>
`https://drive-thirdparty.googleusercontent.com/${iconSize}/type/${e}`
);
const blobs = UrlFetchApp.fetchAll(imageUrls).map((r, i) =>
r.getBlob().setName(`${mimeTypes[i].split("/")[1]}.png`)
);
const zip = Utilities.zip(blobs, "sampleIcons.zip");
DriveApp.createFile(zip);
}
Gists
Updated on January 25, 2024
Overview:
This is a report for challenging exporting the selected cells on Spreadsheet as an image using Google Apps Script and Javascript.

Description:
This report is based on this question by Max Makhrov. When I saw this question, I remembered that there are many questions for asking this in Stackoverflow. And, I thought that when this is achieved, it will be useful for the owner of this question and a lot of users. So, I have discussed this in his question.
Gists
This is a sample script for clearing the discrete cell values on multiple sheets using Google Apps Script.
There might be a case where you want to clear the values of the discrete cells in the multiple sheets using Google Apps Script. In this post, I would like to introduce the efficient script for achieving this.
Sample script 1
Please copy and paste the following script to the script editor of the Google Spreadsheet you want to use.
Gists
This is a sample script for creating the user’s dashboard by inputting the user name and password using Web Apps with Google Apps Script. In this case, Google Spreadsheet is used as a database of the dashboard.
Usage
1. Create a Google Apps Script project.
In order to use Web Apps, please create a new Google Apps Script project. In this case, please create a new Spreadsheet and open the script editor of Spreadsheet.
Gists
This is a sample script for retrieving the names of month and day of week using Google Apps Script.
I think that you might have a case that you want to retrieve the names of month and day of week using Google Apps Script. This sample script retrieves them using a simple script.
Using Utilities.formatDate of Google Apps Script, the names of month and day of week can be retrieved using a simple script.
Gists

This is a sample script for checking the exchange rate using GOOGLEFINANCE with Google Apps Script.
Recently, I have published a report of “Report: Obtaining Values from GOOGLEFINANCE using Google Apps Script”. Ref In this post, I would like to introduce a sample script for checking the exchange rate using Google Apps Script.
Sample script
Please copy and paste the following script to the script editor of Spreadsheet.
// When this script is run, a trigger for executing "checkCurrency" function is installed.
function setTrigger() {
const functionName = "checkCurrency";
const trigger = ScriptApp.getScriptTriggers().find(t => t.getHandlerFunction() == functionName);
if (trigger) {
ScriptApp.deleteTrigger(trigger);
}
ScriptApp.newTrigger(functionName).timeBased().everyMinutes(10).create();
}
function checkCurrency() {
const threshold = ###; // Please set the the threshold value you want to check.
const ticker = "CURRENCY:USDJPY"; // Please set ticker you want to check.
const email = "###"; // Please set the email address you want to notice.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheets()[0];
const range = sheet.getRange(sheet.getLastRow() + 1, 1, 1, 2);
range.setFormulas([["=NOW()", `=GOOGLEFINANCE("${ticker}")`]]);
range.offset(0, 0, 1, 1).setNumberFormat("yyyy/MM/dd H:mm:ss");
SpreadsheetApp.flush();
const values = range.getValues();
range.setValues(values);
if (values[0][1] > threshold) { // Or if you want to check when the current value is less than the threshold, please modify this to values[0][1] < threshold
MailApp.sendEmail({
to: email,
subject: `Report: Value is over the threshold (${threshold})`,
htmlBody: `<p>Current value is ${values[0][1].toFixed(2)}.</p><p><a href="${ss.getUrl()}">Open Spreadsheet</a>`,
});
}
}
-
In this script, when the function of checkCurrency is run, the current value of exchange rate is retrieved as a fixed value without using the formula. When the value is over threshold, an email is sent.
Gists

This is a sample script for replacing images on Google Document in order using Google Apps Script.
Sample script
This sample script uses Drive API and Docs API. So, please enable Drive API and Docs API at Advanced Google services. Ref
In this sample script, the images on Google Document are replaced with the image files on your Google Drive in order. Each image in Document is replaced in order of file Ids in fileIds.
Gists

This is a report for management of images on Google Spreadsheet using Google Apps Script.
At October 30, 2018, Cass OverGridImage and the method of inserImage have been added to Spreadsheet Service. Ref At January 19, 2022, Class CellImageBuilder and Class CellImage have been added to Spreadsheet Service. Ref By these Classes and methods, the images got to be able to be managed on Google Spreadsheet. But, when the image is used to the various situations, there are the cases that it is required to ingenuity to manage the images. So, in this report, I would like to introduce the management of images on Google Spreadsheet using the sample scripts of Google Apps Script.
Gists
This is a report for the documentation comments for the functions of Google Apps Script.
When the documentation comments for functions of Google Apps Script are considered, you will think JsDoc. At Google Apps Script, a part of JsDoc can be used. But, in this report, I would like to introduce the documentation comments including JsDoc.
Sample situations
Sample 1
For example, when the following sample function is written,
Gists
Introduction
In order to retrieve the values from XML data, when XML data is parsed using Google Apps Script, there are several methods for parsing the data. Class XmlService, which is a built-in Class for managing XML data, might be the first way to come up with it. At Stackoverflow, it is posted questions that XML data is often parsed using Class XmlService. It is considered that Class XmlService is suitable for managing XML data.
Gists
This is a sample script for retrieving the values of dropdown list of the smart chips on Google Document using Google Apps Script.
At August 23, 2021, 3 Classes for retrieving the smart chips have been added to Google Apps Script. But, in the current stage, unfortunately, all values of the smart chips cannot be retrieved by the Classes. For example, the dropdown list of the smart chips cannot be retrieved using the 3 Classes.
Gists
This is a sample script for removing the invalid named range of #REF from Google Spreadsheet using Google Apps Script.
Issue and workaround
For example, there are 2 sheets of “Sheet1” and “Sheet2” in a Google Spreadsheet. A new named range of sample is created for the range of Sheet1!A1, and remove the sheet of “Sheet1”. By this flow, when the named range list is checked by UI on Spreadsheet, sample has #REF. This is the invalid named range.
Gists
This is a sample script for converting A1Notation to GridRange and vice versa using Google Apps Script without any scopes.
A1Notation and GridRange are often used with Sheets API. I have posted a sample script for converting A1Notation to GridRange before. Ref But, in that case, I used the method of Spreadsheet service (SpreadsheetApp). By this, in order to use the script, it is required to authorize the scopes. In this sample script, A1Notation can be converted to GridRange and vice versa with no scopes. Also, this sample script can be used for Javascript and Node.js.
Gists
This is a sample script for shortening a long URL using Firebase Dynamic Links API with Google Apps Script.
IMPORTANT
Before you use this script, please create a new Firebase project and link it to your Google Cloud Platform Project. Ref And, please enable Firebase Dynamic Links API at the API console. And then, please create your API key from your Google Cloud Platform Project.
Sample script
const apiKey = "###"; // Please set your API key.
const longUrl = "###"; // Please set the long URL you want to shorten.
const yourDynamicLinkDomain = "###"; // Please set your dynamic link domain.
const url =
"https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=" + apiKey;
const options = {
payload: JSON.stringify({
dynamicLinkInfo: {
dynamicLinkDomain: yourDynamicLinkDomain,
link: longUrl,
},
}),
contentType: "application/json",
};
const res = UrlFetchApp.fetch(url, options);
const { shortLink } = JSON.parse(res.getContentText());
console.log(shortLink);
- When this script is run,
longUrl is shortened.
Note
If the warning of Setup URL patterns to whitelist in the Firebase Dynamic Links console. is shown, please include the URL to the whitelist to “Allowlist URL pattern”. Ref By this, the warning can be removed.
Gists

This is a sample flow for parsing XML data in Google Apps Script using IMPORTXML. Recently, it seems that ContentService.MimeType.XML has been removed by the Google side. By this, in the current stage, the XML data cannot be directly loaded by the Web Apps URL with IMPORTXML. From this current situation, I would like to introduce a workaround. In this workaround, the XML data in Google Apps Script is parsed by IMPORTXML of the built-in function of Google Spreadsheet. By this workaround, I thought that this will be useful for testing a custom XML data using IMPORTXML.
There is a method of ScriptApp.getService().getUrl() for obtaining the Web Apps URL in Google Apps Script.
-
Before the V8 runtime is released, this method had returned the endpoint like https://script.google.com/macros/s/{deploymentId}/exec.
-
After the V8 runtime was released, the endpoint of https://script.google.com/macros/s/{deploymentId}/dev was returned.
-
Now, it seems that this returns https://script.google.com/macros/s/###/exec.
But, in the current stage, when I access this endpoint, the message of Sorry, unable to open the file at this time. Please check the address and try again. is returned. So, I tried to search the deployment ID of ### from https://script.google.com/macros/s/###/exec returned with current ScriptApp.getService().getUrl(). But, unfortunately, I cannot find the deployment ID. I’m worried that this might be related to the error.
Gists
Introduction
When we use HTML in the Google Apps Script project, in order to show the values from the Google Apps Script side, the HTML template is used. When I used the HTML template with a large value, I understood that the process cost can be reduced by devising a script. In this report, I would like to introduce the process cost of the HTML template using the benchmark.
Gists
This is a sample method for publishing various Google Docs files with the same URL using Google Apps Script.
By updating on May 25, 2022, the content got to be able to be embedded as a full page in the new Google site. Ref In this method, this is used.

Usage
1. Create a Google Docs.
First, as a simple sample, please create a new Google Spreadsheet. And please copy the URL like https://docs.google.com/spreadsheets/d/{spreadsheetId}/edit.
Gists
This is a sample script for replacing values in the cells on Google Spreadsheet using Google Apps Script.
Sample situation
The sample situation is as follows.

Sample script
This sample script used Sheets API. So, please enable Sheets API at Advanced Google services.
function myFunction() {
const obj = {
sample1: "ab",
sample2: "cd",
sample3: "ef",
sample4: "gh",
sample5: "ij",
sample6: "kl",
sample7: "mn",
sample8: "op",
sample9: "qr",
};
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheetId = ss.getSheetByName("Sheet1").getSheetId(); // Please set the sheet name you want to use this script.
const requests = Object.entries(obj).map(([k, v]) => ({
findReplace: {
find: `(${k})`,
matchCase: true,
sheetId,
replacement: `[${v}]`,
},
}));
requests.push({
findReplace: { find: ",", matchCase: true, sheetId, replacement: "" },
});
Sheets.Spreadsheets.batchUpdate({ requests }, ss.getId());
}
- In this script, one sheet is used. Also, you can use this script to all sheets in a Google Spreadsheet.
Reference
Gists
This is a sample script for parsing JSON data array by expanding the header row using Google Apps Script.
Sample script
function myFunction() {
const obj = [
{ key1: "value1", key2: "value2", key3: "value3" },
{ key4: "value1", key5: "value2", key6: "value3" },
{ key7: "value1", key8: "value2", key9: "value3" },
];
const headers = Object.keys(
obj.reduce((o, e) => (Object.keys(e).forEach((k) => (o[k] = true)), o), [])
);
const values = [headers, ...obj.map((o) => headers.map((k) => o[k] || null))];
SpreadsheetApp.getActiveSheet()
.clearContents()
.getRange(1, 1, values.length, values[0].length)
.setValues(values);
}
Testing
When this script is run, the following result is obtained. It is found that the header row is expanded by including all keys.
RichTextApp was updated to v1.4.0

-
v1.4.0 (May 25, 2022)
- Added a new method of
ReplaceTextToRichText. In this method, the text in a cell is converted to the richtext.
You can see the detail information here https://github.com/tanaikech/RichTextApp
Gists
This is a sample script for exporting the Tabulator data to Google Drive using Google Apps Script.
As the sample, a dialog on Google Spreadsheet is used. So, please copy and paste the following scripts to the container-bound script of Google Spreadsheet.

Google Apps Script side: Code.gs
const saveFile = (e) => DriveApp.createFile(Utilities.newBlob(...e)).getId();
// Please run this script.
const openDialog = (_) =>
SpreadsheetApp.getUi().showModalDialog(
HtmlService.createHtmlOutputFromFile("index"),
"sample"
);
HTML & Javascript side: index.html
<link
href="https://cdnjs.cloudflare.com/ajax/libs/tabulator/5.2.4/css/tabulator.min.css"
rel="stylesheet"
/>
<script
type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/tabulator/5.2.4/js/tabulator.min.js"
></script>
<div id="table"></div>
<input type="button" value="ok" onclick="download();" />
<script>
const type = "csv"; // In this sample, you can select "csv" or "json".
const filename = "sample"; // Please set the filename.
const table = new Tabulator("#table", {
data: [...Array(5)].map((_, i) =>
[...Array(5)].reduce(
(o, _, j) => ((o[`sample${j + 1}`] = `sample${i + 1}`), o),
{}
)
),
autoColumns: true,
downloadReady: function (fileContents, blob) {
const fr = new FileReader();
fr.onload = (e) =>
google.script.run
.withSuccessHandler((id) => console.log(id))
.saveFile([
[...new Int8Array(e.target.result)],
blob.type,
`${filename}.${type}`,
]);
fr.readAsArrayBuffer(blob);
return false;
},
});
function download() {
table.download(type, `${filename}.${type}`);
}
</script>
-
When openDialog is run with the script editor, a dialog is opened on Spreadsheet. And, you can see the table (as shown in the top of this post) and a button. When “ok” button is clicked, this table is exported as a CSV data and save it as a file in the root folder of Google Drive.
Gists
This is a sample script for requesting to Gate API v4 using Google Apps Script.
The official document of Gate API v4 is here. Recently, I answered this thread. In that case, in order to convert the sample python script to Google Apps Script, the script for retrieving the signature might be a bit complicated. So, here, I would like to introduce this.
Sample python script from official document
This is a sample python script from official document.
Gists
This is a sample script for retrieving the text positions in the text data using Google Apps Script.
For example, in order to set the rich text style the part of text from the text data, this sample script will be useful.
Sample situation 1
The sample situation is as follows.
sample1, sample2, sample3, sample4, sample5
sample1, sample2, sample3, sample4, sample5
sample1, sample2, sample3, sample4, sample5
In this sample, the text positions of sample2 and sample5 are retrieved from this sample text data.
Gists
This is a sample script for retrieving and parsing the XML data from Google Workspace Update Blog and putting it to Google Spreadsheet using Google Apps Script.
At Google Workspace Update Blog, the XML data is provided. By this, the retrieved XML data is parsed with XmlService, and the data is put to Google Spreadsheet. Recently, I got a request for this. So I created this sample script. When this was useful for your situation, I’m glad.
Gists
This is a sample script for retrieving the values of subscriberCount of the channel from the video URLs of YouTube using Google Apps Script.
In this sample, the video URLs are retrieved from Spreadsheet. And, the retrieved values of subscriberCount are put to the Spreadsheet. The sample Spreadsheet is as follows.

Sample script
Please copy and paste the following script to the script editor of Spreadsheet. Before you use this script, please enable YouTube Data API v3 at Advanced Google services. Ref And, please set the sheet name.
Gists
This is a sample script for splitting and processing an array every n length using Google Apps Script. When I prepare a sample script with Google Apps Script, I sometimes have the situation that it is required to split and process an array every n length. This sample script is for achieving this situation.
Please set limit. This sample script splits the sample array every 3 length.
When you use this script with Google Apps Script, please enable V8 runtime.
Gists
This is a report for obtaining the values from GOOGLEFINANCE using Google Apps Script. When I tested to retrieve the values from GOOGLEFINANCE function on Google Spreadsheet using Google Apps Script, I noticed that the values can be retrieved.
When I had tested this before, I had got the value of #N/A. About retrieving the values from GOOGLEFINANCE function on Google Spreadsheet, I had known “Historical GOOGLEFINANCE data no longer accessible outside of Google Sheets”. By this situation, #N/A had been returned when the value had been retrieved using a script.
Gists
This is a sample script for reducing the image data size using Google Apps Script. You might have a situation where you might want to reduce the data size of image data using Google Apps Script. Here, using Google Apps Script, I would like to introduce a sample script for reducing the data size of the image data by reducing the image quality.
Limitations
In the current stage, by the specification of Google side, there are the following limitations.
Gists
This is a sample script for expanding the rows in Google Spreadsheet using Google Apps Script. The sample situation is as follows.
Sample situation

Output

Sample script
function myFunction() {
const expandedColumns = [2, 3, 4, 5]; // Please set the expanded columns you expect.
const delimiter = "\n"; // Please set the delimiter.
const srcSheetName = "Sheet1"; // Please set the source sheet name.
const dstSheetName = "Sheet2"; // Please set the destination sheet name.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [srcSheet, dstSheet] = [srcSheetName, dstSheetName].map((s) =>
ss.getSheetByName(s)
);
const [head, ...values] = srcSheet.getDataRange().getValues();
const res = [
head,
...values.flatMap((r) => {
const { v, max } = expandedColumns.reduce(
(o, c, i) => {
const s = r[c - 1].split(delimiter);
o.v[c - 1] = s;
const len = s.length;
if (i == 0) {
o.max = len;
} else {
o.max = o.max > len ? o.max : len;
}
return o;
},
{ v: {}, max: 0 }
);
return [...Array(max)].map((_, j) =>
r.map((c, k) => (!v[k] ? c : v[k][j] || null))
);
}),
];
dstSheet.getRange(1, 1, res.length, res[0].length).setValues(res);
}
- When this script is run, the above sample situation can be obtained.
- For example, when you change
const expandedColumns = [2, 3, 4, 5]; to const expandedColumns = [5];, only the column “E” is expanded.
Gists
This is a report for checking the number of requests for Sheets API. I had contact about the quota for Sheets API. So, in order to explain this, I used the following simple sample scripts.
Sample 1
This sample puts a value of “sample” to a cell “A1” using the batchUpdate method. This request body includes one request. When this script is run, one API quota is used.
function sample1() {
const spreadsheetId = "###";
const sheetId = 0;
const requests = [{
"updateCells": {
"rows": [
{
"values": [
{
"userEnteredValue": {
"stringValue": "sample"
}
}
]
}
],
"range": {
"sheetId",
"startRowIndex": 0,
"endRowIndex": 1,
"startColumnIndex": 0,
"endColumnIndex": 1
},
"fields": "userEnteredValue.stringValue"
}
}];
Sheets.Spreadsheets.batchUpdate({ requests }, spreadsheetId);
}
Sample 2
This sample puts 1000 values like “sample#” to the cells of “B1:B1000” using the batchUpdate method. This request body includes 1000 requests. When this script is run, one API quota is used.
Gists
This is a sample script for increasing the column letter by one using Google Apps Script.
Sample script
const increase = (ar) =>
ar.map((e) => {
const idx = [...e].reduce(
(c, e, i, a) =>
(c += (e.charCodeAt(0) - 64) * Math.pow(26, a.length - i - 1)),
-1
);
// Ref: https://stackoverflow.com/a/53678158
columnIndexToLetter = (n) =>
(a = Math.floor(n / 26)) >= 0
? columnIndexToLetter(a - 1) + String.fromCharCode(65 + (n % 26))
: "";
return columnIndexToLetter(idx + 1);
});
const samples = ["A", "Z", "AA", "AZ", "ZZ"];
const res = increase(samples);
console.log(res); // <--- [ 'B', 'AA', 'AB', 'BA', 'AAA' ]
- When this script is used, the column letters of
["A", "Z", "AA", "AZ", "ZZ"] is increased by one. As the result, [ 'B', 'AA', 'AB', 'BA', 'AAA' ] is obtained.
Testing
Overview

This is a Google Apps Script library for managing the named range on Google Documents.
Description
Google Document can use the named range. When the named range is used, the users can directly access the contents using the named range. For example, the developer can guide the users to the specific content in Google Documents using the named range. But, unfortunately, in the current stage, it seems that the named range cannot be directly used by the UI on Google Documents. It is required to use Google Apps Script. But, I thought that when I saw the official document of the named range, it might be difficult to understand it. Ref So, I created this library. When this library is used, the named ranges on Google Documents can be managed.
Gists
This is a sample script for analyzing the responses from Grid Items of Google Form using Google Apps Script.
In this sample situation, all responses are retrieved from Grid Items of Google Form, and the average values of each row of each question are calculated. And, the result is put on the Spreadsheet.
Sample situation
The sample Google Form is as follows.

Output: Sample Spreadsheet
The sample output is as follows.
Gists
Introduction
On March 14, 2022, it reported about “Google Sheets doubles cell limit”. Ref By this update, now, the users can use 10,000,000 cells in a Google Spreadsheet. This is great news for us. When I tried to handle 10,000,000 cells in a Google Spreadsheet using Google Apps Script, it was found that there were various important points. In this report, I would like to introduce the important points for handling 10,000,000 cells in Google Spreadsheet using Google Apps Script.
Gists
This is a sample script for replacing the multiple paragraphs on Google Document with a regex using Google Apps Script. There is the method of replaceText(searchPattern, replacement) for replacing the text on Google Document. Ref For example, when a text of sample1 is replaced with sample2, this can be achieved by a script like DocumentApp.getActiveDocument().getBody().replaceText("sample1", "sample2"). But, when the texts for replacing are the multiple paragraphs, this script cannot be used. Namely, it is considered that in the current stage, replaceText cannot be used for replacing the multiple paragraphs. In this post, I would like to introduce a sample script for replacing the texts with the multiple paragraphs using Google Apps Script.
Gists
This is a sample script for simply converting HTML to plain text using Google Apps Script.
Sample values
<div id="sample1">sample text1</div>
<div id="sample2">sample text2</div>
<ul id="sample3">
<li>sample list 1</li>
<li>sample list 2</li>
</ul>
<table id="sample4">
<tbody>
<tr>
<td>a1</td>
<td>b1</td>
<td>c1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
<td>c2</td>
</tr>
</tbody>
</table>
Text (output value)
sample text1
sample text2
- sample list 1
- sample list 2
a1 b1 c1
a2 b2 c2
Sample script
function myFunction() {
const sampleHTML = `<div id="sample1">sample text1</div>
<div id="sample2">sample text2</div>
<ul id="sample3">
<li>sample list 1</li>
<li>sample list 2</li>
</ul>
<table id="sample4">
<tbody>
<tr>
<td>a1</td>
<td>b1</td>
<td>c1</td>
</tr>
<tr>
<td>a2</td>
<td>b2</td>
<td>c2</td>
</tr>
</tbody>
</table>`;
const temp = GmailApp.createDraft("", "", "", { htmlBody: sampleHTML });
const plainText = temp.getMessage().getPlainBody();
temp.deleteDraft();
console.log(plainText);
}
- This method uses
GmailApp.createDraft for converting HTML to plain text. When a draft email is created with GmailApp.createDraft by giving an HTML body, when the message content is retrieved with getPlainBody(), the plain text is retrieved. This method uses this situation.
- When this sample script is run, the result in “Sample values” section can be obtained.
Note
- This method is a simple conversion from HTML to plain text. So I’m not sure whether this method can be used for all HTML data. Please be careful about this.
References
Gists
This is a sample Google Apps Script for processing the values in Google Spreadsheet. In this sample situation, each row is merged using the same header title.
In this sample script, the sample input and output situations are as follows.
Sample situation

Output:

Sample script
In this sample script, this sample can be used as the custom function.
function SAMPLE(values) {
const headers = [
...new Set(
values
.map((r) => [...r])
.flatMap((r) =>
[...Array(Math.ceil(r.length / 2))].map((_) => r.splice(0, 2)[0])
)
),
].filter(String);
const obj = values.reduce((o, r) => {
[...Array(Math.ceil(r.length / 2))].forEach((_) => {
const [k, v] = r.splice(0, 2);
if (k && headers.includes(k)) o[k] = o[k] ? [...o[k], v] : [v];
});
return o;
}, {});
const v = headers.map((e) => [e, ...obj[e]]);
return v[0].map((_, c) => v.map((r) => r[c]));
}
- In this sample script, the following flow is used.
- Retrieve values from cells.
- Retrieve header values.
- Create an object for populating values for each header.
- Convert the object to an array.
- Tanspose the created array.
Reference
On April 13, 2022, “Additional functionality for the Apps Script Integrated Development Environment (IDE) Script Editor” has been reported.
They say as follows.
We’re now adding several new features to the IDE to help achieve functional parity with the legacy IDE experience. These features are:
- Script Properties
- Add-on Testing
- Time Zone Setting
- Rhino Debugging
By this update, I believe that the script editor will be more useful.
Gists

This is a sample script for creating quizzes in Google Form using Google Forms Service with Google Apps Script.
Usage
1. Prepare questions and answers.
In this sample, the questions and answers are prepared using Spreadsheet as follows.

2. Sample script.
This script is container-bound script of the above Spreadsheet.
function myFunction() {
const formTitle = "sample"; // This is a form title.
const sheetName = "Sheet1"; // This is a sheet name.
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
const [, ...values] = sheet
.getDataRange()
.getDisplayValues()
.filter((r) => r.join("") != "");
const obj = values.map(([a, b, c]) => {
const answers = b
.split("\n")
.map((e) => e.trim())
.filter(String);
const correct = c
.split("\n")
.map((e) => e.trim())
.filter(String);
return {
question: a,
answers,
correct,
point: 1,
type: correct.length == 1 ? "addMultipleChoiceItem" : "addCheckboxItem",
};
});
const form = FormApp.create(formTitle)
.setIsQuiz(true)
.setTitle("Sample questions");
obj.forEach(({ question, answers, correct, point, type }) => {
const choice = form[type]();
const choices = answers.map((e) =>
choice.createChoice(e, correct.includes(e) ? true : false)
);
choice.setTitle(question).setPoints(point).setChoices(choices);
});
}
- When this script is run using the prepared Spreadsheet, you can see the result Google Form at the top image in this post.
Note
Gists

This is a sample script for creating quizzes in Google Form using Google Forms API with Google Apps Script. Recently, Google Forms API has been officially published, and it got to be able to be used by users. By this, quizzes in Google Form can be created using Google Forms API.
Here, there is one thing that can be achieved by Google Forms API. When Google Forms API is used, each choice in each question can be shuffled. This cannot be achieved with Google Forms Service (FormApp).
Gists

This is a sample script for retrieving the summary of Google Document using Google Apps Script. Recently, a blog of Auto-generated Summaries in Google Docs has been posted. I thought that this is very interesting function. I thought that when this function is released, checking each summary of a lot of Google Document will be much useful for simply confirming the document content. And also, I thought that when all summaries can be retrieved using a script, it will be also useful. In this post, I would like to introduce to retrieve the summary of Google Document using Google Apps Script.
Gists
This is a sample Google Apps Script for processing the values in Google Spreadsheet. In this sample situation, each column are merged using the same header title.
In this sample script, the sample input and output situations are as follows.
Sample situation

Output: “Sheet2”

Sample script
function myFunction() {
const srcSheetName = "Sheet1"; // This sheet is "Input" situation.
const dstSheetName = "Sheet2"; // This sheet is "Output" situation.
const transpose = (ar) => ar[0].map((_, c) => ar.map((r) => r[c]));
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [src, dst] = [srcSheetName, dstSheetName].map((s) =>
ss.getSheetByName(s)
);
const values = src.getDataRange().getValues();
const temp = [
...transpose(values)
.reduce(
(m, [a, ...b]) => m.set(a, m.has(a) ? [...m.get(a), ...b] : [a, ...b]),
new Map()
)
.values(),
];
const res = transpose(temp);
dst.getRange(1, 1, res.length, res[0].length).setValues(res);
}
- In this sample script, the following flow is used.
- Retrieve values from “Sheet1”.
- Tanspose the retrieved values.
- Create an array using
Map object.
- Tanspose the created array.
- Put the array to “Sheet2”.
Gists
Introduction
In this report, I would like to introduce to apply the spread syntax and the destructuring assignment to Google Spreadsheet with Google Apps Script. The destructuring assignment can be used without V8 runtime. But, the spread syntax is required to be used with V8 runtime. Recently, I often saw the script using them at Stackoverflow. And also, I have sometimes gotten the questions related to the spread syntax and the destructuring assignment. So, I thought that I would like to introduce in my blog.
Gists
When I tested Google Forms API, I noticed that when a new Google Form is created by the method of forms.create, there is not title of the created Google Form. So, I have reported this to Google issue tracker. Ref Today, I confirmed that this bug has been removed.
And, when I saw the official document, I noticed that the following document has been added. Ref

In the current stage, when the following curl command is used, a new Google Form with the file title of sampleFormTitle and the form title of sampletitle can be created.
You can check ggsrun at https://github.com/tanaikech/ggsrun.
Gists

This is a sample script of a counter in a cell of Google Spreadsheet using the infinite loop with Google Apps Script. Recently, I have reported about the infinite loop on Google Spreadsheet. Ref This sample script achieves a counter in a cell using the infinite loop.
Sample script
This sample script is a test script for counting the number using the infinite loop. Please be careful this. Please copy and paste the following script to the script editor of Google Spreadsheet and save it. And, please install OnChange trigger to the function onChange().
Gists

Here, I would like to introduce a report for occurring and resolving the infinite loop on Google Spreadsheet using Google Apps Script. I have reported this to Google issue tracker. Ref
Sample script: Occurring infinite loop
This sample script is a test script for confirming the infinite loop. Please be careful this. Please copy and paste the following script to the script editor of Google Spreadsheet and save it. And, please install OnChange trigger to the function onChange().
Gists
This is a report for inserting the multiple paragraphs to Google Document in order using Google Docs API.
When the multiple paragraphs are inserted to Google Document using Google Docs API, it is required to pay attention to the index for inserting the texts. In this report, I would like to introduce the points for achieving this with a simple method.
Although this report uses Google Apps Script, the logic of this method can be used for other language.
RichTextApp was updated to v1.3.1
You can see the detail information here https://github.com/tanaikech/RichTextApp
Today, I noticed that the sheet ID of Spreadsheet, which is one of database, had been changed. So I used the sheet name of “Libraries” instead of the sheet ID. By this, the Google Apps Script library can be retrieved from 2 databases.
Google Apps Script Library Database
Overview

This is a Google Apps Script library for parsing the form object from HTML form and appending the submitted values to the Spreadsheet.
Description
There is Google Form in the Google service. Google Form can parse the submitted data and put it in the Spreadsheet. But when we want to use the custom form, it is required to use the HTML form on Web Apps, dialog, and sidebar. In this case, it is required to prepare Javascript and Google Apps Script for parsing the form object from the HTML form and appending the parsed values to Spreadsheet. Recently, a bug of the built-in parser from the Javascript side to the Google Apps Script side for parsing the form object from the HTML form had been removed. Ref But, in the current stage, this bug is removed for only Web Apps. Unfortunately, for the dialog and sidebar, this bug has never been removed. And also, unfortunately, the built-in parser from the Javascript side to the Google Apps Script side cannot be used for the multiple files of the input tag. And, this cannot be used except for google.script.run. For example, when the HTML form including the files is submitted using “action” of the form tag, the file content is not included. And then, when the form object is retrieved, it is required to parse the object and put it in the Spreadsheet. From these situations, I thought that when this process can be run using the libraries, that might be useful for users. So I created this.
On January 19, 2022, 2 classes of CellImageBuilder and CellImage have been added to the Spreadsheet Service.
Unfortunately, in the current stage, it seems that the image manually put to a cell without using the URL cannot still be retrieved.
- When an image is manually put from URL and Google Drive to a cell, this image cannot be retrieved.
- When an image is put using
setSourceUrl method with a script, this image and URL cannot be retrieved.
I would like to expect to resolve these in the future update.
Gists

This is a workaround for inserting the non-public image of Google Drive using IMAGE function in a cell on Google Spreadsheet using Google Apps Script.
When an image on Google Drive is inserted to a cell of Spreadsheet using =IMAGE(URL) function, the image of URL is required to be publicly shared. But, there is the case that the image cannot be publicly shared. This workaround might be able to be used for this situation.
This is a Javascript library for sending the HTML form object to Google Apps Script using google.script.run.
HtmlFormObjectParserForGoogleAppsScript_js was updated to v1.0.1.
You can see the detail of this at https://github.com/tanaikech/HtmlFormObjectParserForGoogleAppsScript_js
Gists
This is a sample script for importing a CSV data by keeping the number formats of cells on Google Spreadsheet using Google Apps Script.
When a CSV data is manually put using the default UI using the browser, it seems that the number formats of all cells cannot be kept. In order to import the CSV data to the cells with keeping the number formats, it is required to use a script as a workaround. In this workaround, Google Apps Script is used.
Gists
Published: January 7, 2022
Kanshi Tanaike
Introduction
At Stackoverflow, a lot of people post the questions and answers to the questions every day. There are various tags in Stackoverflow. A lot of discussions are performed at each tag. Their discussions bring important information and are much useful for a lot of people. As one of the tags, there is “google-apps-script”. I sometimes discuss the questions with that tag. When we see the discussions, we can notice that the discussions are changed and progressed by the time, because “Google Apps Script” which is the origin of the tag is updated. This report thinks this change is the trend of the tag of “google-apps-script”. This trend includes the number of questions, questioners, answerers, and tags adding to the tag of “google-apps-script”. The trend of the tag of “google-apps-script” is deeply related to the progression of Google Apps Script and the various applications for Google Apps Script.
Gists

This is a report for detecting the operations to Google Spreadsheet by the owner, the specific users, and the anonymous users using Google Apps Script. When the Spreadsheet is shared with the specific users and/or the anonymous users, when these users can be identified, it will be useful. In this report, I would like to introduce the method for identifying the users who are the owner, the specific users, and the anonymous users.
Gists
This is a simple method for using ggsrun. ggsrun is a CLI tool to execute Google Apps Script (GAS) on a terminal. Also this CLI tool can be used for managing files in Google Drive for OAuth2 and Service Account.
When you use ggsrun, it is required to retrieve the client ID and client secret and/or the service account at Cloud Platform Project. But, there is the case that you want to simply test or you want to just upload and download the files for Google Drive. In this post, I would like to introduce how to simply use ggsrun.
Gists

This is a sample script for inverting the selected objects on Google Slides using Google Apps Script.
I have the case that I want to invert the selected objects on Google Slides. This sample script can be achieved this goal using Google Apps Script.
Sample script
Please copy and paste the following script to the script editor of Google Slides, and save the script. And, please select the objects on the Slide and run the function main(). By this, the selected objects are inverted.
Gists

This is a sample script for inverting the selected ranges on Google Spreadsheet using Google Apps Script.
I have the case that I want to invert the selected ranges on Google Spreadsheet. This sample script can be achieved this goal using Google Apps Script.
Sample script
Please copy and paste the following script to the script editor of Google Spreadsheet, and save the script. And, please select the cells and run the function main(). By this, the selected ranges are inverted.
Gists
This is a sample script for checking whether the cells on Google Spreadsheet have checkboxes using Google Apps Script.
When the checkboxes are used in Google Spreadsheet, there is the case that it is required to know whether the cells have the checkboxes. This sample script can be used for such the situation.
Sample script 1
This sample script can check whether all cells in “A1:B10” have the checkboxes. When all cells in “A1:B10” have the checkboxes, res is true.
Gists

This is a sample script for converting from the string value to the hex value, from the hex value to the byte array, from the byte array to the string value using Google Apps script.
When the creation of a signature for requesting and the encryption of data are used, there is the case that these conversions are required to be used. So I would like to introduce these scripts as sample scripts.
The sample scripts for using Google Forms API have been published by cschalk-goog. The scripts include the method for basically requesting to Forms API. This information will be very useful for a lot of users.
https://github.com/googleworkspace/apps-script-samples/tree/master/forms-api/demos/AppsScriptFormsAPIWebApp

Gists

This is a sample script for achieving the pseudo OnEdit trigger for Google Spreadsheet without the simple and the installable triggers using Google Apps Script.
Today, I saw a question at Stackoverflow. The goal of this question is as follows.
- There is a Google Spreadsheet created by a service account.
- Goal is to use OnEdit trigger on this Spreadsheet.
I thought a workaround for achieving this goal.
Issue and workaround:
In the current stage, unfortunately, when the owner of Google Spreadsheet is the service account. The Google Apps Script cannot be run. By this, even when onEdit function is put to the script editor, this script cannot be run. It seems that this is the current specification of the Google side. Unfortunately, in the current stage, this goal cannot be directly achieved.
Gists

On October 12, 2021, Google Forms API had been announced. Ref On December 7, 2021, Google Forms API had been released as open beta. Ref In the current stage, when the users join the Early Adopter Program, they can use Google Forms API of the beta version. Ref
By using Google Forms API, what Google Forms service cannot achieve got to be able to be achieved by Google Forms API. In this report, I would like to introduce how to use Google Forms API and the sample script of the situations which cannot be achieved by Google Forms service.
After V8 runtime was released, there was a bug that when the file is sent from HTML form to Google Apps Script side using google.script.run, the file blob was the invalid data.
From Apps Script Pulse by Martin Hawksey, it was found that the invalid blob of sending the file of HTML form to Google Apps Script side using google.script.run has finally been resolved. In this case, this script can be used with V8 runtime.
Gists

This is a sample script for achieving the pseudo OnEdit trigger for Google Document using Google Apps Script.
In the current stage, there is not OnEdit trigger for Google Document. Ref But I sometimes have the case that I want to use OnEdit trigger. So, as the current workaround, I created this sample script. I think that this workaround can be also used for Google Slides, Google Form and also Google Spreadsheet. In the case of Spreadsheet, what the existing OnEdit trigger and the time-driven trigger cannot do can be achieved.
Gists
This is a workaround for converting the range ID to the range object on Google Spreadsheet using Google Apps Script.
When the named range is put to a cell as the hyperlink as follows,

the hyperlink is like #rangeid=123456789. When this link is clicked, it moves to the cells of the named range. So it is considered that this value of #rangeid=123456789 includes the information about the range of the named range. But, unfortunately, in the current stage, there is no methods for directly retrieving the range object from the range ID. In this sample sample script, as a workaround, the range ID is converted to the range object using Google Apps Script.
Gists
This is a sample script for exporting all thumbnail images retrieved from Google Slides as a zip file using Google Apps Script.
Sample script
Before you use this script, please enable Slides API at Advanced Google services. Ref
function myFunction() {
const presentationId = "###"; // Please set Google Slides ID.
const folderId = "###"; // Please set the folder ID.
const outputFilename = "###"; // Please set the output filename.
const blobs = SlidesApp.openById(presentationId)
.getSlides()
.map((e, i) =>
UrlFetchApp.fetch(
Slides.Presentations.Pages.getThumbnail(
presentationId,
e.getObjectId(),
{
"thumbnailProperties.mimeType": "PNG",
"thumbnailProperties.thumbnailSize": "LARGE",
}
).contentUrl
)
.getBlob()
.setName(`page${("000" + (i + 1)).slice(-3)}.png`)
);
DriveApp.getFolderById(folderId).createFile(
Utilities.zip(blobs).setName(outputFilename + ".zip")
);
}
Gists
This is a sample workaround for letting users running Google Apps Script on Google Spreadsheet without both authorizing the scopes and showing the script.
The flow of this workaround is as follows.
- Create Web Apps created by Google Apps Script and deploy it as Web Apps. As the returned value, the XML data is returned.
- Your script can be included in this script.
- User put a formula of
=IMPORTML("WebApps URL", "xpath") to a cell.
By this flow, you can achieve to let users running Google Apps Script on Google Spreadsheet without both authorizing the scopes and showing the script.
My post of “Sending Multiple Emails using Batch Request with Gmail API using Google Apps Script” was featured at Google Workspace Developer Newsletter on October 2021.

Gists

This is a sample script for uploading a movie file on Google Drive to YouTube using Google Apps Script.
Before you use these scripts, please enable YouTube API at Advanced Google services. Ref
Sample script 1
This sample script uses YouTube API at Advanced Google services.
function myFunction() {
const fileId = "###"; // Please set the file ID of movie file on the Google Drive.
const res = YouTube.Videos.insert(
{ snippet: { title: "sample title", description: "sample description" } },
["snippet"],
DriveApp.getFileById(fileId).getBlob()
);
console.log(res);
}
Sample script 2
This sample script requests to the endpoint of YouTube API with UrlFetchApp by creating the request body. This script requests with multipart/form-data.
Gists

This is a sample script for updating the values of “Sheet A” with the values of “Sheet B” using Google Apps Script. I often see this situation at Stackoverflow and other sites. So, in this post, I would like to introduce the sample script using Google Apps Script.
Sample script
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [src, dst] = ["Sheet1", "Sheet2"].map((e) => ss.getSheetByName(e));
const obj = src
.getRange("A2:B" + src.getLastRow())
.getValues()
.reduce((o, [a, b]) => ((o[a] = b), o), {});
const values = dst
.getRange("A2:A" + dst.getLastRow())
.getValues()
.map(([b]) => [obj[b] || ""]);
dst.getRange(2, 2, values.length, 1).setValues(values);
}
Of course, this situation can be also achieved with the built-in formula of Spreadsheet. For example, when the above image is used, the same result with the column “B” can be obtained at the column “C” by putting a formula of =ARRAYFORMULA(VLOOKUP(A2:A11,Sheet2!A2:B6,2)) to the cell “C2”.
Gists
This is a sample script for reducing the table height of the table inserted from Google Spreadsheet to Google Slides using Google Apps Script.

Sample script
Please copy and paste the following script to the script editor of Google Slides. This sample script uses Slides API. So, please enable Slides API at Advanced Google services. Ref
As the sample situation, this script supposes that a table is manually copied from Google Spreadsheet to the 1st slide of Google Slides. So when you test this script, please copy the cells from Google Spreadsheet to the 1st slide of Google Slides and run the function.
Gists
This is a sample script for retrieving the glyph value from the list items of Google Document using Google Apps Script.
In the current stage, when the list is put to the Google Document, the count of glyph is automatically calculated. When the glyph values of the list items are tried to be retrieved using the manual operation and the script, unfortunately, the glyph values cannot be retrieved. Only the values of the list are retrieved. Unfortunately, it seems that in the current stage, there are no methods for directly retrieving the glyph value from the list items.
Gists
This is a report about images put with “=IMAGE(IMAGE_URL)” function on Google Spreadsheet.
Experiment
When “=IMAGE(IMAGE_URL)” is put to a cell “A1” on Spreadsheet, the image is shown in the cell as shown in the following image.

For this situation, when the following script is run,
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
const range = sheet.getRange("A1");
range.copyTo(range, { contentsOnly: true });
The following result is obtained. In this case, the formula is removed and an image can be seen as shown in the following image.
GitHub

This is a sample script for the file picker using Google Apps Script and Javascript without 3rd party. I had created the same sample script before. Ref But, in the case of that script, jQuery is used. And, only Google Drive of own account could be used. In this sample script, 3rd party of jQuery is not used, and also, not only Google Drive of your own account, but also Google Drive of the service account can be used. By this, I thought that this file picker will be useful for various scenes.
Gists

This is a sample script for converting the values of Google Spreadsheet to an object using Google Apps Script.
Sample script
function myFunction() {
const sheetName = "Sheet1";
const [headers, ...rows] = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName).getDataRange().getValues();
const res = rows.map((r) => headers.reduce((o, h, j) => Object.assign(o, { [h]: r[j] }), {}));
console.log(res);
}
-
When this script is run, the above sample image can be retrieved.
-
In this sample script, the 1st row of the sheet is used as the header row.
-
const res = rows.map((r) => headers.reduce((o, h, j) => Object.assign(o, { [h]: r[j] }), {})); can be also replaced with const res = rows.map((r) => headers.reduce((o, h, j) => (o[h] = r[j], o), {}));.
RichTextApp was updated to v1.3.0

You can see the detail information here https://github.com/tanaikech/RichTextApp
Gists
There is Class TextFinder in Spreadsheet service for Google Apps Script. Ref The TextFinder can search and replace the texts in the Spreadsheet using Google Apps Script. There is the method for createTextFinder in Class Spreadsheet, Class Sheet and Class Range. When these methods are used, you can search and replace the texts for all sheets in a Spreadsheet, the specific sheet, and the specific range in the specific sheet.
Gists

This is a sample script for sending multiple emails using the batch request with Gmail API using Google Apps Script. When multiple emails are sent using “GmailApp.sendEmail” and “MailApp.sendEmail”, a loop is used. But in this case, the process cost becomes high. In this post, I would like to introduce the sample script for reducing the process cost under this situation. Gmail API can be requested with the batch request. The batch request can be processed with the asynchronous process. By this, I thought that the process cost for sending multiple emails. So, this sample script sends multiple emails using the batch request with Gmail API.
Gists
This is a sample script for putting all response values from Google Form to Google Spreadsheet using Google Apps Script.

Sample script
Please copy and paste the following script to the script editor of Google Spreadsheet and set the variables of formId and sheetName.
function myFunction() {
const formId = "###"; // Please set the Google Form ID.
const sheetName = "Sheet1"; // Please set the sheet name of sheet you want to put the values.
// Retrieve all response values from Google Form.
const form = FormApp.openById(formId);
const headers = ["date", ...form.getItems().map(e => e.getTitle())];
const values = [headers, ...form.getResponses().map((f) => {
const timeStamp = f.getTimestamp();
return f.getItemResponses().reduce((o, i) => {
const r = i.getResponse();
return Object.assign(o, {
[i.getItem().getTitle()]: Array.isArray(r) ? r.join(",") : r,
});
}, { date: timeStamp });
}).map((o) => headers.map((t) => o[t] || ""))];
// Put the values to Spreadsheet.
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName).getRange(1, 1, values.length, values[0].length).setValues(values);
}
- When this script is run, all response values are retrieved from Google Form and put them to the Spreadsheet.
Note
- At Google Form, when the empty answer is submitted, the question has no value. By this, it is required to consider this. So at first, the titles are retrieved from the items, and the values are created using the item titles. I thought that this might be an important point.
References
- This sample script was used for the following threads.
Gists
In this report, it has investigated the large decimal numbers and the exponential notation for Google Spreadsheet. When the large decimal numbers are put to the Spreadsheet, the Spreadsheet automatically sets the display value using the exponential notation. In this report, the result when the values are retrieved by Spreadsheet service and Sheets API is shown.
Sample script
At first, please create new Spreadsheet and open the script editor. And please copy and paste the following script. And, please enable Sheets API at Advanced Google services.
Gists
This is a sample script for sending Gmail with the title and body including Emoji using Google Apps Script.

Sample script
This sample script uses Gmail API. So please enable Gmail API at Advanced Google services. Ref
const convert_ = ({ to, emailFrom, nameFrom, subject, textBody, htmlBody }) => {
const boundary = "boundaryboundary";
const mailData = [
`MIME-Version: 1.0`,
`To: ${to}`,
nameFrom && emailFrom ? `From: "${nameFrom}" <${emailFrom}>` : "",
`Subject: =?UTF-8?B?${Utilities.base64Encode(
subject,
Utilities.Charset.UTF_8
)}?=`,
`Content-Type: multipart/alternative; boundary=${boundary}`,
``,
`--${boundary}`,
`Content-Type: text/plain; charset=UTF-8`,
``,
textBody,
``,
`--${boundary}`,
`Content-Type: text/html; charset=UTF-8`,
`Content-Transfer-Encoding: base64`,
``,
Utilities.base64Encode(htmlBody, Utilities.Charset.UTF_8),
``,
`--${boundary}--`,
].join("\r\n");
return Utilities.base64EncodeWebSafe(mailData);
};
// Please run this function.
function main() {
const obj = {
to: "###", // Please set the email for `to`.
emailFrom: "###", // Please set the email for `from`.
nameFrom: "sample name",
subject: "Hello World 😃⭐",
textBody: "sample text body 😃⭐",
htmlBody: "<p>Hello World 😃⭐</p>",
};
Gmail.Users.Messages.send({ raw: convert_(obj) }, "me");
}
- In order to use Emoji in the subject, the subject value is converted to the base64 data. And, it is used as
=?UTF-8?B?###?=. Ref
- About the method for including Emoji to the email body, I have answered it at this thread of Stackoverflow.
Reference
Gists
This is a sample script for compiling the continuous numbers using Google Apps Script. For example, the values of [4, 5, 9, 3, 10, 5, 11, 7, 7, 13, 1] are converted to ["1","3-5","7","9-11","13"].
Sample script
const compilingNumbers = (ar) => {
const { values } = [...new Set(ar.sort((a, b) => a - b))].reduce(
(o, e, i, a) => {
if (
o.temp.length == 0 ||
(o.temp.length > 0 && e == o.temp[o.temp.length - 1] + 1)
) {
o.temp.push(e);
} else {
if (o.temp.length > 0) {
o.values.push({ start: o.temp[0], end: o.temp[o.temp.length - 1] });
}
o.temp = [e];
}
if (i == a.length - 1) {
o.values.push(
o.temp.length > 1
? { start: o.temp[0], end: o.temp[o.temp.length - 1] }
: { start: e, end: e }
);
}
return o;
},
{ temp: [], values: [] }
);
return values;
};
// Please run this function.
function main() {
const ar = [4, 5, 9, 3, 10, 5, 11, 7, 7, 13, 1]; // This is sample values.
const values = compilingNumbers(ar);
console.log(values);
const res = values.map(({ start, end }) =>
start == end ? start.toString() : `${start}-${end}`
);
console.log(res);
}
When this script is run, console.log(values) and console.log(res) show [{"start":1,"end":1},{"start":3,"end":5},{"start":7,"end":7},{"start":9,"end":11},{"start":13,"end":13}] and ["1","3-5","7","9-11","13"], respectively. From this result, it is found that the continuous numbers were compiled.
Gists
This is a sample script for sending Outlook emails using Microsoft account with Google Apps Script.

Before you use this script, please install OnedriveApp which is Google Apps Script library. Ref And, please authorize your Microsoft account for using Microsoft Graph API. Ref
Sample script
function myFunction() {
const obj = [
{
to: [{ name: "### name ###", email: "### email address ###" }, , ,],
subject: "sample subject 1",
body: "sample text body",
cc: [{ name: "name1", email: "emailaddress1" }, , ,],
},
{
to: [{ name: "### name ###", email: "### email address ###" }, , ,],
subject: "sample subject 2",
htmlBody: "<u><b>sample html body</b></u>",
attachments: [blob],
bcc: [{ name: "name1", email: "emailaddress1" }, , ,],
},
];
const prop = PropertiesService.getScriptProperties();
const odapp = OnedriveApp.init(prop);
const res = odapp.sendEmails(obj);
console.log(res);
}
In this sample script, 2 emails are sent using Microsoft Graph API with your Microsoft account. By this, both Outlook Emails and Google Emails can be used by Google Apps Script.
Gists
This is a sample script for retrieving the list of all emails of Microsoft account and putting them to Google Spreadsheet using Google Apps Script.

I updated OnedriveApp to v1.2.0 by adding 1 method for retrieving the access token and 7 methods for managing emails of Microsoft account. By this, the emails got to be able to be gotten and sent using Microsoft account using OnedriveApp with Google Apps Script.
OnedriveApp was updated to v1.2.0.
GitHub of OnedriveApp
OnedriveApp was updated to v1.1.2.
-
v1.1.2 (September 29, 2021)
A bug of method of uploadFile was removed. By this, the files except for Google Docs files can be uploaded to OneDrive.
GitHub of OnedriveApp
Gists
This is a sample script for directly submitting answers to Google Form using Google Apps Script.
The sample Google Form is as follows.

For this Google Form, this sample script submits the values of sample text, option2 and option1, option2, sample option to Google Form.
Sample script
For the multiple answers, it seems that it is required to send the values as the query parameter. I thought that the same key is used.
Gists
This is a sample script for replacing the template texts with an array in Google Document using Google Apps Script. This is for Google Apps Script of this report.
The sample input and output situations are as follows.

In the current stage, when replaceAllText of Docs API is used with the sample value of ["updated text 1", "updated text 2", "updated text 3"], all values of {{oldText}} are replaced with the 1st value of updated text 1 in one batch request. So in order to replace each {{oldText}} with ["updated text 1", "updated text 2", "updated text 3"], it is required to use a workaround. So I proposed this report.
Gists
This is a sample script for executing a function with the minutes timer in the specific times using Google Apps Script. For example, when this sample script is used, the following situation can be achieved.
- Execute a function every 10 minutes only in 09:00 - 12:00 and 15:00 - 18:00 for the weekday.
When the above situation is shown as an image, it becomes as follows.

In the above sample situation, a function is run every 10 minutes in the green ranges of 09:00 - 12:00 and 15:00 - 18:00.
Gists

This is a sample script for simply editing the texts of texts boxes on Google Slides using Google Apps Script. The supposed situation is as follows.
- Google Slides has several text boxes of the same size and the same position.
- You want to retrieve the list of texts from the text boxes and want to change the texts using a simpler method.
In this case, I thought that when the sidebar created by Google Apps Script is used for changing the texts, your goal might be able to be simply achieved.
Gists
-
Published: September 15, 2021
-
Updated: September 17, 2021
- From the discussions, added data by changing the wait time of LockService for Web Apps.
Kanshi Tanaike
Introduction
When the users try to write to a Spreadsheet using a form, the developers have to consider the concurrent submission from the form. For example, when multiple users submit the data with the form simultaneously, all data are possibly not to be saved to the Spreadsheet. So it is considered that it is important to know the information about the concurrent writing to Google Spreadsheet using a form. In this report, such a situation was investigated.
Gists
This is a sample script for retrieving the hidden rows and showing rows by the filter view on Google Spreadsheet using Google Apps Script. In the current stage, there are no methods for directly retrieving the hidden rows and showing rows by the filter view in Spreadsheet service (SpreadsheetApp). And, isRowHiddenByFilter of Class Sheet cannot be used for the filter view. But, fortunately, when Sheets API is used, the filter view can be retrieved and created. In this report, the hidden rows and showing rows by the filter view are retrieved using Sheets API.
Gists
Introduction
Here, I would like to report the process costs for retrieving the 1st empty cell or 1st non empty cell of the specific column of Google Spreadsheet using Google Apps Script (GAS). For this situations, the following 2 patterns can be considered.
-
Retrieving 1st empty cell of specific column by searching from TOP of sheet
-
Retrieving 1st NON empty cell of specific column by searching from BOTTOM of sheet
Gists
This is a sample script for changing the font of selected text to Google Sans on Google Document using Google Apps Script.

Sample script
Please copy and paste the following script to the script editor of Google Document And, when you use this script, please select a text in Google Document and run the script. By this, the font of selected text is changed to Google Sans.
function myFunction() {
const selection = DocumentApp.getActiveDocument().getSelection();
const element = selection.getRangeElements()[0];
element
.getElement()
.asText()
.setFontFamily(
element.getStartOffset(),
element.getEndOffsetInclusive(),
"Google Sans"
);
}
References
This sample script was posted for explaining at https://groups.google.com/g/google-apps-script-community/c/ehC7C95W5t0.
Gists
This is a sample script for creating the colorful buttons on Google Spreadsheet on Google Apps Script.
In order to achieve this, I have been looking for the method for creating the PNG image with the alpha channel using Google Apps Script. Recently, finally, I could find it. By this, the goal of this report got to be able to be achieved by the report of “Creating PNG Image with Alpha Channel using Google Apps Script”.
This is a sample script for creating a PNG image with the alpha channel using Google Apps Script.
The PNG image with the alpha channel is the image includes the transparent background. I have been looking for the method for creating such image using Google Apps Script. It is considered that when this will be achieved, it will be able to be used for various situations. For example, it is considered the following situations.
Gists
I had confirmed a bug of new IDE about the time zone of Google Apps script project. When I created new Google Apps Script project using new IDE, the time zone of GAS project is always America/New_York. In my area, it’s Asia/Tokyo. The time zone can be confirmed at appscript.json.
So, I had reported this issue to Google issue tracker. Ref After I posted this, I had also confirmed this issue at Stackoverflow. Ref
Gists
This is a sample script for plotting the points on an image using Google Apps Script.
Unfortunately, in the current stage, there are no methods for directly editing the image and putting the texts and some shapes in the methods for Google Apps Script. So in this case, it is required to use the workaround.
Fortunately, I have already published a report about “Inserting Text on Image using Google Apps Script” in my blog. Ref In this report, this sample is used.
Gists
At March 15, 2021, one endpoint is created for one deployment. Ref By this, when you redeploy “Web Apps”, the endpoint is changed. Because the deployment ID is changed. It seems that this it the new specification. In this report, I would like to introduce the method for redeploying Web Apps without changing the URL of Web Apps for new IDE.
Deploy Web Apps
-
Open “New deployment” dialog with “Deploy” -> “New deployment”.
This is the document for linking Google Cloud Platform Project to Google Apps Script Project for New IDE. And also, several sample scripts using Google Apps Script API and Google Photos API are introduced.
You can see the detail of this document at https://github.com/tanaikech/Linking-Google-Cloud-Platform-Project-to-Google-Apps-Script-Project-for-New-IDE.
Gists
This is a sample script for copying the protections for Spreadsheet using Google Apps Script. When several protections of the sheet protection and the range protection are set to a Google Spreadsheet and the Spreadsheet is copied using the script and the manual copy with the browser, unfortunately, the protections of ranges are not copied. And also, the protections of sheets can be copied. But, the editor emails are not included. It seems that this is the current specification.
Overview
This is a Javascript library for sending the HTML form object to Google Apps Script using google.script.run.

Description
HTML form object is parsed by this library, and the object can be sent to Google Apps Script using google.script.run. After the V8 runtime got to be able to be used for Google Apps Script, when the file input tag is included in the HTML form object, the object sent to Google Apps Script using google.script.run cannot be directly used. Because it seems that the binary file data cannot be parsed when it is sent with google.script.run. Ref In the current stage, as the workaround, the file data is required to be sent to Google Apps Script using google.script.run after it was converted to the byte array and the base64 data. I think that this might be resolved in the future update. But I thought that as the current workaround, when the parser for converting this is prepared, it might be useful for users, because I saw the several questions which have this issue at Stackoverflow.
Gists
In this post, I would like to introduce the xpath tester using Web Apps created by Google Apps Script.
Demo

Usage
1. Prepare Google Spreadsheet.
Please create new Google Spreadsheet on your Google Drive.
2. Enable Sheets API.
Please open the script editor at the created new Spreadsheet and enable Sheets API at Advanced Google services.
3. Prepare sample script.
Please copy and paste the following script to the script editor on the created new Spreadsheet and save it.
Overview
This is a sample script for achieving a simple photo gallery created by Google Slides and Web Apps using Google Apps Script.
Description
At Google, there is a great Google Photos. Ref Recently, I was required to have a simple photo gallery. At that time, I thought that when an independence photo gallery instead of Google Photos can be used, it will be useful. Also, this might be useful
for other users. So I published this.
Gists
Published: January 16, 2021
Kanshi Tanaike
Introduction
At Stackoverflow, a lot of people post the questions and answers to the questions every day. There are various tags in Stackoverflow. A lot of discussions are performed at each tag. Their discussions bring the important information and are much useful for a lot of people. As one of tags, there is “google-apps-script”. I sometimes discuss at the questions with that tag. When we see the discussions, we can notice that the discussions are changed and progressed by the time, because “Google Apps Script” which is the origin of the tag is updated. This report thinks this change as the trend of tag of “google-apps-script”. This trend includes the number of questions, questioners, answerers and tags adding to the tag of “google-apps-script”. The trend of tag of “google-apps-script” is deeply related to the progression of Google Apps Script and the various applications for Google Apps Script.
Gists
This is a sample script for creating the custom grid view of Google Slides as an image using Google Apps Script.
Demo

Usage
In order to use this script, please do the following flow.
1. Install GAS library
This sample script uses a library of DocsServiceApp. So please install DocsServiceApp. You can see the method for installing it at here.
2. Enable APIs
This sample script uses 2 APIs of Drive API and Slides API. So please enable them at Advanced Google services. Ref
BatchRequest was updated to v1.1.3.
You can check this at https://github.com/tanaikech/BatchRequest.
Gists
This is a sample script for adding the slide page link to the shape using Google Apps Script.
When I use Google Slides, there is the case that I want to jump to the specific slide on the same Google Slides. And, I have the case that I want to jump from the last slide to the 1st slide. In those cases, I had manually added the slide page link to each shape. But when the number of slides are large, I thought that when a script for achieving this is prepared, it will be useful. So I created this.
Overview
This is a report for safe-uploading files to Google Drive by HTML put in the external server using Google Apps Script.
Description
When you want to make the user upload a file to your own Google Drive using the HTML put in the external server of Google side, when the file size is smaller than 50 MB, this can be achieved without using the access token. Ref (When the HTML is put in the internal server of Google side, you can also use google.script.run.) But, when the file size is over 50 MB, it is required to upload the file with the resumable upload. In this case, the access token is required to be used. In this case that the user uploads to your own Google Drive, when the access token is used in the upload, it is considered that this is the weak point of the security. In this report, I would like to propose the method for safe-uploading files to Google Drive by HTML put in the external server using Google Apps Script. Please think of this as one of several methods.
Original post
Superheroes are well known for wearing capes, fighting villains and looking to save the world from evil. There also are superheroes that quietly choose to use their super powers to explain technology to new users, maintain community forums, write blog posts, speak at events, host video series, create demos, share sample code and more. All in the name of helping other developers become more successful by learning new skills, delivering better apps, and ultimately enhancing their careers. At Google, we refer to the latter category of superheroes as Google Developer Experts or “GDEs” for short.
FilesApp was updated to v1.1.3.
GitHub of FilesApp
New IDE for Google Apps Script has finally been released at December 7, 2020. Ref

I think that the speed for displaying the log is faster than old one, and the code completion also got to be easy to see.
Gists
This is a sample script for achieving the search of files by is:unorganized owner:me using Google Apps Script.
In the current stage, unfortunately, the files cannot be directly retrieved by searching is:unorganized owner:me with Drive API and Drive service. So as the current workaround, all files are retrieved using the method of “Files: list” of Drive API with 'me' in owners and trashed = false, and the file list is retrieved from all file list using a script.
Gists
This is the sample scripts for creating new event with Google Meet link to Google Calendar using various languages. When I saw the official document of “Add video and phone conferences to events”, in the current stage, I can see only the sample script for Javascript. But I saw the several questions related to this for various languages. So I published the sample scripts for creating new event with Google Meet link to Google Calendar using various languages.
Gists
This is a sample script for downloading the active sheet in Google Spreadsheet to the local PC as a CSV file and a PDF file when a button on the side bar and the dialog is clicked. This is created with Google Apps Script and HTML&Javascript. In this post, the script of the previous post was modified.

Sample script
Please create new Google Spreadsheet and copy and paste the following scripts to the script editor. And please run openSidebar(). By this, the side bar is opened to the Spreadsheet.
Gists
This is a sample script for converting the texts to the bold, italic, bold-italic types, underline and strike through of the unicode using Google Apps Script. In the current stage, at Google Docs (Spreadsheet, Document, Slides and so on), the rich texts cannot be directly managed for all places using Google Apps Script. But there are the places which can use the bold, italic and bold-italic fonts with the unicode. This sample script uses this. When this sample script is used, for example, the bold, italic and bold-italic texts can be put using SpreadsheetApp.getUi().alert(convertedText).
Gists
This is a sample script for replacing the multiple values with various values in Google Spreadsheet with the low process cost using Google Apps Script. In this script, the batchUpdate method of Sheets API is used. So the request can be done by one API call. When Spreadsheet services is used for this situation, the values are retrieved from the sheet and replaced the retrieved values, and then, the updated values are put to the sheet. Or the TextFinder is used in a loop. In this case, the process cost is higher than that using Sheets API. By using the bathUpdate method of Sheets API, the process cost is reduced.
Gists
Description
When Google Spreadsheet is used, there is the case that the built-in functions and the custom functions in the cells are used. For the functions of Google Apps Script, there is the method for measuring the process cost. Ref But for the built-in functions, it is required to create the script for it. In this report, the script for measuring a function put in a cell has been proposed, and the process cost of the built-in functions has been measured. The proposed script can measure the process cost for the built-in functions and custom functions on Google Spreadsheet. The script is created with using Google Apps Script. When the process cost can be known for the built-in functions and custom functions, it is considered that it will be useful for the developers using Google Spreadsheet.
Gists
This is a sample script for downloading Google Spreadsheet to the local PC as a XLSX file and a PDF file when a button on the side bar and the dialog is clicked. This is created with Google Apps Script and HTML&Javascript.

Sample script
Please create new Google Spreadsheet and copy and paste the following scripts to the script editor. And please run openSidebar(). By this, the side bar is opened to the Spreadsheet.
Gists
There is a situation that it wants to make users run a script for the range protected by the owner using Google Apps Script. This is a sample script that an user runs a script for the range protected by the owner using Google Apps Script.
Demo

This demonstration shows the following situations.
Gists
Introduction
Here, I would like to report the process costs for retrieving the values from the arrays for Spreadsheet using Google Apps Script (GAS). When Spreadsheet is used with Google Apps Script, we have the following situations.
-
Retrieve values from the multiple rows in a column.
-
Retrieve values from the multiple columns in a row.
When the values are retrieved from above situations, it is required to retrieve the values from 1 dimensional array in the 2 dimensional array. In this report, the process costs for retrieving the values from the 2 dimensional array of above situations have been measured.
Gists
This is a sample script for creating the multiple buttons on Google Spreadsheet using Google Apps Script.
Recently, I have got several contacts about this. I thought that when this is published, it might be useful for other users. So I published this sample script.

Sample script
Please copy and paste the following script to the script editor of the container-bound script of Google Spreadsheet. And, please set the variables and run the function createButtons. By this, the buttons are created to the cells.
Gists
This is a sample script of the request of multipart/form-data with a simple request body using Google Apps Script. I hope that the users will easy to use Class UrlFetchApp by this report.
This report is the updated post of “Multipart-POST Request Using Google Apps Script”.
Description
I had already reported about this at this report. In that case, it was required to create a bit complicated request body to request multipart/form-data. Today, by a comment, I could notice the sample script of Class UrlFetchApp in the official document had been updated. By this, I thought that multipart/form-data will be requested with a simple request body. In this report, I would like to introduce a sample script for requesting multipart/form-data with a simple request body. But I’m not sure whether this request got to be able to be done by the internal update of Class UrlFetchApp.
Gists
This is a sample script for inserting a text on an image using Google Apps Script.
Demo

In this demonstration, “sample text” is inserted to the image. The image is from https://www.deviantart.com/k3-studio/art/Rainbow-painting-281090729.
Preparation
When you use this script, please install the following 2 Google Apps Script libraries.
- DocsServiceApp
- ImgApp
And, please enable Slides API at Advanced Google services.
Flow
The flow of this sample script is as follows.
- Retrieve the image size using ImgApp.
- Create new Google Slides with the custom page size using DocsServiceApp.
- Put the image and text.
- Export the result image.
Sample script
function myFunction() {
const fileId = "###"; // Please set the file ID of image file.
// Please set the text.
const text = {
text: "sample text",
left: 10,
top: 120,
width: 180,
height: 60,
fontSize: 30,
};
// 1. Retrieve the image size using ImgApp.
const file = DriveApp.getFileById(fileId);
const blob = file.getBlob();
const size = ImgApp.getSize(blob);
// 2. Create new Google Slides with the custom page size using DocsServiceApp.
const object = {
title: "sample title", // Title of created Slides.
width: { unit: "pixel", size: size.width },
height: { unit: "pixel", size: size.height },
};
const presentationId = DocsServiceApp.createNewSlidesWithPageSize(object);
// 3. Put the image and text.
const s = SlidesApp.openById(presentationId);
const slide = s.getSlides()[0];
slide.insertImage(blob);
slide
.insertTextBox(text.text, text.left, text.top, text.width, text.height)
.getText()
.getTextStyle()
.setFontSize(text.fontSize);
s.saveAndClose();
// 4. Export the result image.
const obj = Slides.Presentations.Pages.getThumbnail(
presentationId,
slide.getObjectId(),
{
"thumbnailProperties.thumbnailSize": "LARGE",
"thumbnailProperties.mimeType": "PNG",
}
);
const url = obj.contentUrl.replace(/=s\d+/, "=s" + size.width);
const resultBlob = UrlFetchApp.fetch(url)
.getBlob()
.setName("Result_" + file.getName());
DriveApp.createFile(resultBlob);
DriveApp.getFileById(presentationId).setTrashed(true);
}
Note
- This is a simple sample script. When you want to add more texts and change the text style, please modify the section 3 of above script.
- In this sample, the maximum size of image is
25,000,000 pixels^2. Ref Please be careful this.
Testing
- February 6, 2021: When I tested above sample script, I could confirm that the script worked.
- January 3, 2023: When I tested above sample script, I could confirm that the script worked.
Gists
This is a sample script for retrieving all values from all sheets from URL of 2PACX- of Web Published Google Spreadsheet using Google Apps Script and Javascript.
In this post, it supposes that the Google Spreadsheet has already been published for Web. Ref
Flow
The flow of this method is as follows.
- From the client side, send the URL of web published Google Spreadsheet to the Web Apps created by Google Apps Script.
- The URL is like
https://docs.google.com/spreadsheets/d/e/2PACX-###/pubhtml.
- Return the byte array of XLSX data from the Web Apps to the client side.
- At the client side, the XLSX data is parsed with SheetJS js-xlsx.
- Retrieve all values from all sheets.
Usage
1. Prepare script.
Please copy and paste the following script to the script editor and save it.
Gists
This is a sample script for sorting the cells on Google Spreadsheet with the background colors using Google Apps Script.
Unfortunately, in the current stage, it seems that sort(sortSpecObj) of Class Range cannot directly sort by the background colors of cells. But when Sheets API is used, this goal can be achieved. Here, “SortRangeRequest” of the method of “spreadsheets.batchUpdate” in Sheets API is used.

Flow
The flow of this sample script is as follows.
Gists
Introduction
At Stackoverflow, a lot of people post the questions and answer to the questions every day. By this, there are a lot of important information in Stackoverflow. I have already reported “Trend of google-apps-script Tag on Stackoverflow” using the data retrieved from Stackoverflow. Ref. 1 It is found that the important statistical result can be obtained by analyzing the data on Stackoverflow. In this report, I would like to introduce the statistical analysis of duplicated questions for the google-apps-script tag in Stackoverflow. When the duplicated question is analyzed, it is considered that the important issues for users can be known. As the result, it was found that there are the trend that the duplicated questions related to Javascript, Google Spreadsheet , the process cost and the cooperation with HTML and Javascript are posted.
Gists
This is a sample script for setting alternate background colors for rows in Google Spreadsheet using Google Apps Script.
It has already been known when the conditional formatting rule and custom function are used, this can be simply achieved. Ref In this report, I would like to introduce the method for using Google Apps Script.

Sample script
In this sample script, the values of column “A” are checked.
function myFunction() {
const colors = { color1: "#f4cccc", color2: "#d9ead3" };
const sheet = SpreadsheetApp.getActiveSheet();
const ranges = sheet
.getRange("A1:A" + sheet.getLastRow())
.getValues()
.reduce(
(o, [b], i) => {
if (b != o.temp) {
o.temp = b;
o.c++;
}
o[["color1", "color2"][o.c % 2]].push(`${i + 1}:${i + 1}`);
return o;
},
{ color1: [], color2: [], c: 0, temp: "" }
);
Object.entries(colors).forEach(([k, v]) =>
sheet.getRangeList(ranges[k]).setBackground(v)
);
}
- The process cost of this script can be reduced by using RangeList.
Reference
Gists
This is a sample Google Apps Script for running the specific function when the specific sheet is edited.
Sample script
Please copy and paste the following script to the container-bound script of Spreadsheet and set sheets object.
// When the cells are edited, this function is run by the fire of event trigger.
function onEdit(e) {
// Please set the sheet name and function as follows.
const sheets = {
Sheet1: functionForSheet1, // Sheet1 is the sheet name. functionForSheet1 is the function name of function which is run when Sheet1 is edited.
Sheet2: functionForSheet2,
};
const sheetName = e.range.getSheet().getSheetName();
if (sheets[sheetName]) {
sheets[sheetName](e);
}
}
// In this sample, when Sheet1 is edited, this function is run.
function functionForSheet1(e) {
console.log("Sheet1 was edited.");
// do something
}
// In this sample, when Sheet2 is edited, this function is run.
function functionForSheet2(e) {
console.log("Sheet2 was edited.");
// do something
}
- In this sample script, when the cells of “Sheet1” and “Sheet2” are edited,
functionForSheet1() and functionForSheet2() are run, respectively. When other sheets are edited, no functions are run.
- In this sample script,
onEdit of the simple trigger is used. When the functions you want to run include the methods which are required to authorize, please use the installable trigger.
Note
- This method can be also used for other event triggers like OnChange, OnSelectionChange and so son.
References
Gists
Introduction
Here, I would like to report the process costs for searching values in Spreadsheet using Google Apps Script (GAS). When the values are searched in Google Spreadsheet, the following 3 patterns can be considered. Ref
- Retrieve all values using
getValues, and the values are searched from the retrieved array.
- Use TextFinder.
- Use Query language.
In these cases, it has already been found that the lowest process cost is to use the Query language. And about finding values from an array, I have already been reported as “Benchmark: Search for Array Processing using Google Apps Script”. But I had never summarized the process costs for TextFinder and find values from an array. So in this report, I would like to introduce this. As the result, the importance of TextFinder for retrieving the row numbers and the row values by searching a value could be understand.
Gists
In order to print and export as PDF file, this is a sample script for converting Spreadsheet to Spreadsheet which has the custom header and footer.
In this sample script, DocsServiceApp, which is Google Apps Script library, is used. And, in this case, the Spreadsheet with the custom header and footer is created as new Spreadsheet.
Before you use this script, please install DocsServiceApp and enable Drive API at Advanced Google services.
ImgApp was updated to v1.3.0.

- v1.3.0 (September 24, 2020)
- Added new method. Added editImage()
- This method is for editing images. In the current stage, the image can be cropped. And several images can be merged as an image.
You can see the detail information here https://github.com/tanaikech/ImgApp
Overview
This is a Google Apps Script library for supporting Document service, Docs API, Spreadsheet service, Sheets API, Slides service and Slides API. The aim of this library is to compensate the processes that they services cannot achieve.

Description
The Google services, which are Document service, Docs API, Spreadsheet service, Sheets API, Slides service and Slides API, are growing now. But, unfortunately, there are still the processes that they cannot done. I created this GAS library for supporting the Google services.
FetchApp was updated to v1.0.2.
You can check this at https://github.com/tanaikech/FetchApp.
Gists
This is a sample script for retrieving All URLs in Google Document using Google Apps Script. In this sample script, the method of “documents.get” in Google Docs API is used. By this, the URL can be retrieve using JSON.parse().
Sample script
Before you use this script, please enable Google Docs API at Advanced Google Services.
const documentId = "###"; // Please set the Google Document ID.
const content = Docs.Documents.get(documentId).body.content;
const urls = [];
JSON.parse(JSON.stringify(content), (k, v) => {
if (k == "url") urls.push(v);
});
console.log(urls);
References
Gists
This is a sample script for using the values submitted from the HTML form using Google Apps Script and Javascript. In this case, the values include the files.
Issue
<form>
Text: <input type="text" name="sampleText1" /><br />
Single file: <input type="file" name="sampleFile1" /><br />
<input
type="submit"
name="button"
value="submit"
onclick="main(this.parentNode)"
/>
</form>
<script>
function main(e) {
google.script.run.sample(e);
}
</script>
This is a simple sample script for sending the values of form to Google Apps Script. In this case, texts and file are sent. When the button is clicked, main() is run. In this case, this.parentNode is sent to google.script.run.sample(this.parentNode). At that time, at Google Apps Script side, the text value can be correctly retrieved. But the file cannot be correctly sent. When the file is created as a file on Google Drive, the file is broken. I think that the reason of this issue might be due to character code.
Another approach
10 Aug 2022: Report: Challenging Exporting Selected Cells on Spreadsheet as Image using Google Apps Script and Javascript
Old approach
Gists
This is a sample script for converting a range in Google Spreadsheet as an image data using Google Apps Script. Unfortunately, there are no methods for directly converting the range in Google Spreadsheet as an image data in the built-in functions. So in this case, as a workaround, Charts Service is used.
Gists
These are sample scripts for modifying the 1st-page header in Google Document using Google Apps Script. Unfortunately, in the current stage, the 1st-page header cannot be modified by Document service. In this case, it is required to use Google Docs API. Here, I would like to introduce 2 sample scripts for modifying the 1st page header using Docs API.
When you use this, please enable Google Docs API at Advanced Google services.
Gists
This is a sample script for uploading a file to Google Drive from the external HTML without the authorization. In this case, the client side can be used at the outside of Google. And as the server side, the Web Apps created by Google Apps Script is used.
Usage
Please do the following flow.
1. Create new project of Google Apps Script.
Sample script of Web Apps is a Google Apps Script. So please create a project of Google Apps Script.
Gists
This is a sample script for decoding a QR code put in Google Slides using Google Apps Script. In this case, Javascript is used at the opened dialog. And Canvas API and jsQR are used. So unfortunately, this method cannot be used with the time-driven trigger and the Google Apps Script project of the standalone type.
Of course, this method can be also used for Google Document and Google Spreadsheet. But at Google Spreadsheet, I recommend to retrieve the image of QR code with the fetch method from URL.
Gists
This is a sample script for cropping images in the Google Slides using Google Apps Script. In the current stage, in order to crop the images in Google Slides, it is required to use replace(blobSource, crop) Because, although there is the “cropProperties” of “UpdateImagePropertiesRequest” in Slides API, unfortunately, in the current stage, this cannot be still used. This has already been reported. Ref
About cropping using replace(blobSource, crop), I thought that how to use might be a bit difficult. So here, I would like to introduce a sample script for using replace(blobSource, crop).
Gists
This is an important point for using reduceRignt with and without v8 runtime for Google Apps Script.
Sample script
function myFunction() {
var array = ["a", "b", "c", "d", "e"];
var res = array.reduceRight(function (ar, e, i) {
ar.push([e, i]);
return ar;
}, []);
Logger.log(res);
}
Result
With V8
When V8 runtime is used, the following result is obtained.
[["e",4],["d",3],["c",2],["b",1],["a",0]]
Without V8
When V8 runtime is NOT used, the following result is obtained.
[["e",0],["d",1],["c",2],["b",3],["a",4]]
Summary
When above results are compared, it is found that the indexes are different. The indexes of “With V8” is in the opposite direction to that of “Without V8”. Please be careful this.
-
v1.0.3 (August 1, 2020)
- When the file size less than the default chunk is downloaded, an error occurred. This bug was removed.
You can see the detail information here https://github.com/tanaikech/DownloadLargeFilesByUrl
Overview
This is a Google Apps Script library for creating, updating and exporting Google Apps Script project of the standalone type using Drive API. In this case, Apps Script API is not used.
Description
I had reported “Drive API cannot create Google Apps Script project no longer” before. Ref About this, I had reported the future request. Ref At July 30, 2020, I could confirm that the Google Apps Script project of the standalone type got to be able to be created by multipart/form-data using Drive API again. Ref This is a good news for me. By this, in order to use this with Google Apps Script, I created this library. Because in this case, when the update method is used, the special scope of https://www.googleapis.com/auth/drive.scripts is required. So I thought that when this is published as the Google Apps Script library, this will be useful for users.
Gists
I have reported “Drive API cannot create Google Apps Script project no longer”. Ref About this, I had reported the future request. Ref Today, I could confirm that the Google Apps Script project of the standalone type got to be able to be created by multipart/form-data using Drive API. This is a good news for me. By this, the following 2 patterns can be used from now.
Pattern 1:
- Create new standalone GAS project by Apps Script API.
- Put the local script to the created GAS project by updating the project with Apps Script API.
- Move the GAS project from the root folder to the specific folder using Drive API.
In this pattern, 3 API calls are required.
Gists
I have already reported for showing the log to “Apps Script Dashboard” when it requests to the Web Apps. Ref In order to show the log to “Apps Script Dashboard” when it requests to the Web Apps, it is required to use the access token. But in the current stage, when the access token is used for XMLHttpRequest and fetch of Javascript in the request headers, the error related to CORS occurs. So, in this report, I would like to propose the workaround for resolving this issue.
Gists
These are the sample scripts for achieving the switching buttons for Google Spreadsheet using Google Apps Script. The management of images using Spreadsheet service is growing now. But, in the current stage, in order to achieve the switching buttons, it needs a little ingenuity. In this report, I would like to introduce 4 kinds of the switching buttons.
Pattern 1
In this pattern, the drawing is used as the button.
Gists
This is a report for retrieving the logs in Web Apps for Google Apps Script, when it requests to the Web Apps.
Experimental condition
1. Sample script for Web Apps
const doGet = (e) => {
Logger.log(`GET method: ${JSON.stringify(e)}`);
console.log(`GET method: ${JSON.stringify(e)}`);
return ContentService.createTextOutput(
JSON.stringify({ method: "GET", e: e })
);
};
const doPost = (e) => {
Logger.log(`POST method: ${JSON.stringify(e)}`);
console.log(`POST method: ${JSON.stringify(e)}`);
return ContentService.createTextOutput(
JSON.stringify({ method: "POST", e: e })
);
};
- This Web Apps is deployed as
Execute the app as: Me and Who has access to the app: Anyone, even anonymous.
2. Sample Google Apps Script project
-
Google Apps Script of standalone type WITHOUT linking Google Cloud Platform (GCP) Project
Gists
This is a sample script for converting the SVG image data to PNG image data using Google Apps Script.
Unfortunately, in the current stage, there are no methods for directly converting the SVG to PNG in Google Drive service. But it can be achieved by Drive API. The sample script is as follows.
Before you use this, please enable Drive API at Advanced Google services.
Sample script
function myFunction() {
const svgFileId = "###"; // Please set the fileId of the SVG file.
const url = Drive.Files.get(svgFileId).thumbnailLink.replace(
"=s220",
"=s1000"
);
const blob = UrlFetchApp.fetch(url).getBlob(); // blob is the image blob of PNG format.
// In this sample, the retrieved image blob is put to Spreadsheet.
const sheet = SpreadsheetApp.openById("###").getSheetByName("Sheet1");
sheet.insertImage(blob, 1, 1).setWidth(500).setHeight(500);
}
Gists
This is the statistics for the tag triggers on Stackoverflow. The tag of triggers was created at 2011-07-28. This statistics are retrieve from Stackoverflow using Stackexchange API. About 2020, the data is retrieved from 2020-01-01 to 2020-07-16.
This statistics data was obtained at 2020-07-16.
Measurement result

Fig. 1: About triggers tag. Year vs. Total questions, Answered, Solved and Closed questions

Fig. 2: About google-apps-script tag and triggers tag. Year vs. Total questions, Answered, Solved and Closed questions
Gists
This is a sample script for retrieving “Users”, “Sessions” and “PageViews” of User Summary Report from Google Analytics using Google Apps Script. When you use this, please enable Analytics Reporting API at Advanced Google services.
Sample script
function myFunction() {
const viewId = "###";
const startDate = "2020-01-01";
const endDate = "2020-06-01";
const resource = {
reportRequests: [
{
viewId: viewId,
dateRanges: [{ startDate: startDate, endDate: endDate }],
metrics: [
{ expression: "ga:users" },
{ expression: "ga:sessions" },
{ expression: "ga:pageviews" },
],
},
],
};
const res = AnalyticsReporting.Reports.batchGet(resource, { fields: "*" });
console.log(res);
}
Result
{
"reports": [
{
"columnHeader": {
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:users",
"type": "INTEGER"
},
{
"type": "INTEGER",
"name": "ga:sessions"
},
{
"type": "INTEGER",
"name": "ga:pageviews"
}
]
}
},
"data": {
"maximums": [
{
"values": ["###", "###", "###"]
}
],
"rowCount": 1,
"totals": [
{
"values": ["###", "###", "###"]
}
],
"minimums": [
{
"values": ["###", "###", "###"]
}
],
"isDataGolden": true,
"rows": [
{
"metrics": [
{
"values": ["###", "###", "###"]
}
]
}
]
}
}
]
}
Reference
Gists
This table shows all tags using together with the tag of “google-apps-script” at Stackoverflow. The tags are summarized every year. At 2020, the data is retrieved from January 1, 2020 to July 16, 2020. The number enclosed (###) means the number of use of the tag. When this table was a material for discussing about the current tags for “google-apps-script”, I’m glad.
| Year |
Used Tag list |
| 2008 |
|
| 2009 |
google-form(1),google-sheets(1),google-apps-script(1) |
| 2010 |
google-apps-script(50),google-sheets(31),javascript(23),google-apps(4),custom-function(2),google-calendar-api(2),spreadsheet(2),google-docs-api(2),vba(2),google-docs(2),amazon(1),amazon-web-services(1),api(1),timezone(1),ms-office(1),xml-namespaces(1),xml(1),closures(1),google-sites(1),google-maps-api-3(1),array-formulas(1),google-sheets-formula(1),google-data-api(1),date-manipulation(1),datetime(1) |
| 2011 |
google-apps-script(72),google-sheets(31),google-apps(16),javascript(15),google-docs(8),google-spreadsheet-api(4),google-form(3),google-api(3),google-docs-api(2),spreadsheet(2),google-fusion-tables(2),google-calendar-api(2),java(2),google-app-engine(2),number-formatting(1),file-upload(1),google-apps-marketplace(1),json(1),email(1),html(1),tabpanel(1),gmail(1),performance(1),user-interface(1),zend-framework(1) |
| 2012 |
google-apps-script(1877),google-sheets(345),javascript(161),google-docs(63),google-sites(61),google-apps(54),google-spreadsheet-api(44),google-drive-api(44),gmail(40),google-calendar-api(31),google-docs-api(29),html(19),google-visualization(18),triggers(18),email(15),google-form(15),spreadsheet(14),urlfetch(13),gwt(13),oauth(13),custom-function(13),google-app-engine(12),user-interface(11),jquery(11),jdbc(10) |
| 2013 |
google-apps-script(2606),google-sheets(765),javascript(413),google-drive-api(124),google-docs(120),google-form(97),google-spreadsheet-api(78),google-apps(77),gmail(58),google-sites(57),html(56),google-calendar-api(41),google-api(34),email(31),google-docs-api(26),jquery(24),arrays(23),triggers(22),forms(22),google-app-engine(21),google-visualization(21),user-interface(20),spreadsheet(20),json(19),google-caja(19) |
| 2014 |
google-apps-script(2758),google-sheets(875),javascript(606),google-form(177),google-drive-api(168),google-docs(143),google-spreadsheet-api(90),google-apps(84),html(81),google-calendar-api(61),google-sites(56),gmail(54),email(53),jquery(49),arrays(45),forms(39),spreadsheet(35),triggers(35),excel(33),json(33),google-docs-api(28),google-api(28),google-app-engine(24),google-visualization(22),google-bigquery(22) |
| 2015 |
google-apps-script(2781),google-sheets(1134),javascript(714),google-form(159),html(158),google-docs(127),google-apps(115),google-spreadsheet-api(98),google-drive-api(97),gmail(66),arrays(57),google-calendar-api(57),jquery(51),google-api(46),forms(40),spreadsheet(39),email(38),google-docs-api(36),json(35),triggers(33),google-sites(32),regex(32),google-visualization(30),php(23),css(20) |
| 2016 |
google-apps-script(2888),google-sheets(1198),javascript(783),google-form(156),html(118),google-drive-api(117),google-apps(117),google-docs(77),arrays(74),google-spreadsheet-api(73),json(60),gmail(59),email(46),google-calendar-api(43),google-sheets-api(42),google-api(42),triggers(38),google-visualization(31),jquery(31),spreadsheet(31),google-docs-api(29),date(24),regex(23),forms(22),csv(22) |
| 2017 |
google-apps-script(3873),google-sheets(1537),javascript(979),google-form(194),html(158),google-sheets-api(137),google-docs(127),google-apps(122),google-drive-api(122),google-spreadsheet-api(114),arrays(110),gmail(85),email(64),json(56),gmail-api(52),google-api(52),triggers(51),jquery(51),spreadsheet(48),google-calendar-api(42),regex(34),google-sites(31),forms(27),custom-function(27),excel(27) |
| 2018 |
google-apps-script(4716),google-sheets(2062),javascript(1046),google-form(189),google-drive-api(189),google-docs(167),google-sheets-api(165),gmail-addons(155),html(134),triggers(129),gmail(120),arrays(111),google-calendar-api(79),json(68),google-app-maker(63),email(59),google-apps-script-addon(55),gmail-api(54),google-api(50),regex(50),custom-function(48),gsuite(47),google-bigquery(45),google-slides-api(43),web-applications(43) |
| 2019 |
google-apps-script(6731),google-sheets(3300),javascript(1352),google-form(263),html(250),google-sheets-api(223),google-drive-api(216),google-sheets-formula(168),google-docs(158),gmail(154),web-applications(143),arrays(141),google-sheets-macros(134),triggers(128),google-apps-script-web-application(112),google-calendar-api(88),gmail-addons(85),google-apps-script-addon(85),json(82),google-apps(77),gsuite(76),google-api(69),google-app-maker(64),scripting(61),google-apps-script-editor(61) |
| 2020 |
google-apps-script(4853),google-sheets(2503),javascript(1221),html(199),google-form(176),google-drive-api(161),google-apps-script-web-application(160),arrays(154),google-sheets-api(149),google-docs(124),google-sheets-formula(120),google-sheets-macros(90),gmail(86),json(85),google-apps-script-simple-triggers(69),google-calendar-api(68),urlfetch(66),google-apps-script-addon(65),spreadsheet(57),triggers(51),gsuite-addons(48),gs-installable-triggers(47),email(47),gsuite(47),google-apps-script-editor(45) |
Gists
These are the sample scripts by the various languages for requesting to Web Apps created by Google Apps Script.
- curl
- Google Apps Script
- Javascript
- ajax
- Node.js
- axios
- angular
- go
- python
- php
- powershell
Sample script for Web Apps
Gists
This is the statistics for the tag gas on Stackoverflow. This statistics are retrieve from Stackoverflow using Stackexchange API. About 2020, the data is retrieved from 2020-01-01 to 2020-07-01.
This statistics data was obtained at 2020-07-15.
Measurement result

Fig. 1: Year vs. Total questions, Answered, Solved and Closed questions
Table 1: Tags which were used together with gas tag for each year.
| Year |
Used Tag list |
| 2008 |
|
| 2009 |
gas(12),assembly(11),x86(4),gcc(3),nasm(2),linux(2),relative-addressing(1),disassembly(1),avr(1),macos(1),segments(1),inline-assembly(1),tdm-mingw(1),c(1),directive(1),mips(1),compiler-construction(1),gnu(1),stack(1),multithreading(1) |
| 2010 |
gas(31),assembly(28),x86(9),ld(6),gcc(4),linux(4),arm(4),gnu(3),c(3),inline-assembly(2),linker(2),elf(1),gdb(1),macos(1),ubuntu(1),mips(1),binutils(1),iphone(1),x86-64(1),64-bit(1),macros(1),intel-syntax(1),compiler-construction(1),python(1),embedded(1) |
| 2011 |
gas(46),assembly(37),x86(16),gcc(11),c(9),linux(6),gnu(4),64-bit(3),arm(3),nasm(3),att(3),inline-assembly(3),binutils(2),x86-64(2),register-allocation(2),system-calls(1),32-bit(1),cortex-a8(1),fibonacci(1),recursion(1),xcode(1),string(1),mips(1),dwarf(1),callstack(1) |
| 2012 |
gas(59),assembly(46),gcc(15),x86(10),x86-64(6),macos(6),gnu(6),linux(6),att(5),c(5),arm(4),ld(4),system-calls(3),binutils(3),nasm(3),struct(2),elf(2),syntax(2),interrupt(2),fpu(2),inline-assembly(1),clang(1),webrtc(1),compilation(1),iphone(1) |
| 2013 |
gas(70),assembly(55),x86(18),x86-64(16),gcc(14),linux(14),att(7),nasm(6),c++(5),inline-assembly(4),c(4),syntax(3),intel-syntax(2),printf(2),arm(2),intel(2),segmentation-fault(2),arrays(2),linker(2),i386(2),ffmpeg(1),ios(1),yasm(1),tasm(1),elf(1) |
| 2014 |
gas(61),assembly(53),x86(17),c(9),gcc(8),x86-64(7),nasm(5),linux(5),gdb(4),arm(4),stack(3),masm(3),disassembly(3),att(3),inline-assembly(3),arrays(2),32-bit(2),cpu-registers(2),shellcode(1),sockets(1),intel-syntax(1),opcode(1),gnu(1),c++(1),scanf(1) |
| 2015 |
gas(89),assembly(76),x86(25),att(15),c(13),gcc(12),x86-64(12),gnu(6),nasm(4),linux(4),gdb(3),inline-assembly(3),mips(3),macos(2),clang(2),elf(2),disassembly(2),macros(2),yasm(2),xcode(2),calling-convention(2),makefile(2),ld(2),arm64(2),intel-syntax(1) |
| 2016 |
gas(97),assembly(86),x86(32),x86-64(17),gcc(16),linux(16),att(14),c(5),nasm(5),osdev(4),ld(4),x86-16(4),linker(4),c++(3),gnu(3),gdb(2),forth(2),riscv(2),dwarf(2),intel(2),memory-alignment(2),intel-syntax(2),macos(2),system-calls(2),real-mode(2) |
| 2017 |
gas(73),assembly(64),x86(26),gcc(22),att(15),c(11),x86-64(11),intel-syntax(4),gnu(4),linux(4),arm(4),bootloader(4),64-bit(4),nasm(3),x86-16(3),ubuntu(2),osdev(2),inline-assembly(2),gdb(2),macos(2),ld(2),string(2),go(1),if-statement(1),objdump(1) |
| 2018 |
gas(69),assembly(55),x86(24),x86-64(14),gcc(13),att(6),linux(6),arm(4),macos(3),intel-syntax(3),position-independent-code(3),forth(2),ubuntu(2),x86-16(2),gdb(2),scanf(2),inline-assembly(2),gnu(2),blockchain(2),nasm(2),ld(2),osdev(2),bootloader(2),cygwin(1),debugging(1) |
| 2019 |
gas(74),assembly(58),x86(21),x86-64(15),gcc(10),att(10),c(8),linux(8),gnu(5),gdb(5),ld(4),macros(3),intel-syntax(3),inline-assembly(2),shared-libraries(2),macos(2),dwarf(2),elf(2),arm(2),addressing-mode(2),machine-code(2),bootloader(2),c-preprocessor(1),pdp-11(1),thumb(1) |
| 2020 |
gas(68),assembly(55),x86(25),gcc(17),x86-64(16),att(13),intel-syntax(7),c(4),bootloader(4),x86-16(4),osdev(3),arm(3),linux(3),c++(3),gnu(3),linker(3),arm64(2),string-literals(2),powerpc(2),riscv(2),calling-convention(2),ld(2),macos(2),clang(1),abi(1) |
Summary
From Fig. 1, it shows that the tag gas is used a lot at 2016. At that time, this tag is used for 97 questions. After 2016, this frequency of gas is a bit low. The average frequency of use is 71.
Overview
This is a Google Apps Script library for achieving the ownership-transfer of the specific folder including the files and sub-folders using Drive API.

IMPORTANT: PLEASE BE CAREFUL THIS.
At first, please read this section
I cannot take responsibility for the problems occurred by this library. So when you use this library, please use it by according to your own decision and at your own responsibility.

This GAS library transfers the ownership of files and folders. For example, when the ownership of a file is transferred to other account, the file cannot be managed by the original user. And also, when the ownership of the specific folder is transferred to other account, all files ans sub-folders in the specific folder cannot be managed by the original user. PLEASE BE CAREFUL THIS. So when you use this library, at first, please test this library using a sample file and folder. PLEASE BE CAREFUL THIS.
And also, the specification of ownership transfer might be updated by Google side in the future update. Because when I had tested this library, I could notice that the specification had been changed. Ref By this, I noticed that the transferred files had no parent folders, and also, the script was required to be modified. From this situation, when you use this script for your important files and folders, please be careful this. At first, PLEASE TEST THIS LIBRARY USING A SIMPLE FILE AND FOLDER.
Description
Recently, I had the situation that it is required to transfer the ownership of a folder including the files and sub-folders. When I manually transferred the ownership of the top folder from my account to other user’s account, although the ownership of top folder could be transferred, my account is left as the writer. And also, the ownership of the files and sub-folders in the top folder was not changed, while the user is the writer. Although I do the same situation using the method of create.permissions in Drive API, the same result was obtained. In the current stage, unfortunately, by the simple method, the complete ownership-transfer of the file including the files and sub-folders cannot be achieved. From this situation, I created the script for achieving the complete ownership-transfer of the files and folders as a Google Apps Script library.
At July 7, 2020, I have reported the transfer of owner of files got not to be able to be achieved with batch requests of Drive API. Ref But today, I could confirm that this got to be able to be achieved.
But, I’m worry about the possibility that this might not be able to be used in the future again.
At 15, June 2020, I have reported the transfer of owner of files got to be able to be achieved with batch requests of Drive API. Ref And also, yesterday (06, July 2020), I could have confirmed that this could be worked. But, now (07, July 2020), the following response is returned.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalidSharingRequest",
"message": "Bad Request. User message: \"You can't yet change the owner of this item. (We're working on it.)\""
}
],
"code": 400,
"message": "Bad Request. User message: \"You can't yet change the owner of this item. (We're working on it.)\""
}
}
I hope this situation is resolved in the near future.
Gists
This is the statistics for the tag appscript on Stackoverflow. This statistics are retrieve from Stackoverflow using Stackexchange API. About 2020, the data is retrieved from 2020-01-01 to 2020-07-01.
Recently, this tag is modified by editing the tags. So I think that it has to be said that this statistics data is obtained at 2020-07-06.
Measurement result

Fig. 1: Year vs. Total questions, Answered, Solved and Closed questions
Table 1: Tags which were used together with appscript tag for each year.
RichTextApp was updated to v1.2.0
-
v1.2.0 (July 3, 2020)
- Added the method of
AutoResizeFontForSpreadsheet. This method can automatically adjust the text length to fit in the cell width by changing the font size.
You can see the detail information here https://github.com/tanaikech/RichTextApp
Gists
This is a sample script for adjusting the text length to fit in the cell width on Google Spreadsheet using Google Apps Script. In this case, in order to fit to the cell width, the font size is changed.
Issue and workaround:
Unfortunately, in the current stage, there are no methods for automatically resize the font size for fitting in the cell width in the Spreadsheet service. So in this case, it is required to think of the workaround. But the direction for calculating the length of texts in the unit of pixel cannot be directly used. Because as a test case, when I compared the text length (pixel) calculated from the font size and the cell width (pixel), those were different. By this, here, I would like to introduce a workaround using other direction. The base flow of this workaround is as follows.
New section CORS in Web Apps was added to Taking advantage of Web Apps with Google Apps Script
In this section, I would like to introduce CORS in Web Apps. As the result, in order to prevent the error related to CORS, it was found the following important points.
-
It is required to return ContentService.createTextOutput() and ContentService.createTextOutput("done") from doGet and doPost.
-
For POST method, the data is required to be converted to the string and sent to Web Apps.
Gists
In this report, I would like to report for processing to create new file to the specific folder using Drive API. When the new file is created to the specific folder using Drive API, the property of parents with the value of folder ID is included in the request body of the method “Files: create”. About this process, I had thought that the file is directly created to the specific folder. But, I could confirm that the new file is created by the following process.
Gists
This is a sample script for the search dialog using TextFinder with Google Apps Script. If this sample script could help to indicate the possibility of TextFinder, I’m glad.
Demo
In this demonstration, the value of test is searched. When "NEXT" is clicked, the next searched value is activated. When "PREVIOUS" is clicked, the previous searched value is activated. The search can be done for all sheets in the Google Spreadsheet.
Gists
This is a current workaround for putting the multiple hyperlinks to a cell using Sheets API.
Description
Recently, at Spreadsheet service, the multiple hyperlinks got to be able to be put to a cell. Ref In this case, it can be achieved using RichTextValue. On the other hand, at Sheets API, in the current stage, there are no methods for directly putting the multiple hyperlinks to a cell. And also, such methods have not been added. I believe that such methods will be added in the future update. I think that when this is implemented, it might be added to TextFormatRun.
Gists
This is a sample script for managing the texts on Google Slides using Google Apps Script. Recently, I got the request like this. I published this here, because I thought that this might be also useful for other users.
Demo

In this demonstration, the text of {{baz}} on Google Slides are searched and replaced to other text, and also, the text style is changed.
Sample situation
In this case, it supposes that there are 3 types of shapes in the slide. Those are the text box, the rectangle shape and the explosion shape. Each shape has the texts and the title of the shape like shape1, shape2 and shape3. The sample script searches the shape using the title. You can see it at the following image.
Gists
This is a sample script for correctly exporting the charts on Google Spreadsheet as the images using Google Apps Script. In the current stage, using Google Apps Script, when the charts on Google Spreadsheet are exported as the images, it seems that the exported images are not the same with the original one on Google Spreadsheet. About this, today, I could notice that I had answered for 2 questions. Q1, Q2 And also, I had already been reported this at the issue tracker. Ref
Gists
This is a sample script for retrieving the difference between 2 arrays, which are the old values and the new values, using Google Apps Script. In my environment, I sometimes have the situation that it is required to retrieve the difference between 2 arrays. So I prepared this as a sample script. I think that this can be also used at Javascript and Node.js. If this was also useful for your situation, I’m glad.
RichTextApp was updated to v1.1.3
-
v1.1.3 (June 17, 2020)
- The variable name for the error processing was not correct. The bug was removed.
- Added a sample script for using this library.
You can see the detail information here https://github.com/tanaikech/RichTextApp
RichTextApp was updated to v1.1.2
-
v1.1.0 (June 16, 2020)
- Add new method of
RichTextToHTMLForSpreadsheet. The method of RichTextToHTMLForSpreadsheet can convert the rich texts in the cells to the HTML format.
-
v1.1.1 (June 16, 2020)
- About the method of
RichTextToHTMLForSpreadsheet, I forgot to convert hyperlinks to HTML. This was modified.
-
v1.1.2 (June 16, 2020)
- When one row and several columns are used as the range, only 1st column is returned. This bug was removed.
You can see the detail information here https://github.com/tanaikech/RichTextApp
Today, I could confirm that the transfer of owner of files got to be able to be achieved with batch requests of Drive API. When I had tested this at January 31, 2020, an error of there is no function to change the owner of this item yet (currently under development) had occurred.
But today, I could confirm that this got to be able to be achieved by the batch requests. By this, the owner of a lot of files can be transferred by reducing both the process cost and the quota cost.
Overview
These are the sample scripts of the batch requests for Drive API using Google Apps Script.
Description
When we want to manage the files and folders on Google Drive, we have 2 ways. One is the use of Drive service. Another is the use of Drive API. In the case of them, when we want to manage a lot of files and folders, unfortunately, both ways have no batch requests. Namely, for example, the metadata of a lot of files are changed, the methods in Class File and Files: update are required to be used in the loop. In this case, the process cost will be high. On the other hand, Drive API can use the batch requests. But in this case, in order to use this batch requests with Google Apps Script, it is required to create the request body of multipart/mixed by each user. Because there are no methods for automatically requests the batch requests. From this situation, here, I would like to introduce the simple sample scripts for creating, updating and deleting the files and folders on Google Drive using the batch requests with Google Apps Script.
Overview
This is the sample scripts for managing a lot of Google Calendar Events using the batch requests with Google Apps Script.
Description
When we want to manage the events of Google Calendar, we have 2 ways. One is the use of Calendar service. Another is the use of Calendar API. In the case of them, when we want to manage a lot of calendar events, unfortunately, both ways have no batch requests. Namely, for example, when a lot of events are deleted, deleteEvent() and Events: delete are required to be used in the loop. In this case, the process cost will be high. On the other hand, Calendar API can use the batch requests. But in this case, in order to use this batch requests with Google Apps Script, it is required to create the request body of multipart/mixed by each user. Because there are no methods for automatically requests the batch requests. From this situation, here, I would like to introduce the simple sample scripts for creating, updating and deleting the events of Google Calendar using the batch requests with Google Apps Script.
BatchRequest was updated to v1.1.2.
-
v1.1.1 (June 12, 2020)
- Error handling for the input object was added.
-
v1.1.2 (June 12, 2020)
- Removed a bug that when the returned value is empty, an error occurred.
You can check this at https://github.com/tanaikech/BatchRequest.
Gists
This is a sample script for highlighting the row and column of the selected cell using Google Apps Script. For this, the OnSelectionChange event trigger is used.
Demo

Sample script
Please copy and paste the following script to the script editor of Spreadsheet. And, please select a cell. By this, the script is run by the OnSelectionChange event trigger.
function onSelectionChange(e) {
const range = e.range;
const sheet = range.getSheet();
const maxRows = sheet.getMaxRows();
const maxColumns = sheet.getMaxColumns();
sheet.getRange(1, 1, maxRows, maxColumns).setBackground(null);
sheet.getRange(1, range.getColumn(), maxRows, 1).setBackground("yellow");
sheet.getRange(range.getRow(), 1, 1, maxColumns).setBackground("yellow");
}
References
Gists
Description
This is a sample script for disabling the buttons put on Google Spreadsheet using Google Apps Script.
When a script is run by clicking a button on Google Spreadsheet, there is the case that you don’t want to make users run the script in duplicate. This sample script achieves this situation.
Demo

In this demonstration, 2 types of buttons are used. Those are the drawing and image, respectively. When the button is clicked, the worker of 10 seconds is run. You can see that after the button was clicked, even when the button is clicked again, the worker script is not run.
BatchRequest was updated to v1.1.0.
-
v1.1.0 (June 10, 2020)
- New method of
EDo() was added. This method is the enhanced Do() method. When this method is used, the result values from the batch requests are parsed. And also, the number of requests more than 100 can be used. In this case, the split of the number of requests is processed for the limitation of 100.
You can check this at https://github.com/tanaikech/BatchRequest.
Overview
This is a proposal of the enhanced custom function for Google Spreadsheet using Web Apps as the wrapper.
Demo

Description
When the custom function is used, in the current specification, the most methods except several methods (for example, one of them is UrlFetchApp.) that the authorization is required cannot be used. So for example, when the filenames in the folder are retrieved from the folder name, unfortunately, this cannot be directly achieved. When this is tried, an error like Exception: You do not have permission to call DriveApp.getFoldersByName. Required permissions: (https://www.googleapis.com/auth/drive.readonly || https://www.googleapis.com/auth/drive) occurs. From this situation, it is considered that when the authorization has already been done, the method that the authorization is required might be able to be used. In this report. I would like to introduce the method for using such methods by using Web Apps as the wrapper.
Gists
When the method of “Files: list” in Drive API v3, the official document of includeItemsFromAllDrives and supportsAllDrives says as follows.
Deprecated - Whether both My Drive and shared drive items should be included in results. This parameter will only be effective until June 1, 2020. Afterwards shared drive items are included in the results. (Default: false)
Deprecated - Whether the requesting application supports both My Drives and shared drives. This parameter will only be effective until June 1, 2020. Afterwards all applications are assumed to support shared drives. (Default: false)
RunAll was updated to v1.1.2.
-
v1.1.2 (May 31, 2020)
- When the access token and project ID are not included in the object,
getOAuthToken() and getScriptId(). By this, an error is removed.
You can see the detail information here https://github.com/tanaikech/RunAll
FilesApp was updated to v1.1.2.
-
v1.1.2 (May 29, 2020)
- A bug that all files were not retrieved from the shared drive was removed.
GitHub of FilesApp
Gists
This is a sample script for creating a shortcut on Google Drive using Google Apps Script.
Sample script
Before you run the script, please enable Drive API at Advanced Google services.
function createShortcut(targetId, name, folderId) {
const resource = {
shortcutDetails: { targetId: targetId },
title: name,
mimeType: "application/vnd.google-apps.shortcut",
};
if (folderId) resource.parents = [{ id: folderId }];
const shortcut = Drive.Files.insert(resource);
return shortcut.id;
}
// Please run this function.
function main() {
const targetId = "###"; // Please set the ID of target file or folder.
const shortcutName = "###"; // Please set the shortcut name.
const folderId = "###"; // Please set the folder ID for putting the created shortcut.
const id = createShortcut(targetId, shortcutName, folderId);
console.log(id);
}
References
Gists
Abstract
This is a report for detecting quickly checked checkboxes on Google Spreadsheet using Google Apps Script. It supposes that when the checkbox is checked, a function of Google Apps Script is run by the event trigger. In this case, when the multiple checkboxes on Google Spreadsheet are checked quickly, the script cannot be run for all checked checkboxes, because of the response speed of the event trigger. It is considered that to understand the response of event trigger is useful for creating the application for Spreadsheet. In this report, the detection of quickly checked checkboxes on Google Spreadsheet using Google Apps Script has been investigated. From this result, it led to understanding the response of event trigger.
Overview
This is Google Apps Script library for copying folder on Google Drive.

Description
I have sometimes the situation that it is required to back up the folder on Google Drive to Google Drive. But unfortunately, the method of makeCopy() of Class File and the method of Files: copy of Drive API cannot be used for directly copying the folder on Google Drive. So I created this as a library. This library can copy the folder on Google Drive. All files in the folder can be copied to Google Drive with keeping the folder structure. When there are the files with newer modified time in the source folder than those in the destination folder, the files in the destination folder are overwritten by the newer files in the source folder. Also, in this library, the folders in the shared Drive and the publicly shared folders can be used as the source and destination folder.
Gists
Abstract
I have already reported about “Change Tab Detection on Google Spreadsheet using onSelectionChange Event Trigger with Google Apps Script”. Ref It is considered that when the situation which uses the event trigger of onSelectionChange is thought, the response speed is important. So, here, I investigated the characteristics of response for the event trigger of onSelectionChange.
Demo

Experiment
Sample script
In order to investigate the response speed, I used the following sample script. The work of sample script can be seen at above demonstration movie. In this report, the script is important for discussing the result. So I pot this at this section instead of the appendix.
Gists
onSelectionChange has been released at April 22, 2020. But this couldn’t be used at the released day. But now, I could confirm that this got to be able to be used. So in order to test this event trigger, I prepared a simple sample script. This is a sample script for detecting the change tab on Google Spreadsheet using onSelectionChange Event Trigger with Google Apps Script.
Demo

Usage
- Please copy and paste the following script to the container-bound script of Google Spreadsheet, and save the script.
- Please reopen the Google Spreadsheet.
- By this,
onOpen is run and the current sheet is put to PropertiesService.
- Unfortunately, in the current stage, it seems that the event object of
onSelectionChange has no information about the change of tab. So in order to detect the change of tab, I used the PropertiesService.
- Then, please select a cell and cells on sheet.
- By this,
onSelectionChange is run by the onSelectionChange event trigger, and put the A1Notation to the cell.
- When the active tab is moved, the sample script detects this, and the information of the changed tab is put to the cell.
Sample script
function onOpen(e) {
const prop = PropertiesService.getScriptProperties();
const sheetName = e.range.getSheet().getSheetName();
prop.setProperty("previousSheet", sheetName);
}
function onSelectionChange(e) {
const prop = PropertiesService.getScriptProperties();
const previousSheet = prop.getProperty("previousSheet");
const range = e.range;
const a1Notation = range.getA1Notation();
const sheetName = range.getSheet().getSheetName();
if (sheetName != previousSheet) {
range.setValue(`Changed tab from ${previousSheet} to ${sheetName}. ${a1Notation}`);
// When the tab is changed, this script is run.
} else {
range.setValue(a1Notation);
}
prop.setProperty("previousSheet", sheetName);
}
References
Gists
Recently, it seems that the specification of Google Spreadsheet was updated. Before this, when a cell has only one hyperlink. In this case, the hyperlink was given to a cell using =HYPERLINK("http://www.google.com/", "Google") as following figure.

But by the recent update, a cell got to be able to have multiple hyperlinks as following figure. In this case, the hyperlinks are set by the RichTextValue object.

In this report, I would like to introduce the method for setting and retrieving the multiple URLs for a cell.
FilesApp was updated to v1.1.0.
- Shared drive got to be able to be used. From the version 1.1.0, the following modification was added.
- V8 is used.
- As the default setting, the file list is retrieved from both your Google Drive and the shared drive.
- By this, for example, when the folder ID in the shared Drive is used to
### of const res = FilesApp.createTree("###"), the folder tree of the shared Drive is retrieved, if you have the shared Drive.
And also, FilesApp was updated to v1.1.1.
Gists
These are the sample scripts for hiding and deleting rows and columns on Google Spreadsheet using Google Apps Script. I sometimes see the questions for hiding and deleting rows and columns on Spreadsheet at Stackoverflow. So here, I would like to introduce the sample scripts for this.
In this case, when the process costs of the scripts created by using Spreadsheet service and Sheets API are compared, the cost of script created by Sheets API is much lower than that of script created by Spreadsheet service. So when the rows and columns of your Spreadsheet is large and you can use Sheets API, I recommend to use Sheets API.
Gists
Overview
When // in template literal is used in a HTML file in script editor, it is used as a comment start.
For example, when above script is used in a HTML file at the script editor, ;" of const sample =`//`; is used as the comment.
Description
I would like to explain about this bug using the following sample flow.
Flow
-
Create new Spreadsheet and open the script editor. In this explanation, please use the container-bound script.
Gists
This is a sample script for retrieving the direct links of all sheets from the URL like https://docs.google.com/spreadsheets/d/e/2PACX-###/pubhtml of the web published Google Spreadsheet. This sample script can be used for the following situation.
- The Spreadsheet is published to Web and the URL like
https://docs.google.com/spreadsheets/d/e/2PACX-###/pubhtml is known
- You are not the owner of Google Spreadsheet.
- You don’t know the Spreadsheet ID and Sheet IDs.
Under above situation, unfortunately, the direct links of each sheet cannot be directly retrieved. I think that this is the specification of Google side. So in this post, I would like to introduce a workaround for retrieving the direct links of each sheet under above situation.
Gists
Description
When V8 is enabled, Array.apply has the limitation for the number of elements. When it is over the limitation, an error like RangeError: Maximum call stack size exceeded occurs, while the issue didn’t occur when V8 is disabled. In this case, this issue occurs at both Google Apps Script and Javascript. So please be careful this.
Sample situation
For example, when Array.prototype.push.apply is used for combining the arrays because the process cost of Array.prototype.push.apply is lowest of 3 patterns of Array.prototype.push.apply, Spread syntax and concat, please be careful above issue. Ref
FetchApp was updated to v1.0.1.
-
v1.0.1 (April 13, 2020)
- When V8 runtime is enabled, it was found that an error occurred. So this bug was removed.
You can check this at https://github.com/tanaikech/FetchApp.
Gists
This sample script is for expanding a1Notations using Google Apps Script. This was updated from this sample script.
Sample script
function expandA1Notations_(a1Notations, maxRow, maxColumn) {
maxRow = maxRow || "1000";
maxColumn = maxColumn || "Z";
// Ref: https://stackoverflow.com/a/21231012/7108653
const columnToLetter = column => {
let temp,
letter = "";
while (column > 0) {
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
};
const letterToColumn = letter => {
let column = 0,
length = letter.length;
for (let i = 0; i < length; i++) {
column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
}
return column;
};
const reg1 = new RegExp("^([A-Z]+)([0-9]+)$");
const reg2 = new RegExp("^([A-Z]+)$");
const reg3 = new RegExp("^([0-9]+)$");
return a1Notations.map(e => {
const a1 = e.split("!");
const r = a1.length > 1 ? a1[1] : a1[0];
const [r1, r2] = r.split(":");
if (!r2) return [r1];
let rr;
if (reg1.test(r1) && reg1.test(r2)) {
rr = [r1.toUpperCase().match(reg1), r2.toUpperCase().match(reg1)];
} else if (reg2.test(r1) && reg2.test(r2)) {
rr = [
[null, r1, 1],
[null, r2, maxRow]
];
} else if (reg1.test(r1) && reg2.test(r2)) {
rr = [r1.toUpperCase().match(reg1), [null, r2, maxRow]];
} else if (reg2.test(r1) && reg1.test(r2)) {
rr = [[null, r1, maxRow], r2.toUpperCase().match(reg1)];
} else if (reg3.test(r1) && reg3.test(r2)) {
rr =
Number(r1) > Number(r2)
? [
[null, "A", r2],
[null, maxColumn, r1]
]
: [
[null, "A", r1],
[null, maxColumn, r2]
];
} else if (reg1.test(r1) && reg3.test(r2)) {
rr = [r1.toUpperCase().match(reg1), [null, maxColumn, r2]];
} else if (reg3.test(r1) && reg1.test(r2)) {
let temp = r2.toUpperCase().match(reg1);
rr =
Number(temp[2]) > Number(r1)
? [
[null, temp[1], r1],
[null, maxColumn, temp[2]]
]
: [temp, [null, maxColumn, r1]];
} else {
throw new Error(`Wrong a1Notation: ${r}`);
}
const obj = {
startRowIndex: Number(rr[0][2]),
endRowIndex: rr.length == 1 ? Number(rr[0][2]) + 1 : Number(rr[1][2]) + 1,
startColumnIndex: letterToColumn(rr[0][1]),
endColumnIndex:
rr.length == 1
? letterToColumn(rr[0][1]) + 1
: letterToColumn(rr[1][1]) + 1
};
let temp = [];
for (let i = obj.startRowIndex; i < obj.endRowIndex; i++) {
for (let j = obj.startColumnIndex; j < obj.endColumnIndex; j++) {
temp.push(columnToLetter(j) + i);
}
}
return temp;
});
}
// When you use this script, please run main().
function main() {
const a1Notations = ["A1:E3", "B10:W13", "EZ5:FA8", "AAA1:AAB3"];
const res = expandA1Notations_(a1Notations);
console.log(res);
}
Result
[
["A1","B1","C1","D1","E1","A2","B2","C2","D2","E2","A3","B3","C3","D3","E3"],
["B10","C10","D10","E10","F10","G10","H10","I10","J10","K10","L10","M10","N10","O10","P10","Q10","R10","S10","T10","U10","V10","W10","B11","C11","D11","E11","F11","G11","H11","I11","J11","K11","L11","M11","N11","O11","P11","Q11","R11","S11","T11","U11","V11","W11","B12","C12","D12","E12","F12","G12","H12","I12","J12","K12","L12","M12","N12","O12","P12","Q12","R12","S12","T12","U12","V12","W12","B13","C13","D13","E13","F13","G13","H13","I13","J13","K13","L13","M13","N13","O13","P13","Q13","R13","S13","T13","U13","V13","W13"],
["EZ5","FA5","EZ6","FA6","EZ7","FA7","EZ8","FA8"],
["AAA1","AAB1","AAA2","AAB2","AAA3","AAB3"]
]
Retrieve duplicated cells
When this script is used, the duplicated cells can be retrieved as follows.
The drawing objects on Google Spreadsheet got to be able to be managed by the update at April 2, 2020. Ref
By this update, we can assign the function to the drawing objects and remove the drawing objects. The following sample is for removing the drawing objects on the active sheet. Ref
SpreadsheetApp.getActiveSheet()
.getDrawings()
.forEach(e => e.remove());
Gists
This is a sample script for retrieving the overwrapped cells between 2 ranges on Google Spreadsheet using Google Apps Script. Please use this with enabling V8.
const getOverwrappedRanges_ = (rangeList1, rangeList2) => {
if (
rangeList1.toString() != "RangeList" ||
rangeList2.toString() != "RangeList"
) {
throw new Error("Input RangeList object.");
}
// Ref: https://stackoverflow.com/a/21231012/7108653
const columnToLetter = column => {
let temp,
letter = "";
while (column > 0) {
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
};
// Expand range1.
const ar = rangeList1.getRanges().reduce((ar, r) => {
const startRow1 = r.getRow();
const endRow1 = startRow1 + r.getNumRows();
const startColumn1 = r.getColumn();
const endColumn1 = startColumn1 + r.getNumColumns();
for (let j = startRow1; j < endRow1; j++) {
for (let k = startColumn1; k < endColumn1; k++) {
ar.push(columnToLetter(k) + j);
}
}
return ar;
}, []);
// Expand range2.
const map = rangeList2.getRanges().reduce((m, r) => {
const startRow2 = r.getRow();
const endRow2 = startRow2 + r.getNumRows();
const startColumn2 = r.getColumn();
const endColumn2 = startColumn2 + r.getNumColumns();
for (let j = startRow2; j < endRow2; j++) {
for (let k = startColumn2; k < endColumn2; k++) {
m.set(columnToLetter(k) + j, null);
}
}
return m;
}, new Map());
return ar.filter(e => map.has(e));
};
const main = () => {
const range1 = ["B3:C7", "D6:E9"]; // Please input range1 as a1Notation.
const range2 = ["A2:B3", "C7:D10"]; // Please input range2 as a1Notation.
const sheet = SpreadsheetApp.getActiveSheet();
const res = getOverwrappedRanges_(
sheet.getRangeList(range1),
sheet.getRangeList(range2)
);
console.log(res); // <--- ["B3","C7","D7","D8","D9"]
};
-
In this sample script, from the ranges of "B3:C7", "D6:E9" and "A2:B3", "C7:D10", the overwrapped cells are returned. In this case, ["B3","C7","D7","D8","D9"] is returned.
Gists
Kanshi Tanaike
Introduction
V8 engine got to be able to be used at Google Apps Script. By this, I have reported about the process costs with and without using V8. Ref It is considered that knowing the process costs for various methods will be useful for creating the applications with Google Apps Script. Here, I would like to introduce the process costs of each situations under V8. The situations which measured the cost are as follows.
Gists
This is a sample script for retrieving the files and folders which have no parents in own Google Drive.
When you use this script, please enable Drive API at Advanced Google services.
Sample script
const myFunction = () => {
const token = ScriptApp.getOAuthToken();
const fields = decodeURIComponent(
"nextPageToken,files(name,id,mimeType,parents)"
);
const q = decodeURIComponent("'me' in owners and trashed = false");
let files = [];
let pageToken = "";
do {
const res = UrlFetchApp.fetch(
`https://www.googleapis.com/drive/v3/files?pageSize=1000&fields=${fields}&q=${q}&pageToken=${pageToken}`,
{ headers: { authorization: `Bearer ${token}` } }
);
const obj = JSON.parse(res);
Array.prototype.push.apply(files, obj.files);
pageToken = obj.nextPageToken;
} while (pageToken);
const result = files.filter(({ parents }) => !parents);
console.log(result);
};
When you run the script, the files and folders which have no parents in own Google Drive are retrieved.
Web Application for searching Google Apps Script Library from Database was completed. So I published it as v1.0.0. Please check Google Apps Script Library Database.
-
v1.7.4 (March 11, 2020)
-
Recently, I noticed that new Google Apps Script project of the standalone script type cannot be created by the create method of Drive API. From now, in order to create the standalone Google Apps Script project, only Google Apps Script API is required to be used. Ref By this, I updated ggsrun. So the command for creating new GAS project is not changed.
$ ggsrun u -p ###folderId### -f sample.gs -pn sampleGASProjectName
You can check ggsrun at https://github.com/tanaikech/ggsrun.
Gists
Today, I noticed that new Google Apps Script project of the standalone script type cannot be created by the method of Files: create in Drive API. From now, in order to manage the Google Apps Script project, only Google Apps Script API is required to be used. By this, the following issues are brought.
- When the new standalone GAS project is created in the specific folder by uploading the local script, the following flow is required to be run.
- Create new standalone GAS project by Apps Script API.
- Put the local script to the created GAS project by updating the project with Apps Script API.
- Move the GAS project from the root folder to the specific folder using Drive API.
From now, 3 API calls are required to be used like above. By the way, this had been able to be achieved by one API call of the method of files.create in Drive API before.
Overview
This is a GAS library for retrieving and creating the albums and media items using Google Photo API using Google Apps Script (GAS).
Description
In the current stage, Google Photo API is not included in Advanced Google services. But in order to use Google Photo API with Google Apps Script, I created this as a GAS library. So in the current stage, in order to use this library, the following flow is required.
Overview

This is a GAS library for copying the rich text with the text styles from Google Document to Google Spreadsheet or from Google Spreadsheet to Google Document using Google Apps Script (GAS).
Description
Google Spreadsheet can use the rich text as the cell value. But I thought that it is difficult for me to directly edit the rich text in a cell. So I wanted to copy the rich text, that I edited at the Google Document, to the cell of Google Spreadsheet. But, unfortunately, when the rich text in Google Document is manually copied to a cell in Google Spreadsheet, the text style is removed. By this, only text values are copied. It seemed that this was the current specification. So in order to achieve above, I created this as a library.
Gists
This is a simple sample script for uploading a file using the file input tag of HTML. As the important point, the file is sent as the byte array for using Google Apps Script. By this, at Google Apps Script side, the byte array can be converted to a blob using a simple script.
HTML & Javascript
<input id="file" type="file" onchange="saveFile(this)" />
<script>
function saveFile(f) {
const file = f.files[0];
const fr = new FileReader();
fr.onload = function(e) {
const obj = {
filename: file.name,
mimeType: file.type,
bytes: [...new Int8Array(e.target.result)]
};
google.script.run.withSuccessHandler(e => console.log(e)).saveFile(obj);
};
fr.readAsArrayBuffer(file);
}
</script>
Google Apps Script
function saveFile(e) {
var blob = Utilities.newBlob(e.bytes, e.mimeType, e.filename);
DriveApp.createFile(blob);
return "Done.";
}
Overview
This is for the Google Apps Script Library Database.
Description
Since Google Apps Script was released on August 19th, 2009, it is used by a lot of users. Ref1, Ref2 By this, now there are a lot of useful libraries of Google Apps Script (GAS) in all over the world. But when I want to search a GAS library, I always use Google search engine. Unfortunately, in the current stage, the libraries cannot be directly searched by a database. On January 11th, 2020, a proposal for the database of Google Apps Script Library has been proposed by Andrew Roberts. Ref3 When I have discussing about this with him, I thought that I tried to think of a sample database. So I prepared this.
ManifestsApp was updated to v1.0.4.
Gists
This is a sample script for rearranging the columns on Google Spreadsheet using Google Apps Script.
Sample script
In this sample script, the columns are rearranged with an array including the rearranged column indexes.
function rearrangeColumns(sheet, ar) {
var obj = ar.reduce(function(ar, e, i) {
return ar.concat({ from: e + 1, to: i + 1 });
}, []);
obj.sort(function(a, b) {
return a.to < b.to ? -1 : 1;
});
obj.forEach(function(o) {
if (o.from != o.to) sheet.moveColumns(sheet.getRange(1, o.from), o.to);
obj.forEach(function(e, i) {
if (e.from < o.from) obj[i].from += 1;
});
});
}
// Please run this function.
function main() {
var sheet = SpreadsheetApp.getActiveSheet();
var rearrangedColumnIndexes = [4, 3, 1, 0, 2];
rearrangeColumns(sheet, rearrangedColumnIndexes);
}
Gists
- February 9, 2020
- Published.
- March 15, 2020
- Results of "for of" and "for of with iterator" were added.
Kanshi Tanaike
Introduction
Please be careful! This result can be only used for Google Apps Script.
There are a limit executing time for Google Apps Script (GAS). That is 6 minutes.1 So users always have to pay attention to reducing the process cost of the scripts. Especially, it is very important to know the process cost for the array processing, because the array processing is often used for spreadsheet and Google APIs. I have already reported “Benchmark: Loop for Array Processing using Google Apps Script”.2 At February 7, 2020, the V8 runtime got to be able to be used in my account. By this, it is considered that it is possibly changed the result of benchmark without V8 2. So I measured about this. In this report, the process cost of “loop” for the array processing using GAS has been investigated with V8 runtime.
Gists
In my environment, at February 7, 2020, when I opened the script editor of Google Apps Script, the following notification could be seen.

By this, I could notice that finally, the V8 Runtime has already been added to Google Apps Script. I think that this will be also the great news for a lot of users including me.
The detail of V8 Runtime can be seen at https://developers.google.com/apps-script/guides/v8-runtime.
Overview
DateFinder is a GAS library for searching the date objects from the cell range on the sheet in the Spreadsheet and retrieving the searched range as the RangeList object using Google Apps Script (GAS).
Description
There is the Class TextFinder for searching the text from cells of the Spreadsheet using the Google Apps Script. But in this case, the date object in the cell is used as the string. Namely, the values for searching are used as the same with the values retrieved by getDisplayValues(). So for example, when there are the date objects in the cells with the various formats, the date cannot be searched by the Class TextFinder. So I created this library. When this library is used, the date objects in the cells can be retrieved by the date object and/or the range between 2 dates.
Overview
EncodeApp is a GAS library for retrieving the encoding set (charset) and doing URL encode with the specific encoding set using Google Apps Script (GAS).
You can see the detail information here https://github.com/tanaikech/EncodeApp
Gists
This is a sample script for achieving the URL encode with Shift-JIS using Google Apps Script.
Unfortunately, there are no methods for directly achieving above in the methods of Google Apps Script. So it is required to prepare it as the script. In order to use Shift-JIS of the character set at Google Apps Script, it is required to use it as the binary data. Because, when the value of Shift-JIS is retrieved as the string by Google Apps Script, the character set is automatically changed to UTF-8. Please be careful this.
Gists
Overview
This is a sample script for deleting the last empty page which has only one paragraph including no values which is "" in the Google Document using Google Apps Script.
Description
As a sample situation, it supposes that there is the following Google Document.

In this sample, the last page of Google Document has only one paragraph including no values which is "". When I try to delete only last page without modifying the previous page, I noticed that this cannot be achieved with only Google Document service. For example, it try to delete the paragraph of the last page using the following scripts,
Gists
Published: January 10, 2020
Kanshi Tanaike
Introduction
At Stackoverflow, a lot of people post the questions and answers to the questions every day. There are various tags in Stackoverflow. A lot of discussions are performed at each tag. Their discussions bring the important information and are much useful for a lot of people. As one of tags, there is “google-apps-script”. I sometimes discuss at the questions with that tag. When we see the discussions, we can notice that the discussions are changed and progressed by the time, because “Google Apps Script” which is the origin of the tag is updated. This report thinks this change as the trend of tag of “google-apps-script”. This trend includes the number of questions, questioners, answerers and tags adding to the tag of “google-apps-script”. The trend of tag of “google-apps-script” is deeply related to the progression of Google Apps Script and the various applications for Google Apps Script.
Gists
This is a sample script for retrieving the event ID from the event URL of Google Calendar using Google Apps Script.
The event URL is like https://www.google.com/calendar/event?###. At the event URL, ### of https://www.google.com/calendar/event?### is not the event ID. So it is required to convert it.
Sample script
var eventUrl = "https://www.google.com/calendar/event?###";
var eventId = Utilities.newBlob(Utilities.base64Decode(eventUrl.split("=")[1]))
.getDataAsString()
.split(" ")[0];
Logger.log(eventId);
Gists
Overview
This is a simple method running Google Apps Script by the event notification from Google Calendar.
Description
There are several event triggers in Google Apps Script. Ref1, Ref2 There is an event trigger for Google Calendar. The official document says An installable calendar event trigger runs when a user's calendar events are updated—created, edited, or deleted.. Ref3 If I want to use the trigger when the event in the calendar is starts and finished, it is required to use Calendar API by preparing the URL for receiving from Google. Ref4, Ref5 Also, there is the method that the start time are retrieved from all event lists and run the script for each start time. But in this case, it is required to check new events and manage the time-driven triggers for running the script. I thought that those are the higher hurdle for me. So I thought a workaround.
Gists
This is a sample script for dynamically updating the custom menu of Google Spreadsheet using Google Apps Script.
Demo

In this demonstration, when the Spreadsheet is opened, 5 functions added to the custom menu. You can see that when a column is added and deleted, the custom menu is updated.
Issue and workaround for this goal
Unfortunately, in the current stage, when a function is added to the custom menu with addItem method, the argument cannot been able to be used. And when one of functions in the custom menu is run, the information about the function name which was run cannot be retrieved. By this, the goal cannot be directly achieved. So it is required to use the workaround.
GmailToList was updated to v1.0.1.
You can see the detail information here https://github.com/tanaikech/GmailToList
Overview
This is a library for exporting all messages of Gmail as a list using Google Apps Script (GAS).
Description
Recently, I have had a situation it had been required to backup all messages in own Gmail. In order to achieve this, I created a simple script. After I created it, I thought that when such situation might occur for other users and the script is published as a library, they might be useful. So I created this library. But I created this for my situation. So if this cannot be used for your environment and an error occurs, I apologize.
Gists
These are 3 sample scripts for moving a file to the specific folder in Google Drive using Google Apps Script.
Sample script 1
In this script, only Drive Service is used.
var sourceFileId = "###";
var destinationFolderId = "###";
var file = DriveApp.getFileById(sourceFileId);
DriveApp.getFolderById(destinationFolderId).addFile(file);
file
.getParents()
.next()
.removeFile(file);
Sample script 2
In this script, only Drive API at Advanced Google services. (In this case, it’s Drive API v2.)
var sourceFileId = "###";
var destinationFolderId = "###";
Drive.Files.update({ parents: [{ id: destinationFolderId }] }, sourceFileId);
Sample script 3
In this script, only Drive API v3 is used.
Gists
In this sample script, all pages in the Figma file are retrieved and the retrieved pages are put to new Google Slides as the image.
Usage
1. Retrieve access token
You can see the method for retrieving the access token at here. Although there is also OAuth2 for retrieving the access token, in your situation, I thought that the method for directly generating the access token on the site might be suitable. So in this answer, the generated access token on the site is used. Please retrieve the access token as follows.
Gists
Overview
This is a sample script for retrieving values from a sheet filtered by Slicer in Spreadsheet using Google Apps Script.
Description
By the update of Google side at November 6, 2019, Class Slicer was added. And also, for Sheets API, AddSlicerRequest and UpdateSlicerSpecRequest were added. By this, Slicer of Spreadsheet got to be able to be managed with Google Apps Script and other languages.
Here, I would like to introduce the method for retrieving values from a sheet filtered by Slicer in Spreadsheet using Google Apps Script.
Gists
Description
I have already reported about “Automatic Recalculation of Custom Function on Spreadsheet Part 1” at here. Here, I would like to introduce other workaround for forcibly recalculating the custom functions and built-in functions using Class TextFinder. Class TextFinder has added at April 5, 2019. By this, this workaround can be proposed.
Sample scripts
Pattern 1
If you want to refresh all functions of all sheets in a Spreadsheet, you can use the following script. In this script, when the script is run, all built-in functions and custom functions in the Spreadsheet are refreshed.
GetEditType was updated to v1.0.1.
You can see the detail information here https://github.com/tanaikech/GetEditType
ZipFolder was updated to v1.0.1.
You can see the detail information here https://github.com/tanaikech/ZipFolder
Overview
This is a sample script for uploading multiple files with large size (> 50 MB) at the sidebar, dialog of Google Docs and Web Apps using the resumable upload of the asynchronous process with Javascript and Google Apps Script (GAS).
Demo

This is a demonstration of this script. As a demonstration, it uploads 5 files with the size of 100 MB to own Google Drive. When the files were selected and the upload button is clicked, those are uploaded by the resumable upload with the asynchronous process. It is found that the files can be completely uploaded with the asynchronous process. In this demo, as a test case, the chunk size of 20 MB was used.
Overview
This is a sample script for downloading files from Google Drive by the one time download method.
Description
When you download a file from Google Drive, in generally, the login and the access token are required. If you want to download the file without the authorization for the simple situation, the file is required to be publicly shared. But the file might not be able to be shared publicly, because of various reasons.
RunAll was updated to v1.1.1.
You can see the detail information here https://github.com/tanaikech/RunAll
Gists
This is a sample script for modifying the revisions of a file on Google Drive using Google Apps Script. This script can be used for not only Google Docs files, but also the files except for Google Docs.
Issue and workaround:
Unfortunately, in the current stage, at Google Docs files, the revision of Google Docs cannot be directly changed by APIs with a script. So as one of several workarounds, I would like to propose to overwrite the Google Docs file using the exported data. On the other hand, at the files except for Google Docs, the data can be directly retrieved with the revision ID. This can be used for overwriting the file. The flow of this script is as follows.
Gists
August 28, 2019
Published.
Kanshi Tanaike
Introduction
Please be careful! This result can be only used for Google Apps Script.
There are a limit executing time for Google Apps Script (GAS). That is 6 minutes for Consumer and Google Apps free edition, and 30 minutes for G Suite and Early Access. 1 So many users always have to pay attention to reducing the process cost of scripts. So it is very important to know the process cost of various situations. I have already reported the costs for various processes as the reports. 2 In this report, the process cost for importing CSV data to Spreadsheet using GAS has been investigated.
Gists
In this report, I would like to introduce the method for running functions by directly specifying the function names with Web Apps for Google Apps Script.
Description
It has already been known that the directly specified functions in the project can be run from the outside by enabling “API executable” and using the method of scripts.run in Google Apps Script API. In this case, the installation for using Apps Script API is a bit complicate. I think that this is making users difficult to use Apps Script API, although the important settings are including in the installation when the importance of the security is considered. As one of workarounds for making easy to run the directly specified functions in the project, I would like to introduce the method using Web Apps. When Web Apps is accessed, the functions of doGet() and doPost() are used. These are the reserved function name. But, when this method is used, the functions in the project can be run by directly selecting from the outside.
RunAll was updated to v1.1.0.
You can see the detail information here https://github.com/tanaikech/RunAll
Gists
This is a sample script for “Examples of How to Derive a Signing Key for Signature Version 4” using Google Apps Script.
In order to use AWS SDKs, there are the sample scripts for the languages of Java, .NET (C#), Python, Ruby, JavaScript (Node.js). But the sample script of Google Apps Script is not prepared. I saw the question related to this at Stackoverflow. So I would like to also introduce the sample script here.
Gists
This is a sample script for parsing HTML using Google Apps Script. When HTML data is converted to Google Document, the HTML data can be parsed and be converted to Google Document. In this case, the paragraphs, lists and tables are included. From this situation, I thought that this situation can be used for parsing HTML using Google Apps Script. So I could came up with this method.
In the Sheet API, the HTML data can be put to the Spreadsheet with the PasteDataRequest. But unfortunately, in this case, I couldn’t distinguish between the body and tables.
Gists
This is a sample script for retrieving values from filtered Sheet in Spreadsheet using Google Apps Script. When the values are retrieved the filtered sheet by the basic filter, if setValues() and setDisplayValues() are used, all values without the filter are retrieved. In this script, I would like to introduce the method for retrieving the values from the filtered sheet using Google Apps Script.
In order to retrieve the values from the filtered sheet, one method has already been proposed. That method retrieved the values from the filtered sheet by retrieving columnMetadata and rowMetadata of the method of spreadsheet.get of Sheets API. In this case, the rows and columns hidden by the filter can be retrieved.
Overview
This is a GAS library for unzipping a Zip file protected by a password using Google Apps Script.
Description
Recently, I had a situation that it is required to unzip a Zip file protected with the password. But unfortunately, in the current stage, the method of Utilities.unzip() cannot unzip such protected files. So when I had been looking for the other workarounds, I found zlib.js. Especially, it’s unzip.min.js. This is created for Javascript. So when I used this using Google Apps Script, it was found that it didn’t work for Google Apps Script. So I prepared a wrapper script for running it with Google Apps Script. And when I created the wrapper script, I thought that under the current stage, if the protected Zip file can be unzipped, this will be useful for other users. So I created this as a GAS library.
Gists
This is the method for protecting cells of Spreadsheet that users copied from your Google Drive to user’s Google Drive using Google Apps Script.
Situation:
This method supposes the following situation.
- You want to make users copy a Spreadsheet on your Google Drive to user’s Google Drive. - Your Spreadsheet has several protected ranges. - Your Spreadsheet is shared with the user. - User doesn’t have own folder shared with you.
- You want to protect the ranges of Spreadsheet for the user. Namely, you want to remove the user from the editor of protected ranges.
- You want to achieve this using Google Apps Script.
Issue:
In above situation, I think that the following points are the bottleneck.
Gists
Introduction
At April 8, 2019, the specification of Google Apps Script Project was changed. You can see this at Google Cloud Platform Projects. The official document says as follows.
Warning: Starting on or after April 8, 2019, the Google Cloud Platform Console won’t be able to access the default GCP projects created for new Apps Script projects. Older, existing scripts may have default GCP projects that are still accessible, however. If you have a new script and require access to its GCP project from the Google Cloud Platform Console, you must use a standard GCP project.
Overview
GetEditType is a GAS library for retrieving the edit types of the OnEdit event trigger of Spreadsheet using Google Apps Script (GAS).
Description
In the case that the OnEdit event trigger (simple and installable triggers) is used at Spreadsheet, when users manually edited the cell of Spreadsheet, the trigger is fired. At this time, there is the case that I want to know the edit type. For example, I would like to know about the following edit types.
Gists
This is a sample script for fixing a value putting by a custom function of Spreadsheet using Google Apps Script. When a custom function is used, the value retrieved by the custom function of Spreadsheet is automatically updated by recalculating. So in the case that the value retrieved by the custom function is changed by the time, the value is also changed by automatically updating. In this sample script, I would like to introduce a method for fixing such values.
Gists
This is a sample script for retrieving the values with and without duplicating from JSON object using Google Apps Script. Also this can be used by Javascript.
Sample script
var obj = [
{ key1: "value1a", key2: "value1b" },
{ key1: "value2a", key2: "value2b" },
{ key1: "value5a", key2: "value5b" },
{ key1: "value3a", key2: "value3b" },
{ key1: "value1a", key2: "value1b" },
{ key1: "value4a", key2: "value4b" },
{ key1: "value5a", key2: "value5b" },
{ key1: "value3a", key2: "value3b" }
];
var res = obj.reduce(
function(obj, e) {
if (
obj.withoutDuplicating.some(function(f) {
return f.key1 === e.key1 && f.key2 === e.key2;
})
) {
obj.withDuplicating.push(e);
} else {
obj.withoutDuplicating.push(e);
}
return obj;
},
{ withoutDuplicating: [], withDuplicating: [] }
);
Logger.log(res);
Result
{
"withoutDuplicating": [
{
"key1": "value1a",
"key2": "value1b"
},
{
"key1": "value2a",
"key2": "value2b"
},
{
"key1": "value5a",
"key2": "value5b"
},
{
"key1": "value3a",
"key2": "value3b"
},
{
"key1": "value4a",
"key2": "value4b"
}
],
"withDuplicating": [
{
"key1": "value1a",
"key2": "value1b"
},
{
"key1": "value5a",
"key2": "value5b"
},
{
"key1": "value3a",
"key2": "value3b"
}
]
}
Note
- As other situation, when
f.key1 === e.key1 && f.key2 === e.key2 is modified to f.key1 === e.key1, the duplication of key1 can be retrieved.
Reference
Gists
This is a sample script for creating new table and putting values to cells using Google Docs API with Google Apps Script. Unfortunately, in the current stage, although I had been looking for the method for creating a table and putting the values in each cell at the official document, I couldn’t find. Google Docs API is growing now. So such documents might be not prepared yet. By this situation, I investigated about the method for achieving this method.
Gists
This is a sample script for investigating the possibility of the real time processes in a cell on Google Spreadsheet using Google Apps Script. As a sample situation, it tried the real time clock in a cell on Google Spreadsheet using Google Apps Script.
Demo:

Usage:
When you use this script, please do the following flow.
- Copy and paste the following script to the script editor (the container-bound script of Spreadsheet).
- Run the function of
run().
- By this, a sidebar is opened on the Spreadsheet.
- When you click a button of “start”, the clock is started at the cell “A1” of the active sheet.
- In this sample script, the value is updated every 0.2 seconds. But the process speed of Google Apps Script is often changed even if the same script is run. So when you see the demonstration, there are sometimes the cases of 2 second step.
- If you want to stop the clock, please click “stop” button.
Sample script:
function runCLock() {
Utilities.sleep(200);
var time = Utilities.formatDate(
new Date(),
Session.getScriptTimeZone(),
"HH:mm:ss"
);
SpreadsheetApp.getActiveSheet()
.getRange("A1")
.setValue(time);
}
function run() {
var str =
'<input type="button" value="start" onclick="start()"><input type="button" id="stop" value="stop" onclick="stop=true"><script>var stop=false; function work(){return new Promise((resolve, reject)=> google.script.run.withSuccessHandler(()=> resolve()).runCLock());}async function start(){while(!stop) await work();}</script>';
var html = HtmlService.createHtmlOutput(str);
SpreadsheetApp.getUi().showSidebar(html);
}
Expanded HTML:
At above sample script, HTML is minified. Below script is the expanded HTML.
Gists
This is a sample script for deleting pages of Google Document from the last page using Google Apps Script. There are no methods for directly deleting pages of Google Document. This is one of several workarounds. In this workaround, the following flow is used.
Flow
- Retrieve paragraphs in the body of Document.
- Retrieve elements in each paragraph. The page break is included in the paragraph.
- Delete elements from last page in order.
- When the number of page breaks is the same with deletePages, the script is stopped.
By this flow, several pages can be deleted from the last page in order.
Gists
This is a sample script for retrieving total page of Google Document using Google Apps Script. There are no methods for directly retrieving the total page of Google Document. This is one of several workarounds. In this workaround, the total page is retrieved by converting to PDF format.
var n =
DriveApp.getFileById(id)
.getBlob()
.getDataAsString()
.split("/Contents").length - 1;
Logger.log("totalPages: %s", n);
- When you use this, please set the Google Document ID as
id.
Gists
Overview
These are sample scripts for processing the duplicated rows of 2 dimensional arrays using Google Apps Script.
Description
When I use Google Spreadsheet and/or see Stackoverflow, I sometimes see the situation which is required to process the duplicated rows of 2 dimensional arrays. I thought that when the sample scripts for it have already prepared, they will be useful for other users including me. So I published this post. This sample scripts can be also used for Javascript. If this post is useful for you, I’m glad.
Gists
At April 8, 2019, the specification of Google Apps Script Project was changed. Various specification was changed. Please see the detail at Google Cloud Platform Projects. Here, I would like to introduce one change which might be useful for users. The official document says as follows.
When you enable an advanced service for your script project in the Apps Script editor, it is automatically enabled in the default GCP project when the script project is saved.
Gists
This is a sample script for backing up a project as a zip file. When you use this script, please install a GAS library of ProjectApp2. You can back up both the standalone script type and the container-bound script type.
In this script, the blob of zip file can be retrieved from ProjectApp2. So you can also send it as email without creating a file.
var projectId = "### fileId of project ###";
var blob = ProjectApp2.getProjectBlob(projectId, true);
DriveApp.createFile(blob[0].setName("backupProject.zip"));
Testing:
- July 2, 2020: I could confirm that the script worked. So in the current stage, it seems that the specification is not changed.
Gists
This is a sample script for splitting an array by n elements using Google Apps Script.
Sample script 1:
var limit = 3;
var ar = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var res = [];
while (ar.length > 0) res.push(ar.splice(0, limit));
Logger.log(res); // [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0], [10.0]]
Above sample script is a simple. But at Google Apps Script, the process cost of “while” is higher than the for loop as shown in this report. So I recommend the following sample script for Google Apps Script.
Gists
This is a sample script for overwriting several Google Documents by 2 text files using Google Apps Script.
Before you run this sample script, please install a GAS library of FetchApp.
As a sample situation, it supposes to overwrite 2 existing Google Documents by 2 text files using the method of files.update Drive API v3. In the current stage, the batch request of Drive API cannot use the file media. This sample script might become a workaround for updating files by quasi batching request with the asynchronous process.
Gists
This is a sample script for creating Google Document by converting PDF and image files with OCR using Google Apps Script.
Before you run this sample script, please install a GAS library of FetchApp.
function sample() {
var fileId = "### fileId of PDF file and image files ###";
var metadata = {
name: "sampleDocument", // Filename of created Google Document
mimeType: MimeType.GOOGLE_DOCS // MimeType of Google Document
};
var fileBlob = DriveApp.getFileById(fileId).getBlob();
var form = FetchApp.createFormData(); // Create form data
form.append(
"metadata",
Utilities.newBlob(JSON.stringify(metadata), "application/json")
);
form.append("file", fileBlob);
var url =
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart";
var params = {
method: "POST",
headers: { Authorization: "Bearer " + ScriptApp.getOAuthToken() },
body: form
};
var res = FetchApp.fetch(url, params);
Logger.log(res);
// DriveApp.createFile(blob) // This comment line is used for automatically detecting scope for running this sample script.
}
Overview
This is a GAS library for creating and requesting the type of multipart/form-data using Google Apps Script. This library enhances Class UelFetchApp of Google Apps Script.
Description
In order to fetch data from URL, there is Class UrlFetchApp in Google Apps Script. As the method for fetching, there is the method of fetch(url, params). In the current stage which was released this library, when user want to request with the type of multipart/form-data, the request body is required to be created by the user. But it is a bit difficult to create the request body. I thought that if the request body for the type of multipart/form-data can be easily created, it might be also useful for other users. So I created this as a GAS library.
Gists
This is a sample script for converting a lot of files to Google Docs (Spreadsheet, Document and Slides).
- Batch request can be used for converting files. In this sample script, the files are converted using the batch request.
- Batch request can request 100 API by one API call.
- This sample script uses the fetchAll method. So even if there are over 100 files, this script can process them.
Sample script:
Before you run the script, please set the variables at main(). And, please enable Drive API at Advanced Google services.
ImgApp was updated to v1.2.2.
You can see the detail information here https://github.com/tanaikech/ImgApp
Gists
When an image is inserted to Google Docs (Spreadsheet, Document and Slides) using the method of insertImage using Google Apps Script, there is the case that the error occurs. The error messages are “server error” and “invalid image data”. Here, I would like to introduce the limitations for inserting images to Google Docs. As the result, it was found that the limitation is due to both the mimeTypes and the area of image rather than the file size.
Gists
This is a sample script for deleting the positioned images on Google Document using Google Apps Script. In the current stage, unfortunately, there are no methods for deleting the positioned images in Class PositionedImage, yet. But when Google Docs API is used, the positioned images can be deleted.
When you use this script, please enable Google Docs API at Advanced Google Services and API console. You can see how to enable them at here
Gists
This is a sample script for modifying the searched text to the small capital letters using Google Apps Script. Unfortunately, in the current stage, there are no methods for modifying the part of texts to the small capital letters in Document Service, yet. But when Google Docs API is used, this can be achieved.
When you use this script, please enable Google Docs API at Advanced Google Services and API console. You can see how to enable them at here
Overview
This is a GAS library for notifying the change of number of comments, stars and forks of own Gists as an email using Google Apps Script.
Description
Recently, I noticed that when a comment was posted to own Gists, and the numbers of stars and forks of own Gists were changed, the notification mail is not sent. Also I knew that in the current stage, there are no official methods for notifying them, yet. For this situation, I thought an application for notifying them as an email can be created using Google Apps Script, and when such application can be easily to be used, it may be useful for other users. So I created this as a GAS library.
Gists
Consumer (personal) version of Google+ is closed on April 2, 2019. By this, Apps Script community of Google+ is also closed. This is one of important communities for discussing. So in this post, I would like to introduce the other communities related to Google Apps Script.
-
As the next community of Apps Script community of Google+, Google Apps Script Community was launched.
-
Stackoverflow: https://stackoverflow.com/questions/tagged/google-apps-script
Gists
This is a sample script for parsing query parameters from an URL using Google Apps Script. Also this can be used at Javascript. The process cost becomes a bit lower than that of the script using the regular expression.
Sample script
function parseQuery(url) {
var query = url.split("?")[1];
if (query) {
return query.split("&")
.reduce(function(o, e) {
var temp = e.split("=");
var key = temp[0].trim();
var value = temp[1].trim();
value = isNaN(value) ? value : Number(value);
if (o[key]) {
o[key].push(value);
} else {
o[key] = [value];
}
return o;
}, {});
}
return null;
}
// Please run this function when you test this script.
function main() {
var url = "https://sampleUrl.com/sample?key1=value1&key2=value2&key1=value3&key3=value4&key2=value5";
var res = parseQuery(url);
Logger.log(res);
}
Result
{
"key1": [
"value1",
"value3"
],
"key2": [
"value2",
"value5"
],
"key3": [
"value4"
]
}
Gists
March 25, 2019
Published.
Kanshi Tanaike
Introduction
At Stackoverflow, a lot of people post the questions and answers to the questions every day. There are various tags in Stackoverflow. A lot of discussions are performed at each tag. Their discussions bring the important information and are much useful for a lot of people. As one of tags, there is “google-apps-script”. I sometimes discuss at the questions with that tag. When we see the discussions, we can notice that the discussions are changed and progressed by the time, because “Google Apps Script” which is the origin of the tag is updated. This report thinks this change as the trend of tag of “google-apps-script”. This trend includes the number of questions, questioners, answerers and tags adding to the tag of “google-apps-script”. The trend of tag of “google-apps-script” is deeply related to the progression of Google Apps Script and the various applications for Google Apps Script.
Gists
This is a script for modifying the shading color of paragraph on Google Document using Google Apps Script.
Recently, by releasing Google Docs API, the shading color got to be able to be modified using the script. Here, I would like to introduce a sample script for modifying the shading color of the paragraph on Google Document. At the current Document Service, the shading color cannot be modified yet. I think that this will be achieved in the future update. At that time, I think that a new property might be added to Enum Attribute.
Gists
When a chart is created by using EmbeddedChartBuilder of Spreadsheet service, the title of vAxis which is put by setOption("vAxis", {title: "y axis"}) doesn’t work. It is considered that this is a bug. Because I have confirmed that this had worked fine. Ref But this specification had been changed. So I would like to introduce the method for adding the title of vAxis when a chart is created using Google Apps Script.
Overview
This is a script for extracting files from a tar file using Google Apps Script. This script was created by native Google Apps Script.
The following 3 situations gave me the motivarion for creating this script.
- Although I had been looking for the script for extracting files from a tar file from before, I have still not been able to find it.
- Unfortunately, there are no methods for extracting the files from the tar file in Google Apps Script. But fortunately, from wiki of tar, I could retrieve the structure information of the tar data. And I can also study by creating this script.
- I found this thread at Stackoverflow. By this, I could understand that other users also want the script for extracting files from the tar file.
So I created this.
ProcessApp was updated to v1.0.1.
You can see the detail information here https://github.com/tanaikech/ProcessApp
Overview
This is a library for retrieving the process and information of Google Apps Script.
Methods
- getExecutionTimeOfTrigger() : This method retrieves the total execution time of all functions executed by the time-driven trigger at owner’s account. For example, you can know the total execution time of all functions executed by the time-driven trigger in 24 h.
- getDevUrl() : This method retrieves the endpoint of developer mode for Web Apps like
https://script.google.com/macros/s/#####/dev.
- getRunningFunctions() : This method retrieves the functions which are running now.
You can check this at https://github.com/tanaikech/ProcessApp.
Gists
This sample script is for creating one-time writing cells using Google Apps Script. At first, it supposes the following situation.
- A Spreadsheet is shared with users. The owner of Spreadsheet is you.
- After users put a value to a cell, you don’t want to make users edit the cell again.
- Namely, you want to protect the cell.
This sample script achieves above situation.
Preparation
Before you use this script, please do the following flow.
“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.
Gists
- When it starts a calculation, open a dialog box.
- 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.
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.
ggsrun was updated to v.1.7.1
- v1.7.1 (December 30, 2018)
- 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.
ggsrun was updated to v.1.7.0
You can check ggsrun at https://github.com/tanaikech/ggsrun.
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.
- Select files at browser.
- Upload the files every file.
- 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.
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:
- Copy the original Slides file as a temporary file.
- 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.
- 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.
Gists
Updated on June 22, 2024
This is a sample script for retrieving the access token for Service Account using Google Apps Script. The flow for using this script is as follows.
Usage
- Create the Service Account and retrieve JSON file.
- Put Scopes,
private_key and client_email as an object.
- If you want to use impersonate email, please set the value of
impersonate_email.
- Run the script.
/**
* ### Description
* Get access token from service account.
* ref: https://tanaikech.github.io/2018/12/07/retrieving-access-token-for-service-account-using-google-apps-script/
*
* @param {Object} object Object including private_key, client_email, impersonate_email.
* @param {String} object.private_key
* @param {String} object.client_email
* @param {String} object.impersonate_email
* @param {Array} object.scopes
* @returns {String} Access token.
*/
function getAccessTokenFromServiceAccount_(object) {
const { private_key, client_email, impersonate_email = "", scopes = [] } = object;
const url = "https://www.googleapis.com/oauth2/v4/token";
const header = { alg: "RS256", typ: "JWT" };
const now = Math.floor(Date.now() / 1000);
const claim = { iss: client_email, scope: scopes.join(" "), aud: url, exp: (now + 3600).toString(), iat: now.toString() };
if (impersonate_email != "") {
claim.sub = impersonate_email;
}
const signature = Utilities.base64Encode(JSON.stringify(header)) + "." + Utilities.base64Encode(JSON.stringify(claim));
const jwt = signature + "." + Utilities.base64Encode(Utilities.computeRsaSha256Signature(signature, private_key));
const params = { payload: { assertion: jwt, grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer" } };
const res = UrlFetchApp.fetch(url, params);
const { access_token } = JSON.parse(res.getContentText());
return access_token;
}
// Please run this script.
function main() {
const object = {
private_key: "-----BEGIN PRIVATE KEY-----\n###-----END PRIVATE KEY-----\n",
client_email: "###",
// impersonate_email: "###", // If you want to use an impersonate email, please set this.
scopes: ["###", "###",,,],
};
const accessToken = getAccessTokenFromServiceAccount_(object);
console.log(accessToken);
}
Sample script
When you can obtain the access token by the above script, you can also use the following sample script. The following sample script retrieves the file list of the drive of the service account with Method: files.list of Drive API v3.
You can see the detail information here https://github.com/tanaikech/DownloadLargeFilesByUrl
ggsrun was updated to v.1.6.0
- v1.6.0 (November 30, 2018)
- Although at ggsrun, files can be searched by filename and file ID, searching files using search query and regex couldn’t be done. From version 1.6.0, files got to be able to be searched using the search query and regex.
$ ggsrun sf -q "### search query ###" -f "### fields ###" -r "### regex ###"
- Some modifications.
You can check ggsrun at https://github.com/tanaikech/ggsrun.
ImgApp was updated to v1.2.1.
You can see the detail information here https://github.com/tanaikech/ImgApp
ggsrun was updated to v.1.5.2
- v1.5.2 (November 4, 2018)
- About downloading folders, when files are downloaded from a folder, you can download Google Docs files with the mimeType you want. For example, when you download files from the folder, if
-e txt is used, Google Docs are downloaded as the text file. When -e pdf is used, they are downloaded as the PDF file. Of course, there are mimeType which cannot be converted.
$ ggsrun d -f [folderName] -e txt -j
- About uploading files, when files are uploaded from your local PC, the files got to be able to be converted to Google Docs. For this, new option of
--convertto, -c is added. For example, when a text file is uploaded, if you use -c doc, the text file is uploaded as Google Document.
$ ggsrun u -f [fileName] -c doc -j
You can check ggsrun at https://github.com/tanaikech/ggsrun.
ggsrun was updated to v.1.5.1
- v1.5.1 (November 2, 2018)
- Removed a bug.
- When a file information was retrieved, createdTime and modifiedTime couldn’t be seen and the information was incomplete.
You can check ggsrun at https://github.com/tanaikech/ggsrun.
ggsrun was updated to v.1.5.0
- v1.5.0 (October 27, 2018)
- From this version, ggsrun got to be able to download all files and folders in the specific folder in Google Drive. When all files are downloaded from a folder, the same folder structure of Google Drive is created to the local PC.
$ ggsrun d -f folderName or folderId
- When the project file is downloaded, it is downloaded as a zip file. All scripts in the project is put in the zip file.
- Also when you download a single project, you can use an option
--zip or -z. By this, the downloaded project is saved as a zip file.
- This new function can be also used for the shared folders. When you want to download the files from the shared folder, please use the folder ID of the shared folder.
- The file list with the folder tree in the specific folder got to be able to be retrieved.
- When the files are downloaded, the progression got to be able to be seen. When you want to see the progression, please use
-j when you download files and folders.
- Files with large size got to be able to be used. In order to download files with large size (several gigabytes), files are saved by chunks.
- Some modifications.
You can check ggsrun at https://github.com/tanaikech/ggsrun.
Gists
Benchmark: Reading and Writing Spreadsheet using Google Apps Script
October 12, 2018
Published.
October 18, 2018
Updated.
In order to compare with Advanced Google Service, a result of Sheets API by UrlFetchApp was added to Appendix.
Kanshi Tanaike
Introduction
Please be careful! This result can be only used for Google Apps Script.
There are a limit executing time for Google Apps Script (GAS). That is 6 minutes for Consumer and Google Apps free edition, and 30 minutes for G Suite and Early Access. 1 So many users always have to pay attention to reducing the process cost of scripts. So it is very important to know the process cost of various situations. I have already reported the costs for various processes as the reports. 2 In this report, the process cost for reading and writing values for Spreadsheet using GAS has been investigated.
Overview
ArrangeStackingOrder is a GAS library for arranging the stacking order of page elements on Google Slides using Google Apps Script (GAS).
Demo

This is a demonstration of this library when this is used as a Google Slides Addon.
Description
Do you have situations that you want to arrange the stacking order of page elements on Google Slides using GAS? I had it before. At that time, I could achieve it by creating a simple script. Recently, I found that users who have the same situation. I thought that if there is a library for this, it will be useful for me and other developers. So I created this. If this was useful for your situation, I’m glad.
Recently, I was invited to Skillshare.com. They said that “will you teach about Google Apps Script?”. I thought that if I can be helpful for other users, I’m glad. So I joined to there and created a presentation. I would like to create more classed in the future. If those were helpful for you, I’m glad.
Gists
September 21, 2018
Published.
Kanshi Tanaike
Overview
This is a report about the possibility of asynchronous process using event triggers. This is for Google Apps Script (GAS).
Description
onEdit() which is a simple trigger is often used as a trigger when the values are modified on Spreadsheet. When users want to use the script including some methods which are required to be authorized as the onEdit event, a installable trigger of onEdit is used. If the trigger is installed for the function of onEdit(), when the event trigger is run, onEdit() is run 2 times. In order to avoid this, the installable trigger is installed to the functions except for the functions of simple triggers. The functions of simple triggers which is the same events are not used in the project. When I thought about this situation, I thought that both onEdit() which is run by the simple trigger and the function which is run by the installable trigger might be able to be used, simultaneously. So I investigated about this situation.
RangeListApp was updated to v1.0.1.
You can check this at https://github.com/tanaikech/RangeListApp.
Gists
This is a sample script for expanding a1Notations using Google Apps Script (GAS). In this script, for example, “A1:E3” is expanded to “A1, B1, C1, D1, E1, A2, B2, C2, D2, E2, A3, B3, C3, D3, E3”. When each cell in “A1:E3” is checked, this script might be able to be used. If this was useful for your situation, I’m glad.
Script:
function expandA1Notation(a1Notations) {
var columnToLetter = function(column) {
var temp, letter = '';
while (column > 0) {
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
};
var letterToColumn = function(letter) {
var column = 0, length = letter.length;
for (var i = 0; i < length; i++) {
column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
}
return column;
};
var reg = new RegExp("([A-Z]+)([0-9]+)");
var res = a1Notations.map(function(e) {
var a1 = e.split("!");
var r = a1.length > 1 ? a1[1] : a1[0];
var rr = r.split(":").map(function(f) {return f.toUpperCase().match(reg)});
var obj = {
startRowIndex: Number(rr[0][2]),
endRowIndex: rr.length == 1 ? Number(rr[0][2]) + 1 : Number(rr[1][2]) + 1,
startColumnIndex: letterToColumn(rr[0][1]),
endColumnIndex: rr.length == 1 ? letterToColumn(rr[0][1]) + 1 : letterToColumn(rr[1][1]) + 1,
};
var temp = [];
for (var i = obj.startRowIndex; i < obj.endRowIndex; i++) {
for (var j = obj.startColumnIndex; j < obj.endColumnIndex; j++) {
temp.push(columnToLetter(j) + i);
}
}
return temp;
});
return res;
}
// When you use this script, please run main().
function main() {
var a1Notations = ["A1:E3", "B10:W13", "EZ5:FA8", "AAA1:AAB3"];
var res = expandA1Notation(a1Notations);
Logger.log(res);
}
Result:
[
["A1","B1","C1","D1","E1","A2","B2","C2","D2","E2","A3","B3","C3","D3","E3"],
["B10","C10","D10","E10","F10","G10","H10","I10","J10","K10","L10","M10","N10","O10","P10","Q10","R10","S10","T10","U10","V10","W10","B11","C11","D11","E11","F11","G11","H11","I11","J11","K11","L11","M11","N11","O11","P11","Q11","R11","S11","T11","U11","V11","W11","B12","C12","D12","E12","F12","G12","H12","I12","J12","K12","L12","M12","N12","O12","P12","Q12","R12","S12","T12","U12","V12","W12","B13","C13","D13","E13","F13","G13","H13","I13","J13","K13","L13","M13","N13","O13","P13","Q13","R13","S13","T13","U13","V13","W13"],
["EZ5","FA5","EZ6","FA6","EZ7","FA7","EZ8","FA8"],
["AAA1","AAB1","AAA2","AAB2","AAA3","AAB3"]
]
This script uses 2 methods (https://stackoverflow.com/a/21231012/7108653) for converting from index to letter and from letter to index.
FilesApp was updated to v1.0.1.
- Removed a bug.
- When there are files and folders without the parents, an error occurred. In this version, this issue was removed.
GitHub of FilesApp
Overview
DownloadLargeFilesByUrl is a GAS library for downloading large files from URL to Google Drive using Google Apps Script (GAS).
Description
I had been thinking of about whether a large file from an URL can be downloaded to Google Drive using GAS. When I have tried to download such large files, I noticed the following limitations. These limitations are due to the specification of GAS.
- When users download a file from URL using GAS, at the most users, it retrieves the blob using
UrlFetchApp.fetch(url).getBlob() and saves it as a file using DriveApp.createFile(blob). In this case, only files less than 50 MB (52,428,800 bytes) can be created, because of the size limitation of Blob.
- There are a limit executing time for Google Apps Script (GAS). That is 6 min/execution.
- There are a limit of total executing time for running scripts by triggers. That is 90 min/day. (Recently, it became from 60 min/day to 90 min/day.)
When it tries to create the application for downloading the large files, it is required to consider above limitations. On the other hand, there are the following relaxations of quotas by the recent Google’s update.
Gists
Overview
This is sample scripts for copying files to a specific folder in Google Drive using Google Apps Script (GAS).
Description
When the files in Google Drive are copied to a specific folder using GAS, most users will use makeCopy(destination). When the files are copied using makeCopy(), you might have already noticed that only the standalone projects cannot be copied to the specific folder. They are copied to the root folder (My Drive). Also this situation can be also seen even when “copy” of Drive API v2 and v3 is used. I think that this might be a bug. So I would like to introduce 2 sample scripts as the workaround. In the workaround, it uses Drive API.
Gists
This is a sample script for replacing text to image for Google Document using Google Apps Script (GAS). There is a method for replacing text to text at Class Text of DocumentApp. But there are not methods for replacing text to image. So I created this sample script.
Demo :

This sample image was created by k3-studio.
Usage :
replaceTextToImage(body, replaceText, image, width);
body : body of document. You can set by DocumentApp.getActiveDocument().getBody() and DocumentApp.openById(documentId).getBody().
replaceText : string you want to replace.
image : blob of image you want to replace.
width : Width of replaced image. The aspect ratio is constant. The unit is pixels. If you don’t use this, the original size is used.
Script :
In this sample script, all strings of “sample” in the document are replaced to image with the file ID of imageFileId.
Gists
Benchmark: Decreasing Loop for Array Processing using Google Apps Script
August 11, 2018
Published.
Kanshi Tanaike
Introduction
Please be careful! This result can be only used for Google Apps Script.
There are a limit executing time for Google Apps Script (GAS). That is 6 minutes. 1 So users always have to pay attention to reducing the process cost of the scripts. Especially, it is very important to know the process cost for the array processing, because the array processing is often used for spreadsheet and Google APIs. I have already reported the process costs for various processes as reports. 2-7 In this report, the process cost of “Decreasing loop” for the array processing using GAS has been investigated.
Gists
This is a sample script for retrieving screen shots of sites using Google Apps Script. In order to retrieve the screen shot, here, I used PageSpeed API.
When you use this, please copy and paste the following script, and set an URL you want to retrieve a screen shot.
var siteUrl = "### URL you want to retrieve a screen shot. ###";
var url =
"https://www.googleapis.com/pagespeedonline/v4/runPagespeed?screenshot=true&fields=screenshot&url=" +
encodeURIComponent(siteUrl);
var res = UrlFetchApp.fetch(url).getContentText();
var obj = JSON.parse(res);
var blob = Utilities.newBlob(
Utilities.base64DecodeWebSafe(obj.screenshot.data),
"image/png",
"sample.png"
);
DriveApp.createFile(blob);
Note :
- Retrieved value of screen shot is a base64 data with Web Safe.
- In my environment, when I ran this script as a test, it was not required to enable this API at API console. And also I used no API key. If you want to retrieve values from a lot of URLs, it might be required to enable API and use API key.
Updated at December 9, 2021
Now, version 5 can be used. The script is as follows. In this case, please add the scope as the value of openid. By this, the access token can be used. Although this sample script uses the access token, of course, you can also use the API key instead of the access token.
OnedriveApp was updated to v1.1.1.
I have to apologize you and all users.
I had forgot that it added setProp(). I could notice about this by reporting at here.
I would like to report because I could remove this bug.
GitHub of OnedriveApp
Overview
RangeListApp is a GAS library for retrieving, putting and replacing values for Spreadsheet by a range list with a1Notation using Google Apps Script (GAS).
Description
There is Class RangeList as one of classes for Spreadsheet. There is setValue(value) in Class RangeList as a method. setValue(value) puts value to the cells of range list. Recently, when I used this method, I noticed that the following situations what I want cannot be achieved.
I updated the report of “Benchmark: Loop for Array Processing using Google Apps Script”. In this update, “reduce” was added. If this report is useful for your situation, I’m glad.
You can check this at https://gist.github.com/tanaikech/848aeafaac1ec676900bb78e3ce220b6.
Overview
This is a Google Apps Script for notifying with email when Netatmo was down.
Description
I’m measuring the surrounding environment using Netatmo. There were little that my Netatmo was down so far. But recently, my Netatmo is sometimes down. It is considered that the reason is due to the thermal runaway, because the recent Japan is very hot. When Netatmo was down, users can know it by logging in using the browser and/or running the mobile application. But I couldn’t find the applications and methods for automatically noticing that the Netatmo was down. So I thought that this can be achieved using Netatmo API and Google Apps Script. And I created this. If this is also useful for other Netatmo’s users, I’m glad.
Gists
This is a sample script for retrieving the last coordinate of the specific row and column. When the methods of getLastRow() and getLastColumn() of Class Range for Spreadsheet are used, the last coordinates of the vertical and horizontal data range can be retrieved. When users want to retrieve the last coordinates of each row and column, there are no methods. So I created this script. I think that there are several scripts for this situation. So please think of this as one of them. If this was useful for you, I’m glad.
This is a script for sending an email when users got comments at Stackoverflow. I had wished I could get an email when I got a comment at Stackoverflow. Although I investigated about this, it seems that I can get the email every 3 hours. For this situation, I wished I could get it much earlier. I thought that this can be achieved using GAS and Stack Exchange API. So I created this script. The features of this script are as follows.
Gists
Updated on February 5, 2024
This is for adding the query parameters to the URL. These scripts can be also used for Javascript. When I created an endpoint with some query parameters, I had used the scripts of various patterns every time. Today, I prepared this sample script to unify them. If this is also useful for you, I’m glad.
Sample script (With V8 runtime):
String.prototype.addQuery = function (obj) {
return (this == "" ? "" : `${this}?`) + Object.entries(obj).flatMap(([k, v]) => Array.isArray(v) ? v.map(e => `${k}=${encodeURIComponent(e)}`) : `${k}=${encodeURIComponent(v)}`).join("&");
}
function myFunction1() {
const url = "https://sampleUrl";
const query = {
query1: ["value1A", "value1B", "value1C"],
query2: "value2A, value2B",
query3: "value3A/value3B",
};
const endpoint = url.addQuery(query);
console.log(endpoint); // https://sampleUrl?query1=value1A&query1=value1B&query1=value1C&query2=value2A%2C%20value2B&query3=value3A%2Fvalue3B
}
// In this case, only the query parameter is exported. This value can be used for requesting with Form data.
function myFunction2() {
const url = "";
const query = {
query1: ["value1A", "value1B", "value1C"],
query2: "value2A, value2B",
query3: "value3A/value3B",
};
const endpoint = url.addQuery(query);
console.log(endpoint); // query1=value1A&query1=value1B&query1=value1C&query2=value2A%2C%20value2B&query3=value3A%2Fvalue3B
}
Sample script (Without V8 runtime):
String.prototype.addQuery = function (obj) {
return this + Object.keys(obj).reduce(function (p, e, i) {
return p + (i == 0 ? "?" : "&") +
(Array.isArray(obj[e]) ? obj[e].reduce(function (str, f, j) {
return str + e + "=" + encodeURIComponent(f) + (j != obj[e].length - 1 ? "&" : "")
}, "") : e + "=" + encodeURIComponent(obj[e]));
}, "");
}
function myFunction() {
var url = "https://sampleUrl";
var query = {
query1: ["value1A", "value1B", "value1C"],
query2: "value2A, value2B",
query3: "value3A/value3B",
};
var endpoint = url.addQuery(query);
Logger.log(endpoint);
}
Result:
Both sample scripts return the following URL including the query parameters.
Gists
Benchmark: Conditional Branch using Google Apps Script
July 11, 2018
Kanshi Tanaike
Introduction
Please be careful! This result can be only used for Google Apps Script.
There are a limit executing time for Google Apps Script (GAS). That is 6 minutes.1 So users always have to pay attention to reducing the process cost of the scripts. Especially, it is very important to know the process cost for the array processing, because the array processing is often used for spreadsheet and Google APIs. Recently, I have already published some reports about the process cost using GAS.2-6 From these reports, it has found that GAS shows much different process cost from other languages. So it is important to investigate the process cost for various scenes. In this report, the process cost of “conditional branch” using GAS has been investigated.
ManifestsApp was updated to v1.0.3.
-
v1.0.3 (July 11, 2018)
- By Google’s update, “sheets” was added to manifests for installing the configuration of Macro. By this, this library was updated.
- You can see the added methods (getSheets(), setSheets()) at Usage.
- If you set “sheets”, please put the value of “sheets” as the resource like below sample.
{"macros": [{"menuName": "QuickRowSum", "functionName": "calculateRowSum"}]}
- Don’t put
{"sheets": {"macros": [{"menuName": "QuickRowSum", "functionName": "calculateRowSum"}]}}
You can check this at https://github.com/tanaikech/ManifestsApp.
Gists
Introduction
Here I would like to introduce about the limitation of images for inserting to Spreadsheet using Google Apps Script (GAS). When you want to insert the images to Spreadsheet using GAS, insertImage() of class Sheet is usually used for this situation. At this time, an error sometimes occurs. This indicates that there is the limitation for inserting images to Spreadsheet. So I investigated the limitation.
As a result, it was found that the limitation depends on the image area (pixels^2) rather than the file size of it. The maximum area of image which can be inserted was 1,048,576 pixels^2.
Here, CLI tools, libraries, Add-ons, Reports, Benchmarks and Sample Scripts for taking advantage of Google Apps Script which are publishing in my blog, Gists and GitHub are summarized. If these are useful for you, I’m glad.
You can check this at https://github.com/tanaikech/taking-advantage-of-google-apps-script.
Gists
There are no prepared methods for retrieving the number of lines in the Google Document. So I thought this workaround. If the end of each line can be detected, the number of lines can be retrieved. So I tried to add the end markers of each line using OCR.
At Google Documents, when a sentence is over the page width, the sentence automatically has the line break. But the line break has no \r\n or \n. When users give the line break by the enter key, the line break has \r\n or \n. By this, the text data retrieved from the document has only the line breaks which were given by users. I thought that OCR may be able to be used for this situation. The flow is as follows.
Gists
Benchmark: Search for Array Processing using Google Apps Script
July 2, 2018
Kanshi Tanaike
Introduction
Please be careful! This result can be only used for Google Apps Script.
There are a limit executing time for Google Apps Script (GAS). That is 6 minutes.1 So users always have to pay attention to reducing the process cost of the scripts. Especially, it is very important to know the process cost for the array processing, because the array processing is often used for spreadsheet and Google APIs. Recently, I have reported about the process cost of the loop for the array processing.2 Also I have reported “Improved Algorithms for Summation of Array Elements” as a method for reducing the process cost.3 From these reports, it has found that GAS shows much different process cost from other languages. So it is important to investigate the process cost for various scenes. In this report, the process cost of “searching strings in an array” for the array processing using GAS has been investigated.
Gists
Overview
This is a sample script which can achieve the resumable conversion from the large CSV-file to several spreadsheets by splitting the CSV file using Google Apps Script (GAS).
Description
Is there a situation that you want to convert a CSV file with the large size (> 50 MB) to Spreadsheet? When such large CSV file is converted to Spreadsheet, you will experience the error. The reason is the size and/or also it may be due to the total cells (> 2,000,000 cells) of CSV file. In this case, you will think that when the file is split, each file can be converted to Spreadsheet. But the blob which can be used at GAS is less than 50 MB (52,428,800 bytes). Ref1 So when you have a CSV file with more than 50 MB, it is not possible to split it. In this case, you can split such large file by files.get of Drive API. files.get of Drive API has a function of Partial download. Ref2 Using this, the file can be split. By the way, in my environment, when a CSV file with the size of 100 MB is used for this sample script, when the file is split by 10 MB, about 65 seconds was required to convert a chunk to Spreadsheet. In this case, when the CSV file is completely converted, it is considered that it will be over the limitation time (6 min) for executing GAS. So in this post, I would like to introduce a sample script which can achieve the resumable conversion from the large CSV-file to several spreadsheets.
Gists
By the Google’s update at June 19, 2018, finally, Utilities.computeDigest(), Utilities.computeHmacSha256Signature() and Utilities.computeHmacSignature() got to be able to use the byte arrays. By this, using only native Google Apps Script, the result can be retrieved without using jsSHA. So Cryptopia API can be created using only Google Apps Script. If this is useful for you, I’m glad.
Sample script :
When you use this, at first, please input the requiring values. Now the sample values are used.
Gists
By the Google’s update at June 19, 2018, finally, Utilities.computeDigest(), Utilities.computeHmacSha256Signature() and Utilities.computeHmacSignature() got to be able to use the byte arrays. By this, using only native Google Apps Script, the result can be retrieved without using jsSHA. When I used the updated them, the response speed is much faster than that of jsSHA. It is considered that this may be optimized for Google Apps Script. As a sample, it shows 2 samples as follows. The both results are the same.
Overview
FilesApp is a GAS library for retrieving file and folder list in Google Drive using Google Apps Script (GAS). Also this can create a tree from all files and folders in Google Drive.
Description
When I create some applications using Google Drive, there are often the case which is required to retrieve the file list and folder list. I had prepared the script each time for each case so far. But recently, I thought that if there is a library for retrieving the file and folder list (as a tree), it will be useful for me and other developers. So I created this. If this was useful for your situation, I’m glad.
Gists
This sample script is for retrieving a key with the maximum value from an object. This can be also used by Google Apps Script.
var obj = {"a": 5, "b": 4, "c": 3, "d": 2, "e": 1};
var res = Object.keys(obj).reduce(function(a, c) {
return obj[a] > obj[c] ? a : c;
});
Logger.log(res); // >>> a
Gists
Overview
This is a sample script for easily retrieving the reformatted scripts without comments in a project using Google Apps Script (GAS).
Description
When I create GAS script, if the format of script is not correct, the script editor lets me know about it. By this, I can find that the script editor and/or Google Drive checks the format of scripts. I had wished if I could use this function. Recently, I noticed an interesting function. A GAS project is created and when function myFunction() {Logger.log(this)} is run in the script, I noticed that all scripts in the project are included in this. Furthermore, when I saw the retrieved script, also I noticed that their scripts are reformatted and all comments are removed. In the case of Apps Script API, when the scripts are retrieved by the API, the retrieved script is the same to the original one. So I think that this will help users retrieve simply the reformatted GAS scripts, and such the reformatted scripts will be able to be used for the various situations.
Gists
Overview
This is a method for removing Third-party Apps with Account Access using a script.
Demo

Description
When users create a script in a project and run the script, if the methods which are required to use scopes are included, users have to authorize to use the scopes using the browser. By authorizing it, users can use the script. The authorized projects can be seen at Third-party Apps with Account Access. One day, I had a situation that it required to remove the authorization of project, because of the security. Third-party Apps with Account Access can be manually removed as you know. But at that time, I wanted to remove using a script. So I came up with this method.
News
Overview
This is a sample script for uploading files with large size (> 50 MB) at Web Apps using Google Apps Script (GAS). The resumable upload method is used for uploading files. This script can be also applied to the script using gapi of javascript.
Gists
This sample script retrieves the difference elements between 2 dimensional arrays using Google Apps Script. In Google Apps Script, 2 dimensional arrays are often used at Google Docs and Google APIs. And from my recent report, it has already found that the process cost of filter() is the lowest in the other loop methods. So I use the script like this.
var ar1 = [["a1", "b1", "c1"], ["a2", "b2", "c2"], ["a3", "b3", "c3"], ["a4", "b4", "c4"], ["a5", "b5", "c5"]];
var ar2 = [["a2", "b2", "c2"], ["a5", "b5", "c5"], ["a1", "b2", "c3"]];
var res = ar1.filter(function(e) {return ar2.filter(function(f) {return e.toString() == f.toString()}).length == 0});
Logger.log(res); // [["a1","b1","c1"],["a3","b3","c3"],["a4","b4","c4"]]
For above script, when it changes from == 0 to > 0, the duplication elements can be retrieved as follows.
Overview
This is a library for running Batch Requests using Google Apps Script (GAS).
Description
When users use Google’s APIs, one quota is used for one API call. When the batch request is used, several APIs can be called by one quota, although there are some limitations in the batch request. For example, in GAS, Drive API can be used be DriveApp. In this case, the quota is not used for using Drive API. (When Drive of Advanced Google Services is used, the quota is used.) But this is Drive API v2. If users want to use Drive API v3, it is required to directly request each endpoint of Drive API v3. The batch request is much useful for this situation. However, it is a bit difficult for users to use the batch request. Because the batch request is requested by multipart/mixed. I thought that the script may become a bit complicated, because of the request of multipart/mixed using UrlFetchApp. And although I had been looking for the libraries for the batch request, I couldn’t find them. So I created this.
Gists
This is a sample script which works the same action with the CLEAN method of VBA. The CLEAN method of VBA removes the characters of 0-31, 127, 129, 141, 143, 144, 157. Although I had looked for such method for Google Apps Script, I couldn’t find it. So I created this. If this is useful for you, I’m glad.
function cleanForGAS(str) {
if (typeof str == "string") {
var escaped = escape(str.trim());
for (var i = 0; i <= 31; i++) {
var s = i.toString(16);
var re = new RegExp("%" + (s.length == 1 ? "0" + s : s).toUpperCase(), "g");
escaped = escaped.replace(re, "");
}
var remove = ["%7F", "%81", "%8D", "%8F", "%90", "%9D"];
remove.forEach(function(e) {
var re = new RegExp(e, "g");
escaped = escaped.replace(re, "");
});
return unescape(escaped).trim();
} else {
return str;
}
}
function main() {
var res = cleanForGAS(str);
}
Overview
This is a report to take advantage of Web Apps with Google Apps Script (GAS).
Description
There is Web Apps as one of applications using Google Apps Script (GAS). I sometimes use this Web Apps. But I have only a little the information for the specification of Web Apps. So in order to take more advantage of Web Apps, I investigated and summarized about this. The aim of this report is to become one of the basic information for creating various applications using Web Apps with GAS.
Gists
This is a sample script for Google Apps Script (GAS). This script retrieves all named ranges in Spreadsheet. The names and range of the retrieved named ranges are output as the keys and the values of JSON object, respectively. The sample output is {"name1": "Sheet1!A1:B2", "name2": "Sheet2!B1:C2",,,}. The name of named range has to be only one in the spreadsheet. This was used.
Sheets.Spreadsheets.get() of Sheets API can retrieve all named ranges. But the retrieved range is the grid range. So in this sample script, the grid range was converted to a1Notation. The main part of this sample script is here.
Overview
This is a library for running the concurrent processing using only native Google Apps Script (GAS).
Description
Have you ever thought about the concurrent processing using only native Google Apps Script (GAS)? So far, I had run the concurrent processing using golang, javascript and python. But the script cannot be used by the trigger event, because these are not native GAS. Recently, it was found that the fetchAll method added by the Google’s update at January 19, 2018 is worked by the asynchronous processing. By this, the concurrent processing using the native GAS got to be able to be achieved. This library makes users work the concurrent processing of functions using the fetchAll method and the execution API. This can drastically reduce the process cost in the script. And also this can be used under the trigger event. So it is considered that it will be useful for both the limit executing time of 6 minutes for GAS and the limit total executing time of 1 hour/day for the trigger event.
Gists
By Google’s update at January 19, 2018, fetchAll method was added to the UrlFetch service. When I saw the usage, I couldn’t find the detail information about the actual running state. So I investigated about it.
As the result, it was found that the fetchAll method is worked by the asynchronous processing. The returned data is reordered by the order of requests. By this, it was also found that if you want to retrieve the data from the several URL, the process cost of UrlFetchApp.fetchAll() is much lower than that of UrlFetchApp.fetch() using for loop.
Gists
Benchmark: Loop for Array Processing using Google Apps Script
April 16, 2018
Published.
July 26, 2018
Updated.
Result of reduce was added.
Kanshi Tanaike
Introduction
Please be careful! This result can be only used for Google Apps Script.
There are a limit executing time for Google Apps Script (GAS). That is 6 minutes.1 So users always have to pay attention to reducing the process cost of the scripts. Especially, it is very important to know the process cost for the array processing, because the array processing is often used for spreadsheet and Google APIs. I have already reported “Improved Algorithms for Summation of Array Elements” as a method for reducing the process cost.2 In this report, the process cost of “loop” for the array processing using GAS has been investigated.
Gists
Introduction
There are event objects at Google Apps Script. Typically, users which use Spreadsheet often use onEdit(event). Here, I would like to introduce the process costs for the event objects using this onEdit(event).
When onEdit(event) is used for the spreadsheet, event of onEdit(event) has the following structure.
{
"authMode": {},
"range": {
"columnStart": 1,
"rowStart": 1,
"rowEnd": 1,
"columnEnd": 1
},
"source": {},
"oldValue": "old sample text",
"user": {
"nickname": "sampleName",
"email": "sample email"
},
"value": "sample text"
}
In this structure, for example, the range of active cell is "range": {"columnStart": 1, "rowStart": 1, "rowEnd": 1, "columnEnd": 1 }. Namely, it’s “A1”. Users can use the range of active cell using this event object. In this report, I have investigated the process cost for retrieving the range of active cell as a sample.
Overview
This is a script for converting strings from NFD (Normalization Form Decomposition) to NFC (Normalization Form Composition) using Google Apps Script.
Description
Here, I would like to introduce a script for the unicode normalization using Google Apps Script. There are the characters with ゙ which is the voiced dot and the characters with ゚ which is the semi-voiced dot in Japanese language. When these are used for some applications, there are 2 kinds of usages for the character. For example, when for は (\u306f) HA with the voiced dot, there are ば and ば. These unicodes are \u3070 and \u306f\u3099. Namely, there are the case which displayed 1 character as 2 characters. In most cases, the characters like \u3070 are used. This called NFC (Normalization Form Composition). But we sometimes meet the characters like \u306f\u3099. This called NFD (Normalization Form Decomposition). When the document including such characters which are displayed as 2 characters is converted to PDF file, each character is separated like は ゙. So users often want to convert the characters constructed by 2 characters to the single characters. Recently, String.prototype.normalize was added at ES2015. But ES2015 cannot be used at Google Apps Script yet. And although I had looked for the scripts like this for GAS, unfortunately, I couldn’t find. So I created this script.
RearrangeScripts was updated to v2.1.1
-
v2.1.1 (Match 2, 2018)
- Added a notification to turn on the switch for using Google Apps Script API.
Gists
This is a sample script for transposing JSON object using Google Apps Script.
[
{"key1":"a1","key2":"a2","key3":"a3","key4":"a4","key5":"a5"},
{"key1":"b1","key2":"b2","key3":"b3","key4":"b4","key5":"b5"},
{"key1":"c1","key2":"c2","key3":"c3","key4":"c4","key5":"c5"},
{"key1":"d1","key2":"d2","key3":"d3","key4":"d4","key5":"d5"},
{"key1":"e1","key2":"e2","key3":"e3","key4":"e4","key5":"e5"}
]
Output data :
{
"key1": ["a1", "b1", "c1", "d1", "e1"],
"key2": ["a2", "b2", "c2", "d2", "e2"],
"key3": ["a3", "b3", "c3", "d3", "e3"],
"key4": ["a4", "b4", "c4", "d4", "e4"],
"key5": ["a5", "b5", "c5", "d5", "e5"]
}
Script :
At first, keys have to be defined by yourself, because the order of json is not decided.
var keys = ["key1", "key2", "key3", "key4", "key5"];
var result = {};
data.map(function(_, i){return keys.map(function(f, j){return data[i][keys[j]]})}).forEach(function(e, i){result[keys[i]] = e});
Logger.log(JSON.stringify(result))
Gists
This is a sample script for opening a site with new window using Google Apps Script. It is possible to open the site inside the opened dialog box using iframe. But in my situation, I had to open the site as new window. So I created this. As a sample application, it can think of like this. When the special keyword was inputted, open sites and files in Google Drive as a help window. In this case, the trigger installed onEdit() is required to be used. I think that there are some other applications.
At February 15th, 2018, ShapeApp was featured as one of “4 useful add-ons launched last month”.
ggsrun was updated to v.1.4.1
- v1.4.1 (February 9, 2018)
- For uploading, the resumable-upload method was added.
- The resumable-upload method is automatically used by the size of file.
- “multipart/form-data” can upload files with the size less than 5 MB.
- “resumable-upload” can upload files with the size more than 5 MB.
- The chunk for resumable-upload is 100 MB as the default.
- Users can also give this chunk size using an option.
$ ggsrun u -f filename -chunk 10
- This means that a file with filename is uploaded by each chunk of 10 MB.
You can read “How to install” at here.
Gists
These are sample scripts for adding a label to a message using message ID for Gmail.
Sample 1
This sample adds a label to a thread using message ID. In this case, all messages in the thread have the label. Even if it adds a label to a message in the thread using addLabel(), all messages in the thread have the label, becauce addLabel can only be used for the thread.
Gists
Description :
This sample script is for retrieving emails which replied for received mails. Because there are no samples which confirm whether the owner (me) replied to the received mails, I created this. The point is as follows.
- When there are more than 2 messages in a thread, there might be a possibility to have replied.
- For more than 2 messages in a thread
- The email address of “from” for the 1st message is the sender’s address.
- When the email address of “to” of after 2nd messages is the same to that of “from” of 1st one, it is indicates that the thread was replied by owner.
This sample script is made of Google Apps Script (GAS). But also this can be applied to other languages.
ManifestsApp was updated to v1.0.2.
You can check this at https://github.com/tanaikech/ManifestsApp.
Overview
This is a GAS project library for Google Apps Script (GAS). This library can be used for the projects of both standalone script type and container-bound script type.
Description
There are Class SpreadsheetApp and Class DocumentApp for operating spreadsheet and document, respectively. But there is no Class for operating GAS project. If there is such Class ProjectApp, GAS project can be directly operated by GAS script. I thought that this will lead to new applications, and created ProjectApp. On the other hand, as a CLI tool for operating GAS project, there has already been ggsrun.
ggsrun was updated to v.1.4.0
-
v1.4.0 (January 25, 2018)
Google Apps Script API was finally released. From this version, ggsrun uses this API. So ggsrun got to be able to use not only projects of standalone script type, but also projects of container-bound script type. I hope this updated ggsrun will be useful for you.
- To users which are using ggsrun with v1.3.4 and/or less.
- For retrieving, downloading, creating and updating projects, Apps Script API is used.
- About retrieving information of projects, the information from Drive API is more than that from Apps Script API. So I used Drive API in this situation.
- Please read how to enable APIs.
- ggsrun got to be able to use both standalone scripts and container-bound scripts by Apps Script API.
- Create projects
- Update projects
- There are some issues for creating projects.
- After Manifests was added to GAS, the time zone can be set by it. But when a new project is created by API, I noticed that the time zone is different from own local time zone. When a new project is manually created by browser, the time zone is the same to own local time zone. I think that this may be a bug. So I added an option for setting time zone when a new project is created. And also I reported about this to Google Issue Tracker.
- If you want to create a bound script in Slide, an error occurs. When a bound script can be created to Spreadsheet, Document and Form using Apps Script API. Furthermore, when the bound script in Slide is updated, it works fine. So I think that this may be also a bug. I reported about this to Google Issue Tracker.
- About this, when you create a bound script in Slides, if ggsrun returns no errors, it means that this issue was solved.
- Both standalone scripts and container-bound scripts can be rearranged.
- The file of
appsscript for Manifests is always displayed to the top of files on the script editor, while the array of files can be changed. I think that this is the specification.
- For the option
exe1 for executing GAS, it can use for both standalone scripts and container-bound scripts.
- Delete files using file ID on Google Drive.
- Delete files in the project.
- ggsrun can create new container-bound script in the new Google Docs.
- For example, ggsrun creates a new Spreadsheet and uploads the script files to the Spreadsheet as a container-bound script.
- Retrieve and create versions of projects.
- Unified the order of directories for searching
client_secret.json and ggsrun.cfg.
- Some modifications.
You can read “How to install” at here.
Gists
Pattern 1
This is a sample script for copying GAS project to a container-bound script of Google Docs (Spreadsheet, Document and Form (and Slides)). The project is created as a new project.
In order to use this sample, please do the following installation flow.
If you use this sample script, at first, please test using a new project and new Google Docs. By this, please understand the work of this script.
Gists
There is the bathing requests in the Google APIs. The bathing requests can use the several API calls as a single HTTP request. By using this, for example, users can modify filenames of a lot of files on Google Drive. But there are limitations for the number of API calls which can process in one batch request. For example, Drive API can be used the maximum of 100 calls in one batch request.
Gists
This sample script is for using Zaif API by Google Apps Script.
The following go script is a sample at Zaif API.
package main
import (
"fmt"
"time"
"strconv"
"crypto/hmac"
"crypto/sha512"
"io/ioutil"
"net/http"
"encoding/hex"
"net/url"
"strings"
)
var key = "<your_key>"
var secret = "<your_secret>"
func main() {
uri := "https://api.zaif.jp/tapi"
values := url.Values{}
values.Add("method", "get_info")
values.Add("nonce", strconv.FormatInt(time.Now().Unix(), 10))
encodedParams := values.Encode()
req, _ := http.NewRequest("POST", uri, strings.NewReader(encodedParams))
hash := hmac.New(sha512.New, []byte(secret))
hash.Write([]byte(encodedParams))
signature := hex.EncodeToString(hash.Sum(nil))
req.Header.Add("Key", key)
req.Header.Add("Sign", signature)
client := new(http.Client)
resp, _ := client.Do(req)
defer resp.Body.Close()
byteArray, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(byteArray))
}
When this is converted to GAS, the script is as follows.
Gists
This sample script is for using Bittrex API by Google Apps Script.
The following PHP script is a sample at bittrex.com.
$apikey='xxx';
$apisecret='xxx';
$nonce=time();
$uri='https://bittrex.com/api/v1.1/market/getopenorders?apikey='.$apikey.'&nonce='.$nonce;
$sign=hash_hmac('sha512',$uri,$apisecret);
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('apisign:'.$sign));
$execResult = curl_exec($ch);
$obj = json_decode($execResult);
When this is converted to GAS, the script is as follows.
function main() {
var apikey = '#####'; // Please input your key.
var apisecret = '#####'; // Please input your secret.
var nonce = Number(new Date().getTime() / 1000).toFixed(0);
var uri = 'https://bittrex.com/api/v1.1/market/getopenorders?apikey=' + apikey + '&nonce=' + nonce;
var sign = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, uri, apisecret);
sign = sign.map(function(e) {return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2);}).join("");
var params = {
method: "get",
headers: {Apisign: sign}
}
var res = UrlFetchApp.fetch(uri, params);
Logger.log(res.getContentText())
}
Gists
This sample script is for using Binance API by Google Apps Script. This script encryptes “signature” like samples. In this script, “Example 1: As a query string” is used, and it retrieves “All orders (SIGNED)” by “GET”.
function main() {
var key = '#####'; // Please input your key.
var secret = '#####'; // Please input your secret.
var api = "/api/v3/allOrders"; // Please input API Endpoint you want.
var timestamp = Number(new Date().getTime()).toFixed(0);
var string = "symbol=LTCBTC×tamp=" + timestamp; // Please input query parameters for the inputterd API.
var baseUrl = "https://api.binance.com";
var signature = Utilities.computeHmacSha256Signature(string, secret);
signature = signature.map(function(e) {
var v = (e < 0 ? e + 256 : e).toString(16);
return v.length == 1 ? "0" + v : v;
}).join("");
var query = "?" + string + "&signature=" + signature;
var params = {
'method': 'get',
'headers': {'X-MBX-APIKEY': key},
'muteHttpExceptions': true
};
var data = UrlFetchApp.fetch(baseUrl + api + query, params);
Logger.log(data.getContentText())
}
ShapeApp for Google Slides was published as an add-on application
When you use Google Slides, have you ever thought about creating and updating shapes on Slides by inputting parameters, and arranging selected shapes? I have thought about them. Recently, since Class SlidesApp was added to GAS, it came to be able to easily to create various applications for Slides. So I created this. This application is add-on application which was made of GAS.
Gists
Experiment
It has investigated the differences between the documents of “Search for Files” for v2 and v3. The following table shows the comparison of v2 and v3 for “Valid fields for files.list”. The column of DriveApp.searchFiles() means whether the query can be used for DriveApp.searchFiles().
| v2 |
v3 |
Difference |
DriveApp.searchFiles() |
| title |
name |
different |
v2: succeed, v3: fail |
| fullText |
fullText |
same |
|
| mimeType |
mimeType |
same |
|
| modifiedDate |
modifiedTime |
same |
|
| lastViewedByMeDate |
viewedByMeTime |
different |
v2: succeed, v3: fail |
| trashed |
trashed |
same |
|
| starred |
starred |
same |
|
| parents |
parents |
same |
|
| owners |
owners |
same |
|
| writers |
writers |
same |
|
| readers |
readers |
same |
|
| sharedWithMe |
sharedWithMe |
same |
|
| properties |
properties |
same |
|
| properties with visibility=‘PRIVATE’ |
appProperties |
different |
v2: succeed, v3: fail |
| visibility |
visibility |
same |
|
Result
As the result, it is considered that DriveApp.searchFiles() is used as Drive API v2 yet.
ggsrun was updated to v.1.3.4
-
v1.3.4 (January 2, 2018)
- Added new option for downloading ‘bound-scripts’ of Google Sheets, Docs, or Forms file.
- When the bound-scripts are downloaded, the project name cannot be retrieved because Drive API cannot be used for the bound-scripts. So when the bound-scripts are downloaded, the project ID had been used previously. Such filename is not easily to be seen. By this additional option, users can give the filename when it downloads the bound-scripts.
- The usage is here
- Removed a bug.
- When a project is downloaded, script ID in the project is added to the top of each downloaded script as a comment. There was a problem at the character using for the comment out. This was modified.
You can check this and download ggsrun at https://github.com/tanaikech/ggsrun.
I have reported because I found a bug for scopes of Slides. The detail is the following URL.
https://issuetracker.google.com/issues/71448583
Gists
This sample script is converted this sample script (javascript) to Google Apps Script. The point for converting is signature as shown in the following sample script.
- At Bitfinex API, after
"/api/" + apiPath + nonce + rawBody is encrypted using HMAC SHA-384, the data of byte array is converted to HEX.
- In Google Apps Script, there is no the method for this.
- The data which was encrypted by
Utilities.computeHmacSignature() is the bytes array of the signed hexadecimal.
- On the other hand, at this sample script for javascript, the data which was encrypted by
crypto.createHmac('sha384', apiSecret).update(signature).digest('hex') is the string of the unsigned hexadecimal.
In order to achieve above, I made the method of bytesToHex().
RearrangeScripts was updated. Added “About” to the menu of add-on. By this, users can see the help document easily.
Gists
In this report, I would like to introduce a workaround for automatically recalculating custom functions on Spreadsheet.
1. Situation
The sample situation is below. This is a sample situation for this document.
- There are 3 sheets with “sheet1”, “sheet2” and “sheet3” of sheet name in a Spreadsheet.
- Calculate the summation of values of “A1” of each sheet using a custom function.
- Sample script of the custom function is as follows.
function myFunction(e) {
var r = 0;
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i in sheets) {
r += sheets[i].getRange(e).getValue();
}
return r;
}
2. Workaround for recalculating
When =myFunction("A1") is put in a cell, the custom function sums each “A1” of “sheet1”, “sheet2” and “sheet3”. But in this case, when “A1” of one of 3 sheets is changed, the custom function is not recalculated.
RearrangeScripts was published as an add-on application
Recently, I have reported RearrangeScripts for rearranging scripts in a GAS project. At that time, I got messages and mails from many developers. They said that you should publish this as an add-on. So, this was released. Now you can search “RearrangeScripts” as an add-on for Spreadsheet. If this is helpful for you, I’m happy.
Demo

Gists
This is a document for explaining the difference between given values and retrieved values for shapes on Google Slides. When a shape is created to a slide using Slides API, most users give the size of height and width as pt. When the size is retrieved from the created shape as pt, the size is often difference from the given size.
For example, when a square shape is created by giving the height and width of 100 pt, the size which is retrieved from the created square becomes 99.99212598425197 pt for the height and width.
Gists
This is a sample script for retrieving clientId using Google Apps Script.
var accessToken = ScriptApp.getOAuthToken();
var url = "https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=" + accessToken;
var params = {
method: "post",
headers: {"Authorization": "Bearer " + accessToken}
};
var res = UrlFetchApp.fetch(url, params).getContentText();
var clientId = JSON.parse(res).azp;
Logger.log(clientId)
Gists
This is a sample script for downloading a file using a button of dialog box on Google Docs (Spreadsheet, Document and Slides).
Please use this sample script at script editor on Google Docs (Spreadsheet, Document and Slides). And please set file ID in the script.
FLow :
The flow of this sample script is as follows.
- Run
dialog().
- When users click a download button, retrieve file ID at GAS side.
- Create download URL from the file ID. Download URL and filename are sent to
download(obj) of Javascript.
- Create a tag for downloading and click it at Javascript side.
- By this, users can download the file of file ID.
Code.gs
function dialog() {
var html = HtmlService.createHtmlOutputFromFile('download');
SpreadsheetApp.getUi().showModalDialog(html, 'Sample dialog'); // If you use other Google Docs, please modify here.
}
function getDownloadUrl() {
var id = "### file id ###";
var file = DriveApp.getFileById(id);
return {
url: file.getDownloadUrl().replace("?e=download&gd=true",""),
filename: file.getName()
};
}
download.html
<input type="button" value="download" onclick="getUrl()" />
<script>
function getUrl() {
google.script.run.withSuccessHandler(download).getDownloadUrl();
}
function download(obj) {
var d = document.createElement('a');
d.href = obj.url;
d.download = obj.filename;
d.click();
}
</script>
Gists
Introduction
Recently, I have introduced a GAS library and a CLI tool for rearranging files in GAS project. Those are RearrangeScripts and ggsrun. Because today, I found a new way for rearranging files, I would like to introduce it although there is a restriction.
By the recent Google-update, users become able to create folders in GAS project. The new way uses this. At first, please see the demonstration GIF animation.
Demo

Gists
This sample script is for retrieving an instance of user-interface environment for Spreadsheet, Document and Slides. When I create applications which use user interface (for example, sidebar, dialog and so on), the user interface can be used for Spreadsheet, Document and Slides. If the application doesn’t use the methods depend on Spreadsheet, Document and Slides, this script can give 3 choices to users.
function getUi() {
var ui;
try {
ui = SpreadsheetApp.getUi();
} catch(e) {}
try {
ui = DocumentApp.getUi();
} catch(e) {}
try {
ui = SlidesApp.getUi();
} catch(e) {}
return ui || null;
}
function main() {
var ui = getUi();
if (ui) {
ui.alert('Hello, world!');
}
}
Gists
This is a sample script for combining and mixing 2 objects. Each object is an array which included a dictionary type. When the key of the dictionary object is the same, the values are mixed.
This can be also used for Google Apps Script.
var obj1 = [
{"key1": ["value1a1", "value1a2"]},
{"key1": ["value1aa1", "value1aa2"]},
{"key2": ["value2a1", "value2a2"]},
{"key3": ["value3a1", "value3a2"]},
];
var obj2 = [
{"key1": ["value1b1", "value1b2"]},
{"key3": ["value3b1", "value3b2"]},
{"key3": ["value3bb1", "value3bb2"]},
{"key4": ["value4b1", "value4b2"]},
];
Output
[
{"key1": ["value1a1", "value1a2", "value1b1", "value1b2", "value1aa1", "value1aa2"]},
{"key2": ["value2a1", "value2a2"]},
{"key3": ["value3a1", "value3a2", "value3b1", "value3b2", "value3bb1", "value3bb2"]},
{"key4": ["value4b1", "value4b2"]}
]
Sample script :
Javascript :
function mixture(obj1, obj2) {
Array.prototype.push.apply(obj1, obj2);
var temp = [];
var res = [];
obj1.forEach(function(e, i){
temp[i] = !~temp.indexOf(Object.keys(e)[0]) ? Object.keys(e)[0] : false;
if (temp[i]) {
res.push(e);
} else {
res.forEach(function(f, j){
if (Object.keys(f)[0] == Object.keys(e)[0]) {
Array.prototype.push.apply(res[j][Object.keys(f)[0]], e[Object.keys(e)[0]]);
}
});
}
});
return res;
}
var obj1 = [
{"key1": ["value1a1", "value1a2"]},
{"key1": ["value1aa1", "value1aa2"]},
{"key2": ["value2a1", "value2a2"]},
{"key3": ["value3a1", "value3a2"]},
];
var obj2 = [
{"key1": ["value1b1", "value1b2"]},
{"key3": ["value3b1", "value3b2"]},
{"key3": ["value3bb1", "value3bb2"]},
{"key4": ["value4b1", "value4b2"]},
];
var res = mixture(obj1, obj2);
console.log(JSON.stringify(res))
CoffeeScript :
This is a sample script for coffeescript.
Gists
Introduction
By recent Google update (Google update at October 24, 2017), various new winds to GAS developers were blown. There is “Manifests” as one of the new winds. “Manifests” makes us manage the project using JSON. Especially, the special scopes which have to use OAuth2 process can be used by only setting them to the Manifests. I think that this is the largest modification. However, when scopes are added to a project using Manifests, users who use the project can use only added scopes. This means that when users create scripts in the project, if there are some scopes which is required to be added, such scopes cannot be automatically added. So the error of “Insufficient Permission” occurs.
Gists
This sample script is for retrieving the size (width and height) of a table in Google Slides using Google Apps Script.
There are no methods for directly retrieving the table size using SlidesApp yet. So I thought of a workaround using Slides API.
- When the slide information is retrieved using
Slides.Presentations.Pages.get() of Slides API, the information of tables is also included. In the information, the height and width of table are also included.
- But the unit is EMU (English Metric Unit), and the height and width is separated by each cell. So it is required to sum each height and width while modifying the unit.
The modified script reflected this is as follows.
Gists
By recent Google updated, Class SlideApp is added to Google Slides. SlideApp will be bring a lot of applications. Here, I would like to introduce 2 samples.
function showSidebar() {
var html = HtmlService
.createHtmlOutput('Hello, world! <input type="button" value="Close" onclick="google.script.host.close()" />')
.setTitle('My custom sidebar')
.setWidth(300);
SlidesApp.getUi().showSidebar(html);
}
2. Copy slides in existing Slide to a new Slide
This sample script create a new Slide with slides you want to copy.
Overview
This is a GAS application for rearranging Google Apps Scripts (GAS) in a project which can be seen at the script editor.
Description
Have you ever thought about rearranging Google Apps Scripts in a project which can be seen at the script editor? I also have thought about it. Finally, I could find the workaround to do it. And recently, I have given this function to ggsrun which is a CLI tool. Furthermore, I thought that if there is a GUI application for rearranging scripts in a project, it may be useful for more users. So I created this. Today, I published this as a GUI tool using Google Apps Script. If this was useful for you, I’m glad.
Overview
This is a library for zipping a folder using Google Apps Scripts.
Description
When users manually download a folder on Google Drive, users can download all files in the folder as a zip file using the web interface. There are zip tools in Class Utilities of Google Apps Script. However, the zip tools cannot create a zip file from a folder. And it cannot retrieve all files included any folders in a folder. So I created this. This library works like almost the same to the web interface using GAS.
Overview
This is a Manifests library for Google Apps Scripts.
Description
By recent update of Google, Manifests was added to Google Apps Script Project. At the moment I saw the detail, I thought that this Manifests will blow a new wind for a lot of GAS developers. So I created this.
This library makes users easily access Manifests using Google Apps Script. If this was useful for you, I’m glad.

Overview
This is a GAS project library for Google Apps Script (GAS).
Description
There are Class SpreadsheetApp and Class DocumentApp for operating spreadsheet and document, respectively. But there is no Class for operating GAS project. If there is the Class ProjectApp, GAS project can be directly operated by GAS script. I thought that this will lead to new applications, and created ProjectApp.
On the other hand, as a CLI tool for operating GAS project, there has already been ggsrun.
Gists
This is a sample script for uploading local file to Google Drive without the authorization using HTML form. A selected file in your local PC using HTML form is uploaded to Google Drive and saved to Google Drive.
When you use this, at first, please deploy Web Apps. The script is doPost() of following scripts.
Script : Google Apps Script
function doPost(e) {
var data = Utilities.base64Decode(e.parameters.data);
var blob = Utilities.newBlob(data, e.parameters.mimetype, e.parameters.filename);
DriveApp.createFile(blob);
var output = HtmlService.createHtmlOutput("<b>Done!</b>");
output.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
return output;
// return ContentService.createTextOutput("Done.") <--- Here, an error occurred.
}
Flow :
- Retrieve data, filename and mimetype as
e.parameters.data, e.parameters.filename and e.parameters.mimetype, respectively.
- Decode the data using
Utilities.base64Decode().
- Create blob using
Utilities.newBlob().
- Create the file in the root folder of Google Drive.
Script : HTML
https://script.google.com/macros/s/#####/exec is the URL obtained when the Web Apps was deployed. Please replace it to your Web Apps URL. You can open this HTML for the browser of your local PC.
It was found that you can also create new project with your original Manifests using ggsrun. By using this, for example, when you created new project, the project can have libraries, Advanced Google Services and so on at the initial stage. I think that this can be used as a template for Project.
$ ggsrun u -pn [Project name] -f appsscript.json
https://github.com/tanaikech/ggsrun/blob/master/help/README.md#ModifyManifests

You can check this and download ggsrun at https://github.com/tanaikech/ggsrun.
ggsrun was updated to v.1.3.3
Awesome points of Manifests :
Awesome points of Manifests that I think are below.
Gists
This sample script is for measuring the execution time of built-in functions for Google Spreadsheet. Unfortunately, there are not measurement tools for retrieving the execution time of built-in functions. So I thought of about a workaround.
Flow :
- Import a value to a cell. The value is anything good, because this is used as a trigger. Please do this by yourself.
- Custom functions cannot use
setValue(). So I used onEdit().
func1() imports a formula that you want to measure the execution time by the script launched by the trigger.
- At
func2(), after set the formula, the measurement is started. The confirmation when built-in function was completed is carried out using loop.
- By measuring the cost per one call for
getValue(), it was found that that was about 0.0003 s. So I thought that this can be used.
- The result of measurement can be seen at Stackdriver as milliseconds.
Sample script :
function func1(range, formula) {
range.setFormula(formula);
}
function func2(range) {
var d = range.getValue();
while (r == d) {
var r = range.getValue();
}
}
function onEdit() {
var formula = '### Built-in function ###'; // Set the built-in function you want to measure.
var label = "Execution time for built-in functions.";
var ss = SpreadsheetApp.getActiveSheet();
var cell = ss.getActiveCell();
var range = ss.getRange(cell.getRow(), cell.getColumn());
func1(range, formula);
console.time(label);
func2(range);
console.timeEnd(label);
}
Note :
- When built-in functions with very long time is measured, an error may occur at
getValue().
- In my environment, the built-in function for 10 seconds worked fine.
Gists
This sample script is for straightening elements in 2 dimensional array using Google Apps Script (GAS). When applications using Spreadsheet are developed by GAS, it usually uses 2 dimensional array by setValues(). And the lengths of each element are required to be the same. On the other hand, data used for the applications might not be the same length for each element in 2 dimensional array. This sample script can be used under such situation.
ggsrun was updated to v.1.3.2

Gists
onEdit(e) which is used for the Edit event on Spreadsheet has the old value as e.oldValue. The specifications for this are as follows.
- When an user edited a single “A1” cell,
e of onEdit(e) shows hoge for e.oldValue and fuga for e.value.
- When an user edited the “A1:A2” multiple cells,
e.oldValue and e.value of onEdit(e) are not shown anything.
- When an user copied and pasted from other cell,
e.oldValue and e.value of onEdit(e) are not shown anything.
This sample script was created to retrieve both the edited values and the old values for the range of edited cells. This is the modified e.oldValue.
OnedriveApp was updated to v1.1.0.
From this version, retrieving access token and refresh token became more easy.

GitHub of OnedriveApp
Gists
This is a sample script for selecting files in Google Drive using HTML select box for Google Apps Script.
Feature
Feature of this sample.
- It is a simple and space saving.
- When the folder is selected, the files in the folder are shown.
- When the file is selected, the ID of file is retrieved. Users can use this ID at GAS.
- When a folder is opened, all files in the folder are cached. By this, the second access of the folder is faster.
- It doesn’t retrieve all files in Google Drive at once, so the read of files from Google Drive becomes the minimum necessary.
I will use this for applications that users need to select files on Google Drive.
ggsrun was updated to v.1.3.1
- Recently, when scripts on local PC is uploaded to Google Drive as a new project, the time to create on Google became a bit long. (I think that this is due to Google Update.) Under this situation, when the script is uploaded, the timeout error occurs while the new project is created using the script. So the time until timeout of fetch was modified from 10 seconds to 30 seconds. By this, when the script is uploaded, no error occurs and the information of the created project is shown.
- You can create a new project on Google Drive using scripts on local PC. The sample command is
ggsrun u -f sample.gs1,sample2.gs,sample3.html -pn newprojectname
You can check this and download ggsrun at https://github.com/tanaikech/ggsrun.
Gist
This sample script is for uploading image files to Slack using Incoming Webhooks by Google Apps Script.
When users try to upload image files to Slack using Incoming Webhooks, it has been known that although the access token is required to directly upload them, Incoming Webhooks can upload them by using the tag of image_url. In this sample script, it uploads image files (BMP, GIF, JPEG and PNG) on Google Drive to Slack using Incoming Webhooks. The script is written by Google Apps Script.
Gists
This sample script is for retrieving files with filename included special characters using Google Apps Script. The files are used on Google Drive.
The files with filename of special characters cannot be retrieved using DriveApp.getFilesByName(). This workaround solved this.
As a query parameter, name contains 'filename with special characters' is used. This contains is very important. name='filename with special characters' cannot retrieve such files. Today, it was found that name contains 'filename with special characters' is the workaround. I have been looking for this workaround for a while. Finally, I found this today. By using this method, filename included umlauts can be also retrieved.
Here, it introduces an application of Retrieving Spreadsheet ID from Range using Google Apps Script.
Please check this. https://github.com/tanaikech/getSpreadsheetByRange
Gists
This is a sample script for retrieving spreadsheet ID from a range using Google Apps Script. I sometimes want to retrieve spreadsheet ID from ranges. In such case, I always use this.
- Range
- -> Retrieve Sheet using
getSheet()
- -> Retrieve Spreadsheet using
getParent()
- -> Retrieve spreadsheet ID
var id = "123456789abcdefg";
var sheet = "Sheet";
var cells = "a1:b10";
var range = SpreadsheetApp.openById(id).getSheetByName(sheet).getRange(cells);
var id = range.getSheet().getParent().getId();
>>> id ---> 123456789abcdefg
ggsrun was updated to v.1.3.0
- From this version, container-bound scripts can be downloaded. The container-bound script is the script created at the script editor on Google Sheets, Docs, or Forms file.
- In order to download container-bound scripts, the project ID of container-bound scripts is required. The project ID can be retrieved as follows.
- Open the project. And please operate follows using click.
- -> File
- -> Project properties
- -> Get Script ID (This is the project ID.)
- When a project is downloaded, the filename of HTML file had become
.gs. This bug was modified.
The usage is here.
Gists
This is a sample script for retrieving values by header title for Spreadsheet. This is created by Google Apps Script. The main script is as follows.
Main script :
When the instance is retrieved, all data of the sheet is analyzed. So when the each value is retrieved, the speed is fast.
function GetValueByKey(sheetname) {
return new getValueByKey(sheetname);
};
(function(r) {
var getValueByKey;
getValueByKey = (function() {
getValueByKey.name = "getValueByKey";
function getValueByKey(sheetname) {
var alldata, e, header, ss;
try {
ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetname);
} catch (error) {
e = error;
throw new Error("Error: No sheetname (" + sheetname + ").");
}
alldata = ss.getDataRange().getValues();
header = alldata[0];
alldata.shift();
this.manageddata = (function(header, alldata) {
var i, j, k, key, len, len1, result, temp, value;
result = [];
for (j = 0, len = alldata.length; j < len; j++) {
value = alldata[j];
temp = {};
for (i = k = 0, len1 = header.length; k < len1; i = ++k) {
key = header[i];
temp[key] = value[i];
}
result.push(temp);
}
return {
values: result,
headerLength: header.length,
dataLength: alldata.length
};
})(header, alldata);
}
getValueByKey.prototype.getValue = function(index, key) {
return this.manageddata.values[index][key];
};
getValueByKey.prototype.getAllValues = function() {
return this.manageddata;
};
return getValueByKey;
})();
return r.getValueByKey = getValueByKey;
})(this);
Demo
Following sheet is a sample sheet for this.

OnedriveApp was updated to v1.0.2.
Moved the instance of PropertiesService.getScriptProperties() to outside of this library. When there is the PropertiesService.getScriptProperties() inside the library, it was found that the parameters that users set was saved to the library. So this was modified. I’m sorry that I couldn’t notice this situation.
GitHub of OnedriveApp
OnedriveApp was updated to v1.0.1.
Added a method for retrieving access token and refresh token using this library.
By added this method, OneDrive APIs can be used by only this library.
GitHub of OnedriveApp
Gists
This sample script is for changing values by checking duplicated values of JSON for Javascript.
Please see the following script. There is an array with a JSON data with 3 keys and 3 values. It is found that the values for each element duplicate. These duplicated values are changing by adding numbers.
I use this for managing filenames. This script also can be used for Google Apps Script. If this was useful for you, I’m glad.
ImgApp was updated to v1.2.0. New method was added.
3. updateThumbnail()
Overview
This method is for updating thumbnail of files on Google Drive using images you selected.
Description
For example, zip files don’t have the thumbnail on Google Drive. An icon is shown as the thumbnail. For the most files, Google Drive can create automatically each thumbnail. But there are sometimes files which cannot be created the thumbnail. Zip file is also one of them. In order to add and update thumbnails to such files, I added this method.
This is a library of Google Apps Script for using Microsoft OneDrive.
Feature
This library can carry out following functions using OneDrive APIs.
- Retrieve file list on OneDrive.
- Delete files and folders on OneDrive.
- Create folder on OneDrive.
- Download files from OneDrive to Google Drive.
- Upload files from Google Drive to OneDrive.
Demo

You can see the detail information here https://github.com/tanaikech/OnedriveApp
Gists
Updated: January 22, 2023
This sample script is for the interconversion between Google Docs (document, spreadsheet and presentation) and Microsoft Docs (word, excel and powerpoint). The feature is to convert them without Advanced Google Services.
Since Advanced Google Services is not used for this, if you publish your script with this script, you are not necessary to explain how to install Advanced Google Services. This script converts between Google Docs and Microsoft Docs using UrlFetchApp.fetch(). Although Drive API v3 is used, Drive API is automatically enabled by the recent update on Google. Ref (I’m sorry. This is Japanese language.) So you are not necessary to explain about the use of Drive API. By this, users will be easy to use the scripts that Drive API is used. This is very important for a lot of users.
Gist
Overview
This GAS sample is for retrieving access token to use OneDrive APIs using Google Apps Script.
In this script, the authorization code is automatically retrieved.
Demo

Usage
In order to use this, both accounts of Google and OneDrive (MSN) are required.
Google side
- Copy and paste the sample script to your script editor. You can use the standalone script for this.
- Deploy Web Apps.
- On the Script Editor
- File
- -> Manage Versions
- -> Save New Version
- Publish
- -> Deploy as Web App
- -> At Execute the app as, select “your account”
- -> At Who has access to the app, select “Only myself”
- -> Click “Deploy”
- -> Copy URL of “latest code” (This is important!)
- -> Click “OK”
- URL of “latest code” is
https://script.google.com/macros/s/###/dev. So please modify this URL. Replace from “dev” to “usercallback” for the URL. And copy this modified URL.
- From :
https://script.google.com/macros/s/###/dev
- To :
https://script.google.com/macros/s/###/usercallback
OneDrive side
- Log in to Microsoft Azure portal.
- Search “Azure Active Directory” at the top of text input box. And open “Azure Active Directory”.
- Click “App registrations” at the left side bar.
- In my environment, when I used Chrome as the browser, no response occurred. So in that case, I used Microsoft Edge.
- Click “New registration”
- app name: “sample app name”
- Supported account types: “Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)”
- Redirect URI (optional): Web
- URL:
https://script.google.com/macros/s/###/usercallback
- Click “Register”
- Copy “Application (client) ID”.
- Click “Certificates & secrets” at the left side bar.
- Click “New client secrets”.
- After input the description and select “expire”, click “Add” button.
- Copy the created secret value.
By above operation, the preparation is done.
Gists
When it uses Google Sheets API v4, GridRange is used for it as the range property. These sample scripts are for converting from a1Notation to GridRange. You can chose from following 2 scripts. Both scripts can retrieve the same result.
Script 1 :
This is from me.
function a1notation2gridrange1(sheetid, a1notation) {
var data = a1notation.match(/(^.+)!(.+):(.+$)/);
var ss = SpreadsheetApp.openById(sheetid).getSheetByName(data[1]);
var range = ss.getRange(data[2] + ":" + data[3]);
var gridRange = {
sheetId: ss.getSheetId(),
startRowIndex: range.getRow() - 1,
endRowIndex: range.getRow() - 1 + range.getNumRows(),
startColumnIndex: range.getColumn() - 1,
endColumnIndex: range.getColumn() - 1 + range.getNumColumns(),
};
if (!data[2].match(/[0-9]/)) delete gridRange.startRowIndex;
if (!data[3].match(/[0-9]/)) delete gridRange.endRowIndex;
return gridRange;
}
Script 2 :
String.prototype.to10 was used for this script. String.prototype.to10 is from Alexander Ivanov. I think that String.prototype.to10 is a clever solution.
Gist
These sample scripts are for requesting multipart post using Google Apps Script.
In most cases, the multipart request is used for uploading files. So I prepared 2 sample situations as follows. For each situation, the request parameters are different.
- Upload a file from Google Drive to Slack.
- Convert an excel file to Spreadsheet on Google Drive using Drive API v3.
Multipart post is required for these situations.
1. Uploading Files From Google Drive To Slack
Curl Code
In order to use this sample, please retrieve access token for uploading file to Slack.
Gist
This is a sample script for retrieving images on Spreadsheet.
Unfortunately, there are no methods for retrieving directly images on spreadsheet using GAS. So I use the method which retrieves URL from =image(URL) and retrieves the image from the URL.
In this case, =image(URL) has to be in the cell. Images embedded by insertImage() cannot be retrieved.
At first, please confirm them.
Sample script :
var cell = "A1"; // Cell address with the function of "=image()"
var filename = "samplename"; // Output filename
var image = SpreadsheetApp.getActiveSheet().getRange(cell).getFormula();
var blob = UrlFetchApp.fetch(image.match(/\"(.+)\"/)[1]).getBlob();
DriveApp.createFile(blob.setName(filename));
Flow :
- Retrieve
=image(URL) using getFormula().
- Retrieve URL from
=image(URL).
- Retrieve file blob using
UrlFetchApp.fetch() from the URL.
- Output the file blob as a file.
This sample is for retrieving array coordinates of duplicated elements.
Script :
var inputdata = ["a", "b", "b", "c", "d", "c", "e", "a", "f", "g"];
var dic = {};
var result = [];
inputdata.forEach(function(e, i){
if (dic[e]) {
result[i] = 'Duplicated';
} else {
result[i] = null;
}
dic[e] = "temp";
});
Logger.log(JSON.stringify(result))
Logger.log([i for (i in result) if(result[i]=='Duplicated')])
Result :
[null,null,"Duplicated",null,null,"Duplicated",null,"Duplicated",null,null]
[2, 5, 7]
Gists
This is a sample of Google Apps Script. This script is for retrieving all files and folders under a folder on Google Drive. All files and folders in the specific folder can be retrieved.
If you want to retrieve file list with all files and folders on Google Drive, please use DriveApp.getRootFolder().getId() as folderId.
When there are a lot of files in the folder, it may be over the limitation time to execute script.
ggsrun was updated to v.1.2.2
- For Google Docs (spreadsheet, document, slide and drawing), since I noticed that the revision files would not be able to be retrieved using Drive API v3, I modified this using new workaround.
- The new workaround is to use Drive API v2.
drive.revisions.get of Drive API v2 can retrieve not only the revision list, but also the export links. I thought of the use of the export links. This became the new workaround.
- For the files except for Google Docs, the revision files can be retrieved using Drive API v3.
- The usage is here.
I don’t know when this workaround will not be able to be used. But if this could not be used, I would like to investigate of other method.
Gist
Overview
This is a sample script for creating the pseudo browser using Google Spreadsheet.
Description
I unexpectedly noticed this. I think that this is for off-line browsing using HTML data. So there are many limitations. At first, please confirm them.
- Limitations
- It cannot move from opened site to other outside site. If the outer site is opened as a new wind, your own browser is opened and move there.
- For URL, it can move directories which is one low. But it cannot move directories more than two deeper.
- Because it retrieves the HTML data from the inputted URL using
UrlFetchApp. It cannot move to the out side of data retrieved by UrlFetchApp.
- The access to the site opened by inputting URL is run at Google side.
- Javascript on the opened site is run at your local PC side.
User-Agent cannot be changed from Mozilla/5.0 (compatible; Google-Apps-Script).
What I thought the interesting is that the appearance of the site has been maintained at this pseudo browser. And, by using this, the sites which are slow speed at your environment might be able to be opened smoothly.
Gist
This is a sample script for downloading files from Google Drive under no authorization using browser. By using this sample, you can make other users download files from your Google Drive. Even if the other users are not Google users, they can download the files.
Demo

This is a demonstration for downloading files from Google Drive under no authorization using browser. From the top document, You can see that an user who is not owner of Google Drive is downloading files.
ImgApp was updated to v1.1.0. New method was added.
2. doResize()
Overview
This method is for resizing images.
Description
Unfortunately, there are no methods to resize images at Google Apps Script. As a workaround, there is a method that it imports the image in Google Document and resizes the image using setWidth() and setHeight(). But in this method, the resized blob cannot be retrieved. So although I had thought of other workaround, I had not been able to find it. Recently, I accidentally discovered the other workaround doResize(). Since it was found that this workaround can be surely used, I added this to ImgApp.
1. getSize()
Overview
This method is for retrieving the width and height of image as the unit of pixel.
Description
Unfortunately, there are no methods to directly retrieve the image size at Google Apps Script. As a workaround, there is a method that it imports the image in Google Document and retrieves the size using getWidth() and getHeight(). But in this method, it uses much time and resources on Google. So I thought of retrieving the information of image at the binary level, and created this. By this, the low process cost could be achieved.
Gists
This sample is for retrieving access token for Google APIs. I created this for studying newStateToken().
Preparation
In order to use this sample, please do as follows.
- Deploy and launch Web Apps for retrieving redirect uri
- On the Script Editor
- File
- -> Manage Versions
- -> Save New Version
- Publish
- -> Deploy as Web App
- -> At Execute the app as, select “your account”
- -> At Who has access to the app, select “Only myself”
- -> Click “Deploy”
- -> Click “latest code” (By this click, it launches the authorization process.)
- -> Please copy URL shown in the top of your browser as the redirect URI. And please modify the redirect URI like
https://script.google.com/macros/s/#####/usercallback.
- Open console project
- On the Script Editor
- -> Resources
- -> Cloud Platform Project
- -> Click “Projects currently associated with this script”
- -> Click API in start guide
- Retrieve client id and client secret
- On the Console Project
- Click authentication information at left side
- -> Create a valid Client ID as OAyth client ID
- -> Choose Web Application
- -> Input Name (This is a name you want.)
- -> Input redirect URI that you have already copied.
- -> done
- -> Please copy client ID and client Secret in a pop-up window.
Here, you have client ID, client Secret and redirect URI to retrieving refresh token and access token. These can be used for following sample script.
SOUWA means summing in Japanese. SOUWA can sum string elements in an array at the high speed. The speed of SOUWA with the pyramid algorithm is about 380 times faster than that of the standard method. New algorithm for summing array elements was developed for SOUWA. You can see the detailed report of this library at here. If you are interested in this, I’m glad.
It was updated to v1.0.2. Please check it out. https://github.com/tanaikech/SOUWA_GAS
This sample script is for searching route between place A and B and embedding a map by custom function on Spreadsheet.
I think that this method is one of various ideas.
Problem
When the map is embedded to a cell on spreadsheet as an image, the function =IMAGE() is suitable for this situation. However, Class Maps, setFormula() for importing =IMAGE() and DriveApp.createFile() for creating images from maps also cannot be used for custom functions.
This sample script is for retrieving parameters from a chart. The chart created by both Google Apps Script and manually operation can be used.
Creates Chart
When a chart is created, it supposes following parameters.
var parameters = {
"title": "x axis",
"fontName": "Arial",
"minValue": 0,
"maxValue": 100,
"titleTextStyle": {
"color": "#c0c0c0",
"fontSize": 10,
"fontName": "Roboto",
"italic": true,
"bold": false
}
};
.setOption('hAxis', parameters)
Retrieve Parameters From Chart
For the chart created by above parameters, in order to retrieve the parameters, it uses following script.
Description
There are a limit executing time for Google Apps Script (GAS). It’s 6 minutes. So users have to pay attention to the process cost of the script. GAS can use JavaScript 1.7. This means to be able to be used comprehension for GAS.
In this report, the process cost for the comprehension has been investigated. The normal for loop was used as the competitor. As a result, it was found that the comprehension can be used one of methods for reducing the process cost. For 1 dimensional array, the process cost of comprehension is about 60% lower than that of the normal one. For 2 dimensional array, the process cost of comprehension is about 50% lower than that of the normal one. Each data is the average for 10 times measurements.
This sample script is for embedding animation GIF in a cell using custom function on Spreadsheet.
I think that this method is one of various ideas.
Problem
There are some limitations.
- Images of jpeg and png can be embedded in a cell using
=IMAGE(). But when animation GIF is embedded using it, GIF is not played.
insertImage() can insert the animation GIF to sheet. But it is not imported to one cell. It floats on several cells.
- In order to float the animation GIF on one cell, the size of GIF has to be retrieved. But the size of image cannot be retrieved at spreadsheet APIs.
=IMAGE() and insertImage() cannot be used by custom functions.
Solution
I thought a method to floating an animation GIF on one cell using insertImage(). By this, I thought that it will be easy to use as a sheet with GIF images.
This sample script performs OCR and imports resultant text to a cell using custom function on Spreadsheet.
Drive API has a function to do OCR. It was used for this sample.
I think that this method is one of various ideas.
Problem
When OCR is performed and imported the result to a cell on spreadsheet, there are some limitations. DriveApp, UrlFetchApp, setFormula() cannot be used for custom functions.
Solution
In order to avoid these limitations, I used Web Apps. From previous research, it has been found that Web Apps can avoid various limitations. Also in the case of this situation, Web Apps could avoid the above limitations.
This sample retrieves all files in a folder with spreadsheet. When there are some folders in the folder with spreadsheet, this script can retrieve all files in all folders. This script has to be a container-bound script for spreadsheet.
Script :
function getFileList(){
var folderlist = (function(folder, folderSt, results){
var ar = [];
var folders = folder.getFolders();
while(folders.hasNext()) ar.push(folders.next());
folderSt += folder.getId() + "#_aabbccddee_#";
var array_folderSt = folderSt.split("#_aabbccddee_#");
array_folderSt.pop()
results.push(array_folderSt);
ar.length == 0 && (folderSt = "");
for (var i in ar) arguments.callee(ar[i], folderSt, results);
return results;
})(DriveApp.getFolderById(
DriveApp.getFileById(
SpreadsheetApp.getActiveSpreadsheet().getId()
).getParents().next().getId()
),"",[]);
var filelist = [];
for (var i in folderlist){
var folderid = folderlist[i][folderlist[i].length - 1];
var temp = [];
var folder = DriveApp.getFolderById(folderid);
var files = folder.getFiles();
var foldername = folder.getName();
while(files.hasNext()){
var file = files.next();
temp.push([foldername, file.getName()]);
}
filelist.push(temp);
}
return Array.prototype.concat.apply([], filelist);
}
function main() {
var data = getFileList();
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
ss.getRange(1,1,data.length,data[0].length).setValues(data);
}
Result :

This sample script embeds a map to a cell using custom function on Spreadsheet.
I think that this method is one of various ideas.
Problem
When the map is embeded to a cell on spreadsheet as an image, the function =IMAGE() is suitable for this situation. However, setFormula() for importing =IMAGE() and DriveApp.createFile() for creating images from maps also cannot be used for custom functions.
Solution
In order to avoid these limitations, I used Web Apps. From previous research, it has been found that Web Apps can avoid various limitations. Also in the case of this situation, Web Apps could avoid the above limitations.
ggsrun was updated to v.1.2.1
- Configuration file (
ggsrun.cfg) became to be able to be read using the environment variable.
You can check this at here.
This sample script embeds a chart to a cell using custom function on Spreadsheet.
I think that this method is one of various ideas.
Problem
When you want to create a chart and embed it to a cell using custom functions, you notice that insertChart() cannot be used. There are some limitations for using custom functions. But insertChart() creates floating charts. So in order to embed a chart to a cell, the function =IMAGE() is suitable for this situation. Here, setFormula() for setting =IMAGE() and DriveApp.createFile() for creating images from charts also cannot be used for custom functions.
This sample script converts from Microsoft Docx File on Google Drive to Google Spreadsheet, and converts to HTML file.
Drive APIs v2 and v3 are used for this. Please set as follows.
“Drive API v2” can be used at Google Apps Script by enabling Drive API of Advanced Google services and of Google API Console.
How to use it is as follows.
-
In the script editor, select Resources > Advanced Google services
ggsrun was updated to v.1.2.0
- Added a command for retrieving revision files on Google Drive.
- Some modifications.
You can check this at here.
Sample data
This is a sample data for this sample script. The column B was created by the normal distribution formula, and the column C was created by multiplying random number for column B.
A, B, C
1.0, 0.0001, 0.0000
1.5, 0.0009, 0.0006
2.0, 0.0044, 0.0037
2.5, 0.0175, 0.0133
3.0, 0.0540, 0.0236
3.5, 0.1296, 0.0533
4.0, 0.2420, 0.0073
4.5, 0.3522, 0.2468
5.0, 0.3990, 0.0843
5.5, 0.3522, 0.3352
6.0, 0.2420, 0.2201
6.5, 0.1296, 0.0607
7.0, 0.0540, 0.0256
7.5, 0.0175, 0.0006
8.0, 0.0044, 0.0030
8.5, 0.0009, 0.0005
9.0, 0.0001, 0.0001
Create chart
createChart() creates a chart from data. A chart with 2 lines is created by this method.
This sample script sends an e-mail, when spreadsheet was edited from outside by Sheet API v4. When you use this sample, please create a container bound script with spreadsheet which is edited by Sheet API. And please input your e-mail and run firstly a method of createTrigger(). By this, a trigger is installed as onChange(). After this, edit spreadsheet from outside by Sheet API v4.
When when spreadsheet was edited from outside by Sheet API v4, I used sendEmail() as a sample, because script editor is closed.
Overview
In this article, I would like to introduce how to transfer files for Google Drive under no authorization.
This has also been published here. https://github.com/tanaikech/FileTransfer
Description
When we download and upload files for Google Drive, it usually has to use Drive API. In order to use Drive API, access token is required. If you want to make your friends download and upload files for your Google Drive, the authorization process is to take time. So I proposal this.
This script changes slack status using GAS. If you want to change it on time you decided, it can be achieved by installing this method as a trigger.
In order to use this, the required scope is users.profile:write.
function setSlackStatus(token, user, status_text, status_emoji) {
return UrlFetchApp.fetch(
'https://slack.com/api/users.profile.set',
{
method: 'post',
payload: {
token: token,
user: user,
profile: JSON.stringify({status_text: status_text, status_emoji: status_emoji})
},
muteHttpExceptions: true
}
).getContentText();
}
function main() {
var res = setSlackStatus(
'### Your access token ###',
'### User ID ###',
'sample',
':coffee:'
);
Logger.log(res)
}
This sample script retrieves the user information which is editing the shared spreadsheet.
It was found as follows.
- User information retrieving by Class Session is the owner and users which installed triggers by themselves.
- When each user installs a trigger, user information retrieving by Class Session losts the accuracy. So user information has to be retrieved using a temporally installed trigger.
- Using
onOpen(), it cannot directly install triggers and authorize.
- Using menu bar, it can install triggers and authorize Google Services using API.
Here, I thought 2 problems.
Overview
This is a CLI tool to execute Google Apps Script (GAS) on a terminal.
Motivation
Will you want to develop GAS using CoffeeScript on your local PC? Generally, when we develop GAS, we have to login to Google using own browser and develop it using Javascript on the Script Editor. Recently, I have wanted to have more convenient local-environment for developing GAS. So I created this “ggsrun”.

The detail information and how to get this are https://github.com/tanaikech/ggsrun.
This sample script converts a spreadsheet to excel file, and overwrites the excel file to the existing excel file. When you use this script, at first, please confirm whether Drive API is enabled at Google API console. Because the existing excel file is overwritten, the file name and file ID are not changed.
function overWrite(src_spreadsheetId, dst_excelfileId) {
var accesstoken = ScriptApp.getOAuthToken();
return UrlFetchApp.fetch(
"https://www.googleapis.com/upload/drive/v3/files/" +
dst_excelfileId +
"?uploadType=multipart",
{
method: "PATCH",
headers: {Authorization: "Bearer " + accesstoken},
contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
payload: function(a, s) {
return UrlFetchApp.fetch(
"https://www.googleapis.com/drive/v3/files/" +
s +
"/export?mimeType=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
{
method: "GET",
headers: {Authorization: "Bearer " + a},
muteHttpExceptions: true
}
).getBlob().getBytes();
}(accesstoken, src_spreadsheetId)
}
).getContentText();
}
Converting Spreadsheet to PDF
This sample script converts from a spreadsheet to a PDF file which has all sheets in the spreadsheet. When you use this, please enable Drive API at Google API console.
var spreadsheetId = "#####";
var folderId = "#####";
var outputFilename = "#####";
DriveApp.getFolderById(folderId)
.createFile(UrlFetchApp.fetch(
"https://www.googleapis.com/drive/v3/files/" +
spreadsheetId +
"/export?mimeType=application/pdf",
{
method: "GET",
headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
})
.getBlob())
.setName(outputFilename);
Recently, I had been looking for creating an image from coordinate data. Unfortunately I have never found them. So I made this. This Google Apps Script (GAS) library creates an image file from coordinate data.
You can see the detail information at https://github.com/tanaikech/CreateImg.
There is a part where I would like to improve in this library. That’s convByteSlice(). I think that there is the method to be faster about the part. If you know much about the logical operation using GAS, if you teach me about the improvements. I’m so glad.
Here, I would like to introduce a comprehension of GAS.
Input :
var data = [[[0], [1], [2], [3]], [[4], [5], [6], [7]]];
Output :
[[0.0, 2.0], [0.0, 2.0]]
Pattern 1
var a = [];
for (var i=0; i<data.length; i++) {
var temp = [];
for (var j=0; j<data[i].length; j++) {
if (data[i][j][0] % 2 == 0) temp.push(j);
}
a.push(temp);
}
Logger.log(a)
Pattern 2
var b = [];
data.forEach(function(e1){
var temp = [];
e1.forEach(function(e2, i2){
if (e2[0] % 2 == 0) temp.push(parseInt(i2, 10));
});
b.push(temp);
});
Logger.log(b)
Pattern 3
var c = [[parseInt(i, 10) for (i in e) if (e[i][0] % 2 == 0)] for each (e in data)];
Logger.log(c)
GAS can use JavaScript 1.7. So it can write as above.
These scripts can be executed on Script Editor. But, in order to use these, you have to enable Drive API of Advanced Google services and of Google API Console. “Drive API v2” can be used at Google Apps Script by enabling Drive API of Advanced Google services and of Google API Console.
How to use it is as follows.
-
In the script editor, select Resources > Advanced Google services
-
In the dialog that appears, click the on/off switch for Drive API v2.
This is a sample GAS script to create an Excel file, which was downloaded from web, as Spreadsheet. By using Drive API, it can be achieved without access token.
Script :
function downloadFile(fileURL, folder) {
var filename = fileURL.match(".+/(.+?)([\?#;].*)?$")[1];
var response = UrlFetchApp.fetch(fileURL);
var rc = response.getResponseCode();
var blob = response.getBlob();
var resource = {
"mimeType": "application/vnd.google-apps.spreadsheet",
"parents": [{id: folder}],
"title": filename
};
var res = Drive.Files.insert(resource, blob);
var fileInfo = [rc, res.title, blob.getBytes().length, res.id];
return fileInfo;
}
Result :
[
200,
sample.xlsx,
10000.0,
## file id ##
]
There are a lot of APIs on Google. When we use Google Drive APIs, they usually have “fields” as a resource. The parameter “fields” gives various information which is selected to us. This is one of important parameters. And this can be used at Google Apps Script (GAS) although that version is v2. About how to use it, there are some documents. But it is difficult to find how to use it at GAS. So I would like to write down here as a memorandum. Most parameters for APIs have to be expressed as JSON. However, the expressions are different for each API. I would like to introduce this using some samples. This is for GAS.
This is a sample script of GAS for converting file name to file id on Google Drive. Drive API is used for this. So please enable Drive API at Advanced Drive Services and Google API Console.
function nameToId(filename){
return [i.id for each (i in Drive.Files.list({q: "title='" + filename + "' and trashed=false"}).items)];
}
Overview
In this article, files can be downloaded without authorization.
Description
When we download files from Google Drive, it usually has to use Drive API. In order to use Drive API, access token is required. If you want to make your friends download files from your Google Drive, the authorization process is to take time. Also Web Link for each files can be used. But it has to set for each files. So I proposal this.
This is a sample script for creating a folder tree including all folders in Google Drive. For each element, parent folder and sub folder are retrieved.
Script :
var results = (function(folder, folderSt, results){
var ar = [];
var folders = folder.getFolders();
while(folders.hasNext()) ar.push(folders.next());
folderSt += folder.getName() + "(" + folder.getId() + ")#_aabbccddee_#";
var array_folderSt = folderSt.split("#_aabbccddee_#");
array_folderSt.pop()
results.push(array_folderSt);
ar.length == 0 && (folderSt = "");
for (var i in ar) arguments.callee(ar[i], folderSt, results);
return results;
})(DriveApp.getRootFolder(),"",[]);
Result :
[
[foldername1(folder1 id)],
[foldername1(folder1 id), sub foldername1s(sub folde1s id)],
[foldername1(folder2 id)],
[foldername2(folder2 id), sub foldername2s1(sub folde2s1 id)],
[foldername2(folder2 id), sub foldername2s1(sub folde2s1 id), sub foldername2s2(sub folde2s2 id)]
]
By the way :
ar.length == 0 && (folderSt = "");
if (ar.length == 0) {
folderSt = "";
}
Both scripts are the same meaning.
This is a script to export a CSV file from spreadsheet and make an user download it. When the users download it, they can download by push a button made by this script.
In order to use this script, put both HTML and script in a GAS project.
html :
This file name is “download.html”.
<!DOCTYPE html>
<html>
<body>
Download CSV?
<form>
<input type="button" value="ok" onclick="google.script.run
.withSuccessHandler(executeDownload)
.saveAsCSV();" />
</form>
</body>
<script>
function executeDownload(url) {
window.location.href = url;
}
</script>
</html>
Script :
This is a script to send e-mail with a xlsx file converted from spreadsheet as an attachment file. Access token is necessary to use this script.
function excelSender() {
var accesstoken = "[your accesstoken]";
var sheetID = "[sheet id]";
var xlsxName = "[output xlsx file name]"
var params = {
"headers" : {Authorization: "Bearer " + accesstoken},
"muteHttpExceptions" : true
};
var dUrl = "https://www.googleapis.com/drive/v3/files/" + sheetID + "/export?mimeType=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
var xlsxlFile = UrlFetchApp.fetch(dUrl, params).getBlob().setName(xlsxName);
MailApp.sendEmail({
to: "[your mail address]",
subject: "sample mail",
body: "sample mail with an excel file",
attachments: [xlsxlFile]
});
}
These GASs retrieve an access token for using Google Drive API. There are 3 parts. Before you use this, please retrieve client ID, client secret and redirect uri from Google , and choose scopes.
1. Retrieving code from web
This is a script to output URL for retrieving “code” from web. Please retrieve “code” by import this URL to your browser. After you run this script, using “url” got from this script, it retrieves “code”.
This sample script sends an e-mail with an Excel file exported from Spreadsheet as an attachment file.
function excelSender() {
var sheetID = [Sheet ID];
var xlsxName = [Excel file name];
var params = {
"headers" : {Authorization: "Bearer [Retrieved AccessToken]"},
"muteHttpExceptions" : true
};
var dUrl = "https://www.googleapis.com/drive/v3/files/" + sheetID + "/export?mimeType=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
var xlsxlFile = UrlFetchApp.fetch(dUrl, params).getBlob().setName(xlsxName);
MailApp.sendEmail({
to: [Mail address],
subject: "sample subject",
body: "sample body",
attachments: [xlsxlFile]
});
}

Here, I introduce how to download a CSV file from spreadsheet using Google HTML Service.
- Using “onOpen()”, it addes menu for launching a dialog.

-
After launching the dialog, “getFileUrl()” is launched by pushing a button. “getFileUrl()” exports a CSV file and outputs download URL.
-
The CSV file is downloaded by “executeDownload()”.
Please put both HTML and GAS to a GAS project.
HTML : download.html
<!DOCTYPE html>
<html>
<body>
Download CSV?
<form>
<input type="button" value="ok" onclick="google.script.run
.withSuccessHandler(executeDownload)
.getFileUrl();" />
</form>
</body>
<script>
function executeDownload(url) {
window.location.href = url;
}
</script>
</html>
GAS :
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('export')
.addItem('export csv files', 'dialog')
.addToUi();
}
function dialog() {
var html = HtmlService.createHtmlOutputFromFile('download');
SpreadsheetApp.getUi().showModalDialog(html, 'CSV download dialog');
}
function getFileUrl() {
var filename = "#####"; // CSV file name
var folder = "#####"; // Folder ID
var csv = "";
var v = SpreadsheetApp // Now spreadsheet is an active sheet.
.getActiveSpreadsheet()
.getActiveSheet()
.getDataRange()
.getValues();
v.forEach(function(e) {
csv += e.join(",") + "\n";
});
var url = DriveApp.getFolderById(folder)
.createFile(filename, csv, MimeType.CSV)
.getDownloadUrl()
.replace("?e=download&gd=true","");
return url;
}

var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var chart = sheet.newChart()
.setChartType(Charts.ChartType.LINE)
.asLineChart()
.addRange(sheet.getRange('a1:a21'))
.addRange(sheet.getRange('b1:b21'))
.addRange(sheet.getRange('c1:c21'))
.setColors(["green", "red"])
.setBackgroundColor("black")
.setPosition(5, 5, 0, 0)
.setPointStyle(Charts.PointStyle.MEDIUM)
.setOption('useFirstColumnAsDomain', true)
.setOption('height', 280)
.setOption('width', 480)
.setOption('title', 'Sample chart')
.setOption('hAxis', {
title: 'x axis',
minValue: 0,
maxValue: 20,
titleTextStyle: {
color: '#c0c0c0',
fontSize: 20,
italic: false,
bold: false
},
textStyle: {
color: '#c0c0c0',
fontSize: 12,
bold: false,
italic: false
},
baselineColor: '#c0c0c0',
gridlines: {
color: '#c0c0c0',
count: 4
}
})
.setOption('vAxis', {title: 'y axis',
minValue: 0,
maxValue: 800,
titleTextStyle: {
color: '#c0c0c0',
fontSize: 20,
italic: false,
bold: false
},
textStyle: {
color: '#c0c0c0',
fontSize: 12,
bold: false,
italic: false
},
baselineColor: '#c0c0c0',
gridlines: {
color: '#c0c0c0',
count: 4
}
})
.setOption('legend', {
position: 'right',
textStyle: {
color: 'yellow',
fontSize: 16
}
})
.build();
sheet.insertChart(chart);

About Event Objects
For example, it thinks the situation of input text of ’test’ to ‘A1’ on a sheet.
When you use only ‘onEdit(e)’ without an installing trigger, ’e’ has following parameters.
{authMode=LIMITED, range=Range, source=Spreadsheet, user=, value=test}
In this case, the event cannot send an e-mail because of ‘authMode=LIMITED’.
When you use “onEdit(e)” with an installing trigger of “Edit”, ’e’ has following parameters.
{authMode=FULL, range=Range, source=Spreadsheet, value=test, triggerUid=#####}
In this case, the event can send an e-mail because of ‘authMode=FULL’.
Rule
-
Following scripts have to be made into a project of Google Apps Script.
-
Deploy the GAS project as a web application. Ref
-
After updated the script, it has to be updated as a new version.
Form.html :
<html>
<body>
<form>
<input type="file" name="imageFile">
<input type="button" value="ok" onclick="google.script.run.upload(this.parentNode)">
</form>
</body>
</html>
GAS :
function doGet() {
return HtmlService.createHtmlOutputFromFile('Form.html');
}
function upload(e) {
var destination_id = '#####'; // Folder ID of destination folder
// Reference : https://developers.google.com/apps-script/reference/base/blob#getAs(String)
// You can use 'application/pdf', 'image/bmp', 'image/gif', 'image/jpeg' and 'image/png'.
var contentType = 'image/jpeg';
var img = e.imageFile;
var destination = DriveApp.getFolderById(destination_id);
var img = img.getAs(contentType);
destination.createFile(img);
}
When you set ‘image/jpeg’ as “contentType” and upload png file, the uploaded image file is converted to jpeg file and saved it to the destination folder.
This is a sample script for retrieving cells without blank cells. Figure 1 shows the sample spreadsheet. In this sheet, the row 14 has one space.
|
 |
| Fig. 1: Sample spreadsheet. |
Data is retrieved as follows.
var data = SpreadsheetApp
.getActiveSpreadsheet()
.getActiveSheet()
.getRange('a1:a30')
.getValues();
1. Retrieving cells with spaces and no blank cells.
var Result = [i for each (i in data)if (i)].join('');
Result : Hello World