copy data from one google spreadsheet to another - google-apps-script

i've made script for coping the details with the help of id column which will common in both sheets this code is not copying any detail
function myFunction()
{
}
function onOpen() {
var subMenus = [
{name:"Generate farnchise username", functionName: "approveRequests"},
];
SpreadsheetApp.getActiveSpreadsheet().addMenu("Custom Functions", subMenus);
}
function approveRequests() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
sheet = ss.getActiveSheet(),
sheetName = sheet.getName(),
data = sheet.getDataRange().getValues();
if (sheetName == "g6-live-properties") {
var range = sheet.getActiveRange(),
startRow = range.getRowIndex(),
numRows = range.getNumRows(),
numCols = range.getNumColumns()
if (numCols == 3) {
if (data.length > 1) {
var values = range.getValues(),
nextSheet = ss.getSheetByName("11-Apr-60+"),
lastRow = nextSheet.getLastRow();
nextSheet.getRange(lastRow+1,1,numRows,3).setValues(values);
sheet.deleteRows(startRow,numRows);
}
}
}
}

Related

Import 3 google spreadsheet at same time into another

With this script, I can import one spreadsheet into another spreadsheet in a tab.
function importA() {
var values1 = SpreadsheetApp.openById('xxxurl').
getSheetByName('xxxname').getRange('A1:DE300').getValues();
SpreadsheetApp.getActive().getSheetByName('TAB').
getRange(1,1,values1.length,values1[0].length).setValues(values1)
}
Now, I would like to import 3 spreadsheets one below the other (in the same tab), preserving any increase in the rows of each sheet at the same time.
How could I proceed?
You can try this code and see if it works for you:
function collectAll() {
createNew(); //this can be removed for instances that you would need to run the two functions separately.
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ["TAB1","TAB2","TAB3"];
for( var i=0; i<sheets.length; i++ ) {
if (sheets[i] == "TAB1"){
var sh = ss.getSheetByName('TAB1');
var range1 = sh.getRange(1,1, sh.getLastRow(), sh.getLastColumn()).getValues();
Logger.log(range1);
}
else if (sheets[i] == "TAB2"){
var sh = ss.getSheetByName('TAB2');
var range2 = sh.getRange(1,1, sh.getLastRow(), sh.getLastColumn()).getValues();
Logger.log(range2);
}
else if (sheets[i] = "TAB3"){
var sh = ss.getSheetByName('TAB3');
var range3 = sh.getRange(1,1, sh.getLastRow(), sh.getLastColumn()).getValues();
Logger.log(range3);
}
}
var range = range1.concat(range2,range3);
Logger.log(range);
ss.getSheetByName('TAB').getRange(1,1, range.length, sh.getLastColumn()).setValues(range);
}
function createNew() { //This function creates the Tabs from 3 different sheets using Sheet ID
var sheets = ["ID1","ID2","ID3"]; //Spreadsheet ID goes here
for (i=0; i<sheets.length; i++ ) {
var ssh = SpreadsheetApp.openById(sheets[i]);
var values = ssh.getSheetValues(1,1, ssh.getLastRow(), ssh.getLastColumn());
var create = SpreadsheetApp.getActive().insertSheet('TAB'+(1+i));
create.getRange(1,1, ssh.getLastRow(), ssh.getLastColumn()).setValues(values);
Logger.log(create);
}
}
What this does is that it assigns all of the values of each tab to its own variable range1, range2 and range3 and then it concatenates all values in a single range, then sets the value to the sheet named "TAB".
I've used getSheetByName instead of openByID but you can get the idea.
function test() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ["Sheet1","Sheet2","Sheet3"];
for( var i=0; i<sheets.length; i++ ) {
importA(sheets[i]);
}
}
catch(err) {
console.log(err);
}
}
function importA(name) {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh1 = ss.getSheetByName("TAB");
sh1.clear() // if you want to erase old data in TAB
var sh2 = ss.getSheetByName(name);
var r1 = sh1.getDataRange();
var r2 = sh2.getDataRange();
// to prevent a blank line at the top
var i = r1.getNumRows() === 1 ? 0 : 1;
sh1.getRange(r1.getNumRows()+i,1,r2.getNumRows(),r2.getNumColumns()).setValues(r2.getValues());
}
catch(err) {
console.log(err);
}
}
Merge all spreadsheets sheets into one sheet
function mergeSpreadsheetsAllIntoOneSheet() {
const ss = SpreadsheetApp.getActive();
['id1', 'id2', 'id3'].forEach((id, i) => {
let sss = SpreadsheetApp.openById(id);
sss.getSheets().forEach(sh => {
let vs = sh.getDataRange().getValues();
let a = [...Array.from(new Array(vs[0].length).keys(), x => (x == 0)?sss.getName():sh.getName())];
vs.unshift(a);
let ash = ss.getSheets()[0];
if (vs && vs.length > 0) {
ash.getRange(ash.getLastRow() + 1, 1, vs.length, vs[0].length).setValues(vs);
}
});
});
}

