Make a copy of google sheet into google drive folder - javascript

I have two Spreadsheets. The first spreadsheet contains my raw data that indicates the employee # and name of employees. The second spreadsheet is the spreadsheet I want to copy into a google drive folder. I want to update the specific fields on the 2nd spreadsheet based on the employee number and employee name from the 1st spreadsheet. Everytime it updates the cells in the second spreadsheet, it will create copy of the 2nd spreadsheet into google drive folder.
However, it keeps on setting just one value inside the replicated spreadsheets. It doesn't loop the employee names and employee numbers from the 1st spreadsheet.
My code is already replicating the 2nd spreadsheet. It's just the values aren't updating.
function replicateCards() {
var ss = SpreadsheetApp.openById('xxxxxxxx');
var copyCard = SpreadsheetApp.openById('zzzzzzzzz');
var getID = DriveApp.getFileById(copyCard.getId())
var card = copyCard.getSheetByName("Card");
var mastersheet = ss.getSheetByName("Mastersheet");
var getLastRow = mastersheet.getLastRow();
var destinationFolder = DriveApp.getFolderById('yyyyyyyyyy');
;
var changeColorToGrayList = card.getRangeList(['C7', 'E7', 'G7', 'I7', 'K7', 'M7', 'O7', 'Q7',
'C9', 'E9', 'G9', 'I9', 'K9', 'M9', 'O9', 'Q9',
'C11', 'E11', 'G11', 'I11', 'K11', 'M11', 'O11', 'Q11']);
var setValueToZero = card.getRangeList(['C8', 'E8', 'G8', 'I8', 'K8', 'M8', 'O8', 'Q8',
'C10', 'E10', 'G10', 'I10', 'K10', 'M10', 'O10', 'Q10',
'C12', 'E12', 'G12', 'I12', 'K12', 'M12', 'O12', 'Q12']);
for (i = 1; i < getLastRow; i++) {
var employeeNumber = mastersheet.getRange(i + 1, 1).getValue();
var employeeName = mastersheet.getRange(i + 1, 2).getValue();
card.getRange("C3").setValue(employeeName);
card.getRange("H3").setValue(employeeNumber);
card.setActiveRangeList(changeColorToGrayList).setBackground("gray");
card.setActiveRangeList(setValueToZero).setValue(0);
// var getID = DriveApp.getFileById(card).getId();
getID.makeCopy(employeeNumber + " High Flyer Card", destinationFolder);
}
}
I expect the output of getID.makeCopy(employeeNumber + " High Flyer Card", destinationFolder); contains different employee # and employee names, not just one value inside the google folder.

Your code should work as intended, unless a bulky file makes the code overlap.
If so, implementation of flush() will make your code run sequentially, see here for a detailed explanation.
In your case, modifying the for loop to
for (i = 1; i < getLastRow; i++) {
var employeeNumber = mastersheet.getRange(i + 1, 1).getValue();
var employeeName = mastersheet.getRange(i + 1, 2).getValue();
card.getRange("C3").setValue(employeeName);
card.getRange("H3").setValue(employeeNumber);
card.setActiveRangeList(changeColorToGrayList).setBackground("gray");
card.setActiveRangeList(setValueToZero).setValue(0);
getID.makeCopy(employeeNumber + " High Flyer Card", destinationFolder);
SpreadsheetApp.flush();
}
should solve the issue.

Related

App Script new Google Sheet creation issue

