I want to combine JavaScript Objects with the same variable name - javascript

Right now, If i run for loop
{“FirstName” : “Kim”}
{“LastName” : “hana”}
{“Phone” : “010-1234-5648”}
{“Email” : “abc#gmail.com”}
It comes out like this.
But the result I want is
{“FirstName” : “Kim”, “LastName” : “hana”, “Phone” : “010-1234-5648”, “Email” : “abc#gmail.com”}
I want to make it come out like this.
What should I do?
This is my code that I just wrote.
function testRun(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var LastRow = ss.getLastRow();
var LastCol = ss.getLastColumn();
var arr = [];
for(var i = 1; i<=LastCol; i ++){
var fieldName = ss.getRange(1,i).getValue();
arr.push(fieldName);
}
//arr = [FirstName, LastName, Phone, Email]
for(var i =2;i<=LastRow;i++){
for(var j=1;j<=LastCol;j++){
var payload = Utilities.jsonStringify({
[arr[j-1]] : ss.getRange(i,j).getValue()}
);
}
}
}

Modification points:
In your showing script, it seems that payload is not used.
When getValue() is used in a loop, the process cost becomes high. Ref
When these points are reflected in a sample script for achieving your goal, it becomes as follows.
Sample script:
When your showing script is modified, how about the following modification?
function testRun() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var LastRow = ss.getLastRow();
var LastCol = ss.getLastColumn();
var [header, ...values] = ss.getRange(1, 1, LastRow, LastCol).getValues();
var arr = [];
for (var i = 0; i < LastRow - 1; i++) {
var temp = {};
for (var j = 0; j < LastCol; j++) {
temp[header[j]] = values[i][j];
}
arr.push(temp);
}
console.log(JSON.stringify(arr))
}
When this script is run, arr is [{"FirstName":"Kim","LastName":"hana","Phone":"010-1234-5648","Email":"abc#gmail.com"}].
As another apporach, I thought that you might be able to also use the following sample script.
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var [header, ...values] = ss.getRange(1, 1, ss.getLastRow(), ss.getLastColumn()).getValues();
var arr = values.map(r => header.reduce((o, h, j) => (o[h] = r[j], o), {}));
console.log(JSON.stringify(arr))

Your code creates separate objects in each iteration. Create an empty object for every Person, then add the properties you need.
This should look something like this:
for(var i=2; i<=LastRow; i++){
var payload = {}
for(var j=1; j<=LastCol; j++){
payload[arr[j-1]] = ss.getRange(i,j).getValue()};
}
}

Related

Google Apps Script to list only assignments after certain date in Google Classroom

I have a Google Apps Script that pulls and lists all the assignments from Google Classroom within a domain in a Google Sheet, but now I need to pull only certain assignments after a certain date. I must be putting the date or condition wrong, because the array remains empty at the end (whereas if I comment out the if condition with the date filter, the code works perfectly fine and lists all assignments).
The other "non-visible" problem is that the for loop is still going through all of the assignments before applying the filter, which wastes time. The idea would be to have for loop be limited to only the assignments after a certain date from the beginning instead of searching through everything, but I don't know if that is possible.
The code is below.
function listAssignmentsbyDate() {
var s1 = SpreadsheetApp.getActiveSpreadsheet();
var sh = s1.getSheetByName('LA');
var response = Classroom.Courses.list();
var courses = response.courses;
var arr1 = []; var arr2 = []; var arr3 = []; var arr4 = [];
var today = new Date();
var oneWeekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
for (i = 0; i < courses.length; i++) {
var course = courses[i];
var ids = course.id;
var title = course.name;
var state = course.courseState;
arr1.push([ids,title,state]);
}
for (i = 0; i < arr1.length; i++) {
if (arr1[i][2] !== 'ARCHIVED'){
var list = arr1[i][0];
var page = null, t = [];
do {
var tea = Classroom.Courses.CourseWork.list(list, {pageToken: page, pageSize: 100});
page = tea.nextPageToken; var t = t.concat(tea.courseWork);
} while (page);
try {
for (q = 0; q < t.length; q++) {
var c = t[q];
var name = arr1[i][1];
// The line below is what is not working.
if(oneWeekAgo < c.creationTime){
var ti = c.title;
var des = c.description;
var st = c.state;
var link = c.alternateLink;
var typ = c.workType;
var poi = c.maxPoints;
var create = c.creationTime;
var due = c.dueDate;
var duet = c.dueTime;
var cour = c.courseId;
var ids = c.id;
var user = c.creatorUserId;
arr2.push([name,ti,des,st,link,typ,poi,create,due,duet,cour,ids]);
arr3.push(user);
}
}
} catch (e) {continue;}
}
}
for (r=0; r < arr3.length; r++){
try {
var eu = arr3[r];
var us = AdminDirectory.Users.get(eu).primaryEmail;
arr4.push([us]);
} catch(e){continue;}
}
sh.getRange(2, 2, arr4.length, arr5[0].length).setValues(arr4);
sh.getRange(2, 3, arr2.length, arr2[0].length).setValues(arr2);
s1.getSheetByName('CACHE').getRange('B1').setValue('');
}

