Split some strings and pass them in two different columns. - google-apps-script

I've the following situation :
Sheet 1 (input) :
www.url1.com?somestuff
www.url2.com?somestuff
www.url3.com?somestuff
www.url4.com?somestuff
Sheet 2 (expected output):
Col1 Col2
www.url1.com ?somestuff
www.url2.com ?somestuff
www.url3.com ?somestuff
www.url4.com ?somestuff
Here is what I've done until now :
function testwoD() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet11");
var row_count = input.getLastRow()
var col_count = input.getLastColumn();
raw_data = input.getRange(1, 1,row_count,col_count).getValues()
tempArr = [] // or new Array
for (var i = 0; i < row_count; i++) {
tempArr.push(raw_data[i][6].split("?")[0]);
tempArr.push(raw_data[i][6].split("?")[1]);
}
var toAddArray = [];
for (i = 0; i < tempArr.length; ++i){
toAddArray.push([tempArr[i]]);
}
Logger.log(tempArr)
output.getRange(1, 1,730,1).setValues(toAddArray);
}
And here is the result I have on Sheet2 :
www.url1.com
?somestuff
www.url2.com
?somestuff
www.url3.com
?somestuff
www.url4.com
?somestuff
How can I reach the expected output ? I've read a lot of questions about transposing array but couldn't find the answer that could help me solve my issue.
Thanks !

Instead of push and concat you can do this
tempArr = [] // or new Array
for (var i = 0; i < row_count; i++) {
tempArr[i] = []
tempArr[i][0] = raw_data[i][6].split("?")[0];
tempArr[i][1] = raw_data[i][6].split("?")[1];
}
or better still you just push the whole split array.
for (var i = 0; i < row_count; i++) {
tempArr.push(raw_data[i][6].split("?"))
}
The basic idea is to get the two columns in the array per row index. So when you do setValues it writes in two corresponding columns
Final code:
function testwoD() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet11");
var row_count = input.getLastRow()
var col_count = input.getLastColumn();
raw_data = input.getRange(1, 1,row_count,col_count).getValues()
tempArr = [] // or new Array
for (var i = 0; i < row_count; i++) {
tempArr[i] = []
tempArr[i][0] = raw_data[i][6].split("?")[0];
tempArr[i][1] = raw_data[i][6].split("?")[1];
}
// Not sure what this code is suppose to achieve? hence removed it
/*var toAddArray = [];
for (i = 0; i < tempArr.length; ++i){
toAddArray.push([tempArr[i]]);
}*/
Logger.log(tempArr)
// You can use setValues and get numof rows and columns using array length
output.getRange(1, 1,tempArr.length,tempArr[0].length).setValues(tempArr);
}
Hope that helps

Related

Convert string range to float and return its max on GAS

I haven't been able to convert the array into float to get its max and add 0.1 to it and then return it in string format.
Any idea on what needs tweaking here?
function newVersion() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("ArquivoItens");
var range = sheet.getRange(2,1,sheet.getLastRow(),3).getValues();
var editarSheet = ss.getSheetByName('EditarItem');
var itemCode = editarSheet.getRange("W5").getValue();
var lastVersion = [];
var max = 0;
for (var i = 0; i < range.length; i++){
if(range[i].indexOf(itemCode) != -1){
lastVersion.push(parseFloat(range[i][2]));
}
}
max = Math.max(lastVersion);
return max; //to string
Logger.log(max);
}
Thanks for any light here.
Here is the working piece of code that does what the question says:
for (var i = 0; i < range.length; i++){
if(range[i].indexOf(itemCode) != -1){
lastVersion.push(parseFloat(range[i][2]));
}
}
max = Math.max.apply(null, lastVersion) + .1;
Logger.log(max.toFixed(1));
return max.toFixed(1);
}
If you want to apply Math.max() to an array, you need to expand the values of the array into the function's arguments
So:
max = Math.max(...lastVersion);
Read this for more information.
Also, return will finish your function execution, so any logs or other code you implement subsequently will be ignored.

How to pass data from one column to another one ?

I have a spreadsheet with multiple rows and columns. Two columns (column 3&4) are filled with text. I want to clean the text from this two columns and delete every specific characters (newlines, comma, exclamation point, quote,etc...). So I wrote the following script :
function testwoD() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var row_count = input.getLastRow()
var col_count = input.getLastColumn();
raw_data = input.getRange(1, 1,row_count,col_count).getValues()
temp3 = []
for (var i = 0; i < row_count; i++) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
temp3.push(raw_data[i][4].toString().replace(punctRE, '').replace(spaceRE, ' '));
}
temp4 = []
for (var i = 0; i < row_count; i++) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
temp4.push(raw_data[i][3].toString().replace(punctRE, '').replace(spaceRE, ' '));
}
var toAddArray3 = [];
for (i = 0; i < temp3.length; ++i){
toAddArray3.push([temp3[i]]);
}
var toAddArray4 = [];
for (i = 0; i < temp4.length; ++i){
toAddArray4.push([temp4[i]]);
}
output.getRange(1, col_count-13,row_count,1).setValues(toAddArray3);
output.getRange(1, col_count-14,row_count,1).setValues(toAddArray4);
}
It's working but It's very complicated and confusing. I made it step-by-step so even myself have some difficulties to really explain it.
Is there a way to significantly improve it ?
Best,
Simon.
DRY! - Do not repeat yourself.
Another popular idiom should be UMNF - Use map not for.
Putting everything into its own function encapsulates functionality and puts the focus on what you want to do with the data at each level rather than bookkeeping indices and subscripts.
function cleanColumns() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var raw_data = input.getDataRange().getValues();
var columnsToClean = [3,4];
function cleanText(t) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
return t.toString().replace(punctRE, "").replace(spaceRE, " ");
};
function cleanColumn(col) {
return raw_data
.map(function(row) {return row[col];})
.map(cleanText)
.map(function(row) {return [row];})
};
function cleanAndWrite(col) {
var data = cleanColumn(col);
output.getRange(1, col + 1, data.length, 1).setValues(data);
}
columnsToClean.forEach(cleanAndWrite);
}

