Задать вопрос
Ответы пользователя по тегу Google Apps Script
  • 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();


    С уважением.
    Ответ написан
  • Как скачать файл средствами google apps script?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Вариантов загрузки может быть несколько. Как и способов создания файла. Из вопроса не ясно, как создается файл, каие требования предъявляются к загрузке, какой интерфейс используется.
    Предположим, что:
    1. Файл создается в момент загрузки
    2. Файл сохраняется на Диске
    3. Файл загружается через основной интерфейс приложения Таблицы Google

    Основной идеей экспорта/скачивания файлов из Диска является получение ссылки на ресурс
    var file = DriveApp.createFile(fileName, content, 'text/html');
    var downloadUrl = file.getDownloadUrl();

    Теперь достаточно создать событие на стороне клиента, котрое вызовет загрузку. Вариантов может быть несколько. Вот один из них:
    // Создаем окно на клиенте и запускаем
    var a = window.document.createElement('a');
    a.href = downloadUrl;
    a.text = 'Download';
    document.body.appendChild(a);
    a.click();

    В данном месте самое сложное - поставить пользователю интерфейс для реализации загрузки. Это может быть и письмо, и нотификация, и все, что угодно, что может нажимать ссылки.

    Другим вариантом может быть поставка блока данных через Client-side API. Принцип останется прежним, изменится только формат передаваемых данных. С сервера Blob, на клиенте загрузка локального Blob-ресурса.

    Полный код и ссылка на рабочее приложение https://gitlab.com/google-apps-script-russian/zagr...
    Ответ написан
    Комментировать
  • Почему "После списка аргументов отсутствует закрывающая круглая скобка (")"). (строка 2, файл Код)"?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Скорей всего проблема в использовании символа ";". В языке Google Apps Script он используется как разделитель команд интерпретатору. Вы не можете их использовать в таком контексте.
    Ответ написан
    Комментировать
  • Как разрешить Google Apps Script отправлять email для любого пользователя Spreadsheet?

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

    Судя по описанию, User-B прошел авторизацию, а остальные пользователи нет. Заставьте этих пользователей пройти авторизацию, и у них появится разрешение на запуск функций.

    Как заставить пользователей авторизоваться - это проблема разработчика, а не Google. Но, не имея в техническом плане серьезных противоречий, этот подход сложен для понимания практического. Примеры приложений, код которых может быть одинаков до запятой.
    • Отправить присьмо при изменении. Простой триггер onEdit(). Может отпрвлять только то, кто прошел авторизацию.
    • Отправить присьмо при изменении. Устанавливаемый триггер. Триггер установлен кем-то одним. Может отпрвлять только то, кто прошел авторизацию, т.е. один. Письма будут приходить согласно условию в коде.
    • Отправить присьмо при изменении. Устанавливаемый триггер. Триггер установлен каждым умником, кто залез в код. Может отпрвлять только тот, кто прошел авторизацию. Письма будут приходить согласно условию в коде умноженное на количество умников, потому что это будет один и тот же код, срабатываемый для каждого триггера в каждом аккаунте.

    Разрабатывая клиент-серверное приложение, вам необходимо заботиться о многопользовательском доступе. Необходимо разработать процесс и порядок доступа, и только после этого разбираться, как это реализовать. Например,
    • Каждый пользователь сам себе будет отправлять письма? Зачем и нах!?
    • Каждый пользователь будет отправлять письма на заданный адрес?
    • Письма будет отправлять только один аккаунт всем участникам подписки, группе, редакторам и т.д.?
    • Письма будет отправлять только один аккаунт, тому кто совершил изменения? Для аккаунтов googlemail.com это недоступно.

    Лично мне было бы неприятно, что кто-то требует от меня отпрвлять непонятно куда и зачем какие-то письма, выжирая и так скудную квоту.

    Пересмотрите свое приложение. Какие цели оно преследует? Чего вы уже добились? Так ли это работает? Приведите пример кода и суть приложения.
    Ответ написан
    1 комментарий