I work for a Google Apps Reseller and I implement gadgets for our clients.
We have several gadgets that use Google Visualization API to query a spreadsheet (with a dynamic id) and display the result in a table.
We are using this piece of code:
function drawVisualization() {
var oldSpreadsheetUrl = "https://docs.google.com/spreadsheet/tq?key=<ss_id>";
var newSpreadsheetUrl = "https://docs.google.com/spreadsheets/d/<ss_id>/gviz/tq";
var query = new google.visualization.Query(oldSpreadsheetUrl);
query.setQuery("SELECT A,B");
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
if(response.isError()) {
console.log(response.getMessage());
} else {
console.log("NUMBER OF COLUMNS: " + response.getDataTable().getNumberOfColumns());
}
}
And testing with this sample spreadsheet (New Google Spreadsheet)
SPREADSHEET ID: 1qMvY3y4MkwoK1UvCA9A8dW4BbmhH1iMwWqGLEM5vjJk
As long as we query an old spreadsheet everything works ok, but if we query a new spreadsheet (with the standard url - oldSpreadsheetUrl) the request fails with a timeout exception and we get a 404 exception.
This is the message we get in the Browser Console:
http://i.imgur.com/h4DjyQ6.png
We were able to make the query work anyway, by using this new url in the datasource:
"https://docs.google.com/spreadsheets/d/<spreadsheet_id>/gviz/tq"
But with this notation the setQuery directive is ignored and all of the three columns are returned instead of the first two ("SELECT A,B").
We are using this in several gadgets and therefore want to know:
How can we overcome the setQuery bug?
Is there a programmatic way to know if a spreadsheet is a new version or an old version?
Thank you in advance.
Regards,
Riccardo
I ran into this same problem a few weeks ago when we did some testing with the new Google Sheets. Basically, the old Google Sheets expect a URL with the following format:
https://spreadsheets.google.com/tq?key={key}
While the new Google Sheets expects a URL with this format:
https://docs.google.com/spreadsheets/d/{key}/gviz/tq
You should be able to use the domain to distinguish between old and new Google Sheets. Failing that, you could always look for /gviz/ to tell if the new Google Sheets are being used. You can find additional information in this bug report.
In regards to your other point about setQuery, I've just noticed this morning while debugging my own issue that column IDs are being returned by the Visualization API as "Col 0", "Col 1" etc. instead of "A", "B" etc. So that's likely why your ("SELECT A,B") query isn't working. I've also just logged a bug for this issue.
Hope that helps.
Related
I'm not very used to Active Reports and I got an old software using those. The software provide some kind of stripped version of Active Reports Designer 7.
I got a PageFooter section with some fields and I want to remove one to display it only when it's the last page.
Basically, what I want to do is this in scripts :
if (this.PageNumber == this.PageCount) {
Field.Visible = true;
}
I only find one post here that say this.PageNumber should work, but it dosent.
So I tried to use the ReportInfo using the FormatString as {PageNumber}, but I don't seems to be able to read the value using this.ReportInfo.Value or this.ReportInfo.Text
I also tried to make a TextBox, using SummaryType : PageCount. But I'm still unable to read the Value.
So the question is :
How can I know the Page Number and Page Count in the script section?
Or how can I read the value of those textbox I created ?
Thanks a lot!
I think these docs cover what you are looking for:
https://help.grapecity.com/activereports/webhelp/Legacy/AR7Help/OnlineEN/AddPageNumbering.html
https://help.grapecity.com/activereports/webhelp/Legacy/AR7Help/OnlineEN/index.html
I want to make data like 2022/12/15 (imported from Google Sheets at the moment of page load) display as "Dec 15" in one column, and as "Thu" in another column.
I found the format codes:
moment().format("MMM d"); // "Dec 15" and
moment().format("ddd"); // "Thu".
I read https://momentjs.com/docs/ and https://momentjs.com/guides/, but could not find:
Where do I enter that code?
Can I skip entering that code, and instead just enter this?:
$(document).ready(function () {
$('#example').DataTable({
columnDefs: [
{
targets: 4,
render: DataTable.render.datetime('MMM d'),
},
],
});
});
Perhaps I should separate my questions into different posted questions, but I imagine it will be more helpful for future readers to find the combined challenges asked and answered in a single thread.
I'm using the WordPress plugin "Inline Google Spreadsheet Viewer", which is built on DataTables.
[Edit: I realized I should not paste that code into inline_gdocs_viewer.php, and intended to paste it into igsv-datatables.js. I could not however figure out where to paste within that file. What should I look for to know where to insert it? (The author of that plugin publicly announced that no more support will be given.) Should I post the contents of the js file somewhere so you can see it?]
[Edit 2: Would entering that code make column 5 always displayed in MMM d format, even if I want column 5 to be displayed in a different format? Shouldn't specifying what format to apply to which column happen when I create a page / post and use the shortcode to embed the spreadsheet?]
(I read the plugin's documentation and I read DataTables documentation.)
If my table doesn't have a name, what do I use instead of #example? Do I need to name my table? If so, how? (I tried to find the answer at, for example, https://www.w3schools.com/html/html_tables.asp.)
The source for the longer code came from a live example where the dates were in column 5, but the code says "targets:4". To apply the code to column 3 (for example), should I enter targets:2? I read https://datatables.net/reference/option/columns.render, but bizarrely that didn't address this basic question.
If you're wondering if I upgraded DataTables from the old version that comes with Inline Google Spreadsheet Viewer, yes I did.
If you're wondering if I got the script array to call moment.js, I might have. Into the scripts array I added
,
'moment' => array(
'src' => plugins_url('moment.min.js', __FIL__),
'deps' => array( 'moment' )
)
I'm not sure about the "deps" part. Does it mean dependencies? Was I right to use "moment" twice in that code?
If you only know a possible answer to one of these questions, that's better than nothing, so please do share what you can.
I know the Moment team recommends you choose a different library than Moment for new projects, but DataTables to this day recommends Moment for sorting by Day of the week or sorting by Date.
Thanks
Using moment.js 2.29.2 and DataTables 1.13.1.
What I tried, and what I expected:
I read the documentation for all the programs, and I read forum discussions for all the programs, and I studied examples, expecting to find where to enter the code, but nowhere could I find what to do with it. It was always assumed that that part was already known.
I can only read from the first 100,000 rows of any particular tab in a Google Sheet via the API.
Is this a known limitation of the Google Sheets API? I didn't see a reference to it in the documentation.
Issue and workaround:
I thought that if you want to retrieve the values from Spreadsheet, it seems that when the method of "spreadsheets.get" is used for the Spreadsheet including the large data, the data cannot be correctly retrieved because of an error like Response Code: 413. Message: response too large.. I thought that this might be the reason for your issue. And, in this situation, I confirmed that even when the method is changed from "spreadsheets.get" to "spreadsheets.values.get " and "spreadsheets.values.batchGet", the issue occurred. So I thought that this situation might be the current specification of Sheets API.
But, fortunately, I confirmed that when I tested to retrieve the values from your Spreadsheet using the query language, all values can be retrieved. And also, I confirmed that when I tested to retrieve the values from your Spreadsheet using the Spreadsheet service of Google Apps Script, all values can be retrieved.
So in this answer, I would like to propose these 2 patterns.
Pattern 1:
In this pattern, the values are retrieved by the query language. I thought that in your situation, this might be suitable. The endpoint is as follows.
https://docs.google.com/spreadsheets/d/###spreadsheetId###/gviz/tq?tqx=out:csv&gid=###sheetId###&access_token=###accessToken###
In this case, the access token can be also included in the request header instead of the query parameter. At that time, please use Authorization: Bearer ###. When the above endpoint is accessed using your access token, all values are returned as CSV data.
Pattern 2:
In this pattern, the values are retrieved by the Spreadsheet service of Google Apps Script. The sample script is as follows. When you use this script, please test this script at the script editor of Google Apps Script.
function myFunction() {
const id = "###spreadsheetId###";
const sheet = SpreadsheetApp.openById(id).getSheetByName("Tab 1");
const values = sheet.getDataRange().getValues();
console.log(values.length)
}
When I tested this script for your sample Spreadsheet, 405028 can be seen in the log.
References:
Query Language
Spreadsheet Service
Using Google Sheets, I am trying to retrieve text passages from the Perseus Scaife Library, which has a working API.
When I query for the document node (=importxml("https://scaife-cts.perseus.org/api/cts?request=GetPassage&urn=urn:cts:greekLit:tlg0527.tlg001.opp-grc2:1.1","/")) I get all the data, including the URNs etc. However, any other xpath_query gives an error.
I know that Google Sheets can access the data, but I would like to be able to select only one node (//p).
You want to retrieve the text in passage. If my understanding is correct, how about this answer?
=importxml(A1, "//*[local-name()='passage']")
Result :
Note :
https://scaife-cts.perseus.org/api/cts?request=GetPassage&urn=urn:cts:greekLit:tlg0527.tlg001.opp-grc2:1.1 is converted by URL encode and put to "A1".
Converted URL is https://scaife-cts.perseus.org/api/cts?request=GetPassage&urn=urn%3acts%3agreekLit%3atlg0527%2etlg001%2eopp%2dgrc2%3a1%2e1.
Reference :
local-name
If this was not what you want, I'm sorry.
I am using google image search API. Till yesterday it was working, but today morning it says "This API is no longer available"
Is it officially closed, Or any error at my side
Request
https://ajax.googleapis.com/ajax/services/search/images?v=1.0&rsz=8&q=cute+kittens
Response
{"responseData": null, "responseDetails": "This API is no longer available.", "responseStatus": 403}
The answer I found was using Google's Custom Search Engine (CSE) API. Note that this is limited to 100 free requests per day.
Creating cx and modifying it to search for images
Create custom search engine at https://cse.google.com/cse/create/new based on your search criteria.
Choose sites to search (leave this blank if you want to search the entire web, otherwise you can enter a site to search in one particular site)
Enter a name and a language for your search engine.
Click "create." You can now find cx in your browser URL.
Under "Modify your search engine," click the "Control Panel" button. In the "edit" section you will find an "Image Search" label with an ON/OFF button, change it to ON. Click "update" to save your changes.
Conducting a search with the API
The API endpoint url is https://www.googleapis.com/customsearch/v1
The following JSON parameters are used for this API:
q: specifies search text
num: specifies number of results. Requires an integer value between 1 and 10 (inclusive)
start: the "offset" for the results, which result the search should start at. Requires an integer value between 1 and 101.
imgSize: the size of the image. I used "medium"
searchType: must be set to "image"
filetype: specifies the file type for the image. I used `"jpg", but you can leave this out if file extension doesn't matter to you.
key: an API key, obtained from https://console.developers.google.com/
cx: the custom search engine ID from the previous section
Simply make a GET request by passing above parameters as JSON to the API endpoint (also listed above).
Note: If you set a list of referrers in the search engine settings, visiting the URL via your browser will likely not work. You will need to make an AJAX call (or the equivalent from another language) from a server specified in this list. It will work for only the referrers which were specified in the configuration settings.
Reference:
https://developers.google.com/custom-search/json-api/v1/reference/cse/list
Now You can search images with Custom image search API.
You can do this with two steps:
Get CUSTOM_SEARCH_ID
Go to - https://cse.google.ru/cse/all
Here you must create new Search Engine. Do this and enable Image Search at there.
Screen(i am Russian... sorry)
then get this search engine ID. To do this press at Get Code button:
And there find line with cx = "here will be your CUSTOM_SEARCH_ID":
Ok. It's done, now second step:
Get SERVER_KEY
Go to google Console - https://console.developers.google.com/project
Press to Create project button, enter the name and other required information.
Pick this project and go to Enable Apis
Now find Custom Search Engine.
And Enable it.
Now we must go to Credentials and create new Server Key:
Ok. Now we can use Image Search.
Query:
https://www.googleapis.com/customsearch/v1?key=SERVER_KEY&cx=CUSTOM_SEARCH_ID&q=flower&searchType=image&fileType=jpg&imgSize=xlarge&alt=json
Replace the SERVER_KEY and CUSTOM_SEARCH_ID and call this request.
Limit: for free you can search only 100 images per day.
If this is just for your own purposes (not for production) and you're not planning to abuse Google Image Search, you can simply extract first image URL from Google search results using JSOUP.
For example:
Code to retrieve image URL of the first thumbnail:
public static String FindImage(String question, String ua) {
String finRes = "";
try {
String googleUrl = "https://www.google.com/search?tbm=isch&q=" + question.replace(",", "");
Document doc1 = Jsoup.connect(googleUrl).userAgent(ua).timeout(10 * 1000).get();
Element media = doc1.select("[data-src]").first();
String finUrl = media.attr("abs:data-src");
finRes= "<img src=\"" + finUrl.replace(""", "") + "\" border=1/>";
} catch (Exception e) {
System.out.println(e);
}
return finRes;
}
Guide:
question - image search term
ua - user agent of the browser
After I read several responses I compiled a response with images:
Access the website: https://developers.google.com/custom-search/v1/introduction, on the page you will find this part, so click in the button Get a Key:
Create or select a project, and then NEXT:
Copy the API KEY:
Access the website to create your CX: https://cse.google.com/cse/create/new, write some random domain like “www.anypage.com”, (after we will delete), select a language, and define some name for your search engine. Click on the Button CREATE.
Will see this page, then click in Control Panel:
Copy the Search engine ID for later (this is your CX). After you can set to search in all websites (active Search the entire web, select on the random website www.anypage.com then click on the button Delete) and you can active Image search. So will see like this:
And Using REST you can get the results, using this example code (searching for flower):
<html lang="pt">
<head>
<title>JSON Custom Search API Example</title>
</head>
<body>
<div id="content"></div>
<script>
function hndlr(response) {
console.log(response);
for (var i = 0; i < response.items.length; i++) {
var item = response.items[i];
// in production code, item.htmlTitle should have the HTML entities escaped.
document.getElementById("content").innerHTML += "<br>" + item.htmlTitle;
}
}
</script>
<script src="https://www.googleapis.com/customsearch/v1?key=API_KEY&cx=SEARCH_ENGINE_KEY&q=flower&searchType=image&callback=hndlr"></script>
</body>
</html>
The base code is found here: https://developers.google.com/custom-search/v1/using_rest
After setting your API_KEY (key) and your SEARCH ENGINE KEY (cx), the result will see like this:
Thanks to #Vijay Shegokar, #aftamat4ik and #Alladinian
This is the full URL template to be used
We can eliminate unnecessary parameters.
https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={safe?}&cx={cx?}&cref={cref?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json
I am using
https://www.googleapis.com/customsearch/v1?key=ap_key&cx=cx&q=hello&searchType=image&imgSize=xlarge&alt=json&num=10&start=1
Change the API url to
Google Custom Image search
Provide the same parameters along with with API KEY and CX.
More Info and Explorer
The Yahoo Boss API is a reasonable substitute, although it's not free and the results are not quite as good.
UPDATE: YAHOO BOSS JSON Search API will discontinue on March 31, 2016
SerpAPI enables to search through Google Images and returns a clean json. it integrates with most of the programming languages: python, php, java, golang, nodejs...
https://serpapi.com/images-results
Google limit the number of search per day.
but this service provides unlimited searches...
looks like we need to implement google custom search API
https://developers.google.com/custom-search/
says so on top of the page you provided yourself