Google Documents – How to Replace Text in Header and Footer

The upcoming release of Document Studio includes support for adding markers in the header, footer and the footnotes section of your Microsoft Word template. The add-on will automatically replace this placeholder text with actual values sourced from Google Sheets or Google Forms.

Header and footer in Google Docs

This Apps Script snippet uses the Google Docs API to find and replace multiple blocks of text in the header and footer section of your Google Document. The header and footer sections are children of the parent DOCUMENT section.

const replaceHeaderFooter = () => {
  // Returns the document with the specified ID
  const doc = DocumentApp.openById("DOCUMENT ID");

  // Retrieves the headers's container element which is DOCUMENT
  const parent = doc.getHeader().getParent();

  for (let i = 0; i < parent.getNumChildren(); i += 1) {
    // Retrieves the child element at the specified child index
    const child = parent.getChild(i);

    // Determine the exact type of a given child element
    const childType = child.getType();

    if (childType === DocumentApp.ElementType.HEADER_SECTION) {
      // Replaces all occurrences of a given text in regex pattern
      child.asHeaderSection().replaceText("{{Company}}", "Digital Inspiration");
    } else if (childType === DocumentApp.ElementType.FOOTER_SECTION) {
      // Replaces all occurrences of a given text in regex pattern
      child.asFooterSection().replaceText("{{Copyright}}", "© Amit Agarwal");
    }
  }

  // Saves the current Document.
  // Causes pending updates to be flushed and applied.
  doc.saveAndClose();
};

If the current document doesn’t include an header section, the getHeader() function will return null so you may wish to include additional checks to determine whether a document has an header or footer.

How to Schedule a Google Meeting with Google Calendar and Apps Script

This Apps Script sample shows how you can programmatically schedule video meetings inside Google Meet with one or more participants using the Google Calendar API. It can be useful for teachers who wish to schedule regular meetings with their students but instead of manually creating meeting invites, they can easily automate the whole process for the entire class.

Schedule Google Meeting

Setup Google Meeting with Apps Script

Give your meeting a title, the start date, the meeting duration, the list of attendees and how often you wanted to be reminded of the upcoming Google meeting. A new meeting event will be added to your Google Calendar and you’ll also be provided with a Google Meet link that you share with your students and colleagues through mail merge.

const createGoogleMeeting = () => {
  // The default calendar where this meeting should be created
  const calendarId = "primary";

  // Schedule a meeting for May 30, 2021 at 1:45 PM
  // January = 0, February = 1, March = 2, and so on
  const eventStartDate = new Date(2021, 4, 30, 13, 45);

  // Set the meeting duration to 45 minutes
  const eventEndDate = new Date(eventStartDate.getTime());
  eventEndDate.setMinutes(eventEndDate.getMinutes() + 45);

  const getEventDate = (eventDate) => {
    // Dates are computed as per the script's default timezone
    const timeZone = Session.getScriptTimeZone();

    // Format the datetime in `full-date T full-time` format
    return {
      timeZone,
      dateTime: Utilities.formatDate(
        eventDate,
        timeZone,
        "yyyy-MM-dd'T'HH:mm:ss"
      ),
    };
  };

  // Email addresses and names (optional) of meeting attendees
  const meetingAttendees = [
    {
      displayName: "Amit Agarwal",
      email: "amit@labnol.org",
      responseStatus: "accepted",
    },
    { email: "student1@school.edu", responseStatus: "needsAction" },
    { email: "student2@school.edu", responseStatus: "needsAction" },
    {
      displayName: "Angus McDonald",
      email: "assistant@school.edu",
      responseStatus: "tentative",
    },
  ];

  // Generate a random id
  const meetingRequestId = Utilities.getUuid();

  // Send an email reminder a day prior to the meeting and also
  // browser notifications15 minutes before the event start time
  const meetingReminders = [
    {
      method: "email",
      minutes: 24 * 60,
    },
    {
      method: "popup",
      minutes: 15,
    },
  ];

  const { hangoutLink, htmlLink } = Calendar.Events.insert(
    {
      summary: "Maths 101: Trigonometry Lecture",
      description: "Analyzing the graphs of Trigonometric Functions",
      location: "10 Hanover Square, NY 10005",
      attendees: meetingAttendees,
      conferenceData: {
        createRequest: {
          requestId: meetingRequestId,
          conferenceSolutionKey: {
            type: "hangoutsMeet",
          },
        },
      },
      start: getEventDate(eventStartDate),
      end: getEventDate(eventEndDate),
      guestsCanInviteOthers: false,
      guestsCanModify: false,
      status: "confirmed",
      reminders: {
        useDefault: false,
        overrides: meetingReminders,
      },
    },
    calendarId,
    { conferenceDataVersion: 1 }
  );

  Logger.log("Launch meeting in Google Meet: %s", hangoutLink);
  Logger.log("Open event inside Google Calendar: %s", htmlLink);
};