How to make a sum of arrays

I'm using the following code to get all the value of all my sheets that have a numeric name. Once it find a numeric sheet name, it must sum row 8 to 108 of column 6. All the sheets must be sum in the right array. Right now, my script add the data in the array after then it crash instead of doing a sum.
example (cell = value : variable = value)
sheet 1 (8,6)=1 : colonne[1] = 1
sheet 2 (8,6)=2 : colonne[1] = 3
sheet 3 (8,6)=3 : colonne[1] = 6
sheet 1 (8,7)=2 : colonne[2] = 2
sheet 2 (8,7)=2 : colonne[2] = 4
sheet 3 (8,7)=2 : colonne[2] = 6
function CalculTotal() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var out = new Array()
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var substring1;
var colonne=[];
for (var i=0 ; i<sheets.length ; i++)
{
substring1=sheets[i].getName();
if(!isNaN(parseFloat(substring1)) && isFinite(substring1)){
colonne=colonne+(ss.getSheetByName(substring1).getRange(8,6,100).getValues());
}
}
s.getRange(8,4,100).setValues(colonne);
}
Try this:
function CalcTotal() {
var ss=SpreadsheetApp.getActive();
var sheets=ss.getSheets();
var regex=new RegExp('^[\\d\\.,]+$')
var total=0;
var n=1;
var html='<style>th,td{border:1px solid #000;}</style><table>';
html+=Utilities.formatString('<tr><th>%s</th><th>%s</th><th>%s</th></tr>','Item','Sheet','Sum')
for(var i=0;i<sheets.length;i++){
var name=sheets[i].getName();
var sum=0;
var nameisnum=false;
var result=regex.exec(name);
if(result){
nameisnum=true;
var shi=ss.getSheetByName(name);
var rgi=shi.getRange(8,6,101,1);
var vAi=rgi.getValues();
for(var j=0;j<vAi.length;j++){
sum+=vAi[j][0];
}
if(nameisnum){
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td></tr>',n++,name,sum);
total+=sum;
}
}
}
html+=Utilities.formatString('<tr><td colspan="2">Total:</td><td>%s</td></tr>',total);
html+='</table>';
var ui=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModelessDialog(ui, 'Sheet Sums');
}
Here is an example of how to add 2 arrays, but notice this is done in the form of a 2D array. getValues() returns an array of array[i] i = number of rows, array[i][j] j is the column both indexes start with 0. setValues() works the same way but places a 2D array.
function CalculTotal() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var out = new Array()
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var substring1;
var colonne=[];
// Initialize result array
for( var i=0; i<100; i++ ) colonne[i] = [0];
for (var i=0 ; i<sheets.length ; i++)
{
substring1=sheets[i].getName();
if(!isNaN(parseFloat(substring1)) && isFinite(substring1)){
var values = ss.getSheetByName(substring1).getRange(8,6,100,1).getValues();
for( var j=0; j<values.length; j++ ) {
colonne[j][0] = colonne[j][0]+values[j][0];
}
}
}
s.getRange(8,4,100,1).setValues(colonne);
}

How to get values from Google Sheet Column