issue during google sheet macro

I have an issue with this google sheet macro. Error message is: Exception: Range not found
I am trying to perform this script in order to copy recipient string (that can change according to data in P2 cell.
Can you help me?
Thanks
function macro()
{
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("A2:L1000");
var data = dataRange.getValues();
for (i in data)
{
var rowData = data[i];
var recipient = rowData[0];
var parameter1 = rowData[1];
if (parameter1 == "OK")
{
sheet.getRange('P2').activate();
sheet.getRange(recipient).copyTo(sheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
}
}
}
Perhaps this is what you want:
function macro() {
var sh = SpreadsheetApp.getActiveSheet();
var rg = sh.getRange("A2:L1000");
var data = rg.getValues();
data.forEach((r,i)=>{
if(r[1] == "OK") {
sh.getRange(r[0]).copyTo(sh.getRange(i + 2, 16),SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
}
})
}
I have made something like this but it is only copy/paste first row (copy B2 to P2 works fine).
If I try to copy B3 to P2 it does not work..
function macro()
{
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("A2:L1000");
var data = dataRange.getValues();
for (i in data)
{
var rowData = data[i];
var parameter1 = rowData[10];
if (parameter1 == "OK")
{
sheet.getRange('P2').activate();
sheet.getRange("B" +(i+2)).copyTo(sheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
}
}
}

How to paste in an email a table with google script/google sheets Macros?

I have this Macro to send emails to some people. The problem is that it pastes the table in values, not in table format. I need to paste the table as a table.
function Mails() {
var values = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var filas= values[0][1];
var columnas= values[1][0];
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Enviar"));
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange(2,4,filas,columnas);
var data = dataRange.getValues();
for (i in data) {
var rowData = data[i];
var emailAddress = sheet.getRange(1, 3).getValue();
var destinatario = rowData[0];
var sigla1 = sheet.getRange(2,4,filas,columnas).getValues();
var mensaje = 'Estimado ' + destinatario + ',\n\n' + sigla1 ;
var asunto = 'Mensajes Pendientes';
MailApp.sendEmail(emailAddress, asunto, mensaje);
}
}
function onOpen () {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [
{name: 'Send Emails', functionName: 'Mails'}
];
spreadsheet.addMenu('Enviar Emails', menuItems);
}
The problem is this line var sigla1 = sheet.getRange(2,4,filas,columnas).getValues();
I have to paste it as a table, not in values. How can i do that?
Thanks
I'am trying with this code now.. but it doesn't function..
function Mails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Enviar"));
var sheet = SpreadsheetApp.getActiveSheet();
var values = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var filas= values[0][1];
var columnas= values[1][0];
var recipient = sheet.getRange(1, 3).getValue();
var subject = 'Estimado';
var vA=SpreadsheetApp.getActive().getSheetByName('Enviar').getDataRange().getValues();
var html="<style>th,td{border:1px solid black;}<table>";
for(var i=0;i<vA.length;i++) {
html+="<tr>";
for(var j=0;i<vA[i].length;j++) {
if(i==0) {
html+=Utilities.formatString('<th>%s</th>', vA[i][j]);
}else{
html+=Utilities.formatString('<td>%s</td>', vA[i][j]);
}
}
html+="</tr>";
}
GmailApp.sendEmail(recipient, subject, null, {htmlBody:html})
}
function onOpen () {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [
{name: 'Send Emails', functionName: 'Mails'}
];
spreadsheet.addMenu('Enviar Emails', menuItems);
}
Here you have an image of what i need to send via email.
The rows change with the data, so the table depend of how many operations are in the day..
Html Table into Email
function sendHtmlTableViaEmail() {
var vA=SpreadsheetApp.getActive().getSheetByName('name').getDataRange().getValues();
var html="<style>th,td{border:1px solid black;}<table>";
for(var i=0;i<vA.length;i++) {
html+="<tr>";
for(var j=0;i<vA[i].length;j++) {
if(i==0) {
html+=Utilities.formatString('<th>%s</th>', vA[i][j]);
}else{
html+=Utilities.formatString('<td>%s</td>', vA[i][j]);
}
}
html+="</tr>";
}
//You have to add the code for recipient and subject
GmailApp.sendEmail(recipient, subject, null, {htmlBody:html})
}

Google Script: When cell is filled, have prompt ask if user wants to run script

I have written a script to clean up and move data between 3 different sheets. A user first paste a data extract on to the "Extract" page, and then runs the script.
When a user paste the data into cell A1 on the "Extract" page, I would like a prompt box to ask the user if they would like to run the script; if Yes, run script, if No, don't run script and show message. How would I go about doing this?
This is what I have so far...everything after the first function works.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Extract");
if(ss.s().getRange("A1").getValue() != ""){
var ui = SpreadsheetApp.getUi()
var response = ui.alert('Would you jbot to find new claims for you?', ui.ButtonSet.OK_CANCEL);
if (response == ui.Button.OK) {
jbot();
} else {
Logger.log('The user clicked "No" or the close button in the dialog\'s title bar.');
}
}
}
function jbot(){
movetobot();
deleteRows();
removeDupesInOtherSheets();
deleteCol();
cleanup();
movetoqueue();
message();
};
function movetobot() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Extract");
var ts = ss.getSheetByName("bot");
s.getRange("A1:BW").moveTo(ts.getRange("A1"));
}
function deleteRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("bot");
var r = s.getRange("BO:BO");
var v = r.getValues();
for(var i=v.length-1;i>=0;i--)
if(v[0,i]=='#POSTLESSEE' || v[0,i]=='#TDI CRC_OANKURA' || v[0,i]=='#Partpaymentoffer' || v[0,i]=='#TDI_CRC_DVANKURA' || v[0,i]=='#partpaymentdupe' )
s.deleteRow(i+1);
}
function removeDupesInOtherSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName("bot").getDataRange().getValues();
var s2 = ss.getSheetByName("Queue").getDataRange().getValues();
// iterate 'Queue' and check in 'bot' if duplicate values exist
var nS1 = [];
var s2Col1 = [];// data in column1 of Queue
for(var n in s2){
s2Col1.push(s2[n][0]);
}
for(var n in s1){ // iterate '180418970' and test col 1 vs col 1 in 'Queue'
var noDup1 = checkForDup(s1[n],s2Col1)
if(noDup1){nS1.push(noDup1)};// if not present in 'Queue' then keep
}
Logger.log(nS1);// view result
ss.getSheetByName("bot").getDataRange().clear();// clear and update sheets
ss.getSheetByName("bot").getRange(1,1,nS1.length,nS1[0].length).setValues(nS1);
}
function checkForDup(item,s){
Logger.log(s+' = '+item[0]+' ?')
if(s.indexOf(item[0])>-1){
return null;
}
return item;
}
function deleteCol() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var lastCol = sheet.getLastColumn();
var keep = [1,2,3,4,45,53,74, 75]; // array of column numbers to keep
for (var col=lastCol; col > 0; col--) {
if (keep.indexOf(col) == -1) {
// This isn't a keeper, delete it
sheet.deleteColumn(col);
}
}
}
function cleanup() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
sheet.getRange("B1:B").moveTo(sheet.getRange("H1"));
sheet.deleteColumn(2)
sheet.deleteRow(1)
var cell = sheet.getRange("D:D");
cell.setNumberFormat("m/d/yy");
var cell = sheet.getRange("F:F");
cell.setNumberFormat("m/d/yy");
var cell = sheet.getRange("A:A");
cell.setHorizontalAlignment("center");
var cell = sheet.getRange("C:D");
cell.setHorizontalAlignment("center");
var cell = sheet.getRange("F:G");
cell.setHorizontalAlignment("center");
sheet.autoResizeColumn(2)
sheet.autoResizeColumn(5)
sheet.autoResizeColumn(7)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var cell = sheet.getRange("BW1");
cell.setFormula("=COUNT(A:A)");
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var range = sheet.getRange("A1:G");
range.sort({column: 4, ascending: true})
}
function movetoqueue() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
// skip row 1 (header) and beyond column G
var range = sheet.getRange(1,1,sheet.getLastRow()-1,7);
sheet = spread.getSheetByName("Queue");
var rows = sheet.getRange(1,1,sheet.getLastRow(),1).getValues();
// search for first blank row column 1
for( var i=0; i<rows.length; i++ ) {
if( rows[i][0] === "" ) {
var offset = sheet.getRange(1,1).offset(i,0);
range.copyTo(offset);
break;
}
}
}
function message() {
SpreadsheetApp.getActive().getSheetByName("Queue").activate();
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var range = sheet.getRange("bot!BW1:BW1");
var data = range.getValue();
Browser.msgBox(data + " new claims have been added to the queue. Thank you for using jBot!");
}
Your onEdit(e) will trigger the alert regardless of which cell is edited. You need to check the event range to limit it to cell A1 of Extract like this.
function onEdit(e) {
if( e.range.getSheet().getName() === "Extract" ) {
if( e.range.getA1Notation() === "A1" ) {
if( e.value !== "" ) {
var ui = SpreadsheetApp.getUi();
// Do the rest of your stuff here
}
}
}
}

