Append only non empty cells to another sheet google script - google-apps-script

I want to copy only non-empty cells in column C & E & append all of them in "Update" Sheet 1st column. Below is what i tried for copy non-empty cells but it doesnt append
here is Dummy Sheet for reference
function emaillFilter(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ws = ss.getSheetByName("Email");
var updateSheet = ss.getSheetByName("Update");
var range = ws.getRange(1,5,ws.getLastRow());
var emptycells = SpreadsheetApp.newFilterCriteria().setHiddenValues(['']).build();
var filter = range.getFilter() || range.createFilter();
filter.setColumnFilterCriteria(5, emptycells);
var data = ws.getRange(2,5,ws.getLastRow()).getValues();
var array = [];
for (var i = 0; i < data.length; i++){
if(!ws.isRowHiddenByFilter(i+1)){
array.push(data[i]);
}
}
updateSheet.getRange(updateSheet.getLastRow()+1, 1, array.length).setValues(array);
}
input sheet Column C & E
desired output - paste column C & append E without blanks in column A of another sheet

How about this:
function emaillFilter(){
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName("Email");
const ush=ss.getSheetByName("Update");
const data=sh.getRange(2,1,sh.getLastRow(),5).getValues();
var array=[];
data.forEach(function(r,i){
if(r[2] && r[4]) {
array.push(r);
}
});
ush.getRange(ush.getLastRow()+1, 1, array.length,array[0].length).setValues(array);
}
Okay I think you want this based upon your comment:
desired output - paste column C & append E without blanks in column A of another sheet
But I must admit that I don't see that reflected in your example second image so we may need another iteration.
function emaillFilter(){
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName("Email");
const ush=ss.getSheetByName("Update");
const data=sh.getRange(2,1,sh.getLastRow(),5).getValues();
var array=[];
data.forEach(function(r,i){
//is columnC and columnE both truth
if(r[2] && r[4]) {
array.push([r[2] + ',' + r[4]]);
//is columnC truthy and columnE falsy
}else if(r[2] && !r[4]) {
array.push([r[2]]);
}
});
ush.getRange(ush.getLastRow()+1, 1, array.length,array[0].length).setValues(array);
}
Okay I think this is it:
function emaillFilter(){
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName("Email");
const ush=ss.getSheetByName("Update");
const data=sh.getRange(2,1,sh.getLastRow(),5).getValues();
var array1=[];
var array2=[];
data.forEach(function(r,i){
if(r[2]) {
array1.push([r[2]]);
}
if(r[4]) {
array2.push([r[4]]);
}
});
var array=array1.concat(array2);
ush.getRange(ush.getLastRow()+1, 1, array.length,array[0].length).setValues(array);
}
Thanks for the images. They really helped.
truthy
falsy

Related

' getValues() ' collecting only one value when trying to remove empty cells

