Делаем переводчик
// Функция onEdit является триггером, который срабатывает при завершении ввода данных в ячейку Таблицы пользователем
// https://developers.google.com/apps-script/guides/triggers/#onedite
function onEdit(e) {
Logger.log(e);
// Получаем диапазон ячеек, в которых произошли изменения
// https://developers.google.com/apps-script/reference/spreadsheet/range
var range = e.range;
// Лист, на котором производились изменения
// https://developers.google.com/apps-script/reference/spreadsheet/sheet
var sheet = range.getSheet();
// Проверяем, нужный ли это нам лист
Logger.log(sheet.getName());
if (sheet.getName() != 'Перевод текста') {
return false;
}
// Переводить необходимо текст, введённый только в первую колонку.
// Проверяем стартовую позицию диапазона
Logger.log(range.getColumn());
if (range.getColumn() != 1) {
return false;
}
for (var i = 1; i <= range.getNumRows(); i++) {
var cell = range.getCell(
i, // номер строки
1 // номер колонки
);
// Получаем текст на русском
var russianText = cell.getValue();
// Переводим текст на английский
// https://developers.google.com/apps-script/reference/language/language-app
var translatedText = LanguageApp.translate(
russianText, // текст
'ru', // с какого языка переводим
'en' // на какой язык переводим
);
// Вставляем переведённый текст во вторую колонку
sheet.getRange(
cell.getRowIndex(), // номер строки
2 // номер столбца
).setValue(translatedText);
}
}

добавляем новый язык / меняем название листа / меняем переменные с var на let
Добавили меню
// Функция onOpen() запускается всегда при открытии документа
// https://developers.google.com/apps-script/guides/triggers/#onopen
function onOpen() {
// Создаём новое меню
// https://developers.google.com/apps-script/reference/base/ui#createmenucaption
SpreadsheetApp.getUi()
.createMenu('Konspekti näited')
.addItem('Пример', '...') // При нажатии откроется ...
.addToUi();
}

