Import 3 google spreadsheet at same time into another - google-apps-script

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);
}
});
});
}

Related

Script for sheets to change a cell based on a value on a different cell

everyone!
I'm trying to write a script where the cell G3 on the sheet 'ref view' will change to 'Yes' if the cell D9 on 'view' contains 'BP' when I run it. The problem is that the execution is completed without errors but when I try to test it nothing happens.
This is the code:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetInfo = ss.getSheetByName('ref view')
var data = sheet.getDataRange().getValues();
var rangeView = ss.getRange('View!D9');
var cell = ss.getRange('ref view!G3');
var range = rangeView;
for(var i=0; i<data.length; i++) {
if(rangeView == 'BP') {
sheet.getRange(cell).clear().setValue('Yes');
}
}
} ```
Try it this way:
function one() {
var ss = SpreadsheetApp.getActive();
var sh1 = ss.getActiveSheet();
var vs1 = sh1.getDataRange().getValues();
var sh2 = ss.getSheetByName('ref view')
var sh3 = ss.getSheetByName('view');
var sh3D9v = sh3.getRange('D9').getValue();//value
var sh2G3r = sh2.getRange('G3');//Range
for(var i=0; i<vs1.length; i++) {
if(sh3D9v == 'BP') {
sh1.getRange(sh2G3r).setValue('Yes');
}
}
}
Be aware that a range does not return a value without the use of a getValue() or a getValues();

Google script function works when it runs separately, but when I run all the functions together it doesn't work

I've got a question about my script. I've got a script where when running together only 2 out of 3 functions run, the other function does not run. The one function that does not work when running together is the "medewerkerLijst" function. When I run that function on it's own it works perfectly as it should, when running it together with the other 2 functions it does not work. I can't figure out why it's not working.
The functions "nieuwDossier" & "sorteerDossiers" do work when running together. Sorry if my code is a mess, I'm still learning how to code.
function Aanmaken(){
medewerkerLijst();
nieuwDossier();
sorteerDossiers();
}
function medewerkerLijst() {
var ss5 = SpreadsheetApp.getActiveSpreadsheet();
var copySheet2 = ss5.getSheetByName("-Dossier");
var pasteSheet2 = ss5.getSheetByName("-Medewerkers");
// get source range
var source2 = copySheet2.getRange(2,7,1,1);
// get destination range
var destination2 = pasteSheet2.getRange(pasteSheet.getLastRow()+1,1,1,1);
// copy values to destination range
source2.copyTo(destination2, {contentsOnly:true});
}
function nieuwDossier() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var sheet = source.getSheetByName('-Template');
sheet.copyTo(source).setName('Nieuw');
var sheet2 = source.getSheetByName('-Dossier');
var cell = sheet2.getRange("G2");
var value = cell.getValue();
var sheet3 = source.getSheetByName('Nieuw');
sheet3.setName(value);
sheet3.setTabColor(null);
}
function sorteerDossiers () {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetNameArray = [];
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
sheetNameArray.push(sheets[i].getName());
}
sheetNameArray.sort();
for( var j = 0; j < sheets.length; j++ ) {
ss.setActiveSheet(ss.getSheetByName(sheetNameArray[j]));
ss.moveActiveSheet(j + 1);
}
}
This runs just fine
function main() {
var ss = SpreadsheetApp.getActive();
var sh1 = ss.getSheetByName("Sheet1");
var sh2 = ss.getSheetByName("Sheet2");
var rg1 = sh1.getRange(2, 7, 1, 1);
var rg2 = sh2.getRange(sh2.getLastRow() + 1, 1, 1, 1);
rg1.copyTo(rg2, { contentsOnly: true });
var sh3 = ss.getSheetByName('Sheet3');
var sh4 = sh3.copyTo(ss).setName('Sheet4');
var cell = sh1.getRange("G2");
var v1G2 = cell.getValue();
sh4.setName(v1G2);
sh4.setTabColor(null);
var shts = ss.getSheets().map(sh => sh.getName()).sort().forEach((n, i) => {
ss.setActiveSheet(ss.getSheetByName(n));
ss.moveActiveSheet(i + 1)
});
}

data transfert based on cell value on google sheet

I'm not good with coding and i tried to mix some codes that i found and made what i needed, but now i face a difficult problem for me, so I'm trying when to press the button that i created to run the script to send the data that have for example an 'X' in the last column. i successfully made the sending from one sheet to another but it send all the data for now i want to be sent only the chosen ones with an 'X'.
any help I'll be grateful.
this is my code
thank you
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Sheet1");
var url = "https://docs.google.com/spreadsheets/d/15nIAXcP0a14OvvBr5lww4tO23stQD4PEu0QDAcgaFyE/edit#gid=0";
var ss2 = SpreadsheetApp.openByUrl(url);
var pasteSheet = ss2.getSheetByName("Sheet2");
// get source range
var max = copySheet.getMaxRows().toString();
var range = copySheet.getRange(2,1,max,4);
var dataValues = range.getValues();
for(var i = 1; i < dataValues.length; i++)
{
if(dataValues[i][5] === 'X')
{
copySheet.appendRow([dataValues[i][0],
dataValues[i][1],
dataValues[i][2],
dataValues[i][3],
dataValues[i][4]]);
}
}
for(var i = 1; i < dataValues.length; i++)
{
if(dataValues[i][5] === 'X')
{
var clearRow = i+1;
dataSheet.getRange('A' + clearRow + ':F' + clearRow).clear();
}
}
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,max,1);
// clear source values
Browser.msgBox('Commande Confirmer');
}
This is all that your function does
dataSheet is undefined so I assume it was csh
function lfunko() {
const ss = SpreadsheetApp.getActive();
const csh = ss.getSheetByName("Sheet1");
const ss2 = SpreadsheetApp.openByUrl("ssurl");
const psh = ss2.getSheetByName("Sheet2");
var vs = csh.getRange(2, 1, csh.getLastRow() - 1, csh.getLastColumn()).getValues();
vs.forEach((r,i) => {
if (vs[i][5] === 'X') {
csh.appendRow([vs[i][0], vs[i][1], vs[i][2], vs[i][3], vs[i][4]]);
csh.getRange(i + 1, 1, 1, 6).clear();
}
});
}

Count colored cells in multiple sheets in a single Spreadsheet

I have a master sheet in Google Spreadsheet as below;
what i want is to get color counts from a given tab/sheets(Column A) in google spreadsheet. According to my research in stackoverflow, i found the code which works perfect in an active single sheet (https://stackoverflow.com/a/57571668/12906920);
function countColoredCells(countRange,colorRef) {
var activeRange = SpreadsheetApp.getActiveRange();
var activeSheet = activeRange.getSheet();
var formula = activeRange.getFormula();
var backgrounds = activeSheet.getRange(countRange).getBackgrounds();
var colorRefBackground = activeSheet.getRange(colorRef).getBackground();
var count = 0;
for(var i=0;i<backgrounds.length;i++)
for(var j=0;j<backgrounds[0].length;j++)
if( backgrounds[i][j] == colorRefBackground )
count=count+1;
return count;
};
But i could not add sheet name (cell value) as argument . For example; to get given sheet2 color in a given range with reference to B1, my function could be:
countColoredCells(countRange,colorRef,sheet_name) > countColoredCells(F1:F30,B1,A2)
the function looks which sheets' range will be searched and return the count values from reference color in master excel. Can someone help me how to do that?
UPDATE
Here the modified code but i still get "range not found error"
function countColoredCells(countRange,colorRef,sheetName) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName(sheetName));
var activeRange = SpreadsheetApp.getActiveRange();
var activeSheet = activeRange.getSheet();
var formula = activeRange.getFormula();
var backgrounds = activeSheet.getRange(countRange).getBackgrounds();
var colorRefBackground = activeSheet.getRange(colorRef).getBackground();
var count = 0;
for(var i=0;i<backgrounds.length;i++)
for(var j=0;j<backgrounds[0].length;j++)
if( backgrounds[i][j] == colorRefBackground )
count=count+1;
return count;
}
In your original function, just change var backgrounds = activeSheet.getRange(countRange).getBackgrounds();
to
const backgrounds = SpreadsheetApp.getActive()
.getSheetByName(sheetName)
.getRange(countRange)
.getBackgrounds();
Background Color Count in a column
Defaults to active spreadsheet, active sheet and column 1
function getBGColorCount(col, sh, ss) {
var ss = ss || SpreadsheetApp.getActive();
var sh = sh || SpreadsheetApp.getActiveSheet();
var col = col || 1;
const bgs = sh.getRange(1, col, sh.getMaxRows()).getBackgrounds().flat();
let colors = { pA: [] };
bgs.forEach((c, i) => {
if (!colors.hasOwnProperty(c)) {
colors[c] = 1;
colors.pA.push(c);
} else {
colors[c] += 1;
}
});
let html = '<style>td,th{border:1px solid black;width:25px;}</style><table>';
//add this to remove white filter(p => p != "#ffffff")
colors.pA.forEach(p => {
html += `<tr><td style="background-color:${p};"></td><td>${colors[p]}</td></tr>`;
});
html += '</table>'
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), 'Color Count');
}
Multiple Sheets
function getBGColorCountMultipleSheets(col, shts, ss) {
var ss = ss || SpreadsheetApp.getActive();
var shts = shts || ['Sheet1', 'Sheet2', 'Sheet0'];
var col = col || 1;
let colors = { pA: [] };
ss.getSheets().filter(s => ~shts.indexOf(s.getName())).forEach(sh => {
let bgs = sh.getRange(1, col, sh.getMaxRows()).getBackgrounds().flat();
bgs.forEach((c, i) => {
if (!colors.hasOwnProperty(c)) {
colors[c] = 1;
colors.pA.push(c);
} else {
colors[c] += 1;
}
});
});
let html = '<style>td,th{border:1px solid black;width:25px;}</style><table>';
//add this to remove white filter(p => p != "#ffffff")
colors.pA.forEach(p => {
html += `<tr><td style="background-color:${p};"></td><td>${colors[p]}</td></tr>`;
});
html += '</table>'
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), 'Color Count');
}
Here is the working code for counting colored cells in multiple sheets in a single google spreadsheet:
function goToSheet(countRange,colorRef,sheetName) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName(sheetName));
var activeRange = SpreadsheetApp.getActiveRange();
var activeSheet = activeRange.getSheet();
var formula = activeRange.getFormula();
const backgrounds = SpreadsheetApp.getActive()
.getSheetByName(sheetName)
.getRange(countRange)
.getBackgrounds();
var colorRefBackground = activeSheet.getRange(colorRef).getBackgrounds();
var count = 0;
for(var i=0;i<backgrounds.length;i++)
for(var j=0;j<backgrounds[0].length;j++)
if( backgrounds[i][j] == colorRefBackground )
count=count+1;
return count;
}
I would like to thank user
https://stackoverflow.com/users/8404453/themaster who helped me to achieve it and also, i changed
var colorRefBackground = activeSheet.getRange(colorRef).getBackground()
to
var colorRefBackground = activeSheet.getRange(colorRef).getBackgrounds()
which returns the background colors of the cells in the range.

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
}
}
}
}