How do I get the values of my spreadsheet columns - javascript

I'm new to apps script and javascript but I managed to get all the defined value numbers or column numbers right except for one that is about 200 columns to the right. But column numbers don't always ad up as it seems like it skips some empty columns sometimes but not others for some reason. Is there a way to number the columns with a script? I found this one which runs successfully but I don't know how to print the result.
function getValue() {
var values = SpreadsheetApp.getActiveSheet().getDataRange().getValues()
}

function numberColumns() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getActiveSheet();
const rg=sh.getRange(1,1,1,sh.getMaxColumns());
var v=rg.getValues()[0].map(function(e,i){return i+1;});
sh.insertRowBefore(1);//inserts a row first to hold column numbers
rg.setValues([v]);
}

Related

How Do I Copy Non-Adjacent Cell Values to a Row for a Log Sheet?

I want to copy three cells, which are non-adjacent (AA9, AA12, and AA15), and paste them on another sheet in a single row, like a log sheet. (A2,B2,C2) I'm using "getLastRow+1" to make this happen. Currently, I'm only able to use getValue and setValue for a single cell (AA9) and after searching for similar examples online, I'm still struggling to make this work.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Main")
var destSheet = ss.getSheetByName('Log');
// Get the Cell Values from Main Sheet
var streak = sheet.getRange('AA9').getValue();
// Set the Values on Log Sheet
destSheet.getRange(destSheet.getLastRow()+1,1).setValue(streak);
I'm struggling to understand how to correctly implement what I want. I essentially want to copy the values in AA9, AA12, and AA15, and paste them (or use setValue) in A2,B2, and C2 on the other sheet.
I'm slowly learning and getting a better understanding of everything, and examples from google searches have gotten me far, but this is a headscratcher for me.
I've tried using Named Ranges, but I didn't understand how to find the last EMPTY row of that named range.
I've tried creating an Array for those cells, but didn't understand how to use SetValues correctly (got an error about the number of rows not being equal to the data rows, something like that)
// THIS DIDN"T WORK
var results = ['AA9','AA12','AA15'];
var streak = sheet.getRangeList(results).getRanges().map(range => range.getValues());
destSheet.getRange(destSheet.getLastRow()+1,1).setValues(streak);
I've also searched google quite a bit, and while the results have helped me script a random number generator (not shown here), I still struggle with more basic tasks.
You can make your latter code example work by using Range.getValue() instead of Range.getValues().
To easily append the values to the destination sheet, use Sheet.appendRow(), like this:
const sheet = ss.getSheetByName('Main');
const destSheet = ss.getSheetByName('Log');
const data = sheet.getRangeList(['AA9', 'AA12', 'AA15'])
.getRanges()
.map(range => range.getValue());
destSheet.appendRow(data);
Try it this way:
function myfunk() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
const dsh = ss.getSheetByName('Sheet1');
const [a,,,b,,,c] = sh.getRange("AA9:AA15").getValues().flat();
dsh.appendRow([a,b,c]);
}
When I use getValues, it works perfectly! But it does throw an error, saying "Exception: The parameters (number[]) don't match the method signature for SpreadsheetApp.Range.setValues.". But again, it does actually work on my spreadsheet.
When I use getValue, it strangely works, and doesn't throw an error, it sets the values appropriately in an appended row, but then loops back around again and repeatedly sets the value in the first cell again, albeit one row down (because it just filled the previous row so it moves down). It's so strange. I can see it do it slowly, it sets the values in the row, a split second later it loops back to the first value, but one row down, and sets that value again. But none of the other ones.
If you can visualize this, it'll post 3 numbers, correctly, appended in the row, then one row down it'll post only 1 number, but leave the other two blank.
Screenshot Example
function log_data() {
const data = sheet.getRangeList(['AA9','AA12','AA15'])
.getRanges()
.map(range => range.getValue());
destSheet.appendRow(data);
destSheet.getRange(destSheet.getLastRow()+1,1).setValue(data);
}

Trouble getting App Script to read data in multiple ranges