I am trying to write an App Script that takes string data from multiple different spreadsheets (completely separate documents) and puts them all in a new spreadsheet. When I run the logger, it shows me all the data I want. I want each piece of data to show up in Column A, but when I run my script, it only puts 1 data point in the spreadsheet instead of all of them. Can someone give me some guidance? Here is my code:
function pullTogether() {
var files = DriveApp.getFolderById('Folder ID').searchFiles('title != "nothing"');
const rangeName = 'Sheet1!B2:C';
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getId();
const values = Sheets.Spreadsheets.Values.get(name, rangeName).values;
for (const row in values) {
var a1 = (values[row][0]);
Logger.log(a1);
var ss = SpreadsheetApp.openById("ID of new spreadsheet"); //I have the real ID in my code
var cell = ss.getRange("A2");
cell.setValue(a1);
}
}
}
I believe your goal is as follows.
You want to retrieve the values from the column "B" of each Spreadsheet under the specific folder.
You want to put the retrieved values to the column "A" of the destination sheet.
Modification points:
About but when I run my script, it only puts 1 data point in the spreadsheet instead of all of them., when I saw your script, the retrieved value is always put to the cell "A2" of the destination sheet. I think that this might be the reason for your issue.
In your script, I thought that when the following flow is used, the process cost will become low. By this flow, your issue can be also removed.
In your situation, even when Sheets API is not used, the script might work using getValues().
When these points are reflected in your script, it becomes as follows.
Modified script:
Please set the folder ID and the destination Spreadsheet ID.
function pullTogether() {
// Retrieve values from each Spreadsheet.
var values = [];
var files = DriveApp.getFolderById('Folder ID').searchFiles(`title != 'nothing' and mimeType='${MimeType.GOOGLE_SHEETS}'`);
var sheetName = 'Sheet1'
while (files.hasNext()) {
var xFile = files.next();
var sheet = SpreadsheetApp.open(xFile).getSheetByName(sheetName);
if (sheet) {
var v = sheet.getRange("B2:B" + sheet.getLastRow()).getValues();
values = [...values, ...v];
}
}
// Put values to the destination sheet.
var ss = SpreadsheetApp.openById("ID of new spreadsheet"); //I have the real ID in my code
var dstSheet = ss.getSheets()[0];
dstSheet.getRange(2, 1, values.length, values[0].length).setValues(values);
}
Note:
Although I'm not sure about your actual situation, when the above script didn't work by the large data, please modify as follows.
From
dstSheet.getRange(2, 1, values.length, values[0].length).setValues(values);
To
Sheets.Spreadsheets.Values.update({ values }, ss.getId(), `'${dstSheet.getSheetName()}'!A2`, { valueInputOption: "USER_ENTERED" });
References:
getValues()
setValues(values)

Google Sheets, stack report from multiple workbooks

Goal: To stack data from 90+ google workbooks, all with the same sheet name, into the one master sheet for reporting
Info:
All worksheets have the same number of columns.
I have the following script but it does not run properly, I think the issue is with how I am caching / Pushing the data to the array before pasting to the output sheet.
I am trying to build an array then paste it in one go.
The tables I am stacking have 47 columns, unknown number of rows.
The part that opens the sheets is all working perfectly.
// Get the data from the worksheets
var indexsheet = SpreadsheetApp.getActive().getSheetByName("Index");
var outputsheet = SpreadsheetApp.getActive().getSheetByName("Output");
var response = SpreadsheetApp.getUi().prompt('Current Cycle', 'Enter Cycle Name Exactly in YY-MMM-Cycle# format', SpreadsheetApp.getUi().ButtonSet.OK_CANCEL)
var CurrentCycleName = response.getResponseText()
// Assign datasets to variables
var indexdata = indexsheet.getDataRange().getValues();
// For each workbook in the index sheet, open it and copy the data to a cache
indexdata.forEach(function(row, r) {
try {
//open Entity specific workbook
var workbookid = indexsheet.getRange(r + 1, 7, 1, 1).getValues();
var Entityworkbook = SpreadsheetApp.openById(workbookid)
// Open workhseet
Entitysheet.getSheetByName(CurrentCycleName)
// Add PR Data to cache - stacking for all countrys
var PRDataCache = Entitysheet.getDataRange().push()
} catch {}
})
// Set the all values of the sheet at once
outputsheet.getRange(r + 1, 14).setValue('Issue Splitting Data')
Entitysheet.getRange(2, 1, PRDataCache.length || 1, 47).setValues(PRDataCache)
};
This is the index tab where we are getting the workbookid from to open each file
This is the output file, we are stacking all data from each country
I believe your goal is as follows.
You want to retrieve the Spreadsheet IDs from the column "G" of "Index" sheet.
You want to give the specific sheet name using a dialog.
You want to retrieve all values from the specification sheet in all Spreadsheets. In this case, you want to remove the header row.
You want to put the retrieved values on "Output" sheet.
In this case, how about the following sample script?
Sample script:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var indexsheet = ss.getSheetByName("Index");
var outputsheet = ss.getSheetByName("Output");
var response = SpreadsheetApp.getUi().prompt('Current Cycle', 'Enter Cycle Name Exactly in YY-MMM-Cycle# format', SpreadsheetApp.getUi().ButtonSet.OK_CANCEL);
var CurrentCycleName = response.getResponseText();
var ids = indexsheet.getRange("G1:G" + indexsheet.getLastRow()).getValues();
var values = ids.reduce((ar, [id]) => {
try {
var [, ...values] = SpreadsheetApp.openById(id).getSheetByName(CurrentCycleName).getDataRange().getValues();
ar = [...ar, ...values];
} catch (e) {
console.log(`"${id}" was not found.`);
}
return ar;
}, []);
if (values.length == 0) return;
// If the number of columns is different in all Spreadsheets, please use the following script.
// var maxLen = Math.max(...values.map(r => r.length));
// values = values.map(r => r.length < maxLen ? [...r, ...Array(maxLen - r.length).fill("")] : r);
outputsheet.getRange(outputsheet.getLastRow() + 1, 1, values.length, values[1].length).setValues(values);
}
Note:
When the number of Spreadsheet IDs is large, the processing time might be over 6 minutes. I'm worried about this. At that time, how about separating the Spreadsheet IDs?
Reference:
reduce()