Also see: Generate Add to Calendar Links

Google Meeting with Recurring Schedule

The above code can be extended to create meetings that occur on a recurring schedule.

You need to simply add a recurrence attribute to the meeting event resource that specifies the recurring event in RRULE notation. For instance, the following rule will schedule a recurring video meeting for your Maths lecture every week on Monday, Thursday for 8 times.

{
  ...event,
  recurrence: ["RRULE:FREQ=WEEKLY;COUNT=8;INTERVAL=1;WKST=MO;BYDAY=MO,TH"];
}

Here are some other useful RRULE examples:

  • FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR - Occurs every week except on weekends
  • FREQ=MONTHLY;INTERVAL=2;BYDAY=TU - Occurs every Tuesday, every other month
  • INTERVAL=2;FREQ=WEEKLY - Occurs every other week
  • FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH;BYMONTH=12 - Occurs every other week in December on Tuesday and Thursday
  • FREQ=MONTHLY;INTERVAL=2;BYDAY=1SU,-1SU - Occurs every other month on the first and last Sunday of the month

How to Add a Watermark in Google Documents

Microsoft Word includes a useful “Insert Watermark” feature to help you easily add your brand’s logo image or a text stamp that fades behind the content of every page in the document. A company’s policy may require employees to add watermarks to indicate if any document is in draft stage or if the document is confidential and not meant for external distribution.

Microsoft Word Watermark

Insert Watermarks in Google Docs

Unlike Microsoft Word, there’s no built-in support for Watermarks in Google Docs but there’s a simple workaround - create a faded image with the text of your watermark and place that image behind the text of your document pages. Here’s how:

1. Create the watermark stamp

Launch MS Paint on your computer and create a simple watermark image in landscape mode with dark gray text. Please use a bold font like Impact with large font size as the large image can always be resized inside Google Docs but not vice-versa.

I’ve also added some ready-to-use image stamps on Canva and Imgur.

Upload Watermark Image

2. Upload Watermark to Google Docs

Inside Google Docs, go to the Insert menu, choose the Image submenu and select Upload from Computer. Upload the watermark image that you saved in the previous step to Google Docs.

3. Open Image Options

Right-click the uploaded image inside Google Docs and choose Image Options from the contextual menu.

Watermark Diagonal Image

4. Change Rotation

Expand the Image Options sidebar and, under the Size & Rotation section, set the angle to around 320° to make the watermark diagonal.

5. Send the Image Behind Text

  • Under the text wrapping section, choose Behind Text to send the watermark image behind the content of your document.
  • Under Position, choose the Fixed position option with the layout set as Center. This will position your watermark image right in the center of the page.
  • Under the Adjustments section, set the transparency level to around 80% to fade the watermark image in the background.

The Watermark Effect in Documents

Here’s how the final watermark effect will look like in your Google Document.

Watermark in Document

Tip: You can use Document Studio to generate PDF files from Google Forms and the watermarks would be also show up in your PDF document.

How to Use PayPal Subscriptions API with Node.js

