I'm trying to implement the countdown script from https://developers.google.com/adwords/scripts/docs/tutorials/countdown-sale
The script works for single Ad Group but when trying to Multiple ad groups part of I keep getting following error:
TypeError: Cannot call method "setAdParam" of undefined. (line 9)
My full script is:
// Date to use to find out how many days are remaining.
var END_DATE = new Date('February 24, 2013');
// Change this to the Ad Group you set up with text ads with AdParams.
var AD_GROUP_NAMES = ['AdGroup1', AdGroup2'];
function main() {
var timeLeft = calculateTimeLeftUntil(END_DATE);
var adGroups = getAdGroups(AD_GROUP_NAMES);
while (adGroups.hasNext()) {
var adGroup = adGroups.next();
var keywords = adGroup.keywords().get();
// We want to update {param1} to use our calculated days and {param2} for hours.
keywords.setAdParam(1, timeLeft['days']); // HERE COMES THE ERROR
keywords.setAdParam(2, timeLeft['hours']);
}
}
var DAY_IN_MILLISECONDS = 1000*60*60*24;
function calculateTimeLeftUntil(end) {
var current = new Date();
var timeLeft = {};
var daysFloat = (end - current) / (DAY_IN_MILLISECONDS);
timeLeft['days'] = Math.floor(daysFloat);
timeLeft['hours'] = Math.floor(24 * (daysFloat - timeLeft['days']));
return timeLeft;
}
function getAdGroups(names) {
var predicateValues = "['" + names.join("','") + "']";
Logger.log(predicateValues);
return AdWordsApp.adGroups()
.withCondition('Name IN ' + predicateValues)
.withLimit(names.length)
.get();
}
The issue is that you're trying to set the ad param to a keyword iterator, not individual keywords.
Instead of this
var keywords = adGroup.keywords().get();
// We want to update {param1} to use our calculated days and {param2} for hours.
keywords.setAdParam(1, timeLeft['days']); // HERE COMES THE ERROR
Try this:
var keywords = adGroup.keywords().get();
while (keywords.hasNext()) {
var keyword = keywords.next();
// and now
keyword.setAdParam(...);
}
Related
I looking for script, that will create audit log in another sheet. In this log it should be:
1)Time stamp
2)User who edited cell
3)The value of the edited cell
I tryed many of tutorial, but I am really new in this and little lost.
This script will log all activities in the sheet "Logging"
function onEdit(e) {
var email = Session.getEffectiveUser().getEmail();
var timeZone = Session.getScriptTimeZone();
var key = Session.getTemporaryActiveUserKey();
var sName = e.source.getActiveSheet().getSheetName();
if(sName !== "Logging") {
var value;
var mA1 = e.range.getA1Notation().split(":")[0];
if(typeof(e.value) == 'string') {
var aCell = e.source.getRange(mA1);
value = aCell.getValue();
var form = "'" + aCell.getFormula();
} else {
value = e.value;
}
var data = [sName, mA1, timeZone, email, key, value, form];
e.source.getSheetByName("Logging").appendRow(data);
}
}
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");
}
}
I am trying to find about getting a script that when I put my part number and qty in it adds to my list and when the wrong part number is entered it displays in error message that says invalid part number.
I am not sure if i am on the right track. this is what I have currently.
function addQty() {
var ssheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ssheet.getSheetByName('List');
var inputPartnum = ssheet.getRange("K2").getValue();
var inputQty = ssheet.getRange("$L$2").getValue();
var partNum1 = ssheet.getRange("I").getValue();
if (inputPartnum=partNum1){
var num1 = ssheet.getRange("C").getValue();
ssheet.getRange("C").setValue(inputQty+num1);
ssheet.getRange('K2').clear();
ssheet.getRange('L2').clear();
}
else {
catch (error) {
throw new Error( "Part Number Not Found" );
ssheet.getRange('K2').clear();
ssheet.getRange('L2').clear();
}
}
}
You were close. You need to loop through the part numbers looking for a match. Try this:
function addQty() {
var ssheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ssheet.getSheetByName('List');
var lr= sheet.getLastRow()
var inputPartnum = sheet.getRange("K2").getValue().toLowerCase();
var inputQty = sheet.getRange("$L$2").getValue();
var partNum1 = sheet.getRange(6,9,lr,1).getValues();//Array of part numbers
var count=0 //Set counter
for(var i=0;i<partNum1.length;i++){ //Loop through part numbers
if (inputPartnum == partNum1[i][0].toLowerCase()){
var num1 = ssheet.getRange("C"+(i+6)).getValue(); //Get current part count
ssheet.getRange("C"+(i+6)).setValue(inputQty+num1);
count=count+1 //Add to count if a match is found
ssheet.getRange('K2').clear();
ssheet.getRange('L2').clear();
break
}}
if(count==0){// If no matching part number is found give message.
Browser.msgBox( "Part Number "+inputPartnum+" Not Found" );
ssheet.getRange('K2').clear();
ssheet.getRange('L2').clear();
}}
I changed the script to get all the part numbers. If this is not what you are after, please explain what you are after.
I'm trying to create an app script that you can type in the name and username of an individual and select various dates associated with their training. I'm nearly done with the project but one piece of script is giving me issues. What the script is supposed to do is take the User Name I've entered into the app and see if that value already exists in column L of the archive. If the value exists then it should return an alert with a YES_NO option and depending on what is selected it will either cancel the import or continue on and import the username to the sheet.
I've been trying to figure out this script for about 5 days and cannot figure it out. I've tried pretty much everything I can think of. Here's the code. The Username already exists in Cell L3 of the Archive.
function postApp(e)
{
var usern = e.parameter.userN;
var name1 = e.parameter.name;
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var tM = sheet.getSheetByName('Archive');
var tR = tM.getLastRow()-1;
var tC = tM.getLastColumn();
var tD = tM.getRange("L3").getValues();
if(tD == usern )
{
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.alert('Wait', 'The Username you are trying to use has already been archived. Would you still like to continue?', ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.Yes) {
// User clicked "Yes".
SpreadsheetApp.getActiveSpreadsheet().toast('Error Report Has Been Updated', 'UPDATE ERRORS',3);
var date = new Date();
var d = Utilities.formatDate(date, Session.getScriptTimeZone(), 'M/d/yyyy');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('SyNERGY');
var lR = s.getLastRow()+1;
var lC = s.getLastColumn();
var app = UiApp.getActiveApplication();
var name = e.parameter.name;
var user = e.parameter.userN;
var team = e.parameter.team;
var hire = e.parameter.hire;
////////////////////////////
// CREATE REPORT CARD
genReportCard(name, team, hire, app, user);
s.getRange(lR,12).setValue([[user]]).setNumberFormat(';;;');
s.getRange(lR,12).setValue(user.toString().toLowerCase());
s.getRange(lR,11).setValue('SyN');
///////////////////////////////////////////
///////////Close after complete////////////
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.alert("Specialist Created!");
var app = UiApp.getActiveApplication();
app.close();
return app;
}else {
// User clicked "No" or X in the title bar.
ui.alert('Import Canceled');
}
}else{
var date = new Date();
var d = Utilities.formatDate(date, Session.getScriptTimeZone(),
'M/d/yyyy');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('SyNERGY');
var lR = s.getLastRow()+1;
var lC = s.getLastColumn();
var app = UiApp.getActiveApplication();
var name = e.parameter.name;
var user = e.parameter.userN;
var team = e.parameter.team;
var hire = e.parameter.hire;
////////////////////////////
// CREATE REPORT CARD
genReportCard(name, team, hire, app, user);
s.getRange(lR,12).setValue([[user]]).setNumberFormat(';;;');
s.getRange(lR,12).setValue(user.toString().toLowerCase());
s.getRange(lR,11).setValue('SyN');
///////////////////////////////////////////
///////////Close after complete////////////
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.alert("Specialist Created!");
var app = UiApp.getActiveApplication();
app.close();
return app;
}
}
This script Works as long as I am referencing One Cell so tM.getRange("L3").getValues(); Works. However, As soon as I change that to tM.getRange("L3:L").getValues(); it does not recognize the value exists within the range and returns the else portion of the code.
I have also tried a loop for the top section that is giving me issues but the same thing is happening. As soon as I try to find a value within the column rather than a specific cell it won't work. Here is what it looks like with the loop.
function postApp(e)
{
var usern = e.parameter.userN;
var name1 = e.parameter.name;
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var tM = sheet.getSheetByName('Archive');
var tR = tM.getLastRow()-1;
var tC = tM.getLastColumn();
var tD = tM.getDataRange().getValues();
for(var i = 0; i<tD.length; i++){
if(tD[i][11] == usern )
{
If anyone can figure out what i'm doing wrong or why it's not working as soon as I reference the entire column any help would be greatly appreciated.
Thanks!
I'm trying to create a script in google sheets. What I'm trying to do is to search the value of a cell (let's say A2 sheet1), then change the value of another cell (B2 sheet2). When the first iteration is over, proceed to the next row (A3 sheet1) and again change the value of B2. Also wait 10 secs at the end of every iteration.
I don't know why it is not working. After I run the code it just says "Finished", but nothing has changed.
function test() {
var ss = SpreadsheetApp.getActive();
var gensheet = ss.getSheetByName('Generador SE');
var clientsheet = ss.getSheetByName('Clientes SE');
var clientrange = clientsheet.getRange("A1:C200");
var clientsquantity = clientrange.getNumRows()
var servicetochange = gensheet.getRange(2,2)
var i;
for (i=1;i>clientsquantity;i++){
var currentservice = clientrange.getRange(i,1).getValue;
servicetochange=gensheet.getRange().setValue(currentservice);
Utilities.sleep(10000);
}
}
I have changed some code in the loop ... now it does something (but I can't be sure it does what you expect):
function test() {
var ss = SpreadsheetApp.getActive();
var gensheet = ss.getSheetByName('Generador SE');
var clientsheet = ss.getSheetByName('Clientes SE');
var clientrange = clientsheet.getRange("A1:C200");
var clientsquantity = clientrange.getNumRows()
var servicetochange = gensheet.getRange(2,2)
var i;
for (i=1;i<clientsquantity;i++){
var currentservice = clientrange.offset(i,0,1,1).getValue();
servicetochange.offset(i,0,1,1).setValue(currentservice);
Utilities.sleep(10000);
}
}