My idea is to remove the diacricts from the values and send them to Column B, but also send the original values to Column C of the spreadsheet.
Column A on Spreadsheet:
ábéécÓ
Á
ábéécÓ
Á
My code:
var defaultDiacriticsRemovalMap = [
{'base':'A', 'letters':'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'},
{'base':'AA','letters':'\uA732'},
{'base':'AE','letters':'\u00C6\u01FC\u01E2'},
{'base':'AO','letters':'\uA734'},
{'base':'AU','letters':'\uA736'},
{'base':'AV','letters':'\uA738\uA73A'},
{'base':'AY','letters':'\uA73C'},
{'base':'B', 'letters':'\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'},
{'base':'C', 'letters':'\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'},
{'base':'D', 'letters':'\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0'},
{'base':'DZ','letters':'\u01F1\u01C4'},
{'base':'Dz','letters':'\u01F2\u01C5'},
{'base':'E', 'letters':'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'},
{'base':'F', 'letters':'\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'},
{'base':'G', 'letters':'\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'},
{'base':'H', 'letters':'\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'},
{'base':'I', 'letters':'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'},
{'base':'J', 'letters':'\u004A\u24BF\uFF2A\u0134\u0248'},
{'base':'K', 'letters':'\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'},
{'base':'L', 'letters':'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'},
{'base':'LJ','letters':'\u01C7'},
{'base':'Lj','letters':'\u01C8'},
{'base':'M', 'letters':'\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'},
{'base':'N', 'letters':'\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'},
{'base':'NJ','letters':'\u01CA'},
{'base':'Nj','letters':'\u01CB'},
{'base':'O', 'letters':'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'},
{'base':'OI','letters':'\u01A2'},
{'base':'OO','letters':'\uA74E'},
{'base':'OU','letters':'\u0222'},
{'base':'OE','letters':'\u008C\u0152'},
{'base':'oe','letters':'\u009C\u0153'},
{'base':'P', 'letters':'\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'},
{'base':'Q', 'letters':'\u0051\u24C6\uFF31\uA756\uA758\u024A'},
{'base':'R', 'letters':'\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'},
{'base':'S', 'letters':'\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'},
{'base':'T', 'letters':'\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'},
{'base':'TZ','letters':'\uA728'},
{'base':'U', 'letters':'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'},
{'base':'V', 'letters':'\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'},
{'base':'VY','letters':'\uA760'},
{'base':'W', 'letters':'\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'},
{'base':'X', 'letters':'\u0058\u24CD\uFF38\u1E8A\u1E8C'},
{'base':'Y', 'letters':'\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'},
{'base':'Z', 'letters':'\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'},
{'base':'a', 'letters':'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'},
{'base':'aa','letters':'\uA733'},
{'base':'ae','letters':'\u00E6\u01FD\u01E3'},
{'base':'ao','letters':'\uA735'},
{'base':'au','letters':'\uA737'},
{'base':'av','letters':'\uA739\uA73B'},
{'base':'ay','letters':'\uA73D'},
{'base':'b', 'letters':'\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'},
{'base':'c', 'letters':'\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'},
{'base':'d', 'letters':'\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'},
{'base':'dz','letters':'\u01F3\u01C6'},
{'base':'e', 'letters':'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'},
{'base':'f', 'letters':'\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'},
{'base':'g', 'letters':'\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'},
{'base':'h', 'letters':'\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'},
{'base':'hv','letters':'\u0195'},
{'base':'i', 'letters':'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'},
{'base':'j', 'letters':'\u006A\u24D9\uFF4A\u0135\u01F0\u0249'},
{'base':'k', 'letters':'\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'},
{'base':'l', 'letters':'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'},
{'base':'lj','letters':'\u01C9'},
{'base':'m', 'letters':'\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'},
{'base':'n', 'letters':'\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'},
{'base':'nj','letters':'\u01CC'},
{'base':'o', 'letters':'\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'},
{'base':'oi','letters':'\u01A3'},
{'base':'ou','letters':'\u0223'},
{'base':'oo','letters':'\uA74F'},
{'base':'p','letters':'\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'},
{'base':'q','letters':'\u0071\u24E0\uFF51\u024B\uA757\uA759'},
{'base':'r','letters':'\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'},
{'base':'s','letters':'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'},
{'base':'t','letters':'\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'},
{'base':'tz','letters':'\uA729'},
{'base':'u','letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'},
{'base':'v','letters':'\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'},
{'base':'vy','letters':'\uA761'},
{'base':'w','letters':'\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'},
{'base':'x','letters':'\u0078\u24E7\uFF58\u1E8B\u1E8D'},
{'base':'y','letters':'\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'},
{'base':'z','letters':'\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'}
];
var diacriticsMap = {};
for (var i=0; i < defaultDiacriticsRemovalMap .length; i++){
var letters = defaultDiacriticsRemovalMap [i].letters;
for (var j=0; j < letters.length ; j++){
diacriticsMap[letters[j]] = defaultDiacriticsRemovalMap [i].base;
}
}
function Looping() {
var sheet = SpreadsheetApp.getActive().getSheetByName('remove_diacritics'),
range,
values_array;
range = sheet.getRange('A1:A');
var loop = range.getValues().flat().filter(e => e);
sheet.getRange(1, 3).setValue(loop);
var new_values = [];
for (var key of loop) {
var newText = key.replace(/[^\u0000-\u007E]/g, function(a){
return diacriticsMap[a] || a;
});
new_values.push(newText);
}
sheet.getRange(1, 2).setValue(new_values);
}
Column B and C on Spreadsheet return after run the code:
abeecO ábéécÓ
Expected Result in Column B and C on Spreadsheet:
abeecO ábéécÓ
A Á
abeecO ábéécÓ
A Á
I also tried create a loop using but it didn't work:
var loop = range.getValues().filter(function(array){
return array != ''
})
What am I doing wrong that all four values are not collected?
Modification points:
When I saw your 1st submitted quesiton, you are trying to put an array of var loop = range.getValues().flat().filter(e => e); to the sheet with sheet.getRange(1, 3).setValue(loop);. In this case, 1st element of the array loop is put to the cell "C1". I thought that this is the reason of your issue. And also, at var loop = range.getValues().flat().filter(e => e);, 2 dimensional array is converted to 1 dimensional array. In this case, it it is required to modify as follows.
From
range = sheet.getRange('A1:A');
var loop = range.getValues().flat().filter(e => e);
sheet.getRange(1, 3).setValue(loop);
To
range = sheet.getRange('A1:A' + sheet.getLastRow());
var loop = range.getValues().filter(([a]) => a.toString() != "");
sheet.getRange(1, 3, loop.length, 1).setValues(loop);
By this modification, the filtered values of loop are put to the column "C".
When I saw your latest question, the same situation as the above situation can be seen. I think that it is required to modify your latest script like the above one. But, from your showing sample input and output situations, I thought that when the cell value of column "A" is empty, it might be required to put the empty.
When these points are reflected in your script, it becomes as follows.
Modified script:
In this case, please modify Looping() as follows.
function Looping() {
var sheet = SpreadsheetApp.getActive().getSheetByName('remove_diacritics');
var range = sheet.getRange('A1:A' + sheet.getLastRow());
var loop = range.getValues();
var new_values = [];
for (var key of loop) {
var value = key[0];
if (value != "") {
var newText = value.replace(/[^\u0000-\u007E]/g, function (a) {
return diacriticsMap[a] || a;
});
new_values.push([newText, value]);
} else {
new_values.push(["", ""]);
}
}
sheet.getRange(1, 2, new_values.length, new_values[0].length).setValues(new_values);
}
Or, you can also the following modified script.
function Looping() {
var sheet = SpreadsheetApp.getActive().getSheetByName('remove_diacritics');
var values = sheet.getRange('A1:A' + sheet.getLastRow()).getValues();
var new_values = values.map(([v]) => [v.toString() != "" ? v.replace(/[^\u0000-\u007E]/g, a => diacriticsMap[a] || a) : "", v]);
sheet.getRange(1, 2, new_values.length, new_values[0].length).setValues(new_values);
}
When these modified scripts are used, your expected result is obtained. And, in this modification, when the cell value of column "A" is empty, the empty values are put to the columns "B" and "C".
If you want to skip the empty rows of the column "A", please modify var loop = range.getValues(); in the above 2 scripts as follows.
function Looping() {
var sheet = SpreadsheetApp.getActive().getSheetByName('remove_diacritics');
var range = sheet.getRange('A1:A' + sheet.getLastRow());
var loop = range.getValues().filter(([a]) => a.toString() != "");
var new_values = [];
for (var key of loop) {
var newText = key[0].replace(/[^\u0000-\u007E]/g, function (a) {
return diacriticsMap[a] || a;
});
new_values.push([newText, key[0]]);
}
sheet.getRange(1, 2, new_values.length, new_values[0].length).setValues(new_values);
}
Or
function Looping() {
var sheet = SpreadsheetApp.getActive().getSheetByName('remove_diacritics');
var values = sheet.getRange('A1:A' + sheet.getLastRow()).getValues();
var new_values = values.flatMap(([v]) => v.toString() != "" ? [[v.replace(/[^\u0000-\u007E]/g, a => diacriticsMap[a] || a), v]] : []);
sheet.getRange(1, 2, new_values.length, new_values[0].length).setValues(new_values);
}
References:
setValue(value)
setValues(values)
map()
Getting all of column one
Using ranges like A1:A is not useful because it returns nulls from lastrow to maxrows which need to be filtered out which is just a waste of time.
function Looping() {
const ss = SpreadsheetApp.getActive();
const sheet = ss.getSheetByName('Sheet0');
const vs = sheet.getRange('A1:A' + sheet.getLastRow()).getValues();
Logger.log(JSON.stringify(vs));
}
Execution log
5:43:28 PM Notice Execution started
5:43:27 PM Info [["ábéécÓ"],["Á"],["ábéécÓ"],["Á"]]//2D array
5:43:29 PM Notice Execution completed
Original Data:
A
ábéécÓ
Á
ábéécÓ
Á

