Задать вопрос
  • Как скачать файл средствами 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...
    Ответ написан
    Комментировать
  • Можно ли создавать свои формулы в Googl Spreadsheets?

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

    https://developers.google.com/apps-script/guides/s...
    Ответ написан
    Комментировать
  • Почему "После списка аргументов отсутствует закрывающая круглая скобка (")"). (строка 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 комментарий
  • Метод getFilesByName() не находит файлы, если в имени с кириллицей присутствуют буквы в верхнем регистре?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Как раз сейчас описываю этот баг. Поставьте звездочку тут.

    Используйте менее точный поиск с дополнительной обработкой результатов. И сервис DriveApp и сервис Drive умеют в строке запроса обрабатывать директиву title contains. См. Search for Files. На данный момент, 2017-08-13, используется API v2, и для поиска в данном случае - это принципиально. Следующий код вернет то, что вы ожидаете:
    function getFileByName(name) { 
      var files = DriveApp.searchFiles(Utilities.formatString('title contains "%s" and trashed=false', name));
      var result = undefined;
      while(files.hasNext()){
        var file = files.next();
        if(file.getName() === name){
          result = file;
          break;
        }
      }
      return result;
    }
    Ответ написан
  • Как связать 2 Google Form между собой?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Задача нетривиальная. Даже не знаю, стоит ли ее решать через Google Apps Script.

    Положим, что есть две Формы. Во-первых, необходимо место под генерацию промокодов. А это должна быть Таблица. Во-вторых, при использовании промокода необходимо выяснить его валидность. А, ну далее продолжать не стоит - Формы неинтерактивны. Форма - это интерфейс сбора информации. Интерфейс - это совокупность средств, методов и правил взаимодействия, в котором нет возможности обратной связи. У разработчика нет доступа к реализации таких методов как загрузка Формы, проверка данных на стороне клиента и пр. Т.е. разработчик не в состоянии реализовать интерфейс Форм.
    Ему доступен интерфейс хранилища Форм. Т.е. разработчик может обратиться по адресу к Форме, получить ее данные, изменить ее свойства.

    Только качественный и проверенный контент
    Ответ написан
  • Как настроить автоответчик писем на заполнение форм на разных языках?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    У вас этот код никогда не заработает нормально. Почитайте комментарии на приведенном вами ресурсе.

    Главная ошибка - это ссылка на активную Таблицу SpreadsheetApp.getActiveSpreadsheet(); В триггере OnFormSubmit не может быть активной Таблицы, потому что никакой пользователь ее не открыл. А если даже и открыл, то он может не быть регистратором триггера или его инициатором.

    Обработка ошибок
    Google Apps Script (речь о данном моменте времени развития языка) не имеет развитых методов отладки. Поэтому обвяжите основной вызов:
    /**
    * В Таблице должен быть лист "Лог".
    * Чтобы лист существовал всегда
    * https://github.com/oshliaer/google-apps-script-snippets#get-a-sheet-by-name
    **/
    function handler(e) {
      try {
        sendFormByEmail(getNewEmailMessage(e));
      } catch(err) {
        e.source.getSheetByName('Лог').appendRow([new Date(), err.message, err.stack]);
      }
    }

    Отлично, теперь все, что упало в рантайме, будет вам известно.

    Текущая Таблица/Лист
    Я приываю не только автора топика, но вообще всех: "Пожалуйста, не трогайте ActiveSpreadsheet, ActiveSheet и ActiveRange, т.к. это не VBA. Это #ВАЩЕ_НАФИГ_ДРУГАЯ_ВСЕЛЕННАЯ!". Обратите внимание на код выше e.source.getSheetByName(). Это все, что надо.
    А вот пример комутатора:
    /**
    * Определение языка на основе ответа
    **/
    function getNewEmailMessage(e) {
      var sheet = e.range.getSheet();
      var lang = 'EN';
      switch(sheet.getName()){
        case 'RU':
           return 'Ответ на русском';
           break;
        case 'EN':
           return 'Ответ на нерусском';
           break;
      }
      return 'Ответ на русском';
    }

    Осталось добавить аргументов и переписать sendFormByEmail согласно принимаемым параметрам.

    Триггер на несколько Форм

    Вместо заключения
    Только качественный и проверенный контент
    Ответ написан
    4 комментария
  • Почему не работает Get запрос в Google Apps Script через file_get_contents?

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

    Самый простой способ вызвать корректно сервис - это опубликовать его. Ссылки очень легко отличаются по своим окончаниям:
    • /dev - адрес для тестирования
    • /exec - текщий адрес приложения


    Подробности Web Apps / Deploying a script as a web app
    Консультации по GS
    Ответ написан
    Комментировать
  • Удобоваримые ответы из google forms в spreadsheet, как правильно?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Не используйте "обработку формулой по триггеру" в данном случае. Вам просто необходим скрипт, который будет преобразовывать текущие данные в подходящие для отчета формы. Без примера сложно сказать, как именно необходимо разделить данные, но в общем случае это будет выглядеть как-то так https://productforums.google.com/forum/#!topic/doc... Там задача несколько сложнее чем у вас, рассчитываются веса вхождений для каждого ответа. Скопируйте Таблицу, в ней появится меню генерации отчета.

    Консультации https://google-apps-script-russian.gitlab.io/page/...
    Ответ написан
    Комментировать
  • Как отфильтровать таблицу по определенному тексту в столбце?

    oshliaer
    @oshliaer Куратор тега Google Sheets
    Google Products Expert
    Используйте опцию "Filter by condition..." См. "фильтровать по условию".
    Ответ написан
    Комментировать
  • Суммирование по цвету ячеек и цвету шрифтов?

    oshliaer
    @oshliaer Куратор тега Google Sheets
    Google Products Expert
    Custom Count and Sum - дешево и сердито.
    Ответ написан
    Комментировать
  • Как работать в google script с защищенными листами google таблиц?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Вам нужны два скрипта:
    1. Сервер-приемник (запускается от имени владельца защищенного диапазона)
    2. Программа-инициатор (запускается от имени пользователя)


    Вам необходимо будет решить несколько проблем:
    • Определение подлинности программы-инициатора на сервере
    • Контроль команд на выполнение
    • Согласованная разработка и поддержка двух программ
    Ответ написан
    Комментировать
  • Как заставить работать скрипт дистанционно?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Рассмотрите две возможные проблемы:

    Во-первых. Прежде чем отправлять запрос, ваше приложение должно авторизоваться через и получить токен.
    This method requires authorization with an OAuth 2.0 token that includes at least one of the scopes listed in the Authorization section; script projects that do not require authorization cannot be executed through this API.


    Во-вторых: У вас 404 ошибка. Ресурс не найден. Проверьте коррекность адреса
    POST https://script.googleapis.com/v1/scripts/{scriptId}:run

    В данном случае {scriptId} - это уникальный номер самого скрипта, который находится в меню Файл - Свойства проекта - Ключ проекта

    Если вы не хотите авторизовываться, но вам очень надо отправить POST, попробуйте
    function doPost(e) {
      return ContentService.createTextOutput(JSON.stringify({status: 'ok'}))
        .setMimeType(ContentService.MimeType.JSON);
    }


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

    Добавлено

    Еще одной частой проблемой является необходимость вручную добавить в файл манифеста области видимости для скрипта, чтобы он мог иметь доступ к Script API.
    Ответ написан
    1 комментарий
  • Как сделать COUNTIF по условию соседнего столбца?

    oshliaer
    @oshliaer Куратор тега Google Sheets
    Google Products Expert
    Вероятнее всего вам нужна формула COUNTIFS()
    Например,
    =COUNTIFS(A2:A9,"=Яндекс.Такси",B2:B9,"=Стоимость")

    Пример Таблицы с полями выбора

    2ff795ba82e44844a2e99880c6ea9ee5.png
    Ответ написан
    1 комментарий
  • Можно ли загружать фаилы с сервера на Google drive с их api без OAuth 2.0?

    oshliaer
    @oshliaer
    Google Products Expert
    AlexStolman,
    Authorizing Your App with Google Drive
    All requests to the Google Drive API must be authorized by an authenticated user. Google Drive uses the OAuth 2.0 protocol for authenticating a Google account and authorizing access to user data. You can also use OAuth 2.0 or Google+ Sign-in to provide a "sign-in with Google" authentication method for your app #REF

    Поэтому выход только один PHP Quickstart.
    Простым вариантом может быть поиск приложения или расширения (как это в PHP?) вашего фреймворка (или у вас все от руки?) для работы с Диском.

    С уважением.
    Ответ написан
    Комментировать
  • Можно ли полностью расшарить Google Drive?

    oshliaer
    @oshliaer
    Google Products Expert
    Алексей Савчук,
    • Если речь идет об обычном частном аккаунте, то нет. Как вариант можно написать скрипт, который будет добавлять (не перемещать) в заданную папку все что видит и назначать права.
    • В Google Apps for Work администратор домена имеет такие привилегии.

    С уважением.
    Ответ написан
    Комментировать
  • Как отправить данные javaScript - ом в гугл таблицы?

    oshliaer
    @oshliaer Куратор тега Google Sheets
    Google Products Expert
    1. Ваша функция на сервере Google Apps Script ничего не возвращает.
    2. Ваш сервер на Google Apps Script ожидает GET-запрос.

    Код сервера
    function doPost(e){
      var response = {};
      try {
        var sheet = SpreadsheetApp.openById('1iZazQ8YSMa6b9WFKTHJ99WooEC48nH9IF1x9fh6dQ9Y');
        sheet.appendRow([new Date(), JSON.stringify(e)]);
        response = {'result': 'OK'};
      } catch(err) {
        response = {'error': 'error'};
      } finally {    
        return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
      }
    }


    С уважением.
    Ответ написан
    Комментировать
  • Как сделать выпадающий список с добавлением новых элементов?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Здравствуйте,

    доступа к манипулированию IU нет. Добавят ли разработчики эту особенность неизвестно. Вопрос был поднят больше года назад на импортном форуме по Диску. Тогда из вариантов был сайдбар, но это неудобно.

    Идея larionov_n похожа на выстрел из пушки по воробьям. Почему бы тогда не использовать нормальную БД вместо кастрированного табличного процессора? Но, в то же время, могу сказать, что манипулирование Таблицей через внешнее приложение с AngularJS на фронте самое популярное в моих заказах. Т.е. на свой вопрос я найти ответа не могу.
    Ответ написан
    Комментировать
  • Как избежать timout в 6 минут при разработке дополнения?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Здравствуйте.

    Никак.
    Script runtime 6 min / execution и добавьте к ним Triggers total runtime 1 hr / day , а еще URL Fetch data received 50MB / day (хотя не понятно, что вы там такое втягиваете). Вам необходимо завести собственный сервер.

    Еще возможно, что страдает логика приложения.

    С уважением.
    Ответ написан
    1 комментарий
  • Как сделать вложенный цикл в google spreadsheet?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Ни при каких обстоятельствах не дразните систему setValue(), да еще и во вложенном цикле. Запись происходит не на ваш ПК, а на сервер. Кому понравится, когда его так дергают?

    Чтобы работало даже с "черновиками", т.е. до 50 000 строк на лист, сначала берите ВСЕ данные, потом формируйте ГОТОВЫЙ массив, потом делайте setValue().

    Примерно так:
    function writeData(){
      //Не факт, что поможет, но вдруг
      SpreadsheetApp.flush();
      
      //Далее как у всех
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      
      var resultSheet = ss.getSheetByName("Result");
      var agentsSheet = ss.getSheetByName("Buyers");
      var productsSheet = ss.getSheetByName("Products");
      
      var aV = agentsSheet.getDataRange().getValues();
      var pV = productsSheet.getDataRange().getValues();
      
      //срезать шапку
      aV.shift();
      //  pV.shift();
      
      var res = [];
      
      for(var i = 0; i< aV.length; i++)
      {
        res.push([].concat([aV[i][0]], pV[0]));    
        for(var j = 1; j < pV.length; j++){      
          res.push([].concat([''], pV[j]));      
        }
      }
      
      res = res.slice(0, 50000);
      resultSheet.getDataRange().clear(); 
      resultSheet.getRange(1, 1, res.length, res[0].length).setValues(res);
    }
    Ответ написан
    1 комментарий