I have the following Apps Script, which is almost what I'm looking for. What it's doing is getting a list of items from a Google Sheet to populate a Google Form Multiple Choice Question with a list of items. However, it's including all 100 rows, rather than just the ones that have values in them.
What am I missing to make sure it only includes cells that have a len > 1?
function getWorkbookNames(){
var form = FormApp.getActiveForm();
var items = form.getItems();
var ss = SpreadsheetApp.openByUrl(
'spreadsheetnamestringhere');
var sheet = ss.getSheetByName('Unique Databases');
var sheetValues = sheet.getRange("A2:A").getValues();
var values = sheetValues.slice(1);
var names = [];
for(var p = 0; p < values.length; p++){
names.push(values[p][0])
}
var pValues = items[8].asListItem();
pValues.setChoiceValues(names).setRequired(true)
var areas = [];
for (var i = 0; i < values.length; i++) {
areas.push(values[i][1])
}
}
Any help/advice you all could provide would be greatly appreciated.
Solved by adding another filter layer:
function getWorkbookNames() {
var form = FormApp.getActiveForm();
var items = form.getItems();
var ss = SpreadsheetApp.openByUrl(
'spreadsheetnamestringhere');
var sheet = ss.getSheetByName('Unique Databases');
var sheetValues = sheet.getRange("A2:A").getValues();
var filterValues = sheetValues.filter(String);
var values = filterValues.slice(1);
var names = [];
for (var p = 0; p < values.length; p++) {
names.push(values[p][0])
}
var pValues = items[8].asListItem();
pValues.setChoiceValues(names).setRequired(true)
var areas = [];
for (var i = 0; i < values.length; i++) {
areas.push(values[i][1])
}
}

Rearrange multiple columns on sheet with Google script

I am trying to convert a VBA macro that rearranges columns on a sheet from an array of column indices to a Google script
I want to return all columns but with the columns listed in the array as the first 3 columns and all the other columns in their same order
The original vba is using header names but I am using column indices
I get error Incorrect range height, was 1 but should be 24
I have no idea if there are other issues as well
Thanks in advance
Here is what I have
function myFunction() {
var sheet =SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Elements");
var data = sheet.getDataRange().getValues();
var LC = sheet.getLastColumn();
var LR = sheet.getLastRow();
var headers = [4,2,3]; //array of colunm indices
var temp = [];
var Dex = 0
for (var i = 0; i < LC; i++) {
for(var j = 0; j < LC; j++) {
for (var F = 0; F < headers.length - 1; F++) {
if (headers[F] = data[j]) {
Dex = F
break;
};
}
if (F < i) {
temp = data.indexOf(i);
data[i] = data.indexOf(j)
data[j] = temp
}
};
};
sheet.getRange(1, 1, LC,LR).setValues([data])
}
Here is the vba
Sub vba()
Dim rng As Range
Dim i As Integer
Dim J As Integer
Dim Temp
Dim nams As Variant
Dim F
Dim Dex As Integer
nams = Array("ItemID", "FirstName", "LastName", "Year")
Set rng = Range("A1").CurrentRegion
For i = 1 To rng.Columns.Count
For J = i To rng.Columns.Count
For F = 0 To UBound(nams)
If nams(F) = rng(J) Then Dex = F: Exit For
Next F
If F < i Then
Temp = rng.Columns(i).Value
rng(i).Resize(rng.Rows.Count) = rng.Columns(J).Value
rng(J).Resize(rng.Rows.Count) = Temp
End If
Next J
Next i
End Sub
Try this:
function moveColumns() {
var sh=SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Elements");
var rg= sh.getDataRange()
var vA=rg.getValues();
var vB=[];
var first3 = [8,7,6,5];
var first3desc=first3.slice();
first3desc.sort(function(a, b){return b-a;});
for(var i=0;i<vA.length;i++){
var row=vA[i];
for(var j=0;j<first3.length;j++){
row.splice(j,0,vA[i][first3[j]-1+j]);
}
for(var j=0;j<first3desc.length;j++){
var c=first3desc[j]-1+first3.length;//for debugging
row.splice(first3desc[j]-1+first3.length,1);
}
vB.push(row);
}
sh.getRange(1,1,vB.length,vB[0].length).setValues(vB);
}
Here's the function as I run it this time.
function moveColumns() {
var sh=SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Elements");
var rg= sh.getDataRange()
var vA=rg.getValues();
var vB=[];
var first3 = [8,7,6,5,4,3,2,1];
var first3desc=first3.slice();
first3desc.sort(function(a, b){return b-a;});
for(var i=0;i<vA.length;i++){
var row=vA[i];
for(var j=0;j<first3.length;j++){
row.splice(j,0,vA[i][first3[j]-1+j]);
}
for(var j=0;j<first3desc.length;j++){
var c=first3desc[j]-1+first3.length;
row.splice(first3desc[j]-1+first3.length,1);
}
vB.push(row);
}
sh.getRange(1,1,vB.length,vB[0].length).setValues(vB);
}
My "Elements" sheet before:
My "Elements" sheet after:
On this line
var data = sheet.getDataRange().getValues();
data gets a 2D array, but later the script handled it as 1D array. In other words, to reference a cell value, instead of data[index] use something like data[row][column].
A single equal sign = is use to assign an object/literal to a variable so this headers[F] = data[j] instead of doing a comparison replaces the value of headers[F] by the object of data[j] which initially is an array.

