#google-apps-script #google-sheets #google-places-api
Вопрос:
Я начал с этого проекта в надежде, что API Google Places сможет автоматизировать поиск конкретной информации о бизнесе и местах. Хотя я начал с отдельных функций, я вижу, что это создало чрезмерное количество запросов, которые прошли через мой бесплатный ежемесячный кредит Google Cloud. Это произошло потому, что я написал функции, которые вызывались каждый раз, когда Лист открывался в любом случае.
Вместо этого я хочу, чтобы функции запускались только тогда, когда я использую кнопку пользовательского интерфейса для ее вызова. Но как я могу указать, что он должен выполняться только в тех случаях, когда информация о местах еще не заполнена на листе?
Я бы ввел название места в колонку A, а в колонках B — F у меня будет функция поиска запрошенной информации. Мой скрипт просматривает название места в столбце А и находит идентификатор Google Place. Оттуда он форматирует URL-адрес для этой записи Google Places и извлекает запрошенную информацию из объединенного URL-адреса.
Вот мой текущий код:
// This location basis is used to narrow the search -- e.g. if you were
// building a sheet of bars in NYC, you would want to set it to coordinates
// in NYC.
// You can get this from the url of a Google Maps search.
const LOC_BASIS_LAT_LON = "37.7644856,-122.4472203"; // e.g. "37.7644856,-122.4472203"
function COMBINED2(text) {
var API_KEY = 'AxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxQ';
var baseUrl = 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json';
var queryUrl = baseUrl '?input=' text 'amp;inputtype=textqueryamp;key=' API_KEY "amp;locationbias=point:" LOC_BASIS_LAT_LON;
var response = UrlFetchApp.fetch(queryUrl);
var json = response.getContentText();
var placeId = JSON.parse(json);
var ID = placeId.candidates[0].place_id;
var fields = 'name,formatted_address,formatted_phone_number,website,url,types,opening_hours';
var baseUrl2 = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=';
var queryUrl2 = baseUrl2 ID 'amp;fields=' fields 'amp;key=' API_KEY "amp;locationbias=point:" LOC_BASIS_LAT_LON;
if (ID == '') {
return 'Give me a Google Places URL...';
}
var response2 = UrlFetchApp.fetch(queryUrl2);
var json2 = response2.getContentText();
var place = JSON.parse(json2).resu<
var placeAddress = place.formatted_address;
var placePhoneNumber = place.formatted_phone_number;
var placeWebsite = place.website;
var placeURL = place.url;
var weekdays = '';
place.opening_hours.weekday_text.forEach((weekdayText) => {
weekdays = ( weekdayText 'rn' );
} );
var data = [ [
place.formatted_address,
place.formatted_phone_number,
place.website,
place.url,
weekdays.trim()
] ];
return data;
}
// add menu
// onOpen is a special function
// runs when your Sheet opens
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu("Custom Menu")
.addItem("Get place info","COMBINED2")
.addToUi();
}
Я получил помощь в отдельном сообщении, в котором мне посоветовали использовать другую функцию для вызова COMBINED2
, но я не уверен, применимо ли это по-прежнему при изменении моих планов.
// this function calls COMBINED2()
function call_COMBINED2() {
var ss = SpreadsheetApp.getActiveSheet();
var text = ss.getRange("A2").getValue();
var data = COMBINED2(text);
var dest = ss.getRange("B2:F2");
dest.setValues(data);
}
Если это что-то изменит, мой план на будущее будет состоять в том, чтобы иметь две кнопки в пользовательском пользовательском интерфейсе. Один из них будет работать над первоначальным поиском данных о местоположении. Второй сделает обновление. Если будет обнаружено изменение и ячейка будет изменена/обновлена, то она каким — то образом выделится, чтобы я мог это отметить.
Этот проект-часть того, как я путешествую. Я часто составляю списки рекомендуемых и проверенных достопримечательностей, баров и ресторанов в Google, чтобы я мог импортировать лист в Google myMap для справки, когда мы действительно посещаем. Со временем эти листы/карты, как правило, устаревают с изменениями (особенно с COVID). Я надеюсь, что это послужит их доказательству в будущем и облегчит их обновление.
Ответ №1:
Триггер onOpen в вашем сценарии предназначен только для добавления пользовательского меню на ваш лист. Функция будет выполнена только в том случае, если пользователь выбрал пункт в меню, связанный с этой функцией. В вашем примере щелчок Get place info
приведет к выполнению COMBINED2
функции.
Кроме того, выполнение сценария только в том случае, если информация о месте отсутствует на листе, невозможно, вам необходимо запустить сценарий, чтобы получить идентификатор места и сравнить его с данными на листе. В вашем примере в качестве идентификатора можно использовать place.url. Единственное, что вы можете сделать, — это запретить сценарию заполнять лист.
Здесь я обновил ваш скрипт, изменив функцию, связанную с Get place info
writeToSheet()
«кому». writeToSheet()
позвонит COMBINED2(text)
, чтобы получить информацию о месте, и с помощью текстового навигатора проверит, существует ли URL-адрес места на листе. Если результат TextFinder равен 0, он заполнит лист.
// const LOC_BASIS_LAT_LON = "40.74516247433546, -73.98621366765811"; // e.g. "37.7644856,-122.4472203"
const LOC_BASIS_LAT_LON = "37.7644856,-122.4472203";
function COMBINED2(text) {
var API_KEY = 'enter api key here';
var baseUrl = 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json';
var queryUrl = baseUrl '?input=' text 'amp;inputtype=textqueryamp;key=' API_KEY "amp;locationbias=point:" LOC_BASIS_LAT_LON;
var response = UrlFetchApp.fetch(queryUrl);
var json = response.getContentText();
var placeId = JSON.parse(json);
var ID = placeId.candidates[0].place_id;
var fields = 'name,formatted_address,formatted_phone_number,website,url,types,opening_hours';
var baseUrl2 = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=';
var queryUrl2 = baseUrl2 ID 'amp;fields=' fields 'amp;key=' API_KEY "amp;locationbias=point:" LOC_BASIS_LAT_LON;
if (ID == '') {
return 'Give me a Google Places URL...';
}
var response2 = UrlFetchApp.fetch(queryUrl2);
var json2 = response2.getContentText();
var place = JSON.parse(json2).resu<
var weekdays = '';
place.opening_hours.weekday_text.forEach((weekdayText) => {
weekdays = ( weekdayText 'rn' );
} );
var data = [
place.name,
place.formatted_address,
place.formatted_phone_number,
place.website,
place.url,
weekdays.trim()
];
return data;
}
function getColumnLastRow(range){
var ss = SpreadsheetApp.getActiveSheet();
var inputs = ss.getRange(range).getValues();
return inputs.filter(String).length;
}
function writeToSheet(){
var ss = SpreadsheetApp.getActiveSheet();
var lastRow = getColumnLastRow("A1:A");
var text = ss.getRange("A" lastRow).getValue();
var data = COMBINED2(text);
var placeCid = data[4];
var findText = ss.createTextFinder(placeCid).findAll();
if(findText.length == 0){
ss.getRange(lastRow,2,1, data.length).setValues([data])
}
}
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu("Custom Menu")
.addItem("Get place info","writeToSheet")
.addToUi();
}
Выход:
Пример 1:
После нажатия на пользовательское меню:
Пример 2:
После нажатия на пользовательское меню:
Примечание: Поскольку мы используем lastRow, новая запись должна быть вставлена под последней строкой столбца A. В противном случае она перезапишет последнюю запись.
Ссылка:
Комментарии:
1. Извините, что так долго следил за вашим ответом. Я попытался реализовать это, но не смог добиться таких же результатов, как вы. Я попытался ввести одно или два названия мест в столбец A, но результаты заполнили бы, казалось бы, случайную запись под моей последней введенной строкой и не нашли бы никаких данных для мест, которые я ввел в столбец A. Связано ли это с использованием ввода ячейки
ss.getRange(range).getValue()
, как вы описали в своей последней строке?2. @JeffAbrahams — Вы хотите заполнить столбцы B-G той же строкой, что и столбец A?
3. Да, таково было мое намерение. Я хотел, чтобы можно было ввести название места в колонку А и чтобы запрошенная информация отображалась в той же строке.
4. @JeffAbrahams — Смотрите мой обновленный ответ
5. Я чувствую, что мы почти на месте… Итак, я вошел в три пивоварни в районе определения местоположения GPS в Сан-Франциско. Пивоварение Lupulandia в A2, Dirty Robot Brew Работает в A3, а Cellarmaker Brewing Co. в A4. Когда я нажимаю меню пользовательских функций, он звонит
getColumnLastRow
, чтобы найти последний элемент вошел, а потом работаетCOMBINED2
но вот только собираюсь посмотреть Cellarmaker пивоварения Co. так как он является последним в колонне, когда мы хотим выглядеть на все три пока TextFinder не найти места URL-адрес, как мы указали наwriteToSheet
это нужно перебирать строки?