I found this amazing masterpiece of #Cooper to search for duplicates based on values in 1 column. Now instead of removing these duplicates as the code does, I want to move them to another sheet. Any idea how this can be done?
Thanks :).
Here is the code:
function removeDuplicates() {
var sh=SpreadsheetApp.getActiveSheet();
var dt=sh.getDataRange().getValues();
var uA=[];
var d=0;
for(var i=0;i<dt.length;i++) {
if(uA.indexOf(dt[i][0])==-1) {
uA.push(dt[i][0]);
}else{
sh.deleteRow(i+1-d++);
}
}
}
Move row
function removeDuplicates() {
const ss = SpreadsheetApp.getActive();
const dsh = ss.getSheetByName('Destination');
var sh=SpreadsheetApp.getActiveSheet();
var dt=sh.getDataRange().getValues();
var uA=[];
let d = 0;
for(var i=0;i<dt.length;i++) {
if(uA.indexOf(dt[i][0])==-1) {
uA.push(dt[i][0]);
}else{
dsh.appendRow(dt[i]);//append
sh.deleteRow(i+1-d++);//delete
}
}
}
Related
I have a macro running through a forEach loop that works but always ends on the last sheet in my workbook.
How do I get it to finish on a specified sheet?
I tried a few variations of getSheetbyname
but I don't really know where to put it.
This is the code:
function ResetPage() {
var sheet = SpreadsheetApp.getActive();
var racenumber = sheet.getRange('B2');
var venue = sheet.getRange('E2');
venue.clearContent();
racenumber.activate();
sheet.getCurrentCell().setValue('1');
}
function doForAllTabs() {
var spreadsheet = SpreadsheetApp.getActive();
var allsheets = spreadsheet.getSheets();
allsheets.forEach(function(workbook) {
if(workbook.getSheetName() !== "Venues") {
workbook.activate();
ResetPage();
}
});
}
You don't need to set each sheet active to change the values. The macro recorder does it but it makes the process slower.
This should do the updates without changing your active cell:
function ResetPage(sheet) {
var racenumber = sheet.getRange('B2');
var venue = sheet.getRange('E2');
racenumber.setValue(1);
venue.clearContent();
}
function doForAllTabs() {
var spreadsheet = SpreadsheetApp.getActive();
var allsheets = spreadsheet.getSheets();
allsheets.forEach(function(workbook) {
if(workbook.getSheetName() !== "Venues") {
ResetPage(workbook);
}
});
}
function doForAllTabs() {
SpreadsheetApp.getActive().getSheets().forEach(sh => {
if (sh.getName() != "Venues") {
sh.getRange('B2').setValue(1);
sh.getRange('E2').setValue('');
}
});
}
Im trying to find if a range is in a rangeList and I saw somewhere something like the statement:
if ( myrange in myrangelist ) ...
I have tried to get this to work but cannot.
Does someone know if possible and if yes then how?
Perhaps this will help:
function isContainedInActiveRangeList(rgA1) {
var rgA1=rgA1||'B2';
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var list=sh.getActiveRangeList();
var rgA=list.getRanges();
var fulllist=[];
for(var i=0;i<rgA.length;i++) {
var rvA=rgA[i].getValues();
var row=rgA[i].getRow();
var col=rgA[i].getColumn();
for(var j=0;j<rvA.length;j++) {
for(var k=0;k<rvA[j].length;k++) {
fulllist.push(sh.getRange(row+j,col+k).getA1Notation());
}
}
}
var trg=sh.getRange(rgA1);
var tvA=trg.getValues();
var trow=trg.getRow();
var tcol=trg.getColumn();
var cObj={ins:[],outs:[],fully:true,partially:false};
for(var i=0;i<tvA.length;i++) {
for(var j=0;j<tvA[i].length;j++) {
var a1=sh.getRange(trow+i,tcol+j).getA1Notation();
if(fulllist.indexOf(a1)>=0) {
cObj.ins.push(a1);
}else{
cObj.outs.push(a1);
}
}
}
if(cObj.ins.length>0) {
cObj.partially=true;
}
if(cObj.outs.length>0) {
cObj.fully=false;
}
Logger.log(cObj);
Logger.log(fulllist);
return (cObj.fully)?true:false;
}
My intention is to be able to delete for example cell F1 without deleting cell F2.
var sheet = ss.getSheetByName("QuestionĂ¡rio DQSA");
var range = sheet.getRange("B1:U1");
range.clearContent();
Here I clear the content of these cells but I would like to know how to delete them.
You can use Range.deleteCells(Dimension):
var sheet = ss.getSheetByName("QuestionĂ¡rio DQSA");
var range = sheet.getRange("F1");
range.deleteCells(SpreadsheetApp.Dimension.COLUMNS);//F2 becomes the new F1
If you want to roll your own:
function deleteCell(shift) {
var shift=shift || "left"; //left or up
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var cell=ss.getActiveCell();
if(shift=="left") {
var rg=sh.getRange(cell.getRow(),1,1,sh.getLastColumn());
var vA=rg.getValues();
var row=vA[0];
row.splice(cell.getColumn()-1,1);
rg.clearContent();
sh.getRange(cell.getRow(),1,1,row.length).setValues([row]);
}
if(shift=="up") {
var rg=sh.getRange(1,cell.getColumn(),sh.getLastRow(),1);
var vA=rg.getValues();
var row=vA.map(function(r){return r[0]});
row.splice(cell.getRow()-1,1);
var col=[];
row.forEach(function(e){
col.push([e]);
});
rg.clearContent();
sh.getRange(1,cell.getColumn(),col.length,1).setValues(col);
}
}
Of course now that I know about that new method in range it's a lot easier to write. Thanks to #TheMaster
function deleteCell(shift) {
var shift=shift || "left";
var ss=SpreadsheetApp.getActive();
var cell=ss.getActiveCell();
if(shift=="left") {
cell.deleteCells(SpreadsheetApp.Dimension.COLUMNS);
}
if(shift=="up") {
cell.deleteCells(SpreadsheetApp.Dimension.ROWS);
}
}
I have searched on many forums yet and could not find this issue.
I have a script that moves a row from sheet 1 to sheet 2.
What I'm trying to achieve is that when a specific cell from sheet 1 is forgotten and left blank.
When I run the moverows() script I want to check if this row is has any empty cells and prompt with a dialog that there are still blank cells and abort the moverows() script if all the cells are not blank. Then proceed without a dialog.
I hope that you can point a direction or to a thread where there is a similar question.
I don't have enough knowledge to combine the dialog prompt with a check combine it with what I've got now:
function Moverows5() {
var ss = SpreadsheetApp.openById('sheetID');
var sourceSheet = ss.getSheetByName("sheetname1");
var targetSheet = ss.getSheetByName("sheetname 2");
var values = sourceSheet.getRange("B8:T43").getValues();
var range0 = sourceSheet.getRange("C8:K43");
var range1 = sourceSheet.getRange("Q8:T43");
var range2 = sourceSheet.getRange("P2");
var range3 = sourceSheet.getRange("R2");
var firstFreeRow = goToFirstRowAfterLastRowWithData(targetSheet, "A:AD");
//check column to whatever column you want to check
targetSheet.getRange(firstFreeRow, 1, values.length, values[0].length) .setValues(values);
range0.clearContent();
range1.clearContent();
range2.clearContent();
range3.clearContent();
createPdf()//function gets started
} //end of first function
function goToFirstRowAfterLastRowWithData(sheet, range) {
var v = sheet.getRange(range).getValues(),l = v.length,r;
while (l > 0) {
if (v[l] && v[l][0].toString().length > 0) {
r = (l + 2);
break;
} else {
l--;
}
}
return r ? r : 'no data found';
}
Check range for blanks before copying
This function checks the values array for blanks. If blanks are found it alerts the user, identifies the blank cells and terminates the function. Otherwise, it makes the transfer and clears some ranges.
function Moverows5() {
var ss=SpreadsheetApp.getActive();
var sourceSheet=ss.getSheetByName("Sheet1");
var targetSheet=ss.getSheetByName("Sheet2");
var sourceRange=sourceSheet.getRange("B8:T43");
var values=sourceRange.getValues();
var range0=sourceSheet.getRange("C8:K43");
var range1=sourceSheet.getRange("Q8:T43");
var range2=sourceSheet.getRange("P2");
var range3=sourceSheet.getRange("R2");
var firstFreeRow=targetSheet.getLastRow() + 1;
var noBlanks=true;
var bA=[];
var ro=sourceRange.getRow();
var co=sourceRange.getColumn();
for(var ri=0;ri<values.length;ri++) {
for(var ci=0;ci<values[ri].length;ci++) {
if(!values[ri][ci]) {
noBlanks=false;
bA.push(sourceSheet.getRange(ri+ro,ci+co).getA1Notation());
}
}
}
if(noBlanks) {
targetSheet.getRange(firstFreeRow,1,values.length,values[0].length).setValues(values);
range0.clearContent();
range1.clearContent();
range2.clearContent();
range3.clearContent();
//createPdf()//function gets started
}else{
SpreadsheetApp.getUi().alert('Sorry there are blanks in the following cells: ' + bA.join(', '));
return;
}
}
If you wish you may use this function to create some test data before testing on valuable spreadsheet.
function createTestData() {
var m=1;//0 for random column positions >0 for fixed position
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.clearContents();
var cols=30;//number of columns
var rows=50;//number of rows
var hpref='hdr';
var hA=[];
var hdrA=[];
var cA=[];
for(var i=0;i<cols;i++) {hA.push(i+1);};
for(var i=0;i<cols;i++) {
if(m==0) {
var index=Math.floor(Math.random() * hA.length);
}else{
var index=i;
}
var hnum=hA[index];
hdrA.push(hpref + hnum);
cA.push(hnum);
if(m==0) {
hA.splice(index,1);
}
}
sh.getRange(1,1,1,hdrA.length).setValues([hdrA]);
var rg=sh.getRange(2,1,rows,cols);
var vA=rg.getValues();
for(var i=0;i<rows;i++) {
for(var j=0;j<cols;j++) {
vA[i][j]=Number(i+1) + ',' + cA[j];
}
}
rg.setValues(vA);
sh.getRange("B8:T43").setBackground('#ff00ff');
}
Got help with my script from Cooper yet i need some modification, the script basically moverows with a custom dialog if a cell in the row is left blank.
What i like to accomplish is that only the specific cells in a row will be checked.
e.g. row 1 and 4 are mandatory and row 2 and 3 are not.
This is the code what I've got so far.
function Moverows57654() {
var ss=SpreadsheetApp.getActive();
var sourceSheet=ss.getSheetByName("sheet1");
var targetSheet=ss.getSheetByName("sheet2");
var sourceRange=sourceSheet.getRange("A2:T2");
var values=sourceRange.getValues();
var range0=sourceSheet.getRange("A2:B2");
var range1=sourceSheet.getRange("D2:E2");
var firstFreeRow=goToFirstRowAfterLastRowWithData(targetSheet, "A:AD");
var noBlanks=true;
var bA=[];
var ro=sourceRange.getRow();
var co=sourceRange.getColumn();
for(var ri=0;ri<values.length;ri++) {
for(var ci=0;ci<values[ri].length;ci++) {
if(!values[ri][ci]) {
noBlanks=false;
bA.push(sourceSheet.getRange(ri+ro,ci+co).getA1Notation());
}
}
}
if(noBlanks) {
targetSheet.getRange(firstFreeRow,1,values.length,values[0].length)
.setValues(values); targetSheet.getRange(firstFreeRow, 1, values.length, values[0].length)
.setValues(values);
range0.clearContent();
range1.clearContent();
//createPdf()//function gets started
}else{
SpreadsheetApp.getUi().alert('Sorry there are blanks in the following cells: ' + bA.join(', '));
return;
}
Try this:
function Moverows57654() {
var ss=SpreadsheetApp.getActive();
var sourceSheet=ss.getSheetByName("sheet1");
var targetSheet=ss.getSheetByName("sheet2");
var sourceRange=sourceSheet.getRange("A2:T2");
var values=sourceRange.getValues();
var range0=sourceSheet.getRange("A2:B2");
var range1=sourceSheet.getRange("D2:E2");
//var firstFreeRow=targetSheet.getLastRow() + 1;
var firstFreeRow=goToFirstRowAfterLastRowWithData(targetSheet, "A:AD");
var noBlanks=true;
var bA=[];
var skA=[1,2];//column -1
var ro=sourceRange.getRow();
var co=sourceRange.getColumn();
for(var ri=0;ri<values.length;ri++) {
for(var ci=0;ci<values[ri].length;ci++) {
if(!values[ri][ci] && skA.indexOf(ci)==-1) {
noBlanks=false;
bA.push(sourceSheet.getRange(ri+ro,ci+co).getA1Notation());
}
}
}
if(noBlanks) {
targetSheet.getRange(firstFreeRow,1,values.length,values[0].length)
.setValues(values); targetSheet.getRange(firstFreeRow, 1, values.length, values[0].length)
.setValues(values);
range0.clearContent();
range1.clearContent();
//createPdf()//function gets started
}else{
SpreadsheetApp.getUi().alert('Sorry there are blanks in the following cells: ' + bA.join(', '));
return;
}
}