Парсинг заголовков сайтов
VAR меняем на LET, название листа – Parsing
function parser() {
let ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName('Parser');
let values = sheet.getDataRange().getValues();
let insertError = function(msg, numRow) {
sheet.getRange(numRow, 2).setValue('ОШИБКА! ' + msg).setBackground('red');
}
let rowNumStart = 1; // Номер строки, с которой необходимо начать парсинг
for (let i = rowNumStart; i < values.length; i++) {
let url = values[i][0];
try {
let response = UrlFetchApp.fetch(url, {
'muteHttpExceptions': true,
'validateHttpsCertificates': false,
'followRedirects': true,
}); // Загружаем страницу по указанному url
} catch(e) {
insertError(e, i+1);
continue;
}
// https://developers.google.com/apps-script/reference/url-fetch/http-response
var responseCode = response.getResponseCode(); // Код ответа сервера
if (responseCode === 200) {
try {
let headers = response.getHeaders();
let charset = headers['Content-Type'].match(/charset=(.*)$/)[1].replace(/[";]+/gi, ''); // Кодировка страницы
} catch (e) {
let contentForCharset = response.getContentText();
let charsetMatch = contentForCharset.match(/charset=(.*?)"/);
let charset = (charsetMatch !== null) ? charsetMatch[1] : "UTF-8";
}
let content = response.getContentText(charset); // Получаем html код страницы
// Получаем название поста
let titleMatch = content.match(/<title[^>]*>\s*([\s\S]*?)\s*</);
if (titleMatch !== null) {
let title = titleMatch[1];
// Вставляем название в таблицу
sheet.getRange(i+1,2).setValue(title);
} else {
insertError('Не удалось распарсить title.', i+1);
}
} else {
insertError('Код ответа сервера != 200.', i+1);
}
}
добавил еще LOGGER для отладки, что бы показывал в логах информацию о том прошел скрипт или нет
Logger.log(“Запрашиваю URL: ” + url);
Logger.log(“Загружено: ” + content.substring(0, 500)); // первые 500 символов
Вводим в url название сайта, выбираем из меню – “запустить парсер” после чего будет выведен title сайта

Дорабатываем код что бы он находил URL
function parser() {
let ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName('Parsing');
if (!sheet) {
SpreadsheetApp.getUi().alert("Ошибка: Лист 'Parser' не найден! Проверьте название.");
return;
}
let values = sheet.getDataRange().getValues();
let insertError = function(msg, numRow) {
sheet.getRange(numRow, 2).setValue('ОШИБКА! ' + msg).setBackground('red');
}
let rowNumStart = 1; // Начинаем со 2-й строки (первая - заголовок)
for (let i = rowNumStart; i < values.length; i++) {
let url = values[i][0];
try {
Logger.log("Запрашиваю URL: " + url);
let response = UrlFetchApp.fetch(url, {
'muteHttpExceptions': true,
'validateHttpsCertificates': false,
'followRedirects': true,
});
let responseCode = response.getResponseCode();
if (responseCode !== 200) {
insertError('Код ответа != 200 (' + responseCode + ')', i+1);
continue;
}
let content = response.getContentText();
let titleMatch = content.match(/<title[^>]*>\s*([\s\S]*?)\s*<\/title>/i);
let title = titleMatch ? titleMatch[1].trim() : "Не найдено";
if (!title || title.length === 0) {
insertError('Не удалось распарсить title.', i+1);
} else {
sheet.getRange(i+1, 2).setValue(title); // Записываем title в колонку B
}
let linkMatch = content.match(/<a\s+(?:[^>]*?\s+)?href=["'](https?:\/\/[^"']+)["']/i);
let firstLink = linkMatch ? linkMatch[1] : "Не найдено";
sheet.getRange(i+1, 3).setValue(firstLink); // Записываем первую найденную ссылку в колонку C
} catch (e) {
insertError("Ошибка запроса: " + e.message, i+1);
}
}
}
let linkMatch = content.match(/<a\s+(?:[^>]*?\s+)?href=["'](https?:\/\/[^"']+)["']/i);
let firstLink = linkMatch ? linkMatch[1] : "Не найдено";
sheet.getRange(i+1, 3).setValue(firstLink); //записываем в С
Ищем первую ссылку на странице


Ищем заголовок первого уровня H1
let h1Match = content.match(/<h1[^>]*>\s*([\s\S]*?)\s*<\/h1>/i);
let firstHeading = h1Match ? h1Match[1].trim() : "Не найдено";
sheet.getRange(i+1, 4).setValue(firstHeading); // Записываем в колонку D

function parser() {
let ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName('Parsing');
if (!sheet) {
SpreadsheetApp.getUi().alert("Ошибка: Лист 'Parser' не найден! Проверьте название.");
return;
}
let values = sheet.getDataRange().getValues();
let insertError = function(msg, numRow) {
sheet.getRange(numRow, 2).setValue('ОШИБКА! ' + msg).setBackground('red');
}
let rowNumStart = 1; // Начинаем со 2-й строки (первая - заголовок)
for (let i = rowNumStart; i < values.length; i++) {
let url = values[i][0];
try {
Logger.log("Запрашиваю URL: " + url);
let response = UrlFetchApp.fetch(url, {
'muteHttpExceptions': true,
'validateHttpsCertificates': false,
'followRedirects': true,
});
let responseCode = response.getResponseCode();
if (responseCode !== 200) {
insertError('Код ответа != 200 (' + responseCode + ')', i+1);
continue;
}
let content = response.getContentText();
//<title>
let titleMatch = content.match(/<title[^>]*>\s*([\s\S]*?)\s*<\/title>/i);
let title = titleMatch ? titleMatch[1].trim() : "Не найдено";
if (!title || title.length === 0) {
insertError('Не удалось распарсить title.', i+1);
} else {
sheet.getRange(i+1, 2).setValue(title); // Записываем title в колонку B
}
let linkMatch = content.match(/<a\s+(?:[^>]*?\s+)?href=["'](https?:\/\/[^"']+)["']/i);
let firstLink = linkMatch ? linkMatch[1] : "Не найдено";
sheet.getRange(i+1, 3).setValue(firstLink); // Записываем первую найденную ссылку в колонку C
let h1Match = content.match(/<h1[^>]*>\s*([\s\S]*?)\s*<\/h1>/i);
let firstHeading = h1Match ? h1Match[1].trim() : "Не найдено";
sheet.getRange(i+1, 4).setValue(firstHeading); // Записываем в колонку D
} catch (e) {
insertError("Ошибка запроса: " + e.message, i+1);
}
}
Доработал меню, корректное название
// Создаём новое меню
// https://developers.google.com/apps-script/reference/base/ui#createmenucaption
let ui = SpreadsheetApp.getUi();
ui.createMenu('Konspekti näited') // Создаём меню
.addItem('Запустить парсер', 'parser') // Добавляем пункт для запуска функции
.addToUi();
}