Copying multiple non empty rows to a new sheet

I am trying to save the daily feedback that i get from a website from the "feedback" sheet into another google sheet that i called "Feedback Database"
Column A: the Date
Column B: Time
Column C: The email address
Column D: the feedback
The data rows start from row 3.
What i am currently doing to save the data based on the basic knowledge that i have is:
copying all the data in row 3 in the "feedback" sheet
Saving it to the "database" sheet
Getting back to the "feedback" sheet and deleting row 3 so that data in row 4 becomes in row 3.
I have another function that count the number of rows and run the saveFeedback_Data() function based on the number of rows.
I know that what i am doing in step 3 isn't a proper way, I would really appreciate it if you guys recommend a better way to perform this function with a commentary in order to understand.
Appreciate your help,
function saveFeedback_Data() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('feedback'), true);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var Date= sheet.getRange('feedback !A3').getValue();
var Time = sheet.getRange('feedback !B3').getValue();
var Email = sheet.getRange('feedback !C3').getValue();
var Feedback = sheet.getRange('feedback !D3').getValue();
var sheet_dest = ss.getSheetByName("Database");
sheet_dest.appendRow([Date,Time, Email,Feedback]);
Logger.log('Issue Date : ' + Date + ' Issue time : ' + Time + ' Email Address : ' + Email + ' Feedback : ' + Feedback + '\n');
//now deleting the row
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('feedback'), true);
spreadsheet.getRange('3:3').activate();
spreadsheet.getActiveSheet().deleteRows(spreadsheet.getActiveRange().getRow(), spreadsheet.getActiveRange().getNumRows());
spreadsheet.getRange('A10').activate();
}
Save Feedback Data
This will run about ten times faster
function saveFeedback_Data() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Feedback');
const shsr = 3;
const dbsh = ss.getSheetByName('Database');
const rg = sh.getRange(shsr, 1, sh.getLastRow() - shsr + 1, 4);
const vs = rg.getValues().filter(r => !r.every(e => !e));//gets all non blank rows at one time
dbsh.getRange(dbsh.getLastRow() + 1, 1, vs.length, vs[0].length).setValues(vs);//moves all data at one time
rg.clearContent();//clears all data at one time
}
You can goto to Google Apps Script Reference and using the search box find any function that you don't understand. If it's a pure JavaScript function the go here

Google App Script throwing a #REF error when exporting a PDF

