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.
Related
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.
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 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])
}
}
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.
I am looping through a range of data in a Google spreadsheet in JavaScript.
The problem I'm having is I have some merged cells that have the same value, for example C:6 to E:6 all have the same value as those 3 cells are merged.
So in my loop it will show C:6 = 'Focus and targeting' D:6 = '' and E:6 = '' What I'm trying to do is in my loop assign the 2nd and 3rd values to the first cell value.
Here is what I have:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Audit');
var range = sheet.getDataRange();
var numRows = range.getNumRows();
var numCols = sheet.getMaxColumns();
var values = range.getValues();
var count = 0;
for (var i = 2; i <= numCols - 2; i++) {
var questionCategory = values[5][i];
if(questionCategory == undefined) {
continue;
}
if(questionCategory == "") {
// need to assign 2nd and 3rd cells of merged list to have the value of 1st cell in merged list
}
count++;
}
Here is what the data looks like:
Any ideas how I can achieve this?
Here is custom function to get merged cell value:
function getMergedCellValue(cellRange)
{
if (!cellRange.isPartOfMerge())
{
return cellRange.getDisplayValue();
}
return cellRange.getMergedRanges()[0].getDisplayValue();
}
And updated code using this function:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Audit');
var range = sheet.getDataRange();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
var values = range.getValues();
var count = 0;
var questionRowNum = 6;
for (var i = 0; i < numCols; i++)
{
// assign 2nd and 3rd cells of merged list to have the value of 1st cell in merged list
var questionCategory = values[questionRowNum-1][i] || getMergedCellValue(sheet.getRange(questionRowNum, i+1));
count++;
}