I just started to learn Apps Script and I need to add some text to each value of an array. This code just puts the values in another column:
function getData() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName("Stocks");
var symbol = sheet1.getRange('A1:A7').getValues();
sheet1.getRange('C1:C7').setValues(symbol);
}
I want to add some text to the output, like this:
function getData() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName("Stocks");
var symbol = sheet1.getRange('A1:A7').getValues();
sheet1.getRange('C1:C7').setValues(
'=GOOGLEFINANCE("FRA:' + symbol + ")'
);
}
But I know that this won't work. How do I add to each value being written?
use a loop to go through your array of values
function getData() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Stocks");
var symbol = sheet1.getRange('A1:A7').getValues();
var destRange = sheet1.getRange('C1:C7');
for (var i = 0; i < symbol.length; i++)
symbol[i][0] = '=GOOGLEFINANCE("FRA:' + symbol[i][0] + '")');
destRange.setFormulas(symbol);
}
As range A1:A7 and C1:C7 are of same widht and height you can use back that array to then use setFormulas(array) of course use this method if you only use once symbol array if not then declare an empty array befor your loop as so :
var resultArray = []
then inside your for loop do:
resultArray.push(['=GOOGLEFINANCE("FRA:' + symbol[i][0] + '")']);
then use outside the for loop setFormulas():
destRange.setFormulas(resultArray);
Related
https://i.stack.imgur.com/7VAJk.png
i want to copy data from "dB" sheet A5:A29 and paste to correct column.
so i use the script to find the correct column.
there range B2:CX2 have 0(not-correct) or 1(correct) value, so i use 'for' & 'if'
BUT!! It's too delay!!
i use console.time() and i get 25909ms(timecheck2 value) !!!
please help me.....
here is my code
function save(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('dB');
console.time("timecheck1");
//find last row
var copyrangeO = sheet.getRange(5,1,25,1).getValues();
var lastrowO = copyrangeO.filter(String).length;
var copyrange = sheet.getRange(5,1,lastrowO,1);
console.timeEnd("timecheck1");
//my dB data start "B2".
var cv = 1;
//find correct value(1). B2 ~ CX2 (#100)
console.time("timecheck2");
for (var i=2; i<101;i++){
if(sheet.getRange(2,i).getValue()===1){
cv = i;
}
}
console.timeEnd("timecheck2");
//if data isn't correct, cv===1. so error msg print.
console.time("timecheck3");
if(cv ===1){
Browser.msgBox("ERROR")
}else {
//data copy and paste.
var columnToCheck = sheet.getRange(4,cv,1000).getValues();
var lastrow = getLastRowSpecial(columnToCheck);
var pasterange = sheet.getRange(lastrow+4,cv);
copyrange.copyTo(pasterange, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
Browser.msgBox(lastrowO + " saved!");
}
console.timeEnd("timecheck3");
}
Issue:
If I understand your situation correctly, you want to find the cell in B2:CX2 in which the value is 1, but the script is taking too much time for this.
The problem here is that you are using getRange and getValue in a loop (sheet.getRange(2,i).getValue()===1). This greatly increases the amount of calls to the Sheets service, which slows down your script, as you can see at Minimize calls to other services.
Solution:
In that case, I'd suggest doing the following:
Get the values from all columns at once using getValues().
Use findIndex to get the column index for which value is 1.
In order to do that, replace this:
var cv = 1;
//find correct value(1). B2 ~ CX2 (#100)
console.time("timecheck2");
for (var i=2; i<101;i++){
if(sheet.getRange(2,i).getValue()===1){
cv = i;
}
}
With this:
var ROW_INDEX = 2;
var FIRST_COLUMN = 2; // Column B
var LAST_COLUMN = 102; // Column CX
var columnValues = sheet.getRange(ROW_INDEX, FIRST_COLUMN, 1, LAST_COLUMN-FIRST_COLUMN+1).getValues()[0];
var cv = columnValues.findIndex(columnValue => columnValue === 1) + FIRST_COLUMN;
Note:
If there's no cell in the range with value 1, findIndex returns -1 which, added to FIRST_COLUMN, results in 1. That's appropriate for your current script, but won't work if the FIRST_COLUMN stops being 2, so be careful with this (either change the condition if(cv ===1){ to something less strict, or don't assign the resulting value to cv if findIndex returns -1).
The function will spend most of its time in the for loop because it repeats the Range.getValue() call many times. You can speed things up quite a bit by getting all values with one Range.getValues() call, like this:
let cv = 1;
console.time("timecheck2");
sheet.getRange('B2:B100').getValues().flat()
.some((value, index) => (cv = 2 + index) && value === 1);
console.timeEnd("timecheck2");
Note that this is not a cleanest way of finding cv, but it should help illustrate why you have a performance issue. You may want to do a complete rewrite of the code, using declarative instead of imperative style.
Try this:
I don't know what you're doing in the save because to did not supply the helper function code.
function save(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('dB');
var vs0 = sh.getRange(5,1,25,1).getValues();
var lr0 = vs0.filter(String).length;
var crg = sh.getRange(5,1,lr0,1);
var cv = 1;
const vs1 = sh.getRange(2,2,1,99).getValues().forEach((c,i) => {
if(c == 1)cv = i + 2
})
if(cv == 1){
Browser.msgBox("ERROR")
}else {
var vs2 = sh.getRange(4,cv,1000).getValues();
var lastrow = getLastRowSpecial(vs2);
var drg = sh.getRange(lastrow+4,cv);
crg.copyTo(drg, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
Browser.msgBox(lr0 + " saved!");
}
}
EDIT - code to calculate refill_playlist_len included
I have a function in Javascript that deletes a row of an HTML table and populates it again with values from arrays.
Within this deleteRow function, I have a for loop which loops through a string and assigns parts of the strings to different variables and tries to push them onto arrays.
Without the for loop, it works fine (i.e. when I just index manually) but for some reason when I place it in a for loop, the values aren't pushed onto the arrays. The values themselves print fine on each iteration they just aren't added to the array.
Refill_playlist_len is the count of the Django Queryset (30).
var refill_playlist_len = '{{ playlist.count }}';
var artist_Arr = [];
var track_Arr = [];
var track_id_Arr = [];
var album_Arr = [];
var artist_name;
var track_name;
var track_id;
var album_name;
for (var i = 0; i < refill_playlist_len; i++) {
var searchStr = refill_playlist[i];
console.log(searchStr);
console.log(typeof searchStr);
console.log(typeof refill_playlist);
//grab variables
artist_name = searchStr.match(new RegExp("artist_name:" + "(.*)" + ", album_name:"));
console.log(artist_name[1]);
artist_Arr.push(artist_name[1]);
track_name = searchStr.match(new RegExp("track_name:" + "(.*)" + ", acousticness:"));
console.log(track_name[1]);
track_Arr.push(track_name[1]);
track_id = searchStr.match(new RegExp("track_id:" + "(.*)" + ", track_name:"));
console.log(track_id[1]);
track_id_Arr.push(track_id[1]);
album_name = searchStr.match(new RegExp("album_name:" + "(.*)" + ", track_number:"));
console.log(album_name[1]);
album_Arr.push(album_name[1]);
}
The console logs are in the image below. You can see part of the 'searchStr' printed, along with the data types, artist name, track IDs, etc but for some reason, it says that 'searchStr' is undefined?
Console
I'm quite new to Javascript so my apologies if there is something basic I'm forgetting.
Multiple issues with code. Please clean up code. Sample is given below.
function find(refill_playlist) {
const refill_playlist_len = refill_playlist.length
let artist_Arr = []
let track_id_Arr = []
let track_Arr = []
let album_Arr = []
for (i = 0; i < refill_playlist_len; i++) {
var searchStr = refill_playlist[i];
if(!searchStr) continue;
//grab variables
artist_name = searchStr.match(/artist_name:(.*), album_name:/);
artist_name && artist_Arr.push(artist_name[1]);
track_name = searchStr.match(/track_name:(.*), acousticness:/);
track_name && track_Arr.push(track_name[1]);
track_id = searchStr.match(/track_id:(.*), track_name:/);
track_id && track_id_Arr.push(track_id[1]);
album_name = searchStr.match(/album_name:(.*), track_number:/);
album_name && album_Arr.push(album_name[1]);
}
console.log(artist_Arr)
console.log(track_id_Arr)
console.log(track_Arr)
console.log(album_Arr)
}
find(
[
`
artist_name: test, album_name:
`,
null
]
)
The problem is: I have big spreadsheet (more than 4500 rows) with a lot of data in the first column - for ex. with types of fruits, which are not unique, like this:
APPLE
BANANA
APRICOTS
APPLE
BLACKCURRANT
APPLE
BANANA
APRICOTS
etc.
What I need - locate each BANANA, to be able to put in cell beside some info, for ex. YES. I tried to loop solution from Locating a cell's position in google sheets using a string or an integer but for sure my code is wrong. I already spent a lot of hours to invent something, but still don't understand what I'm missing.
function test(){
var dispatch = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FRUITS");
var find = dispatch.getRange("A:A").getValues();
var name = "BANANA";
var lastRow = dispatch.getLastRow();
var n = 1;
var temp = dispatch.getRange(n, 2).getValue();
var i = 0;
while (temp != ""){
for(var n in find){
if(find[n][0] === name){break}
}
n++;
var n = n + i;
dispatch.getRange(n, 2).setValue("YES");
var temp = dispatch.getRange(n, 2).getValues();
var find = dispatch.getRange(n, 2, lastRow).getValues();
var i = n;
}
}
I will be very grateful for the help.
The code example is below:
function test(){
var dispatch = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FRUITS");
var range = dispatch.getRange(1, 1, dispatch.getLastRow(), 2);
var values = range.getValues();
values.map(function(row) {
if (row[0] == "BANANA")
row[1] = "YES";
});
range.setValues(values);
}
JS array map() method does the most part of work. We convert range values to JS array and back after mapping completes.
I modified the code this way... it gathers data from all the sheets and finds only the rows that have data, BUT now I am having a problem modifying the range with each pass so that it is equal to the number of rows that do have value (found with (values[row][0] != '')). I have put a ??? in the spot where I am trying to have a variable height.
function getAllData() {
var folder = DocsList.getFolderById("folderid");
var contents = folder.getFiles();
Logger.log("file length: " + contents.length);
var file;
var data;
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Base")
sheet.clearContents();
var numOfFiles = contents.length;
for (var i = 0; i < numOfFiles; i++) {
file = contents[i];
Logger.log("count: " + i);
var theFileType = file.getFileType();
Logger.log("theFileType: " + theFileType);
if (theFileType==DocsList.FileType.SPREADSHEET) {
var sheet2 = SpreadsheetApp.open(file).getSheetByName("Sheet 1");
var lastLine = sheet2.getLastRow();
var values = sheet2.getRange('A3:J').getValues();
var formulas = sheet2.getRange('A3:J').getFormulas();
var data = [];
for(var row = 0 ; row < (values).length ; row++){
var lastrow = sheet.getLastRow()+1;
if (values[row][0] != '') {
for(var col = 0 ; col < formulas[row].length ; col++){
if(formulas[row][col] != '')
{values[row][col] = formulas[row][col]};
data.push(values[row]);}
if(data.length > 0)
sheet.getRange(lastrow, 1, ???, data[0].length).setValues(data);
}
}
};
}}
You are using getValue() as opposed to getValues() (With a letter "s" on the end)
var onecell = posheet.getRange('B4').getValue();
The documentation states:
getValue() - Returns the value of the top-left cell in the range.
The parameter for getRange() is kind of tricky and not well documented.
For example this:
getRange(2, 3, 6, 4)
gets a range from C2 to G8. Figure that out. The first number is the number 2, which is for the row 2. The second number is 3, for the third column (which is C). The third and fourth numbers are relative to the first two numbers.
Also, you are using: appendRow([array]) which uses an array for the parameter. So you must make sure that the data is in the form of an array, or use something else.
Here is the link for getValues:
Google Documentation - getValues
The example is this code:
// The code below will get the values for the range C2:G8
// in the active spreadsheet. Note that this will be a javascript array.
var values = SpreadsheetApp.getActiveSheet().getRange(2, 3, 6, 4).getValues();
Logger.log(values[0][0]);
Here is code that seems to work:
function getAllData() {
var folder = DocsList.getFolderById("Your file ID");
var contents = folder.getFiles();
Logger.log("file length: " + contents.length);
var file;
var data;
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1")
sheet.clearContents();
sheet.appendRow(["Value from Sheet One", "Range of values from Sheet Two"]);
var numOfFiles = contents.length;
for (var i = 0; i < numOfFiles; i++) {
file = contents[i];
Logger.log("count: " + i);
//Reset to null on every iteration
var onecell = null;
var theRange = null;
var theFileType = file.getFileType();
Logger.log("theFileType: " + theFileType);
if (theFileType==DocsList.FileType.SPREADSHEET) {
var sheet1 = SpreadsheetApp.open(file).getSheetByName("Sheet1");
var sheet2 = SpreadsheetApp.open(file).getSheetByName("Sheet2");
// The code below will get the values for the range A3:A9
// in the active spreadsheet. Note that this will be a javascript array.
onecell = sheet1.getRange('B4').getValue();
theRange = sheet2.getRange(1,3,1,6).getValues();
Logger.log('onecell: ' + onecell);
Logger.log('onecell[0][0]: ' + onecell[0][0]);
Logger.log('theRange: ' + theRange)
Logger.log('theRange[0][0]: ' + theRange[0][0])
var multipleValues = [theRange[0][0], theRange[0][1], theRange[0][2], theRange[0][3], theRange[0][4]];
Logger.log('multipleValues: ' + multipleValues);
sheet.appendRow([onecell, "'" + multipleValues]);
};
}
}
In the first column, it only enters one value into the sheet cell. In the second column, the cell gets multiple values put into it from the row. In other words, and entire rows values, and combined and put into one cell. I think that's what you want from the code.
If you try to put an array into a spreadsheet cell, instead of showing the array of values as text, it shows something like an object. So I put a quote in front of the values so the cell formatting would default to text.
I am using multi dimension array to store data. It working but when we print it in console it show blank array and under it its showing two array, it should be show only one array inside.
It should look like this.
ar['outbound']['Meal']="111,121"
and its look in console like this
It is printing undefined also and one more thing
how to remove "," from the last
Here is fiddle
Code
var ar = [];
ar['Outbound'] = [];
ar['Inbound'] = [];
var ch="";
var sr= [];
sr['Meal']= [];
sr['Lounge']= [];
$('a').click(function(){
ch = $(this).parent().find('.no').text();
var boundType= $(this).parent().find('.bound').text();
ar[boundType][$(this).parent().find('.service').text()] +=($(this).parent().find('.no').text()) + ","; console.log(ar)
})
To avoid "undefined" you have to set a default value to your array items:
if (!ar[boundType][service]) {
ar[boundType][service] = '';
}
And it's better to add ',' before adding a new value:
if (ar[boundType][service].length > 0) {
ar[boundType][service] += ',';
}
See demo: http://jsfiddle.net/AVU54/1/
The problem is here:
ar[boundType][$(this).parent().find('.service').text()] +=($(this).parent().find('.no').text()) + ",";
Replace that with:
var temp = $(this).parent().find('.service').text();
ar[boundType][temp] = (ar[boundType][temp] + "," || '') + ($(this).parent().find('.no').text());
This checks if the variable exists.
Also, arrays can't have strings as indexes. Use objects, instead:
var ar = {};
ar['Outbound'] = {};
ar['Inbound'] = {};
// etc...