Select the text you want to create a script out of
9 |
10 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/LimitResponses.js:
--------------------------------------------------------------------------------
1 | // This code is written in Google Apps Script(JavaScript)
2 | // This codes limit responses in Google Forms
3 | // As soon as the form responses reaches the limit, it closes the Google Form
4 |
5 | function Limit_Responses() {
6 |
7 | max_responses = 5;// Maximum number of responses you want
8 | var form = FormApp.openById("Your Form ID ");// Get the form by ID
9 | var responses = form.getResponses();// Get the responses
10 | len = responses.length;// Get the length of the responses
11 | //Logger.log(len);
12 | if (len == max_responses){
13 | form.setAcceptingResponses(false); // Close the form and stop the responses
14 |
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/youtubePlaylist.js:
--------------------------------------------------------------------------------
1 | function addvideos() {
2 |
3 | const ss = SpreadsheetApp.getActiveSpreadsheet();
4 |
5 | const sheet = ss.getActiveSheet();
6 |
7 | const START_ROW = 2;
8 |
9 | const START_COLUMN = 1;
10 |
11 | const video_ID = sheet.getRange(START_ROW,START_COLUMN,sheet.getLastRow()).getValues().flat([1]);
12 |
13 | const playlistId = "PL36VXnx9Wxva1nNai3erO1Hpzuu-2zwES";
14 |
15 | video_ID.forEach( vid =>
16 |
17 | YouTube.PlaylistItems.insert({
18 |
19 | snippet: {
20 |
21 | playlistId: playlistId,
22 |
23 | resourceId: {
24 |
25 | kind: "youtube#video",
26 |
27 | videoId: vid
28 |
29 | }
30 | }
31 | }, "snippet"));
32 | }
33 |
--------------------------------------------------------------------------------
/PaLM.js:
--------------------------------------------------------------------------------
1 | function BARD(prompt) {
2 | var apiKey = "your_api_key";
3 | var apiUrl = "https://generativelanguage.googleapis.com/v1beta2/models/text-bison-001:generateText";
4 | var url = apiUrl + "?key=" + apiKey;
5 | var headers = {
6 | "Content-Type": "application/json"
7 | };
8 | var requestBody = {
9 | "prompt": {
10 | "text": prompt
11 | }
12 | };
13 | var options = {
14 | "method": "POST",
15 | "headers": headers,
16 | "payload": JSON.stringify(requestBody)
17 | };
18 | var response = UrlFetchApp.fetch(url, options);
19 | var data = JSON.parse(response.getContentText());
20 | var output = data.candidates[0].output;
21 | //return generatedText;
22 | Logger.log(output);
23 | return output;
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/GetClassroomData.js:
--------------------------------------------------------------------------------
1 | //This code is written in Google Apps Script
2 | // This code gets all the data in the Google Classroom into your Google Sheet using Google Apps Script and the Google Classroom API.
3 |
4 | function getData(){
5 |
6 |
7 | const CLASS_DATA = Classroom.Courses.list().courses;
8 |
9 | //console.log(CLASS_DATA);
10 |
11 |
12 | const DATA = CLASS_DATA.map(c => {
13 |
14 | return [c.name, c.section,c.room,c.description,c.enrollmentCode];
15 | });
16 |
17 |
18 | const ss = SpreadsheetApp.getActiveSpreadsheet();
19 | const sheet = ss.getSheetByName("Sheet1");
20 |
21 | const START_ROW = 2;
22 | const START_COLUMN = 1
23 |
24 | sheet.getRange(START_ROW,START_COLUMN,DATA.length,DATA[0].length).setValues(DATA);
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/PaLM-GAPS.gs:
--------------------------------------------------------------------------------
1 | function getPalmData() {
2 | var apiKey = "your_api_key";
3 | var apiUrl = "https://generativelanguage.googleapis.com/v1beta2/models/text-bison-001:generateText";
4 |
5 | var url = apiUrl + "?key=" + apiKey;
6 |
7 | var headers = {
8 | "Content-Type": "application/json"
9 | };
10 |
11 | var prompt = {
12 | "text": "Write a story about a magic backpack"
13 | };
14 |
15 | var requestBody = {
16 | "prompt": prompt
17 | };
18 |
19 | var options = {
20 | "method": "POST",
21 | "headers": headers,
22 | "payload": JSON.stringify(requestBody)
23 | };
24 |
25 | var response = UrlFetchApp.fetch(url, options);
26 | var data = JSON.parse(response.getContentText());
27 |
28 | Logger.log(data);
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/ExtractCellNotes.js:
--------------------------------------------------------------------------------
1 | // This code is written in Google Apps Script
2 | // This code extract cell notes and pastes them in the adjacent cell
3 | // This makes it easier for the user to read the cell notes
4 |
5 | function getNote()
6 | {
7 | // Get the sheet
8 | var ss = SpreadsheetApp.getActiveSpreadsheet();
9 | var sheet = ss.getActiveSheet();
10 | // Get the data from the sheet
11 | var range = sheet.getDataRange();
12 | // Get the notes from the sheet
13 | var notes = range.getNotes();
14 |
15 | for(var i = 0;i < notes.length;i++){
16 | for (var j = 0; j < notes[0].length; j++){
17 | // If note is not empty
18 | if(notes[i][j]){
19 | var note = notes[i][j];
20 | var cell = range.getCell(i+1,j+1);
21 | cell.offset(0,1).setValue(note);
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ExtractURL.js:
--------------------------------------------------------------------------------
1 | function extractAndPasteLinks() {
2 |
3 | var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
4 |
5 | // Get the number of rows with data in column B
6 | var lastRow = sheet.getLastRow();
7 |
8 | for (var i = 2; i <= lastRow; i++) {
9 | var cell = sheet.getRange(i, 2);
10 | var richTextValue = cell.getRichTextValue(); // Get the rich text value
11 |
12 | if (richTextValue) {
13 | var runs = richTextValue.getRuns(); // Get the runs (segments of text)
14 | for (var j = 0; j < runs.length; j++) {
15 | var url = runs[j].getLinkUrl(); // Get the URL from the text run
16 | if (url) {
17 | sheet.getRange(i, 3).setValue(url); // Paste the URL in Column C
18 | break; // Stop after the first URL is found
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Timestamp.js:
--------------------------------------------------------------------------------
1 | // This code is wriiten in Google Apps Script(JavaScript)
2 | // This code adds timestamp to Google Sheets as soon as a change is made to a specified column
3 | function onEdit(e){
4 |
5 | const row = e.range.getRow();
6 | const col = e.range.getColumn();
7 |
8 |
9 | const sheetName = "Sheet1";
10 | if (col === 1 && row > 1 && e.source.getActiveSheet().getName() === "Sheet1"){
11 |
12 | const currentDate = new Date();
13 | e.source.getActiveSheet().getRange(row,4).setValue(currentDate);
14 | const name = Session.getActiveUser().getEmail();
15 |
16 | e.source.getActiveSheet().getRange(row,5).setValue(name)
17 |
18 | if(e.source.getActiveSheet().getRange(row,3).getValue() == ""){
19 |
20 | e.source.getActiveSheet().getRange(row,3).setValue(currentDate);
21 |
22 | }
23 |
24 | }
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/Bard_Lang.js:
--------------------------------------------------------------------------------
1 | function BARD(sentence,origin_language,target_lanugage) {
2 | var apiKey = "your_api_key";
3 | var apiUrl = "https://generativelanguage.googleapis.com/v1beta2/models/text-bison-001:generateText";
4 | var url = apiUrl + "?key=" + apiKey;
5 | var headers = {
6 | "Content-Type": "application/json"
7 | };
8 |
9 | var prompt = {
10 |
11 | 'text': "Convert this sentence"+ sentence + "from"+origin_language + "to"+target_lanugage
12 |
13 | }
14 |
15 | var requestBody = {
16 |
17 | "prompt": prompt
18 | }
19 |
20 |
21 | var options = {
22 | "method": "POST",
23 | "headers": headers,
24 | "payload": JSON.stringify(requestBody)
25 | };
26 | var response = UrlFetchApp.fetch(url, options);
27 | var data = JSON.parse(response.getContentText());
28 | var output = data.candidates[0].output;
29 | Logger.log(output);
30 | return output;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/GetEvents_CalendarAPI.js:
--------------------------------------------------------------------------------
1 | function getEvents(){
2 | var ss = SpreadsheetApp.getActiveSpreadsheet();
3 | var sheet = ss.getSheetByName("GetEvents");
4 |
5 | var cal = CalendarApp.getCalendarById("aryanirani123@gmail.com");
6 | var events = cal.getEvents(new Date("6/27/2021 12:00 AM"), new Date("6/30/2021 11:59 PM"));
7 |
8 | for(var i = 0;i{
11 |
12 | all_labels.push(label.getName());
13 |
14 | })
15 |
16 | Logger.log(all_labels);
17 |
18 | let tempLabel;
19 |
20 | if(all_labels.includes(myLabel)){
21 | tempLabel = GmailApp.getUserLabelByName(myLabel);
22 | }
23 |
24 | else{
25 | GmailApp.createLabel(myLabel)
26 | }
27 |
28 | Logger.log(tempLabel)
29 |
30 | threads.forEach(function(message){
31 |
32 | //Logger.log(message);
33 | const first_message = message.getFirstMessageSubject();
34 | if(first_message.includes("Stats for your stories")){
35 |
36 | message.addLabel(tempLabel);
37 | //message.moveToArchive();
38 | }
39 | })
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/DriveGAPS.js:
--------------------------------------------------------------------------------
1 | const fileId = "your_file_id";
2 |
3 | function getUsers() {
4 | const file = DriveApp.getFileById(fileId);
5 | const editors = file.getEditors();
6 | const viewers = file.getViewers();
7 |
8 | const userEmails = [];
9 |
10 | // Extract emails from editors
11 | if (editors.length > 0) {
12 | editors.forEach(editor => {
13 | const email = editor.getEmail();
14 | if (email) {
15 | userEmails.push(email);
16 | }
17 | });
18 | }
19 |
20 | // Extract emails from viewers
21 | if (viewers.length > 0) {
22 | viewers.forEach(viewer => {
23 | const email = viewer.getEmail();
24 | if (email) {
25 | userEmails.push(email);
26 | }
27 | });
28 | }
29 |
30 | if (userEmails.length > 0) {
31 | Logger.log("Users with access:");
32 | userEmails.forEach(email => Logger.log(email));
33 | } else {
34 | Logger.log("No editors or viewers found for this file.");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Create_Events.js:
--------------------------------------------------------------------------------
1 | function create_Events(){
2 |
3 | var ss = SpreadsheetApp.getActiveSpreadsheet();
4 | var sheet = ss.getSheetByName("Calendar_Events");
5 | var last_row = sheet.getLastRow();
6 | var data = sheet.getRange("A1:E" + last_row).getValues();
7 | var cal = CalendarApp.getCalendarById("aryanirani123@gmail.com");
8 | //Logger.log(data);
9 |
10 | for(var i = 0;i< data.length;i++){
11 | // index 0 = Name of the Event
12 | // index 1 = Start Time of the Event
13 | // index 2 = End Time of the Event
14 | // index 3 = Location of the Event
15 | // index 4 = Description of the Event
16 | // index 5 = Attendess of the Event
17 |
18 | var Events = cal.createEvent(data[i][0],
19 | new Date(data[i][1]),
20 | new Date(data[i][2]),
21 | {location: data[i][3], description : data[i][4]});
22 | //Logger.log('Event ID: ' + event.getId());
23 |
24 | }
25 | Logger.log("Events have been added to the calendar");
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/ChangeCellColour.js:
--------------------------------------------------------------------------------
1 | //This code is written in Google Apps Script(JavaScript).
2 | //This code changes the colours of cells in Google Sheets on meeting the given criteria.
3 | //In this example, if the number in the cell is greater than 3, the cell colour to green.
4 |
5 | function ChangeColor(){
6 |
7 | const sheet = SpreadsheetApp.getActiveSheet();
8 | const range = sheet.getRange("D1:D10");
9 | const rule = SpreadsheetApp.newConditionalFormatRule()
10 | .whenNumberLessThan(4)
11 | .setBackground("red")
12 | .setRanges([range])
13 | .build();
14 | var rules = sheet.getConditionalFormatRules();
15 | rules.push(rule);
16 | sheet.setConditionalFormatRules(rules);
17 |
18 | var rule = SpreadsheetApp.newConditionalFormatRule()
19 | .whenNumberGreaterThan(3)
20 | .setBackground("green")
21 | .setRanges([range])
22 | .build();
23 | var rules = sheet.getConditionalFormatRules();
24 | rules.push(rule);
25 | sheet.setConditionalFormatRules(rules);
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/ChatGPT.gs:
--------------------------------------------------------------------------------
1 | / Replace with your OpenAI API key
2 | var API_KEY = "your_api_key";
3 |
4 |
5 | function GPT(prompt) {
6 |
7 | var Model_ID = "text-davinci-002";
8 | var maxTokens = 64;
9 | var temperature = 0.5;
10 | // Build the API payload
11 | var payload = {
12 | 'model': 'text-davinci-002', // or your desired model
13 | 'prompt': prompt,
14 | 'temperature': temperature,
15 | 'max_tokens': maxTokens,
16 | };
17 |
18 | // Build the API options
19 | var options = {
20 | "method": "post",
21 | "headers": {
22 | "Content-Type": "application/json",
23 | "Authorization": "Bearer " + API_KEY
24 | },
25 | "payload": JSON.stringify(payload)
26 | };
27 |
28 | // Make the API request
29 | var response = UrlFetchApp.fetch("https://api.openai.com/v1/completions", options);
30 |
31 | // Parse the response and return the generated text
32 | var responseData = JSON.parse(response.getContentText());
33 | return responseData.choices[0].text.trim();
34 | }
35 |
--------------------------------------------------------------------------------
/FiltersGoogleSheets.js:
--------------------------------------------------------------------------------
1 | // This code is written in Google Apps Script(JavaScript)
2 | // This code creates Filters in Google Sheets\
3 | // The filter criterias are specified in the code
4 |
5 |
6 | function create_filter(){
7 |
8 | var ss = SpreadsheetApp.getActiveSpreadsheet();
9 | var sheet1 = ss.getSheetByName("Filter_Sheet");
10 | var range = sheet1.getRange("A:D");
11 |
12 | var filter = range.createFilter();
13 |
14 | var Filter_Criteria1 = SpreadsheetApp.newFilterCriteria().whenNumberGreaterThan(500);
15 | var Filter_Criteria2 = SpreadsheetApp.newFilterCriteria().whenTextContains(['India/Mumbai']);
16 |
17 | var add_filter1 =filter.setColumnFilterCriteria(3,Filter_Criteria1);
18 | var add_filter2 = filter.setColumnFilterCriteria(4,Filter_Criteria2);
19 |
20 | Logger.log("Filter has been added.");
21 |
22 | var range = sheet1.getDataRange();
23 |
24 | var new_sheet = ss.insertSheet();
25 | new_sheet.setName("India/Mumbai Data");
26 |
27 | range.copyTo(new_sheet.getRange(1,1));
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/SendCharts.js:
--------------------------------------------------------------------------------
1 | // This code is written in Google Apps Script(JavaScript)
2 | // This code sends out charts from Google Sheets
3 | // Charts are created in Google Sheets,using Google Apps Script the charts will be emailed to the specified email.
4 |
5 | function emailChartSourceImage(){
6 | const sheet = SpreadsheetApp.getActiveSheet();
7 | const charts = sheet.getCharts();
8 |
9 | // setup some variables for our email
10 | const chartBlobs = new Array();
11 | const emailImages = {};
12 | let emailBody = "Charts ";
13 |
14 | charts.forEach(function(chart, i){
15 | chartBlobs[i] = chart.getAs("image/png");
16 | emailBody += "
"; // Alligning the chart to the center of the body in the email
17 | emailImages["chart"+i] = chartBlobs[i];
18 | });
19 |
20 | MailApp.sendEmail({
21 | to: "aryanirani123@gmail.com",
22 | subject: "Chart for average marks per subject",
23 | htmlBody: emailBody,
24 | inlineImages:emailImages});
25 | }
26 |
--------------------------------------------------------------------------------
/YouTube_DataAPI.js:
--------------------------------------------------------------------------------
1 | function getYoutube(){
2 |
3 | var sheet = SpreadsheetApp.getActiveSheet();
4 | var range = sheet.getRange(2,1, sheet.getLastRow() - 1);
5 | var vids = range.getValues();
6 | //Logger.log(vids);
7 |
8 | var links = vids.map(function(res){ return res[0];}).join(",");
9 | //Logger.log(links);
10 |
11 | var stats_vids = YouTube.Videos.list("snippet, statistics",{id: links});
12 | //Logger.log(stats_vids.items);
13 |
14 | var details = stats_vids.items.map(function(s){return [s.snippet.title];});
15 | sheet.getRange(2,2, details.length,details[0].length).setValues(details);
16 | //Logger.log(details);
17 |
18 | Logger.log("Title has been added");
19 |
20 | var final_stats = stats_vids.items.map(function(res){ return [res.statistics.viewCount,res.statistics.likeCount,res.statistics.dislikeCount]});
21 | //Logger.log(final_stats);
22 |
23 | sheet.getRange(2,3, final_stats.length,final_stats[0].length).setValues(final_stats);
24 | Logger.log("Stats have been added");
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/GoogleMapsDistance.gs:
--------------------------------------------------------------------------------
1 | function calculateDistances() {
2 | var ss = SpreadsheetApp.getActiveSpreadsheet();
3 | var sheet = ss.getSheetByName("Sheet1");
4 | var numRows = sheet.getDataRange().getNumRows();
5 | var data = sheet.getRange("A2:B" + numRows).getValues();
6 | var status_column = 5;
7 |
8 | for (var i = 0; i < data.length; i++) {
9 | var start = data[i][0];
10 | var end = data[i][1];
11 | var flag = data[i][4];
12 |
13 |
14 | if (start && end && flag !== "done") {
15 | var directions = Maps.newDirectionFinder()
16 | .setOrigin(start)
17 | .setDestination(end)
18 | .setMode(Maps.DirectionFinder.Mode.DRIVING)
19 | .getDirections();
20 |
21 | var distance = directions.routes[0].legs[0].distance.text;
22 | var duration = directions.routes[0].legs[0].duration.text;
23 |
24 | sheet.getRange(i+2, 3).setValue(distance);
25 | sheet.getRange(i+2, 4).setValue(duration);
26 | sheet.getRange(i+2, 5).setValue("done");
27 |
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/GeminiAPI.js:
--------------------------------------------------------------------------------
1 | function onFormSubmit(e){
2 |
3 | var reviewtext = e.namedValues["Describe your Experience "];
4 | var apiKey = "your_api_key";
5 | var apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent"
6 | var url = apiUrl +"?key="+apiKey;
7 |
8 | var headers = {
9 | "Content-Type": "application/json"
10 |
11 | };
12 |
13 | var requestBody = {
14 | "contents": [
15 | {
16 | "parts": [
17 | {
18 | "text": "Identify the items that the reviewer liked and did not like. Please categorise them in different lists, nicely formatted"+reviewtext
19 | }
20 | ]
21 | }
22 | ]
23 | };
24 | var options = {
25 |
26 | "method": "POST",
27 | "headers": headers,
28 | "payload": JSON.stringify(requestBody)
29 | };
30 |
31 | var response = UrlFetchApp.fetch(url,options);
32 | var data = JSON.parse(response.getContentText());
33 | var output = data.candidates[0].content.parts[0].text
34 | Logger.log(output);
35 |
36 |
37 |
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/SendBulkEmails.js:
--------------------------------------------------------------------------------
1 | // This Code is written in Google Apps Script
2 | // This code sends out Bulk Emails
3 | // The Data for Bulk emails is being extracted from two Google Sheets.
4 | // The First Google Sheet contains the data to be sent, and the second Google Sheets contains the email addresses of the recipients.
5 |
6 |
7 |
8 | function sendEmail() {
9 |
10 | // Get handle to active spreadsheet and sheet
11 | var ss = SpreadsheetApp.getActiveSpreadsheet();
12 | var responses1 = ss.getSheetByName("Sheet1");
13 | var responses2 = ss.getSheetByName("Sheet2");
14 |
15 | // Getting data from the sheets
16 | var data1 = responses1.getRange(2,1,2,3).getValues(); // Getting the subject, body and the footer from the sheet
17 | var data2 = responses2.getRange(2,3,responses2.getLastRow() - 1,4).getValues(); // Getting the email address of the residents
18 |
19 | //Row 1 and Col 1
20 | var EmailSubject = data1[0][0];
21 | var EmailBody = data1[0][1];
22 | var EmailFooter = data1[0][2];
23 |
24 | data2.forEach(function (row,i) {
25 | MailApp.sendEmail(row[1],EmailSubject,'Dear ' + row[0] + ',\n\n' + EmailBody + '\n\n' + EmailFooter);
26 | });
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/BulkEmails.js:
--------------------------------------------------------------------------------
1 | function SendEmail(){
2 |
3 | const ss = SpreadsheetApp.getActiveSpreadsheet();
4 | const sheet = ss.getSheetByName("Student Details");
5 |
6 | var data = sheet.getRange(2,1,sheet.getLastRow() - 1,2).getValues();
7 | //Logger.log(data);
8 |
9 |
10 | data.forEach(function(row,i){
11 |
12 | var name = row[0];
13 | var email = row[1];
14 | Logger.log(name)
15 | Logger.log(email)
16 |
17 |
18 |
19 | var body = "Dear "+ name + "
"+
20 |
21 | " It was noted with serious concern that quite a few students were detained last semester on account of attendance default. Despite monthly attendance information" + "
"+
22 | "being provided to students and regular counselling by faculty members, it is found that students do not take the attendance rules seriously. This results in losing an academic year affecting career" + "
"+
23 | "prospects after graduation. It is also noted that students do not read the SRB and are not aware of the various rules and regulations and the repercussions of non-compliance."+ ",
" +
24 | "Regards,"+ "
"+
25 | " XYZ University " + "
";
26 |
27 |
28 | var subject = "Student Attendance";
29 | //GmailApp.sendEmail(email, subject, "", { htmlBody: body } );
30 |
31 | });
32 |
33 |
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/BlogSummaryPaLM.js:
--------------------------------------------------------------------------------
1 | function onOpen(){
2 |
3 | var ui = DocumentApp.getUi();
4 | ui.createMenu('Custom Menu')
5 | .addItem('Summarize Selected Paragraph', 'summarizeSelectedParagraph')
6 | .addToUi();
7 |
8 | }
9 |
10 | function DocSummary(paragraph){
11 |
12 | var apiKey = "your_api_key";
13 | var apiUrl = "https://generativelanguage.googleapis.com/v1beta2/models/text-bison-001:generateText";
14 |
15 | var url = apiUrl + "?key=" + apiKey;
16 |
17 | var headers = {
18 |
19 | "Content-Type": "application/json"
20 | }
21 |
22 | var prompt = {
23 |
24 | 'text': "Please generate a short summary for :\n" + paragraph
25 | }
26 |
27 | var requestBody = {
28 | "prompt": prompt
29 | }
30 |
31 | var options = {
32 |
33 | "method": "POST",
34 | "headers": headers,
35 | "payload": JSON.stringify(requestBody)
36 |
37 | }
38 |
39 | var response = UrlFetchApp.fetch(url,options);
40 | var data = JSON.parse(response.getContentText());
41 | return data.candidates[0].output;
42 |
43 |
44 | }
45 |
46 | function summarizeSelectedParagraph(){
47 |
48 | var selection = DocumentApp.getActiveDocument().getSelection();
49 | var text = selection.getRangeElements()[0].getElement().getText();
50 | var summary = DocSummary(text);
51 | DocumentApp.getActiveDocument().getBody().appendParagraph("Summary");
52 | DocumentApp.getActiveDocument().getBody().appendParagraph(summary)
53 |
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/BlogSummaryAI.gs:
--------------------------------------------------------------------------------
1 | var API_key = "your_api_key";
2 |
3 | function BlogSummary(){
4 |
5 | var Model_ID = "text-davinci-002";
6 | var maxtokens = 200;
7 | var temperature = 0.7;
8 |
9 |
10 | var ss = SpreadsheetApp.getActiveSpreadsheet();
11 | var sheet = ss.getSheetByName("Sheet1");
12 | var urls = sheet.getRange("A2:A6").getValues()
13 |
14 | for(var i=0; i
2 |
3 |
4 | Countdown Timer
5 |
20 |
21 |
22 |
23 |
53 |
54 |
--------------------------------------------------------------------------------
/SendPDF.js:
--------------------------------------------------------------------------------
1 | // This code is written in Google Apps Script(JavaScript)
2 | // This code sends out automated pdfs on email to the people who have registered for the Event.
3 | // The Google Sheet contains details on each of the student for whom we have to create ID cards
4 | // On running the code the ID cards will automatically get created and send it to the email address of the student.
5 |
6 |
7 |
8 | function After_Submit(e){
9 |
10 | const info = e.namedValues;
11 | const pdfFile = Create_PDF(info);
12 |
13 | console.log(info);
14 |
15 | sendEmail(e.namedValues['Email Address'][0],pdfFile);
16 | }
17 |
18 | function sendEmail(email,pdfFile){
19 |
20 | GmailApp.sendEmail(email, "ID CARD", "This is your ID Card.", {
21 | attachments: [pdfFile],
22 | name: "HEllO"
23 |
24 | });
25 |
26 | }
27 | function Create_PDF(info) {
28 |
29 | const PDF_folder = DriveApp.getFolderById("1zx7rnI2M3p2U7RGTJugM_0G5aMINYTyh");
30 | const TEMP_FOLDER = DriveApp.getFolderById("1jO1BHwhwkKbGFcyT8DAJsew2v0gjCI4W");
31 | const PDF_Template = DriveApp.getFileById("1qHOMwuq2X_5LhUCfPLWcpUSh2n7pVRvHZ_kE-hsGmwg");
32 |
33 | const newTempFile = PDF_Template.makeCopy(TEMP_FOLDER);
34 | const OpenDoc = DocumentApp.openById(newTempFile.getId());
35 | const body = OpenDoc.getBody();
36 |
37 | console.log(body);
38 |
39 | body.replaceText("{email}", info['Email Address'][0])
40 | body.replaceText("{name}", info['Enter your name'][0]);
41 | body.replaceText("{roll}", info['Enter your Roll number'][0]);
42 | body.replaceText("{number}", info['Enter your phone number '][0]);
43 | body.replaceText("{DOB}", info['Enter you Date of Birth '][0]);
44 | body.replaceText("{BLOOD}", info['Enter your Blood Group [Eg: O negative]'][0]);
45 |
46 | OpenDoc.saveAndClose();
47 |
48 |
49 | const BLOBPDF = newTempFile.getAs(MimeType.PDF);
50 | const pdfFile = PDF_folder.createFile(BLOBPDF).setName(info['Enter your name'][0] + " " + info['Enter your Roll number'][0]);
51 | console.log("The file has been created ");
52 |
53 | return pdfFile;
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/CreateBulkClassroom.js:
--------------------------------------------------------------------------------
1 | /*
2 | This code is wriiten in Google Apps Script(JavaScript)
3 | This code creates nulk Google Classroom using Google Apps Script
4 | The Classes are created provided the following data is present in the Google Sheet
5 |
6 | (1) Name of the Class
7 | (2) Section of the Class
8 | (3) Room
9 | (4) Description of the Class
10 |
11 | */
12 | OWNER_EMAIL = "aryanirani123@gmail.com"; //Don't forget to update this value with your email address :)
13 |
14 | function onOpen(){
15 | const menu = SpreadsheetApp.getUi().createMenu('Custom');
16 | menu.addItem('Create Classroom','createClasses');
17 | menu.addToUi();
18 | }
19 | function classroomData(properties){
20 |
21 | const crs = Classroom.newCourse();
22 | Object.keys(properties).forEach(key => {
23 | Crs[key] = properties[key];
24 | })
25 | const createdCourse = Classroom.Courses.create(crs);
26 | return createdCourse.enrollmentCode;
27 | }
28 | function createClasses(){
29 |
30 | const ss = SpreadsheetApp.getActiveSpreadsheet();
31 | const sheet = ss.getActiveSheet();
32 | const START_ROW= 2;
33 | const START_COLUMN = 1;
34 | const LAST_COLUMN= 4;
35 | const data = sheet.getRange(
36 | START_ROW,
37 | START_COLUMN,
38 | sheet.getLastRow()-1,
39 | LAST_COLUMN).getValues();
40 | const enrollmentCodes = [];
41 | const nameIndex = 0;
42 | const sectionIndex = 1;
43 | const roomIndex = 2
44 | const descriptionIndex = 3;
45 | const START_COLUMN = 5;
46 | const LAST_COLUMN = 1;
47 | data.forEach(row => {
48 | const eCode = classroomData({
49 | name: row[nameIndex],
50 | section: row[sectionIndex],
51 | room: row[roomIndex],
52 | description: row[descriptionIndex],
53 | ownerId: OWNER_EMAIL
54 | });
55 | enrollmentCodes.push([eCode]);
56 | sheet.getRange(
57 | START_ROW,
58 | COLUMN_START,
59 | enrollmentCodes.length,
60 | COLUMN_LAST).setValues(enrollmentCodes);
61 | });
62 | }
63 |
--------------------------------------------------------------------------------
/DocsAgentADK/code.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Adds a custom menu in Google Docs to run the AI Audit directly.
3 | */
4 | function onOpen() {
5 | DocumentApp.getUi()
6 | .createMenu('AI Audit Tools')
7 | .addItem('Run AI Audit', 'runAuditAndInsert')
8 | .addToUi();
9 | }
10 |
11 | /**
12 | * Returns the entire text content of the document.
13 | */
14 | function getDocumentText() {
15 | const doc = DocumentApp.getActiveDocument();
16 | const body = doc.getBody();
17 | let text = body.getText();
18 | return text.trim();
19 | }
20 |
21 | /**
22 | * Runs the AI Audit and inserts the result as text at the end of the document.
23 | */
24 | function runAuditAndInsert() {
25 | const docText = getDocumentText();
26 | const result = runAudit(docText);
27 |
28 | if (result) {
29 | const doc = DocumentApp.getActiveDocument();
30 | const body = doc.getBody();
31 | // Append the audit result as a new paragraph at the end of the document
32 | body.appendParagraph('AI Audit Result: ' + result);
33 | }
34 | }
35 |
36 | /**
37 | * Runs the AI Audit using ADK Agent and Gemini formatting.
38 | */
39 | function runAudit(docText) {
40 | console.log('[INFO] Starting AI audit process...');
41 | if (!docText) {
42 | console.log('[WARN] No text in document.');
43 | return '⚠️ The document is empty. Please add some text to audit.';
44 | }
45 |
46 | // Check for excessive document length to avoid token limits
47 | if (docText.length > 10000) {
48 | console.log('[WARN] Document too long.');
49 | return '⚠️ Document exceeds 10,000 characters. Please shorten the text.';
50 | }
51 |
52 | console.log('[STEP] Sending text to ADK Agent...');
53 | const rawAudit = requestLlmAuditorAdkAiAgent(docText);
54 |
55 | // Check if rawAudit is an error message
56 | if (rawAudit.startsWith('ERROR:')) {
57 | console.error('[ERROR] ADK Agent returned error:', rawAudit);
58 | return rawAudit;
59 | }
60 |
61 | console.log('[STEP] Formatting AI response...');
62 | let formatted;
63 | try {
64 | formatted = requestOutputFormatting(
65 | `Here is a fact-checking result: ${rawAudit}.
66 | Summarize it. Keep the main verdict and reasoning. Remove markdown and make it concise.`
67 | );
68 | } catch (error) {
69 | console.error('[ERROR] Formatting failed:', error.toString());
70 | return `ERROR: Failed to format audit result - ${error.toString()}`;
71 | }
72 |
73 | console.log('[SUCCESS] Audit completed successfully.');
74 | console.log('[RESULT] Final Output:', formatted);
75 | return formatted;
76 | }
77 |
--------------------------------------------------------------------------------
/SendEmail.js:
--------------------------------------------------------------------------------
1 | // This code is written in Google Apps Script
2 | // This code takes data from a Google Sheet and send Automated Emails to the students.
3 | // Each email depends on the students grade. If a student recieves a bad grade, he will be sent a special email.
4 | // To know more, check out the blog link: https://aryanirani123.medium.com/google-sheets-automation-using-google-apps-script-60c107ff6bcd
5 |
6 |
7 |
8 | function sendEmail() {
9 |
10 | //Get the handle to the active spreadsheet & sheet.
11 | var ss = SpreadsheetApp.getActiveSpreadsheet();
12 | var responses = ss.getSheetByName("Form Responses 1");
13 |
14 | //Get the data starting from values (i.e. skip the header row)
15 | var data = responses.getRange(2,1,responses.getLastRow() - 1,6).getValues();
16 |
17 | Logger.log(data);
18 |
19 | //Iterate each row of data
20 | data.forEach(function(row, i) {
21 |
22 | // variables
23 | var Marks = row[1]; // marks secured by the students
24 | var Name = row[2]; // Name of the student
25 | var Email_ID = row[3];// Email address of the student
26 | var Roll_no = row[4]; // Roll number of the student
27 |
28 | // only send reply if the replied column is still blank
29 | if (Marks <= 10){
30 | // send an email for marks less than equal to 10
31 | var body = formatEmailBody("Bad",Name, Marks,Email_ID,Roll_no);
32 | }
33 |
34 | else if (Marks <10) {
35 | // send an email for marks greater than 10
36 |
37 | var body = formatEmailBody("Moderate",Name, Marks,Email_ID,Roll_no);
38 | }
39 | else if (Marks <= 15) {
40 | // send an email for marks greater than equal to 15
41 | var body = formatEmailBody("good",Name, Marks,Email_ID,Roll_no);
42 | }
43 |
44 | else if (Marks <= 20) {
45 | // send an email marks greater than equal to 20
46 | var body = formatEmailBody("Very Good",Name, Marks,Email_ID,Roll_no);
47 | }
48 |
49 | else if (Marks <= 25) {
50 | // send an email for marks greater than equal to 25
51 | var body = formatEmailBody("Great",Name, Marks,Email_ID,Roll_no);
52 | }
53 |
54 | var subject = "Report for Maths Test";
55 | GmailApp.sendEmail(Email_ID, subject, "", { htmlBody: body } );
56 |
57 | });
58 |
59 | }
60 |
61 | function formatEmailBody(Rating, Name, Marks,Email_ID,Roll_no) {
62 |
63 | var emailTxt = "Teachers remarks: " + Rating + "
"+
64 |
65 | " Name : " + Name + ",
" +
66 | " Score : " + Marks + "
" +
67 | " Email Address : " + Email_ID + "
" +
68 | " Roll Number : " + Roll_no + "
";
69 |
70 | return emailTxt;
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/ServiceAccount.js:
--------------------------------------------------------------------------------
1 | // Save in Apps Script Properties or Secret Manager
2 |
3 | var CREDENTIALS = {
4 | private_key: "your_private_key"
5 | client_email: 'examplename@project2-283514.iam.gserviceaccount.com',
6 | };
7 |
8 | function getOAuthService(user) {
9 | return OAuth2.createService("Service Account")
10 | .setTokenUrl('https://oauth2.googleapis.com/token')
11 | .setPrivateKey(CREDENTIALS.private_key)
12 | .setIssuer(CREDENTIALS.client_email)
13 | .setSubject(user)
14 | .setPropertyStore(PropertiesService.getScriptProperties())
15 | .setParam('access_type', 'offline')
16 | .setScope('https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/spreadsheets')
17 | }
18 |
19 | function reset() {
20 | var service = getOAuthService();
21 | service.reset();
22 | }
23 |
24 |
25 | // Function to execute BigQuery query
26 | function executeQuery(query) {
27 | const service = getOAuthService(CREDENTIALS.client_email);
28 | if (!service.hasAccess()) {
29 | throw new Error('Authorization required. Check script permissions.');
30 | }
31 |
32 | const request = {
33 | query: query,
34 | useLegacySql: false
35 | };
36 | const projectId = 'project2-283514';
37 | return BigQuery.Jobs.query(request, projectId);
38 | }
39 |
40 | // Function to process and log results
41 | function processQueryResults(queryResults, sheet, headers, startRow) {
42 | if (queryResults.rows && queryResults.rows.length > 0) {
43 | const data = queryResults.rows.map(row => row.f.map(cell => cell.v));
44 | const lastRow = sheet.getLastRow();
45 |
46 | // Clear previous data
47 | if (lastRow > startRow - 1) {
48 | sheet.getRange(startRow, 2, lastRow - startRow + 1, headers.length).clear();
49 | }
50 |
51 | // Write headers and data
52 | sheet.getRange(1, 2, 1, headers.length).setValues([headers]);
53 | sheet.getRange(startRow, 2, data.length, headers.length).setValues(data);
54 | } else {
55 | Logger.log('No data found.');
56 | }
57 | }
58 |
59 | // Fetch results for multiple IDs
60 | function FetchResults() {
61 | const spreadsheetId = 'your_spreadsheet_id';
62 | const sheetName = 'your_sheet_name';
63 | const timestampCell = 'your_timestamp_cell';
64 |
65 | const spreadsheet = SpreadsheetApp.openById(spreadsheetId);
66 | const sheet = spreadsheet.getSheetByName(sheetName);
67 | const ids = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues().flat();
68 |
69 | if (ids.length === 0) {
70 | Logger.log('No IDs found in the sheet.');
71 | return;
72 | }
73 | // This is an example query you can always customise it to your needs.
74 | const query = `
75 | SELECT
76 | \`Test Name\`,
77 | \`Participants\`,
78 | \`Test Focus\`
79 | FROM \`project2-283514.invoices_dataset.FInalTry\`
80 | WHERE \`id\` IN (${ids.map(id => `'${id}'`).join(", ")})
81 | ORDER BY \`Test Name\`;
82 | `;
83 |
84 | const queryResults = executeQuery(query);
85 | processQueryResults(queryResults, sheet, ['Test Name', 'Participants', 'Test Focus'], 2);
86 | sheet.getRange(timestampCell).setValue(`Last Updated: ${new Date()}`);
87 | }
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Google-Apps-Script
2 | Collection of Google Apps Script Automation scripts written and compiled by Aryan Irani.
3 |
4 | AddGoogleMeet.js - Create Calendar Events with a Google Meet link using Google Apps Script. The Calendar Events contain data from a Google Sheet.
5 |
6 |
7 | Blog Link : https://bit.ly/3bw8KsI
8 | Video Tutorial : https://www.youtube.com/watch?v=_pY9eK1V_JA
9 |
10 | ChangeCellColour.js - Changes colour of cells in Google Sheets using Google Apps Script.If a change is made in the Google Sheet, that meets the conditions
11 | mentioned in the script, the colour of the cell will be changed.
12 |
13 |
14 | Blog Link : https://bit.ly/3jSV5Rk
15 | Video Tutorial : will be out soon :)
16 |
17 | CreateBulkClassroom.js - Bulk create Google Classrooms, with custom data present in Google Sheets using Google Apps Script. After the classrooms are created, the
18 | class codes are pasted in the Google Sheet for further use.
19 |
20 |
21 | Blog Link : https://bit.ly/3nIkUVk
22 | Video tutorial : https://www.youtube.com/watch?v=YZQdkrJSVgQ&t=2s
23 |
24 | Create_Events.js - Create calendar events with data from Google Sheets using Google Apps Script. Bulk create calendar events wtih custom details for each event.
25 |
26 |
27 | Blog Link : https://bit.ly/3q0VwN4
28 | Video Tutorial : https://www.youtube.com/watch?v=DKYM8CYwSUE
29 |
30 | ExtractCellNotes.js - Extract cell notes from Google Sheets using Google Apps Script. Extract cell notes into the adjacent column using Google Apps Script.
31 |
32 |
33 | Blog Link : https://bit.ly/3bqgWuy
34 | Video Tutorial : https://www.youtube.com/watch?v=z0k0nNieL2o
35 |
36 | FiltersGoogleSheets.js - Create filters in Google Sheets using Google Apps Script. Instead of manually creating filters, automate the process using Google Apps Script,
37 | by just specifying the filter criteria.
38 |
39 |
40 | Blog Link : https://bit.ly/2ZB7gem
41 | Video Tutorial : https://www.youtube.com/watch?v=0dKQy0yakvI&t=139s
42 |
43 | GetEvents_CalendarAPI.js - Get calendar events with all the details from your Google Calendar into your Google Sheet using Google Apps Script.
44 |
45 |
46 | Blog Link : https://bit.ly/3pRoUW8
47 | Video tutorial : https://www.youtube.com/watch?v=YDhln3ukH7Y&t=2s
48 |
49 | LimitResponses.js - Limit responses in Google Forms, using Google Apps Script.
50 |
51 |
52 | Blog Link : https://bit.ly/317vQ78
53 | Video Tutorial :https://www.youtube.com/watch?v=Uee_7cZW0p0&t=2s
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/Renewal.js:
--------------------------------------------------------------------------------
1 | function checkAndSendRenewalEmails() {
2 | const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
3 | const data = sheet.getDataRange().getValues();
4 |
5 | // Assuming 'Subscription End Date' is in column 6 (F), 'Name' is in column 2 (B), and 'User ID' is in column 0 (A)
6 | const EmailRange = sheet.getRange(3, 2, sheet.getLastRow() - 2, 1);
7 | const EndDateRange = sheet.getRange(3, 7, sheet.getLastRow() - 2, 1);
8 | const NameRange = sheet.getRange(3, 3, sheet.getLastRow() - 2, 1);
9 | const StatusRange = sheet.getRange(3, 10, sheet.getLastRow() - 2, 1); // Assuming we add 'Status' column
10 | const LogsRange = sheet.getRange(3, 11, sheet.getLastRow() - 2, 1); // Assuming we add 'Logs' column
11 |
12 | const EmailValues = EmailRange.getValues();
13 | const EndDateValues = EndDateRange.getValues();
14 | const NameValues = NameRange.getValues();
15 | const StatusValues = StatusRange.getValues();
16 | const LogsValues = LogsRange.getValues();
17 |
18 | const today = new Date();
19 | const currentmonth = today.getMonth();
20 | const currentyear = today.getFullYear();
21 | const dayOfMonth = today.getDate();
22 |
23 | if (dayOfMonth !== 30) { // Adjust this check as per your requirement
24 | Logger.log("Today is not the 6th of the month. No emails will be sent.");
25 | return;
26 | }
27 |
28 | Logger.log(`Today's date is ${today}`);
29 | Logger.log(`Processing ${EmailValues.length} rows`);
30 |
31 | for (let i = 0; i < EmailValues.length; i++) {
32 | const email = EmailValues[i][0];
33 | const endDateStr = EndDateValues[i][0];
34 | const name = NameValues[i][0];
35 |
36 | Logger.log(`Row ${i + 3}: email=${email}, endDateStr=${endDateStr}`);
37 |
38 | if (email !== "" && endDateStr !== "") {
39 | const endDate = new Date(endDateStr);
40 | if (isNaN(endDate)) {
41 | Logger.log(`Invalid date in row ${i + 3}: ${endDateStr}`);
42 | LogsValues[i][0] = `Invalid date format: ${endDateStr}`;
43 | continue;
44 | }
45 |
46 | const monthend = endDate.getMonth();
47 | const dayend = endDate.getDate();
48 |
49 | Logger.log(`Row ${i + 3}: endDate=${endDate}, monthend=${monthend}, dayend=${dayend}, name=${name}`);
50 |
51 | if (monthend === currentmonth && endDate.getFullYear() === currentyear) {
52 | try {
53 | const emailBody = `
54 | Dear ${name},
55 |
56 | We hope you're enjoying your fitness journey with us! We wanted to remind you that your gym membership is set to expire on ${endDateStr}.
57 |
58 | To keep your momentum going and continue achieving your fitness goals, we encourage you to renew your membership before it expires. By renewing now, you'll ensure that you have uninterrupted access to all our facilities, classes, and expert trainers.
59 |
60 | If you have any questions about your renewal options or need assistance, our team is here to help. Just give us a call or drop by the front desk on your next visit.
61 |
62 | Thank you for being a valued member of our fitness community. We look forward to supporting you in your ongoing pursuit of health and wellness.
63 |
64 | Stay strong,
65 |
66 | 24/7 Fitness
67 | Member Support Team
68 | Rachel Grae
69 |
70 | P.S. Renew your membership this month and enjoy exclusive offers, including discounted personal training sessions!
71 | `;
72 |
73 | MailApp.sendEmail(email, "Please upgrade your subscription", emailBody);
74 | Logger.log(`Email sent to ${email} for renewal date ${endDateStr}`);
75 | StatusValues[i][0] = 'Pending';
76 | LogsValues[i][0] = 'EMAIL SENT';
77 | } catch (e) {
78 | Logger.log(`Failed to send email to ${email}: ${e.message}`);
79 | LogsValues[i][0] = `Failed to send email: ${e.message}`;
80 | }
81 | }
82 | } else {
83 | Logger.log(`Skipping row ${i + 3} due to missing email or end date.`);
84 | LogsValues[i][0] = 'Missing email or end date';
85 | }
86 | }
87 |
88 | // Update the Status and Logs columns
89 | StatusRange.setValues(StatusValues);
90 | LogsRange.setValues(LogsValues);
91 | }
92 |
--------------------------------------------------------------------------------
/DocsAgentADK/AIVertex.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2025 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | const LOCATION = PropertiesService.getScriptProperties().getProperty('LOCATION');
18 | const GEMINI_MODEL_ID = PropertiesService.getScriptProperties().getProperty('GEMINI_MODEL_ID');
19 | const REASONING_ENGINE_ID = PropertiesService.getScriptProperties().getProperty('REASONING_ENGINE_ID');
20 | const SERVICE_ACCOUNT_KEY = PropertiesService.getScriptProperties().getProperty('SERVICE_ACCOUNT_KEY');
21 |
22 | const credentials = credentialsForVertexAI();
23 |
24 | /**
25 | * @param {string} statement The statement to fact-check.
26 | */
27 | function requestLlmAuditorAdkAiAgent(statement) {
28 | return UrlFetchApp.fetch(
29 | `https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${credentials.projectId}/locations/${LOCATION}/reasoningEngines/${REASONING_ENGINE_ID}:streamQuery?alt=sse`,
30 | {
31 | method: 'post',
32 | headers: { 'Authorization': `Bearer ${credentials.accessToken}` },
33 | contentType: 'application/json',
34 | muteHttpExceptions: true,
35 | payload: JSON.stringify({
36 | "class_method": "async_stream_query",
37 | "input": {
38 | "user_id": "google_sheets_custom_function_fact_check",
39 | "message": statement,
40 | }
41 | })
42 | }
43 | ).getContentText();
44 | }
45 |
46 | /**
47 | * @param {string} prompt The Gemini prompt to use.
48 | */
49 | function requestOutputFormatting(prompt) {
50 | const response = UrlFetchApp.fetch(
51 | `https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${credentials.projectId}/locations/${LOCATION}/publishers/google/models/${GEMINI_MODEL_ID}:generateContent`,
52 | {
53 | method: 'post',
54 | headers: { 'Authorization': `Bearer ${credentials.accessToken}` },
55 | contentType: 'application/json',
56 | muteHttpExceptions: true,
57 | payload: JSON.stringify({
58 | "contents": [{
59 | "role": "user",
60 | "parts": [{ "text": prompt }]
61 | }],
62 | "generationConfig": { "temperature": 0.1, "maxOutputTokens": 2048 },
63 | "safetySettings": [
64 | {
65 | "category": "HARM_CATEGORY_HARASSMENT",
66 | "threshold": "BLOCK_NONE"
67 | },
68 | {
69 | "category": "HARM_CATEGORY_HATE_SPEECH",
70 | "threshold": "BLOCK_NONE"
71 | },
72 | {
73 | "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
74 | "threshold": "BLOCK_NONE"
75 | },
76 | {
77 | "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
78 | "threshold": "BLOCK_NONE"
79 | }
80 | ]
81 | })
82 | }
83 | );
84 | return JSON.parse(response).candidates[0].content.parts[0].text
85 | }
86 |
87 | /**
88 | * Gets credentials required to call Vertex API using a Service Account.
89 | * Requires use of Service Account Key stored with project.
90 | *
91 | * @return {!Object} Containing the Google Cloud project ID and the access token.
92 | */
93 | function credentialsForVertexAI() {
94 | const credentials = SERVICE_ACCOUNT_KEY;
95 | if (!credentials) {
96 | throw new Error("service_account_key script property must be set.");
97 | }
98 |
99 | const parsedCredentials = JSON.parse(credentials);
100 |
101 | const service = OAuth2.createService("Vertex")
102 | .setTokenUrl('https://oauth2.googleapis.com/token')
103 | .setPrivateKey(parsedCredentials['private_key'])
104 | .setIssuer(parsedCredentials['client_email'])
105 | .setPropertyStore(PropertiesService.getScriptProperties())
106 | .setScope("https://www.googleapis.com/auth/cloud-platform");
107 | return {
108 | projectId: parsedCredentials['project_id'],
109 | accessToken: service.getAccessToken(),
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/PodcastGenAI/Script.js:
--------------------------------------------------------------------------------
1 | function onOpen() {
2 | var ui = DocumentApp.getUi();
3 | ui.createMenu('PodcastGenPro')
4 | .addItem('Launch Sidebar', 'showSidebar')
5 | .addToUi();
6 | }
7 |
8 | function showSidebar() {
9 | var html = HtmlService.createHtmlOutputFromFile('Sidebar')
10 | .setTitle('PodcastGeneratorPro')
11 | .setWidth(800);
12 | DocumentApp.getUi().showSidebar(html);
13 | }
14 |
15 | function getSelectedText() {
16 | var doc = DocumentApp.getActiveDocument();
17 | var selection = doc.getSelection();
18 | if (selection) {
19 | var elements = selection.getRangeElements();
20 | var selectedText = elements.map(function (element) {
21 | return element.getElement().asText().getText();
22 | }).join("\n");
23 | return selectedText;
24 | }
25 | return "";
26 | }
27 | function sendToGemini(selectedText) {
28 | const GEMINI_KEY = 'YOUR_API_KEY';
29 | const GEMINI_ENDPOINT = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=${GEMINI_KEY}`;
30 |
31 | var headers = {
32 | "Content-Type": "application/json",
33 | };
34 |
35 | var requestBody = {
36 | "contents": [
37 | {
38 | "parts": [
39 | {
40 | "text": `You are an AI scriptwriter for a podcast called *The Machine Learning Engineer*. Your task is to generate a natural, engaging, and dynamic podcast script in a conversational format between two speakers: Marina and Sascha. The discussion should feel spontaneous and lively, with realistic interactions. The output should be in Hindi langauge
41 | Use the following format:
42 | [
43 | {
44 | "speaker": "Marina",
45 | "text": ""
46 | },
47 | {
48 | "speaker": "Sascha",
49 | "text": ""
50 | },
51 | ]
52 | ### Topic:
53 | ${selectedText}
54 |
55 | Use the information provided above as the core discussion material for this episode. Marina will introduce the topic, and Sascha will explain it in detail, with back-and-forth interactions that make the conversation engaging.
56 |
57 | ### Tone & Style:
58 | - Friendly, engaging, and conversational.
59 | - Natural flow, like two experts chatting informally.
60 | - Keep it dynamic with occasional expressions of surprise, humor, or curiosity.
61 |
62 | ### Instructions for Response:
63 | - The response should be a structured JSON list of dialogue exchanges.
64 | - Maintain a lively discussion with a smooth flow of ideas.
65 | - Ensure Sascha provides clear and engaging explanations while Marina asks insightful follow-up questions.
66 |
67 | Return the response in the specified JSON format, ensuring it stays structured correctly while keeping the dialogue engaging and informative.
68 | `
69 | }
70 | ]
71 | }
72 | ]
73 | };
74 |
75 | var options = {
76 | "method": "POST",
77 | "headers": headers,
78 | "payload": JSON.stringify(requestBody),
79 | "muteHttpExceptions": true
80 |
81 | };
82 |
83 | try {
84 | var response = UrlFetchApp.fetch(GEMINI_ENDPOINT, options);
85 | var data = JSON.parse(response.getContentText());
86 |
87 | Logger.log("Gemini API Response: " + JSON.stringify(data));
88 |
89 | // Extract the JSON part from the response
90 | if (data.candidates && data.candidates[0].content.parts[0].text) {
91 | var scriptText = data.candidates[0].content.parts[0].text;
92 |
93 | // Remove code block markers and parse JSON
94 | var startIndex = scriptText.indexOf('[');
95 | var endIndex = scriptText.lastIndexOf(']');
96 | var cleanScriptText = scriptText.substring(startIndex, endIndex + 1);
97 | var conversationScript = JSON.parse(cleanScriptText);
98 |
99 | Logger.log(conversationScript)
100 |
101 | // Cloud Run Call
102 | const url1 = 'YOUR_CLOUD_RUN_ENDPOINT';
103 | var payload1 = {
104 | 'variable': JSON.stringify(conversationScript)
105 | };
106 | var options1 = {
107 | 'method': 'post',
108 | 'contentType': 'application/json',
109 | 'payload': JSON.stringify(payload1),
110 | 'muteHttpExceptions': true
111 | };
112 |
113 | var cloudFunctionResponse = UrlFetchApp.fetch(url1, options1);
114 | Logger.log("Script sent to Cloud Run");
115 | Logger.log("Cloud Run Response: " + cloudFunctionResponse.getContentText());
116 | } else {
117 | Logger.log("Unexpected Gemini API response format: " + JSON.stringify(data));
118 | }
119 | } catch (e) {
120 | Logger.log("Error during Gemini API or Cloud Run call: " + e.message);
121 | }
122 | }
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/PodcastGenAI/audio.py:
--------------------------------------------------------------------------------
1 | import os
2 | import flask
3 | import datetime
4 | import re
5 | import json
6 | from google.cloud import storage, texttospeech
7 | from pydub import AudioSegment
8 |
9 | # Directory to store files (Cloud Run allows writing to /tmp)
10 | FILE_DIR = '/tmp/'
11 | BUCKET_NAME = 'aryan_bucket'
12 |
13 | # Google TTS Client
14 | client = texttospeech.TextToSpeechClient()
15 |
16 | # Speaker-to-voice mapping
17 | speaker_voice_map = {
18 | "Sascha": "en-US-Wavenet-D",
19 | "Marina": "en-US-Journey-O"
20 | }
21 |
22 | # Google TTS function
23 | def synthesize_speech_google(text, speaker, index):
24 | synthesis_input = texttospeech.SynthesisInput(text=text)
25 | voice = texttospeech.VoiceSelectionParams(
26 | language_code="en-US",
27 | name=speaker_voice_map[speaker]
28 | )
29 | audio_config = texttospeech.AudioConfig(
30 | audio_encoding=texttospeech.AudioEncoding.LINEAR16
31 | )
32 | response = client.synthesize_speech(
33 | input=synthesis_input, voice=voice, audio_config=audio_config
34 | )
35 | filename = f"{FILE_DIR}{index}_{speaker}.wav"
36 | with open(filename, "wb") as out:
37 | out.write(response.audio_content)
38 | print(f'Audio content written to file "{filename}"')
39 |
40 | def synthesize_speech(text, speaker, index):
41 | synthesize_speech_google(text, speaker, index)
42 |
43 | # Function to sort filenames naturally
44 | def natural_sort_key(filename):
45 | return [int(text) if text.isdigit() else text for text in re.split(r'(\d+)', filename)]
46 |
47 | # Function to merge audio files
48 | def merge_audios(audio_folder, output_file):
49 | combined = AudioSegment.empty()
50 | audio_files = sorted(
51 | [f for f in os.listdir(audio_folder) if f.endswith(".wav")],
52 | key=natural_sort_key
53 | )
54 | for filename in audio_files:
55 | audio_path = os.path.join(audio_folder, filename)
56 | print(f"Processing: {audio_path}")
57 | audio = AudioSegment.from_file(audio_path)
58 | combined += audio
59 | combined.export(output_file, format="mp3")
60 | print(f"Merged audio saved as {output_file}")
61 |
62 | # Function to upload file to GCS
63 | def upload_to_gcs(file_path, file_name):
64 | client = storage.Client()
65 | try:
66 | blob = client.bucket(BUCKET_NAME).blob(file_name)
67 | blob.upload_from_filename(file_path)
68 | print(f"File uploaded to GCS: {BUCKET_NAME}/{file_name}")
69 | except Exception as e:
70 | print(f"Error uploading to GCS: {e}")
71 | raise
72 |
73 | # Function to generate the podcast audio from the provided conversation
74 | def generate_audio(conversation, file_name_prefix):
75 | os.makedirs(FILE_DIR, exist_ok=True)
76 | for index, part in enumerate(conversation):
77 | speaker = part['speaker']
78 | text = part['text']
79 | synthesize_speech(text, speaker, index)
80 |
81 | audio_folder = FILE_DIR
82 | final_file_name = f"{file_name_prefix}_podcast.mp3"
83 | output_file_path = os.path.join(FILE_DIR, final_file_name)
84 | merge_audios(audio_folder, output_file_path)
85 |
86 | # Upload the final file to GCS
87 | try:
88 | upload_to_gcs(output_file_path, final_file_name)
89 | print(f"Final podcast uploaded successfully: {final_file_name}")
90 | except Exception as e:
91 | print(f"Error during final upload: {e}")
92 | raise
93 |
94 | # Flask handler to accept the script through 'variable'
95 | def hello_world(request):
96 | # Parse the JSON request body
97 | request_json = request.get_json(silent=True)
98 |
99 | # Extract the 'variable' parameter from the request body
100 | if request_json and 'variable' in request_json:
101 | try:
102 | # Parse the conversation script from the 'variable' field
103 | conversation = json.loads(request_json['variable'])
104 | except json.JSONDecodeError as e:
105 | return flask.make_response(f"Invalid input: 'variable' must be a valid JSON. Error: {e}", 400)
106 | else:
107 | return flask.make_response("Invalid input: Please provide a 'variable'.", 400)
108 |
109 | # Print the conversation to the console (Cloud Function logs)
110 | print(f"Received conversation script: {conversation}")
111 |
112 | # Create a unique file name based on the current timestamp
113 | timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
114 | file_name_prefix = f"podcast_{timestamp}"
115 |
116 | # Generate audio based on the provided conversation
117 | try:
118 | generate_audio(conversation, file_name_prefix)
119 | except Exception as e:
120 | return flask.make_response(f"Error during podcast generation: {e}", 500)
121 |
122 | response_message = f"Podcast generated and uploaded to GCS with prefix: {file_name_prefix}_podcast.mp3"
123 | return flask.make_response(response_message, 200)
124 |
--------------------------------------------------------------------------------
/GeminiDataExtract.js:
--------------------------------------------------------------------------------
1 | function processPdfToSheet() {
2 | var archiveFolderId = "YOUR_ARCHIVE_FOLDER_ID";
3 | const folderId1 = "YOUR_FOLDER_ID";
4 | var folder = DriveApp.getFolderById(folderId1);
5 | var files = folder.getFiles();
6 |
7 | while (files.hasNext()) {
8 | var file = files.next();
9 | if (file.getMimeType() === MimeType.PDF) { // Filter PDF files
10 | var fileId = file.getId();
11 | var pdfContent = convertPdfToGoogleDoc(fileId, folder);
12 | var responseData = sendToGemini(pdfContent);
13 | var details = extractFields(responseData);
14 |
15 | // Update Google Sheet with extracted details
16 | updateSheet(details);
17 |
18 | // Move the original PDF and the converted Google Doc to the archive folder
19 | var archiveFolder = DriveApp.getFolderById(archiveFolderId);
20 | moveFileToArchive(file, archiveFolder);
21 | }
22 | }
23 | }
24 |
25 |
26 | function convertPdfToGoogleDoc(fileId, folder) {
27 | var file = DriveApp.getFileById(fileId);
28 | var blob = file.getBlob();
29 | var newFileName = file.getName().replace(/\.pdf$/, '') + ' converted';
30 | var resource = {
31 | title: newFileName,
32 | mimeType: MimeType.GOOGLE_DOCS
33 | };
34 | var options = {
35 | ocr: true,
36 | ocrLanguage: 'en'
37 | };
38 | var convertedFile = Drive.Files.create(resource, blob, options);
39 | var doc = DocumentApp.openById(convertedFile.id);
40 | var pdfContent = doc.getBody().getText();
41 | var convertedFileObj = DriveApp.getFileById(convertedFile.id);
42 | convertedFileObj.setTrashed(true); // Move to trash
43 | return pdfContent;
44 | }
45 |
46 | function sendToGemini(pdfData) {
47 | const GEMINI_KEY = 'YOUR_API_KEY';
48 | const GEMINI_ENDPOINT = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=${GEMINI_KEY}`;
49 | var headers = {
50 | "Content-Type": "application/json",
51 | "Accept": "application/json"
52 | };
53 | var requestBody = {
54 | "contents": [
55 | {
56 | "parts": [
57 | {
58 | "text": `extract the following details: Vendor Name: Invoice Number: Amount Due: Due Date: Description Tax: \n${pdfData}`
59 | }
60 | ]
61 | }
62 | ]
63 | };
64 | var options = {
65 | "method": "POST",
66 | "headers": headers,
67 | "payload": JSON.stringify(requestBody)
68 | };
69 | try {
70 | var response = UrlFetchApp.fetch(GEMINI_ENDPOINT, options);
71 | var datanew = JSON.parse(response.getContentText());
72 | return datanew;
73 | } catch (error) {
74 | Logger.log('Error calling Gemini API: ' + error);
75 | return null;
76 | }
77 | }
78 |
79 | function extractFields(datanew) {
80 | if (!datanew || !datanew.candidates || !datanew.candidates.length) {
81 | Logger.log('No valid data returned from Gemini.');
82 | return {};
83 | }
84 |
85 | var textContent = datanew.candidates[0].content.parts[0].text;
86 | textContent = textContent.replace(/- /g, '').trim();
87 | var lines = textContent.split('\n');
88 |
89 | var details = {};
90 | lines.forEach(function (line) {
91 | var parts = line.split(':');
92 | if (parts.length === 2) {
93 | var key = parts[0].replace(/\*\*/g, '').trim();
94 | var value = parts[1].replace(/\*\*/g, '').trim();
95 | details[key] = value;
96 | }
97 | });
98 |
99 | return details;
100 | }
101 |
102 | function updateSheet(details) {
103 | var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Invoices");
104 | var range = sheet.getDataRange();
105 | var values = range.getValues();
106 |
107 | var vendorName = details['Vendor Name'];
108 | var nameFound = false;
109 |
110 | var currentDate = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'MM/dd/yy');
111 | var formattedDateTime = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm:ss");
112 |
113 | for (var i = 1; i < values.length; i++) {
114 | if (values[i][2].toLowerCase() === vendorName.toLowerCase()) { // Compare by Vendor Name
115 | nameFound = true;
116 | sheet.getRange(i + 1, 1).setValue(details['Invoice Number']); // Column A
117 | sheet.getRange(i + 1, 6).setValue(details['Amount Due']); // Column F
118 | sheet.getRange(i + 1, 7).setValue(details['Due Date']); // Column G
119 | sheet.getRange(i + 1, 9).setValue("Last updated at: " + formattedDateTime); // Column I
120 | Logger.log("Updated Row " + (i + 1));
121 | break;
122 | }
123 | }
124 |
125 | if (!nameFound) {
126 | Logger.log("Vendor not found: " + vendorName);
127 | var newRow = values.length + 1;
128 |
129 | sheet.getRange(newRow, 1).setValue(details['Invoice Number']); // Column A
130 | sheet.getRange(newRow, 3).setValue(vendorName); // Column C
131 | sheet.getRange(newRow, 4).setValue(details['Description']); // Column D
132 | sheet.getRange(newRow, 5).setValue(vendorName); // Column E
133 | sheet.getRange(newRow, 6).setValue(details['Amount Due']); // Column F
134 | sheet.getRange(newRow, 7).setValue(details['Due Date']); // Column G
135 | sheet.getRange(i + 1, 9).setValue("Last updated at: " + formattedDateTime); // Column I
136 | Logger.log("New Row Added");
137 | }
138 | }
139 |
140 | function moveFileToArchive(file, archiveFolder) {
141 | file.moveTo(archiveFolder);
142 | }
143 |
--------------------------------------------------------------------------------
/PDF.js:
--------------------------------------------------------------------------------
1 | function CreateBulkPDF(PDFContentBlob){
2 |
3 | // Getting all the Files to store the PDF's
4 | const docfile = DriveApp.getFileById("1UCwUYnp94yYwQp8ZK30ks3UtRX3id5cX5wz97E55CRQ");
5 | const TempFolder = DriveApp.getFolderById("1N0ayWXIEU1oHmhg02wx7FkBNliEturZV");
6 | const PDFFolder = DriveApp.getFolderById("1NJlToP7fsLIO4T9NpXC4FmJY4S-SMHMR");
7 |
8 | const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("marks");
9 | var data = ss.getRange(4,1, ss.getLastRow() -3,19).getValues();
10 | //Logger.log(data);
11 |
12 | // Getting the Name of the Subjects
13 | var sub1 = ss.getRange("E3").getValue(); // Subject 1
14 | //console.log(sub1);
15 |
16 | var sub2 = ss.getRange("G3").getValue(); // Subject 3
17 | //console.log(sub3);
18 |
19 | var sub3 = ss.getRange("I3").getValue(); // Subject 2
20 | //console.log(sub5);
21 |
22 | var sub4 = ss.getRange("K3").getValue(); // Subject 1
23 | //console.log(sub7);
24 |
25 | var sub5 = ss.getRange("M3").getValue(); // Subject 3
26 | //console.log(sub9);
27 |
28 | var sub6 = ss.getRange("O3").getValue(); // Subject 3
29 | //console.log(sub11);
30 | // Getting all the Details of the Students using ForEach
31 |
32 | data.forEach(function(row,i){
33 |
34 | var SapId = row[1]; // Sap Id of the student
35 | //console.log(sap);
36 |
37 | var rollnum = row[2]; // Roll number of the student.
38 | // console.log(roll);
39 |
40 | var name = row[3]; // Name of the student
41 | // console.log(name);
42 |
43 | var SOM1 = row[4];
44 | // console.log(SOM1); // Marks Strength of materials test1
45 |
46 | var SOM2 = row[5];
47 | // console.log(SOM2); // Marks of Strength of materials test2
48 |
49 | var Surv1 = row[6];
50 | // console.log(Surveying1); // Marks of Surveying Test1
51 |
52 | var Surv2 = row[7];
53 | // console.log(Surveying2) // Marks of Surveying Test2
54 |
55 | var Geo1 = row[8];
56 | //console.log(Eng_Geo1); // Marks of Engineering Geology Test1
57 |
58 | var Geo2 = row[9];
59 | // console.log(Eng_Geo2); // Marks of Engineering Geology Test2
60 |
61 | var Math1 = row[10];
62 | //console.log(Eng_Maths1); // Marks of Engineering Maths Test 1
63 |
64 | var Math2 = row[11];
65 | //console.log(Eng_Maths2); // Marks of Engineering Maths Test 2
66 |
67 | var Phy1 = row[12];
68 | // console.log(Eng_Phy1); // Marks of Engineering Physics Test 1
69 |
70 | var Phy2 = row[13];
71 | // console.log(Eng_Phy2); // Marks of Engineering Physics Test 2
72 |
73 | var Num1 = row[14];
74 | // console.log(Num_Tech1); // Marks of Numerical Techniques Test 1
75 |
76 | var Num2 = row[15];
77 | // console.log(NumTech2); // Marks of Numerical Techniques Test 2
78 | var email = row[18];
79 | // console.log(email); // Email of the Parent
80 |
81 | var pdfName = name+" " + rollnum;
82 |
83 |
84 | createPDF(name,rollnum,SapId,SOM1,SOM2,Surv1,Surv2,Geo1, Geo2,Math1,Math2,Phy1,Phy2,Num1,Num2,sub1,sub2,sub3,sub4,sub5,sub6,email,docfile,TempFolder,PDFFolder,pdfName);
85 |
86 | });
87 |
88 | }
89 |
90 |
91 |
92 |
93 | // Function that creates the PDF
94 | function createPDF(name,rollnum,SapId,SOM1,SOM2,Surv1,Surv2,Geo1, Geo2,Math1,Math2,Phy1,Phy2,Num1,Num2,sub1,sub2,sub3,sub4,sub5,sub6,email, docfile,TempFolder,PDFFolder,pdfName){
95 | // Getting all the Files like Docs, Temp Folder , Pdf Folder
96 |
97 | const tempFile = docfile.makeCopy(TempFolder);
98 | const TempDocFile = DocumentApp.openById(tempFile.getId());
99 | const body = TempDocFile.getBody();
100 |
101 | // Searching and replacing the text into the Doc
102 | TempDocFile.getBody().replaceText("{name}", name); // Name of the Student
103 | TempDocFile.getBody().replaceText("{roll}", rollnum); // Roll Number of the Student
104 | TempDocFile.getBody().replaceText("{sap}", SapId); // Sap ID of the Student
105 | TempDocFile.getBody().replaceText("{som1}", SOM1); // Strength of Materials M1
106 | TempDocFile.getBody().replaceText("{som2}", SOM2); // Strength of Materials M2
107 | TempDocFile.getBody().replaceText("{surv1}", Surv1); // Surveying M1
108 | TempDocFile.getBody().replaceText("{surv2}", Surv2); // Surveying M2
109 | TempDocFile.getBody().replaceText("{geo1}", Geo1); // Engineering Geology M1
110 | TempDocFile.getBody().replaceText("{geo2}", Geo2); // Engineering Geology M2
111 | TempDocFile.getBody().replaceText("{maths1}", Math1); // Engineering Mathematics M1
112 | TempDocFile.getBody().replaceText("{maths2}", Math2); // Engineering Mathematics M2
113 | TempDocFile.getBody().replaceText("{phy1}", Phy1); // Engineering Physics M1
114 | TempDocFile.getBody().replaceText("{phy2}", Phy2); // Engineering Physics M2
115 | TempDocFile.getBody().replaceText("{num1}", Num1); // Numerical Techniques M1
116 | TempDocFile.getBody().replaceText("{num2}", Num2); // Numerical Techniques M2
117 |
118 | TempDocFile.getBody().replaceText("{Som}", sub1); // Strength of Materials
119 | TempDocFile.getBody().replaceText("{Surv}", sub2 ); // Surveying
120 | TempDocFile.getBody().replaceText("{geo}", sub3); // Engineering Geology
121 | TempDocFile.getBody().replaceText("{maths}", sub4); // Engineering Mathematics
122 | TempDocFile.getBody().replaceText("{phy}", sub5); // Engineering Physics
123 | TempDocFile.getBody().replaceText("{num}", sub6); // Numerical Techniques
124 |
125 | var pdfName = name+" " + rollnum;
126 |
127 | // Saving all the changes made in the doc
128 | TempDocFile.saveAndClose();
129 | const PDFContentBlob = tempFile.getAs(MimeType.PDF);
130 | const PDF_File = PDFFolder.createFile(PDFContentBlob).setName(pdfName);
131 | TempFolder.removeFile(tempFile);
132 |
133 | MailApp.sendEmail(email,name + " " + rollnum,"These are your marks for M1 and M2",{
134 |
135 | attachments: [PDF_File.getAs(MimeType.PDF)]
136 |
137 | });
138 |
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/Fetch&SummariseDocComments.js:
--------------------------------------------------------------------------------
1 | const GEMINI_API_KEY = "your_api_key";
2 |
3 | function onOpen() {
4 | const ui = DocumentApp.getUi();
5 | ui.createMenu('AI Comment Tools')
6 | .addItem('Summarize All Comments (Gemini)', 'summarizeDocComments')
7 | .addToUi();
8 | }
9 |
10 | /**
11 | * Fetch comments and their context from the Google Doc
12 | */
13 | function listComments() {
14 | const documentId = DocumentApp.getActiveDocument().getId();
15 | const documentBodyText = DocumentApp.getActiveDocument().getBody().getText();
16 | const options = {
17 | fields: 'comments(id, content, createdTime, author(displayName), resolved, replies(id, content, createdTime, author(displayName)), anchor)'
18 | };
19 |
20 | let allCommentsAndContext = '';
21 | let commentCount = 0;
22 |
23 | try {
24 | const response = Drive.Comments.list(documentId, options);
25 | const comments = response.comments;
26 |
27 | if (!comments || comments.length === 0) {
28 | return { commentsString: '', count: 0 };
29 | }
30 |
31 | commentCount = comments.length;
32 | comments.forEach(comment => {
33 | const author = comment.author ? comment.author.displayName : 'Unknown Author';
34 | const commentContent = comment.content || '[No Content]';
35 | let contextualText = '';
36 |
37 | if (comment.anchor && comment.anchor.range) {
38 | const range = comment.anchor.range;
39 | const startIndex = range.startIndex || 0;
40 | const endIndex = range.endIndex || documentBodyText.length;
41 | contextualText = documentBodyText.substring(startIndex, endIndex).trim();
42 | }
43 |
44 | allCommentsAndContext += `--- Context for Comment by ${author} ---\n`;
45 | allCommentsAndContext += `${contextualText || '[No context found]'}\n`;
46 | allCommentsAndContext += `--- Comment: ---\n${commentContent}\n`;
47 |
48 | if (comment.replies && comment.replies.length > 0) {
49 | comment.replies.forEach(reply => {
50 | const replyAuthor = reply.author ? reply.author.displayName : 'Unknown Author';
51 | const replyContent = reply.content || '[No Content]';
52 | allCommentsAndContext += ` ↳ Reply from ${replyAuthor}: ${replyContent}\n`;
53 | });
54 | }
55 | allCommentsAndContext += `------------------------\n\n`;
56 | });
57 | } catch (e) {
58 | Logger.log(`Error fetching comments: ${e.message}`);
59 | return { commentsString: '', count: 0 };
60 | }
61 |
62 | return { commentsString: allCommentsAndContext, count: commentCount };
63 | }
64 |
65 | /**
66 | * Generate a summary using Gemini API
67 | */
68 | function generateSummary(commentsAndContext) {
69 | const endpoint = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
70 | const promptText = `Summarize the following Google Docs comments (with context). Identify key feedback, action items, and recurring themes. Format as clear bullet points. Be concise and omit quotation marks.\n\n${commentsAndContext}`;
71 |
72 | const headers = { "Content-Type": "application/json" };
73 | const payload = JSON.stringify({
74 | contents: [{ parts: [{ text: promptText }] }]
75 | });
76 |
77 | const response = UrlFetchApp.fetch(endpoint, {
78 | method: "POST",
79 | headers: headers,
80 | payload: payload,
81 | muteHttpExceptions: true
82 | });
83 |
84 | const json = JSON.parse(response.getContentText());
85 | if (json.candidates && json.candidates.length > 0) {
86 | return json.candidates[0].content.parts[0].text.trim();
87 | } else if (json.error) {
88 | throw new Error(json.error.message);
89 | } else {
90 | throw new Error("Unexpected API response format.");
91 | }
92 | }
93 |
94 | /**
95 | * Insert a styled summary at the top of the Google Doc
96 | */
97 | function insertStyledSummary(summary) {
98 | const doc = DocumentApp.getActiveDocument();
99 | const body = doc.getBody();
100 |
101 | // Insert header
102 | const header = body.insertParagraph(0, "🧠 AI Comment Summary (Powered by Gemini AI)");
103 | header.setHeading(DocumentApp.ParagraphHeading.HEADING2);
104 |
105 | // Insert timestamp
106 | const timestamp = new Date().toLocaleString();
107 | const timestampPara = body.insertParagraph(1, `Generated on: ${timestamp}`);
108 | timestampPara.setItalic(true);
109 |
110 | // Insert summary content
111 | const summaryPara = body.insertParagraph(2, summary);
112 | summaryPara.setSpacingAfter(12);
113 | }
114 |
115 | /**
116 | * Main function that runs the summarization
117 | */
118 | function summarizeDocComments() {
119 | const ui = DocumentApp.getUi();
120 |
121 | if (!GEMINI_API_KEY || GEMINI_API_KEY === "YOUR_GEMINI_API_KEY") {
122 | ui.alert("API Key Missing", "Please add your Gemini API key at the top of the script.", ui.ButtonSet.OK);
123 | return;
124 | }
125 |
126 | ui.alert("Fetching all comments from your document...");
127 | const commentsData = listComments();
128 |
129 | if (!commentsData.count) {
130 | ui.alert("No Comments Found", "This document has no comments to summarize.", ui.ButtonSet.OK);
131 | return;
132 | }
133 |
134 | const confirmMessage = `Found ${commentsData.count} comments. Do you want to summarize them using Gemini AI?`;
135 | const userResponse = ui.alert("Confirm Summarization", confirmMessage, ui.ButtonSet.YES_NO);
136 | if (userResponse !== ui.Button.YES) {
137 | ui.alert("Action Cancelled", "Comment summarization was cancelled.", ui.ButtonSet.OK);
138 | return;
139 | }
140 |
141 | ui.alert("Processing...", "Sending comments to Gemini AI for summarization.", ui.ButtonSet.OK);
142 |
143 | let summary;
144 | try {
145 | summary = generateSummary(commentsData.commentsString);
146 | } catch (e) {
147 | ui.alert("Gemini API Error", `An error occurred: ${e.message}`, ui.ButtonSet.OK);
148 | return;
149 | }
150 |
151 | insertStyledSummary(summary);
152 | ui.alert("✅ Summary Inserted", "Your AI summary has been added to the top of the document.", ui.ButtonSet.OK);
153 | }
154 |
--------------------------------------------------------------------------------
/LabelConfig.js:
--------------------------------------------------------------------------------
1 | function analyzeAndApplyDynamicLabel66556() {
2 | const fileID = "1hK8E-7z-XgpvtWJ7MTxz7d4giGZULjAjG6VssDMPHrs";
3 | const driveFileID = '1hK8E-7z-XgpvtWJ7MTxz7d4giGZULjAjG6VssDMPHrs';
4 | const apiKey = "AIzaSyDHWFWH9IVgnUGftBown8OBJiRwL-rLOx8"; // Replace with your actual API key
5 |
6 | try {
7 | // Step 1: Fetch labels dynamically
8 | const labelsResponse = DriveLabels.Labels.list({ view: "LABEL_VIEW_FULL" });
9 | const labels = labelsResponse.labels;
10 | if (!labels || labels.length === 0) {
11 | Logger.log("No labels found.");
12 | return;
13 | }
14 |
15 | const labelMap = {};
16 | labels.forEach(label => {
17 | if (label.properties?.title) {
18 | labelMap[label.properties.title] = {
19 | id: label.id,
20 | fields: label.fields
21 | };
22 | }
23 | });
24 | Logger.log(`Available Labels: ${JSON.stringify(labelMap)}`);
25 |
26 | // Step 2: Get document content
27 | const doc = DocumentApp.openById(fileID);
28 | const documentContent = doc.getBody().getText();
29 | Logger.log(`Document Content: ${documentContent}`);
30 |
31 | // Step 3: Gemini API call for label suggestion
32 | const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=${apiKey}`;
33 | const labelSuggestionPrompt = `Analyze the document and suggest an appropriate label. Just return the label. Available labels are: ${Object.keys(labelMap).join(", ")}.\nDocument:\n${documentContent}`;
34 |
35 | const labelResponse = makeGeminiApiRequest(apiUrl, labelSuggestionPrompt);
36 | if (!labelResponse) return;
37 |
38 | const suggestedLabel = labelResponse.candidates[0].content.parts[0].text.trim();
39 | Logger.log(`Suggested Label: ${suggestedLabel}`);
40 |
41 | // Step 4: Apply the label and populate fields
42 | if (labelMap[suggestedLabel]) {
43 | const labelData = labelMap[suggestedLabel];
44 | const labelId = labelData.id;
45 |
46 | const addLabelRequest = Drive.newModifyLabelsRequest()
47 | .setLabelModifications([Drive.newLabelModification().setLabelId(labelId)]);
48 | const addLabelResponse = Drive.Files.modifyLabels(addLabelRequest, driveFileID);
49 | Logger.log(`Labels applied: ${JSON.stringify(addLabelResponse.modifiedLabels)}`);
50 |
51 | if (labelData.fields && labelData.fields.length > 0) {
52 | const fieldPrompt = generateFieldPrompt(labelData.fields, documentContent);
53 | const fieldResponse = makeGeminiApiRequest(apiUrl, fieldPrompt);
54 |
55 | if (fieldResponse) {
56 | const fieldValues = parseFieldData(fieldResponse.candidates[0].content.parts[0].text.trim());
57 | applyLabelAndPopulateFields(driveFileID, labelId, labelData.fields, fieldValues);
58 | } else {
59 | Logger.log('Failed to fetch field data for label.');
60 | }
61 | }
62 | } else {
63 | Logger.log(`Suggested label "${suggestedLabel}" not found among available labels.`);
64 | }
65 | } catch (error) {
66 | Logger.log(`Failed to analyze and apply label: ${error.message}`);
67 | }
68 | }
69 |
70 | function makeGeminiApiRequest(apiUrl, prompt) {
71 | const requestBody = { contents: [{ parts: [{ text: prompt }] }] };
72 | const options = {
73 | method: 'post',
74 | contentType: 'application/json',
75 | payload: JSON.stringify(requestBody),
76 | muteHttpExceptions: true
77 | };
78 |
79 | const response = UrlFetchApp.fetch(apiUrl, options);
80 | const responseCode = response.getResponseCode();
81 | const responseText = response.getContentText();
82 |
83 | Logger.log(`Gemini API Response Code: ${responseCode}`);
84 | Logger.log(`Gemini API Response Text: ${responseText}`);
85 |
86 | if (responseCode !== 200) {
87 | Logger.log(`Error calling Gemini API: ${responseText}`);
88 | return null;
89 | }
90 |
91 | try {
92 | return JSON.parse(responseText);
93 | } catch (e) {
94 | Logger.log(`Error parsing Gemini API response: ${e.message}`);
95 | return null;
96 | }
97 | }
98 |
99 | function generateFieldPrompt(fields, documentContent) {
100 | const fieldNames = fields.map(field => field.properties.displayName).join(", ");
101 | return `Analyze the document and extract the following details: ${fieldNames}. Document Content:\n${documentContent}`;
102 | }
103 |
104 | function parseFieldData(fieldData) {
105 | const fieldValues = {};
106 | const lines = fieldData.split('\n');
107 |
108 | lines.forEach(line => {
109 | const [key, value] = line.split(':').map(part => part.trim());
110 | if (key && value) {
111 | fieldValues[key] = value;
112 | }
113 | });
114 |
115 | Logger.log(`Parsed field values: ${JSON.stringify(fieldValues)}`);
116 | return fieldValues;
117 | }
118 |
119 | function applyLabelAndPopulateFields(fileId, labelId, fields, fieldValues) {
120 | try {
121 | // Step 1: Apply the label
122 | const labelModification = Drive.newLabelModification().setLabelId(labelId);
123 | const applyLabelRequest = Drive.newModifyLabelsRequest().setLabelModifications([labelModification]);
124 |
125 | const applyLabelResponse = Drive.Files.modifyLabels(applyLabelRequest, fileId);
126 | Logger.log(`Label applied successfully: ${JSON.stringify(applyLabelResponse.modifiedLabels)}`);
127 |
128 | // Step 2: Populate label fields
129 | const labelModifications = fields.map(field => {
130 | const fieldValue = fieldValues[field.properties.displayName];
131 |
132 | if (field.selectionOptions) {
133 | const choice = field.selectionOptions.choices.find(choice =>
134 | choice.properties.displayName.toLowerCase() === fieldValue.toLowerCase()
135 | );
136 | if (choice) {
137 | return Drive.newFieldModification()
138 | .setFieldId(field.id)
139 | .setChoiceId(choice.id);
140 | }
141 | } else if (fieldValue) {
142 | return Drive.newFieldModification()
143 | .setFieldId(field.id)
144 | .setText(fieldValue);
145 | }
146 |
147 | Logger.log(`No valid value for field: ${field.properties.displayName}`);
148 | return null;
149 | }).filter(mod => mod !== null);
150 |
151 | if (labelModifications.length === 0) {
152 | Logger.log('No valid modifications for fields.');
153 | return;
154 | }
155 |
156 | // Send modifications in a single request
157 | const populateFieldsRequest = Drive.newModifyLabelsRequest()
158 | .setLabelModifications([
159 | Drive.newLabelModification()
160 | .setLabelId(labelId)
161 | .setFieldModifications(labelModifications)
162 | ]);
163 |
164 | const populateFieldsResponse = Drive.Files.modifyLabels(populateFieldsRequest, fileId);
165 | Logger.log(`Fields populated successfully: ${JSON.stringify(populateFieldsResponse.modifiedLabels)}`);
166 |
167 | } catch (error) {
168 | Logger.log(`Error while applying label and populating fields: ${error.message}`);
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/DriveLabelAutomation.js:
--------------------------------------------------------------------------------
1 | function analyzeAndApplyDynamicLabel66556() {
2 | const fileID = "your_file_id";
3 | const driveFileID = 'your_file_id';
4 | const apiKey = "your_api_key"; // Replace with your actual API key
5 | try {
6 | // Step 1: Fetch labels dynamically
7 | const labelsResponse = DriveLabels.Labels.list({ view: "LABEL_VIEW_FULL" });
8 | const labels = labelsResponse.labels;
9 | if (!labels || labels.length === 0) {
10 | Logger.log("No labels found.");
11 | return;
12 | }
13 | const labelMap = {};
14 | labels.forEach(label => {
15 | if (label.properties?.title) {
16 | labelMap[label.properties.title] = {
17 | id: label.id,
18 | fields: label.fields
19 | };
20 | }
21 | });
22 | Logger.log(`Available Labels: ${JSON.stringify(labelMap)}`);
23 | // Step 2: Get document content
24 | const doc = DocumentApp.openById(fileID);
25 | const documentContent = doc.getBody().getText();
26 | Logger.log(`Document Content: ${documentContent}`);
27 | // Step 3: Gemini API call for label suggestion
28 | const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${apiKey}`;
29 | const labelSuggestionPrompt = `Analyze the document and suggest an appropriate label. Just return the label. Available labels are: ${Object.keys(labelMap).join(", ")}.\nDocument:\n${documentContent}`;
30 | const labelResponse = makeGeminiApiRequest(apiUrl, labelSuggestionPrompt);
31 | if (!labelResponse) return;
32 | const suggestedLabel = labelResponse.candidates[0].content.parts[0].text.trim();
33 | Logger.log(`Suggested Label: ${suggestedLabel}`);
34 | // Step 4: Apply the label and populate fields
35 | if (labelMap[suggestedLabel]) {
36 | const labelData = labelMap[suggestedLabel];
37 | const labelId = labelData.id;
38 | if (labelData.fields && labelData.fields.length > 0) {
39 | const fieldPrompt = generateFieldPrompt(labelData.fields, documentContent);
40 | const fieldResponse = makeGeminiApiRequest(apiUrl, fieldPrompt);
41 | if (fieldResponse) {
42 | const fieldValues = parseFieldData(fieldResponse.candidates[0].content.parts[0].text.trim());
43 | applyLabelAndPopulateFields(driveFileID, labelId, labelData.fields, fieldValues);
44 | } else {
45 | Logger.log('Failed to fetch field data for label.');
46 | }
47 | } else {
48 | // Apply label without fields
49 | const addLabelRequest = Drive.newModifyLabelsRequest()
50 | .setLabelModifications([Drive.newLabelModification().setLabelId(labelId)]);
51 | const addLabelResponse = Drive.Files.modifyLabels(addLabelRequest, driveFileID);
52 | Logger.log(`Labels applied: ${JSON.stringify(addLabelResponse.modifiedLabels)}`);
53 | }
54 | } else {
55 | Logger.log(`Suggested label "${suggestedLabel}" not found among available labels.`);
56 | }
57 | } catch (error) {
58 | Logger.log(`Failed to analyze and apply label: ${error.message}`);
59 | }
60 | }
61 |
62 | function makeGeminiApiRequest(apiUrl, prompt) {
63 | const requestBody = { contents: [{ parts: [{ text: prompt }] }] };
64 | const options = {
65 | method: 'post',
66 | contentType: 'application/json',
67 | payload: JSON.stringify(requestBody),
68 | muteHttpExceptions: true
69 | };
70 | const response = UrlFetchApp.fetch(apiUrl, options);
71 | const responseCode = response.getResponseCode();
72 | const responseText = response.getContentText();
73 | Logger.log(`Gemini API Response Code: ${responseCode}`);
74 | Logger.log(`Gemini API Response Text: ${responseText}`);
75 | if (responseCode !== 200) {
76 | Logger.log(`Error calling Gemini API: ${responseText}`);
77 | return null;
78 | }
79 | try {
80 | return JSON.parse(responseText);
81 | } catch (e) {
82 | Logger.log(`Error parsing Gemini API response: ${e.message}`);
83 | return null;
84 | }
85 | }
86 |
87 | function generateFieldPrompt(fields, documentContent) {
88 | const fieldNames = fields.map(field => field.properties.displayName).join(", ");
89 | return `Analyze the document and return ONLY a JSON object with the following keys: ${fieldNames}.
90 | No markdown. No additional text. Just valid JSON.
91 | Document Content:
92 | ${documentContent}`;
93 | }
94 |
95 | function parseFieldData(fieldData) {
96 | try {
97 | // Strip common markdown code blocks (e.g., ```json ... ```)
98 | let cleanData = fieldData
99 | .replace(/```json\s*/g, '') // Remove ```json
100 | .replace(/```\s*/g, '') // Remove ```
101 | .replace(/^\s*[\n\r]+|[\n\r]+\s*$/g, '') // Trim leading/trailing newlines
102 | .trim();
103 |
104 | // Fallback: If still invalid, try to extract JSON substring (between { and })
105 | if (!cleanData.startsWith('{') || !cleanData.endsWith('}')) {
106 | const jsonMatch = cleanData.match(/\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/);
107 | if (jsonMatch) {
108 | cleanData = jsonMatch[0];
109 | } else {
110 | throw new Error('No valid JSON object found');
111 | }
112 | }
113 |
114 | const fieldValues = JSON.parse(cleanData);
115 | Logger.log(`Parsed field values: ${JSON.stringify(fieldValues)}`);
116 | return fieldValues;
117 | } catch (e) {
118 | Logger.log(`Error parsing JSON field data: ${e.message}. Raw data: ${fieldData}`);
119 | return {};
120 | }
121 | }
122 |
123 | function applyLabelAndPopulateFields(fileId, labelId, fields, fieldValues) {
124 | try {
125 | // Build field modifications as plain objects based on type
126 | const fieldModifications = fields.map(field => {
127 | const displayName = field.properties.displayName;
128 | const fieldValue = fieldValues[displayName];
129 | if (!fieldValue) {
130 | Logger.log(`No value for field: ${displayName}`);
131 | return null;
132 | }
133 |
134 | let fieldMod = {
135 | kind: "drive#labelFieldModification",
136 | fieldId: field.id
137 | };
138 |
139 | if (field.selectionOptions) {
140 | const choice = field.selectionOptions.choices.find(choice =>
141 | choice.properties.displayName.toLowerCase() === fieldValue.toLowerCase()
142 | );
143 | if (choice) {
144 | fieldMod.setSelectionValues = [choice.id];
145 | } else {
146 | Logger.log(`No matching choice for ${displayName}: ${fieldValue}`);
147 | return null;
148 | }
149 | } else if (field.integerOptions) {
150 | const intValue = parseInt(fieldValue);
151 | if (!isNaN(intValue)) {
152 | fieldMod.setIntegerValues = [intValue.toString()];
153 | } else {
154 | Logger.log(`Invalid integer for ${displayName}: ${fieldValue}`);
155 | return null;
156 | }
157 | } else if (field.dateOptions) {
158 | // Parse to ISO "2025-11-28"
159 | const date = new Date(fieldValue);
160 | if (!isNaN(date.getTime())) {
161 | const isoDate = date.toISOString().split('T')[0];
162 | fieldMod.setDateValues = [isoDate];
163 | } else {
164 | Logger.log(`Invalid date for ${displayName}: ${fieldValue}`);
165 | return null;
166 | }
167 | } else if (field.textOptions) {
168 | fieldMod.setTextValues = [fieldValue];
169 | } else {
170 | Logger.log(`Unknown field type for ${displayName}`);
171 | return null;
172 | }
173 |
174 | return fieldMod;
175 | }).filter(mod => mod !== null);
176 |
177 | if (fieldModifications.length === 0) {
178 | Logger.log('No valid modifications for fields.');
179 | return;
180 | }
181 |
182 | // Build request as plain object (applies label + fields atomically)
183 | const request = {
184 | kind: "drive#modifyLabelsRequest",
185 | labelModifications: [
186 | {
187 | kind: "drive#labelModification",
188 | labelId: labelId,
189 | fieldModifications: fieldModifications,
190 | removeLabel: false // Ensure label is kept/applied
191 | }
192 | ]
193 | };
194 | Logger.log(`Request body: ${JSON.stringify(request)}`);
195 |
196 | const response = Drive.Files.modifyLabels(request, fileId);
197 | Logger.log(`Label and fields applied: ${JSON.stringify(response.modifiedLabels)}`);
198 | } catch (error) {
199 | Logger.log(`Error while applying label and populating fields: ${error.message}`);
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/DriveLabelsAutomation.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Tutorial: Complete Google Drive Labels Automation in Apps Script
3 | *
4 | * Copy-paste this entire code into a new Google Apps Script project (script.google.com).
5 | * Prerequisites:
6 | * 1. Enable Drive API v3 and Drive Labels API v2 (Editor > Services > + > Search/Add each).
7 | * 2. Re-authorize permissions (Run > Review permissions).
8 | * 3. Replace fileId in fullLabelAutomation() with your actual file ID.
9 | * 4. Ensure "Invoice" label exists and is published in Google Workspace Admin > Drive > Labels.
10 | *
11 | *
12 | * This script:
13 | * - Fetches available labels.
14 | * - Mocks suggestion as "Invoice" (replace with Gemini for dynamic).
15 | * - Fetches fields for the label.
16 | * - Applies label + populates fields with mock values (from your invoice example).
17 | * - Logs everything; check file in Drive > Details > Labels for results.
18 | */
19 |
20 | // 1. Fetch Currently Available Labels and Their IDs
21 | function fetchAvailableLabels() {
22 | try {
23 | const response = DriveLabels.Labels.list({ view: "LABEL_VIEW_FULL" });
24 | const labels = response.labels || [];
25 | if (labels.length === 0) {
26 | Logger.log("No labels found. Check Workspace admin for published labels.");
27 | return {};
28 | }
29 |
30 | const labelMap = {};
31 | labels.forEach(label => {
32 | if (label.properties?.title) {
33 | labelMap[label.properties.title] = label.id;
34 | }
35 | });
36 |
37 | Logger.log(`Fetched ${labels.length} labels: ${JSON.stringify(labelMap)}`);
38 | return labelMap;
39 | } catch (error) {
40 | Logger.log(`Error fetching labels: ${error.message}`);
41 | return {};
42 | }
43 | }
44 |
45 | // 2. Fetch Label Fields and Their IDs (list-based to avoid 404)
46 | function fetchLabelFields(labelId) {
47 | try {
48 | if (!labelId) {
49 | throw new Error("labelId is required. Run fetchAvailableLabels() first and copy an ID.");
50 | }
51 |
52 | const response = DriveLabels.Labels.list({ view: "LABEL_VIEW_FULL" });
53 | const labels = response.labels || [];
54 | if (labels.length === 0) {
55 | Logger.log("No labels found. Check Workspace admin for published labels.");
56 | return {};
57 | }
58 |
59 | const targetLabel = labels.find(label => label.id === labelId);
60 | if (!targetLabel) {
61 | Logger.log(`Label ID "${labelId}" not found in available labels. Run fetchAvailableLabels() to verify.`);
62 | return {};
63 | }
64 |
65 | const fields = targetLabel.fields || [];
66 | if (fields.length === 0) {
67 | Logger.log(`No fields found for label ${labelId}.`);
68 | return {};
69 | }
70 |
71 | const fieldMap = {};
72 | fields.forEach(field => {
73 | const displayName = field.properties?.displayName;
74 | if (displayName) {
75 | let type = 'text'; // Default
76 | if (field.integerOptions) type = 'integer';
77 | else if (field.dateOptions) type = 'date';
78 | else if (field.selectionOptions) type = 'selection';
79 |
80 | fieldMap[displayName] = {
81 | id: field.id,
82 | type: type
83 | };
84 | }
85 | });
86 |
87 | Logger.log(`Fetched ${fields.length} fields for label ${labelId}: ${JSON.stringify(fieldMap)}`);
88 | return fieldMap;
89 | } catch (error) {
90 | Logger.log(`Error fetching fields for label ${labelId}: ${error.message}`);
91 | return {};
92 | }
93 | }
94 |
95 | // 3. Apply Label to File
96 | function applyLabelToFile(fileId, labelId) {
97 | try {
98 | if (!fileId || !labelId) {
99 | throw new Error("fileId and labelId are required.");
100 | }
101 |
102 | const request = {
103 | kind: "drive#modifyLabelsRequest",
104 | labelModifications: [
105 | {
106 | kind: "drive#labelModification",
107 | labelId: labelId,
108 | removeLabel: false
109 | }
110 | ]
111 | };
112 |
113 | const response = Drive.Files.modifyLabels(request, fileId);
114 | Logger.log(`Label ${labelId} applied to file ${fileId}: ${JSON.stringify(response.modifiedLabels)}`);
115 | return response.modifiedLabels || [];
116 | } catch (error) {
117 | Logger.log(`Error applying label ${labelId} to file ${fileId}: ${error.message}`);
118 | return [];
119 | }
120 | }
121 |
122 | // 4. Apply Label and Update Fields
123 | function applyLabelAndUpdateFields(fileId, labelId, fields) {
124 | try {
125 | if (!fileId || !labelId || !fields || fields.length === 0) {
126 | throw new Error("fileId, labelId, and non-empty fields array are required.");
127 | }
128 |
129 | const fieldModifications = fields.map(field => {
130 | let fieldMod = {
131 | kind: "drive#labelFieldModification",
132 | fieldId: field.id
133 | };
134 |
135 | const value = field.value;
136 | if (!value) {
137 | Logger.log(`Skipping field ${field.id}: No value provided.`);
138 | return null;
139 | }
140 |
141 | switch (field.type) {
142 | case 'selection':
143 | fieldMod.setSelectionValues = [value];
144 | break;
145 | case 'integer':
146 | const intVal = parseInt(value);
147 | if (!isNaN(intVal)) {
148 | fieldMod.setIntegerValues = [intVal.toString()];
149 | } else {
150 | Logger.log(`Invalid integer for field ${field.id}: ${value}`);
151 | return null;
152 | }
153 | break;
154 | case 'date':
155 | const date = new Date(value);
156 | if (!isNaN(date.getTime())) {
157 | const isoDate = date.toISOString().split('T')[0];
158 | fieldMod.setDateValues = [isoDate];
159 | } else {
160 | Logger.log(`Invalid date for field ${field.id}: ${value}`);
161 | return null;
162 | }
163 | break;
164 | case 'text':
165 | default:
166 | fieldMod.setTextValues = [value];
167 | break;
168 | }
169 |
170 | return fieldMod;
171 | }).filter(mod => mod !== null);
172 |
173 | if (fieldModifications.length === 0) {
174 | Logger.log('No valid field modifications; applying label only.');
175 | return applyLabelToFile(fileId, labelId);
176 | }
177 |
178 | const request = {
179 | kind: "drive#modifyLabelsRequest",
180 | labelModifications: [
181 | {
182 | kind: "drive#labelModification",
183 | labelId: labelId,
184 | fieldModifications: fieldModifications,
185 | removeLabel: false
186 | }
187 | ]
188 | };
189 |
190 | const response = Drive.Files.modifyLabels(request, fileId);
191 | Logger.log(`Label ${labelId} and fields applied to file ${fileId}: ${JSON.stringify(response.modifiedLabels)}`);
192 | return response.modifiedLabels || [];
193 | } catch (error) {
194 | Logger.log(`Error applying label and fields to file ${fileId}: ${error.message}`);
195 | return [];
196 | }
197 | }
198 |
199 | // Full Label Automation: Chains all steps (mock suggestion/values for demo)
200 | function fullLabelAutomation(fileId) {
201 | try {
202 | Logger.log(`Starting automation for file: ${fileId}`);
203 |
204 | // Step 1: Fetch labels
205 | const labelMap = fetchAvailableLabels();
206 | if (Object.keys(labelMap).length === 0) {
207 | Logger.log("No labels available. Exiting.");
208 | return;
209 | }
210 |
211 | // Step 2: Mock suggestion (replace with Gemini for dynamic AI)
212 | const suggestedLabel = "Invoice"; // Hardcoded for demo; integrate Gemini here
213 | const labelId = labelMap[suggestedLabel];
214 | if (!labelId) {
215 | Logger.log(`Suggested label "${suggestedLabel}" not found. Available: ${Object.keys(labelMap).join(", ")}. Exiting.`);
216 | return;
217 | }
218 | Logger.log(`Suggested and found label: ${suggestedLabel} (ID: ${labelId})`);
219 |
220 | // Step 3: Fetch fields
221 | const fieldMap = fetchLabelFields(labelId);
222 | if (Object.keys(fieldMap).length === 0) {
223 | Logger.log("No fields for label. Applying label only.");
224 | applyLabelToFile(fileId, labelId);
225 | return;
226 | }
227 |
228 | // Step 4: Build fields array with mock values (from your invoice doc; extract dynamically in prod)
229 | const fields = Object.keys(fieldMap).map(key => ({
230 | id: fieldMap[key].id,
231 | type: fieldMap[key].type,
232 | value: key === "Invoice Number" ? "100556" :
233 | key === "Invoice Date" ? "November 28, 2025" :
234 | key === "Vendor Name" ? "Spark Electrical Services" : "Default Value"
235 | }));
236 |
237 | // Apply label + fields
238 | applyLabelAndUpdateFields(fileId, labelId, fields);
239 | Logger.log("Automation complete! Check file labels in Drive.");
240 | } catch (error) {
241 | Logger.log(`Automation failed: ${error.message}`);
242 | }
243 | }
244 |
245 | function runDemo() {
246 | // Replace this with your actual File ID
247 | const myFileId = "your_file_id";
248 |
249 | fullLabelAutomation(myFileId);
250 | }
251 |
--------------------------------------------------------------------------------