Как получить доступ к новому in-cell-image из скрипта Google Apps?
Новая функция Вставить> Изображение> Изображение в ячейке на листах Google вставляет изображение в ячейку, а не как OverGridImage. Я хотел бы вставить изображение таким образом, а затем получить доступ к изображению из скрипта Google Apps. Это возможно?
После вставки изображения формула ячейки остается пустой, когда ячейка выбрана. Я попытался найти ссылку на газ, но не смог найти никакой информации об этой относительно новой функции. Есть информация по изображениям над сеткой. Я ожидаю, что изображение в камере будет иметь аналогичные функции.
Я пробовал такие вещи:
// See what information is available on a cell with inserted image:
var image = sheet.getRange(1, 1).getFormula();
Logger.log(image);
Логи отображаются пустыми. Я пробовал несколько: .getImage() (не существует), .getValue(), .getFormula()
Я ожидаю, что смогу получить доступ к URL-адресу изображения или Blob каким-либо образом.
7 ответов
Я из службы поддержки G-Suite. Это новая функция, и, к сожалению, в настоящее время нет способа, позволяющего вставить изображение в ячейку таким образом, используя Google Apps Script или API-интерфейсы Sheets. Попытка получить данные в ячейке с помощью spreadsheets.get
метод со следующими параметрами
spreadsheetId: "ID of private spreadsheet created in Drive"
includeGridData: True
ranges: D7
fields: sheets/data/rowData/values
Вернет 200 response
Однако данные изображения не возвращаются:
{
"sheets": [
{
"data": [
{
"rowData": [
{
"values": [
{
"userEnteredValue": {},
"effectiveValue": {},
"effectiveFormat": {
"backgroundColor": {
"red": 1,
"green": 1,
"blue": 1
},
"padding": {
"top": 2,
"right": 3,
"bottom": 2,
"left": 3
},
"horizontalAlignment": "LEFT",
"verticalAlignment": "BOTTOM",
"wrapStrategy": "OVERFLOW_CELL",
"textFormat": {
"foregroundColor": {},
"fontFamily": "Arial",
"fontSize": 10,
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false
},
"hyperlinkDisplayType": "PLAIN_TEXT"
}
}
]
}
]
}
]
}
]
}
Тем не менее, есть запрос функции для этого в системе отслеживания проблем Google, который вы можете найти здесь. Если вы перейдете на страницу запроса функции и нажмете звездочку в верхнем левом углу, вы можете сообщить Google, что вам также нужна эта функция, и она автоматически получит обновления о ее продвижении.
Я считаю вашей целью следующее.
- Вы хотите получить изображение в ячейке таблицы Google с помощью скрипта Google Apps.
Проблема и решение:
К сожалению, на текущем этапе нет методов для получения изображений в ячейке в электронной таблице в службе электронных таблиц и API таблиц. Об этом уже упоминал Рафа Гильермо в ответе. Итак, в этом ответе я хотел бы предложить обходной путь для получения изображений в ячейках с помощью скрипта Google Apps.
В этом обходном пути я использую данные Microsoft Excel, преобразованные из электронной таблицы Google. Даже когда электронная таблица Google конвертируется в данные Microsoft Excel, изображения в ячейках не удаляются. Я использую это. Конечно, изображения можно также получить из данных HTML, преобразованных из электронной таблицы. Но в этом случае анализ данных HTML немного сложнее, чем анализ данных Excel. Итак, здесь я хотел бы предложить извлекать изображения из данных Excel, преобразованных из электронной таблицы. Последовательность этого обходного пути выглядит следующим образом.
- Преобразуйте электронную таблицу Google в Microsoft Excel (данные XLSX) с помощью Drive API.
- Анализируйте данные XLSX с помощью скрипта Google Apps.
- Когда преобразованные данные XLSX распакованы, данные можно анализировать как данные XML. К счастью, в Microsoft Docs подробная спецификация опубликована как Open XML. Таким образом, в этом случае документы Microsoft, такие как XLSX, DOCX и PPTX, можно анализировать с помощью XmlService скрипта Google Apps. Думаю, что этот метод будет полезен и в других ситуациях.
- Получать изображения из данных XLSX.
Схема 1:
В этом шаблоне я хотел бы представить простой метод.
Пример сценария:
function myFunction() {
const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
const url = "https://docs.google.com/spreadsheets/export?exportFormat=xlsx&id=" + spreadsheetId;
const blob = UrlFetchApp.fetch(url, {headers: {authorization: `Bearer ${ScriptApp.getOAuthToken()}`}}).getBlob().setContentType(MimeType.ZIP);
const xlsx = Utilities.unzip(blob);
xlsx.forEach(b => {
const name = b.getName().match(/xl\/media\/(.+)/);
if (name) DriveApp.createFile(b.setName(name[1]));
});
}
- В этом примере сценария все изображения в электронной таблице экспортируются в виде файлов. Таким образом, в этом случае извлекаются как изображения в ячейках, так и поверх ячеек со всех листов в электронной таблице. Кроме того, он не может получить координату ячейки, в которой изображение находится в ячейке.
- На текущем этапе нет методов для получения изображений в Google Spreadsheet в виде большого двоичного объекта. В этом примере сценария это может быть достигнуто.
- Этот пример сценария не может экспортировать чертежи. Пожалуйста, будьте осторожны.
- когда
setContentType(MimeType.ZIP)
не используется, ошибка возникает наUtilities.unzip(blob)
. Пожалуйста, будьте осторожны.
Схема 2:
В этом шаблоне изображения извлекаются из электронной таблицы с именем листа и координатой ячейки. В этом случае сценарий немного усложняется. Итак, здесь я хотел бы представить образец сценария с использованием библиотеки сценариев Google Apps. Ref Конечно, вы можете увидеть там весь сценарий.
Пример сценария:
Прежде чем использовать этот сценарий, установите
DocsServiceApp
(Автор этой библиотеки GAS - tanaike.) Библиотеки Google Apps Script. Ref И запустить функцию
myFunction
.
function myFunction() {
const cell = "A1";
const sheetName = "Sheet1";
const spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
const obj = DocsServiceApp.openBySpreadsheetId(spreadsheetId).getSheetByName(sheetName).getImages();
console.log(obj)
const blobs = obj.filter(({range, image}) => range.a1Notation == cell && image.innerCell);
console.log(blobs.length)
if (blobs.length > 0) DriveApp.createFile(blobs[0].image.blob);
}
- В этом примере извлекается изображение в ячейке "A1" листа "Sheet1" в активной электронной таблице, и полученный большой двоичный объект создается в корневой папке в виде файла изображения.
Заметка:
- На текущем этапе, когда изображение вставляется в электронную таблицу Google и электронная таблица преобразуется в данные XLSX, изображение, включающее данные XLSX, имеет имя файла
image1
,image2
,,, которые не являются исходным именем файла. Похоже, что это текущая спецификация. - Когда изображения извлекаются из данных XLSX, кажется, что изображение немного отличается от исходного. Формат изображения такой же. Но размер данных меньше, чем у оригинала. Когда размер изображения превышает 2048 пикселей и 72 точек на дюйм, изображение изменяется до 2048 пикселей и 72 точек на дюйм. Даже если размер изображения меньше 2048 пикселей и 72 точек на дюйм, размер файла становится меньше исходного. Поэтому я думаю, что изображение может быть сжатым. Пожалуйста, будьте осторожны.
- На текущем этапе чертежи не могут быть получены напрямую.
Рекомендации:
Теперь доступно по состоянию на январь 2022 г. (примечания к выпуску ):
Следующие классы были добавлены в службу электронных таблиц, чтобы вы могли добавлять изображения в ячейки:
- CellImageBuilder: этот построитель создает значение изображения, необходимое для добавления изображения в ячейку.
- CellImage: представляет изображение для добавления в ячейку.
Чтобы добавить изображение в ячейку, вы должны создать новое значение изображения для изображения, используя
SpreadsheetApp.newCellImage()
а такжеCellImageBuilder
. Затем используйтеRange.setValue(value)
или жеRange.setValues(values)
чтобы добавить значение изображения в ячейку.
Пример:
function insertImageIntoCell()
{
let image = SpreadsheetApp.newCellImage().setSourceUrl('https://www.gstatic.com/images/branding/product/2x/apps_script_48dp.png').setAltTextDescription('Google Apps Script logo').toBuilder().build();
SpreadsheetApp.getActive().getActiveSheet().getRange('A1').setValue(image);
}
Результат:
function getImageFromCell()
{
let value = SpreadsheetApp.getActive().getActiveSheet().getRange('A1').getValue();
console.log(value.getAltTextDescription());
console.log(value.getUrl());
}
Результат:
Примечание:getUrl
возвращается
null
для этого конкретного примера, который, по-видимому, связан с некоторой внутренней недоступностью API, из документов:
Получает URL-адрес источника изображения; возвращает null, если URL-адрес недоступен. Если изображение было вставлено по URL-адресу с помощью API, этот метод возвращает URL-адрес, указанный во время вставки изображения.
Этот ответ касается ВСТАВКИ изображений в ячейку. Мне не удалось найти способ фактически извлечь данные изображения, поэтому ответ Паноса - лучший вариант для чтения данных изображения в ячейке.
Есть несколько способов сделать это, некоторые из них используют недокументированные API.
1.
В =IMAGE(<http url>)
- это стандартная функция, которая отображается на изображении внутри ячейки. Он делает почти то же самое, что и вставка изображения в ячейку вручную.
2. Копирование по стоимости
Как только у вас будет
=IMAGE
image вы можете скопировать его и вставить по значению, которое будет дублировать изображение без формулы (если вы этого хотите по какой-то причине). Вы можете сделать это в скрипте, используя copyTo
функция :
srcImageRange.copyTo(dstRange, { contentsOnly: true })
Это ИЗОБРАЖЕНИЕ без формул отличается от настоящего изображения в ячейке только тем, что при щелчке правой кнопкой мыши по нему отсутствуют параметры контекстного меню «Альтернативный текст» и «Поместить изображение поверх ячеек». Эти параметры отображаются только на реальных изображениях в ячейках.
3. Недокументированные API
Когда ты звонишь
getValue()
на изображении в ячейке (как формуле, так и вставленном вручную) вы получите
CellImage
пример.
CellImage
Основное преимущество, которое я вижу в использовании этого над
IMAGE()
заключается в том, что он поддерживает URL-адреса данных и, следовательно, косвенно поддерживает большие двоичные объекты.
Рабочий пример кода
Имейте в виду, что недокументированные API могут быть изменены без предварительного уведомления.
// 1 (or just use IMAGE in formula directly)
function insertImageFormula(range, httpUrl) {
range.setFormula(`=IMAGE("${httpUrl}")`);
}
// 2
function insertImageValue(range, httpUrl) {
range.setFormula(`=IMAGE("${httpUrl}")`);
SpreadsheetApp.flush(); // Flush needed for image to load.
range.copyTo(range, { contentsOnly: true }); // Copy value onto itself, removing the formula.
}
// 3
function insertCellImage(range, sourceUrl) {
range.setFormula('=IMAGE("http")'); // Set blank image to get CellImageBuilder handle.
const builder = range.getValue().toBuilder();
builder.setSourceUrl(sourceUrl);
builder.setAltTextDescription(sourceUrl); // Put url in description for later identification, for example.
range.setValue(builder.build());
}
const DATA_URI = "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7///"
+ "/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAos"
+ "J6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7";
function test() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
sheet.clear();
sheet.getRange(1, 1).setValue("IMAGE formula");
insertImageFormula(sheet.getRange(2, 1), "https://www.google.com/images/icons/illustrations/paper_pencil-y128.png");
sheet.getRange(1, 2).setValue("Copied-by-value IMAGE");
insertImageValue(sheet.getRange(2, 2), "https://www.google.com/images/icons/illustrations/paper_pencil-y128.png");
sheet.getRange(1, 3).setValue("In-Cell Image (Http URL)");
insertCellImage(sheet.getRange(2, 3), "https://www.google.com/images/icons/illustrations/paper_pencil-y128.png");
sheet.getRange(1, 4).setValue("In-Cell Image (DATA URI)");
insertCellImage(sheet.getRange(2, 4), DATA_URI);
sheet.getRange(1, 5).setValue("In-Cell Image (Blob DATA URI)");
const blob = UrlFetchApp.fetch("https://www.gstatic.com/script/apps_script_1x_24dp.png").getBlob();
insertCellImage(sheet.getRange(2, 5), blobToDataUrl(blob));
}
function blobToDataUrl(blob) {
return `data:${blob.getContentType()};base64,${Utilities.base64Encode(blob.getBytes())}`
}
Этот вопрос немного устарел, но, поскольку сегодня я столкнулся с этой проблемой, позвольте мне поделиться своим опытом.
Я понял, что getValue() ячейки возвращает объект, текст которого является « CellImage ». Это позволяет мне понять, что в этой ячейке есть встроенное изображение. Эти объекты кажутся похожими (или одинаковыми) с объектом OverGridImage . По крайней мере, вы можете использовать методы getAltTextTitle и getAltTextDescription .
Объединив все эти функции, я могу обойтись следующим образом:
- Добавьте определенный AltText к изображению в ячейке.
- Получить значение ячейки в объекте.
- Проверьте, равно ли это "CellImage".
- Если это CellImage, получите AltText.
- В зависимости от значения этого AltText делайте все, что хотите.
Ниже приведен пример кода:
/*-------------------------------------------------------------------------
Custom event handler triggered when a single cell is selected in the spreadsheet.
@param {Event} e The onSelectionChange event.
-------------------------------------------------------------------------*/
function onSingleCellSelected(e) {
var cell = e.range.getCell(1, 1);
var v = cell.getValue();
if(v == "CellImage") {
var altText = v.getAltTextTitle();
Logger.log(v.getAltTextDescription());
if(altText == "@action(recordTime)"){
cell.setBackground("cyan");
}
}
}
И Рафа Гильермо, и Танаике просили меня дать ответ на основе моего комментария к сообщению Танаике. Я делаю это ниже, но это скорее относится к категории обходного пути, чем "ответа". Правильный ответ будет соответствовать точному вопросу в исходном сообщении.
Как я уже сказал в своем комментарии, я использовал этот метод для простых случаев, а также провел несколько тестов, которые показывают, что он сохраняет разрешение изображения. Поскольку я использовал это только для простых случаев, подобных приведенному ниже, я не знаю, как в целом это будет работать.
Шаги, которые я привожу ниже (в меру своих возможностей), я помню, как я проходил через один конкретный пример. Вот первая дюжина строк окончательного результата после использования этого метода:
В этом примере было всего 7100+ строк
Столбец 1 содержал 430+ изображений или пустых ячеек, большинство из которых повторялось несколько раз.
Столбец 2 содержал уникальные идентификаторы для каждого изображения.
Столбец 3 - это имена файлов, которые были привязаны к каждому идентификатору с помощью метода ниже.
Шаги по извлечению изображений из ячеек таблицы Google:
- Измените размер столбца и строк, содержащих изображения, до большего размера (например, 300).
- Используйте Файл> Опубликовать в Интернете и вставьте сгенерированную ссылку в новую вкладку.
- В Chrome используйте Файл> Сохранить страницу как…> Веб-страница, Завершить.
- Изображения будут найдены в папке html, оканчивающейся на _files.
- При необходимости переименуйте файлы, чтобы использовать расширение изображения, и перечислите их по порядку *
Чтобы привязать имена загруженных файлов изображений к ячейкам изображения на листе:
- Дублирующий лист, поскольку следующее приведет к удалению исходных данных
- Выберите столбцы, содержащие изображения и идентификаторы, и используйте Данные> Удалить дубликаты.
- Добавьте новый столбец рядом с идентификаторами, содержащими имена файлов **
- Используйте функцию ВПР для переноса всех имен файлов на исходный лист на основе уникальных идентификаторов ***
* В моем примере все изображения имели такие имена, как p.txt, p(1).txt, p(2).txt и т. Д. В Mac OS Finder я выбрал все файлы и щелкнул правой кнопкой мыши> Переименовать файлы... а затем заменить параметр для замены.txt на.jpg, (1) на (001) и т. д.
** список имен файлов можно получить, например, используя
Terminal ls -l
команда
*** например, я использовал:
=vlookup(B2,unique!$B$2:$C$430,2,false)
Я просто попробовал кое-что довольно простое, и это сработало. Может быть, не работает во всех случаях, зависит от того, добавляли ли вы изображения ранее с помощью формулы ...
- Добавьте изображение через скрипт Google Apps:
var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
var sheet = ss.getSheetByName(SHEET_NAME);
sheet.getRange('A1').setFormula('=IMAGE("https://developers.google.com/google-ads/scripts/images/reports.png")');
Сработало (оно находится в ячейке и будет работать автоматически при изменении размера):
- Затем, чтобы получить URL-адрес изображения из ячейки:
var imgVal = sheet.getRange('A1').getFormula();
var regEx = /"(.*)"/gm;
var url = regEx.exec(imgVal)[1];
Logger.log(url);
Журналы будут: