Google Ads Script (AWQL) get custom date range for reporting - google-ads-api

I need to pull a google ads report that will get data from a fixed date (28th May) until today and push the data to a spreadsheet. I can't figure out how to define the date range for this query
I've tried googling and reading the google documentation but I can't figure it out
function main() {
var spreadsheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/XXX');
var sheet = spreadsheet.getSheetByName('Data')
var report = AdsApp.report(
'SELECT Date, CampaignName, AverageFrequency, Impressions, ImpressionReach ' +
'FROM CAMPAIGN_PERFORMANCE_REPORT ' +
'WHERE Impressions > 0 ' +
'DURING 20190528,TODAY');
sheet.clearContents();
report.exportToSheet(sheet);
}
I need to use today as the end date instead of the campaign end date as the end date for this query as I'm trying to pull frequency as a metric and it will just show blank values if the end date is in the future.
Please let me know if there is a way to make the query work. Thanks!

The TODAY keyword acts as the "full range" of the DURING property and cannot be used as the end part (as far as I know). The following should work.
function main() {
var endDate = new Date();
var endRange = Utilities.formatDate(endDate, 'America/Chicago', 'YYYYMMdd');
var spreadsheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/XXX');
var sheet = spreadsheet.getSheetByName('Data')
var report = AdsApp.report(
'SELECT Date, CampaignName, AverageFrequency, Impressions, ImpressionReach ' +
'FROM CAMPAIGN_PERFORMANCE_REPORT ' +
'WHERE Impressions > 0 ' +
'DURING 20190528,' + endRange);
sheet.clearContents();
report.exportToSheet(sheet);
}

Date ranges for the report are defined in the DURING clause of the query. Date ranges can be specified in two different ways:
A custom date range using regular AWQL syntax, for example:
SELECT Id, Criteria, AdGroupName
FROM KEYWORDS_PERFORMANCE_REPORT
DURING 20190101,20190325
A date range type, for example:
SELECT Id, Criteria, AdGroupName
FROM KEYWORDS_PERFORMANCE_REPORT
DURING LAST_7_DAYS
In your case you should use:
DURING 20190528, 20190723
There is no other option for you to do that.

Related

Create a Google Calendar Event from Google Sheets Row

I have a dataset in Google Sheets with each row being a job with columns for date, frequency, place etc.
Name # Email Phone Type Freq Date Start End Dur Place ID
Jim 1 xxxxx xxxxx Hourly Weekly 12/12 9am 10am 2 xxxxx Job 1
Bob 2 xxxxx xxxxx By Size Once 12/12 2pm 5pm 6 xxxxx Job 2
Tim 1 xxxxx xxxxx Hourly Monthly 12/12 1pm 3pm 4 xxxxx Job 3
A new job will populate a new row at the bottom. What I would like to automate is that for each new job that comes into the Google Sheet, a corresponding Google Calendar event is created. A couple of cavets:
Events must only be created for jobs with col # equal to 1
Event repeat frequency must be equal to col Freq
Event colour must be equal to #fbd75b
I want the format to be like below for the event (row 3 for example):
Summary
col ID Job 3
Description
col Type "job" Hourly Job
col Dur "Hours" 4 Hours
Col Freq Monthly
col Name Tim
col Email xxxxx
col Phone xxxxx
Location
Col Place xxxxx
Start Date & Time
col Date at col start 1pm
End Date & Time
col Date at col End 3pm
Is this possible using script editor?
Answer
Yes, it is possible
How to do it
Use an onEdit trigger to check if a new job is added
Use SpreadsheetApp to get the necessary information
Use CalendarApp to create the events
Notes
You can add a new column with a link to the event to track the jobs that have been processed.
If you add a sample spreadsheet I can test it and attach you the final code working.
Update
I have written a small code example to help you get started. In this, there are two functions, one to read all the lines of the sheet and one to process each line. This is because the problem has two subtasks: on the one hand to manage the new data in the sheet once it is written and on the other hand the processing of this data.
subtask 1: manage new data
I don't know if you enter the data manually or through some function or with a different method. Nor if it is important that the events are generated just when you enter the data, that's why there are different solutions:
Each time a new row is inserted, check all data and create events for those who have not yet filled in the new eventId column. For this it is convenient to use [triggers][10].
Execute a function at the desired time to check the data and create the remaining events. This can be called from the main sheet via a button.
There are more options, but depending on the workflow you have it will be more convenient one or another, if you explain it to me I can guide you.
subtask 2: create the event with a single line
On the other hand, once a line has been detected as valid to create an event from it, the necessary information must be obtained and processed to create the event.
In the code you can see how I process line by line once I have obtained all the values of the sheet. Most of the code simply obtains the desired values from an array and stores them in variables that will later be used to create the event. The information that requires a little more processing is in obtaining the dates and creating recursive or non-recursive events. Finally, the formatting (color) is applied and the description is added regardless of the type of event it is.
Code
function main() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
var values = ss.getDataRange().getDisplayValues()
var lc = ss.getLastColumn()
for (var i = 1; i < values.length; i++) {
var evId = processLine(values[i], lc) // create the event and get id of the event
ss.getRange(i, lc).setValue(evId) // write the id of the event in the last column of the sheet
}
}
function processLine(x, lc) {
var jobType = x[5]
var evId = x[lc-1]
// check job type
if (jobType == 1 && evId == '') {
// summary
var summary = x[4]
// description
var type = x[17]
var dur = x[14]
var freq = x[10]
var description = type + ' - ' + dur + ' - ' + freq
// location
var location = x[15]
// date
var start = x[12]
var end = x[13]
var date = x[11]
// formated date
var eStart = new Date(date + ' ' + start)
var eEnd = new Date(date + ' ' + end)
// options
var opts = {
location: location
}
// SINGLE EVENTS
if (freq == 'Once Off') {
var ev = CalendarApp.createEvent(summary, eStart, eEnd, opts)
} else {
// RECURRENT EVENTS
// CREATE RECURRENCE FREQUENCY
switch (freq) {
case 'Monthly':
var recurrence = CalendarApp.newRecurrence().addMonthlyRule().times(dur)
break
case 'Weekly':
var recurrence = CalendarApp.newRecurrence().addWeeklyRule().times(dur)
break
}
// CREATE EVENT
var ev = CalendarApp.createEventSeries(summary, eStart, eEnd, recurrence, opts)
}
// ADD PARAMETERS
ev.setColor(CalendarApp.EventColor.YELLOW)
ev.setDescription(description)
console.log(ev.getId())
return ev.getId()
}
}
Reference
Simple Triggers: onEdit
SpreadsheetApp
CalendarApp

