Delete only certain values not all values - google-apps-script

The script deletes all values in the selected cells. I would like to write in exceptions if the value is something I don't want to be deleted.
Haven't tried anything because I'm not that good.
function Gtown() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('O38:P39').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('A38:B39').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('O26:P27').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('I26:J27').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('G26:H27').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('A26:B27').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('O16:P17').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('I16:J17').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('G16:H17').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('A16:B17').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('O6:P7').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('I6:J7').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('G6:H7').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('A6:B7').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
};
No messages. I only want to delete certain values.

First of all, please, use a loop! Right now your script is very "heavy":
function Gtown() {
var ss = SpreadsheetApp.getActive();
var rl = ss.getRangeList(['A1:A5','B1:B5']); //put any Range references here;
var rs = rl.getRanges();
var opts = {contentsOnly: true, skipFilteredRows: true};
rs.forEach(function(range){
range.clear(opts);
});
}
Then, inside the forEach "loop", instead of unconditional cleanup, wrap clear() method in an if...else statement (Range values can be accessed via getValue() or getValues() method calls)

Try this:
function clearSelectedLocations() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rA=['O38:P39','A38:B39','O26:P27','I26:J27','G26:H27','A26:B27','O16:P17','I16:J17','G16:H17','A16:B17','O6:P7','I6:J7','G6:H7','A6:B7'];
var rgA=sh.getRangeList(rA).getRanges();
for(var i=0;i<rgA.length;i++) {
rgA[i].clear({contentsOnly: true, skipFilteredRows: true});
}
}
Try this:
function clearSelectedLocations() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var vA=rg.getValues()
for(var i=0;i<vA.length;i++) {
if(sh.isRowHiddenByFilter(i+1)) {
continue;
}else{
for(var j=0;j<vA[i].length;j++) {
if(vA[i][j].toString()=="On Duty") {
sh.getRange(i+1,j+1).clear({contentsOnly: true});
}
}
}
}
If you have more than one values to clear:
function clearSelectedLocations() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var vA=rg.getValues();
var clA=["On Duty"];
for(var i=0;i<vA.length;i++) {
if(sh.isRowHiddenByFilter(i+1)) {
continue;
}else{
for(var j=0;j<vA[i].length;j++) {
if(clA.indexOf(vA[i][j].toString())>-1) {
sh.getRange(i+1,j+1).clear({contentsOnly: true});
}
}
}
}

Related

Google Sheets App Scripts If Else doesn't work

I have created the following app script in my google sheets but its returning always true. why is that?
if (Dsheet.getRange('A3').isBlank) {
Logger.log('true');
var dest = Dsheet.getRange('A1')
source.copyTo (dest, {formatOnly: true});
source.copyTo (dest, {contentsOnly: true});
} else {
Logger.log('false');
var lastRow = Dsheet.getLastRow()+5;
var dest = Dsheet.getRange('A' + lastRow )
source.copyTo (dest, {formatOnly: true});
source.copyTo (dest, {contentsOnly: true});
}
You have to call the function using ()
if (Dsheet.getRange('A3').isBlank())

Google Sheets script to archive data