Our Google add-on store uses PayPal Subscriptions with Digital Goods to process recurring payments and the invoices are sent to customers through Document Studio.

There are two steps.

  1. Customers makes the payment and completes the order on our website.
  2. PayPal sends a BILLING.SUBSCRIPTION.ACTIVATED webhook to a serverless function.
  3. The function (running on Firebase, Google Cloud) verifies the subscription and checks if the status is active.
  4. It invokes the Apps Script API to complete the order.

The cloud function was previously using the official PayPal SDK for Node.js but it has been recently deprecated and no longer supports the new PayPal subscriptions API endpoints. Migrating from the PayPal Node SDK to your own solution is relatively simple and involves two steps:

1. Get the PayPal Access Token

const { default: axios } = require("axios");

const getPayPalAccessToken = async () => {
  const client_id = "PayPal Client ID goes here";
  const client_secret = "PayPal Client Secret goes here";
  const options = {
    url: "https://api-m.paypal.com/v1/oauth2/token",
    method: "POST",
    headers: {
      Accept: "application/json",
      "Accept-Language": "en_US",
      "Content-Type": "application/x-www-form-urlencoded",
    },
    auth: {
      username: client_id,
      password: client_secret,
    },
    params: {
      grant_type: "client_credentials",
    },
  };
  const { status, data } = await axios(options);
  return data.access_token;
};

If you are planning to test your integration with your PayPal sandbox account instead of the production version, replace api-m.paypal.com in the requests with api-m.sandbox.paypal.com and use the sandbox client secret credentials.

2. Verify the Subscription

A successful request returns the HTTP 200 OK status code and a JSON response body.

const { default: axios } = require("axios");

const verifyPayPalSubscription = async (subscription_id) => {
  const token = await getPayPalAccessToken();
  const options = {
    method: "GET",
    url: `https://api-m.paypal.com/v1/billing/subscriptions/${subscription_id}`,
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
    },
  };
  const { status, data = {} } = await axios(options);
  if (status === 200) {
    const { subscriber: { email_address } = {}, status } = data;
    return status === "ACTIVE";
  }
  return false;
};

Once the PayPal Subscription is found to be active, an HTTP request is made to the Google Apps Script API that sends the invoice and license to the customer. Learn more.

The Best Extensions for Google Chrome

Best Google Chrome extensions

Here’s a comprehensive list of the best extensions for Google Chrome that will help you do more and also enhance your web browsing experience.