google apps script two columns summary

I have a google spreadsheet with two columns corresponding to lessons: the first with names of the porfessors (occasionally repeating themselves) and the second with numbers (number of hours). I would like to have as output two columns, the first with the names of the porfessors and the second with the sum of all the hours
I tried with the following code, but it seems to give me back two arrays with the initial colums, as if the condition if (names[names.length-1] == namesColumn[i]) is never met.
What am I doing wrong?
function resumeProfessors() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
var namesColumn = sheet.getRange("C4:C31").getValues();
var lessonsColumn = sheet.getRange("G4:G31").getValues();
var names = [];
names.length = 0;
var lessons = [];
lessons.length = 0;
namesColumn.sort();
for (var i = 0; i < namesColumn.length; i++) {
if (names[names.length-1] == namesColumn[i]){
lessons[lessons.length-1] = lessons[lessons.length-1] + lessonsColumn[i];}
else{
sheet.getRange(i+4, 9).setValue(names[names.length-1] + namesColumn[i]);
names[names.length] = namesColumn[i];
lessons[lessons.length] = lessonsColumn[i];
};}
writeResume(names, lessons);
}
Ty
Given your use-case, I'd recommend using a Pivot table or the =QUERY formula.
However, assuming your input sheet looks something like this -
And the expected output is something like this -
You can try the below code -
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var input = ss.getSheetByName('Sheet1');
var output = ss.getSheetByName('Sheet2');
var inputValues = input.getDataRange().getValues();
Logger.log(inputValues)
for (var i = 1; i < inputValues.length; i++) {
var name = inputValues[i][0];
var totalHours = [];
for (var j = 0; j < inputValues.length; j++) {
var hours = inputValues[j][1];
if (name == inputValues[j][0]) {
totalHours.push(inputValues[j][1]);
}
}
var outputValues = output.getDataRange().getValues();
var newEntry = true;
for (var k = 0; k < outputValues.length; k++) {
if (name == outputValues[k][0]) {
newEntry = false;
}
}
if (newEntry) {
output.appendRow([name,totalHours.reduce(function(a, b) {return a + b})]);
}
}
}
Hope this helps.

Get row & column indices of found value

How do I get the row and column indices of the cell containing a value I'm looking for?
Here's an example of two sheets, "Grave" and "Data_grave":
My code, below, should...
First, get a specific value in sheet "Grave" (in example value is - "Win").
Find the number of the row & column with this value in sheet "Data_grave".
Finally, it should write some data ("wow") near the found value "Win" (from column+1).
However, I receive an error message at line 17 (the line following my search loops):
Can't convert 4,4 to (class)
How do I solve that?
function myFind() {
var ss = SpreadsheetApp.getActive(), rowNum = [], collNum = [];
var findData = ss.getSheetByName('Grave').getRange("A2").getValue();
var searchData = ss.getSheetByName('Data_grave').getDataRange().getValues();
for(var i=1, iLen=findData.length; i<iLen; i++) {
for(var j=0, jLen=searchData.length; j<jLen; j++) {
for(var k=0, kLen=searchData[0].length; k<kLen; k++) {
var find = findData;
if(find == searchData[j][k]) {
rowNum.push([j+1]);
collNum.push([k+2]);
}
}
}
}
ss.getSheetByName('Data_grave').getRange(rowNum,collNum).setValue("wow");
}
As Adelin commented: the error message is indicating that you are not using .getRange(rowNum,collNum) properly. That method expects two numbers, but you're providing it two arrays.
When you've "found" the cell you're searching for, instead of push() (which treats rowNum and colNum as arrays), you simply want to use:
var rowNum = j+1;
var colNum = k+2;
You could also use a boolean found as an additional exit condition for all your loops, to stop searching upon success.
function myFind() {
var ss = SpreadsheetApp.getActive(), rowNum = [], collNum = [];
var findData = ss.getSheetByName('Grave').getRange("A2").getValue();
var searchData = ss.getSheetByName('Data_grave').getDataRange().getValues();
var found = false;
for(var i=1, iLen=findData.length; i<iLen && !found; i++) {
for(var j=0, jLen=searchData.length; j<jLen && !found; j++) {
for(var k=0, kLen=searchData[0].length; k<kLen && !found; k++) {
var find = findData;
if(find == searchData[j][k]) {
var rowNum = j+1;
var collNum = k+2;
found = true;
}
}
}
}
ss.getSheetByName('Data_grave').getRange(rowNum,collNum).setValue("wow");
}

How do I split up an array in bits in AS3

I'm making a game which reads from an array to find out what to put where.
An example:
[1,1,2,
2,3,1,
3,3,1]
How do I make it so that the last row comes first and then the second row after and so on.
What I want:
[3,3,1,
2,3,1,
1,1,2]
thanks in advance!
You can use something like this:
// Written in JavaScript, but should work as is in AS3
var list = [1,1,2,
2,3,1,
3,3,1];
var rowLength = 3;
var rowCount = list.length / rowLength;
var rows = [];
for (i = 0; i < rowCount; ++i)
{
var offset = i * rowLength;
rows.push(list.slice(offset, offset + rowLength));
}
rows.reverse();
var result = [];
for (var j in rows)
{
result = result.concat(rows[j]);
}
console.log(result); // result = [3,3,1,
// 2,3,1,
// 1,1,2];