How to get row and col from e with onEdit - javascript

I'm trying to get the coordinates of the modified cell with a script in order to perform some actions, in the documentation I see that e.range returns a range object, so according to this documentation
if I'm not mistaking, I should be able to perform e.range.getRow() or e.range.getCol().
I tried this :
function onEdit(e) {
const RANGE = e.range;
let row = RANGE.getRow();
let col = RANGE.getCol();
Logger.log('line : ', row, 'column : ', col)
}
but nothing happens except this in th executions tab:
TypeError: RANGE.getCol is not a function
at onEdit(script:5:19)
Whet am I doing wrong?

Use the properties of the event object as Cooper recommends. To answer your question, the Range() object does not have a .getCol() method. The correct method is .getColumn().
See these onEdit(e) optimization tips.

Related

having trouble with a simple copy and paste function in google scripts

i'm trying to call a function from the menu bar to copy a set of values in google sheets to an "archive" tab. The error i'm getting is "Exception: The parameters (SpreadsheetApp.Range) don't match the method signature for SpreadsheetApp.Range.setValues." here is the code:
function archiveCompleted () {
var spreadsheet = SpreadsheetApp.getActive();
var copyFrom = spreadsheet.getSheetByName("completed autofill");
var copyDest = spreadsheet.getSheetByName("Completed Orders");
var sourceRange = copyFrom.getRange(1,1,copyFrom.getLastRow(),copyFrom.getLastColumn());
var destRange = copyDest.getRange(copyDest.getLastRow() + 1,1,copyFrom.getLastRow(),copyFrom.getLastColumn());
//1,1,copyFrom.getLastColumn());
sourceRange.copyValuesToRange(destRange);
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Copy From Feildpine'),true);
}
thanks for any help!
I thought that about your error message of Exception: The parameters (SpreadsheetApp.Range) don't match the method signature for SpreadsheetApp.Range.setValues., unfortunately, I cannot find setValues in your showing script. So I'm worried that you miscopied your current script.
But, when I saw your script, I thought that sourceRange.copyValuesToRange(destRange); is required to be modified. Because the arguments of copyValuesToRange are gridId, column, columnEnd, row, rowEnd or sheet, column, columnEnd, row, rowEnd. Ref1, Ref2
So, in this modification, I would like to propose modifying the line as follows.
From:
sourceRange.copyValuesToRange(destRange);
To:
sourceRange.copyTo(destRange, {contentsOnly: true});
Reference:
copyTo(destination, options)

How can I leave a blank space/column inside an appended row?

I'm trying to leave a blank column in between data of an appended row, so that I can add a VLOOKUP function, functionally I don't need to do this (I could just add the VLOOKUP to the end of the row), but aesthetically it would be better if I could. Is there a way to just skip a column when appending data into a row?
Explanation:
You can use two separate setValues statements to achieve your goal and paste the data right after the last row with content with getLastRow().
I have fully described each block of lines in the following script so I think it is straightforward to work with it.
I tried to create a generic code where you can select:
the column you want to separate the data: sep_col
the starting column you want to paste the data: start_col
the number of columns you want to have between the two different datasets: space_col
Code snippet:
function myFunction() {
// get spreadsheet details
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet1'); // change that to the name of your sheet
// provide some data
const sep_col = 3; // column you want to separate the data
const data = ["d1","d2","d3","d5","d6"];
const data1 = data.slice(0,sep_col);
const data2 = data.slice(sep_col,data.length);
// get current last row of document
const Lrow = sh.getLastRow();
// paste the data to separate ranges
const start_col = 1;
const space_col = 1;
sh.getRange(Lrow+1,start_col, 1, data1.length).setValues([data1]);
sh.getRange(Lrow+1,start_col+data1.length + space_col, 1, data2.length).setValues([data2]);
}
JavaScript References:
Array.prototype.slice()
Sheet used for the code snippet:

Google Sheets + Monday.com API - Change column value

I managed to connect the Monday.com API with google sheets using Scripts and create a new item in my board, however, I can only insert the item name, how can I insert a value in my column.
Code example:
function Create_Line()
{
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName("tests");
var values = sh.getDataRange().getValues();
var mondayAPIkey = "API_KEY"
for(var i=1;i<values.length;i++)
{
if(values[i][7]=="")
{
var query = "mutation($board:Int!, $name:String!,$colvals:JSON!){create_item(board_id:$board, item_name:$name, column_values:$colvals){id}}";
var variables = {
"board" : "board_id",
"name" : values[i][0], //where column A has the name I want for the item
"colvals": JSON.stringify({ "column_id": "Coluna 1", "value": "Done"}) //calling the now formatted date variable
};
var pulseID = JSON.parse(makeAPICall(mondayAPIkey, query, variables)).data.create_item.id;
sh.getRange(i+1, 8).setValue(pulseID)
}
}
}
EDIT: To explain the question in a better way, the result that I'm looking for is this:
The script runs through the entire google sheets list and creates the lines on Monday.com, the problem is that I can not fill the column value
The column values argument you're passing to the monday.com API is in the wrong format. I cannot find your column ID in your original post, so I'm going to assume it's 'coluna_1'.
Try changing your variables to this:
var variables = {
"board" : YOUR_BOARD_ID,
"name" : values[i][0],
"colvals" : JSON.stringify({"coluna_1" : "Done"})
}
According to the official monday API Quickstart:
Our GraphQL schema defines a set of column values as a JSON string (key-value pairs). The keys of the column_values object must be column IDs, and the values must be structured depending on the type of the column.
You can find the column ID by enabling developer mode, as described in this article.
The value depends on the column type in monday.com. You can see a list of columns supported by the monday.com API here: API Documentation