The Best Google Chrome extensions

  • Vimium C — Browse the web, interact with web pages, navigate browser history using keyboard shortcuts. Inspired by Vim commands.
  • Fika - Read pages in a Kindle-style clean layout with beautiful typography while hiding the distracting parts.
  • PushBullet — Easily transfer web page links, text notes, or push photos and files from the computer to your phone and vice-versa.
  • OneTab — Save all your open tabs in a group and duplicate your session anytime later with a click.
  • Gmail Sender Icons - Quickly identify the sending domain of an email in Gmail without opening the message.
  • Bubble Cursor - The add-on makes it easy for you to click on links that are too small to select with your mouse or for typing inside input boxes.
  • Picture in Picture - Watch YouTube videos in an always-on-top floating window while you work on other tasks.
  • Zoho Annotator - A simple ad-free screenshot capture tool with a built-in editor for annotating images. Also integrates with Google Drive, OneDrive and Dropbox.
  • Loom - Record a screencast video with voice narration, include your webcam video and share instantly. Also see Screenity.
  • URL Render - Instead of clicking individual links on the Google search page, hover your mouse and instantly view the underlying page in a floating window.
  • Clipt - A universal clipboard for Android and desktop computers. Copy any text on your phone and instantly paste it on the desktop and vice-versa.
  • Hover Zoom - Hover your mouse over any thumbnail image on sites like Facebook and Amazon and the add-on will enlarge the image to its full size.
  • Quick Source Viewer - A better alternative to the native View Source option that displays both JS and CSS files in addition to HTML content.
  • Save To Drive - Right-click and save the current web page, or images on a page, to your Google Drive.
  • Google Input - Type text in any language of your choice using virtual keyboards, your handwriting and transliteration.
  • Google Dictionary - Use this add-on to view definitions of words and learn their correct pronunciation.
  • uBlacklist - Blocks specific sites and entire domains from appearing in your Google search results.
  • Gmail Notes - Attach sticky notes to your email message that are persistent and will show up the next time you open that same email inside Gmail.
  • Ugly Email - Some emails contain a tracking pixel that notifies the sender when their emails are read. This add-on blocks the tracking attempts.
  • Stylebot - Change the appearance of any web page with CSS selectors, permanently hide elements on a page and the changes persist across browser sessions.
  • Webtime Tracker — Keep track of how you spend your time on individual websites and visualize your Internet usage through graphs.
  • Skip Search - An address bar shortcut for the I'm lucky command that directly takes you to the most relevant website for your search query.
  • Single File - Download the entire web page into a single HTML file. The associated CSS files, fonts and images are also saved in the file.
  • Go Incognito - Open the current tab of your browser in a new incognito tab, useful for browsing news websites are behind paywalls.
  • Feeder - An excellent RSS feed reader that is accessible from the Chrome toolbar and supports notifications for your favorite feeds.
  • Scribe - Create step-by-step guides and tutorials by recording steps and publish them as PDF guides.
  • Visbug - A must-have design tool for web developers that brings powerful editing capabilities to the browser.
  • TabNotes - A minimalistic start page for Chrome that opens a simple notepad in each new tab.
  • Sitemod - Modify any website on the Internet through Chrome Dev Tools and create a permanent copy of the modified website with a unique, shareable URL.
  • iCloud Passwords - Access your Safari passwords that are saved inside iOS and Mac device from Chrome on Windows PCs.
  • Twitter Screenshots - Take beautiful, uncluttered screenshots of tweets with a click.
  • StayFocusd - It helps you limit the time you spend on distracting websites Facebook or Reddit by temporarily blocking the site when the allotted time has passed.
  • Black Menu - Create shortcuts to your favorite Google services and access your emails, calendar, videos and more in an easily accessible popup.

How to Use Notion with Gmail and Google Sheets using Apps Script

Notion, my absolute favorite tool for storing all sorts of things from web pages to code snippets to recipes, just got better. They’ve released a public API and thus it will be a lot easier for developers to read and write to their Notion workspace from external apps.

For instance, you can create a document in Google Docs and export it to Notion while staying inside Docs. Google Sheets users can pull pages from Notion database into their spreadsheet. Any new submissions in Google Forms can be directly saved to Notion and so on!

Save Gmail Messages in Notion

I have put together a Gmail add-on that makes it easy for you to save email messages, or any other text content, from Gmail to your Notion workspace with a click. Here’s how the app works.

Step 1: Connect Gmail to Notion

002815

Step 2: Allow Access to Notion pages - if you have multiple databases in your Notion workspace, you have an option to grant access to select databases and the rest will be inaccessible to the external app.

Authorize Notion

Step 3: Choose Email - open any email message in Gmail and you’ll have an option to edit the content of the email subject and body before sending the content to your Notion page. Please note that the app only supports plain text format at this time.

Send Email to Notion

Step 4: Open Notion - As soon as you hit the Send to Notion button, the content of the currently selected email message is added to your Notion database. You can click the All updates link in your Notion sidebar to view to recently added page.

Notion page

How to Use Notion with Google Apps Script

If you would to integrate your own Google add-on with Notion API, here’s a brief outline of the steps involved.

  1. Go to notion.so and click the Create New Integration button. You’ll be provided with a Client ID and Client Secret that you’ll need in a later step.

  2. Include the OAuth2 library in your Apps Script project and invoke the getRedirectUri method to get the OAuth2 redirect URL for the previous step.