How to compute the Google Query's data field?

how can I compute QUERY's data attribute to make data range dynamic?
More details: I have a spreadsheet with multiple worksheets incl. a separate "summary" one. Here, a couple of queries are aggregating data from these multiple sheets. All fine. But: any time I add/remove a sheet, I will have to update all queries manually - which is quite cumbersome. So I created a small script that returns the names of all worksheets. Nice.
What I have trouble with: how can I make QUERY() accept these worksheet names? It returns #value.
originally:= QUERY({'sheet 1'!$A:$C; 'sheet 2'!$A:$C}; "SELECT SUM(Col2), ...") //works.
with script:= QUERY(getSheetNames(); "SELECT SUM(Col2), ...") //#value error
add script to cell and referencing cell:= QUERY(A1; "SELECT SUM(Col2), ...") //#value error
custom function:getSheetNames() currently returns "{'sheet 1'!$A:$C; 'sheet 2'!$A:$C}"
function getSheetNames() {
var out = "";
var columns = "!$A:$C";
var apostrophe = "'";
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for (var i = 1 ; i < sheets.length; i++) {
out += apostrophe + sheets[i].getName() + apostrophe + columns + "; ";
}
out = "{" + out.slice(0, -2) + "}";
return out;
}
Many thanks for help!

Script on google sheet for filtering a specific name

