Как получить доступ к новому 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, преобразованных из электронной таблицы. Последовательность этого обходного пути выглядит следующим образом.

  1. Преобразуйте электронную таблицу Google в Microsoft Excel (данные XLSX) с помощью Drive API.
  2. Анализируйте данные XLSX с помощью скрипта Google Apps.
    • Когда преобразованные данные XLSX распакованы, данные можно анализировать как данные XML. К счастью, в Microsoft Docs подробная спецификация опубликована как Open XML. Таким образом, в этом случае документы Microsoft, такие как XLSX, DOCX и PPTX, можно анализировать с помощью XmlService скрипта Google Apps. Думаю, что этот метод будет полезен и в других ситуациях.
  3. Получать изображения из данных 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. Копирование по стоимости

Как только у вас будет =IMAGEimage вы можете скопировать его и вставить по значению, которое будет дублировать изображение без формулы (если вы этого хотите по какой-то причине). Вы можете сделать это в скрипте, используя copyToфункция :

      srcImageRange.copyTo(dstRange, { contentsOnly: true })

Это ИЗОБРАЖЕНИЕ без формул отличается от настоящего изображения в ячейке только тем, что при щелчке правой кнопкой мыши по нему отсутствуют параметры контекстного меню «Альтернативный текст» и «Поместить изображение поверх ячеек». Эти параметры отображаются только на реальных изображениях в ячейках.

3. Недокументированные API

Когда ты звонишь getValue() на изображении в ячейке (как формуле, так и вставленном вручную) вы получите CellImage пример.

CellImage

Основное преимущество, которое я вижу в использовании этого над IMAGE() заключается в том, что он поддерживает URL-адреса данных и, следовательно, косвенно поддерживает большие двоичные объекты.

Рабочий пример кода

Имейте в виду, что недокументированные API могут быть изменены без предварительного уведомления.

Ссылка на пример Spreadhseet

      // 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:

  1. Измените размер столбца и строк, содержащих изображения, до большего размера (например, 300).
  2. Используйте Файл> Опубликовать в Интернете и вставьте сгенерированную ссылку в новую вкладку.
  3. В Chrome используйте Файл> Сохранить страницу как…> Веб-страница, Завершить.
  4. Изображения будут найдены в папке html, оканчивающейся на _files.
  5. При необходимости переименуйте файлы, чтобы использовать расширение изображения, и перечислите их по порядку *

Чтобы привязать имена загруженных файлов изображений к ячейкам изображения на листе:

  1. Дублирующий лист, поскольку следующее приведет к удалению исходных данных
  2. Выберите столбцы, содержащие изображения и идентификаторы, и используйте Данные> Удалить дубликаты.
  3. Добавьте новый столбец рядом с идентификаторами, содержащими имена файлов **
  4. Используйте функцию ВПР для переноса всех имен файлов на исходный лист на основе уникальных идентификаторов ***

* В моем примере все изображения имели такие имена, как 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);

Журналы будут:

Другие вопросы по тегам