const getNotionService = () => {
  return OAuth2.createService("Notion")
    .setAuthorizationBaseUrl("https://api.notion.com/v1/oauth/authorize")
    .setTokenUrl("https://api.notion.com/v1/oauth/token")
    .setClientId(CLIENT_ID)
    .setClientSecret(CLIENT_SECRET)
    .setCallbackFunction("authCallback")
    .setPropertyStore(PropertiesService.getUserProperties())
    .setCache(CacheService.getUserCache())
    .setTokenHeaders({
      Authorization: `Basic ${Utilities.base64Encode(
        `${CLIENT_ID}:${CLIENT_SECRET}`
      )}`,
    });
};

const authCallback = (request) => {
  const isAuthorized = getNotionService().handleCallback(request);
  return HtmlService.createHtmlOutput(
    isAuthorized ? "Success!" : "Access Denied!"
  );
};

const getRedirectUri = () => {
  console.log(OAuth2.getRedirectUri());
};
  1. Connect to Notion API - Make a Get HTTP request to the /vi/databases to fetch a list of all databases that the user has explicitly shared with authorized app.
function getDatabasesList() {
  var service = getNotionService();
  if (service.hasAccess()) {
    const url = "https://api.notion.com/v1/databases";
    const response = UrlFetchApp.fetch(url, {
      headers: {
        Authorization: `Bearer ${service.getAccessToken()}`,
        "Notion-Version": "2021-05-13",
      },
    });
    const { results = [] } = JSON.parse(response.getContentText());
    const databases = results
      .filter(({ object }) => object === "database")
      .map(({ id, title: [{ plain_text: title }] }) => ({ id, title }));
    console.log({ databases });
  } else {
    console.log("Please authorize access to Notion");
    console.log(service.getAuthorizationUrl());
  }
}

Download Gmail to Notion

The Gmail to Notion app is in beta. If you would like to use it with your Gmail or Google Workspace account, please install from here - Gmail to Notion

Create React App with Multiple Entry Points

The Create React App frameworks lets you easily build single page applications but it doesn’t support multiple entry points. To give you an example, if a website outputs separate home pages for mobile and desktop clients, the pages could be sharing some common React components between them, and it may thus not be practical to build two completely separate React applications.

Also see: Bundle React App with Gulp

CRA doesn’t support multiple entry points but there are couple of ways to solve this problem.

Option 1 Eject from the Create React App using the npm run eject command and update the entry inside webpack.config.js file to include multiple entry points.

Option 2 Use an alternate build tool like Vite.js that includes support for multiple entry points out of the box.

Option 3 Use the rewired app - it lets you easily make changes and small tweaks to the default Webpack configuration without ejecting the app.

Option 4 Use REACT_APP environment variables to specify the target component and then use ES5 dynamic imports to load the corresponding app component as shown in this example.

React Multiple Entry Points

Multiple Entry Points for Create React App

If you intend to use the Create React App configuration without ejecting it, here’s a simple workaround that will help you define multiple entry points and the output will be bundle in separate folders.

Inside the src folder, create two components.

// ./src/Desktop.js
import React from "react";

const Desktop = () => {
  return <h1>For Desktop</h1>;
};

export default Desktop;
// ./src/Mobile.js
import React from "react";

const Mobile = () => {
  return <h1>For Mobile</h1>;
};

export default Mobile;

The default entry file index.js looks something like this:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

Next, edit your package.json file and add commands, one per build target.

"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "build:mobile": "cp src/Mobile.js src/App.js && npm run build && mv build build-mobile",
    "build:desktop": "cp src/Desktop.js src/App.js && npm run build && mv build build-desktop"
  }

Run npm run build:mobile when the build target is mobile or npm run build:desktop for the desktop entry point.

Google Sheets – Find Values in One Column that are Missing in Another Column

A small business maintains their staff roster in a simple Google Sheet - the column A of the sheet contains a list of all employee names and column B contains a list of employees who have been assigned to a project.

Items in column A that are not in column B

The immediate task is to identify staff members who are part of the organization but have not been assigned any project yet. In other words, the manager needs to figure out all employee names from column A who are not preset in column B.

