├── Chapter1 ├── Automatically create Google Calendar events from Google Sheets data ├── Automatically send emails to new form respondents ├── Create a web app to collect user feedback ├── Example of Bound Script add menu Item ├── Example of Standalone Script Check emails ├── Example of error handling function ├── Hello World ├── Sending Email Notifications from Google Sheets └── Write To a Sheet ├── Chapter10 ├── Create weekly report ├── Data report to doc ├── Fetch JSON data populate Sheet ├── Filtering Data in Apps Script ├── JSON data for sheets ├── Summarize Data ├── Writing Data to a Spreadsheet ├── calculateAverageRatings ├── complexSheetDataToJson ├── create text file with JSON data ├── createWeeklyTrigger ├── customizedSheetDataToJson ├── draw chart in web app ├── exportSheetToPDF ├── fetchAndParseRSSFeed ├── fetchDataFromAPI ├── generateResponseSummary ├── line chart ├── readSheetData ├── save CSV to drive ├── sendReportByEmail ├── sendSheetAsEmailAttachment ├── sendSheetDataAsJson ├── sheet data chart └── sheetDataToJson ├── Chapter11 ├── Document maker ├── Generating and Sending Custom Invites ├── Google Calendar ├── assign tasks └── sheets assign tasks ├── Chapter13 ├── Generate and send invoice ├── Generating and Sending Financial Reports ├── Monthly Expense Report ├── Streamlining Employee Onboarding Process ├── Synchronizing Calendars for Room Booking System ├── distribute docs to assigned users └── syncBookingsToCalendar ├── Chapter14 ├── ProcessResponses ├── optimizeDataProcessing ├── scheduleMeetingsFromSheet └── trackUsage ├── Chapter2 ├── Debug └── error handling ├── Chapter3 ├── A custom function that converts temperatures from Celsius to Fahrenheit ├── Accessing a specific spreadsheet and writing data to a cell ├── Auto Fill data ├── Automatically updating inventory levels ├── Automating Invoice Generation ├── Building Custom Inventory Tracking Systems ├── Conditional Formatting Automation ├── Creating Custom Data Validation Functions ├── Creating the Invoice Template ├── Developing Dynamic and Interactive Reports ├── Generating a report with a button click: ├── Using sheet data for cleint info for invoice ├── add a new sheet ├── check and mark invalid emails ├── clear range ├── copy range of data ├── create Sheets PDF invoice ├── create backup file ├── custom function highest sales ├── delete a sheet ├── remove duplicates ├── rename sheet with testing function ├── sort data └── udpate range ├── Chapter4 ├── Basic Text Parsing and Manipulation Extracting Specific Text Segments ├── Batch update format ├── Cereate new table ├── Highlight existing text ├── Mail Merge Docs ├── Mail merge with Sheets Data ├── Sheet Data report ├── Sheet Data to Docs sheet report ├── access doc ├── analyze text data ├── apply style to doc ├── create doc from template ├── create list items ├── create new doc ├── creating headings ├── email doc as PDF ├── format document H1 ├── format for printing ├── format text in doc ├── generate report ├── generate report from Sheets data ├── generate table data ├── headers in table doc ├── insert image ├── insert on condition ├── modify doc ├── pivot table in sheets ├── read doc contents ├── replace text in doc ├── resize image ├── update existing doc ├── update list items └── update table ├── Chapter5 ├── Accessing Form Responses ├── Advanced form creation from sheets ├── Automating Feedback and Follow-up Processes ├── Dynamic Form from Sheet data ├── Set up Autograding ├── Setting Up Simple Triggers ├── Trigger to run function on submit ├── Updating Google Sheets Based on Form Responses ├── Writing Form Responses to Google Sheets ├── create a form ├── create form from sheet data ├── generate Quiz Feedback Form ├── get form responses ├── latest response ├── process response with trigger ├── responses to sheet ├── send Confirmation Emai ├── send email response Autoresponder ├── send quiz feedback ├── update form └── update form options ├── Chapter6 ├── Add chart from Sheets to Slides ├── Apply theme ├── Create doc and share with anyone ├── Creating Slides Dynamically ├── Insert Image ├── access gmail messages ├── create Slides ├── customize slide layout ├── generate from tempalte ├── insert dynamic content ├── insert shape └── insert text ├── Chapter7 ├── Create from template and share ├── Creating Files and Folders ├── Move file to folder ├── back up of folders ├── file metadata ├── organize files by Date ├── search fiels by name ├── update metadata └── update user permissions ├── Chapter8 ├── Check for email by subject in thread ├── Parsing Email Messages ├── Sending Personalized Emails ├── Triggering Actions Based on Email Content ├── applyLabelToMatchingEmails ├── create and add label if needed ├── create label and filter messages ├── createNewLabel ├── deleteLabel ├── extractUrlsFromBody └── send Email ├── Chapter9 ├── Custom Dialogs and Sidebars ├── Docs Custom UI menu ├── Example with Google Calendar ├── New Task List ├── UI menu example ├── UI menu run report ├── UrlFetchApp example ├── add task to list ├── checkDeadlinesAndSendEmails ├── createCalendarEvents ├── createCustomEventReminder ├── custom function in sheets ├── custom menu in Docs ├── custom menus UI ├── doGet Deploy Web App ├── extractDataToSheet from Doc ├── formatCells ├── send email from sheet data ├── sendEmailNotifications └── sendEmails ├── Data JSON Data └── Examples ├── Append a Row to a Spreadsheet ├── Automate Document Creation and Sharing ├── Batch Update Spreadsheet Cells ├── Convert Spreadsheet Data to JSON ├── Create a Google Doc ├── Create a Menu in Google Sheets ├── Fetch Data from an API ├── Generate PDFs from Google Docs Template ├── Generate a Spreadsheet Report from Form Responses ├── Log a Custom Message ├── Monitor Sheet Changes and Send Notifications ├── Read Data from a Spreadsheet ├── Schedule Email Reminders from Spreadsheet Data ├── Send an Email ├── Update Spreadsheet Formatting └── Write Data to a Spreadsheet /Chapter1/Automatically create Google Calendar events from Google Sheets data: -------------------------------------------------------------------------------- 1 | function createCalendarEvents() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const data = sheet.getDataRange().getValues(); 4 | data.forEach(function(row) { 5 | const eventTitle = row[0]; 6 | const eventDate = row[1]; 7 | const eventDescription = row[2]; 8 | //Create Calendar Event 9 | const calendar = CalendarApp.getDefaultCalendar(); 10 | calendar.createEvent(eventTitle, new Date(eventDate), new Date(eventDate), {description: eventDescription}); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter1/Automatically send emails to new form respondents: -------------------------------------------------------------------------------- 1 | function sendEmails() { 2 | const formResponses = FormApp.openById('FORM_ID').getResponses(); 3 | const template = HtmlService.createHtmlOutputFromFile('emailTemplate').getContent(); 4 | 5 | formResponses.forEach(function(response) { 6 | const respondentEmail = response.getRespondentEmail(); 7 | const emailSubject = "Thank you for your response!"; 8 | const emailBody = "Here is the email content..."; 9 | //Send email 10 | MailApp.sendEmail(respondentEmail, emailSubject, emailBody, {htmlBody: template}); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter1/Create a web app to collect user feedback: -------------------------------------------------------------------------------- 1 | const SHEET_ID = '1lBa1WHvB8MgKCUN8GTI2G-3ECTZG3QvZwtZwPD9L-OM'; 2 | 3 | function doGet() { 4 | return HtmlService.createHtmlOutputFromFile('index'); 5 | } 6 | function submitFeedback(form) { 7 | const timestamp = new Date(); 8 | const feedback = form.feedback; 9 | //Store feedback in Google Sheet 10 | const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName('data'); 11 | sheet.appendRow([timestamp, feedback]); 12 | return "Feedback submitted successfully!"; 13 | } 14 | 15 | 16 | 17 | 18 | 19 | 30 | 31 | 32 |

Feedback Form

33 |
34 |
35 |

36 | 37 |
38 |

39 | 40 | 41 | -------------------------------------------------------------------------------- /Chapter1/Example of Bound Script add menu Item: -------------------------------------------------------------------------------- 1 | function onOpen() { 2 | const ui = SpreadsheetApp.getUi(); 3 | ui.createMenu('Custom Menu') 4 | .addItem('Clear Range', 'clearRange') 5 | .addToUi(); 6 | } 7 | function clearRange() { 8 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 9 | sheet.getRange('A1:D10').clear(); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter1/Example of Standalone Script Check emails: -------------------------------------------------------------------------------- 1 | function checkUnreadEmails() { 2 | const unread = GmailApp.getInboxUnreadCount(); 3 | Logger.log('You have ' + unread + ' unread emails.'); 4 | } 5 | -------------------------------------------------------------------------------- /Chapter1/Example of error handling function: -------------------------------------------------------------------------------- 1 | function myFunction() { 2 | try { 3 | // Code that may throw an exception 4 | const result = 1 / 0; // Example of code that will cause an exception 5 | } catch (e) { 6 | // Code to handle the exception 7 | Logger.log('An error occurred: ' + e.toString()); 8 | } finally { 9 | // Code that will run regardless of the try / catch result 10 | Logger.log('Function execution has ended.'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter1/Hello World: -------------------------------------------------------------------------------- 1 | function helloWorld() { 2 | Logger.log('Hello, world!'); 3 | } 4 | -------------------------------------------------------------------------------- /Chapter1/Sending Email Notifications from Google Sheets: -------------------------------------------------------------------------------- 1 | function sendEmailNotification() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const lastRow = sheet.getLastRow(); 4 | for (let i = 2; i <= lastRow; i++) { 5 | const assignedTo = sheet.getRange(i, 2).getValue(); // Assuming assignedTo column is B 6 | const taskDescription = sheet.getRange(i, 1).getValue(); // Assuming taskDescription column is A 7 | const emailAddress = sheet.getRange(i, 3).getValue(); // Assuming emailAddress column is C 8 | if (assignedTo !== "" && emailAddress !== "") { 9 | const subject = "Task Assigned: " + taskDescription; 10 | const message = "You have been assigned a new task: " + taskDescription; 11 | MailApp.sendEmail(emailAddress, subject, message); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter1/Write To a Sheet: -------------------------------------------------------------------------------- 1 | function writeToSheet() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | sheet.getRange('A1').setValue('Hello, world!'); 4 | } 5 | -------------------------------------------------------------------------------- /Chapter10/Create weekly report: -------------------------------------------------------------------------------- 1 | function createWeeklyReport() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 3 | const data = sheet.getDataRange().getValues(); 4 | 5 | // Assuming generateDocReport is defined elsewhere in your script 6 | const reportUrl = generateDocReport(data); 7 | 8 | Logger.log(`Report generated: ${reportUrl}`); 9 | } 10 | 11 | function generateDocReport(data) { 12 | const doc = DocumentApp.create('Weekly Report'); 13 | const body = doc.getBody(); 14 | body.appendParagraph('Weekly Report').setHeading(DocumentApp.ParagraphHeading.HEADING1); 15 | 16 | data.forEach((row, index) => { 17 | if (index === 0) return; // Skip headers 18 | body.appendParagraph(`Data Point: ${row.join(', ')}`); 19 | }); 20 | 21 | return doc.getUrl(); 22 | } 23 | -------------------------------------------------------------------------------- /Chapter10/Data report to doc: -------------------------------------------------------------------------------- 1 | To match the requirements of the generateReport function which generates a document with a data report from a spreadsheet, we'll design a simple data table structure. This structure assumes that your data is organized in a typical tabular format with headers in the first row and subsequent rows containing the data. 2 | 3 | Example Spreadsheet Data 4 | Let's assume your spreadsheet data looks like this: 5 | -------------------------------------------------------------------------------- /Chapter10/Fetch JSON data populate Sheet: -------------------------------------------------------------------------------- 1 | function fetchDataFromAPI2() { 2 | try { 3 | // Fetch data from the API 4 | const response = UrlFetchApp.fetch('https://jsonplaceholder.typicode.com/users'); 5 | if (response.getResponseCode() !== 200) { 6 | throw new Error('Failed to fetch data: API returned status code ' + response.getResponseCode()); 7 | } 8 | const data = JSON.parse(response.getContentText()); 9 | // Check if data is an array and has at least one element 10 | if (!Array.isArray(data) || data.length === 0) { 11 | throw new Error('Invalid or empty data received from the API'); 12 | } 13 | // Assuming all objects have the same structure, extract headers (keys) from the first object 14 | const headers = Object.keys(data[0]); 15 | const numRows = data.length + 1; // Adding one row for headers 16 | const numCols = headers.length; 17 | // Transform data into a 2D array 18 | const rows = data.map(obj => headers.map(header => obj[header] || '')); 19 | rows.unshift(headers); // Add headers at the beginning 20 | // Reference the specific sheet by ID and name 21 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 22 | // Clear existing content before setting new values 23 | sheet.clear(); 24 | // Set values in the sheet dynamically based on data size 25 | sheet.getRange(1, 1, numRows, numCols).setValues(rows); 26 | } catch (error) { 27 | // Log the error or use a more sophisticated error handling approach 28 | Logger.log('Error fetching or processing data: ' + error.toString()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter10/Filtering Data in Apps Script: -------------------------------------------------------------------------------- 1 | function filterData() { 2 | const spreadsheet = SpreadsheetApp.openById(SHEETID); 3 | const sheet = spreadsheet.getSheetByName('data'); 4 | const range = sheet.getDataRange(); 5 | const values = range.getValues(); 6 | 7 | const filteredData = values.filter(function(row) { 8 | return row[2] >= 90; // Assuming scores are in the third column 9 | }); 10 | 11 | // Check if the "Filtered Scores" sheet exists, if not, create it 12 | let filteredSheet = spreadsheet.getSheetByName("Filtered Scores"); 13 | if (!filteredSheet) { 14 | filteredSheet = spreadsheet.insertSheet("Filtered Scores"); 15 | } else { 16 | // Clear the existing contents before writing new data 17 | filteredSheet.clear(); 18 | } 19 | 20 | // Write the filtered data to the "Filtered Scores" sheet 21 | if (filteredData.length > 0) { 22 | filteredSheet.getRange(1, 1, filteredData.length, filteredData[0].length).setValues(filteredData); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter10/JSON data for sheets: -------------------------------------------------------------------------------- 1 | function fetchDataFromAPI3() { 2 | // Assuming SHEETID is defined elsewhere as the actual ID of your sheet 3 | const sheetName = 'data'; // The name of your sheet tab 4 | // Predefined data 5 | const predefinedData = [ 6 | ["1", "Leanne Graham", "Bret", "Sincere@april.biz"], 7 | ["2", "Ervin Howell", "Antonette", "Shanna@melissa.tv"] 8 | ]; 9 | // Headers 10 | const headers = ['ID', 'Name', 'Username', 'Email']; 11 | // Reference the sheet 12 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName(sheetName); 13 | sheet.clear(); // Clear existing contents 14 | // Set headers 15 | sheet.getRange(1, 1, 1, headers.length).setValues([headers]); 16 | // Set data (accounting for headers, start from row 2) 17 | sheet.getRange(2, 1, predefinedData.length, predefinedData[0].length).setValues(predefinedData); 18 | } 19 | -------------------------------------------------------------------------------- /Chapter10/Summarize Data: -------------------------------------------------------------------------------- 1 | function summarizeData() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 3 | const range = sheet.getDataRange(); 4 | const values = range.getValues(); 5 | const summary = {}; // Object to hold data summary 6 | // Loop through rows of data and accumulate information 7 | for (let i = 0; i < values.length; i++) { 8 | const row = values[i]; 9 | const category = row[0]; // Assuming the category is in the first column 10 | const amount = row[1]; // Assuming the amount is in the second column 11 | if (!isNaN(amount)) { // Ensure amount is a number 12 | if (summary[category]) { 13 | summary[category] += amount; 14 | } else { 15 | summary[category] = amount; 16 | } 17 | } 18 | } 19 | // Check if the "Summary" sheet exists, update it if it does, or create a new one if it doesn't 20 | let summarySheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Summary'); 21 | if (summarySheet !== null) { 22 | // If "Summary" sheet exists, clear it 23 | summarySheet.clear(); 24 | } else { 25 | // If "Summary" sheet doesn't exist, create it 26 | summarySheet = SpreadsheetApp.openById(SHEETID).insertSheet('Summary'); 27 | } 28 | // Output the summary to the "Summary" sheet 29 | let rowIndex = 1; // Fixed the scope of rowIndex 30 | for (let key in summary) { 31 | summarySheet.getRange(rowIndex, 1).setValue(key); 32 | summarySheet.getRange(rowIndex, 2).setValue(summary[key]); 33 | rowIndex++; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter10/Writing Data to a Spreadsheet: -------------------------------------------------------------------------------- 1 | function writeSheetData() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const data = [ 4 | ['Name', 'Email', 'Score'], 5 | ['John Doe', 'john@example.com', 88], 6 | ['Jane Smith', 'jane@example.com', 92] 7 | ]; 8 | const range = sheet.getRange(1, 1, data.length, data[0].length); 9 | range.setValues(data); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter10/calculateAverageRatings: -------------------------------------------------------------------------------- 1 | function calculateAverageRatings() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Form Responses 1'); 3 | const responses = sheet.getDataRange().getValues(); 4 | const headers = responses.shift(); // Assuming first row contains headers 5 | const ratingColumnIndex = headers.indexOf('Rating'); // Adjust based on your actual question title 6 | let totalRating = 0; 7 | responses.forEach(function(row) { 8 | totalRating += row[ratingColumnIndex]; 9 | }); 10 | const averageRating = totalRating / responses.length; 11 | Logger.log('Average Rating: ' + averageRating); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter10/complexSheetDataToJson: -------------------------------------------------------------------------------- 1 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 2 | -------------------------------------------------------------------------------- /Chapter10/create text file with JSON data: -------------------------------------------------------------------------------- 1 | function sheetDataToJson() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 3 | const range = sheet.getDataRange(); 4 | const values = range.getValues(); 5 | const jsonArray = []; 6 | // Assuming the first row contains headers 7 | const headers = values[0]; 8 | values.slice(1).forEach(function (row) { 9 | const obj = {}; 10 | row.forEach(function (cell, index) { 11 | obj[headers[index]] = cell; 12 | }); 13 | jsonArray.push(obj); 14 | }); 15 | const jsonString = JSON.stringify(jsonArray); 16 | Logger.log(jsonString); // Log the JSON string 17 | 18 | // Optionally, write JSON to a text file in Google Drive 19 | writeJsonToDrive(jsonString, "Data_JSON.txt"); 20 | } 21 | 22 | function writeJsonToDrive(jsonString, fileName) { 23 | const folder = DriveApp.getRootFolder(); // You can specify a different folder here 24 | const file = folder.createFile(fileName, jsonString, MimeType.PLAIN_TEXT); 25 | Logger.log("File created with ID: " + file.getId()); 26 | } 27 | -------------------------------------------------------------------------------- /Chapter10/createWeeklyTrigger: -------------------------------------------------------------------------------- 1 | function createWeeklyTrigger() { 2 | // Run 'generateAndSendReport' function every Monday at 9 AM 3 | ScriptApp.newTrigger('generateAndSendReport') 4 | .timeBased() 5 | .onWeekDay(ScriptApp.WeekDay.MONDAY) 6 | .atHour(9) 7 | .create(); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter10/customizedSheetDataToJson: -------------------------------------------------------------------------------- 1 | function customizedSheetDataToJson() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getDataRange(); 4 | const values = range.getValues(); 5 | const jsonArray = []; 6 | values.slice(1).forEach(function(row) { 7 | const obj = {}; 8 | row.forEach(function(cell, index) { 9 | const header = values[0][index]; 10 | if (cell) { // Exclude empty cells 11 | obj[header] = cell; 12 | } 13 | }); 14 | jsonArray.push(obj); 15 | }); 16 | // Custom formatting (e.g., date formatting) 17 | jsonArray.forEach(function(item) { 18 | if (item.date) { 19 | item.date = Utilities.formatDate(new Date(item.date), Session.getScriptTimeZone(), "yyyy-MM-dd"); 20 | } 21 | }); 22 | const jsonString = JSON.stringify(jsonArray, null, 2); // Pretty print JSON 23 | Logger.log(jsonString); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter10/draw chart in web app: -------------------------------------------------------------------------------- 1 | function doGet() { 2 | return HtmlService.createHtmlOutputFromFile('Page'); 3 | } 4 | 5 | 6 | 7 | 8 | 27 | 28 | 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /Chapter10/exportSheetToPDF: -------------------------------------------------------------------------------- 1 | function exportSheetToPDF() { 2 | const spreadsheetId = SHEETID; 3 | const sheetId = '1764361424'; // You can find this in the sheet URL 4 | const folderId = FOLDERID; // Where you want to save the PDF 5 | const exportUrl = `https://docs.google.com/spreadsheets/d/${spreadsheetId}/export?format=pdf&gid=${sheetId}`; 6 | const response = UrlFetchApp.fetch(exportUrl, { 7 | headers: { 8 | 'Authorization': 'Bearer ' + ScriptApp.getOAuthToken() 9 | } 10 | }); 11 | const blob = response.getBlob().setName('ExportedSheet.pdf'); 12 | DriveApp.getFolderById(folderId).createFile(blob); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter10/fetchAndParseRSSFeed: -------------------------------------------------------------------------------- 1 | function fetchAndParseRSSFeed() { 2 | const url = 'https://basescripts.com/feed'; // Replace with the URL of the RSS feed 3 | const xml = UrlFetchApp.fetch(url).getContentText(); 4 | const document = XmlService.parse(xml); 5 | const entries = document.getRootElement().getChild('channel').getChildren('item'); 6 | const data = []; 7 | entries.forEach(function(entry) { 8 | const postTitle = entry.getChild('title').getText(); 9 | const postLink = entry.getChild('link').getText(); 10 | const postDescription = entry.getChild('description').getText(); 11 | // Add more fields as needed 12 | data.push([postTitle, postLink, postDescription]); 13 | }); 14 | // Do something with the data, like writing it to a Google Sheet 15 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 16 | sheet.getRange(1, 1, data.length, data[0].length).setValues(data); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter10/fetchDataFromAPI: -------------------------------------------------------------------------------- 1 | function fetchDataFromAPI() { 2 | const response = UrlFetchApp.fetch('https://api.example.com/data'); 3 | const data = JSON.parse(response.getContentText()); 4 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 5 | sheet.getRange(1, 1, data.length, data[0].length).setValues(data); 6 | } 7 | -------------------------------------------------------------------------------- /Chapter10/generateResponseSummary: -------------------------------------------------------------------------------- 1 | function generateResponseSummary() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Form Responses 1'); 3 | const responses = sheet.getDataRange().getValues(); 4 | const summary = {}; // Object to hold summary counts 5 | responses.forEach(function(row, index) { 6 | if (index === 0) return; // Skip header row 7 | row.forEach(function(response, columnIndex) { 8 | const question = responses[0][columnIndex]; 9 | summary[question] = summary[question] || {}; 10 | summary[question][response] = (summary[question][response] || 0) + 1; 11 | }); 12 | }); 13 | // Log the summary or write it back to another sheet 14 | Logger.log(summary); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter10/line chart: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter10/readSheetData: -------------------------------------------------------------------------------- 1 | function readSheetData() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getDataRange(); // Get all non-empty cells 4 | const values = range.getValues(); // Returns a 2D array of values 5 | // Iterate through rows and columns 6 | for (let i = 0; i < values.length; i++) { 7 | for (let j = 0; j < values[i].length; j++) { 8 | Logger.log(values[i][j]); 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter10/save CSV to drive: -------------------------------------------------------------------------------- 1 | function convertRangeToCSV() { 2 | // You'll need to replace 'SHEETID' with your actual Google Sheet ID 3 | const range = SpreadsheetApp.openById(SHEETID).getSheetByName('data').getDataRange(); 4 | const values = range.getValues(); 5 | let csvContent = ''; // Fixed to 'let' to allow modification 6 | values.forEach(function(row) { 7 | csvContent += row.join(',') + '\n'; 8 | }); 9 | 10 | // Log for testing; in practice, this is where you diverge to write to Drive 11 | Logger.log(csvContent); 12 | 13 | // Write CSV content to a new file in Google Drive 14 | const fileName = 'ExportedData.csv'; // Name your file 15 | const folder = DriveApp.getRootFolder(); // Or specify another folder 16 | const file = folder.createFile(fileName, csvContent, MimeType.PLAIN_TEXT); 17 | Logger.log("CSV file created with ID: " + file.getId()); 18 | } 19 | -------------------------------------------------------------------------------- /Chapter10/sendReportByEmail: -------------------------------------------------------------------------------- 1 | function sendReportByEmail(reportUrl, recipients) { 2 | const subject = 'Weekly Report'; 3 | const body = `Please find this week's report at the following link: ${reportUrl}`; 4 | MailApp.sendEmail(recipients, subject, body); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter10/sendSheetAsEmailAttachment: -------------------------------------------------------------------------------- 1 | function sendSheetAsEmailAttachment() { 2 | const file = DriveApp.getFileById(SHEETID); 3 | const blob = file.getAs(MimeType.PDF); // Change as needed, e.g., MimeType.CSV 4 | blob.setName(file.getName() + '.pdf'); // Change extension as per format 5 | MailApp.sendEmail({ 6 | to: EMAIL, 7 | subject: "Data Report", 8 | body: "Find the attached data report.", 9 | attachments: [blob] 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter10/sendSheetDataAsJson: -------------------------------------------------------------------------------- 1 | function sendSheetDataAsJson() { 2 | const sheetData = SpreadsheetApp.openById(SHEETID).getSheetByName('data').getDataRange().getValues(); 3 | const jsonData = []; 4 | // Assuming the first row contains headers 5 | const headers = sheetData.shift(); // Removes the first row and returns it 6 | sheetData.forEach(function(row) { 7 | const obj = {}; 8 | headers.forEach(function(header, index) { 9 | obj[header] = row[index]; 10 | }); 11 | jsonData.push(obj); 12 | }); 13 | const options = { 14 | 'method': 'post', 15 | 'contentType': 'application/json', 16 | 'payload': JSON.stringify(jsonData) 17 | }; 18 | UrlFetchApp.fetch('https://httpbin.org/post', options); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter10/sheet data chart: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter10/sheetDataToJson: -------------------------------------------------------------------------------- 1 | function sheetDataToJson() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 3 | const range = sheet.getDataRange(); 4 | const values = range.getValues(); 5 | Logger.log(values); 6 | const jsonArray = []; 7 | // Assuming the first row contains headers 8 | const headers = values[0]; 9 | values.slice(1).forEach(function (row) { 10 | const obj = {}; 11 | row.forEach(function (cell, index) { 12 | obj[headers[index]] = cell; 13 | }); 14 | jsonArray.push(obj); 15 | }); 16 | const jsonString = JSON.stringify(jsonArray); 17 | Logger.log(jsonString); // Log the JSON string 18 | } 19 | -------------------------------------------------------------------------------- /Chapter11/Document maker: -------------------------------------------------------------------------------- 1 | function createTimeDrivenTrigger() { 2 | ScriptApp.newTrigger('createDocument') 3 | .timeBased() 4 | .atHour(9) 5 | .everyDays(1) 6 | .create(); 7 | } 8 | function createDocument() { 9 | const doc = DocumentApp.create('Daily Report ' + new Date().toDateString()); 10 | const body = doc.getBody(); 11 | // Add content to the document 12 | body.appendParagraph('Daily Report'); 13 | body.appendParagraph('Date: ' + new Date().toDateString()); 14 | body.appendParagraph('Generated automatically using Google Apps Script.'); 15 | } 16 | // Function to create a meeting agenda document based on calendar event 17 | function createMeetingAgenda(event) { 18 | const doc = DocumentApp.create('Meeting Agenda: ' + event.getTitle()); 19 | const body = doc.getBody(); 20 | // Add content to the document 21 | body.appendParagraph('Meeting Agenda: ' + event.getTitle()); 22 | body.appendParagraph('Date: ' + event.getStartTime().toDateString()); 23 | body.appendParagraph('Location: ' + event.getLocation()); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter11/Generating and Sending Custom Invites: -------------------------------------------------------------------------------- 1 | function sendInvitations() { 2 | const recipients = [ 3 | { name: 'John Doe', email: 'john@example.com', eventName: 'Holiday Party', eventDate: 'December 25, 2023', eventLocation: '123 Main St', rsvpDeadline: 'December 15, 2023' }, 4 | { name: 'Jane Smith', email: 'jane@example.com', eventName: 'Product Launch', eventDate: 'January 10, 2024', eventLocation: '456 Elm St', rsvpDeadline: 'January 5, 2024' } 5 | ]; 6 | const templateDocId = 'your_template_document_id'; // Replace with the ID of your invitation template document 7 | recipients.forEach(function(recipient) { 8 | const templateDoc = DocumentApp.openById(templateDocId); 9 | const templateContent = templateDoc.getBody().getText(); 10 | const customizedContent = templateContent 11 | .replace('{{RecipientName}}', recipient.name) 12 | .replace('{{EventName}}', recipient.eventName) 13 | .replace('{{EventDate}}', recipient.eventDate) 14 | .replace('{{EventLocation}}', recipient.eventLocation) 15 | .replace('{{RSVPDeadline}}', recipient.rsvpDeadline); 16 | // Send email with customized invitation 17 | MailApp.sendEmail({ 18 | to: recipient.email, 19 | subject: 'You are invited!', 20 | body: customizedContent, 21 | name: 'Your Name' 22 | }); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter11/Google Calendar: -------------------------------------------------------------------------------- 1 | function createCalendarEvent() { 2 | const calendar = CalendarApp.getDefaultCalendar(); 3 | const event = calendar.createEvent('Meeting with Client', new Date('2023-03-15T09:00:00'), new Date('2023-03-15T10:00:00')); 4 | Logger.log('Event created: ' + event.getTitle()); 5 | } 6 | 7 | function retrieveCalendarEvents() { 8 | const calendar = CalendarApp.getDefaultCalendar(); 9 | const events = calendar.getEventsForDay(new Date('2023-03-15')); 10 | events.forEach(function(event) { 11 | Logger.log('Event: ' + event.getTitle() + ', Start Time: ' + event.getStartTime()); 12 | }); 13 | } 14 | 15 | function sendEventReminderEmail() { 16 | const event = CalendarApp.getDefaultCalendar().getEventsForDay(new Date())[0]; // Get first event of the day 17 | const recipient = Session.getActiveUser().getEmail(); // Get current user's email 18 | const subject = 'Reminder: ' + event.getTitle(); 19 | const body = 'This is a reminder for your upcoming event: ' + event.getTitle() + '\n\nLocation: ' + event.getLocation() + '\nStart Time: ' + event.getStartTime(); 20 | MailApp.sendEmail(recipient, subject, body); 21 | } 22 | -------------------------------------------------------------------------------- /Chapter11/assign tasks: -------------------------------------------------------------------------------- 1 | function assignTasks() { 2 | const projectSheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Project Tasks'); 3 | const lastRow = projectSheet.getLastRow(); 4 | const data = projectSheet.getRange(2, 1, lastRow - 1, 3).getValues(); // Assuming columns A-C contain task data 5 | data.forEach(function(row) { 6 | const task = { 7 | title: row[0], 8 | assignee: row[1], 9 | status: row[2] 10 | }; 11 | // Code to assign task to assignee (e.g., send email notification) 12 | // Code to update task status (e.g., mark task as assigned) 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter11/sheets assign tasks: -------------------------------------------------------------------------------- 1 | function assignTasks() { 2 | const projectSheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Project Tasks'); 3 | const lastRow = projectSheet.getLastRow(); 4 | const data = projectSheet.getRange(2, 1, lastRow - 1, 3).getValues(); // Assuming columns A-C contain task data 5 | data.forEach(function(row) { 6 | const task = { 7 | title: row[0], 8 | assignee: row[1], 9 | status: row[2] 10 | }; 11 | // Code to assign task to assignee (e.g., send email notification) 12 | // Code to update task status (e.g., mark task as assigned) 13 | }); 14 | } 15 | function sendEmailNotification() { 16 | const recipient = 'team_member@example.com'; 17 | const subject = 'Task Assigned: Review Proposal'; 18 | const body = 'Dear Team Member,\n\nA new task has been assigned to you. Please review the proposal and provide feedback by the end of the day.\n\nRegards,\nProject Manager'; 19 | MailApp.sendEmail(recipient, subject, body); 20 | } 21 | function generateProjectReport() { 22 | const projectData = fetchDataFromProjectManagementTool(); // Function to fetch project data 23 | const report = createReport(projectData); // Function to create report 24 | // Code to share report with stakeholders (e.g., email report as PDF attachment) 25 | } 26 | -------------------------------------------------------------------------------- /Chapter13/Generate and send invoice: -------------------------------------------------------------------------------- 1 | function getLatestOrder() { 2 | // Access the spreadsheet by its ID and specify the sheet 3 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 4 | // Get the last row with data 5 | const lastRow = sheet.getLastRow(); 6 | // Retrieve order details from the last row 7 | const orderData = sheet.getRange(lastRow, 1, 1, sheet.getLastColumn()).getValues()[0]; 8 | // Assuming the data columns match the order in the static example above 9 | const latestOrder = { 10 | orderId: orderData[0], 11 | customerName: orderData[1], 12 | customerEmail: orderData[2], 13 | orderDate: orderData[3], 14 | orderTotal: orderData[4], 15 | productDetails: orderData[5] 16 | }; 17 | 18 | return latestOrder; 19 | } 20 | function generateAndSendInvoice() { 21 | const sheetData = getLatestOrder(); // Assume this function fetches the latest order details 22 | const invoiceTemplate = DriveApp.getFileById(DOCID); // Template document ID 23 | const docCopy = invoiceTemplate.makeCopy('Invoice for ' + sheetData.customerName); 24 | const doc = DocumentApp.openById(docCopy.getId()); 25 | const body = doc.getBody(); 26 | // Replace placeholders in the template with actual order data 27 | body.replaceText('{{CustomerName}}', sheetData.customerName); 28 | body.replaceText('{{OrderDate}}', sheetData.orderDate); 29 | // Add more replacements as needed 30 | doc.saveAndClose(); 31 | // Convert to PDF and email to customer 32 | sendInvoiceAsPdf(doc.getId(), sheetData.customerEmail); 33 | } 34 | function sendInvoiceAsPdf(documentId, customerEmail) { 35 | // Get the document by ID 36 | const doc = DriveApp.getFileById(documentId); 37 | // Convert the document to a PDF 38 | const pdf = doc.getAs(MimeType.PDF); 39 | // Define the subject of the email 40 | const subject = 'Your Invoice from Our Company'; 41 | // Define the body of the email 42 | const body = 'Dear Customer,\n\nPlease find attached your invoice.\n\nThank you for your business!'; 43 | // Define email options, including attachments 44 | const emailOptions = { 45 | attachments: [pdf], 46 | mimeType: MimeType.PDF 47 | }; 48 | // Send the email with the PDF attachment 49 | MailApp.sendEmail(EMAIL, subject, body, emailOptions); 50 | } 51 | -------------------------------------------------------------------------------- /Chapter13/Generating and Sending Financial Reports: -------------------------------------------------------------------------------- 1 | function sendMonthlyFinancialReport() { 2 | const reportContent = generateFinancialReportContent(); // Assume this generates the report text or HTML 3 | const today = new Date(); 4 | const subject = 'Monthly Financial Report - ' + (today.getMonth() + 1) + '/' + today.getFullYear(); 5 | const recipients = EMAIL; // Add your email or stakeholders' emails 6 | MailApp.sendEmail(recipients, subject, '', {htmlBody: reportContent}); 7 | } 8 | function generateFinancialReportContent() { 9 | // Sample data for the financial report 10 | const expenses = { 11 | 'Groceries': 500, 12 | 'Utilities': 200, 13 | 'Transportation': 150, 14 | 'Entertainment': 100 15 | }; 16 | const income = 1200; 17 | // Calculate total expenses 18 | let totalExpenses = 0; 19 | for (const category in expenses) { 20 | totalExpenses += expenses[category]; 21 | } 22 | // Calculate net income 23 | const netIncome = income - totalExpenses; 24 | // Construct the report content 25 | let reportContent = '

Financial Report

'; 26 | reportContent += '

Income: $' + income.toFixed(2) + '

'; 27 | reportContent += '

Expenses:

'; 28 | reportContent += ''; 33 | reportContent += '

Total Expenses: $' + totalExpenses.toFixed(2) + '

'; 34 | reportContent += '

Net Income: $' + netIncome.toFixed(2) + '

'; 35 | return reportContent; 36 | } 37 | -------------------------------------------------------------------------------- /Chapter13/Monthly Expense Report: -------------------------------------------------------------------------------- 1 | function testGenerateMonthlyExpenseReport() { 2 | // Define the month and year for testing 3 | const month = 3; // March 4 | const year = 2024; 5 | 6 | // Call the generateMonthlyExpenseReport function 7 | generateMonthlyExpenseReport(month, year); 8 | } 9 | 10 | function generateMonthlyExpenseReport(month, year) { 11 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName("data"); 12 | const dataRange = sheet.getDataRange(); 13 | const data = dataRange.getValues(); 14 | const report = {}; 15 | 16 | // Start iterating from the second row to skip the header 17 | for (let i = 1; i < data.length; i++) { 18 | const row = data[i]; 19 | const date = new Date(row[0]); // Assumes date is in the first column 20 | const category = row[1]; // Assumes category is in the second column 21 | const amount = parseFloat(row[2]); // Assumes amount is in the third column 22 | 23 | // Check if date, category, and amount are not empty and valid 24 | if (date && !isNaN(amount) && category && date.getMonth() + 1 === month && date.getFullYear() === year) { 25 | report[category] = (report[category] || 0) + amount; 26 | } 27 | } 28 | // Log the report or write it back to another sheet 29 | Logger.log(report); 30 | } 31 | -------------------------------------------------------------------------------- /Chapter13/Streamlining Employee Onboarding Process: -------------------------------------------------------------------------------- 1 | function processNewEmployeeForm() { 2 | const employeeDetails = getNewEmployeeDetails(); // Fetch details from form response 3 | createOnboardingDocuments(employeeDetails); 4 | createEmployeeAccount(employeeDetails); 5 | sendWelcomeEmail(employeeDetails); 6 | } 7 | function getNewEmployeeDetails() { 8 | var sheet = SpreadsheetApp.openById(SHEETID).getSheetByName("data"); 9 | var dataRange = sheet.getDataRange(); 10 | var data = dataRange.getValues(); 11 | 12 | var lastRow = data[data.length - 1]; 13 | var employeeDetails = { 14 | formID: lastRow[0], 15 | name: lastRow[1], 16 | email: lastRow[2], 17 | position: lastRow[3], 18 | startDate: lastRow[4], 19 | department: lastRow[5] 20 | }; 21 | 22 | return employeeDetails; 23 | } 24 | function createOnboardingDocuments(employeeDetails) { 25 | // This is a placeholder for where you would create documents. 26 | // For example, copying a template file and customizing it with the employee's details. 27 | Logger.log("Creating onboarding documents for " + employeeDetails.name); 28 | } 29 | function createEmployeeAccount(employeeDetails) { 30 | // This is a placeholder for the employee account creation logic. 31 | Logger.log("Creating an account for " + employeeDetails.name); 32 | } 33 | function sendWelcomeEmail(employeeDetails) { 34 | var subject = "Welcome to the Team, " + employeeDetails.name + "!"; 35 | var body = "Dear " + employeeDetails.name + ",\n\n" + 36 | "Welcome to the " + employeeDetails.department + " department as our new " + employeeDetails.position + ". " + 37 | "Your start date is " + employeeDetails.startDate + ". We are excited to have you onboard and look forward to your contributions.\n\n" + 38 | "Best,\nThe Team"; 39 | 40 | MailApp.sendEmail(EMAIL, subject, body); 41 | Logger.log("Sent welcome email to " + employeeDetails.email); 42 | } 43 | -------------------------------------------------------------------------------- /Chapter13/Synchronizing Calendars for Room Booking System: -------------------------------------------------------------------------------- 1 | function syncBookingsToCalendar() { 2 | const bookings = getPendingBookings(); // Assume this fetches bookings from the sheet 3 | bookings.forEach(function(booking) { 4 | if (!checkCalendarConflicts(booking)) { 5 | createCalendarEvent(booking); // Create event if no conflict 6 | updateBookingStatus(booking, 'Confirmed'); // Update status in the sheet 7 | } else { 8 | sendConflictNotification(booking); // Notify user of conflict 9 | } 10 | }); 11 | } 12 | function checkCalendarConflicts(booking) { 13 | var calendar = CalendarApp.getDefaultCalendar(); 14 | var startTime = new Date(booking.bookingDate + ' ' + booking.startTime); 15 | var endTime = new Date(booking.bookingDate + ' ' + booking.endTime); 16 | var events = calendar.getEvents(startTime, endTime); 17 | return events.length > 0; // If there are events, return true (conflict exists) 18 | } 19 | function createCalendarEvent(booking) { 20 | var calendar = CalendarApp.getDefaultCalendar(); 21 | var title = 'Booking: ' + booking.customerName; 22 | var startTime = new Date(booking.bookingDate + ' ' + booking.startTime); 23 | var endTime = new Date(booking.bookingDate + ' ' + booking.endTime); 24 | var options = {description: 'Booking ID: ' + booking.bookingID}; 25 | 26 | calendar.createEvent(title, startTime, endTime, options); 27 | } 28 | function updateBookingStatus(booking, status) { 29 | var sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Bookings'); 30 | var dataRange = sheet.getDataRange(); 31 | var data = dataRange.getValues(); 32 | 33 | // Find the booking by ID and update its status 34 | for (var i = 1; i < data.length; i++) { 35 | if (data[i][0] == booking.bookingID) { // Assuming BookingID is in the first column 36 | sheet.getRange(i + 1, 7).setValue(status); // Update status in the 7th column 37 | break; 38 | } 39 | } 40 | } 41 | function sendConflictNotification(booking) { 42 | var emailSubject = 'Booking Conflict Notification'; 43 | var emailBody = 'Dear ' + booking.customerName + ',\n\n' + 44 | 'We regret to inform you that your booking for ' + booking.bookingDate + 45 | ' from ' + booking.startTime + ' to ' + booking.endTime + 46 | ' cannot be confirmed due to a scheduling conflict.\n\n' + 47 | 'Please contact us to reschedule your booking.\n\n' + 48 | 'Best regards,\n' + 49 | 'Your Company Name'; 50 | 51 | MailApp.sendEmail(booking.email, emailSubject, emailBody); 52 | } 53 | 54 | function getPendingBookings() { 55 | var sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Bookings'); 56 | var dataRange = sheet.getDataRange(); 57 | var data = dataRange.getValues(); 58 | var pendingBookings = []; 59 | // Skip the header row with an index of 0 by starting with 1 60 | for (var i = 1; i < data.length; i++) { 61 | var row = data[i]; 62 | var status = row[6]; // Assuming status is in the 7th column 63 | if (status === 'Pending') { 64 | var booking = { 65 | bookingID: row[0], 66 | customerName: row[1], 67 | email: row[2], 68 | bookingDate: row[3], 69 | startTime: row[4], 70 | endTime: row[5], 71 | status: row[6] 72 | }; 73 | pendingBookings.push(booking); 74 | } 75 | } 76 | return pendingBookings; 77 | } 78 | -------------------------------------------------------------------------------- /Chapter13/distribute docs to assigned users: -------------------------------------------------------------------------------- 1 | // Function to fetch student list 2 | function getStudentList() { 3 | // Mock student list data 4 | return [ 5 | { name: 'John Doe', email: 'john.doe@example.com' }, 6 | { name: 'Jane Smith', email: 'jane.smith@example.com' }, 7 | { name: 'Alice Johnson', email: 'alice.johnson@example.com' }, 8 | // Add more students as needed 9 | ]; 10 | } 11 | 12 | // Function to fetch research topics 13 | function getResearchTopics() { 14 | // Mock research topics data 15 | return [ 16 | 'Machine Learning', 17 | 'Artificial Intelligence', 18 | 'Data Science', 19 | 'Blockchain', 20 | 'Internet of Things', 21 | // Add more topics as needed 22 | ]; 23 | } 24 | 25 | // Function to distribute assignments 26 | function distributeAssignments() { 27 | const studentList = getStudentList(); // Fetch student list 28 | const topics = getResearchTopics(); // Fetch research topics 29 | const assignmentsFolderId = FOLDERID; // ID of the Drive folder where assignments are stored 30 | 31 | studentList.forEach(function(student, index) { 32 | const doc = DocumentApp.create(student.name + ' Research Assignment'); 33 | const body = doc.getBody(); 34 | const topic = topics[index % topics.length]; // Rotate topics for each student 35 | body.appendParagraph('Research Topic: ' + topic); 36 | body.appendParagraph('Please submit your paper by the due date.'); 37 | 38 | // Move document to the assignments folder 39 | DriveApp.getFileById(doc.getId()).moveTo(DriveApp.getFolderById(assignmentsFolderId)); 40 | 41 | // Send the assignment link to the student 42 | MailApp.sendEmail(student.email, 'Your Research Assignment', 'Please find your assignment here: ' + doc.getUrl()); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /Chapter13/syncBookingsToCalendar: -------------------------------------------------------------------------------- 1 | function syncBookingsToCalendar() { 2 | const bookings = getPendingBookings(); // Assume this fetches bookings from the sheet 3 | bookings.forEach(function (booking) { 4 | if (!checkCalendarConflicts(booking)) { 5 | createCalendarEvent(booking); // Create event if no conflict 6 | updateBookingStatus(booking, 'Confirmed'); // Update status in the sheet 7 | } else { 8 | sendConflictNotification(booking); // Notify user of conflict 9 | } 10 | }); 11 | } 12 | function checkCalendarConflicts(booking) { 13 | var calendar = CalendarApp.getDefaultCalendar(); 14 | var startTime = new Date( booking.startTime); 15 | var endTime = new Date( booking.endTime); 16 | var events = calendar.getEvents(startTime, endTime); 17 | return events.length > 0; // If there are events, return true (conflict exists) 18 | } 19 | 20 | function createCalendarEvent(booking) { 21 | var calendar = CalendarApp.getDefaultCalendar(); 22 | var title = 'Booking: ' + booking.customerName; 23 | var options = {description: 'Booking ID: ' + booking.bookingID}; 24 | Logger.log(booking); 25 | // Directly parse the full date-time strings 26 | var startTime = new Date(booking.startDateTime); 27 | var endTime = new Date(booking.endDateTime); 28 | // Log startTime and endTime for debugging 29 | console.log('Attempting to create event:', title, 'from', startTime, 'to', endTime); 30 | var event = calendar.createEvent(title, startTime, endTime, options); 31 | // Additional log to confirm event creation 32 | if (event) { 33 | console.log('Event created:', event.getId()); 34 | } else { 35 | console.log('Failed to create event.'); 36 | } 37 | } 38 | 39 | 40 | 41 | function updateBookingStatus(booking, status) { 42 | var sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Bookings'); 43 | var dataRange = sheet.getDataRange(); 44 | var data = dataRange.getValues(); 45 | // Find the booking by ID and update its status 46 | for (var i = 1; i < data.length; i++) { 47 | if (data[i][0] == booking.bookingID) { 48 | sheet.getRange(i + 1, 6).setValue(status); // Make sure this points to the correct Status column 49 | break; 50 | } 51 | } 52 | } 53 | 54 | function sendConflictNotification(booking) { 55 | var emailSubject = 'Booking Conflict Notification'; 56 | var emailBody = 'Dear ' + booking.customerName + ',\n\n' + 57 | 'We regret to inform you that your booking for ' + booking.bookingDate + 58 | ' from ' + booking.startTime + ' to ' + booking.endTime + 59 | ' cannot be confirmed due to a scheduling conflict.\n\n' + 60 | 'Please contact us to reschedule your booking.\n\n' + 61 | 'Best regards,\n' + 62 | 'Your Company Name'; 63 | 64 | MailApp.sendEmail(booking.email, emailSubject, emailBody); 65 | } 66 | 67 | function getPendingBookings() { 68 | var sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Bookings'); 69 | var dataRange = sheet.getDataRange(); 70 | var data = dataRange.getValues(); 71 | var pendingBookings = []; 72 | // Skip the header row with an index of 0 by starting with 1 73 | for (var i = 1; i < data.length; i++) { 74 | var row = data[i]; 75 | var status = row[5]; // Assuming status is now in the 6th column 76 | if (status === 'Pending') { 77 | var booking = { 78 | bookingID: row[0], 79 | customerName: row[1], 80 | email: row[4], 81 | startDateTime: row[2], // Adjusted for combined date and time 82 | endDateTime: row[3], // Adjusted for combined date and time 83 | status: row[5] 84 | }; 85 | pendingBookings.push(booking); 86 | } 87 | } 88 | return pendingBookings; 89 | } 90 | -------------------------------------------------------------------------------- /Chapter14/ProcessResponses: -------------------------------------------------------------------------------- 1 | function testProcessResponses() { 2 | const responses = [ 3 | { 4 | name: 'John Doe', 5 | email: 'john.doe@example.com', 6 | feedback: 'Great presentation! Really enjoyed it.' 7 | }, 8 | { 9 | name: 'Jane Smith', 10 | email: 'jane.smith@example.com', 11 | feedback: 'The training was very informative. Thank you!' 12 | }, 13 | // Add more response objects as needed 14 | ]; 15 | // Call processResponses with sample data 16 | responses.forEach(({ name, email, feedback }, index) => { 17 | const message = `Dear ${name}, thank you for your feedback!`; 18 | MailApp.sendEmail(EMAIL, 'Feedback Received', message); 19 | Logger.log(`Feedback from ${name} processed.`); 20 | }); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Chapter14/optimizeDataProcessing: -------------------------------------------------------------------------------- 1 | function optimizeDataProcessing() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getRange('A1:Z'); // Adjust range as needed 4 | const values = range.getValues(); 5 | // Process data in batches instead of cell by cell 6 | const processedValues = values.map(row => { 7 | // Process each row; for example, summing values 8 | const sum = row.reduce((total, cell) => total + (typeof cell === 'number' ? cell : 0), 0); 9 | return [...row, sum]; // Append sum to row 10 | }); 11 | // Write back all processed data at once 12 | sheet.getRange(1, 1, processedValues.length, processedValues[0].length).setValues(processedValues); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter14/scheduleMeetingsFromSheet: -------------------------------------------------------------------------------- 1 | function scheduleMeetingsFromSheet() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName("data"); 3 | const data = sheet.getDataRange().getValues(); 4 | const calendar = CalendarApp.getDefaultCalendar(); 5 | data.forEach((row, index) => { 6 | if (index === 0 || !row[4]) return; // Skip header and already processed rows 7 | const [title, date, attendees, description] = row; 8 | const event = calendar.createEvent(title, new Date(date), new Date(date), {description: description, guests: attendees}); 9 | sheet.getRange(index + 1, 5).setValue('Scheduled'); // Mark as scheduled 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter14/trackUsage: -------------------------------------------------------------------------------- 1 | function trackUsage(functionName, executionTime, user) { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('UsageLogs'); 3 | sheet.appendRow([new Date(), functionName, executionTime, user]); 4 | } 5 | -------------------------------------------------------------------------------- /Chapter2/Debug: -------------------------------------------------------------------------------- 1 | function debugExample() { 2 | Logger.log('This is a debug message'); 3 | const value = 'test'; 4 | Logger.log('The value is: ' + value); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter2/error handling: -------------------------------------------------------------------------------- 1 | function myFunction() { 2 | try { 3 | // Code that may throw an exception 4 | const result = 1 / 0; // Example of code that will cause an exception 5 | } catch (e) { 6 | // Code to handle the exception 7 | Logger.log('An error occurred: ' + e.toString()); 8 | } finally { 9 | // Code that will run regardless of the try / catch result 10 | Logger.log('Function execution has ended.'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter3/A custom function that converts temperatures from Celsius to Fahrenheit: -------------------------------------------------------------------------------- 1 | function CELSIUS_TO_FAHRENHEIT(celsius) { 2 | return (celsius * 9 / 5) + 32; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter3/Accessing a specific spreadsheet and writing data to a cell: -------------------------------------------------------------------------------- 1 | function writeToSheet() { 2 | const sheet = SpreadsheetApp.openById('your-spreadsheet-id').getActiveSheet(); 3 | sheet.getRange('A1').setValue('Hello, Google Sheets!'); 4 | } 5 | -------------------------------------------------------------------------------- /Chapter3/Auto Fill data: -------------------------------------------------------------------------------- 1 | function autoFillData() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const currentDate = new Date(); 4 | const data = [ 5 | [currentDate, 'Customer A', 'Product X', 10], 6 | [currentDate, 'Customer B', 'Product Y', 15] 7 | // Add more rows as needed 8 | ]; 9 | const range = sheet.getRange('A2:D' + (data.length + 1)); 10 | range.setValues(data); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter3/Automatically updating inventory levels: -------------------------------------------------------------------------------- 1 | function updateInventoryData() { 2 | const inventoryData = [ 3 | { item: 'Apples', quantity: 50 }, 4 | { item: 'Bananas', quantity: 30 }, 5 | { item: 'Oranges', quantity: 20 }, 6 | { item: 'Grapes', quantity: 40 }, 7 | { item: 'Strawberries', quantity: 25 } 8 | ]; 9 | 10 | inventoryData.forEach(item => { 11 | updateInventory(item.item, item.quantity); 12 | }); 13 | } 14 | 15 | function updateInventory(item, quantity) { 16 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Inventory'); 17 | const data = sheet.getDataRange().getValues(); 18 | 19 | data.forEach((row, index) => { 20 | if (row[0] === item) { // Assuming the item name is in the first column 21 | const newQuantity = row[1] + quantity; // Assuming the quantity is in the second column 22 | sheet.getRange(index + 1, 2).setValue(newQuantity); // Update the sheet 23 | } 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /Chapter3/Automating Invoice Generation: -------------------------------------------------------------------------------- 1 | function generateInvoice() { 2 | const customerId = '1'; 3 | const invoiceData = getInvoiceDataForCustomer(customerId); // Implement this function based on your data structure 4 | const templateSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('InvoiceTemplate'); 5 | 6 | // Check if invoice sheet already exists for the customer, create one if it doesn't 7 | let invoiceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Invoice - ' + customerId); 8 | 9 | if (!invoiceSheet) { 10 | invoiceSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet('Invoice - ' + customerId); 11 | templateSheet.getRange('A1:Z100').copyTo(invoiceSheet.getRange('A1:Z100')); // Adjust range according to your template size 12 | } else { 13 | // Clear existing content except for the template 14 | invoiceSheet.getRange('A2:Z100').clear(); 15 | } 16 | 17 | // Fill in the invoice details in invoiceSheet using invoiceData 18 | const dataRows = invoiceData.map(item => [item.description, item.quantity, item.unitPrice, item.total]); 19 | invoiceSheet.getRange(2, 1, dataRows.length, dataRows[0].length).setValues(dataRows); 20 | } 21 | 22 | function getInvoiceDataForCustomer(customerId) { 23 | // This function should return invoice data for the given customer ID 24 | // Implement this function based on your data structure 25 | // Example data structure: 26 | const invoiceData = [ 27 | { description: 'Product A', quantity: 2, unitPrice: 10, total: 20 }, 28 | { description: 'Product B', quantity: 1, unitPrice: 15, total: 15 }, 29 | { description: 'Product C', quantity: 3, unitPrice: 8, total: 24 } 30 | ]; 31 | return invoiceData; 32 | } 33 | 34 | function onOpen() { 35 | const ui = SpreadsheetApp.getUi(); 36 | ui.createMenu('Custom Menu') 37 | .addItem('Generate Invoice', 'generateInvoice') 38 | .addToUi(); 39 | } 40 | -------------------------------------------------------------------------------- /Chapter3/Building Custom Inventory Tracking Systems: -------------------------------------------------------------------------------- 1 | function main() { 2 | updateStock(1001, 20); // Add stock 3 | updateStock(1002, -5); // Decrease stock 4 | } 5 | function updateStock(itemID, quantity) { 6 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Inventory"); 7 | const data = sheet.getDataRange().getValues(); 8 | for (let i = 1; i < data.length; i++) { // Start from row 2 to skip headers 9 | if (data[i][0] == itemID) { // Assuming item ID is in the first column 10 | const currentQuantity = data[i][3]; // Assuming current quantity is in the fourth column 11 | sheet.getRange(i + 1, 4).setValue(currentQuantity + quantity); 12 | checkReorderLevel(itemID, data[i][3], data[i][4]); // Check if new stock level is below reorder level 13 | break; 14 | } }} 15 | function checkReorderLevel(itemID, currentQuantity, reorderLevel) { 16 | if (currentQuantity <= reorderLevel) { 17 | MailApp.sendEmail("gappscourses+2@gmail.com", "Reorder Alert for " + itemID, 18 | "The stock level for " + itemID + " has fallen to " + currentQuantity + 19 | ", which is at or below the reorder level of " + reorderLevel + "."); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter3/Conditional Formatting Automation: -------------------------------------------------------------------------------- 1 | function applyConditionalFormatting() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getRange('D2:D100'); // Assuming D column contains quantities 4 | const rule = SpreadsheetApp.newConditionalFormatRule() 5 | .whenNumberLessThan(5) 6 | .setBackground('#FFC7CE') 7 | .setFontColor('#9C0006') 8 | .setRanges([range]) 9 | .build(); 10 | const rules = sheet.getConditionalFormatRules(); 11 | rules.push(rule); 12 | sheet.setConditionalFormatRules(rules); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter3/Creating Custom Data Validation Functions: -------------------------------------------------------------------------------- 1 | function validateEmail(inputCell) { 2 | const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // Regular expression for validating email 3 | return emailPattern.test(inputCell); 4 | } 5 | function testValidateEmail() { 6 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("emails"); // Change "Sheet1" to your sheet's name 7 | const dataRange = sheet.getRange("B2:B13"); // Adjust the range according to your data 8 | const inputStrings = dataRange.getValues(); 9 | 10 | for (let i = 0; i < inputStrings.length; i++) { 11 | const isValid = validateEmail(inputStrings[i][0]); 12 | sheet.getRange(i + 2, 4).setValue(isValid); // Writing result to "Actual Result" column 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter3/Creating the Invoice Template: -------------------------------------------------------------------------------- 1 | function testGen1() { 2 | generateInvoice(1); // Test with client ID 1 3 | } 4 | function sendInvoiceAsPDF(clientId, emailAddress, invoiceSheet) { 5 | const pdf = DriveApp.getFileById(invoiceSheet).getAs('application/pdf'); 6 | const message = 'Dear ' + clientId + ',\nPlease find attached your latest invoice.'; 7 | const subject = 'Your Invoice from [Your Company]'; 8 | MailApp.sendEmail(emailAddress, subject, message, {attachments: [pdf]}); 9 | } 10 | 11 | function generateInvoice(clientId) { 12 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 13 | 14 | const clientSheet = ss.getSheetByName('Clients'); 15 | const invoiceTemplate = ss.getSheetByName('InvoiceTemplate'); 16 | const invoiceSheet = ss.insertSheet('Invoice - ' + clientId); 17 | // Copy the invoice template 18 | invoiceTemplate.getRange('A1:Z100').copyTo(invoiceSheet.getRange('A1:Z100')); 19 | // Fetch client information 20 | const clientInfo = getClientInfo(clientId); // Implement this function based on your Clients sheet 21 | // Replace placeholders with actual data 22 | replacePlaceholder(invoiceSheet, '{{ClientName}}', clientInfo.name); 23 | replacePlaceholder(invoiceSheet, '{{ClientAddress}}', clientInfo.address); 24 | // Add more placeholders as needed 25 | // Send invoice via email (optional) 26 | sendInvoiceAsPDF(clientId, clientInfo.email, ss.getId()); // Implement this function 27 | } 28 | function replacePlaceholder(sheet, placeholder, value) { 29 | const range = sheet.getDataRange(); 30 | const values = range.getValues(); 31 | 32 | for (let i = 0; i < values.length; i++) { 33 | for (let j = 0; j < values[i].length; j++) { 34 | if (values[i][j] === placeholder) { 35 | sheet.getRange(i + 1, j + 1).setValue(value); 36 | } 37 | } 38 | } 39 | } 40 | function getClientInfo(clientId) { 41 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 42 | const clientSheet = ss.getSheetByName('InvoiceTemplate'); 43 | const data = clientSheet.getDataRange().getValues(); 44 | // Assuming the client IDs are in the first column of the Clients sheet 45 | for (let i = 1; i < data.length; i++) { 46 | if (data[i][0] == clientId) { 47 | return { 48 | name: data[i][1], // Assuming client names are in the second column 49 | address: data[i][2], // Assuming client addresses are in the third column 50 | email: data[i][3] // Assuming client emails are in the fourth column 51 | // Add more properties as needed 52 | }; 53 | } 54 | } 55 | // If client ID is not found, return null or handle error as needed 56 | return null; 57 | } 58 | -------------------------------------------------------------------------------- /Chapter3/Developing Dynamic and Interactive Reports: -------------------------------------------------------------------------------- 1 | function onOpen() { 2 | const ui = SpreadsheetApp.getUi(); 3 | ui.createMenu('Custom Report') 4 | .addItem('Refresh Data', 'refreshData') 5 | .addItem('Generate PDF', 'generatePdfReport') 6 | .addToUi(); 7 | } 8 | function generatePdfReport() { 9 | const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId(); 10 | const sheetId = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetId(); 11 | const url = 'https://docs.google.com/spreadsheets/d/' + spreadsheetId + '/export?'; 12 | const exportOptions = 13 | 'exportFormat=pdf&format=pdf' + 14 | '&size=letter' + 15 | '&portrait=true' + 16 | '&fitw=true' + 17 | '&sheetnames=false&printtitle=false' + 18 | '&pagenumbers=false&gridlines=false' + 19 | '&fzr=false' + 20 | '&gid=' + sheetId; 21 | const token = ScriptApp.getOAuthToken(); 22 | const response = UrlFetchApp.fetch(url + exportOptions, { 23 | headers: { 24 | 'Authorization': 'Bearer ' + token 25 | } 26 | }); 27 | const blob = response.getBlob().setName('Custom Report.pdf'); 28 | // Here you can send the PDF via email or save it somewhere 29 | // Email the PDF to the customer 30 | MailApp.sendEmail({ 31 | to: 'gappscourses+2@gmail.com', 32 | subject: 'Sample', 33 | body: "Please find attached.", 34 | attachments: [blob] 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /Chapter3/Generating a report with a button click:: -------------------------------------------------------------------------------- 1 | function generateReport() { 2 | // Check if 'Report' sheet exists, create one if it doesn't 3 | const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 4 | let sheet = spreadsheet.getSheetByName('Report'); 5 | 6 | if (!sheet) { 7 | sheet = spreadsheet.insertSheet('Report'); 8 | } 9 | 10 | // Clear existing content 11 | sheet.clear(); 12 | 13 | // Insert headers 14 | const headers = ['Column A', 'Column B', 'Column C']; // Example headers 15 | sheet.getRange(1, 1, 1, headers.length).setValues([headers]); 16 | 17 | // Insert data 18 | const data = [ 19 | { data1: 'Value 1', data2: 'Value 2', data3: 'Value 3' }, 20 | { data1: 'Value 4', data2: 'Value 5', data3: 'Value 6' }, 21 | { data1: 'Value 7', data2: 'Value 8', data3: 'Value 9' } 22 | ]; 23 | 24 | const dataArray = data.map(item => [item.data1, item.data2, item.data3]); 25 | sheet.getRange(2, 1, dataArray.length, dataArray[0].length).setValues(dataArray); 26 | 27 | // Add timestamp 28 | sheet.getRange('A1').setValue('Report generated on ' + new Date()); 29 | } 30 | 31 | function onOpen() { 32 | const ui = SpreadsheetApp.getUi(); 33 | ui.createMenu('Custom Menu') 34 | .addItem('Generate Report', 'generateReport') 35 | .addToUi(); 36 | } 37 | -------------------------------------------------------------------------------- /Chapter3/Using sheet data for cleint info for invoice: -------------------------------------------------------------------------------- 1 | function testGen1() { 2 | generateInvoice(1); // Test with client ID 1 3 | } 4 | 5 | function sendInvoiceAsPDF(clientId, emailAddress, invoiceSheet) { 6 | const pdf = DriveApp.getFileById(invoiceSheet).getAs('application/pdf'); 7 | const message = 'Dear ' + clientId + ',\nPlease find attached your latest invoice.'; 8 | const subject = 'Your Invoice from [Your Company]'; 9 | MailApp.sendEmail(emailAddress, subject, message, {attachments: [pdf]}); 10 | } 11 | 12 | function generateInvoice(clientId) { 13 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 14 | 15 | // Ensure 'InvoiceTemplate' sheet exists 16 | let invoiceTemplate = ss.getSheetByName('InvoiceTemplate'); 17 | if (!invoiceTemplate) { 18 | return; // Exit function if template sheet doesn't exist 19 | } 20 | 21 | const invoiceSheet = ss.insertSheet('Invoice - ' + clientId); 22 | 23 | // Copy the invoice template 24 | invoiceTemplate.getRange('A1:Z100').copyTo(invoiceSheet.getRange('A1:Z100')); 25 | 26 | // Fetch client information 27 | const clientInfo = getClientInfo(clientId); // Implement this function based on your Clients sheet 28 | 29 | if (!clientInfo) { 30 | return; // Exit function if client info is not found 31 | } 32 | 33 | // Replace placeholders with actual data 34 | replacePlaceholder(invoiceSheet, '{{ClientName}}', clientInfo.name); 35 | replacePlaceholder(invoiceSheet, '{{ClientAddress}}', clientInfo.address); 36 | replacePlaceholder(invoiceSheet, '{{ClientEmail}}', clientInfo.email); 37 | 38 | // Send invoice via email (optional) 39 | sendInvoiceAsPDF(clientId, clientInfo.email, invoiceSheet.getId()); // Implement this function 40 | } 41 | 42 | function replacePlaceholder(sheet, placeholder, value) { 43 | const range = sheet.getDataRange(); 44 | const values = range.getValues(); 45 | 46 | for (let i = 0; i < values.length; i++) { 47 | for (let j = 0; j < values[i].length; j++) { 48 | if (values[i][j] === placeholder) { 49 | sheet.getRange(i + 1, j + 1).setValue(value); 50 | } 51 | } 52 | } 53 | } 54 | 55 | function getClientInfo(clientId) { 56 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 57 | const clientSheet = ss.getSheetByName('Clients'); 58 | if (!clientSheet) { 59 | return null; // Exit function if Clients sheet doesn't exist 60 | } 61 | 62 | const data = clientSheet.getDataRange().getValues(); 63 | // Assuming the client IDs are in the first column of the Clients sheet 64 | for (let i = 1; i < data.length; i++) { 65 | if (data[i][0] == clientId) { 66 | return { 67 | name: data[i][1], // Assuming client names are in the second column 68 | address: data[i][2], // Assuming client addresses are in the third column 69 | email: data[i][3] // Assuming client emails are in the fourth column 70 | // Add more properties as needed 71 | }; 72 | } 73 | } 74 | // If client ID is not found, return null or handle error as needed 75 | return null; 76 | } 77 | -------------------------------------------------------------------------------- /Chapter3/add a new sheet: -------------------------------------------------------------------------------- 1 | function addNewSheet() { 2 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 | const newSheetName = 'Data-' + new Date().toISOString().slice(0, 10); // YYYY-MM-DD format 4 | ss.insertSheet(newSheetName); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter3/check and mark invalid emails: -------------------------------------------------------------------------------- 1 | function checkAndMarkInvalidEmails() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('emails'); 3 | const emails = sheet.getDataRange().getValues(); // Adjust range accordingly 4 | const invalidEmailsRange = []; 5 | emails.forEach(function (email, index) { 6 | if (!validateEmail(email[1])) { // If the email is invalid 7 | invalidEmailsRange.push('B' + (index + 1)); // Collect range of invalid emails 8 | } 9 | }); 10 | Logger.log(invalidEmailsRange); 11 | sheet.getRange('B2:B').clearFormat(); 12 | // Highlight invalid emails 13 | if (invalidEmailsRange.length > 0) { 14 | sheet.getRangeList(invalidEmailsRange).setBackground('red'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter3/clear range: -------------------------------------------------------------------------------- 1 | function clearRange() { 2 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 | const sheet = ss.getActiveSheet(); 4 | const range = sheet.getRange('D1:E10'); 5 | range.clear(); // Clears content and formatting. Use clearContent() or clearFormat() for specific clear actions. 6 | } 7 | -------------------------------------------------------------------------------- /Chapter3/copy range of data: -------------------------------------------------------------------------------- 1 | function copyRange() { 2 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 | const sourceSheet = ss.getSheetByName('Source'); 4 | const targetSheet = ss.getSheetByName('Target'); 5 | const sourceRange = sourceSheet.getRange('A1:C10'); 6 | const targetRange = targetSheet.getRange('A1:C10'); 7 | sourceRange.copyTo(targetRange); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter3/create Sheets PDF invoice: -------------------------------------------------------------------------------- 1 | function createInvoiceAndEmail() { 2 | // Sample JSON data 3 | var jsonData = { 4 | "invoiceNumber": "123456", 5 | "date": "2024-03-07", 6 | "customerEmail": "gappscourses+2@gmail.com", 7 | "items": [ 8 | { "description": "Item 1", "quantity": 2, "price": 10 }, 9 | { "description": "Item 2", "quantity": 1, "price": 20 } 10 | ] 11 | }; 12 | // Create a new Spreadsheet for the Invoice 13 | var spreadsheet = SpreadsheetApp.create(`Invoice #${jsonData.invoiceNumber}`); 14 | var sheet = spreadsheet.getActiveSheet(); 15 | // Set up the Invoice header 16 | var headers = [["Invoice Number", jsonData.invoiceNumber], ["Date", jsonData.date]]; 17 | sheet.getRange(1, 1, headers.length, 2).setValues(headers); 18 | // Set up the column headers for items 19 | var itemHeaders = [["Description", "Quantity", "Price", "Total"]]; 20 | sheet.getRange(4, 1, 1, 4).setValues(itemHeaders); 21 | // Populate the items in the invoice 22 | var itemsData = jsonData.items.map(function (item) { 23 | return [item.description, item.quantity, item.price, item.quantity * item.price]; 24 | }); 25 | sheet.getRange(5, 1, itemsData.length, 4).setValues(itemsData); 26 | // Adjust column widths for readability 27 | sheet.autoResizeColumns(1, 4); 28 | // Convert the spreadsheet to PDF 29 | SpreadsheetApp.flush(); 30 | Utilities.sleep(1000); // Delays for 1 second (1000 milliseconds) 31 | const file = sendPDF(spreadsheet.getId(), jsonData.invoiceNumber, jsonData.customerEmail); 32 | // Optionally, delete the spreadsheet if you don't want to keep it in your drive 33 | DriveApp.getFileById(spreadsheet.getId()).setTrashed(true); 34 | } 35 | 36 | 37 | function sendPDF(id, invoiceNumber, customerEmail) { 38 | const pdfBlob = DriveApp.getFileById(id).getAs('application/pdf').setName(`Invoice-${invoiceNumber}.pdf`); 39 | // Email the PDF to the customer 40 | MailApp.sendEmail({ 41 | to: customerEmail, 42 | subject: `Invoice #${invoiceNumber}`, 43 | body: "Please find attached your invoice.", 44 | attachments: [pdfBlob] 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /Chapter3/create backup file: -------------------------------------------------------------------------------- 1 | function createBackup() { 2 | const originalSpreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 3 | const date = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyyMMdd'); 4 | const newTitle = originalSpreadsheet.getName() + ' Backup ' + date; 5 | DriveApp.getFileById(originalSpreadsheet.getId()).makeCopy(newTitle); 6 | } 7 | -------------------------------------------------------------------------------- /Chapter3/custom function highest sales: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the highest sales figure from the range. 3 | * 4 | * @param {Array} salesData Range containing sales figures. 5 | * @return {number} The highest sales figure. 6 | * @customfunction 7 | */ 8 | function HIGHEST_SALE(salesData) { 9 | let highestSale = 0; 10 | salesData.forEach(function(row) { 11 | row.forEach(function(cell) { 12 | if (cell > highestSale) { 13 | highestSale = cell; 14 | } 15 | }); 16 | }); 17 | return highestSale; 18 | } 19 | -------------------------------------------------------------------------------- /Chapter3/delete a sheet: -------------------------------------------------------------------------------- 1 | function deleteSheet(sheetName) { 2 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 | const sheet = ss.getSheetByName(sheetName); 4 | if (sheet) { 5 | ss.deleteSheet(sheet); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter3/remove duplicates: -------------------------------------------------------------------------------- 1 | function removeDuplicates() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const data = sheet.getDataRange().getValues(); 4 | const uniqueData = []; 5 | const duplicateIndices = []; 6 | data.forEach((row, index) => { 7 | const serializedRow = row.join('-'); // Create a string representation of the row 8 | if (uniqueData.indexOf(serializedRow) === -1) { 9 | uniqueData.push(serializedRow); // Add unique row to the list 10 | } else { 11 | duplicateIndices.push(index + 1); // +1 because array is 0-based but Sheets are 1-based 12 | } }); 13 | // Remove duplicates from the bottom to not mess up the indices 14 | duplicateIndices.reverse().forEach((rowIndex) => { 15 | sheet.deleteRow(rowIndex); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter3/rename sheet with testing function: -------------------------------------------------------------------------------- 1 | function renameSheet(oldName, newName) { 2 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 | const sheet = ss.getSheetByName(oldName); 4 | if (sheet) { 5 | sheet.setName(newName); 6 | } else { 7 | Logger.log('Sheet not found.'); 8 | } 9 | } 10 | function testRenameSheet() { 11 | // Array of test cases with old and new names 12 | const testCases = [ 13 | {oldName: "Sheet9", newName: "RenamedSheet1"}, 14 | {oldName: "SheetDoesNotExist", newName: "ShouldFail"}, 15 | {oldName: "Sheet2", newName: "RenamedSheet2"} 16 | // Add more test cases as needed 17 | ]; 18 | 19 | // Iterate through each test case and attempt to rename the sheet 20 | testCases.forEach((testCase) => { 21 | try { 22 | renameSheet(testCase.oldName, testCase.newName); 23 | // Check if rename was successful by attempting to get the sheet with the new name 24 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 25 | const sheet = ss.getSheetByName(testCase.newName); 26 | if (sheet) { 27 | Logger.log(`Successfully renamed '${testCase.oldName}' to '${testCase.newName}'.`); 28 | } else { 29 | // If the sheet with the new name is not found, it indicates a failure in renaming 30 | Logger.log(`Failed to rename '${testCase.oldName}'. The sheet with the new name '${testCase.newName}' was not found.`); 31 | } 32 | } catch (e) { 33 | // Log any errors that occur during the renaming process 34 | Logger.log(`Error renaming sheet from '${testCase.oldName}' to '${testCase.newName}': ${e.message}`); 35 | } 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /Chapter3/sort data: -------------------------------------------------------------------------------- 1 | function sortData() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getDataRange(); // Sorts all data in the sheet 4 | range.sort({column: 2, ascending: true}); // Assuming column 2 (B) holds the data to sort by 5 | } 6 | -------------------------------------------------------------------------------- /Chapter3/udpate range: -------------------------------------------------------------------------------- 1 | function updateRange() { 2 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 3 | const sheet = ss.getActiveSheet(); 4 | const range = sheet.getRange('A1:B10'); 5 | range.setValue('Updated'); // Sets all cells in the range to 'Updated' 6 | } 7 | -------------------------------------------------------------------------------- /Chapter4/Basic Text Parsing and Manipulation Extracting Specific Text Segments: -------------------------------------------------------------------------------- 1 | function extractTextSegments() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const bodyText = doc.getBody().getText(); 4 | const segments = bodyText.match(/Important: ([^\n]+)/g); // Regex to extract lines starting with 'Important:' 5 | if (segments) { 6 | segments.forEach(function(segment) { 7 | Logger.log(segment); // Log extracted segments 8 | }); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter4/Batch update format: -------------------------------------------------------------------------------- 1 | function batchUpdateFormat(docId) { 2 | const doc = DocumentApp.openById(docId); 3 | const body = doc.getBody(); 4 | // Assuming you want to format the first 5 paragraphs 5 | const paragraphs = body.getParagraphs().slice(0, 5); 6 | paragraphs.forEach(function(paragraph) { 7 | paragraph.editAsText().setBold(true).setForegroundColor('#555555'); 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter4/Cereate new table: -------------------------------------------------------------------------------- 1 | function createTable() { 2 | const doc = DocumentApp.getActiveDocument(); 3 | const body = doc.getBody(); 4 | const data = [ 5 | ['Header 1', 'Header 2', 'Header 3'], 6 | ['Row 1, Cell 1', 'Row 1, Cell 2', 'Row 1, Cell 3'], 7 | ['Row 2, Cell 1', 'Row 2, Cell 2', 'Row 2, Cell 3'] 8 | ]; 9 | const table = body.appendTable(data); 10 | // Format the header row 11 | const headerRow = table.getRow(0); 12 | headerRow.setBackgroundColor('#f1f1f1'); 13 | for (let i = 0; i < headerRow.getNumCells(); i++) { 14 | headerRow.getCell(i).setBold(true); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter4/Highlight existing text: -------------------------------------------------------------------------------- 1 | function highlightText() { 2 | const keyword = 'Highlight'; 3 | const doc = DocumentApp.openById(DOCID); 4 | const body = doc.getBody(); 5 | let foundElements = body.findText(keyword); 6 | while (foundElements) { 7 | const foundText = foundElements.getElement().asText(); 8 | const startOffset = foundElements.getStartOffset(); 9 | const endOffset = foundElements.getEndOffsetInclusive(); 10 | foundText.setBold(startOffset, endOffset, true); // Set the found text to bold 11 | foundText.setForegroundColor(startOffset, endOffset, '#FF0000'); // Change text color to red 12 | foundElements = body.findText(keyword, foundElements); // Find next instance 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter4/Mail Merge Docs: -------------------------------------------------------------------------------- 1 | function mailMerge() { 2 | const recipients = [['John Doe', 'john@example.com'], ['Jane Smith', 'jane@example.com']]; 3 | const templateId = DOCID; 4 | recipients.forEach(function (recipient) { 5 | const copiedFile = DriveApp.getFileById(templateId).makeCopy('Letter to ' + recipient[0]); 6 | const copiedFileId = copiedFile.getId(); 7 | // Then open the copied document for editing 8 | const doc = DocumentApp.openById(copiedFileId); 9 | const body = doc.getBody(); 10 | body.replaceText('{{name}}', recipient[0]); 11 | body.replaceText('{{email}}', recipient[1]); 12 | doc.saveAndClose(); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter4/Mail merge with Sheets Data: -------------------------------------------------------------------------------- 1 | function runMailMerge() { 2 | const sheetId = SHEEETID; 3 | const templateId = DOCID; 4 | performMailMerge(sheetId, templateId); 5 | } 6 | function performMailMerge(sheetId, templateId) { 7 | const sheetData = SpreadsheetApp.openById(sheetId).getDataRange().getValues(); 8 | sheetData.shift(); // Remove header row 9 | sheetData.forEach(function (row) { 10 | const doc = DriveApp.getFileById(templateId).makeCopy(); 11 | const docBody = DocumentApp.openById(doc.getId()).getBody(); 12 | // Assuming the spreadsheet columns are Name, Date, Address respectively 13 | docBody.replaceText('{{Name}}', row[0]); 14 | docBody.replaceText('{{Date}}', row[1]); 15 | docBody.replaceText('{{Address}}', row[2]); 16 | // Further processing like renaming the document, sharing, or emailing can be done here 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /Chapter4/Sheet Data report: -------------------------------------------------------------------------------- 1 | function getReportData() { 2 | // Example: Fetching data from a Google Sheet 3 | const sheetId = SHEEETID; // Replace with your actual sheet ID 4 | const rangeName = 'Sheet1!A1:E10'; // Adjust the range according to your data 5 | const values = SpreadsheetApp.openById(sheetId).getSheets()[0].getDataRange().getValues(); 6 | if (!values) { 7 | Logger.log('No data found.'); 8 | return []; 9 | } 10 | return values; 11 | } 12 | 13 | function generateTableReport() { 14 | const data = getReportData(); 15 | const doc = DocumentApp.create('Monthly Sales Report'); 16 | const body = doc.getBody(); 17 | // Insert report title and date 18 | body.appendParagraph('Monthly Sales Report').setHeading(DocumentApp.ParagraphHeading.HEADING1); 19 | body.appendParagraph('Date: ' + Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MMMM dd, yyyy")); 20 | // Insert data as a table in the document 21 | body.appendTable(data); 22 | Logger.log('Report generated: ' + doc.getUrl()); 23 | } 24 | -------------------------------------------------------------------------------- /Chapter4/Sheet Data to Docs sheet report: -------------------------------------------------------------------------------- 1 | function generateSheetReport() { 2 | const data = getDataFromSheet(); // Implement this function to fetch data from a sheet 3 | const documentId = 'your-document-id'; 4 | const doc = DocumentApp.openById(DOCID); 5 | const body = doc.getBody(); 6 | 7 | // Example: Append data as new paragraphs 8 | data.forEach(function(item) { 9 | body.appendParagraph('Name: ' + item.name); 10 | body.appendParagraph('Sales: ' + item.sales); 11 | body.appendPageBreak(); // Add a page break after each item 12 | }); 13 | } 14 | function getDataFromSheet() { 15 | const sheet = SpreadsheetApp.openById(SHEEETID).getSheets()[0]; 16 | const range = sheet.getDataRange(); 17 | const values = range.getValues(); 18 | 19 | const data = []; 20 | // Assuming the first row contains headers: Name, Sales 21 | for (let i = 1; i < values.length; i++) { 22 | const row = values[i]; 23 | data.push({ 24 | name: row[0], // Assuming the first column contains the name 25 | sales: row[1] // Assuming the second column contains the sales 26 | }); 27 | } 28 | return data; 29 | } 30 | -------------------------------------------------------------------------------- /Chapter4/access doc: -------------------------------------------------------------------------------- 1 | function openDocument() { 2 | const documentId = 'your-document-id'; // Replace with your document's ID 3 | const doc = DocumentApp.openById(documentId); 4 | const body = doc.getBody(); 5 | // Now you can interact with the document's body 6 | } 7 | -------------------------------------------------------------------------------- /Chapter4/analyze text data: -------------------------------------------------------------------------------- 1 | function analyzeTextData() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const text = doc.getBody().getText(); 4 | const words = text.split(/\s+/); // Split text into words based on whitespace 5 | const wordCount = {}; 6 | words.forEach(function(word) { 7 | word = word.toLowerCase(); 8 | wordCount[word] = (wordCount[word] || 0) + 1; // Increment word count 9 | }); 10 | for (let word in wordCount) { 11 | Logger.log(word + ': ' + wordCount[word]); // Log each word's count 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter4/apply style to doc: -------------------------------------------------------------------------------- 1 | function formatTextInDocument() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const body = doc.getBody(); 4 | const text = body.editAsText(); 5 | text.setFontSize(11).setBold(true).setForegroundColor('#FF0000'); 6 | } 7 | -------------------------------------------------------------------------------- /Chapter4/create doc from template: -------------------------------------------------------------------------------- 1 | function test() { 2 | const data = { 3 | "name": "Alex Johnson", 4 | "date": "2024-03-10", 5 | "address": "1234 Elm Street, YourCity, YourState, 12345" 6 | } 7 | const url = createDocumentFromTemplate(data); 8 | Logger.log(url); 9 | } 10 | function createDocumentFromTemplate(data) { 11 | const doc = DriveApp.getFileById(DOCID).makeCopy(); 12 | const id = doc.getId(); 13 | const body = DocumentApp.openById(id).getBody(); 14 | // Replace placeholders with actual data 15 | body.replaceText('{{Name}}', data.name); 16 | body.replaceText('{{Date}}', data.date); 17 | body.replaceText('{{Address}}', data.address); 18 | return DocumentApp.openById(id).getUrl(); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter4/create list items: -------------------------------------------------------------------------------- 1 | function createList() { 2 | const doc = DocumentApp.getActiveDocument(); 3 | const body = doc.getBody(); 4 | // Create a bulleted list 5 | const items = ['Item 1', 'Item 2', 'Item 3']; 6 | items.forEach(function(item) { 7 | body.appendListItem(item).setGlyphType(DocumentApp.GlyphType.BULLET); 8 | }); 9 | // Add a spacer between lists 10 | body.appendParagraph(''); 11 | // Create a numbered list 12 | let listItem = body.appendListItem(items[0]).setGlyphType(DocumentApp.GlyphType.NUMBER).setNestingLevel(0); 13 | let listId = listItem.getListId(); // Get the list ID of the first item to ensure subsequent items belong to the same list 14 | for (let i = 1; i < items.length; i++) { 15 | listItem = body.appendListItem(items[i]) 16 | .setGlyphType(DocumentApp.GlyphType.NUMBER) 17 | .setNestingLevel(0); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter4/create new doc: -------------------------------------------------------------------------------- 1 | function createNewDocument() { 2 | const doc = DocumentApp.create('New Automated Document'); 3 | const body = doc.getBody(); 4 | body.appendParagraph('This is a new paragraph in the newly created document.'); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter4/creating headings: -------------------------------------------------------------------------------- 1 | function createHeadings() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const body = doc.getBody(); 4 | body.appendParagraph('Main Heading').setHeading(DocumentApp.ParagraphHeading.HEADING1); 5 | body.appendParagraph('Subheading').setHeading(DocumentApp.ParagraphHeading.HEADING2); 6 | } 7 | -------------------------------------------------------------------------------- /Chapter4/email doc as PDF: -------------------------------------------------------------------------------- 1 | function emailReportAsPDF( ) { 2 | const doc = DocumentApp.openById(DOCID); 3 | const pdf = doc.getAs('application/pdf'); 4 | const recipientEmail = 'gappscourses+2@gmail.com'; 5 | const subject = 'Monthly Sales Report'; 6 | const body = 'Please find attached the Monthly Sales Report.'; 7 | MailApp.sendEmail({ 8 | to: recipientEmail, 9 | subject: subject, 10 | body: body, 11 | attachments: [pdf] 12 | }); 13 | Logger.log('Report emailed to: ' + recipientEmail); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter4/format document H1: -------------------------------------------------------------------------------- 1 | function formatDocumentH1() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const body = doc.getBody(); 4 | // Apply heading to the first paragraph 5 | const firstParagraph = body.getParagraphs()[0]; 6 | firstParagraph.setHeading(DocumentApp.ParagraphHeading.HEADING1); 7 | // Change font and size of the second paragraph 8 | const secondParagraph = body.getParagraphs()[1]; 9 | secondParagraph.editAsText().setFontFamily('Arial').setFontSize(12); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter4/format for printing: -------------------------------------------------------------------------------- 1 | function formatReportForPrinting() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const body = doc.getBody(); 4 | // Set custom page margins: top, right, bottom, left (in points) 5 | doc.getBody().setMarginTop(72) // 1 inch 6 | .setMarginRight(72) 7 | .setMarginBottom(72) 8 | .setMarginLeft(72); 9 | // Apply styles to headings and content for better readability 10 | const paragraphs = body.getParagraphs(); 11 | paragraphs.forEach(function (paragraph, index) { 12 | if (index === 0) { // Assuming first paragraph is the title 13 | paragraph.setHeading(DocumentApp.ParagraphHeading.HEADING1); 14 | } else if (paragraph.getText().startsWith('Section')) { // Section headings 15 | paragraph.setHeading(DocumentApp.ParagraphHeading.HEADING2); 16 | } else { 17 | paragraph.setAlignment(DocumentApp.HorizontalAlignment.JUSTIFY); 18 | } 19 | }); // Set document to landscape orientation 20 | const style = {}; 21 | style[DocumentApp.Attribute.PAGE_WIDTH] = 842; // A4 paper size in points 22 | style[DocumentApp.Attribute.PAGE_HEIGHT] = 595; 23 | body.setAttributes(style); 24 | } 25 | -------------------------------------------------------------------------------- /Chapter4/format text in doc: -------------------------------------------------------------------------------- 1 | function formatTextInDoc() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const body = doc.getBody(); 4 | const paragraph = body.getParagraphs()[0]; // Get the first paragraph 5 | paragraph.editAsText() 6 | .setBold(true) 7 | .setFontSize(14) 8 | .setForegroundColor('#FF0000'); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter4/generate report: -------------------------------------------------------------------------------- 1 | function generateReport() { 2 | const data = [['Name', 'Sales'], ['Alice', 1500], ['Bob', 1200]]; // Example data 3 | const templateId = '1LAa1p4eY9cE3Z1EFZZ_ILmK_TEzEZAmhe1SdQFR5W50'; 4 | // Use DriveApp to copy the document 5 | const copiedFile = DriveApp.getFileById(templateId).makeCopy('Sales Report'); 6 | const copiedFileId = copiedFile.getId(); 7 | // Then open the copied document for editing 8 | const doc = DocumentApp.openById(copiedFileId); 9 | const body = doc.getBody(); 10 | data.forEach(function(row, index) { 11 | if (index === 0) { // Assuming first row is headers 12 | // Creating a new paragraph for each header and setting it to bold 13 | body.appendParagraph(row.join('\t')).setBold(true); 14 | } else { 15 | // Creating a new paragraph for each data row 16 | body.appendParagraph(row.join('\t')); 17 | } 18 | }); 19 | // No need to explicitly save, as changes are automatically saved 20 | doc.saveAndClose(); // This line can actually be omitted as the document is auto-saved 21 | } 22 | -------------------------------------------------------------------------------- /Chapter4/generate report from Sheets data: -------------------------------------------------------------------------------- 1 | function runGenerateReport() { 2 | // Replace these with your actual Spreadsheet and Document template IDs 3 | const sheetId = SHEEETID; 4 | const docTemplateId = DOCID; 5 | generateReportFromSheet(sheetId, docTemplateId); 6 | } 7 | function generateReportFromSheet(sheetId, docTemplateId) { 8 | const values = SpreadsheetApp.openById(sheetId).getSheets()[0].getDataRange().getValues(); 9 | const docCopy = DriveApp.getFileById(docTemplateId).makeCopy(); 10 | const body = DocumentApp.openById(docCopy.getId()).getBody(); 11 | values.forEach(function(row, index) { 12 | if (index === 0) return; // Skip header row 13 | const paragraph = body.appendParagraph(''); 14 | row.forEach(function(cell) { 15 | paragraph.appendText(cell + '\t'); 16 | }); 17 | paragraph.appendText('\n'); // New line for each row of data 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter4/generate table data: -------------------------------------------------------------------------------- 1 | function generateDataTable(docId, data) { 2 | const doc = DocumentApp.openById(docId); 3 | const body = doc.getBody(); 4 | const table = body.appendTable(); 5 | data.forEach(function(rowData) { 6 | const row = table.appendTableRow(); 7 | rowData.forEach(function(cellData) { 8 | row.appendTableCell(cellData.toString()); 9 | }); 10 | }); 11 | } 12 | function addSampleDataTable() { 13 | const docId = DOCID; // Replace with your actual document ID 14 | const data = [ 15 | ['Product Name', 'Quantity', 'Price'], // Header row 16 | ['Apples', '10', '$2.00'], 17 | ['Bananas', '8', '$1.50'], 18 | ['Carrots', '15', '$3.00'] 19 | ]; 20 | generateDataTable(docId, data); 21 | } 22 | -------------------------------------------------------------------------------- /Chapter4/headers in table doc: -------------------------------------------------------------------------------- 1 | function manipulateTables() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const body = doc.getBody(); 4 | // Create a table 5 | const table = body.appendTable([ 6 | ['Header 1', 'Header 2'], 7 | ['Cell 1', 'Cell 2'] 8 | ]); 9 | // Format the first row as header 10 | table.getRow(0).editAsText().setBold(true); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter4/insert image: -------------------------------------------------------------------------------- 1 | function insertImage() { 2 | const doc = DocumentApp.getActiveDocument(); 3 | const body = doc.getBody(); 4 | const imageUrl = 'https://www.discoveryvip.com/img/d.png'; // Replace with your image URL 5 | // Fetch the image and insert it into the document 6 | const response = UrlFetchApp.fetch(imageUrl); 7 | const imageBlob = response.getBlob(); 8 | body.appendImage(imageBlob); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter4/insert on condition: -------------------------------------------------------------------------------- 1 | function insertConditionalText() { 2 | const userData = { 3 | name: "John Doe", 4 | membershipLevel: "Gold" // or "Silver", "Bronze", etc., based on your program's levels 5 | }; 6 | const doc = DocumentApp.openById(DOCID); 7 | const body = doc.getBody(); 8 | if (userData.membershipLevel === 'Gold') { 9 | body.appendParagraph('Thank you for being a Gold member!'); 10 | } else { 11 | body.appendParagraph('Become a Gold member to enjoy more benefits.'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter4/modify doc: -------------------------------------------------------------------------------- 1 | function appendTextToDocument() { 2 | const documentId = 'your-document-id'; 3 | const doc = DocumentApp.openById(documentId); 4 | const body = doc.getBody(); 5 | // Append text to the end of the document 6 | body.appendParagraph('This is new text added to the document.'); 7 | } 8 | -------------------------------------------------------------------------------- /Chapter4/pivot table in sheets: -------------------------------------------------------------------------------- 1 | function createPivotTable() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getDataRange(); 4 | const pivotTableSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(); 5 | const pivotTableRange = pivotTableSheet.getRange('A1'); 6 | const pivotTable = pivotTableRange.createPivotTable(range); 7 | pivotTable.addRowGroup(1); // Group data by the values in the first column 8 | pivotTable.addPivotValue(2, SpreadsheetApp.PivotTableSummarizeFunction.SUM); // Sum values from the second column 9 | } 10 | -------------------------------------------------------------------------------- /Chapter4/read doc contents: -------------------------------------------------------------------------------- 1 | function extractDocumentText() { 2 | const documentId = 'your-document-id'; 3 | const doc = DocumentApp.openById(documentId); 4 | const body = doc.getBody(); 5 | const text = body.getText(); 6 | Logger.log(text); // Outputs the entire document text to the logs 7 | } 8 | -------------------------------------------------------------------------------- /Chapter4/replace text in doc: -------------------------------------------------------------------------------- 1 | function replaceTextInDocument() { 2 | const documentId = 'your-document-id'; 3 | const doc = DocumentApp.openById(documentId); 4 | const body = doc.getBody(); 5 | 6 | // Replace occurrences of 'old text' with 'new text' 7 | body.replaceText('old text', 'new text'); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter4/resize image: -------------------------------------------------------------------------------- 1 | function resizeImage() { 2 | const doc = DocumentApp.getActiveDocument(); 3 | const body = doc.getBody(); 4 | const images = body.getImages(); 5 | if (images.length > 0) { 6 | const image = images[0]; // Get the first image 7 | image.setHeight(150).setWidth(150); // Resize the image 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter4/update existing doc: -------------------------------------------------------------------------------- 1 | const DOCID = '1LAa1p4eY9cE3Z1EFZZ_ILmK_TEzEZAmhe1SdQFR5W50'; 2 | function addContentToDocument() { 3 | const docId = 'your-document-id'; 4 | const doc = DocumentApp.openById(DOCID); 5 | const body = doc.getBody(); 6 | body.appendParagraph('New content added to the existing document.'); 7 | } 8 | -------------------------------------------------------------------------------- /Chapter4/update list items: -------------------------------------------------------------------------------- 1 | function updateListProperties() { 2 | const doc = DocumentApp.getActiveDocument(); 3 | const body = doc.getBody(); 4 | const listItems = body.getListItems(); 5 | listItems.forEach(function(listItem) { 6 | listItem.setIndentStart(40).setLineSpacing(1.5); // Change indent and line spacing 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter4/update table: -------------------------------------------------------------------------------- 1 | function updateTable() { 2 | const doc = DocumentApp.getActiveDocument(); 3 | const body = doc.getBody(); 4 | const tables = body.getTables(); 5 | if (tables.length > 0) { 6 | const table = tables[0]; // Get the first table 7 | table.getRow(1).getCell(2).setText('Updated Text'); // Update text in Row 2, Column 3 8 | table.getRow(1).getCell(2).setBackgroundColor('#add8e6'); // Change background color 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter5/Accessing Form Responses: -------------------------------------------------------------------------------- 1 | function getFormResponses() { 2 | const form = FormApp.openById(FORMID); 3 | const responses = form.getResponses(); 4 | // Process each response 5 | responses.forEach(function(response) { 6 | const items = response.getItemResponses(); 7 | items.forEach(function(item) { 8 | const question = item.getItem().getTitle(); 9 | const answer = item.getResponse(); 10 | // Do something with question and answer 11 | }); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter5/Advanced form creation from sheets: -------------------------------------------------------------------------------- 1 | function createAdvancedFormFromSheet() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data2'); 3 | const range = sheet.getDataRange(); 4 | const values = range.getValues(); 5 | const form = FormApp.create('Advanced Form from Spreadsheet'); 6 | values.forEach(function (row, index) { 7 | if (index === 0) return; // Skip header 8 | const type = row[0]; // Question type 9 | const question = row[1]; // Question text 10 | const options = row.slice(2); // Options for multiple choice 11 | switch (type) { 12 | case 'MULTIPLE_CHOICE': 13 | const multipleChoiceItem = form.addMultipleChoiceItem(); 14 | multipleChoiceItem.setTitle(question); 15 | const choices = options.map(option => multipleChoiceItem.createChoice(option)); 16 | multipleChoiceItem.setChoices(choices); 17 | break; 18 | case 'TEXT': 19 | form.addTextItem() 20 | .setTitle(question); 21 | break; 22 | case 'PARAGRAPH_TEXT': 23 | form.addParagraphTextItem() 24 | .setTitle(question); 25 | break; 26 | // Add more cases as needed 27 | } 28 | }); 29 | Logger.log('Advanced form created: ' + form.getPublishedUrl()); 30 | } 31 | -------------------------------------------------------------------------------- /Chapter5/Automating Feedback and Follow-up Processes: -------------------------------------------------------------------------------- 1 | function sendCustomEmailResponses() { 2 | const form = FormApp.openById(FORMID); 3 | const formResponses = form.getResponses(); 4 | const latestResponse = formResponses[formResponses.length - 1]; 5 | const responseData = latestResponse.getItemResponses(); 6 | const userEmail = latestResponse.getRespondentEmail(); 7 | const feedback = responseData[1].getResponse(); // Assuming second question asks for textual feedback 8 | MailApp.sendEmail({ 9 | to: userEmail, 10 | subject: 'Thank you for your feedback', 11 | htmlBody: 'We appreciate your feedback: ' + feedback + '' 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter5/Dynamic Form from Sheet data: -------------------------------------------------------------------------------- 1 | function createFormFromSheetData() { 2 | const ss = SpreadsheetApp.openById(SHEETID); 3 | const sheet = ss.getSheetByName('Questions'); // Assuming a sheet named 'Questions' 4 | const range = sheet.getDataRange(); 5 | const values = range.getValues(); 6 | const form = FormApp.create('New Dynamic Form'); 7 | values.forEach(function(row, i) { 8 | // Skip header or empty rows 9 | if (i === 0 || !row[0]) return; 10 | const questionTitle = row[0]; 11 | const questionType = row[1]; // 'MCQ', 'Text', 'Checkbox', etc. 12 | const options = row.slice(2); // Options for MCQs or Checkboxes 13 | switch (questionType) { 14 | case 'MCQ': 15 | const mcqItem = form.addMultipleChoiceItem(); 16 | mcqItem.setTitle(questionTitle); 17 | mcqItem.setChoices(options.filter(String).map(option => mcqItem.createChoice(option))); // Filter out empty strings 18 | break; 19 | case 'Text': 20 | form.addTextItem().setTitle(questionTitle); 21 | break; 22 | // Handle other cases as needed 23 | } 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /Chapter5/Set up Autograding: -------------------------------------------------------------------------------- 1 | function setUpGradingTrigger() { 2 | const form = FormApp.openById(QUIZID) 3 | ScriptApp.newTrigger('gradeSubmissions') 4 | .forForm(form) 5 | .onFormSubmit() 6 | .create(); 7 | } 8 | function gradeSubmissions(event) { 9 | const itemResponses = event.response.getItemResponses(); 10 | const score = 0; 11 | // Define correct answers for each question 12 | const correctAnswers = ['Answer1', 'Answer2', 'Answer3']; // Example 13 | itemResponses.forEach(function (itemResponse, index) { 14 | if (itemResponse.getResponse() === correctAnswers[index]) { 15 | score++; 16 | } 17 | }); 18 | // Update score in a Google Sheet or send it via email 19 | } 20 | -------------------------------------------------------------------------------- /Chapter5/Setting Up Simple Triggers: -------------------------------------------------------------------------------- 1 | function onFormSubmit(e) { 2 | const response = e.response; 3 | const itemResponses = response.getItemResponses(); 4 | // Process form submission 5 | } 6 | -------------------------------------------------------------------------------- /Chapter5/Trigger to run function on submit: -------------------------------------------------------------------------------- 1 | function setUpTrigger() { 2 | const form = FormApp.openById(FORMID); 3 | ScriptApp.newTrigger('processFormResponse') 4 | .forForm(form) 5 | .onFormSubmit() 6 | .create(); 7 | } 8 | // Function to process responses 9 | function processFormResponse(e) { 10 | const responses = e.response.getItemResponses(); 11 | responses.forEach(function (response) { 12 | // Process each response; for example, log the answers or store them in a spreadsheet 13 | Logger.log('Question: ' + response.getItem().getTitle()); 14 | Logger.log('Answer: ' + response.getResponse()); 15 | const doc = DocumentApp.create('Form1'); 16 | const body = doc.getBody(); 17 | body.appendParagraph('Question: ' + response.getItem().getTitle()); 18 | body.appendParagraph('Answer: ' + response.getResponse()); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /Chapter5/Updating Google Sheets Based on Form Responses: -------------------------------------------------------------------------------- 1 | function updateSheetOnFormSubmit(e) { 2 | const response = e.response; 3 | const item = response.getItemResponses()[0]; 4 | const answer = item.getResponse(); 5 | const sheet = SpreadsheetApp.openById('SHEET_ID').getActiveSheet(); 6 | const range = sheet.getRange('A1'); // Update cell A1 7 | range.setValue(answer); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter5/Writing Form Responses to Google Sheets: -------------------------------------------------------------------------------- 1 | function writeResponsesToSheet() { 2 | const form = FormApp.openById('FORM_ID'); 3 | const responses = form.getResponses(); 4 | const sheet = SpreadsheetApp.openById('SHEET_ID').getActiveSheet(); 5 | responses.forEach(function(response) { 6 | const items = response.getItemResponses(); 7 | const rowData = []; 8 | items.forEach(function(item) { 9 | rowData.push(item.getResponse()); 10 | }); 11 | sheet.appendRow(rowData); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter5/create a form: -------------------------------------------------------------------------------- 1 | function createForm() { 2 | const form = FormApp.create('New Event Feedback Form'); 3 | form.setDescription('Please provide your feedback'); 4 | 5 | // Adding a multiple-choice item 6 | const satisfactionQuestion = form.addMultipleChoiceItem(); 7 | satisfactionQuestion.setTitle('How satisfied were you with the event?'); 8 | 9 | // Correctly setting the choices 10 | satisfactionQuestion.setChoices([ 11 | satisfactionQuestion.createChoice('Very Satisfied'), 12 | satisfactionQuestion.createChoice('Satisfied'), 13 | satisfactionQuestion.createChoice('Neutral'), 14 | satisfactionQuestion.createChoice('Dissatisfied'), 15 | satisfactionQuestion.createChoice('Very Dissatisfied') 16 | ]); 17 | 18 | // Adding a paragraph text item for additional comments 19 | form.addParagraphTextItem().setTitle('Please provide additional comments'); 20 | 21 | Logger.log('Form created: ' + form.getPublishedUrl()); 22 | } 23 | -------------------------------------------------------------------------------- /Chapter5/create form from sheet data: -------------------------------------------------------------------------------- 1 | function createFormFromSheet() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data'); 3 | const range = sheet.getDataRange(); 4 | const values = range.getValues(); 5 | const form = FormApp.create('New Form from Spreadsheet'); // Name your form 6 | values.forEach(function (row, index) { 7 | if (index === 0) return; // Skip header row, if present 8 | const question = row[0]; // Your question text 9 | const options = row.slice(1, -1); // Answer options 10 | const correctAnswer = row[row.length - 1]; // Correct answer 11 | const item = form.addMultipleChoiceItem(); 12 | item.setTitle(question) 13 | .setChoices( 14 | options.map(function (option) { 15 | return item.createChoice(option, option === correctAnswer); 16 | }) 17 | ); 18 | }); 19 | Logger.log('Form created: ' + form.getPublishedUrl()); 20 | } 21 | -------------------------------------------------------------------------------- /Chapter5/generate Quiz Feedback Form: -------------------------------------------------------------------------------- 1 | function generateQuizFeedbackForm() { 2 | const form = FormApp.create('Quiz Feedback Form'); 3 | // Define questions and correct answers 4 | const questionsAndAnswers = { 'Question 1': 'Answer1', 'Question 2': 'Answer2' }; // Example answers 5 | // Iterate through each question and create form items 6 | Object.entries(questionsAndAnswers).forEach(([question, correctAnswer]) => { 7 | const questionItem = form.addMultipleChoiceItem(); 8 | questionItem.setTitle(question); 9 | questionItem.setChoiceValues([correctAnswer, 'Other']); // Provide correct answer and an option for 'Other' 10 | // Set validation to ensure students select an option 11 | questionItem.setRequired(true); 12 | }); 13 | // Add an email question to capture student's email 14 | form.addTextItem().setTitle('Your Email Address').setRequired(true); 15 | // Add a paragraph text item for additional comments 16 | form.addParagraphTextItem().setTitle('Additional Comments'); 17 | Logger.log('Feedback form created: ' + form.getId()); 18 | Logger.log('Feedback form created: ' + form.getPublishedUrl()); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter5/get form responses: -------------------------------------------------------------------------------- 1 | function getAllResponses() { 2 | const form = FormApp.openById(FORMID); 3 | const formResponses = form.getResponses(); 4 | formResponses.forEach(function(formResponse) { 5 | const itemResponses = formResponse.getItemResponses(); 6 | itemResponses.forEach(function(itemResponse) { 7 | console.log(itemResponse.getItem().getTitle() + ': ' + itemResponse.getResponse()); 8 | }); 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter5/latest response: -------------------------------------------------------------------------------- 1 | 2 | function getLatestResponse() { 3 | const form = FormApp.openById(FORMID); 4 | const formResponses = form.getResponses(); 5 | const latestResponse = formResponses[formResponses.length - 1]; // Get the latest response 6 | const itemResponses = latestResponse.getItemResponses(); 7 | itemResponses.forEach(function (itemResponse) { 8 | console.log(itemResponse.getItem().getTitle() + ': ' + itemResponse.getResponse()); 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter5/process response with trigger: -------------------------------------------------------------------------------- 1 | function setUpTrigger() { 2 | const form = FormApp.openById(FORMID); 3 | ScriptApp.newTrigger('processNewResponse') 4 | .forForm(form) 5 | .onFormSubmit() 6 | .create(); 7 | } 8 | function processNewResponse(event) { 9 | const response = event.response; 10 | const itemResponses = response.getItemResponses(); 11 | // Example: Log each response 12 | itemResponses.forEach(function (itemResponse) { 13 | Logger.log(itemResponse.getItem().getTitle() + ': ' + itemResponse.getResponse()); 14 | }); 15 | // Additional processing can be done here, like sending an email or updating a spreadsheet 16 | } 17 | -------------------------------------------------------------------------------- /Chapter5/responses to sheet: -------------------------------------------------------------------------------- 1 | function exportResponsesToSheet() { 2 | const form = FormApp.openById(FORMID); 3 | const formResponses = form.getResponses(); 4 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Options'); 5 | const data = []; 6 | formResponses.forEach(function (formResponse) { 7 | const rowData = []; 8 | const itemResponses = formResponse.getItemResponses(); 9 | itemResponses.forEach(function (itemResponse) { 10 | rowData.push(itemResponse.getResponse()); 11 | }); 12 | data.push(rowData); 13 | }); 14 | sheet.getRange(sheet.getLastRow() + 1, 1, data.length, data[0].length).setValues(data); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter5/send Confirmation Emai: -------------------------------------------------------------------------------- 1 | function sendConfirmationEmail(e) { 2 | const response = e.response; 3 | const respondentEmail = response.getRespondentEmail(); 4 | const formTitle = response.getFormTitle(); 5 | const subject = 'Thank you for your submission!'; 6 | const message = 'Dear respondent,\n\nThank you for completing the form: ' + formTitle + '.'; 7 | MailApp.sendEmail(respondentEmail, subject, message); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter5/send email response Autoresponder: -------------------------------------------------------------------------------- 1 | function sendCustomEmailResponses() { 2 | const form = FormApp.openById(FORMID); 3 | const formResponses = form.getResponses(); 4 | const latestResponse = formResponses[formResponses.length - 1]; 5 | const responseData = latestResponse.getItemResponses(); 6 | const userEmail = latestResponse.getRespondentEmail(); 7 | const feedback = responseData[1].getResponse(); // Assuming second question asks for textual feedback 8 | MailApp.sendEmail({ 9 | to: userEmail, 10 | subject: 'Thank you for your feedback', 11 | htmlBody: 'We appreciate your feedback: ' + feedback + '' 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter5/send quiz feedback: -------------------------------------------------------------------------------- 1 | function sendQuizFeedback() { 2 | const form = FormApp.openById(QUIZID); 3 | const responses = form.getResponses(); 4 | const latestResponse = responses[responses.length - 1]; 5 | const items = form.getItems(); 6 | let feedbackMessage = ''; 7 | const correctAnswers = { 'Question 1': 'Answer1', 'Question 2': 'Answer2' }; // Example answers 8 | let emailUSER = latestResponse.getItemResponses()[2].getResponse(); 9 | latestResponse.getItemResponses().forEach(function (response, index) { 10 | const questionTitle = items[index].getTitle(); 11 | const studentAnswer = response.getResponse(); 12 | Logger.log(studentAnswer); 13 | //Your Email Address 14 | const correctAnswer = correctAnswers[questionTitle]; 15 | feedbackMessage += questionTitle + '\n'; 16 | feedbackMessage += 'Your answer: ' + studentAnswer + '\n'; 17 | feedbackMessage += 'Correct answer: ' + correctAnswer + '\n\n'; 18 | }); 19 | MailApp.sendEmail(EMAIL, 'Quiz Feedback', feedbackMessage); 20 | } 21 | -------------------------------------------------------------------------------- /Chapter5/update form: -------------------------------------------------------------------------------- 1 | function updateFormChoicesFromSheet() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Options'); 3 | const range = sheet.getDataRange(); 4 | const values = range.getValues(); 5 | const form = FormApp.openById(FORMID); 6 | const items = form.getItems(FormApp.ItemType.MULTIPLE_CHOICE); 7 | if (items.length > 0) { 8 | const multipleChoiceItem = items[0].asMultipleChoiceItem(); 9 | // Correct way to set choices 10 | const choices = values.map(function(row) { 11 | return multipleChoiceItem.createChoice(row[0]); // Use the createChoice method correctly 12 | }); 13 | multipleChoiceItem.setChoices(choices); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter5/update form options: -------------------------------------------------------------------------------- 1 | function updateFormOptions() { 2 | const form = FormApp.openById(FORMID); 3 | const item = form.getItems(FormApp.ItemType.MULTIPLE_CHOICE)[0].asMultipleChoiceItem(); // Assuming the first item is your workshop question 4 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data3'); 5 | const data = sheet.getDataRange().getValues(); // Assuming workshop names and slots are in columns A and B 6 | const choices = []; 7 | data.forEach(function(row) { 8 | if (row[1] > 0) { // If slots are available 9 | choices.push(row[0]); // Add workshop name to choices 10 | } 11 | }); 12 | item.setChoices(choices.map(function(choice) { 13 | return item.createChoice(choice); 14 | })); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter6/Add chart from Sheets to Slides: -------------------------------------------------------------------------------- 1 | function getChartFromSheetAndInsertIntoSlide() { 2 | // ID of the Google Sheets spreadsheet 3 | const spreadsheetId = 'SHEETID'; 4 | // Name of the sheet containing the chart 5 | const sheetName = 'data'; 6 | // Get the chart as an image blob 7 | const chartImageBlob = getChartAsImageBlob(spreadsheetId, sheetName); 8 | // Insert the image blob into the first slide of the presentation 9 | if (chartImageBlob) { 10 | const presentation = SlidesApp.openById(SLIDEID); 11 | const slide = presentation.getSlides()[0]; 12 | slide.insertImage(chartImageBlob); 13 | } 14 | } 15 | 16 | function getChartAsImageBlob(spreadsheetId, sheetName) { 17 | // Open the spreadsheet 18 | const spreadsheet = SpreadsheetApp.openById(spreadsheetId); 19 | // Get the sheet 20 | const sheet = spreadsheet.getSheetByName(sheetName); 21 | // Get the chart 22 | const chart = sheet.getCharts()[0]; // Assuming the chart is the first chart in the sheet 23 | if (!chart) { 24 | console.log('No chart found in the specified sheet.'); 25 | return null; 26 | } 27 | // Get the chart as an image blob 28 | const chartImageBlob = chart.getAs('image/png'); 29 | return chartImageBlob; 30 | } 31 | -------------------------------------------------------------------------------- /Chapter6/Apply theme: -------------------------------------------------------------------------------- 1 | function applyThemeToPresentation() { 2 | const sourcePresentation = SlidesApp.openById(SLIDEID); // Presentation containing the theme 3 | const targetPresentation = SlidesApp.openById(SLIDEID2); // Presentation to which the theme will be applied 4 | 5 | // Copy slides from source presentation to target presentation 6 | const sourceSlides = sourcePresentation.getSlides(); 7 | sourceSlides.forEach(function(slide) { 8 | const copiedSlide = slide.duplicate(); 9 | targetPresentation.appendSlide(copiedSlide); 10 | }); 11 | 12 | // Delete the first slide (it might be blank or have default theme) 13 | const firstSlide = targetPresentation.getSlides()[0]; 14 | if (firstSlide) { 15 | firstSlide.remove(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter6/Create doc and share with anyone: -------------------------------------------------------------------------------- 1 | function createDocumentAndShare() { 2 | const doc = DocumentApp.create('New Document'); 3 | const body = doc.getBody(); 4 | body.appendParagraph('This is a new document created with Google Apps Script.'); 5 | const fileId = doc.getId(); 6 | const file = DriveApp.getFileById(fileId); 7 | file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter6/Creating Slides Dynamically: -------------------------------------------------------------------------------- 1 | function createSlidesFromData() { 2 | const presentation = SlidesApp.create('Dynamic Slides Presentation'); 3 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('data3'); 4 | const data = sheet.getDataRange().getValues(); 5 | 6 | data.forEach(function(row) { 7 | const slide = presentation.appendSlide(); 8 | const title = row[0]; 9 | const content = row[1]; 10 | 11 | const titleTextBox = slide.insertTextBox(title); 12 | titleTextBox.getText().setText(title); 13 | titleTextBox.getText().getTextStyle().setBold(true); 14 | 15 | const contentTextBox = slide.insertTextBox(content); 16 | contentTextBox.getText().setText(content); 17 | contentTextBox.getText().getTextStyle().setFontSize(12); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter6/Insert Image: -------------------------------------------------------------------------------- 1 | function insertImage() { 2 | const presentation = SlidesApp.openById(SLIDEID); 3 | const slide = presentation.getSlides()[0]; 4 | const imageUrl = 'https://www.discoveryvip.com/img/d.png'; 5 | const imageBlob = UrlFetchApp.fetch(imageUrl).getBlob(); 6 | slide.insertImage(imageBlob); 7 | } 8 | -------------------------------------------------------------------------------- /Chapter6/access gmail messages: -------------------------------------------------------------------------------- 1 | function accessGmail() { 2 | const threads = GmailApp.getInboxThreads(0, 10); // Get the first 10 threads in the inbox 3 | threads.forEach(function(thread) { 4 | const messages = thread.getMessages(); 5 | messages.forEach(function(message) { 6 | Logger.log('Subject: ' + message.getSubject()); 7 | }); 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter6/create Slides: -------------------------------------------------------------------------------- 1 | function createPresentation() { 2 | // Create a new Google Slides presentation 3 | const presentation = SlidesApp.create('New Presentation'); 4 | 5 | // Access the first slide in the presentation 6 | const slide = presentation.getSlides()[0]; 7 | 8 | // Set the title and subtitle for the first slide 9 | const titleShape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 50, 50, 600, 50); 10 | titleShape.getText().setText('Presentation Title'); 11 | 12 | const subtitleShape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 50, 100, 600, 50); 13 | subtitleShape.getText().setText('Subtitle'); 14 | 15 | // Add some text to the first slide 16 | const shape = slide.insertShape(SlidesApp.ShapeType.TEXT_BOX, 50, 200, 600, 300); 17 | shape.getText().setText('This is a sample text for the presentation.'); 18 | 19 | // Access the second slide in the presentation 20 | const slide2 = presentation.appendSlide(SlidesApp.PredefinedLayout.TITLE_AND_BODY); 21 | 22 | // Set the title and body content for the second slide 23 | slide2.insertTextBox('Second Slide').setLeft(50).setTop(50).setWidth(600).setHeight(50); 24 | slide2.insertTextBox('This is the body text for the second slide.').setLeft(50).setTop(100).setWidth(600).setHeight(300); 25 | } 26 | -------------------------------------------------------------------------------- /Chapter6/customize slide layout: -------------------------------------------------------------------------------- 1 | function customizeSlideLayout() { 2 | const presentation = SlidesApp.openById(SLIDEID2); 3 | const slide = presentation.getSlides()[0]; 4 | // Access shapes on the slide 5 | const shapes = slide.getShapes(); 6 | // Iterate through the shapes to find the header and footer 7 | shapes.forEach(function(shape) { 8 | const text = shape.getText().asString(); // Get the text from the shape as a string 9 | Logger.log(text); 10 | if (text.startsWith("Header")) { // Check if the text starts with "Header" 11 | shape.remove(); // Remove the shape if it's a header 12 | } 13 | if (text.startsWith("Footer")) { // Check if the text starts with "Footer" 14 | shape.remove(); // Remove the shape if it's a footer 15 | } 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter6/generate from tempalte: -------------------------------------------------------------------------------- 1 | function generateSlidesFromTemplate() { 2 | const presentation = SlidesApp.openById(SLIDEID); 3 | const templateSlide = presentation.getSlides()[0]; 4 | const newData = ['Slide 1 Content', 'Slide 2 Content', 'Slide 3 Content']; 5 | newData.forEach(function(content) { 6 | const newSlide = templateSlide.duplicate(); 7 | newSlide.replaceAllText('{CONTENT}', content); 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter6/insert dynamic content: -------------------------------------------------------------------------------- 1 | function insertDynamicContent() { 2 | const presentation = SlidesApp.openById(SLIDEID); 3 | const slides = presentation.getSlides(); 4 | slides.forEach(function(slide) { 5 | const date = new Date().toDateString(); 6 | const textBox = slide.insertTextBox('Today\'s Date: ' + date); 7 | textBox.setLeft(100).setTop(100).setWidth(400).setHeight(50); 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter6/insert shape: -------------------------------------------------------------------------------- 1 | function insertShape() { 2 | const presentation = SlidesApp.openById(SLIDEID2);; 3 | const slide = presentation.getSlides()[0]; 4 | slide.insertShape(SlidesApp.ShapeType.RECTANGLE, 100, 100, 200, 100); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter6/insert text: -------------------------------------------------------------------------------- 1 | function insertText() { 2 | const presentation = SlidesApp.openById(SLIDEID2);; 3 | const slide = presentation.getSlides()[0]; 4 | slide.insertTextBox('Hello, World!'); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter7/Create from template and share: -------------------------------------------------------------------------------- 1 | function generateContractDocument() { 2 | // Code to retrieve contract data 3 | // Create a new document from template 4 | const templateId = DOCID; 5 | const documentName = 'Contract Document'; 6 | const newDoc = DriveApp.getFileById(templateId).makeCopy(documentName); 7 | // Populate document with contract data 8 | // Code to replace placeholders with actual data 9 | // Share document with stakeholders 10 | const stakeholdersEmails = ['stakeholder1@example.com', 'stakeholder2@example.com']; 11 | stakeholdersEmails.forEach(function(email) { 12 | newDoc.addEditor(email); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter7/Creating Files and Folders: -------------------------------------------------------------------------------- 1 | function createNewDocument() { 2 | const doc = DocumentApp.create('New Document'); 3 | } 4 | Similarly, you can create folders using the Drive service: 5 | function createNewFolder() { 6 | const folder = DriveApp.createFolder('New Folder'); 7 | } 8 | -------------------------------------------------------------------------------- /Chapter7/Move file to folder: -------------------------------------------------------------------------------- 1 | function moveFile() { 2 | const file = DriveApp.getFileById(FILEID); 3 | const folder = DriveApp.getFolderById(FOLDERID); 4 | folder.addFile(file); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter7/back up of folders: -------------------------------------------------------------------------------- 1 | function backupDocuments() { 2 | const foldersToBackup = ['New Folder', 'test']; // List of folders to backup 3 | foldersToBackup.forEach(function(folderName) { 4 | const folders = DriveApp.getFoldersByName(folderName); 5 | if (folders.hasNext()) { 6 | const folder = folders.next(); 7 | const backupFolder = createBackupFolder(folderName); 8 | backupFolderFromFolder(folder, backupFolder); 9 | } 10 | }); 11 | } 12 | 13 | function createBackupFolder(folderName) { 14 | const today = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy-MM-dd'); 15 | const backupFolderName = folderName + ' Backup ' + today; 16 | const existingFolders = DriveApp.getFoldersByName(backupFolderName); 17 | if (existingFolders.hasNext()) { 18 | return existingFolders.next(); 19 | } else { 20 | return DriveApp.createFolder(backupFolderName); 21 | } 22 | } 23 | 24 | function backupFolderFromFolder(folder, backupFolder) { 25 | const files = folder.getFiles(); 26 | while (files.hasNext()) { 27 | const file = files.next(); 28 | file.makeCopy(file.getName(), backupFolder); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter7/file metadata: -------------------------------------------------------------------------------- 1 | function getFileMetadata() { 2 | const file = DriveApp.getFileById(FILEID); 3 | const metadata = { 4 | title: file.getName(), 5 | description: file.getDescription(), 6 | createdDate: file.getDateCreated(), 7 | modifiedDate: file.getLastUpdated(), 8 | mimeType: file.getMimeType() 9 | }; 10 | Logger.log(metadata); 11 | return metadata; 12 | } 13 | -------------------------------------------------------------------------------- /Chapter7/organize files by Date: -------------------------------------------------------------------------------- 1 | function organizeFilesByDate() { 2 | const folder = DriveApp.createFolder('Sorted Files'); 3 | const files = DriveApp.getRootFolder().getFiles(); 4 | while (files.hasNext()) { 5 | const file = files.next(); 6 | const dateCreated = file.getDateCreated(); 7 | const year = dateCreated.getFullYear(); 8 | const month = dateCreated.getMonth() + 1; // Months are zero-based 9 | const subfolderName = year + '-' + month; 10 | const subfolder = getOrCreateFolder(folder, subfolderName); 11 | file.moveTo(subfolder); 12 | } 13 | } 14 | function getOrCreateFolder(parentFolder, folderName) { 15 | const folders = parentFolder.getFoldersByName(folderName); 16 | if (folders.hasNext()) { 17 | return folders.next(); 18 | } else { 19 | return parentFolder.createFolder(folderName); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter7/search fiels by name: -------------------------------------------------------------------------------- 1 | function searchFilesByTitle() { 2 | const files = DriveApp.getFilesByName('test'); 3 | while (files.hasNext()) { 4 | const file = files.next(); 5 | Logger.log('File Name: ' + file.getName() + ', ID: ' + file.getId()); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter7/update metadata: -------------------------------------------------------------------------------- 1 | function updateFileDescription() { 2 | const file = DriveApp.getFileById(FILEID); 3 | file.setDescription('test'); 4 | } 5 | -------------------------------------------------------------------------------- /Chapter7/update user permissions: -------------------------------------------------------------------------------- 1 | function updatePermissions() { 2 | const accessLevel = 'view'; 3 | const userEmail = 'stakeholder1@example.com'; 4 | const file = DriveApp.getFileById(FILEID); 5 | const user = Session.getActiveUser().getEmail(); 6 | if (user === EMAIL) { // Check if the user has the necessary permissions 7 | file.removeEditor(userEmail); // Remove existing permission 8 | switch (accessLevel) { 9 | case 'view': 10 | file.addViewer(userEmail); // Grant view access 11 | break; 12 | case 'edit': 13 | file.addEditor(userEmail); // Grant edit access 14 | break; 15 | case 'comment': 16 | file.addCommenter(userEmail); // Grant comment access 17 | break; 18 | default: 19 | // Handle invalid access level 20 | break; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter8/Check for email by subject in thread: -------------------------------------------------------------------------------- 1 | function processIncomingEmails() { 2 | const threads = GmailApp.search('subject:"Support Request"'); 3 | threads.forEach(function (thread) { 4 | const messages = thread.getMessages(); 5 | messages.forEach(function (message) { 6 | const sender = message.getFrom(); 7 | const body = message.getPlainBody(); 8 | // Process email content and trigger appropriate actions 9 | Logger.log(body); 10 | }); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter8/Parsing Email Messages: -------------------------------------------------------------------------------- 1 | function parseEmail() { 2 | const threads = GmailApp.getInboxThreads(0, 1); // Get the latest thread 3 | const messages = threads[0].getMessages(); // Get messages in the thread 4 | const message = messages[0]; 5 | const subject = message.getSubject(); 6 | const sender = message.getFrom(); 7 | const body = message.getPlainBody(); 8 | Logger.log('Subject: ' + subject); 9 | Logger.log('From: ' + sender); 10 | Logger.log('Body: ' + body); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter8/Sending Personalized Emails: -------------------------------------------------------------------------------- 1 | function sendPersonalizedEmail() { 2 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName('Sheet1'); 3 | const rows = sheet.getDataRange().getValues(); 4 | const data = rows.slice(1); 5 | Logger.log(data); 6 | data.forEach(function(row) { 7 | const recipient = row[0]; 8 | const name = row[1]; 9 | const subject = 'Hello, ' + name + '!'; 10 | const body = 'Dear ' + name + ',\n\nThis is a personalized message just for you!'; 11 | MailApp.sendEmail(recipient, subject, body); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter8/Triggering Actions Based on Email Content: -------------------------------------------------------------------------------- 1 | function processIncomingEmails() { 2 | const threads = GmailApp.search('is:unread subject:"Action Required"'); 3 | threads.forEach(function(thread) { 4 | const messages = thread.getMessages(); 5 | messages.forEach(function(message) { 6 | const body = message.getPlainBody(); 7 | if (body.includes('Approve')) { 8 | // Trigger approval workflow 9 | } else if (body.includes('Reject')) { 10 | // Trigger rejection workflow 11 | } 12 | }); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter8/applyLabelToMatchingEmails: -------------------------------------------------------------------------------- 1 | function applyLabelToMatchingEmails() { 2 | // Define the search criteria 3 | const searchCriteria = 'from:example@example.com'; 4 | 5 | // Create or retrieve the label 6 | let label = GmailApp.getUserLabelByName('Example Label'); 7 | if (!label) { 8 | label = GmailApp.createLabel('Example Label'); 9 | } 10 | 11 | // Search for emails matching the criteria 12 | const threads = GmailApp.search(searchCriteria); 13 | 14 | // Apply the label to each thread that matches the criteria 15 | threads.forEach(function(thread) { 16 | thread.addLabel(label); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /Chapter8/create and add label if needed: -------------------------------------------------------------------------------- 1 | function archiveOldEmails2() { 2 | const labelName = 'OlderThanAYear'; // Specify the label name you want to use 3 | let label = GmailApp.getUserLabelByName(labelName); 4 | // Create the label if it doesn't exist 5 | if (!label) { 6 | label = GmailApp.createLabel(labelName); 7 | } 8 | const threads = GmailApp.search('label:inbox older_than:1y'); 9 | threads.forEach(function(thread) { 10 | // Apply the label to each thread before archiving, if you want 11 | thread.addLabel(label); 12 | thread.moveToArchive(); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter8/create label and filter messages: -------------------------------------------------------------------------------- 1 | function applyLabelToMatchingEmails() { 2 | // Define the search criteria 3 | const searchCriteria = 'from:courses@gmail.com'; 4 | 5 | // Create or retrieve the label 6 | let label = GmailApp.getUserLabelByName('Example Label'); 7 | if (!label) { 8 | label = GmailApp.createLabel('Example Label'); 9 | } 10 | 11 | // Search for emails matching the criteria 12 | const threads = GmailApp.search(searchCriteria); 13 | 14 | // Apply the label to each thread that matches the criteria 15 | threads.forEach(function(thread) { 16 | thread.addLabel(label); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /Chapter8/createNewLabel: -------------------------------------------------------------------------------- 1 | function createNewLabel() { 2 | GmailApp.createLabel('Work'); 3 | } 4 | -------------------------------------------------------------------------------- /Chapter8/deleteLabel: -------------------------------------------------------------------------------- 1 | function deleteLabel() { 2 | const label = GmailApp.getUserLabelByName('Work'); 3 | if (label) { 4 | label.deleteLabel(); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter8/extractUrlsFromBody: -------------------------------------------------------------------------------- 1 | function parseEmail() { 2 | const threads = GmailApp.getInboxThreads(0, 1); // Get the latest thread 3 | if (threads.length > 0) { // Check if there's at least one thread 4 | const messages = threads[0].getMessages(); // Get messages in the thread 5 | if (messages.length > 0) { // Check if there's at least one message 6 | const message = messages[0]; 7 | const subject = message.getSubject(); 8 | const sender = message.getFrom(); 9 | const body = message.getPlainBody(); 10 | Logger.log('Subject: ' + subject); 11 | Logger.log('From: ' + sender); 12 | Logger.log('Body: ' + body); 13 | // Now call extractUrlsFromBody to log URLs from the body 14 | extractUrlsFromBody(body); 15 | } 16 | } 17 | } 18 | 19 | function extractUrlsFromBody(body) { 20 | // Check if body is a string 21 | if (typeof body !== 'string') { 22 | Logger.log('Invalid input: body is not a string.'); 23 | return; // Exit the function if body is not a string 24 | } 25 | const urls = body.match(/https?:\/\/\S+/g); // Regular expression to match URLs 26 | if (urls !== null) { 27 | Logger.log('URLs found in the email:'); 28 | urls.forEach(function(url) { 29 | Logger.log(url); 30 | }); 31 | } else { 32 | Logger.log('No URLs found in the email.'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter8/send Email: -------------------------------------------------------------------------------- 1 | function sendEmail() { 2 | const recipient = EMAIL; 3 | const subject = 'Test Email'; 4 | const body = 'This is a test email sent using Google Apps Script!'; 5 | MailApp.sendEmail(recipient, subject, body); 6 | } 7 | -------------------------------------------------------------------------------- /Chapter9/Custom Dialogs and Sidebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Welcome to My Custom Dialog

8 |

This is a sample custom dialog created using Google Apps Script.

9 | 10 | 11 | 12 | 13 | function showDialog() { 14 | const html = HtmlService.createHtmlOutputFromFile('Page') 15 | .setWidth(400) 16 | .setHeight(300); 17 | SpreadsheetApp.getUi() // Or DocumentApp or FormApp. 18 | .showModalDialog(html, 'My custom dialog'); 19 | } 20 | -------------------------------------------------------------------------------- /Chapter9/Docs Custom UI menu: -------------------------------------------------------------------------------- 1 | function onOpen() { 2 | const ui = DocumentApp.getUi(); 3 | ui.createMenu('My Custom Menu') 4 | .addItem('Highlight Text', 'highlightText') 5 | .addSeparator() 6 | .addSubMenu(ui.createMenu('Insert') 7 | .addItem('Insert Date', 'insertDate') 8 | .addItem('Insert Signature', 'insertSignature')) 9 | .addToUi(); 10 | } 11 | function highlightText() { 12 | const doc = DocumentApp.getActiveDocument(); 13 | const body = doc.getBody(); 14 | const text = body.editAsText(); 15 | text.setBold(true); 16 | } 17 | function insertDate() { 18 | // Code to insert the current date 19 | } 20 | function insertSignature() { 21 | // Code to insert a predefined signature 22 | } 23 | -------------------------------------------------------------------------------- /Chapter9/Example with Google Calendar: -------------------------------------------------------------------------------- 1 | function createEvent() { 2 | const calendar = CalendarApp.getDefaultCalendar(); 3 | calendar.createEvent('Apps Script Event', new Date(), new Date()); 4 | } 5 | -------------------------------------------------------------------------------- /Chapter9/New Task List: -------------------------------------------------------------------------------- 1 | function createTaskList() { 2 | // Define the new task list 3 | let taskList = { 4 | title: 'Homework Assignments' 5 | }; 6 | 7 | // Insert the task list using the Tasks API 8 | taskList = Tasks.Tasklists.insert(taskList); 9 | 10 | // Log the title of the created task list 11 | Logger.log('Task list created: ' + taskList.title); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter9/UI menu example: -------------------------------------------------------------------------------- 1 | function onOpen() { 2 | const ui = SpreadsheetApp.getUi(); 3 | ui.createMenu('My Custom Menu') 4 | .addItem('Perform Action', 'performAction') 5 | .addSeparator() 6 | .addSubMenu(ui.createMenu('More Actions') 7 | .addItem('Action 1', 'actionOne') 8 | .addItem('Action 2', 'actionTwo')) 9 | .addToUi(); 10 | } 11 | function performAction() { 12 | SpreadsheetApp.getActiveSheet().getRange('A1').setValue('Action performed!'); 13 | } 14 | function actionOne() { 15 | // Code for Action 1 16 | } 17 | function actionTwo() { 18 | // Code for Action 2 19 | } 20 | -------------------------------------------------------------------------------- /Chapter9/UI menu run report: -------------------------------------------------------------------------------- 1 | function onOpen() { 2 | const ui = SpreadsheetApp.getUi(); 3 | ui.createMenu('Custom Menu') 4 | .addItem('Run Report', 'generateReport') 5 | .addToUi(); 6 | } 7 | function generateReport() { 8 | // Your code to generate the report 9 | SpreadsheetApp.getUi().alert('Report generated successfully!'); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter9/UrlFetchApp example: -------------------------------------------------------------------------------- 1 | function getPosts() { 2 | var url = 'https://jsonplaceholder.typicode.com/posts'; 3 | var response = UrlFetchApp.fetch(url); // Make the GET request 4 | var json = response.getContentText(); // Get the response content as text 5 | var data = JSON.parse(json); // Parse the JSON text into an object 6 | 7 | Logger.log(data); // Log the data to the Google Apps Script log 8 | 9 | // Optional: Process the data as needed 10 | data.forEach(function(post) { 11 | Logger.log(post.title); // Log each post's title 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter9/add task to list: -------------------------------------------------------------------------------- 1 | function getTaskListId(taskListTitle) { 2 | // Get the list of all task lists 3 | const taskLists = Tasks.Tasklists.list(); 4 | // Search for the task list by title 5 | if (taskLists.items) { 6 | for (let i = 0; i < taskLists.items.length; i++) { 7 | const taskList = taskLists.items[i]; 8 | if (taskList.title === taskListTitle) { 9 | Logger.log(taskList.title + " - " + taskList.id); 10 | return taskList.id; 11 | } 12 | } 13 | } 14 | Logger.log('Task list not found.'); 15 | return null; // Return null if not found 16 | } 17 | 18 | function addTaskToTaskList(taskListId, taskTitle) { 19 | // Define the new task 20 | const task = { 21 | title: taskTitle, 22 | notes: 'This is a note.', 23 | due: (new Date(new Date().getTime() + 24*60*60*1000)).toISOString() // Due date, 1 day from now 24 | }; 25 | // Add the task to the specified task list 26 | const addedTask = Tasks.Tasks.insert(task, taskListId); 27 | Logger.log('Task added: ' + addedTask.title); 28 | } 29 | function createAndAddTask() { 30 | const taskListTitle = 'Homework Assignments'; // The title of the task list you're interested in 31 | const taskListId = getTaskListId(taskListTitle); // Find the ID of the task list 32 | if (taskListId) { 33 | addTaskToTaskList(taskListId, 'Math Homework'); // Add a task to this task list 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter9/checkDeadlinesAndSendEmails: -------------------------------------------------------------------------------- 1 | function checkDeadlinesAndSendEmails() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getRange("A2:B10"); // Adjust range to your needs 4 | const values = range.getValues(); 5 | for (let i = 0; i < values.length; i++) { 6 | const row = values[i]; 7 | const task = row[0]; 8 | const dueDate = row[1]; 9 | const today = new Date(); 10 | if (dueDate < today) { 11 | const message = 'The task "' + task + '" is past due.'; 12 | const subject = 'Task Reminder: ' + task; 13 | MailApp.sendEmail("your-email@example.com", subject, message); // Replace with actual email address 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter9/createCalendarEvents: -------------------------------------------------------------------------------- 1 | function createCalendarEvents() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getDataRange(); 4 | const values = range.getValues(); 5 | const calendar = CalendarApp.getDefaultCalendar(); 6 | for (let i = 1; i < values.length; i++) { 7 | const row = values[i]; 8 | const eventName = row[0]; // Assuming the event name is in the first column 9 | const startDate = new Date(row[1]); // Assuming the start date is in the second column 10 | const endDate = new Date(row[2]); // Assuming the end date is in the third column 11 | const options = {description: row[3], location: row[4]}; // Additional details 12 | // Create the calendar event 13 | calendar.createEvent(eventName, startDate, endDate, options); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter9/createCustomEventReminder: -------------------------------------------------------------------------------- 1 | function createCustomEventReminder() { 2 | const calendarId = 'primary'; // Use 'primary' for the user's default calendar 3 | const events = CalendarApp.getCalendarById(calendarId).getEventsForDay(new Date()); 4 | for (let i = 0; i < events.length; i++) { 5 | const event = events[i]; 6 | const startTime = event.getStartTime(); 7 | const endTime = event.getEndTime(); 8 | const now = new Date(); 9 | const timeToEventStart = startTime.getTime() - now.getTime(); 10 | // Send a notification 1 hour before the event starts 11 | if (timeToEventStart <= 3600000 && timeToEventStart > 0) { 12 | const message = 'Reminder: ' + event.getTitle() + ' starts in less than an hour.'; 13 | MailApp.sendEmail("your-email@example.com", "Event Reminder", message); // Replace with actual email address 14 | } }} 15 | -------------------------------------------------------------------------------- /Chapter9/custom function in sheets: -------------------------------------------------------------------------------- 1 | function METERSTOFEET(meters) { 2 | return meters * 3.28084; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter9/custom menu in Docs: -------------------------------------------------------------------------------- 1 | function onOpen() { 2 | const ui = DocumentApp.getUi(); 3 | ui.createMenu('My Custom Menu') 4 | .addItem('Highlight Text', 'highlightText') 5 | .addSeparator() 6 | .addSubMenu(ui.createMenu('Insert') 7 | .addItem('Insert Date', 'insertDate') 8 | .addItem('Insert Signature', 'insertSignature')) 9 | .addToUi(); 10 | } 11 | function highlightText() { 12 | const doc = DocumentApp.getActiveDocument(); 13 | const body = doc.getBody(); 14 | const text = body.editAsText(); 15 | text.setBold(true); 16 | } 17 | function insertDate() { 18 | // Code to insert the current date 19 | } 20 | function insertSignature() { 21 | // Code to insert a predefined signature 22 | } 23 | -------------------------------------------------------------------------------- /Chapter9/custom menus UI: -------------------------------------------------------------------------------- 1 | function onOpen() { 2 | const ui = SpreadsheetApp.getUi(); 3 | ui.createMenu('Custom Menu') 4 | .addItem('First Item', 'menuItem1') 5 | .addSeparator() 6 | .addSubMenu(ui.createMenu('Sub-menu') 7 | .addItem('Second Item', 'menuItem2')) 8 | .addToUi(); 9 | } 10 | function menuItem1() { 11 | SpreadsheetApp.getUi().alert('You clicked the first menu item!'); 12 | } 13 | function menuItem2() { 14 | SpreadsheetApp.getUi().alert('You clicked the second menu item!'); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter9/doGet Deploy Web App: -------------------------------------------------------------------------------- 1 | function doGet(e) { 2 | return HtmlService.createHtmlOutput('

Hello, world!

'); 3 | } 4 | -------------------------------------------------------------------------------- /Chapter9/extractDataToSheet from Doc: -------------------------------------------------------------------------------- 1 | function extractDataToSheet() { 2 | const doc = DocumentApp.openById(DOCID); 3 | const body = doc.getBody(); 4 | const text = body.getText(); 5 | const sheet = SpreadsheetApp.openById(SHEETID).getSheets()[0]; 6 | // Example: Extracting lines of text into separate rows in a sheet 7 | const lines = text.split('\n'); 8 | for (let i = 0; i < lines.length; i++) { 9 | const cell = sheet.getRange(i + 1, 1); // Assumes data starts in the first column 10 | cell.setValue(lines[i]); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter9/formatCells: -------------------------------------------------------------------------------- 1 | function formatCells() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getRange("A1:A10"); 4 | const values = range.getValues(); 5 | for (let i = 0; i < values.length; i++) { 6 | if (values[i][0] > 5) { // If value in cell is greater than 5 7 | sheet.getRange(i + 1, 1).setBackground('yellow'); // Change background color to yellow 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter9/send email from sheet data: -------------------------------------------------------------------------------- 1 | function sendEmails() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getDataRange(); // Get data from all filled cells 4 | const values = range.getValues(); // 2D array of values 5 | // Skip the header row and start from row 2 6 | for (let i = 1; i < values.length; i++) { 7 | const row = values[i]; 8 | const email = row[0]; // Assuming email addresses are in the first column 9 | const name = row[1]; // Assuming names are in the second column 10 | const message = "Dear " + name + ",\n\nYour custom message here."; 11 | const subject = "Automated Email from Google Apps Script"; 12 | // Send the email 13 | MailApp.sendEmail(email, subject, message); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter9/sendEmailNotifications: -------------------------------------------------------------------------------- 1 | function sendEmailNotifications() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getRange("A1:B10"); 4 | const rows = range.getValues(); 5 | for (let i = 0; i < rows.length; i++) { 6 | const status = rows[i][1]; // Assuming status is in the second column 7 | const email = rows[i][0]; // Assuming email address is in the first column 8 | if (status === "Completed") { 9 | MailApp.sendEmail(email, "Task Status", "Your task has been marked as completed."); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter9/sendEmails: -------------------------------------------------------------------------------- 1 | function sendEmails() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getDataRange(); // Get data from all filled cells 4 | const values = range.getValues(); // 2D array of values 5 | // Skip the header row and start from row 2 6 | for (let i = 1; i < values.length; i++) { 7 | const row = values[i]; 8 | const email = row[0]; // Assuming email addresses are in the first column 9 | const name = row[1]; // Assuming names are in the second column 10 | const message = "Dear " + name + ",\n\nYour custom message here."; 11 | const subject = "Automated Email from Google Apps Script"; 12 | // Send the email 13 | MailApp.sendEmail(EMAIL, subject, message); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Data JSON Data: -------------------------------------------------------------------------------- 1 | function fetchDataFromAPI3() { 2 | // Assuming SHEETID is defined elsewhere as the actual ID of your sheet 3 | const sheetName = 'data'; // The name of your sheet tab 4 | // Predefined data 5 | const predefinedData = [ 6 | ["1", "Leanne Graham", "Bret", "Sincere@april.biz"], 7 | ["2", "Ervin Howell", "Antonette", "Shanna@melissa.tv"] 8 | ]; 9 | // Headers 10 | const headers = ['ID', 'Name', 'Username', 'Email']; 11 | // Reference the sheet 12 | const sheet = SpreadsheetApp.openById(SHEETID).getSheetByName(sheetName); 13 | sheet.clear(); // Clear existing contents 14 | // Set headers 15 | sheet.getRange(1, 1, 1, headers.length).setValues([headers]); 16 | // Set data (accounting for headers, start from row 2) 17 | sheet.getRange(2, 1, predefinedData.length, predefinedData[0].length).setValues(predefinedData); 18 | } 19 | -------------------------------------------------------------------------------- /Examples/Append a Row to a Spreadsheet: -------------------------------------------------------------------------------- 1 | function appendRow() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | sheet.appendRow(['New Data', 'More Data', 'Even More Data']); 4 | } 5 | -------------------------------------------------------------------------------- /Examples/Automate Document Creation and Sharing: -------------------------------------------------------------------------------- 1 | function createAndShareDoc() { 2 | const doc = DocumentApp.create('Shared Document'); 3 | DriveApp.getFileById(doc.getId()).addEditor('recipient@example.com'); 4 | } 5 | -------------------------------------------------------------------------------- /Examples/Batch Update Spreadsheet Cells: -------------------------------------------------------------------------------- 1 | function batchUpdateCells() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const rangeList = sheet.getRangeList(['A1', 'B2', 'C3']); 4 | rangeList.setValue('Updated!'); 5 | } 6 | -------------------------------------------------------------------------------- /Examples/Convert Spreadsheet Data to JSON: -------------------------------------------------------------------------------- 1 | function convertSheetToJson() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const data = sheet.getDataRange().getValues(); 4 | const headers = data.shift(); // First row as headers 5 | const jsonData = []; 6 | data.forEach(function(row) { 7 | const obj = {}; 8 | headers.forEach(function(header, i) { 9 | obj[header] = row[i]; 10 | }); 11 | jsonData.push(obj); 12 | }); 13 | Logger.log(JSON.stringify(jsonData)); 14 | } 15 | -------------------------------------------------------------------------------- /Examples/Create a Google Doc: -------------------------------------------------------------------------------- 1 | function createGoogleDoc() { 2 | DocumentApp.create('My New Document'); 3 | } 4 | -------------------------------------------------------------------------------- /Examples/Create a Menu in Google Sheets: -------------------------------------------------------------------------------- 1 | function onOpen() { 2 | const ui = SpreadsheetApp.getUi(); 3 | ui.createMenu('Custom Menu') 4 | .addItem('Run Example', 'logMessage') 5 | .addToUi(); 6 | } 7 | -------------------------------------------------------------------------------- /Examples/Fetch Data from an API: -------------------------------------------------------------------------------- 1 | function fetchData() { 2 | const response = UrlFetchApp.fetch('https://api.example.com/data'); 3 | Logger.log(response.getContentText()); 4 | } 5 | -------------------------------------------------------------------------------- /Examples/Generate PDFs from Google Docs Template: -------------------------------------------------------------------------------- 1 | function generatePDFs() { 2 | var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data"); 3 | var dataRange = dataSheet.getDataRange(); 4 | var data = dataRange.getValues(); 5 | var templateId = "TEMPLATE_DOCUMENT_ID"; 6 | data.slice(1).forEach(function(row) { 7 | var docCopy = DriveApp.getFileById(templateId).makeCopy(); 8 | var doc = DocumentApp.openById(docCopy.getId()); 9 | var body = doc.getBody(); 10 | // Replace placeholder text with actual data 11 | body.replaceText("{{Name}}", row[0]); 12 | body.replaceText("{{Date}}", row[1]); 13 | doc.saveAndClose(); 14 | // Convert to PDF 15 | var pdf = DriveApp.getFileById(doc.getId()).getAs("application/pdf"); 16 | var pdfName = row[0] + "_Document.pdf"; 17 | DriveApp.createFile(pdf).setName(pdfName); 18 | // Optional: delete the Docs copy 19 | DriveApp.getFileById(doc.getId()).setTrashed(true); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /Examples/Generate a Spreadsheet Report from Form Responses: -------------------------------------------------------------------------------- 1 | function generateFormReport() { 2 | const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 3 | const formResponses = spreadsheet.getSheetByName('Form Responses 1'); 4 | const reportSheet = spreadsheet.insertSheet('Report Summary'); 5 | // Example: Summarize total responses 6 | const totalResponses = formResponses.getLastRow() - 1; // Adjust for header row 7 | reportSheet.appendRow(['Total Responses', totalResponses]); 8 | } 9 | -------------------------------------------------------------------------------- /Examples/Log a Custom Message: -------------------------------------------------------------------------------- 1 | function logMessage() { 2 | Logger.log('Hello, Google Apps Script!'); 3 | } 4 | -------------------------------------------------------------------------------- /Examples/Monitor Sheet Changes and Send Notifications: -------------------------------------------------------------------------------- 1 | function onEdit(e) { 2 | var range = e.range; 3 | // Check if the edit is in a specific range (e.g., A1:A10) 4 | if (range.getSheet().getName() === 'Sheet1' && range.getRow() >= 1 && range.getRow() <= 10 && range.getColumn() === 1) { 5 | var emailAddress = 'your_email@example.com'; 6 | var subject = 'Spreadsheet Edit Notification'; 7 | var message = 'A cell in A1:A10 was edited. New value: ' + range.getValue(); 8 | MailApp.sendEmail(emailAddress, subject, message); 9 | } 10 | -------------------------------------------------------------------------------- /Examples/Read Data from a Spreadsheet: -------------------------------------------------------------------------------- 1 | function readSpreadsheet() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getRange('A1:A2'); 4 | const values = range.getValues(); 5 | for (const i = 0; i < values.length; i++) { 6 | Logger.log(values[i][0]); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Examples/Schedule Email Reminders from Spreadsheet Data: -------------------------------------------------------------------------------- 1 | function scheduleEmailReminders() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Schedule'); 3 | const dataRange = sheet.getDataRange(); 4 | const data = dataRange.getValues(); 5 | data.forEach(function(row, index) { 6 | if (index === 0) return; // Skip header row 7 | const email = row[0]; // Assuming email addresses are in the first column 8 | const task = row[1]; // Assuming tasks are in the second column 9 | const message = 'Reminder: You have to ' + task; 10 | const subject = 'Daily Task Reminder'; 11 | MailApp.sendEmail(email, subject, message); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Send an Email: -------------------------------------------------------------------------------- 1 | function sendEmail() { 2 | GmailApp.sendEmail('recipient@example.com', 'Test Email', 'Hello from Google Apps Script!'); 3 | } 4 | -------------------------------------------------------------------------------- /Examples/Update Spreadsheet Formatting: -------------------------------------------------------------------------------- 1 | function formatCells() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | const range = sheet.getRange('A1:A2'); 4 | range.setBackground('yellow'); 5 | range.setFontWeight('bold'); 6 | } 7 | -------------------------------------------------------------------------------- /Examples/Write Data to a Spreadsheet: -------------------------------------------------------------------------------- 1 | function writeSpreadsheet() { 2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); 3 | sheet.getRange('B1').setValue('Hello, Sheet!'); 4 | } 5 | --------------------------------------------------------------------------------