Ответы пользователя по тегу Google Apps Script
  • Удаление символов до определенного сочетания в ячейке таблицы Google Sheets/Excel?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Не получается скриптами, попробуйте для начала формулами. Например,

    =ARRAYFORMULA(REGEXEXTRACT(A2:A;".*?gclid=(.*)$"))

    5c6fcc3c98a59827080515.png

    Пример скрипта. Переписывает данные в диапазоне

    function run() {
      const sheet = SpreadsheetApp.getActiveSpreadsheet()
        .getSheetByName('Решение (скриптами)');
      const range = sheet.getRange('A:A');
      const values = range.getValues();
      const data = values.map(row => {
        const [undefined, value] = String(row[0]).split('gclid=');
        return [value ?? ''];
      });
      range.setValues(data);
    }


    Таблица с примерами https://docs.google.com/spreadsheets/d/1Nll6tQ-I9a...
    Ответ написан
    Комментировать
  • Google forms POST или api?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Единственный на данный момент "правильный" способ управления Формами - использование Google Apps Script. Для реализации API используйте специальный триггер `doGet`.

    У вас должно получиться что-то вроде этого

    function doGet(e){
      /* если `e` содержит параметр на отключение Формы */
      form.setAcceptingResponses(false);
      /* если `e` содержит параметр на разрешение Формы принимать ответы */
      form.setAcceptingResponses(true);
    }


    Опубликуйте скрипт как веб приложение и дергайте из питона сколько лезет. Если сильно заморочиться, то можно опубликовать как API и контролировать доступ к скрипту на уровне авторизации пользователя.
    Ответ написан
    Комментировать
  • Как сравнить два диапазона и выбрать нужные данные?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Вам необходимо строить индекс по принципу баз данных, иначе в циклах все будет очень сложно.

    function main() {
      var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
        'данные'
      );
      var dataArray = dataSheet.getDataRange().getValues();
      var listSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
        'список сайтов'
      );
      var listArray = listSheet.getDataRange().getValues();
      // Строим индекс
      var listIndex = listArray.map(function(r){
        return r[0];
      });
      for (var j = 1; j < dataArray.length; j++) {
        if(dataArray[j][0] === '') continue;
        var pos = listIndex.indexOf(dataArray[j][0]);
        if (pos >= 0) {
          // Обновляем
          listSheet.getRange(pos + 1, dataArray[j].length + 1).setValue(new Date());
        } else {
          // Добавляем
          listSheet.appendRow([].concat(dataArray[j], new Date()));
        }
      }
    }
    Ответ написан
    Комментировать
  • Google Apps Script для Google таблиц: как переименовать все листы в таблице скриптом?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Вам просто необходимо получить листы Таблицы, и переименовать их как надо.

    Решение

    SpreadsheetApp.openById('blah-blah')
      .getSheets()
      .forEach(function(sheet) {
        var name = sheet.getRange('J2').getValue();
        if (name)
          try {
            sheet.setName(name);
          } catch (error) {
            console.error('CATCHED', error);
          }
      });


    Как делают

    Основная идея заключается в том, чтобы перебрать все элементы массива, отсортировать лишнее, а с выбранными элементаи произвести действие. Функция userActionRenameSheets демонстрирует это.

    /* exported userActionRenameSheets */
    
    /**
     * Действие пользователя или триггера. Внешний вызов без параметров
     */
    function userActionRenameSheets() {
      var spreadsheet = SpreadsheetApp.openById('blah-blah');
    
      /** @type {filterSheets} */
      var filterSheets = function(sheet) {
        return true;
      };
    
      /** @type {renameRule} */
      var renameRule = function(sheet) {
        var name = sheet.getRange('J2').getValue();
        if (name)
          try {
            sheet.setName(name);
          } catch (error) {
            console.error('CATCHED', error);
          }
        return sheet;
      };
    
      var sheets = renameSheetsByCellValue_(spreadsheet, filterSheets, renameRule);
      // Делать что-нибудь дальше
    }
    
    /**
     * Переименовывает листы в Таблице согласно заданным правилам
     *
     * @param {GoogleAppsScript.Spreadsheet.Spreadsheet} spreadsheet Таблица,
     *         в которой производим переименование
     * @param {filterSheets} Фильтр листов на всякий случай, вдруг что-то надо да пропустить
     * @param {renameRule} Правило переименования, может возвращать что угодно
     * @param {any[]} Массив отфильрованных результатов функции renameRule
     */
    function renameSheetsByCellValue_(spreadsheet, filterSheets, renameRule) {
      var res;
      var sheets = spreadsheet.getSheets();
      if (filterSheets) res = sheets.filter(filterSheets) || sheets;
      if (renameRule) res = res.map(renameRule);
      return res;
    }
    
    /**
     * Фильтр листов
     * @callback filterSheets
     * @param {GoogleAppsScript.Spreadsheet.Sheet} sheet Текущий лист
     * @param {number} index Текущий индекс массива
     * @param {GoogleAppsScript.Spreadsheet.Sheet[]} sheets Текущий массив
     * @returns {boolean}
     */
    
    /**
     * Правило переименования
     * @callback renameRule
     * @param {GoogleAppsScript.Spreadsheet.Sheet} sheet Текущий лист
     * @param {number} index Текущий индекс массива
     * @param {GoogleAppsScript.Spreadsheet.Sheet[]} sheets Текущий массив
     * @returns {any}
     */
    Ответ написан
  • Как настроить отправку данных из таблицы в виде одной строки в другую закрытую таблицу?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Действительно, это не так очевидно с первого раза, но, когда сталкиваешься, то понимаешь, что пользователь должен быть редактором, чтобы вносить изменения. Чтобы решить эту задачу необходимо предоставить другой интерфейс для ввода данных.

    Замените myFunction на что-то вроде:
    function recordToMain(){
      // Берет диапазон 'Источник!B4:B8' активной Таблицы, т.о. это встроенный скрипт
      var data = SpreadsheetApp.getActive().getRange('Источник!B4:B8')
      .getValues().map(function(row){return row[0];});
      var url = 'https://script.google.com/macros/s/ZZZ/exec';
      var options = {
        method: 'POST',
        headers: {
          ContentType: 'application/json'
        },
        payload: JSON.stringify(data),
        muteHttpExceptions: true
      };
      UrlFetchApp.fetch(url, options); 
    };


    Так же создайте новый проект скриптов, в котором создайте функцию вроде:
    function doPost(e) {
      SpreadsheetApp.openById('YYY') // Должна существовать
      .getSheetByName('Приемник')    // Должен быть лист 'Приемник'
      .appendRow([new Date()].concat(JSON.parse(e.postData.contents)));
    }

    Когда вы опубликуете новый проект для всех от имени себя, то получите url_master для первой функции.
    Ответ написан
  • Загрузка картинок из google drive. Какой правильный путь?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Оба метода сопоставимы и не имеют никакой разницы в контексте инфраструктуры Гугл. Это все сервисы Диска и дергаете вы АПИ Диска. Которое само по себе не дойная корова. Не стоит расчитывать, что при частом запросе изображений вы не увидите отказа в доступе или отказа в соединении. Исполььзуйте Google Cloud Storage. Потратьте уже наконец $10 в год и получите цивильный, быстрый, надежный удобный доступ к сетевому шарингу.
    Ответ написан
  • Как изменить язык в Google Apps Script?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    5c0ffc9a09bee441507346.png
    Ответ написан
    Комментировать
  • Почему неправильно рассчитывается дата?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Ответ на этот вопрос дан на ruSO https://ru.stackoverflow.com/q/882107

    Основная идея в том, чтобы использовать базовые единицы расчета дат (миллисекунды), а не их производные (дни, часы, минуты).

    Хотелось бы добавить, что
    >  new String('Hello world!') == 'Hello world!'
    <· true
    >  new String('Hello world!') === 'Hello world!'
    <· false

    И в данном контексте создание объекта строки неуместно.
    Ответ написан
    Комментировать
  • Как получить значения всех ячеек в колонке?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    /**
     * @param {GoogleAppsScript.Spreadsheet.Sheet} sheet Лист Таблицы
     * @param {number} column Номер столбца
     * @param {number} [startRow] Пропускает количество строк сначала
     * @param {number} [numColums] Количество возвращаемых колонок
     * @returns {Object[][]} Массив значений
     * @see {@link https://toster.ru/q/549725}
     */
    var getValuesFromColumn = function(sheet, column, startRow, numColums) {
        startRow = startRow || 1;
        numColums = numColums || 1;
        var lastRow = sheet.getLastRow();
        return sheet
            .getRange(startRow, column, lastRow - startRow + 1, numColums)
            .getValues();
    };
    
    var arr = getValuesFromColumn(mainSheet, 3, 3, 2);
    Ответ написан
    Комментировать
  • Как можно с помощью google apps script найти все ссылки в google document?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Основной принциип поиска ссылок и базовый код может быть таким
    /**
     * Get an array of all LinkUrls in the document. The function is
     * recursive, and if no element is provided, it will default to
     * the active document's Body element.
     *
     * @param {Element} element The document element to operate on. 
     * .
     * @returns {Array}         Array of objects, vis
     *                              {element,
     *                               startOffset,
     *                               endOffsetInclusive, 
     *                               url}
     */
    function getAllLinks(element) {
      var links = [];
      element = element || DocumentApp.getActiveDocument().getBody();
    
      if (element.getType() === DocumentApp.ElementType.TEXT) {
        var textObj = element.editAsText();
        var text = element.getText();
        var inUrl = false;
        for (var ch=0; ch < text.length; ch++) {
          var url = textObj.getLinkUrl(ch);
          if (url != null) {
            if (!inUrl) {
              // We are now!
              inUrl = true;
              var curUrl = {};
              curUrl.element = element;
              curUrl.url = String( url ); // grab a copy
              curUrl.startOffset = ch;
            }
            else {
              curUrl.endOffsetInclusive = ch;
            }          
          }
          else {
            if (inUrl) {
              // Not any more, we're not.
              inUrl = false;
              links.push(curUrl);  // add to links
              curUrl = {};
            }
          }
        }
      }
      else {
        var numChildren = element.getNumChildren();
        for (var i=0; i<numChildren; i++) {
          links = links.concat(getAllLinks(element.getChild(i)));
        }
      }
    
      return links;
    }


    Источник Get All Links in a Document
    Ответ написан
    Комментировать
  • Как загружать последнюю версию таблицы Google Spreadsheet?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    SpreasheetApp.flush();
    Ответ написан
    Комментировать
  • Как получить названия папок(путь) что хранят файл?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Абсолютно бесполезное занятие, которое требует больших ресурсов. Плюс, на Диске могут быть папки в папках своих папок. Как вам такой поворот?

    Решение доступно в этом топике How do I locate the path of the folder in which th...
    Ответ написан
    Комментировать
  • Как сделать что бы при ставке чисел убирались лишние символы в гугл док?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Если данные заполняются оператором, то скорей всего, ему потребуется инструмент для нормализации данных. Это может быть как локальная программа, например, расширение браузера, так и дополнение к самим Таблицам.

    Пример работы дополнения.
    Пользователь открывает боковое меню, которое остается открытым весь период работы
    5aba02ef6e9b3253891467.png

    Добавляет значение из буфера в верхнее поле, получает результат в нижнем поле. Возможно заполнение буфера новым значением автоматически
    5aba03516b237273893919.png
    Ответ написан
    Комментировать
  • Превышено максимальное время выполнения Google Script, как решить?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Ваш же вопрос тут Максимальное время выполнения скрипта Google Script

    К тому же не ведете переписку по другим вопросам.

    Вы не можете преодолеть пердел исполнения в 6 минут. Для того, чтобы получить результаты поиска при повторном запуске скрипта, вы должны сохранить во внешнем хранилище значение токена, который действет неделю.

    if (continuationToken == null) {
      var files = DriveApp.getFiles();
    } else {
      var files = DriveApp.continueFileIterator(continuationToken);
    }
    где continuationToken заранее получен и извлечен из внешнего хранилища.
    
    if(files.hasNext()){
      var continuationToken = files.getContinuationToken();

    Для автоматического перезапуска скрипта вы должны создавать триггеры времени.

    Чтобы представить всю масштабность задачи, можете взглянуть на готовое приложение для копирования Диска ericyd/gdrive-copy

    Также существует несколько сниппетов и библиотек, которые позволяют "продлить" исполнение тем же методом, который я описал выше.
    Ответ написан
    Комментировать
  • Как сделать, чтобы функция срабатывала, когда значение ячейки в таблице меняется формулой?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Виктор Фамильевич, никак. Это особенность среды исполнения.

    Но у вас нет причин искать вызова триггера при таких условиях. Что-то же меняет это значение? Подпишитесь на изменение этого "что-то же" или дублируйте их.
    Ответ написан
    Комментировать
  • Где ошибка в коде Google Script для экспорта в txt?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Замените
    var values = SpreadSheets.getRange(i, c).getValue();

    на
    var values = SpreadSheets.getRange(i, c).getValues();


    Но я бы так не делал. Диск - сложная экосистема датчиков и инициирующих событий. Возможно, вы могли бы несколько углубиться в изучение и постичь дзен событийной модели, авось, что-то будет работать более плавно и без сбоев, и реально онлайн.
    Ответ написан
    Комментировать
  • Как правильно использовать LockService в Google Apps Script?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Метод waitLock вызывает исключение, обрабатывайте его.

    var lock = LockService.getPublicLock();
    try {
      lock.waitLock(30000);
      return success();
    } catch (err) {
      Logger.log('Could not obtain lock after 30 seconds.');
      return failure();
    }


    Для неразрывности функции используйте tryLock. Этот метод заворачивает результат блокировки в булево значение:
    var lock = LockService.getPublicLock();
    var success = lock.tryLock(30000);
    if (!success) {
      Logger.log('Could not obtain lock after 30 seconds.');
    }
    Ответ написан
    Комментировать
  • Как в Google Apps Script отличить запуск ф-ии по триггеру своего и чужого аккаунта?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Возможно, вы уже читали статью "Эффективный пользователь против Активного", на основании которой ваш вопрос можно считать риторическим. Если у вас, конечно, gmail аккаунт, а не G Suite.

    Подтверждая ваши слова, вам необходимо создать один standalone скрипт. Позволить каждому пользователю зарегистрировать триггер - каждый сам себе. При такой настройке, во время срабатывания скрипта для каждого владельца скрипта в Active User будет его email, иначе пусто.

    Но тут существует подводный камень. Это не всегда работает. В какой-то момент Google раскрыл для владельцев (не G Suite) адреса Effective Users. Это было неприятно. Представьте, я даю вам доступ по ссылке, вы открываете Таблицу, а мой триггер onOpen уже знает, кто вы есть (ну, как минимум ваш адрес электронной почты). Что было делать - отрубить и не давать.

    Как можно решать вашу проблему? Нет эффективных методов решения этой задачи. Они либо громоздкие, либо слишком мутные, чтобы оставаться в рабочем состоянии долгое время.

    Я одно время использовал монитор почты, но пользователю необходимо подписаться на изменения в Таблице. Может быть в новом API есть возможность подписать пользователя автоматически?
    Ответ написан
    3 комментария
  • Как передать группу значений checkbox в форме?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    [Ljava.lang.Object;@556935f1 - это массив. Таблицы не поддерживают сложные типы. Попробуйте привести массив к строке.
    Вместо form['checkbox_name[]']
    можно form['checkbox_name[]'].join(', ')
    или JSON.stringify(form['checkbox_name[]'])
    как вариант предыдущего
    JSON.stringify(form['checkbox_name[]'], null, '  ')
    Ответ написан
    1 комментарий
  • Как отобразить в Таблице текст со страницы?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Никак.

    Такой возможности нет, потому что, скорей всего, контент на странице состоит из компонентов, которые требуют работы браузера, а в Таблицах такой возможности нет.

    Можете попробовать сами любую функцию импорта или скрипт
    UrlFetchApp.fetch('https://www.pochta.ru/tracking#RG886664219CN').getContentText();


    С уважением.
    Ответ написан