I am developing some Stock tools with AppScript and now I dont know why I cannot assign the array A values to array B. Could someone help me ?
I want to copy the values_array [l][0] -> dataArray [l][0]
Could you please give me the solution please?
//Filled up the array for MACD
// var dataArray = [["Stock","Date","Close Price","EMA12","EMA26","DIF","Signal"]];
var dataArray = [];
var accumulationEMA12 = 0;
for (var l = 0; l < values_array.length - 1; l++) // Get the previous day EMA12
{
var temp = values_array[l][5];
// var accumulationEMA12 = accumulationEMA12 + values_array[l][5];
var accumulationEMA12 = accumulationEMA12 + temp;
dataArray[l][0] = values_array[l][0]; // Fill Up the Stock No. <-Here
dataArray[l][1] = values_array[l][1]; // Fill UP the Date <-Here
if (l < 11) //if the dataset is < 12 rows or < 26 rows, calculate the average instead of EMA
{
}
}
//Filled up the array for MACD
// var dataArray = [["Stock","Date","Close Price","EMA12","EMA26","DIF","Signal"]];
var dataArray = [];
var accumulationEMA12 = 0;
for(var l = 0; l< values_array.length-1; l++) // Get the previous day EMA12
{
var temp = values_array[l][5];
// var accumulationEMA12 = accumulationEMA12 + values_array[l][5];
var accumulationEMA12 = accumulationEMA12 + temp;
dataArray[l][0] = values_array[l][0]; // Fill Up the Stock No.
dataArray[l][1] = values_array[l][1]; // Fill UP the Date
if(l < 11) //if the dataset is < 12 rows or < 26 rows, calculate the average instead of EMA
{
}
}
Values_array here
I think you are getting error at the line
dataArray[l][0] = values_array[l][0];
Because, no where I see you have initiated dataArray[l]. In your code, dataArray[l] is undefined, so when you try to do something like dataArray[l][1], you are essentially doing undefined[1] which will throw such type error
Uncaught TypeError: Cannot read property '1' of undefined
So what you need to do is, make sure dataArray[l] is an array itself. Something like this
var dataArray = [];
for (var l = 0; l < values_array.length; l++) {
// make sure dataArray[l] exists
dataArray[l] = [];
// do your operations
dataArray[l][0] = values_array[l][0];
dataArray[l][1] = values_array[l][1];
// other code.
}
Although, I would suggest using modern JS language features, like
const dataArray = [];
values_array.forEach((val, index)=> {
// notice that we are assigning a new array to dataArray[index]
dataArray[index] = [
val[0],
val[1],
];
// do other operations like
if (index < 11) {
// do stuff
}
});
Hope it helps.
Related
I'm working from the solution provided HERE to compare two arrays. The example provided returns values found in both arrays to Array1 (same) and values only found on one or the other two Array2 (diff).
ISSUE: When I apply it to my own script, valuesDATA returns nothing and valuesCheckSeeding returns ALL values from both arrays
DESIRED RESULT: I have two arrays that I'd either like to create a third out of, or only select values from the first array, valuesDATA which are NOT present in the second, valuesCheckSeeding. Using the solution above, I was trying to have all values not found in valuesCheckSeeding AND valuesDATA pushed to valuesDATA.
SAMPLE OF valuesDATA: "U09 F
Harford FC Hill/Healey - A
MD
CMSA Girls Saturday U09 A/B North
Premier - Top
TID0118"
What am I doing wrong? I tinkered with changing matchfound==false and matchfound=true in the loop, but that still didn't give me the desired result.
MOST RELEVANT SNIPPET
var matchfound = false;
for (var i = 0; i < valuesDATA.length; i++) {
matchfound=false;
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i] == valuesCheckSeeding[j]) {
valuesCheckSeeding.splice(j, 1);
matchfound=true;
continue;
}
}
if (matchfound==false) {
valuesCheckSeeding.push(valuesDATA[i]);
valuesDATA.splice(i, 1);
i=i-1;
}
}
WORKIG SCRIPT EDITED FROM COMMENTS/ANSWERS BELOW
//UPDATE SEEDING SHEET
function updateSeedingSheet() {
var today = Utilities.formatDate(new Date(),Session.getScriptTimeZone(), "MM/dd/yyyy hh:mm a");
//INPUT SHEET INFO
var inputCurrentRow = 4;
var inputCurrentColumn = 20;
var inputNumRows = 1000;
var inputNumColumns =1;
var ssInput = SpreadsheetApp.openById('1Wzg2BklQb6sOZzeC0OEvQ7s7gIQ07sXygEtC0CSGOh4');
var sheetDATA = ssInput.getSheetByName('DATAREF');
var rangeDATA = sheetDATA.getRange(inputCurrentRow, inputCurrentColumn, inputNumRows, inputNumColumns);
var valuesDATA = rangeDATA.getValues();
//SEEDING SHEET INFO
var seedingCurrentRow = 4;
var seedingCurrentColumn = 1;
var seedingNumRows = 1000;
var seedingNumColumns = 1;
var ssSeeding = SpreadsheetApp.openById('1DuCHeZ3zba-nHq-7vYTrylncPGqcA1J9jNyW9DaS3mU');
var sheetSeeding = ssSeeding.getSheetByName('Seeding');
var rangeCheckSeeding = sheetSeeding.getRange(4, 102, 1000, 1);
var columnToClear = sheetSeeding.getRange(seedingCurrentRow, seedingCurrentColumn, seedingNumRows, seedingNumColumns);
var valuesCheckSeeding = rangeCheckSeeding.getValues();
//METHOD TO FILTER
valuesCheckSeeding = valuesCheckSeeding.map(function(e){return e[0];}); //flatten this array
var filteredArr = valuesDATA.filter(function(e){
return !(this.indexOf(e[0])+1);
},valuesCheckSeeding);
Logger.log(filteredArr);
Logger.log(filteredArr.length);
var rangeSeeding = sheetSeeding.getRange(seedingCurrentRow, seedingCurrentColumn, filteredArr.length, seedingNumColumns);
sheetSeeding.getRange('A1').setValue(today);
columnToClear.clearContent();
rangeSeeding.setValues(filteredArr);
/*
//ALTERNATIVE METHOD USING LOOPS
for (var i = 0; i < valuesDATA.length; i++) {
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i][0] == valuesCheckSeeding[j][0]) {
valuesDATA.splice(i, 1);
i--; //account for the splice
break; //go to next i iteration of loop
}
}
}
Logger.log("VALUES DATA:" + valuesDATA);
Logger.log("VALUES CHECK SEEDING: " + valuesCheckSeeding);
//sheetSeeding.getRange('A1').setValue(today);
//rangeSeeding.clearContent();
//rangeSeeding.setValues(valuesDATA); //INCORRECT RANGE HEIGHT, WAS 71 BUT SHOULD BE 1000 - Is splice affecting this?
*/
}//END FUNCTION
V8(ES2016 update):
You can use newer and efficient set class
const array1 = [[1],[2],[3]],
array2 = [[1],[3],[4]],
set = new Set(array2.flat())
console.info(array1.filter(e => !set.has(e[0])))
//expected output [[2]]
You're checking a 2D array. You'd need to use [i][0] and [j][0]
You can try only splicing valuesDATA
Try
for (var i = 0; i < valuesDATA.length; i++) {
for (var j = 0; j < valuesCheckSeeding.length; j++) {
if (valuesDATA[i][0] == valuesCheckSeeding[j][0]) {
valuesDATA.splice(i, 1);
i--; //account for the splice
break; //go to next i iteration of loop
}
}
}
Logger.log(valuesDATA);
Alternatively, try
valuesCheckSeeding = valuesCheckSeeding.map(function(e){return e[0];}); //flatten this array
var filteredArr = valuesDATA.filter(function(e){
return !(this.indexOf(e[0])+1);
},valuesCheckSeeding);
Logger.log(filteredArr);
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.
Working on a project for a class and keep getting this error when I want to reference an location in my 2D array.The project is a video game recommender system using pearson correlations. To get the correlations we are pulling results from a database filled usernames, the video game they ranked, and the rank(rating) they gave it. This is then used to create a userArray(array of all users who have ratings) and a rankArray(2D array pictured below with all games and the ratings users have given it) within the generateArrays function.
The error is coming from the line within my sim_pearson function which calculates the actual correlation value. When I try to reference a rating given by a particular user for a particular game, the error arise. I am unsure why as I have referenced the 2D array in a similar way before and had no issue.
Here is my sim_pearson function where the error occurs.
function sim_pearson(rankArray, person1, person2){
var similaritems = [];
for(var i = 0; i <= 9; i++){
if (rankArray[i][person1] !== 0){
if(rankArray[i][person2] !== 0){
similaritems.push(i);
}
}
}
if (similaritems.length === 0){
return 0;
}
console.log(similaritems);
var n = similaritems.length;
var temp1, temp2, sum1, sum2, sum1Sq, sum2Sq, pSum = 0;
for (var x = 0; x <= n; x++){
var sItem = similaritems[x];
temp1 = rankArray[sItem][person1];
temp2 = rankArray[sItem][person2];
sum1 = sum1 + temp1;
sum2 = sum2 + temp2;
sum1Sq = sum1Sq + Math.pow(temp1, 2);
sum2Sq = sum2Sq + Math.pow(temp2, 2);
//sum of products
pSum = pSum + (temp1 * temp2);
}
var num = pSum - (sum1*sum2/n);
var den = Math.sqrt((sum1Sq-Math.pow(sum1, 2)/n)*(sum2Sq-Math.pow(sum2, 2)/n));
if (den === 0){
return 0;
}
var r = num/den;
return r;
}
Here is where I create the arrays:
var userArray = [];
var rankArray = [];
function generateArray(result){
//generate user array
var i,item;
var temp = 0;
for (i in result.rows) {
item = result.rows[i];
var userExists = false;
for (var x = 0; x<=userArray.length; x++){
if(item.username == userArray[x]){
userExists = true;
}
}
if(userExists === false){
userArray.push(item.username);
}
}
for(var y =0; y<10; y++){
rankArray[y] = [];
for(var z = 0; z<userArray.length; z++){
rankArray[y][z] = 0;
}
}
//creating rankarray
var w, item1;
for(w in result.rows) {
item1 = result.rows[w];
for(var k in userArray) {
if (item1.username == userArray[k]) {
temp = k;
}
}
rankArray[(item1.vgnum - 1)][temp] = item1.rank;
}
}
And here is a picture of our arrays when they are created. userArray is first holding all the users, then rankArray which has an array set up in each index for each game(there are only 10) and within that array are the rankings of all the users(0 is user 1, 1 is user 2, etc). After is the similaritems array which just finds the games that two users have both rated.
The line that I am calling sim_pearson from essentially looks like this:
generateArrays(result);
//comparing the first two users
console.log("Pearson value: "+sim_pearson(rankArray, 0, 1);
Really unsure why this error is occuring and why I cannot set a var equal to a location with the rankArray I made like:
temp1 = rankArray[sItem][person1];
Any help would be fantastic!
This line is probably the problem:
for (var x = 0; x <= n; x++){
It should be x < n. Since n = similaritems.length, the indexes of similaritems run from 0 to n-1. So on the last iteration, when you do:
var sItem = similaritems[x];
it sets sItem = undefined. Then you do:
temp1 = rankArray[sItem][person1];
rankArray[undefined] is undefined, so this tries to access undefined[person1], which is not valid.
I am trying to write a custom function that will return an array of all of the unique values when two arrays are compared. This is what I have and it is not working:
function getUniqueCells(range1, range2) {
var sheet = SpreadsheetApp.getActiveSheet();
var range1 = sheet.getRange(range1);
var range2 = sheet.getRange(range2);
var range1Val = range1.getValues();
var range2Val = range2.getValues();
var uniquesArr = [];
for (var i = 0; i <= range1Val.length; i++) {
for(var u = 0; u <= range2Val.length; i++){
if(range1Val[i] === range2Val[u]) {
break;
} else if((u + 1) === range2Val.length){
uniquesArr.push(range1Val[i]);
};
};
};
return uniquesArr;
}
Is there a way not to get the "Internal error executing the custom function" error?
there is an issue on your second for loop.
for(var u = 0; u <= range2Val.length; i++){
it should be for(var u = 0; u <= range2Val.length; u++){
You cant check by range1Val[i] === range2Val[u]. Because they are arrays.
I had the same problem. found answer here:
compare rows on google spreadsheets
I have the following problem:
var price = ['4','5','8','12']
var produce = ['kiwi','orange','apple','banana']
var stock = ['yes','no','no','yes']
i need to group them so that the end output is on array in the following format:
var store = [ ['4','kiwi','yes'],['5','orange','no'], ...]
im so confused as in how to make one array with these values into a 2d array. thanks
Using JavaScript with some overkill :):
var price = ['4','5','8','12']
var produce = ['kiwi','orange','apple','banana']
var stock = ['yes','no','no','yes']
// if the lengths/size of the above arrays are the same
var store = [];
for(var i = 0, len = price.length; i < len; i++) {
store.push([price[i], produce[i], stock[i]]);
}
// if the lengths/size of the above arrays aren't the same and you want the minimum full entries
var storeMin = [];
for(var i = 0, len = Math.min(price.length, produce.length, stock.length); i < len; i++) {
storeMin.push([price[i], produce[i], stock[i]]);
}
// if the lenghts/size of the above arrays aren't the same and you want the maximum entries with defaulting missing values to null
// replace the nulls by any default value want for that column
var storeMax = [];
for(var i = 0, pLen = price.length, prLen = produce.length, sLen = stock.length, len = Math.max(pLen, prLen, sLen); i < len; i++) {
storeMax.push([pLen>i?price[i]:null, prLen>i?produce[i]:null, sLen>i?stock[i]:null]);
}
var price = ['4','5','8','12']
var produce = ['kiwi','orange','apple','banana']
var stock = ['yes','no','no','yes']
var store = [];
$.each(price,function(ind,elm) {
store.push([elm,produce[ind],stock[ind]]);
});
console.log(store);