I have created a Google Sheet for an in game Estate Agency.
The first tab "Residential Appraisal" is the data input form, and with the click of a button I want the data entered (C16:C56) to be archived on "Residential Appraisal Archive" on the next available row.
When the data is pasted it will need to be pasted as transposed and values only (due to formulas).
I am very new to the scripting side of things and have attempted to figure it out myself but got nowhere of any note. Please find the link below to the sheet.
https://docs.google.com/spreadsheets/d/1BF4Ao8L7FfitZFGX7QDfqbthmiu2A7CKXuJw0Av-0jY/edit?usp=sharing
Code:
function Reset_Residential() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('C16:C20').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C22').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C23').activate();
spreadsheet.getCurrentCell().setValue('10');
spreadsheet.getRange('C24').activate();
spreadsheet.getCurrentCell().setValue('Undetermined');
spreadsheet.getRange('C28:C38').activate();
spreadsheet.getActiveRangeList().check();
spreadsheet.getActiveRangeList().uncheck();
spreadsheet.getRange('C39:40').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C45').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C50').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C52').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
};
function Reset_Buisness() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('C16:C21').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C23').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C24').activate();
spreadsheet.getCurrentCell().setValue('10');
spreadsheet.getRange('C25').activate();
spreadsheet.getCurrentCell().setValue('Undetermined');
spreadsheet.getRange('C26').activate();
spreadsheet.getCurrentCell().setValue('Please Select');
spreadsheet.getRange('C30:C31').activate();
spreadsheet.getActiveRangeList().check();
spreadsheet.getActiveRangeList().uncheck();
spreadsheet.getRange('C32:C33').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C38').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C43').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('C45').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
};
function jumpToFirstEmptyBasic() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Appraisal Archive"); // << Change the sheet name to your own sheet.
var lastRow = sheet.getLastRow();
sheet.getRange(lastRow+1,1).activate();
}
function Residential_Archive() {
const ss = SpreadsheetApp.getActive();
const sourceRange = ss.getRange('Residential Appraisal!C16:C56');
const targetRange = ss.getRange('Results Historic!' + ss.getRange('Audit correction!Y3').getValue());
sourceRange.copyTo(targetRange, SpreadsheetApp.CopyPasteType.PASTE_VALUES, true);
showMessage_('Values copied.');
}
I believe your goal is as follows.
You want to copy the values from the cells "C16:C56" of "Residential Appraisal" sheet to the sheet "Residential Appraisal Archive". At this time, you want to copy only the values without including the formulas.
You want to run the script when a button is clicked.
When I saw your sheets of "Residential Appraisal" and "Residential Appraisal Archive", I could confirm the cells "C16:C56" of "Residential Appraisal", and I also confirmed that the sheet "Residential Appraisal Archive" has the empty columns of "F", "J", "L", "Z", "AF", and "AH". In this case, I thought that the values can be directly retrieved from the cells "C16:C56" and copy them to the destination sheet.
And also, I noticed that in your Spreadsheet, there are 2 pairs of source and destination sheets.
source sheet: "Residential Appraisal", destination sheet: "Residential Appraisal Archive"
source sheet: "Buisness Appraisal", destination sheet: "Buisness Appraisal Archive"
I thought that you might have wanted to use this script for the above 2 pairs. So in this answer, I would like to propose a sample script that can use these 2 pairs.
Sample script:
Please copy and paste the following script to the script editor of the Spreadsheet. And, please assign the function name of "sample" to the "Archive" button on the sheets of "Residential Appraisal" and "Buisness Appraisal". By this, when you click the button at "Residential Appraisal", the values are copied to the sheet "Residential Appraisal Archive". And, when you click the button at "Buisness Appraisal", the values are copied to the sheet "Buisness Appraisal Archive".
function sample() {
const obj = [
{srcSheetName: "Residential Appraisal", dstSheetName: "Residential Appraisal Archive"},
{srcSheetName: "Buisness Appraisal", dstSheetName: "Buisness Appraisal Archive"}
];
const ss = SpreadsheetApp.getActiveSpreadsheet();
const currentSheet = ss.getActiveSheet().getSheetName();
const sheet = obj.filter(({srcSheetName}) => srcSheetName == currentSheet);
if (sheet.length == 0) return;
const src = ss.getSheetByName(currentSheet);
const dst = ss.getSheetByName(sheet[0].dstSheetName);
src.getRange("C16:C56").copyTo(dst.getRange(dst.getLastRow() + 1, 1), SpreadsheetApp.CopyPasteType.PASTE_VALUES, true);
}
Note:
If you don't want to use this script at the sheet "Buisness Appraisal", please remove the function name from the button on the sheet "Buisness Appraisal".
Reference:
copyTo(destination, copyPasteType, transposed)

Copy and Past NamedRange/Whole Line