I am currently trying to get App Script to read a ranges of cells from different sheets in a workbook, but I keep getting "Range not found (line 30). I have a bit of experience with Javascript, but App Script is fairly new to me, so some tips and where to find good documentation or tutorials would really help as well.
function getvalues(values2) {
var sheet = SpreadsheetApp.getActiveSheet().getRange(values2)
var raw_values = []
for (var i = 0; i < sheet.length; i++) {
raw_values.push(sheet[i])
}
return raw_values
}
Edit
Here is what the value2 is. They're ranges separated by commas, and each range is from a different sheet in the workbook.
January!W22:W35,February!W22:W35,March!W22:W35,April!W22:W35,May!W22:W35,June!W22:W35,July!W22:W35,August!W22:W35,September!W22:W35,October!W22:W35,November!W22:W35,December!W22:W35
According to the docs, getRange() doesn't seem to specify a comma separated list of ranges as a valid argument. The error is most likely because the function is trying to interpret the entire string as a single range.
You may need to retrieve each range separately and then aggregate them in some way.
I've included an example of how you might do this.
let myRanges = "January!W22:W35,February!W22:W35,March!W22:W35"
function getvalues(values2) {
let raw_values = []
values2.split(",").forEach(a1range => {
let range = SpreadsheetApp.getActiveSheet().getRange(a1range)
console.log(range.getValues())
// get the values from the range and push them to raw_values
})
return raw_values
}
getvalues(myRanges)
Additionally, it looks like getRange() will return a Range object, which doesn't directly contain the values from the range, but has the methods getValue() and getValues() to return the values from the selected cells. getValues appears to return a multidimensional array representing the rows/columns from your range, so you'll need to do some extra processing depending on how you need your data formatted.
https://developers.google.com/apps-script/reference/spreadsheet/range#getValue()
Considering that, it would probably also be a good idea to change the function name to something other than getvalues to avoid confusion.

getLastRow() stops at row 68

I have this function that is supposed to pull form data from one sheet then add it to another but it stops at row 68.
function fData(){
const os = SpreadsheetApp.openById("ID of Sheet with data to copy");
const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Data");
const dataToCopy = os.getSheetByName("Form Data").getRange(1,1,os.getLastRow(),7).getValues();
const dataDst = ss.getRange(1,1,os.getLastRow(),7).clearContent().setValues(dataToCopy);
// Logger.log(dataToCopy);
}
When I change os.getLastRow() to 192 in both locations where it appears in the function, all the information is copied over correctly. I would like to not have to specify the number of rows every time I run the function.
I think there is something wrong with my implementation of getLastRow() or the fact that both the copy and paste sheets share the same name but I am unsure if that is what causes the issue.
Here is the solution that got the desired result. There might be a better way but this worked.
function fData(){
const os = SpreadsheetApp.openById("ID of Sheet with data to copy");
const ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Data");
const dataToCopy = os.getSheetByName("Form Data").getDataRange().getValues();
const lr = os.getSheetByName("Form Data").getDataRange().getLastRow();
const dataDst = ss.getRange(1,1,lr,7).clearContent().setValues(dataToCopy);
// Logger.log(dataToCopy);
}
I used getDataRange to pull the data, then defined lr as the last row of that data set. If you just replace the first instance of getLastRow with getDataRange you run into an error in which the target range and data set do not match in rows and columns and the function with push an error.
getLastRow(): this will get the last row in a Google Sheet that has data in it. It determines the last row based on the last available row value in all columns in the spreadsheet.
getDataRange(): this will get the range up to the last row and column with values in it.
Use getDataRange() instead. One of your columns must not have data in row 68.
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getdatarange

Copy filtered range from one spreadsheet to another - Google app script