There are two ways to solve this problem - visually and through formulas.

Using Visual Formatting

The first option would be to highlight cells in column A that are missing in column B.

Inside the Google Sheet, go to the Format menu and choose conditional formatting. Here select A2:A for the range field, choose Custom Formula from the Format Cells If dropdown and paste the formula:

=COUNTIF(B$2:B, A2)=0

The COUNTIF function will essentially count the occurrence of each item in Column A against the range of cells in Column B. If the count for an item in Column A is 0, it means that the cell value is not present in column B and the cell is highlighted with a different background color.

Visual Formatting - Missing Column Values

Find Missing Items in Another Column

The next approach uses Google Sheet formulas to create a list of items that are in Column A but missing in Column B.

We’ll make use of the FILTER function that, as the name suggests, returns only a filtered version of a range that meets a specific criteria. In our case, the criteria is similar to the one that we used in the visual formatting section.

Go to column C (or any blank column) and enter this formula in the first empty cell.

=FILTER(A2:A,ISNA(MATCH(A2:A,B2:B,0)))

Google Sheets MATCH function

The MATCH function returns the position of items in Column A in the range associated with Column B and it returns #N/A if the values is not found. When the result is used with ISNA, it returns true only when the match is not found.

Using Google Query Language

SQL geeks may also use the Google Query Language, we are used it with D3.js visualization, to print the list of names that are in Column B but not in Column B.