I've been using the script below to copy and paste all previous rows in an inserted row before on Google Sheets.
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('20:20').activate();
spreadsheet.getActiveSheet().insertRowsBefore(spreadsheet.getActiveRange().getRow(), 1);
spreadsheet.getActiveRange().offset(0, 0, 1, spreadsheet.getActiveRange().getNumColumns()).activate();
spreadsheet.getRange('21:21').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
spreadsheet.getRange('L20').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('H20').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
};
As I will have insertions below each other, whenever I use the top ones will change the line to be copied to the others. I would like to remove dependency on expression ('20:20'), and a think that NamedRange is the way.
Is it possible to copy the values of a whole row or named range in one sheet and paste them in the same sheet, just creating a line above?
Using the Porperties Service [1] you can fix your problem, I edited the code linked to your example Spreadsheet as follows:
function PlusMP() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('5:5').activate();
spreadsheet.getActiveSheet().insertRowsBefore(spreadsheet.getActiveRange().getRow(), 1);
spreadsheet.getActiveRange().offset(0, 0, 1, spreadsheet.getActiveRange().getNumColumns()).activate();
spreadsheet.getRange('6:6').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
spreadsheet.getRange('L5').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('H5').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
//Set offset property
var scriptProperties = PropertiesService.getScriptProperties();
var offset = Number(scriptProperties.getProperty('offset'));
if ( offset == null) {
scriptProperties.setProperty('offset', 1);
}
else {
scriptProperties.setProperty('offset', offset + 1);
}
};
function PlusCOMP() {
//Get offset property
var scriptProperties = PropertiesService.getScriptProperties();
var offset = Number(scriptProperties.getProperty('offset'));
if(offset == null) {
offset = 0;
}
var row = 10 + offset;
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange(row + ':' + row).activate();
spreadsheet.getActiveSheet().insertRowsBefore(spreadsheet.getActiveRange().getRow(), 1);
spreadsheet.getActiveRange().offset(0, 0, 1, spreadsheet.getActiveRange().getNumColumns()).activate();
spreadsheet.getRange(row + ':' + row).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
spreadsheet.getRange('L' + row).activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('H' + row).activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
};
function resetOffset() {
PropertiesService.getScriptProperties().setProperty('offset', 0);
}
When the PlusMP function is run it'll set or update the offset property, and when PlusCOMP function is run it'll use the same offset property to insert the rows accordingly.
[1] https://developers.google.com/apps-script/reference/properties/properties

Borders when row has data but no border if empty

I have a sheet that I want to dynamically add borders to filter results. I have it working where it adds the borders, but when i select another filter it keeps the rows with previous data borders. So if data set is smaller it has all empty borders under it. How would I fix this with this script?
function onEdit(ss) {
var classeur = SpreadsheetApp.getActiveSpreadsheet();
var ss = classeur.getActiveSheet();
var range = ss.getRange("A5:a"); // Modified
range.setBorder(false, false, false, false, false, false);
var values = range.getValues();
var offsetRow = range.getRowIndex(); // Added
for (var i = 0; i < values.length; i++) {
if (values[i][0]) { // Modified
ss.getRange("A" + (i + offsetRow) + ":P" + (i + offsetRow))
.setBorder(true, true, true, true, true, true, "black",
SpreadsheetApp.BorderStyle.SOLID_MEDIUM) // Modified
.setBackground('#FFFFFF');
}
}
}
Try this:
function onEdit(e) {
var sh=e.range.getSheet();
sh.getRange(1,1,sh.getMaxRows(),sh.getMaxColumns()).setBorder(false, false, false, false, false, false);
var range = sh.getRange(5,1,sh.getLastRow()-4,1); // Modified
range.setBorder(false, false, false, false, false, false);
var values = range.getValues();
for (var i=0;i<values.length;i++) {
if (values[i][0]) { // Modified
sh.getRange(i+5,1,1,16).setBorder(true, true, true, true, true, true, "black",SpreadsheetApp.BorderStyle.SOLID_MEDIUM).setBackground('#FFFFFF');
}
}
}
You cannot call this function from the script editor unless you supply the event object.

How to Clear all row range rows

I would like to know how to clear the contents of all lines that are being hidden through this code, specifically in the two IFS.
I tried to include this excerpt:
ss.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});}
but it is only cleaning the contents of the selected cell itself
function remcausa() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var cell=sh.getActiveCell();
var row=cell.getRow();
if (row<47) {
sh.hideRows(row + 0, 4);ss.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});}
else { if(row>50) {sh.hideRows(row -1, 4)};
ss.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});}
}
the expected result would be to clear the contents of all the lines being hidden.
Thanks
How about this?
function remcausa() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var cell=sh.getActiveCell();
var row=cell.getRow();
if (row<47) {
sh.hideRows(row, 4);
sh.getRange(row,1,4,sh.getLastColumn()).clearContent();
}else if(row>50) {
sh.hideRows(row-1, 4);
sh.getRange(row-1,1,4,sh.getLastColumn()).clearContent();
}
}