I have a large google sheet with 30275 rows and 133 columns in a google sheet. I want to filter the data and copy column AZ to another spreadsheet.
Link to spreadsheet: https://docs.google.com/spreadsheets/d/1aiuHIYzlCM7zO_5oZ0aOCKDwPo06syXhWvhQMKgJE2I/edit?usp=sharing
I have been trying to follow this link
I am not that familiar with javascript and the code is designed to exclude items from filter rather than including items on filter. I have 500+ items to exclude so need to work out something that will be efficient in filtering large dataset in short time before execution limit is reached.
Here is my code so far. Any help to get this working would be appreciated.
NOTE: Filter/ Query with importrange formulas dont work due to the large volume of data. So I need an efficient script to filter large dataset and move them to another sheet before execution time limit.
function filtered() {
var ss = SpreadsheetApp.openById('1u9z_8J-tvTZaW4adO6kCk7bkWeB0pwPcZQdjBazpExI');
var sheet = ss.getSheetByName('Sheet1');
var destsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('JockeyList');
var demosheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Betting data - Demo');
var jockey = demosheet.getRange('L14').getValues();
// Get full (non-filtered) data
var values = sheet.getRange('A:EC').getValues();
// Apply filter criteria here
//Logger.log(jockey);
var hiddenValues = jockey;
values = values.filter(function(v) {
return hiddenValues.indexOf(v[51]) == 1;
});
Logger.log(values.length);
// Set filtered data on the target sheet
destsheet.getRange(10, 5, values.length, 2).setValues(values);
}
Ok so it seems like you want to copy only the values from AZ in 'Sheet1' that are equal to whatever string value is contained in cell L14 of sheet 'Betting data - Demo.' If that is the case, then here is a change to your original code that will accomplish that:
function filtered() {
var ss = SpreadsheetApp.openById('1u9z_8J-tvTZaW4adO6kCk7bkWeB0pwPcZQdjBazpExI');
var sheet = ss.getSheetByName('Sheet1');
// this assumes that your destsheet and demosheet are in the same spreadsheet. Keep in mind that opening spreadsheets with SpreadsheetApp is costly so you want to minimize your calls to new sheets.
var destsheet = ss.getSheetByName('JockeyList');
var demosheet = ss.getSheetByName('Betting data - Demo');
var jockey = demosheet.getRange('L14').getValue();
var searchTerm = new RegExp(jockey);
// Get full (non-filtered) data
var values = sheet.getRange('A:EC').getValues();
// Apply filter criteria here and return ONLY THE VALUE IN COLUMN AZ
var filteredValues = values.reduce(function(resultArray, row) {
if (searchTerm.test(row[51])) resultArray.push([row[51]]);
return resultArray;
}, [])
// Set filtered data on the target sheet
// Note* not clear why you are starting at row 10, but as is this will overwrite all of the data in column 5 of destsheet starting from row 10 every time this function runs
destsheet.getRange(10, 5, filteredValues.length, 1).setValues(filteredValues);
}
As it says in the code sample, this will only copy and paste the value in column AZ of 'sheet1'. It does not alter 'sheet1' in any way. If that is really all you want to do, then this function works, but it's overkill. Since you are just filtering values in AZ against a single string value, it would be more efficient to simply count the number of times that string occurs in column AZ and then add the string that number of times to your destination sheet.
Also note that your original function is pasting values into destsheet into a constant row (row 10). That means that every time your function runs, the data from row 10 on will be overwritten by whatever data you are copying from 'sheet1'

I need help creating a script to hide columns in google sheets if cells in range are empty

I am trying to create a script which will hide columns where cells in a range are empty (the condition).
Below is what my table looks like, you can see there are 12 roles. I basically want to hide any columns from Role 4 onwards which are unused e.g. no values in the 3 rows.
i have a script that works (see below) but it also hides Roles 1, 2 and 3 if they are blank. I want the script to only work from Role 4 (column F) onwards. What do i need to change in the script for this to work?
P.s. I have used code from other posts to put this together so there may be lines in the code I do not need, I am still very new to google script.
function hidecolumns() {
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getSheetByName("Project Team Resources");
var r = ss.getRange("C5:N10");
var data = r.getValues();
var rData, cData, x;
cData = data[0].map(function (col, c) {
return data.map(function (row, r) {
return data[r][c];
});
});
Logger.log(cData.length);
Logger.log(data.length);
for(var i=0;i<cData.length;i++){
if(cData[i].filter(String).length==0)
ss.hideColumns(i+3)
}
}
Explanation:
Your goal is to hide a column if it is empty with the exception of the first three columns in the range.
One approach to achieve this to iterate over all columns in the desired range and check if they contain at least one non-empty value (length>0). If the length is 0, meaning that all values in this column are empty, then hide it.
In more detail, I use a forEach loop to iterate over each column. Each column is given by a simple map expression:
data.map(d => d[col]) where col takes values 0, 1, 2, ...
I filter on the non-empty values and hide only columns if the length of the non-empty array is 0.
Since the data range starts from column C which is the 3rd column, I hide column col+3. Be careful with this, since it depends on the input range.
Finally, your goal is to keep the first 3 columns (Roles 1,2,3) fixed-unhidden regardless if they contain values or not. To do that, add an extra condition in the if condition to check if column is larger than 2: col>2.
Solution:
function hidecolumns() {
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getSheetByName("Project Team Resources");
var data = ss.getRange("C5:N10").getValues();
data[0].forEach((_,col)=>{
if(data.map(d => d[col]).filter(e=>e!='').length==0 && col>2){
ss.hideColumns(col+3);
}
});
}
underscore as a parameter reference

Categories

Resources