Preserve formula references when printing a single Google Sheets sheet to PDF

I want to accomplish the following:
Make a menu with a print to PDF button.
Have that button export a PDF to with the same name and same destination as the google sheet.
This works well, but the script I found I need to change, because most people print to PDF by making a temporary copy of the sheet, printing, and finally deleting the temporary copy.
I have references from other sheets in my original document that ends up printed as #REF! values because only the one sheet gets copied and printed, not my whole document.
How can i make this process include baking the formulas as text?
CODE FOR PRINTING:
function onOpen() {
var submenu = [{name: "Save PDF", functionName: "generatePdf"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Export', submenu);
}
function generatePdf() {
// Get active spreadsheet.
var sourceSpreadsheet = SpreadsheetApp.getActive();
// Get active sheet.
var sheets = sourceSpreadsheet.getSheets();
var sheetName = sourceSpreadsheet.getActiveSheet().getName();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
// Set the output filename as sheetName.
var pdfName = sheetName;
// Get folder containing spreadsheet to save pdf in.
var parents = DriveApp.getFileById(sourceSpreadsheet.getId()).getParents();
if (parents.hasNext()) {
var folder = parents.next();
}
else {
folder = DriveApp.getRootFolder();
}
// Copy whole spreadsheet.
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
// Delete redundant sheets.
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName){
destSpreadsheet.deleteSheet(sheets[i]);
}
}
var destSheet = destSpreadsheet.getSheets()[0];
// Replace cell values with text (to avoid broken references).
var sourceRange = sourceSheet.getRange(1, 1, sourceSheet.getMaxRows(), sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
// Save to pdf.
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
// Delete the temporary sheet.
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
CODE FOR CONVERTING FORMULAS TO TEXT:
function formulasAsText() {
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var k = 0; k < sheets.length; k++) {
var range = sheets[k].getDataRange();
var values = range.getValues();
var formulas = range.getFormulas();
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[0].length; j++) {
values[i][j] = formulas[i][j] ? "'" + formulas[i][j] : values[i][j];
}
}
range.setValues(values);
}
}
To maintain formula references, you need to modify the formulasAsText() function to accept an input, and also not worry about writing a formula if one is found. This input could be a spreadsheet ID - i.e. the id of the temporary copy - or it could be an array of Sheet objects.
Once you have made these two modifications, you would call the function prior to deleting the non-desired sheets in the temporary copy:
/**
* #param Sheet[] wbSheets An array of Sheets to operate on.
* #param String toPreserve The name of the sheet which should be preserved.
*/
function preserveFormulas(wbSheets, toPreserve) {
if(!wbSheets || !wbSheets.length || !toPreserve)
throw new Error("Missing arguments.");
wbSheets.forEach(function (sheet) {
if ( sheet.getName() === toPreserve ) {
var range = sheet.getDataRange();
// Serialize the cell's current value, be it static or derived from a formula.
range.setValues(range.getValues());
}
});
}
Finished my script. Here is what i ended up with.
function onOpen() {
var submenu = [{name:"Save PDF", functionName:"generatePdf"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Export', submenu);
}
function hideSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("sheet1");
var sheet2 = ss.getSheetByName("PRINT SHEET");
var sheet3 = ss.getSheetByName("sheet3");
var sheet4 = ss.getSheetByName("sheet4");
var sheet5 = ss.getSheetByName("sheet5");
var sheet6 = ss.getSheetByName("sheet6");
var sheet7 = ss.getSheetByName("sheet7");
sheet1.hideSheet();
sheet3.hideSheet();
sheet4.hideSheet();
sheet5.hideSheet();
sheet6.hideSheet();
sheet7.hideSheet();
}
function showSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("sheet1");
var sheet2 = ss.getSheetByName("PRINT SHEET");
var sheet3 = ss.getSheetByName("sheet3");
var sheet4 = ss.getSheetByName("sheet4");
var sheet5 = ss.getSheetByName("sheet5");
var sheet6 = ss.getSheetByName("sheet6");
var sheet7 = ss.getSheetByName("sheet7");
sheet1.showSheet();
sheet3.showSheet();
sheet4.showSheet();
sheet5.showSheet();
sheet6.showSheet();
sheet7.showSheet();
}
function generatePdf() {
// Get active spreadsheet.
var sourceSpreadsheet = SpreadsheetApp.getActive();
// Get active sheet.
var sheets = sourceSpreadsheet.getSheets();
var sheetName = sourceSpreadsheet.getActiveSheet().getName();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
// Set the output filename as BID and number (from cell C4).
var pdfName = "BID " + sheets[0].getRange("C4").getValue() + ".pdf";
var ui = SpreadsheetApp.getUi();
// Get folder containing spreadsheet to save pdf in.
var parents = DriveApp.getFileById(sourceSpreadsheet.getId()).getParents();
if (parents.hasNext()) {
var folder = parents.next();
}
else {
folder = DriveApp.getRootFolder();
}
hideSheets();
// Save to pdf.
var theBlob = sourceSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
showSheets();
ui.alert('Export finished');
}
Thanks.