I'm a total noob when it comes to javascript unfortunately thats what google sheets is using. what i am tasked with is to password protect a drop down menu (data validation) on my google sheets file. so when they try to select their name it asks them for a password, is this possible?
Answer:
With data validation, no this is not possible. You could in theory write an Apps Script workaround but anyone with edit access to the sheet would be able to see the passwords so it would be useless as a protection.
Simple Example:
You'll want to make a data validation dropdown on a cell like normal:
and then write an onEdit function to run when the value is changed:
// define each user password (this is insecure and not recommended)
const userPasswords = {
"Name 1": "password1",
"Name 2": "anotherPassword",
"Name 3": "insecureIsMyMiddleName",
"Name 4": "name4nocapitalsorspaces"
}
function onEdit(e) {
const namesCell = "C2" // the cell with the dropdown
if (e.range.getA1Notation() != namesCell) {
return
}
// show prompt for password:
var ui = SpreadsheetApp.getUi()
const response = ui.prompt("Password protected range",
"Please enter your password:",
ui.ButtonSet.OK_CANCEL)
const button = response.getSelectedButton()
const text = response.getResponseText()
// don't run if the user pressed cancel or close
if (button != ui.Button.OK) {
return
}
// check the passwords
if (text != userPasswords[e.value]) {
ui.alert('Incorrect Password', 'Please try again', ui.ButtonSet.OK);
e.range.setValue(e.oldValue) // reset to old value
}
}
References:
Simple Triggers | Apps Script | Google Developers
Event Objects | Apps Script | Google Developers
Dialogs and Sidebars in Google Workspace Documents | Apps Script | Google Developers
Related
This is what I have.
For my project I have A cloud Function that gets triggered by Pub/Sub.
The function selects data from BigQuery table to which a Google sheet is connected. So my data is inside Google sheet and BiqQuery is used to query my data.
The same function the inserts the selected data into another table inside BigQuery. All the selecting and Inserting is done with BigQuery Jobs.
Here is the problem
When the function is triggered I get the following error message.
Error: Access Denied: BigQuery BigQuery: Permission denied while getting Drive credentials. at new ApiError (/workspace/node_modules/#google-cloud/common/build/src/util.js:73:15) at Util.parseHttpRespBody (/workspace/node_modules/#google-cloud/common/build/src/util.js:208:38) at Util.handleResp (/workspace/node_modules/#google-cloud/common/build/src/util.js:149:117) at /workspace/node_modules/#google-cloud/common/build/src/util.js:479:22 at onResponse (/workspace/node_modules/retry-request/index.js:228:7) at /workspace/node_modules/teeny-request/build/src/index.js:226:13 at processTicksAndRejections (internal/process/task_queues.js:95:5)
The things that do work
When the same function is run via Cloud console selecting and inserting into BigQuery table work.
Querying the Google sheet via BigQuery page inside Google Cloud does also works as it should.
What I have tried
I followed everything inside this: Querying Drive data documentation.
I have have all the required permissions.
Is this a bug or am I doing something wrong?
Edit
I forgot to add my code.
This is the part where I select the data
Something happens with the Tag_Data which triggers the catch.
const Select_Tag_Info_query = `SELECT * FROM \`project.Dataset.table\` where TagId = "${tag}"`;
console.log(Select_Tag_Info_query); // outputs: "SELECT * FROM `pti-tag-copy.ContainerData2.PTI-tags` where TagId = "tag-1"
const Tag_Data = SelectJob(Options(Select_Tag_Info_query));
console.log(`This is Tag-Data: ${Tag_Data}`); // outputs: "This is Tag-Data: [object Promise]"
Tag_Data.catch((error) => {
console.log(`Something went wrong with selecting tag data from the spreadsheet`);
console.error(error);
});
//The resolve is not called because of the error above
Promise.resolve(Tag_Data).then(function (Tag_Data) {
let returned_tag = Tag_Data.TagId;
let returnd_country = Tag_Data.Country;
let returned_location = Tag_Data.Location;
let returned_poleId = Tag_Data.PoleId;
console.log(`this is tag: ${returned_tag}`);
console.log(`this is country: ${returnd_country}`);
console.log(`this is location: ${returned_location}`);
console.log(`this is poleid: ${returned_poleId}`);
});
This is how the BigQuery Jobs function looks like.
function Options(query) {
const options = {
configuration: {
query: {
query: query,
useLegacySql: false,
},
location: 'EU'
},
};
return options;
}
// This function is for selecting the tag data from spreadsheet via bigquery
async function SelectJob(options) {
// Run a BigQuery query job.
console.log(`select job is called.`) // This part is outputed
const [job] = await bigquery.createJob(options); // something goes wrong here.
const [rows] = await job.getQueryResults();
console.log(`${rows[0]["TagId"]}`); // This part is not outputed
console.log(`${rows[0]["Country"]}`); // This part is not outputed
console.log(`${rows[0]["Location"]}`); // This part is not outputed
console.log(`${rows[0]["PoleId"]}`); // This part is not outputed
if (rows.length < 1) {
console.log("array is empty");
} else {
console.log(`selected tag data from spreadsheet`);
return {
TagId: rows[0]["TagId"],
Country: rows[0]["Country"],
Location: rows[0]["Location"],
PoleId: rows[0]["PoleId"]
}
}
}
I think something goes wrong at this part of the code inside the Select Job(). because the other console.logs are not outputed. My reason for saying that is because inside BigQuery project history I don't see the query. I only see a red circle with a white ! mark. see the photo BigQuery project history.
const [job] = await bigquery.createJob(options);
const [rows] = await job.getQueryResults();
I want to know if I can use Google spreadsheet as a back-end database for my Blogger website. I have done so in past using Google Fusion Tables.
I can use Web Apps as well by using a custom domain to direct to their long URL. But when I update the script, I have to deploy the web app. This changes the long URL, so I need to update my redirection.
Is there a way to access & update a Google Spreadsheet from my website.
You cannot do this with Blogger.
However, you can do this with Sites.
If you setup a spreadsheet like this:
Then you create a web app from that like this:
var sheet = SpreadsheetApp.openByUrl("YOUR URL").getSheetByName("LinkConfig");
function getDataIndex(key) {
var Keys = sheet.getRange(2, 1, sheet.getMaxColumns(), 1).getValues().map(function(row) {return row[0]});
for (var i=0; i<Keys.length; i++) {
if (Keys[i]==key) return i+2;
}
}
function getData(key) {
return sheet.getRange(getDataIndex(key), 2).getValue();
}
function test() {
Logger.log(getData("url1"));
Logger.log(getData("url2"));
}
function webApp(key) {
//Get contents from target URL
var content = UrlFetchApp.fetch(getData(key)).getContentText();
return HtmlService.createHtmlOutput(content); //Returns new page with the same content
}
function doGet(e) {
if (e.parameter.key != null && e.parameter.key != undefined) {
return webApp(e.parameter.key);
} else {
return HtmlService.createHtmlOutput("<h1>Error! You didn't specify a 'key' parameter</h1>");
}
}
And deploy it.
Now, as long as you don't change that one URL (meaning you don't edit this main "config" webapp, you are able to change values on the spreadsheet and access the pages linked there by passing the key.
To use it in Sites, add an Embed element and set the URL to : yourwebappurl?key=keyvalue
I Created a android app in which if a press a button and value changes in Firebase database (0/1) , i want to do this using google assistant, please help me out, i searched out but didn't found any relevant guide please help me out
The code to do this is fairly straightforward - in your webhook fulfillment you'll need a Firebase database object, which I call fbdb below. In your Intent handler, you'll get a reference to the location you want to change and make the change.
In Javascript, this might look something like this:
app.intent('value.update', conv => {
var newValue = conv.prameters.value;
var ref = fbdb.ref('path/to/value');
return ref.set(newValue)
.then(result => {
return conv.ask(`Ok, I've set it to ${newValue}, what do you want to do now?`);
})
.catch(err => {
console.error( err );
return conv.close('I had a problem with the database. Try again later.');
});
return
});
The real problem you have is what user you want to use to do the update. You can do this with an admin-level connection, which can give you broad access beyond what your security rules allow. Consult the authentication guides and be careful.
I am actually working on a project using Dialogflow webhook and integrated Firebase database. To make this posible you have to use the fulfilment on JSON format ( you cant call firebasedatabase in the way you are doing)
Here is an example to call firebase database and display a simple text on a function.
First you have to take the variable from the json.. its something loike this (on my case, it depends on your Entity Name, in my case it was "tema")
var concepto = request.body.queryResult.parameters.tema;
and then in your function:
'Sample': () => {
db.child(variable).child("DESCRIP").once('value', snap => {
var descript = snap.val(); //firebasedata
let responseToUser = {
"fulfillmentMessages": [
{ //RESPONSE FOR WEB PLATFORM===================================
'platform': 'PLATFORM_UNSPECIFIED',
"text": {
"text": [
"Esta es una respuesta por escritura de PLATFORM_UNSPECIFIED" + descript;
]
},
}
]
}
sendResponse(responseToUser); // Send simple response to user
});
},
these are links to format your json:
Para formatear JSON:
A) https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/Shared.Types/Platform
B) https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/Shared.Types/Message#Text
And finally this is a sample that helped a lot!!
https://www.youtube.com/watch?v=FuKPQJoHJ_g
Nice day!
after searching out i find guide which can help on this :
we need to first create chat bot on dialogflow/ api.pi
Then need to train our bot and need to use webhook as fullfillment in
response.
Now we need to setup firebase-tools for sending reply and doing
changes in firebase database.
At last we need to integrate dialogflow with google assistant using google-actions
Here is my sample code i used :
`var admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
var database = admin.database();
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
exports.hello = functions.https.onRequest((request, response) => {
let params = request.body.result.parameters;
database.ref().set(params);
response.send({
speech: "Light controlled successfully"
});
});`
I am trying to remove older duplicate form responses based on a column using the following code.
The credit for the code goes to: http://www.jacorre.com/tutorial/remove-duplicate-rows-google-spreadsheets/
The code in my script is:
function removeDuplicates() {
var ss = SpreadsheetApp.getActiveSpreadsheet(),
responses = ss.getSheetByName('Name of Source Sheet'),
range = responses.getDataRange(),
numRows = range.getNumRows()-1,
data = range.getValues(),
columnHeadings = [data[0]],
newData = [];
for (var i=numRows; i>0; i--) {
var row = data[i],
duplicate = false;
for (var j in newData) {
if (row[4] == newData[j][4]) {
duplicate = true;
// [4] is the column number from the 1st column. the above would be 1 + 4 = 5th column
}
}
if (!duplicate) {
newData.push(row);
}
}
var final = ss.getSheetByName('Name of Destination Sheet');
if (!final) {
var final = ss.insertSheet('Name of Destination Sheet');
}
final.clearContents();
final.getRange(1,1,1,columnHeadings[0].length).setFontWeight('bold').setValues(columnHeadings);
final.getRange(2, 1, newData.length, newData[0].length).setValues(newData);
}
This has been set to trigger on Form Submit. It works well on new form submissions.
However, when an existing response is edited using 'Form Edit URL' from: https://webapps.stackexchange.com/questions/89551/show-url-used-to-edit-responses-from-a-google-form-in-a-google-spreadsheet-by-us/89566 the values are not updated into the new sheet.
But if the function is run manually the updated row is updated to the new sheet.
How can I sort this problem? Any help will be appreciated. Thank you.
From my own answer posted at Web Applications SE.
I just did a test and found that the on form submit event it's not
being triggered when a response is edited.
I'm not sure if the on form submit trigger is working as intended, if
the above is due to a bug or to a glitch. To be sure, post an issue to
the Google Apps Script Issue
Tracker.
As a workaround, instead of using the on form submit event, use
another way to run your script, like a time-drive trigger.
References
Custom menus in Google Apps - Google Apps Script Guides
Simple or installable triggers - Google Apps Script Guides
Google Apps Script Support
I'm using the google adwords api, I can retrieve all campaigns, group ads, ads,
but I have no idea on how to retrieve keywords related to an "group ads".
In the google adwords interface, when we select a group ads, we have two tabs, one for ads related to that group ads, and the second for keywords.
but programatily, right now I can only retrieve ads.
I'm using PHP, if some one knew how to do that in php or others programming languages or even a soap call.
To get the details of all the keywords of an adgroup you need the following to get the details of all the keywords.
require_once dirname(dirname(__FILE__)) . '/init.php';
// Enter parameters required by the code example.
$adGroupId = 'Enter your adgroup id';
/**
* Runs the example.
* #param AdWordsUser $user the user to run the example with
* #param string $adGroupId the id of the parent ad group
*/
function GetKeywordsExample(AdWordsUser $user, $adGroupId) {
// Get the service, which loads the required classes.
$adGroupCriterionService =
$user->GetService('AdGroupCriterionService', ADWORDS_VERSION);
// Create selector.
$selector = new Selector();
$selector->fields = array('KeywordText', 'KeywordMatchType', 'Id');
$selector->ordering[] = new OrderBy('KeywordText', 'ASCENDING');
// Create predicates.
$selector->predicates[] = new Predicate('AdGroupId', 'IN', array($adGroupId));
$selector->predicates[] =
new Predicate('CriteriaType', 'IN', array('KEYWORD'));
// Create paging controls.
$selector->paging = new Paging(0, AdWordsConstants::RECOMMENDED_PAGE_SIZE);
do {
// Make the get request.
$page = $adGroupCriterionService->get($selector);
// Display results.
if (isset($page->entries)) {
foreach ($page->entries as $adGroupCriterion) {
printf("Keyword with text '%s', match type '%s', and ID '%s' was "
. "found.\n", $adGroupCriterion->criterion->text,
$adGroupCriterion->criterion->matchType,
$adGroupCriterion->criterion->id);
}
} else {
print "No keywords were found.\n";
}
// Advance the paging index.
$selector->paging->startIndex += AdWordsConstants::RECOMMENDED_PAGE_SIZE;
} while ($page->totalNumEntries > $selector->paging->startIndex);
}
// Don't run the example if the file is being included.
if (__FILE__ != realpath($_SERVER['PHP_SELF'])) {
return;
}
try {
// Get AdWordsUser from credentials in "../auth.ini"
// relative to the AdWordsUser.php file's directory.
$user = new AdWordsUser();
// Log every SOAP XML request and response.
$user->LogAll();
// Run the example.
GetKeywordsExample($user, $adGroupId);
} catch (Exception $e) {
printf("An error has occurred: %s\n", $e->getMessage());
}
In the Adwords API Keywords are dubbed as AdGroup Criteria. You can add or retrieve the keywords for a certain AdGroup by using the AdGroupCriterionService.
If you're using the PHP client library of the Adwords API check out GetAllAdGroupCriteria.php in the example files. (don't forget to enter the AdGroupId you want to get the keywords for first)