here the file
https://docs.google.com/spreadsheet/ccc?key=0AurtxTJwggIpdG9GaE1TOV9wMEw2UHhjZVJyUXVETUE
you'll find on sheet Key, what is meant to do :
Find in all sheets, first in column B the row where the reference (Key!B1) stands, then starting from this row, find in column C where the reference (Key!B2) stands for first
in other words, we are looking for the couple and make the cell in column C as activecell
the script is working in debug mode, only
running it using the button in sheet Key, make it "not select" the good cell, even if the cell to be selected is found (logged in Logger)
I use a color function
That mean, blue or red is the cell to be selected , and sometimes it's not selected
the code :
function lookFor() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var referSheet=ss.getSheetByName("Key");
var sheetToCheck = new Array;
sheetToCheck[0]=ss.getSheetByName("work");
sheetToCheck[1]=ss.getSheetByName("user");
sheetToCheck[2]=ss.getSheetByName("tax");
sheetToCheck[3]=ss.getSheetByName("cont");
sheetToCheck[4]=ss.getSheetByName("ind");
var referenceB=referSheet.getRange("B1").getValue();
var referenceC=referSheet.getRange("B2").getValue();
//loop to work with all reference as long as there are data in the column A
for (j in sheetToCheck){
sheetToCheck[j].setActiveCell("A1");
var dataToCheck=new Array;
dataToCheck=sheetToCheck[j].getRange(1,2,sheetToCheck[j].getLastRow(),2).getValues();
for (i in dataToCheck){
var done=false;
if (dataToCheck[i][0]==referenceB){
for (k=i;k<dataToCheck.length;k++){
if (dataToCheck[k][1]==referenceC){
//this part is user to change the color of the cell, to check if the code is working well
if (sheetToCheck[j].getRange(parseInt(k)+1,3,1,1).getBackgroundColor()=="red"){
sheetToCheck[j].getRange(parseInt(k)+1,3,1,1).setBackgroundColor("blue");
}
else
{
sheetToCheck[j].getRange(parseInt(k)+1,3,1,1).setBackgroundColor("red");
}
var cell=sheetToCheck[j].getRange(parseInt(k)+1,3,1,1).getA1Notation() ;
sheetToCheck[j].setActiveCell(cell);
SpreadsheetApp.flush();
done=true;
Logger.log("Sheet :"+sheetToCheck[j].getName()+" - Cell :"+cell);
break;
}
}
if (done==true){
break;
}
}
}
}
}
enter code here
I noticed you aready fixed this in your script:
var referenceB=referSheet.getRange("B1").getValue(); //A2
var referenceC=referSheet.getRange("B2").getValue(); //B2
Here is a shorter version of your code :)
function LookForCity() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var referSheet = ss.getSheetByName("Key").getDataRange().getValues()[1];
var sheetName = ["work", "user", "tax", "cont", "ind"];
for (j in sheetName){
var sheet = ss.getSheetByName(sheetName[j]);
var values = sheet.getDataRange().getValues();
for(i in values){
if(values[i][1] == referSheet[0] && values[i][2] == referSheet[1]){
Logger.log('Sheet: ' + sheetName[j]+ ' Cell: C'+(parseInt(i)+1) );
sheet.setActiveCell(sheet.getRange(parseInt(i)+1, 3));
Utilities.sleep(3000);
break;
}
}
}
}
Related
I need to take a sheet maintained by someone else and do the following (so that I can export to a csv):
unmerge all cells
fill values down
merged cells are in multiple columns, so I need to iterate over a range
It's too much to do it by hand, and it will need done periodically. My javascript and google sheets object model knowledge approximate zero, but I know it's possible because I could do it in VBA. I searched but can only find programmatic answers for VBA/Excel.
How can I do this efficiently in Google Sheets?
You can use the breakapart() class to do this. I am assuming that the merged range is not static and has multiple occurrences. This script will unmerge all merged ranges in the active sheet.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).breakApart();
}
Adapted from #lreeder's answer
The following breaks and fill blank with above on the selected range:
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('BreakAndFill')
.addItem('Break Fill Blank Cells', 'menuItem1')
.addToUi();
}
function menuItem1() {
BreakandfillBlankWithAbove()
}
//Breaks range
//Iterates over the range from top to bottom
//and left to right, and fills blank cells
//with the value right above them.
function BreakandfillBlankWithAbove() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveRange();
Logger.log('Range height is: ' + range.getHeight());
var values = range.getValues();
range.breakApart();
var width = values[0].length;
var height = values.length;
Logger.log('Width is ' + width);
Logger.log('Height is ' + height);
for (var i = 0; i < width; i++) {
var lastVal = '';
for(var j = 0; j < height; j++) {
var currValue = values[j][i];
var dataType = typeof(currValue);
//Empty string check returns true if dataType
//is a number, and value is zero. In that case
//we don't want to overwrite the zero, so only
//check emptyString for string types.
if(currValue === undefined ||
(dataType === 'string' && currValue == '')
) {
//getCell parameters are relative to the current range
//and ones based
var cell = range.getCell(j+1, i+1);
cell.setValue(lastVal);
}
else {
lastVal = currValue;
}
}
}
SpreadsheetApp.flush();
}
I'm trying to write a script where an automatic email is sent to a specific person upon edit of a cell and the cell equals "Done". However, I want the subject to be the first cell of the edited row. Cell that will contain "Done" is always going to be in the AA Column, and I want the subject to be the A column of the same row. Ex: AA3 was edited so subject is A3. I have spent hours sifting through tutorials and came up with this:
function checkValue() {
var sp = PropertiesService.getScriptProperties();
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Accts");
var valueToCheck = sheet.getRange("AA2:AA1000").getValue();
if (valueToCheck = 'Done') {
MailApp.sendEmail("a***a#gmail.com", activeCell.offset(-26,0).getValue(), Email.html);
}
}
Am I doing this entirely wrong or is there hope?
EDIT:
Now that it's resolved. I thought I'd share what my script ended up looking like. I added a UI and an option to execute using a menu option. Hope this helps someone else.
function onEdit(e)
{
var editRange = { // AA2:AA1000
top : 2,
bottom : 1000,
left : 27,
right : 27
};
// Exit if we're out of range
var thisRow = e.range.getRow();
if (thisRow < editRange.top || thisRow > editRange.bottom) return;
var thisCol = e.range.getColumn();
if (thisCol < editRange.left || thisCol > editRange.right) return;
var thisthang = e.value;
var doit = 'TRUE'
// We're in range; timestamp the edit
if(thisthang == doit)
{
doFinish();
}
else{return};
}
function onOpen()
{
var ui = SpreadsheetApp.getUi();
ui.createMenu('Finished')
.addItem('Finish', 'doFinish')
.addToUi();
}
function doFinish()
{
var cell = SpreadsheetApp.getActiveSheet().getActiveCell();
var row = cell.getRow();
var Campaign = getCampaignFromRow(row, 1);
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Finish '+Campaign.name+'?', ui.ButtonSet.YES_NO);
if(response == ui.Button.YES)
{
handleFinish(row, Campaign);
}
if(response == ui.Button.NO)
{
SpreadsheetApp.getActiveSheet().getRange(row, 27).setValue('FALSE');
}
}
function getCampaignFromRow(row)
{
var values = SpreadsheetApp.getActiveSheet().getRange(row, 1).getValues();
var rec = values[0];
var Campaign =
{
Campaign_Name: rec[0]
};
Campaign.name = Campaign.Campaign_Name;
return Campaign;
}
function handleFinish(row, Campaign)
{
var templ = HtmlService
.createTemplateFromFile('Campaign-email');
templ.Campaign = Campaign;
var message = templ.evaluate().getContent();
MailApp.sendEmail({
to: "a***a#gmail.com",
subject: "A Campaign has been finished!",
htmlBody: message
});
SpreadsheetApp.getActiveSheet().getRange(row, 27).setValue('TRUE');
}
You are trying to trigger an email when the spreadsheet is edited on the "Accts" sheet, in Column "AA" and the value = "Done".
The best solution is to use an onEdit trigger and also make use of Event Objects. In the case, "a simple trigger cannot send an email" ref, so you will need to create an Installable Trigger.
The main differences to your script are:
- var valueToCheck = sheet.getRange("AA2:AA1000").getValue();
- a couple of things here.
- 1) you are trying to get all the values in the column, but you use the getValue (the method for a single cell) instead of getValues.
- 2) you could have defined the ActiveCell and just returned that value
- 3) though you tried to get the values for the entire column, your if statement is designed as though there is a single value rather than an array of values.
- 4) This demonstrates the benefit of the using the Event Objects. You can succinctly get the values of the edited cell and sheet.
- in your if comparison, you use "="; this is only used to assign a value. When comparing values you must use "==" or "===".
- To get the value of the "subject", the script uses the row number derived from the Event Objects; compared to the offset in your script - they are both acceptable. I used the getRange to demonstrate the alternative.
- your email body was defined as "Email.html", but this isn't declared. The answer uses a very simple body but could just as easily use another solution.
function so5967209001(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet()
// establish the values to be checked
var checkSheetname = "Accts"
var checkValue = "Done"
var checkColumn = 27; // column AA
// this will return the event objects
//Logger.log(JSON.stringify(e)); // DEBUG
// variables to use for checking
var editedrange = e.range;
var editedrow = editedrange.getRow();
var editedcolumn = editedrange.getColumn();
var editedsheet = editedrange.getSheet().getSheetName();
var editedvalue = e.value;
//Logger.log("DEBUG: row = "+editedrow+", column = "+editedcolumn+", sheet = "+editedsheet+", value"+editedvalue)
// test the sheet, the column and the value
if (editedsheet ==checkSheetname && editedcolumn==checkColumn && editedvalue == checkValue){
//Logger.log("DEBUG: this is a match");
var subject = sheet.getRange(editedrow,1).getValue(); // Column A of the edited row
//Logger.log("DEBUG: email subject = "+subject);
// build your own body
var body = "this is the body of the email"
// send the email
MailApp.sendEmail("ejb#tedbell.com.au", subject, body);
//Logger.log("DEBUG: mail sent")
}else{
//Logger.log("DEBUG: this isn't a match");
}
}
Certain cell in rows have hyperlink. need hyperlink to follow row when copied from sheet to sheet based on other cell value
function moveToTab() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var range = ss.getActiveRange();
var col = range.getColumn();
Logger.log(col);
var aSheet = ss.getActiveSheet();
var header = aSheet.getRange(10,col,1,1).getValue();
Logger.log(header);
if (header.toLowerCase() !== 'issued to') return;
var target = range.getValue();
if (target.toString().trim() === '') return;
if (target.toString().toLowerCase() === aSheet.getName().toLowerCase()) return;
var sheets = ss.getSheets();
var tSheet = sheets.filter(function(sheet) {
if (sheet.getName().toLowerCase() == target.toLowerCase()) return true;
else return false;
})[0];
if (!tSheet) return;
var row = range.getRow();
var values = aSheet.getRange(row, 1, 1, aSheet.getLastColumn()).getValues();
tSheet.appendRow(values[0]);
aSheet.deleteRow(row);
I know I am missing something simple. In my work book column "F" has a hyperlink to files. I am using the above script to move certain rows from sheet to sheet based on value in Column "K" and would like the hyper link in the cell in column "F" to follow teh row from sheet to sheet. What am i missing
I am trying to create a program that will invite email addresses from a column of cells. However, I only want the cells that have content in them to be used in the program and the empty cells to be ignored. Since the cells are linked to a form, as soon as the program finds a single empty cell as it searches down the column, it should stop looking for more empty cells. This is what I have so far:
function addEditor() {
var sheet = SpreadsheetApp.getActive().getSheetByName('GuestList');
var Blank = sheet.getRange('a51').getValue().isBlank;
for (var i = 2; Blank = true; i++){
var Blank = sheet.getRange(2, 1, i, 1).isBlank;
if (Blank === true){ break;
}
}
var Editors = sheet.getRange(2, 1, i, 1);
sheet.protect().addEditors([Editors]);
}
Try something like this:
function sendEmails() {
var glist=SpreadsheetApp.getActive().getSheetByName('GuestList');
var gdata=glist.getDataRange().getValues();
for (var i=1;i<gdata.length;i++){
if(gdata[i][0]){
//sendEmail
}else{
break;
}
}
}
screenshot
Hi all, i need help and i am not a coder. I am trying to achieve the same thing on sheet number 2.
My datas are imported through "=Submission!$b2" from sheet 1
i need help removing rows automatically when a specific cell on column H does not contain the value "Bekreft", i tried both codes shown here with no success.
This is what i added for script:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('DATA - Do Not Touch!!!'); // change to your own
var values = s.getDataRange().getValues();
for(var i=values.length;i>0;i-=1){
var lcVal=values[i-1][0].toLowerCase() //Change to all lower case
var index = lcVal.indexOf("vent"); //now you only have to check for contains "vent"
if (lcVal.indexOf("vent") > -1){
s.deleteRow(i)};
}}
Seeing as you state you are "not a coder", and the code you pasted will not help you if you are referencing data from another page, I would suggest using a filter function to achieve your goal. You would add the following formula to your second page:
=FILTER(Submission!B:B,ISNUMBER(SEARCH("Bekreft", Submission!H:H)))
If you are looking to have a script go through your static list and delete out values that do not contain "Bekreft" then you can use the following script.
function onEdit() {
var sheet = SpreadsheetApp.openById("Add Sheet ID").getSheetByName('Sheet1');
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var rowsDeleted = 0;
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
//row for condition
if (row[7].indexOf("Bekreft")) {
sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
}
};