I am running a app script that works perfectly and exports a PDF from a organic sheet within a spreadsheet.
The problem is that the spreadsheet copies and throws a #REF error in all the cells.
Is there any way around this? I did see this SO question but I couldn't work my way around it. Code below:
I would assume one needs to use the range. Copy to function? but I couldn't figure it out.
// Simple function to send Weekly Status Sheets to contacts listed on the "Contacts" sheet in the MPD.
// Load a menu item called "Project Admin" with a submenu item called "Send Status"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Send Status", functionName:"exportSomeSheets"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Project Admin', submenu);
}
function exportSomeSheets() {
// Set the Active Spreadsheet so we don't forget
var originalSpreadsheet = SpreadsheetApp.getActive();
// Set the message to attach to the email.
var message = "Daily Sales Snapshot"; // Could make it a pop-up perhaps, but out of wine today
// Get Project Name from Cell A1
var projectname = originalSpreadsheet.getRange("A1:A1").getValues();
// Get Reporting Period from Cell B3
var period = originalSpreadsheet.getRange("B3:B3").getValues();
// Construct the Subject Line
var subject = projectname + " - Daily Status Sheet - " + period;
// Get contact details from "Contacts" sheet and construct To: Header
// Would be nice to include "Name" as well, to make contacts look prettier, one day.
var contacts = originalSpreadsheet.getSheetByName("Contacts");
var numRows = contacts.getLastRow();
var emailTo = contacts.getRange(2, 2, numRows, 1).getValues();
// Google scripts can't export just one Sheet from a Spreadsheet
// So we have this disgusting hack
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create("Spreadsheet to export");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var projectname = SpreadsheetApp.getActiveSpreadsheet();
sheet = originalSpreadsheet.getActiveSheet();
sheet.copyTo(newSpreadsheet);
//create temp sheet that lets us copy the values
sheet = originalSpreadsheet.getActiveSheet();
var temp = originalSpreadsheet.duplicateActiveSheet();
//copy the values
range = temp.getDataRange();
range.copyTo(range, {contentsOnly: true});
//copy the values to a new spreadsheet
temp.copyTo(newSpreadsheet);
//delete our temp sheet.
ss.deleteSheet(temp);
// Find and delete the default "Sheet 1", after the copy to avoid triggering an apocalypse
newSpreadsheet.getSheetByName('Sheet1').activate();
newSpreadsheet.deleteActiveSheet();
// Make zee PDF, currently called "Weekly status.pdf"
// When I'm smart, filename will include a date and project name
var pdf = DriveApp.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'Daily Status.pdf',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
// Delete the wasted sheet we created, so our Drive stays tidy.
DriveApp.getFileById(newSpreadsheet.getId()).setTrashed(true);
}
This worked for me if any unfortunate soul lands on this page.
// Simple function to send Weekly Status Sheets to contacts listed on the "Contacts" sheet in the MPD.
// Load a menu item called "Project Admin" with a submenu item called "Send Status"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Send Status", functionName:"exportSomeSheets"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Project Admin', submenu);
}
function exportSomeSheets() {
// Set the Active Spreadsheet so we don't forget
var originalSpreadsheet = SpreadsheetApp.getActive();
// Set the message to attach to the email.
var message = "Daily Sales Snapshot"; // Could make it a pop-up perhaps, but out of wine today
// Get Project Name from Cell A1
var projectname = originalSpreadsheet.getRange("H1:H1").getValues();
// Get Reporting Period from Cell B3
var period = originalSpreadsheet.getRange("B3:B3").getValues();
// Construct the Subject Line
var subject = projectname + " - Daily Status Sheet - " + period;
// Get contact details from "Contacts" sheet and construct To: Header
// Would be nice to include "Name" as well, to make contacts look prettier, one day.
var contacts = originalSpreadsheet.getSheetByName("Contacts");
var numRows = contacts.getLastRow();
var emailTo = contacts.getRange(2, 2, numRows, 1).getValues();
// Google scripts can't export just one Sheet from a Spreadsheet
// So we have this disgusting hack
var newSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheets = newSpreadsheet.getSheets;
for (var i = 5; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName) {
sheet[i].hideSheet();
}
}
// Make zee PDF, currently called "Weekly status.pdf"
// When I'm smart, filename will include a date and project name
var pdf = DriveApp.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'Daily Status.pdf',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
}

Google Apps Script to email sheet as a PDF working but want to clear some cells

I have edited a script I found to Email a PDF created from the spreadhseet to recipients in the spreadsheet. It is working as I need it to however I need to delete some of the cells before the PDF is created. What would the correct code be to add in to delete from row 194 or cells a194:j200. Code attached below.
Thanks for your help
// Simple function to send Weekly Schedule Sheets to contacts listed on the "Tutors" sheet in the Spreadsheet.
// Load a menu item called "Admin Tasks" with a submenu item called "Email Schedule"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Email Schedule", functionName:"tempsheet"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Admin Tasks', submenu);
}
function tempsheet() {
// Set the Active Spreadsheet so we don't forget
var originalSpreadsheet = SpreadsheetApp.getActive();
// Set the message to attach to the email.
var message = "Please find weekly schedule attached. Contact office for any changes as soon as possible";
// Get Project Name from Cell A1
var projectname = originalSpreadsheet.getRange("A1:A1").getValues();
// Get Reporting Period from Cell B3
var period = originalSpreadsheet.getRange("F2:F2").getValues();
// Construct the Subject Line
var subject = projectname + " - Weekly Schedule Sheet - " + period;
// Get contact details from "Tutors" sheet and construct To: Header
var contacts = originalSpreadsheet.getSheetByName("Tutors");
var numRows = contacts.getLastRow();
var emailTo = contacts.getRange(2, 5, numRows, 1).getValues();
// Create a new Spreadsheet and copy the current sheet into it.
var newSpreadsheet = SpreadsheetApp.create("Temporary Schedule");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var projectname = SpreadsheetApp.getActiveSpreadsheet();
sheet = originalSpreadsheet.getActiveSheet();
sheet.copyTo(newSpreadsheet);
// Make PDF, currently called "Weekly Schedule.pdf"
var pdf = DocsList.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:'Weekly Schedule.pdf',content:pdf, mimeType:'application/pdf'};
// Send the freshly constructed email
MailApp.sendEmail(emailTo, subject, message, {attachments:[attach]});
// Find and delete the default "Sheet 1", after the copy
newSpreadsheet.getSheetByName('copy of MASTERPLAN').activate();
newSpreadsheet.deleteActiveSheet();
// Delete the temporary sheet
DocsList.getFileById(newSpreadsheet.getId()).setTrashed(true);
}
Following should work to clear A194:J200
var range = sheet.getRange(194,1,7,10);
range.clear();

Categories

Resources