Copy sheet to another spreadsheet [Google Apps Script]

I can't get this function working. It's has to copy all the values of spreadsheet "A" to spreadsheet "B".
function triggerOnTime() {
var SpreadSheetKeyA = "142WNsfQQkSx4BuNhskDM9aXD9ylRHNZh34oO5TBTt1g";
var SpreadSheetKeyB = "1h8fDwCUUPHRdmTHu-5gMyqU294ENZxCZcHCNCuN6r_Y";
var sheet1 = SpreadsheetApp.openById(SpreadSheetKeyA).getActiveSheet();
var sheet2 = SpreadsheetApp.openById(SpreadSheetKeyB).getActiveSheet();
var data = sheet1.getDataRange().getValues();
var array = [];
for (var y = 1; y < data.length; y++) {
for (var x = 0; x < 35; x++){
array.push(data[y][x]);
}
Logger.log(array);
sheet2.appendRow(array);
sheet1.deleteRow(y);
}
}
It now copy's two or three values, but copy them multiple times (random). The function must also delete the copied values from sheetA. But it only deletes the values that are added to sheetB.
EDIT (Updated code)
function triggerOnTime() {
var SpreadSheetKeyA = "142WNsfQQkSx4BuNhskDM9aXD9ylRHNZh34oO5TBTt1g";
var SpreadSheetKeyB = "1h8fDwCUUPHRdmTHu-5gMyqU294ENZxCZcHCNCuN6r_Y";
var sheet1 = SpreadsheetApp.openById(SpreadSheetKeyA).getActiveSheet();
var sheet2 = SpreadsheetApp.openById(SpreadSheetKeyB).getActiveSheet();
var data = sheet1.getDataRange().getValues();
var array = [];
for (var y = 0; y < data.length; y++) {
for (var x = 0; x < 35; x++){
array.push(data[y][x]);
}
sheet2.appendRow(array);
sheet1.deleteRow(y+1);
array = [];
}
}
After playing around a little, I have found a fix for you (albeit a hack, I guess. Im sure there's a better way of doing it)
Whats happening is, on line 14 where you appendRow(array), you are appending the array at it's current state to the second sheet; basically creating a big pyramid of values of your array over time.
If sheet 1 contained something like this:
1,1,1
2,2,2
3,3,3
4,4,4
5,5,5
Your sheet 2 would get this appended:
1,1,1
1,1,1,2,2,2
1,1,1,2,2,2,3,3,3
... and so on.
You could do something like this:
function triggerOnTime() {
var SpreadSheetKeyA = "142WNsfQQkSx4BuNhskDM9aXD9ylRHNZh34oO5TBTt1g";
var SpreadSheetKeyB = "1h8fDwCUUPHRdmTHu-5gMyqU294ENZxCZcHCNCuN6r_Y";
var sheet1 = SpreadsheetApp.openById(SpreadSheetKeyA).getActiveSheet();
var sheet2 = SpreadsheetApp.openById(SpreadSheetKeyB).getActiveSheet();
var data = sheet1.getDataRange().getValues();
var array = [];
for (var y = 1; y < data.length; y++) {
for (var x = 0; x < 35; x++){
array.push(data[y][x]);
}
sheet2.appendRow(array);
sheet1.deleteRow(y);
array = []; //reset the array contents
}
}
The additional line will just reset the array and add the row you want to copy across.
Let me know if this works out for you.

Categories

Resources