need some help with script on google sheets
I'm having some issues to try to use "setVisibleValues" and I got an error saying "Exception: Visible values are not currently supported. As an alternative specify a list of hidden values that excludes the values that should be visible.". But my problem is, I've a huge number of employee names on a list, and I wanna filter just based in one person.
I cant show some information, but the thing is: "I just wanna filter one value, and I don't know how to do it using "setHiddenValues".
function Filtersheet() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A3:S').activate();
spreadsheet.getRange('H3').activate();
var criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues([''])
var criteria = SpreadsheetApp.newFilterCriteria()
.setVisibleValues(['tayzer'])
.build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(8, criteria);
}
Lets say that the names of the Employees are : jorge, lucas, nuno, fernando, marta, beatriz, tayzer, larissa, and I wanna use the filter script to only show on the column the information related to tayzer
But my way to change the filter employee will be on a cell outside the script (cause I've around 200 employees)
Thanks in advance for the help
try this
function setFilter() {
// replace 'sheet name' with you sheet
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet name');
var range = ss.getDataRange();
var filter = range.getFilter() || range.createFilter()
var criteria = SpreadsheetApp.newFilterCriteria().whenTextContains('tayzer');
filter.setColumnFilterCriteria(8, criteria);
}
if i am not wrong if you put "jorge" in cell_C4 you want it to filter "jorge" in column E, if so try below code.
function setFilter() {
// replace 'sheet name' with you sheet
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet name');
var range = ss.getDataRange();
var filter = range.getFilter() || range.createFilter()
var criteria = SpreadsheetApp.newFilterCriteria().whenTextContains(ss.getRange('C4').getValue()).build();
filter.setColumnFilterCriteria(8,criteria)
}

Google Sheets - Add note on edit when user edits only a portion of the sheet

This may be a simple answer, I'm very new to the script editor in google sheets.
I have about 8 sheets for individual users to enter data. I would like a note showing the last modified date on a range of cells in each of the 8 sheets. Each of the 8 sheets is identical in the layout. With the code below, I'm able to get a last modified date note on column 2, row 26, and it works great. However, I can't figure out how to expand that to include columns 2-7 and rows 26-35. I assumed just entering 2:7 under range.getRow() would work, but it does not.
Any suggestions on how to achieve this? Even better, ideally having just one comment note in a single cell on the sheet(L24 as an example), that shows the last modified date of any cell edited between columns 2-8 and rows 26-35?
My goal is really just to identify the last time a user has modified any cells within that specified range.
Any suggestions would be greatly appreciated. The script is below.
/**
* The event handler triggered when editing the spreadsheet.
* #param {Event} e The onEdit event.
*/
function onEdit(e) {
// Set a comment on the edited cell to indicate when it was changed.
var range = e.range;
if(range.getRow() == 26 && range.getColumn() == 2){
range.setNote('ROW: ' + range.getRow() + " COLUMN: "+ e.range.getColumn());
range.setNote('Last modified: ' + new Date());
}}
The OP wants to create a note in cell L24 on any sheet where the edited cell is in the range B26:H35 (columns 2 to 8 inclusive).
The OP's own code could create a note in the edited cell but was only configured for edits in the range "B26". However, most of the logic was in place, and only modest changes are required.
The points to note in this answer are:
the Note is entered in cell "L24" of the edited sheet; this is made easier by defining a variable noterange.
the row and column numbers for the edited range are assigned to variables; this makes it easier to use when building the IF statement.
the edited range is assigned to a variable; this simplifies displaying the cell reference in the note.
the IF statement is in two parts: it tests whether i) the edited row is between 26 and 35 AND ii) the edited column is between 2 and 8.
the cell reference in the note is simplified by using getA1Notation.
I left the date as used by the OP, but this can be shortened/simplified
I inserted a line break between the range reference and "Date Modified" for easier reading
I created an Installable onEdit Trigger
function so54658181(e) {
// setup spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get the active sheet
var eactiveSheet = e.source.getActiveSheet();
// set the location for the Note
var noterange = eactiveSheet.getRange("L24");
// get the edited cell and find the row and column numbers
var erange = e.range;
var editedRow = erange.getRow();
var editedColumn = erange.getColumn()
// if the row is between 26 and 35, and the column is between 2 and 8, then set the note
if ((editedRow >= 26 && editedRow <= 35) && (editedColumn >= 2 && editedColumn <= 8)) {
noterange.setNote("Cell " + erange.getA1Notation() + String.fromCharCode(10) + "Last modified: " + new Date());
}
}
Formatting the Date
Add these two line anywhere above the IF statement
// set date format
var curDate = Utilities.formatDate(new Date(), "GMT+1", "E, MMM dd yyyy");
Edit the following line of the IF statement; note that it now references curDate
noterange.setNote("Latest edit: Cell " + erange.getA1Notation() + String.fromCharCode(10) + "On: " + curDate);
A link to the most recent Date and Time Patterns is included in the Google documentation.

Script for "Split text to columns" with form in Google Sheets

I am using IFTTT to push forms sent to my email address to a Google Sheet. The contents get pasted into column A in one big clump, and I can't figure out how to split the text into columns in a way that formats well. Ideally, I'd like to only include the answers to questions on the form in the columns to the right of column A.
Here is a sample of what gets pasted into column A:
New customer message on May 9, 2017 at 12:15 PM
You received a new message from your Online Store's contact form.
Name:
Jon Snow
Email:
sample#gmail.com
Q1:
Yes
Q2:
No
Q3:
yes
Q4:
no
Q5:
no
Is there some sort of script I could use to display the name, email address, and answers to the 5 questions in the 7 columns to the right of column A?
I have a rudimentary solution that you can build on if you like.
My solution assumes a few things, firstly the name is always going to be two words, secondly the answers are always going to be yes or no.
This will work for any number of rows in column A.
The whole solution is based on splitting up the string in a particular way, and it's not very fluid as it assumes the amount of spaces and the formatting will always be the same. It's a start :)
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var dataRangelength = ss.getDataRange().getLastRow();
var strRef = ss.getRange("A1:A" + dataRangelength);
var str = strRef.getValues();
for (var i = 0; i < dataRangelength; i++) {
var row = str[i];
var A1ref = i + 1
var rowRef = ss.getRange("A" + A1ref);
if (row != "") {
var arr = row.toString().split(" ");
var arr1 = arr[20].toString().split("\n");
var arr2 = arr[21].toString().split("\n");
rowRef.offset(0, 1).setValue(arr1[4] + " " + arr2[0]);
rowRef.offset(0, 2).setValue(arr2[4]);
rowRef.offset(0, 3).setValue(arr2[8]);
rowRef.offset(0, 4).setValue(arr2[12]);
rowRef.offset(0, 5).setValue(arr2[16]);
rowRef.offset(0, 6).setValue(arr2[20]);
rowRef.offset(0, 7).setValue(arr2[24]);
}}
}

Resources