How to loop through each cell in column?

The script simply adds 1 to the cell in a specific column, but I'd like it to +1 to every cell in a specific column with a set delay.
This is what I've gathered so far, but need that extra step.
function plus() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var yesCount = ss.getRange("B4");
var yesAdd = yesCount.getValue();
if(yesAdd != ""){
yesCount.setValue(yesAdd+1);
Utilities.sleep(1000);
}
}
Basically B4 should be the entire B column and I'd like to step through each (non-empty) cell wait for one or two second and move on to the next cell.
Note that the spreadsheet may not be updated immediately every time you change the value.
function plus() {
const row = 4;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Sheet Name');
const rows = sheet.getLastRow() - row + 1;
const range = sheet.getRange(row, 2, rows, 1);
const values = range.getValues().flat();
const matches = {};
values.forEach((value, i) => {
if (value !== '') {
sheet.getRange(row + i, 2).setValue(value + 1);
Utilities.sleep(1000);
}
});
}

loop through 2 google sheets

Goodday,
I have 2 sheets. For each ID on sheet1 I need to verify if that ID is also on sheet2 AND if Date Processed is blank.
If both condition are true > today's date should be set in Date Processed.
I've managed to do so for just 1 value (A2) from sheet1.
What I need is a way to go through all the values in sheet1. Ideally the row in sheet1 would also get deleted (not sure if that is possible)
This is my code till now
function myMatch(){
var file = SpreadsheetApp.getActiveSpreadsheet();
var ss = file.getSheetByName("Sheet1");
var ws = file.getSheetByName("Sheet2");
var wsData = ws.getDataRange().getValues();
var mySearch = ss.getRange("A2").getValue();
for(var i = 0; i < wsData.length; i++){
if(wsData[i][1] == mySearch && wsData[i][2] == "")
{
ws.getRange(i+1,3).setNumberFormat('dd"-"mmm"-"yyyy').setValue(new Date());
}
}
}
Your help is really appreciated as I have been trying and searching for a solution for 2 days now. Thank you
I know it doesn't makes much sense. Muhammet's code works and looks just fine. But, rather for fun and educational purposes, here is another "functional" solution:
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const s1 = ss.getSheetByName('Sheet1');
const s2 = ss.getSheetByName('Sheet2');
// get data from Sheet1 and Sheet2
const s1_data = s1.getDataRange().getValues().slice(1,);
const s2_data = s2.getDataRange().getValues().slice(1,);
// get IDs from data of Sheet1
const IDs = s1_data.map(x => x[0]);
const IDs_to_delete = []; // here will be IDs to delete
// function checks and fill a row and adds ID to array to delete
const write_date = (id,row) => {
if (row[1] == id && row[2] == '') {
IDs_to_delete.push(id);
row[2] = new Date();
}
}
// change rows within data of Sheet 2
IDs.forEach(id => s2_data.forEach(row => row = write_date(id,row)));
// clear and fill Sheet 2
s2.getDataRange().offset(1,0).clearContent();
s2.getRange(2,1,s2_data.length,s2_data[0].length).setValues(s2_data);
// remove rows from data of Sheet 1
const s1_data_new = s1_data.filter(row => !IDs_to_delete.includes(row[0]));
// clear and fill Sheet 1 with new data
s1.getDataRange().offset(1,0).clearContent();
s1.getRange(2,1,s1_data_new.length,s1_data_new[0].length).setValues(s1_data_new);
}
The only improvements over Muhamed's code is that this implementation removes processed rows from Sheet1. And, I believe, it will work faster for huge lists, because it doesn't use getRange() and setValue() on every found cell but fills all cells of the sheet at once with setValues() method.
You need a loop for this. Use
var mySearchs = ss.getRange('A2:A').getValues();
and loop through all values of this array.
function myMatch(){
var file = SpreadsheetApp.getActiveSpreadsheet();
var ss = file.getSheetByName("Sheet1");
var ws = file.getSheetByName("Sheet2");
var wsData = ws.getDataRange().getValues();
var mySearchs = ss.getRange('A2:A').getValues();
mySearchs.forEach((v) => {
for(var i = 0; i < wsData.length; i++){
if(wsData[i][1] == v && wsData[i][2] == "")
{
ws.getRange(i+1,3).setNumberFormat('dd"-"mmm"-"yyyy').setValue(new Date());
}
}
})
}