How to compare two sheets and delete/add any column with a distinct value in row 1? Google Script

I want to compare two sheets (based on header values in row 1) and delete any column with a unique value (without a match). For example, Assuming Sheet1, Row 1 data and Sheet 2, Row 1 are uniform, if a user adds/deletes a column within any sheet, I want to always match the number of columns in both sheets with their values
Screenshots of sheets headings.
IF both sheets looks like this
And a user adds a new Column N
Or delete column N
How can I ensure that both sheet matches by deleting the odd/distinct column in Sheet 1?
I have tried modifying this code below but I can't just get the unique one out. This code only look for headers with a defined value.
function deleteAloneColumns(){
var sheet = SpreadsheetApp.getActiveSheet();
var lastColumnPos = sheet.getLastColumn();
var headers = sheet.getRange( 1 ,1, 1, lastColumnPos ).getValues()[0];
for( var i = lastColumnPos ; i < 1; i--){
if( headers[i] === "alone" ) sheet.deleteColumn(i);
}
SpreadsheetApp.getUi().alert( 'Job done!' );
}
Any help to compare and delete the column with the unique value will be appreciated.
Problem
Balancing sheets based on header row values mismatch.
Solution
If I understood you correctly, you have a source sheet against which validation is run and two primary use cases: user adds a new column named differently than any other column (if you want to check that the column strictly matches the one in sheet1, it is easy to modify) in source sheet or deletes one that should be there.
const balanceSheets = (sourceShName = 'Sheet1',targetShName = 'Sheet2') => {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const s1 = ss.getSheetByName(sourceShName);
const s2 = ss.getSheetByName(targetShName);
const s2lcol = s2.getLastColumn();
//keep all vals from source to reduce I/O
const s1DataVals = s1.getDataRange().getValues();
const s2Vals = s2.getRange(1, 1, 1, s2lcol).getValues();
const h1Vals = s1DataVals[0];
const h2Vals = s2Vals[0];
//assume s1 is source (validation) sheet
//assume s2 is target sheet that a user can edit
//case 1: target has value not present in source -> delete column in target
let colIdx = 0;
h2Vals.forEach(value => {
const isOK = h1Vals.some(val => val===value);
isOK ? colIdx++ : s2.deleteColumn(colIdx+1);
});
//case 2: target does not have values present in source -> append column from source
h1Vals.forEach((value,index) => {
const isOK = h2Vals.some(val => val===value);
!isOK && s2.insertColumnAfter(index);
const valuesToInsert = s1DataVals.map(row => [row[index]]);
const numRowsToInsert = valuesToInsert.length;
s2.getRange(1,index+1, numRowsToInsert,1).setValues(valuesToInsert);
});
};
Showcase
Here is a small demo of how it works as a macros:
Notes
Solving your problem with two forEach is suboptimal, but I kept number of I/O low (it can be lowered further by, for example, moving deleteColum out of the loop while only keeping track of column indices).
The script uses ES6 capabilities provided by V8, so please, be careful (although I would recommend migrating as soon as possible - even if you encounter bugs / inconsistencies , it is worth more than it costs.
UPD made script more flexible by moving sheet names to parameter list.
UPD2 after discussing the issue with deleteColumn() behaviour, the answer is updated to keep column pointer in bounds (for those curious about it - forEach kept incrementing the index, while deleteColumn reduced bounds for any given index).
Reference
insertColumnAfter() method reference

Retrieve Google Sheets column by header name

Is there a way to retrieve a column dynamically by it's column name (header)?
Instead of:
var values = sheet.getRange("A:A").getValues();
Something like: (Just for simplicity)
var values = sheet.getRange(sheet.column.getHeader("name").getValues();
Please keep in mind that Google Apps Script is roughly ES3.
You can write one ;)
function getColValuesByName(sheet, name) {
var index = sheet.getRange(1,1,1,sheet.getLastColumn()).getValues()[0].indexOf(name);
index++;
return sheet.getRange(1,index,sheet.getLastRow(),1).getValues();
}
Here's a very simple one-line function you can copy. It returns the column number (A = 1, B = 2, etc.) for use in getRange, for example.
function getColByHeader(name) {
return SpreadsheetApp.getActiveSheet().getRange('1:1').getValues()[0].indexOf(name) + 1;
}
Although there is no direct way, there are plenty of ways to get what you want with a little set up:
Get all data and filter it(no set up):
var values = sheet.getDataRange().getValues();
var headers = values.splice(0,1);
headerIdx = headers[0].indexOf("name");
values = values.map(function(row){return [row[headerIdx]];})
Named ranges set up:
If you have named ranges associated with that column,
spreadsheet.getRangeByName('Sheet Name!name').getValues();//where 'name' is a named range
Developer metadata set up:
If you have developer metadata associated with that column,
SpreadsheetApp.getActive()
.createDeveloperMetadataFinder()
.withKey(/*METADATA_KEY_ASSOCIATED_WITH_COLUMN*/)
.find()[0]
.getLocation()
.getColumn()
.getValues();

Categories

Resources