=QUERY(A2:A,
   "SELECT A WHERE A <> ''
    AND NOT A MATCHES '"&TEXTJOIN("|",TRUE,B2:B)&"'
    ORDER BY A")

missing values - Google Query

The matches operator in the where clause does a regex comparison and the order by clause in the query will automatically sort the output alphabetically.

Calculate the Battery Level and Charging Status with HTML5

When someone visits your website, you can easily retrieve information about the charge level of their mobile or laptop’s battery through the HTML5 Battery API. This is currently supported on Google Chrome, Opera & Firefox on the desktop and Chrome for Android.

Companies like Uber look at the battery status of their customer’s mobile phone and may apply a price surge if the battery is low because of the urgency of the customer.

The Battery API can be implemented with few lines of JavaScript code and reveals all the required details about the device’s battery charge level. You’ll get to know:

  1. Whether or not the battery is currently being charged.
  2. How much is the battery charged?
  3. If charging, how many seconds until the battery is fully charged.
  4. The remaining time in seconds until the battery is completely discharged.

Battery Status Demo

You can attach event listeners so the battery data is updated as soon as the charge level of the hardware’s battery is changed while the visitor is still on your page. You can go one step further and even integrate this with Google Analytics and store the battery charge level of your visitor’s devices using Events in Analytics.

<script>
  if (navigator.getBattery) {
    navigator.getBattery().then(function (battery) {
      display(battery);
    });
  } else if (navigator.battery) {
    display(navigator.battery);
  } else {
    console.log("Sorry, Battery Status API is not supported");
  }

  function display(battery) {
    console.log("Charge level? " + battery.level);
    console.log("Battery charging? " + battery.charging);
    console.log("Time to charge? " + battery.chargingTime);
    console.log("Time to discarge? " + battery.dischargingTime);
  }
</script>

This can have several use cases. For instance, when the visitor’s device is running low on battery and not plugged-in, the web developer can choose to automatically save the changes - like the form entries - in localStorage before the battery is completely drained.

<!-- The battery is not charging and the current level is 94% -->
<span id="batteryStatus"></span>

<script>
  if ("getBattery" in navigator) {
    navigator.getBattery().then((battery) => {
      const { level, charging } = battery;
      const status = charging ? "charging" : "not charging";
      const percent = `${Math.round(level * 100)}%`;
      const message = `The battery is ${status} and the current level is ${percent}`;
      document.getElementById("batteryStatus").textContent = message;
    });
  }
</script>

Here’s a complete list of browsers that currently support the Batter Status API as found on caniuse.com. To know more, refer to the documentation on Mozilla and W3.

HTML5 Battery Status

How to Email Spreadsheets Automatically on a Recurring Schedule

The Email Spreadsheets add-on for Google Sheets will help you automate the reporting of spreadsheet data and dashboards by email. If you are an office worker who has been emailing spreadsheets to colleagues manually, this add-on will save you a ton of time. And because it runs on the Google Cloud, your spreadsheet reports will be delivered even while you are offline or on vacation.

With Email Spreadsheets, you can schedule reports and it will automatically send them by email on a recurring schedule. You can email entire workbooks, specific sheets inside a workbook or even range of cells. Watch the video to get started.

Email Google Sheets Automatically

Go to the Google add-on store and install Email Google Sheets. Next, open any Google Spreadsheet in your Google Drive, go to the Add-ons menu inside the sheet, choose Email Spreadsheets from the dropdown and then choose Rules to create your first scheduled email report.

You are presented with a 3-step wizard to help the email schedule of your spreadsheet report.

Step 1: Select Sheet Export Options

Google Sheet - Export Options

  1. Expand the “Select Sheets” dropdown and select one or more sheets that you would like to include in the email. Each sheet is attached as a separate file in the email but you can choose the “Merge all sheets” option to create a single file from all sheets in the workbook.
  2. Select the export format. You can choose between PDF, Excel (xlsx), OpenDocument or CSV formats. The “Email without Attachment” option can be used to embed a specific range of cells in the email body without including any sheet as an attachment.
  3. If you have selected PDF as the export format in step 2, you are presented with a few more options. For instance, you can change the paper orientation (Portrait or Landscape), the paper size or alter the print margins to fit more content on a page. You can choose to show gridlines, notes, sheet names and page numbers in the exported file.
  4. (optional) The Cell Range option lets you specify a range in A1 notation and only that range will be exported in the PDF file.

Tip: Use the Preview button to test how your exported files would be like with the various export options.

Step 2: Write the Email Template

Email Template with Dynamic Sheet Cell Values

Next, we create an email template that will be sent with your reports. You can specify one or email recipients in the TO, CC, or BCC fields. Multiple email addresses should be separated by a comma.

You can also specify dynamic email recipients based on cell values in the spreadsheet. For instance, if the email address of the recipient is specified in cell B2 of a sheet titled “Employee Shifts”, you can put {{Employee Shifts!B2}} in the To field, and the add-on will pull the dynamic value from the cell at the time of sending the email report.

These dynamic cell values enclosed inside double curly braces can be used inside any of the email fields including subject, email body, and the sender’s name.

The email body can include dynamic cell values as well as ranges that make it easy of you to send portions of the spreadsheet without sharing the full workbook. For instance, you can write {{Employee Wages!B2:F9}} to include only the specific range (B2:F9) from the Wages sheet. Internally, the add-on converts the range to an HTML table, retaining all the display formatting with CSS, and embed it into the email.

You can also include standard HTML tags like H1, IMG, A, B, EM and more to include images and rich formatting in your emails.

Tip: Use the Test Email button to send an email with the exported files before setting up the schedule.

C: Create the Email Schedule

Email Sheets Daily, Hourly, Weekly or Monthly

The Google Sheets add-on includes a scheduler to help you set up recurring schedules visually. You can send email hourly, daily, weekly, monthly or even on a yearly recurring basis.

It is also possible to setup advanced schedules like:

  • Send a recurring email on the last working day of the month.
  • Send email reports every alternate day and end the reporting after 15 days.
  • Set up a quarterly schedule and send email reports on the first Monday of the quarter.

That’s it. After specifying the schedule, hit the Save button and your email report will be scheduled.

If you would like to edit your current email report or schedule a new report, go the add ons menu again, choose Email Spreadsheets and Rules.

Download Email Sheets

Email Google Sheets - How it works?

The add-on is written in Google Apps Script. It uses the Google Sheets API to convert sheets to PDF files and uses the Gmail API for sending the converted files as attachments.