How to iterate through a range and build a "table" based on a criteria, using Google Apps Script?

I got the following table to populate (range D6:J15) as I search the data in another sheet, based on a date criteria found in row 4:
This is where I'm to look for the data, considering Col A as the basis for the criteria:
My difficulty is to concatenate the data, as they meet the criteria.
This is the code I'm working on:
/* #OnlyCurrentDoc */
function editarPrevProd() {
const lock = LockService.getScriptLock();
lock.tryLock(3000);
if (lock.hasLock()) {
var sourceSheet = 'PrevProdDB2';
var destinationSheet = 'Previsão Entreposto';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sourceSheet);
var ActiveSheetName = ss.getActiveSheet().getName();
var LastRowSource = sheet.getLastRow();
var LastColumnSource = sheet.getLastColumn();
var values = sheet.getRange(2,1,LastRowSource,9).getValues();
var csh = ss.getSheetByName(destinationSheet);
var itens = csh.getRange("I40:J57");
var data = [];
var weekNo = csh.getRange("B4").getValue();
var weekDates = csh.getRange("D4:J4").getValues();
if (weekNo == "") {
Browser.msgBox("Escolher uma data e tente novamente!");
return;
}
//var clearRng = ["K34:K35", "N34:N35", "I40:K"];
//csh.getRangeList(clearRng).clearContent();
for (var i = 0; i < values.length; i++) {
if (values[i][7] == weekNo) {
data.push(values[i]);
//break;
}
}
var dias = 0;
var prevData = [];
for (var j = 0; j < weekDates.length; j++) {
dias = dias + 1;
Logger.log("Dias da Semana: " + dias);
for (var a = 0; a < data.length; a++) {
if (weekDates[j].valueOf() == data[a][0].valueOf()){
prevData.push(data[a][4]);
}
}
}
//map columns whose data will be set in the header.
var user = data.map(function(e){return e[5];});
var lastUpdate = data.map(function(e){return e[6];});
//Copy data array to destination sheet
csh.getRange("I1").setValue(user);
csh.getRange("I2").setValue(lastUpdate);
//csh.getRange("E6").setValue(timeStamp);
//If you wanted to set arrays in the form of
//a table, you'd use this below instead
var seg = data.map(function(e) {return [e[3]];});
var ter = data.map(function(e) {return [e[4]];});
var qua = data.map(function(e) {return [e[5]];});
var qui = data.map(function(e) {return [e[6]];});
var sex = data.map(function(e) {return [e[7]];});
var sab = data.map(function(e) {return [e[8]];});
var dom = data.map(function(e) {return [e[9]];});
//csh.getRange(6,4,data.length,1).setValues(seg);
lock.releaseLock();
}
}
Here's a sample of the file. Note that the gs file I'm working on is named SalvaPrevProducao.
https://docs.google.com/spreadsheets/d/1NOWkzQIAPPdZdxeeTR7Id2v8LR00_u06uPhHs3tzLuU/edit?usp=sharing
I believe your goal as follows.
You want to convert the above image to the bottom image using Google Apps Script.
The date header is the cells "D4:J4".
The source values are the cells "A6:M".
The column "M" of ID is Semana in the destination sheet.
In this case, I would like to propose the following flow.
Retrieve values from the source sheet.
Create an array for putting to the destination sheet.
Put the array to the destination sheet.
When this flow is reflected to the Google Apps Script, it becomes as follows.
Sample script:
Before you use this script, please set the variables of srcSheetName and dstSheetName.
function editarPrevProd() {
const srcSheetName = "Data Source"; // This is the source sheet name.
const dstSheetName = "destSheet"; // Please set the destination sheet name.
// This is from https://stackoverflow.com/a/44563639
Object.prototype.get1stNonEmptyRowFromBottom = function (columnNumber, offsetRow = 1) {
const search = this.getRange(offsetRow, columnNumber, this.getMaxRows()).createTextFinder(".").useRegularExpression(true).findPrevious();
return search ? search.getRow() : offsetRow;
};
// 1. Retrieve values from the source sheet.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const srcSheet = ss.getSheetByName(srcSheetName);
const lastRow = srcSheet.get1stNonEmptyRowFromBottom(1);
const [[, , , ...header1], header2, ...srcValues] = srcSheet.getRange("A4:M" + lastRow).getValues();
// 2. Create an array for putting to the destination sheet.
const values = header1.reduce((ar, h, i) => {
srcValues.forEach(([a, b, c, ...dm]) => ar.push([h, a, b, c, dm[i] || 0, "", "", dm.pop(), h]));
return ar;
}, [["Data", "Tipo", "Cod", "Descrição", "Qtd", "Usuário", "TimeStamp", "Semana", "Data"]]);
// 3. Put the array to the destination sheet.
const dstSheet = ss.getSheetByName(dstSheetName);
dstSheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
When above script is run, the values are retrieved from srcSheetName and the converted values are put to dstSheetName .
Result:
When above script is run, the following result is obtained.
Note:
Unfortunately, from your question and sample Spreadsheet, I couldn't understand about Usuário and TimeStamp of the columns "F" and "G". At the sample output situation of Turn the data from the left into the format on the right side, Usuário and TimeStamp have no values.
References:
reduce()
forEach()
It is unclear why you would need to resort to scripting to look up those values, when a filter() formula would seem capable to do the same. Try this formula in cell D6:
=sum( iferror( filter(PrevProdDB2!$E$2:$E, PrevProdDB2!$B$2:$B = $A6, PrevProdDB2!$H$2:$H = $B$4, PrevProdDB2!$I$2:$I = D$4) ) )

How can I check if a numerical value is within a range of cells in google sheets?

I would like to find if a certain value is in a range using app scripts for google sheets.
var sheet = SpreadsheetApp.getActiveSheet();
var rangeBikeNumbers = sheet.getDataRange("A5:A5000");
var values = rangeBikeNumbers.getValues();
If I have my range rangeBikeNumbers, how can I check if the number "42" for example is in that range. I have searched for hours now and have beeb unable to find any answer to this. indexOf only seems to return -1, regardless of whether or not the value is in the range.
var indexDataNumber = values.indexOf(42); for example always ends up being -1
I believe your goal as follows.
You want to check whether the value of 42 is existing in the range of A5:A5000.
In this case, I would like to propose to use TextFinder. Because when TexiFinder is used, the process cost is low. Ref By the way, getDataRange has not arguments. From your script, I thought that you might want var rangeBikeNumbers = sheet.getRange("A5:A5000");.
When this is reflected to your script, it becomes as follows.
Modified script:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var rangeBikeNumbers = sheet.getRange("A5:A5000");
var find = rangeBikeNumbers.createTextFinder("42").matchEntireCell(true).findNext();
if (find) {
// In this case, the value of 42 is existing in the range.
} else {
// In this case, the value of 42 is NOT existing in the range.
}
}
Note:
About var indexDataNumber = values.indexOf(42); for example always ends up being -1, I think that the reason of this issue is due to that values is 2 dimensional array. If you want to use this, you can also use the following script.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var rangeBikeNumbers = sheet.getRange("A5:A5000");
var values = rangeBikeNumbers.getValues();
var find = values.map(([e]) => e).indexOf(42); // of values.flat().indexOf(42);
if (find > -1) {
// In this case, the value of 42 is existing in the range.
} else {
// In this case, the value of 42 is NOT existing in the range.
}
}
References:
Benchmark: Process Costs for Searching Values in Spreadsheet using Google Apps Script
getDataRange()
getRange(a1Notation)
createTextFinder(findText)
Select any active range that you wish to search and it will search for the seed in that at range. The seed is currently defaulted to 42 but you can change it.
function findSeedInRange(seed = 42) {
const ui = SpreadsheetApp.getUi();
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const rg = sh.getActiveRange();
const row = rg.getRow();
const col = rg.getColumn();
var found = false;
rg.getValues().forEach((r, i) => {
r.forEach((c, j) => {
if (c == seed) {
let r = sh.getRange(i + row, j + col).getA1Notation();
ui.alert(`Found ${seed} in ${r}`);
found = true;
}
})
})
if(!found) {
ui.alert(`Did not find ${seed}`);
} else {
ui.alert('That is all.')
}
}
Here's another approach:
function findSeedInRange() {
const ui = SpreadsheetApp.getUi();
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const rg = sh.getActiveRange();
const resp = ui.prompt('Enter Seed', 'Enter Seed', ui.ButtonSet.OK_CANCEL)
if (resp.getSelectedButton() == ui.Button.OK) {
var seed = parseInt(resp.getResponseText());
const row = rg.getRow();
const col = rg.getColumn();
var found = false;
rg.getValues().forEach((r, i) => {
r.forEach((c, j) => {
if (c == seed) {
let r = sh.getRange(i + row, j + col).getA1Notation();
ui.alert(`Found ${seed} in ${r}`);
found = true;
}
});
});
if (!found) {
ui.alert(`Did not find ${seed}`);
} else {
ui.alert('That is all.')
}
} else {
ui.alert('Operation cancelled.')
}
}