This question already has answers here:
Long processing time likely due to getValue and cell inserts
(2 answers)
Closed 8 months ago.
I have a code working fine but not optimized (I am new to Google App script).
This code is doing the following :
Get data from external URL
Filter the data
Parse data in sheets contained in a folder
Change columns header
Appen content in a specific column
function myfunction() {
var keywords = ["valuetoremove1", "valuetoremove2"]; // filter the column "C".
// Retrieve CSV data.
var csvUrl = "https://myurl";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent, ";");
// Retrieve Spreadsheet and put the CSV data.
var root = DriveApp.getFoldersByName("Folder1");
while (root.hasNext()) {
var folder = root.next();
var files = folder.getFiles();
while (files.hasNext()) {
var spreadsheet = SpreadsheetApp.open(files.next());
var name = spreadsheet.getName().toUpperCase();
var values = csvData.reduce((ar, r) => {
if (!keywords.some(e => r[2].toUpperCase().includes(e.toUpperCase())) && r.join("").toUpperCase().includes(name)) {
ar.push(r);
}
return ar;
}, []);
if (values.length == 0) continue;
var sheet = spreadsheet.getSheets()[0];
sheet.clearContents().getRange(2, 1, values.length, values[0].length).setValues(values);
// modify column titles
var cell = sheet.getRange(1,1);
cell.setValue("Column1");
var cell = sheet.getRange(1,2);
cell.setValue("Column2");
var cell = sheet.getRange(1,3);
cell.setValue("Column3");
var cell = sheet.getRange(1,4);
cell.setValue("Column4");
var cell = sheet.getRange(1,5);
cell.setValue("Column5");
// Modify column E
var dataRange = spreadsheet.getDataRange().getValues();
var colData = [];
for (var i = 1; i < dataRange.length; i++) {
colData.push(dataRange[i][0]);
}
for (var i = 0; i < colData.length; i++) {
// Get column E
var comments_cell = spreadsheet.getDataRange().getCell(i + 2, 5).getValue();
// Append
spreadsheet.getDataRange().getCell(i + 2, 5).setValue('<button type="button">Button</button>');
}
}
}
}
It works but it takes ages, especially the last part, the lines are being changed one by one.
Is there any way to make it much faster ?
Thanks
Try (after // Modify column E)
var dataRange = spreadsheet.getDataRange().getValues()
for (var i = 1; i < dataRange.length; i++) {
// Get column E
var comments_cell = dataRange[i][4];
dataRange[i][4] = '<button type="button">Button</button>'
}
spreadsheet.getDataRange().setValues(dataRange)
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Ó
Á
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) ) )
I am trying to consolidate data from multiple tabs into a consolidated sheet. Each tab is an individual form and has the same format. On the consolidated sheet, I want to re-arrange the data so the data field name is in a column, and data values are in rows. I tried the following:
function consolidateData(){
// defined all variables
var sheetNames = [];
var dataSheet = [];
var dataValues = [];
var conso=[];
var header = [["Faculty Name","Faculty ID","Date of Joining"]];
var ws = SpreadsheetApp.getActiveSpreadsheet();
// get all sheets
var allsheets = ws.getSheets();
for(var s in allsheets)
var sheet = allsheets[s];
sheetNames[s] = sheet.getName();
dataSheet[s] = ws.getSheetByName(sheetNames[s]);
// writing data into new sheet
var newSheet = ws.insertSheet().setName("Consolidated_Data");
newSheet.getRange("A1:C1").setValues(header);
var name = dataSheet[s].getRange("B1").getValue();
var id = dataSheet[s].getRange("B3").getValue();
var doj = dataSheet[s].getRange("B5").getValue();
var faculty = [(name),(id),(doj)];//convert into array
var facultycount = faculty.length;
for (var i = 0; i < faculty.length; i++)
//Loop through all rows and write them out starting on ROW2
{
newSheet.getRange(2 + i, 1).setValue(faculty[0]);//
newSheet.getRange(2 + i, 2).setValue(faculty[1]);//
newSheet.getRange(2 + i, 3).setValue(faculty[2]);//
}
}
There are four tabs and I expect to see results from each tab in the Consolidated_Data tab. But I only saw the last tab data got inserted repeatedly. Can anyone help? Thank you. Consolidated Data Sheet Example of an individual tab
While traversing through all your sheets, you haven't used curly braces after the for loop -
for(var s in allsheets)
So it's running the loop and the value of s stays at the last index of allsheets.
However, might I suggest a simplified version I have tested out -
function consolidateData () {
const headers = ["Faculty Name", "Faculty ID", "Date of joining"];
const rows = { "name": 0, "id": 2, "doj": 4 };
const consolidatedSheetName = "Consolidated_Data";
const ss = SpreadsheetApp.getActive();
const sheets = ss.getSheets();
let consolidatedValues = [];
// Setting headers
consolidatedValues.push(headers);
// Fetching values
for(let sheet of sheets) {
if(sheet.getName()==consolidatedSheetName) { continue; }
let data = sheet.getRange("B1:B5").getValues();
let faculty = [ data[rows.name][0], data[rows.id][0], data[rows.doj][0] ];
consolidatedValues.push(faculty);
}
// Adding to sheet
let consolidatedSheet = ss.getSheetByName(consolidatedSheetName);
if(!consolidatedSheet) {
consolidatedSheet = ss.insertSheet().setName(consolidatedSheetName);
}
let range = consolidatedSheet.getRange(1, 1, consolidatedValues.length, consolidatedValues[0].length); // 1, 1, 3, 3
range.setValues(consolidatedValues);
}
Issue:
The script is overwriting the same range here:
newSheet.getRange(2 + i, 1).setValue(faculty[0]);
Solution:
Add 1 for each row added:
newSheet.getRange(2 + i + s, 1).setValue(faculty[0]);
Or use sheet#appendRow()
newSheet.appendRow(faculty);
If you practice best practices, Your script can be simplified like this:
const consolidate = () => {
const ws = SpreadsheetApp.getActiveSpreadsheet(),
oldSheets = ws.getSheets(),
newSheet = ws.insertSheet().setName('Consolidated_Data');
newSheet.getRange(1, 1, 1 + oldSheets.length * 3, 3).setValues([
['Faculty Name', 'Faculty ID', 'Date of Joining'],
...oldSheets.map(sheet =>
sheet
.getRange('B1:B5')
.getValues()
.reduce((a, c, i) => (i % 2 === 0 ? [...a, c[0]] : a), [])
),
]);
};
I have script that searches through an entire workbook for a specific name and returns all the data on that name. The script works, but only collects data from 1 sheet within the workbook.
I searched for some code to assist me getting all the sheet names. So I have code that does that, but for some reason it still only returns from 1 sheet.
The code below collects all the sheet names.
This function is then called in the query function.
I Suspect that this is where the issue is occuring
function sheetnames() {
var out = new Array()
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i=0 ; i < sheets.length ; i++) {
var name = sheets[i].getName();
var data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(name);
var values = data.getRange(4, 1, data.getLastRow(),
data.getLastColumn()).getValues();
out.push(values);
}
return out;
}
This function then searches for the requested data.
function query() {
var Sheet = SpreadsheetApp.getActiveSpreadsheet();
var searchSheet = Sheet.getSheetByName("Search");
var searchByName = searchSheet.getRange(4, 8).getValue();
var uses = sheetnames();
var output = new Array();
var i = 0;
var r = 0;
do{
var from = uses[i];
do{
var row = from[r];
if(row == null){
r++;
continue;
}
if(searchByName != null ){
var newName = row[7];
if(newName == searchByName){
output.push(row);
}
}
r ++;
}while(r < from.length);
i ++;
}while(i < uses.length);
return output;
}
This part just prints the data into the cells and is attached to a search drawing, which runs the function in the sheet.
function search() {
var Sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Search");
var data = query();
var count1 = 0;
do{
var subData = data[count1];
var count2 = 0;
do{
var setTo = subData[count2];
Sheet.getRange((count1 + 5), (count2 + 1)).setValue(setTo);
count2 ++;
}while(count2 < subData.length);
count1 ++;
}while(count1 < data.length);
}
The sheet is called the "Daily Payments Sheet." As you can imagine there is A LOT of data. Each sheet name is named by the month and the year that the payment occurred. The more consistent customers would obviously make purchases in more than one month.
So when searching for a customers name, I only get 1 month (1 sheet's data) returned. We have data from May 2018 till date, so again, the script doesn't collect from all the sheets.
Your code is not very readable so I figured some things on my own and simplified it. Things I assume - your search term is in 'Search' sheet column H4 and you want to search all sheets for this term in H4 column and write those out in 'Search' sheet after 4th row. Try this.
// return all rows from all sheets except Search sheet
function sheetValues(ss) {
var out = [];
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
var sheet = sheets[i];
if (sheet.getName() == 'Search') continue;
var values = sheet.getRange(4, 1, sheet.getLastRow() - 3, sheet.getLastColumn()).getValues();
out.concat(values);
}
return out;
}
// search all rows for given term and return results
// look for term in H column of every row
function query(ss, term) {
if (!term) return;
var values = sheetValues(ss);
var output = [];
for (var i = 0; i < values.length; i++) {
var row = values[i];
var name = row[7]; // 7 = col H
if (name == term) {
output.push(row);
}
}
return output;
}
// get search results and print into Search sheet
function search() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Search');
var searchByName = sheet.getRange(4, 8).getValue(); // search term is in H4 cell
var data = query(ss, searchByName);
sheet.getRange(5, 1, sheet.getLastRow() - 4, sheet.getLastColumn()).clearContent();
sheet.getRange(5, 1, data.length, data[0].length).setValues(data);
}