Ответы пользователя по тегу Google Apps Script
  • Как автоматизировать загрузку данных с определенной ячейки на множестве листов?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Есть несколько ускоренных вариантов:
    1. Получить скриптом имена всех листов, скопировать из в Notepad++ и сделать пару замен-дополнений, преобразовав всё в формулы, а формулы вставить в лист
    2. Написать скрипт, который пропишет эти формулы в ячейки - опять же, перебор листов, запись в ячейки
    3. Сделать юзер функцию, которая переберёт листы и вытащит нужную ячейку. Я бы предусмотрел в ней чёрный список, чтобы не хватала всё подряд

    Если нужно готовое решение - пишите в телеграм
    Ответ написан
    2 комментария
  • Как написать скрипт, чтобы в определенной ячейке/ах каждое слово было с заглавной буквы?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    function doProperFirst(sheetName="Лист1") {
      let dataRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName).getDataRange();
      let data = dataRange.getValues()
                          .map(row=>row.map(properFirst));
      dataRange.setValues(data);
    };
    
    /**
     Преобразует первую букву каждого слова в верхний регистр.
     @param {string} str - Строка для преобразования.
     @returns {string} - Преобразованная строка.
    */
    function properFirst(str){
      return String(str).split(" ").map(word=>word===""?"":word.charAt(1).toLocaleUpperCase()+word.substring(1)).join(" ");
    };
    Ответ написан
  • Как задать условие импорта через Apps Script?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    const filterValue = bookSS.getSheetByName("Sheet_Values ").getRange("B3").getValue();
    var bookListValues = bookRange.getValues().filter(row=>row[3]===filterValue );
    Ответ написан
    3 комментария
  • Как сделать уведомление о изменении ячейки в Google таблицах?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    /**
     * Возникает при изменении ячейки
    * @param {e} event event-объект https://developers.google.com/apps-script/guides/triggers/events?hl=ru
     * [ ProgrammerForever (c) 2020 ]
     * @return Не возвращает значений
     */
    function onEdit(event) {
      var ss = event.source.getActiveSheet();//Текущий лист
      var address = event.range.getA1Notation().toUpperCase();//Адрес ячейки
      var row = event.range.getRow();      //Номер строки
      var col = event.range.getColumn();  //Номер столбца
      var newValue = event.value;            //Новое значение
      var oldValue = event.oldValue;        //Старое значение
      var userEmail = event.user.getEmail();//Пользователь(работает только при вручную назначенном триггере)
      
      if((ss.getName==="Лист1")&&(row>=2)&&(col===4)&&(newValue ==="Готово")){ // Все проверки
        // Что-то делаем
      };
    };
    Ответ написан
    Комментировать
  • Изменение, создание гугл документа через apps script в гугл таблицах?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Начните с...
    let doc = DocumentApp.openById(docId);
    Остальное интуитивно понятно. Ну или читайте соответствующую документацию
    Ответ написан
  • Как сделать так, чтобы данные из ячейки падали в сумму?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    При интенсивном вводе часть событий onEdit может пропускаться. Если это просто индикатор "плюс-минус-лапоть", то можно так и сделать. Иначе можно просто потерять часть данных. Лучшее решение: всё-таки держать реестр операций; таблица может содержать миллионы ячеек, да и лист можно скрыть с глаз, если мешает.
    Заготовка кода для onEdit() триггера

    /**
     * Возникает при изменении ячейки
    * @param {e} event event-объект https://developers.google.com/apps-script/guides/triggers/events?hl=ru
     * [ ProgrammerForever (c) 2020 ]
     * @return Не возвращает значений
     */
    function onEdit(event) {
      var ss = event.source.getActiveSheet();//Текущий лист
      var address = event.range.getA1Notation().toUpperCase();//Адрес ячейки
      var row = event.range.getRow();      //Номер строки
      var col = event.range.getColumn();  //Номер столбца
      var newValue = event.value;            //Новое значение
      var oldValue = event.oldValue;        //Старое значение
      var userEmail = event.user.getEmail();//Пользователь(работает только при вручную назначенном триггере)
      
      //Делаем что-то
    };

    Ответ написан
    Комментировать
  • Google apps script Exception: Address unavailable?

    ProgrammerForever
    @ProgrammerForever
    Учитель, автоэлектрик, программист, музыкант
    WB блокирует IP гугла. Но это не точно, читал мельком недавно в профильных чатах.
    Ответ написан
    Комментировать
  • Как с помощью importxml узнать, что объявление на авито снято с продажи?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Сайты подобной тематики и сложности не очень-то и любят парсинг. Уверен, что данные получаются отдельным запросом. Отключите JS в браузере и проверьте что отдаёт страница. Или вместо запроса в IMPORTXML поставьте звёздочку - вывалится список всех нод. Или ещё вариант:
    /**
    * Открывает URL и возращает код страницы
    * Telegram - @ProgrammerForever
    *
    * @param {string} URL URL который нужно открыть
    * @param {boolean} isCut Указывакт, нужно ли обрезать страницу до 50000 символов по длине, по умолчанию false
    * @param {boolean} noScript Указывакт, нужно ли удалять скрипты из кода
    * @return Исходный код страницы
    * @customfunction
    */
    function getHTML(URL,isCut,noScript) {
      if ((URL === undefined)||(URL == "")) { return "#ОШИБКА Пустой URL";};
      if (isCut === undefined) {var isCut=true;};
      if (noScript === undefined) {var noScript=true;};
      if (URL.map){     //Если задан диапазон
        return URL.map(getHTML);
      }else{
        try {
          var payload = {
            'rand':(new Date()).getTime()
          };
          var headers={
            'Connection': 'keep-alive',
            'Cache-Control': 'max-age=0',
            'Upgrade-Insecure-Requests': 1,
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'Accept-Encoding': 'gzip, deflate, br',
            'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7'
          };
          var options = {
            'method' : 'get',
            'headers' : headers,
            'payload': payload
          };
          
          var response = UrlFetchApp.fetch(URL,options);
          var charset=response.getAllHeaders["charset"];
          //var responseText=response.getContentText(charset?charset:"windows-1251");
          var responseText=response.getContentText(charset?charset:"UTF-8");
          if (noScript){ 
            responseText=responseText.replace(/<script[^>]*>(?:(?!<\/script>)[^])*<\/script>/gmi,"");
            responseText=responseText.replace(/<!--.*?-->/gmi,"");
            responseText=responseText.replace(/<link.*?\/>/gmi,"");
            responseText=responseText.replace(/<meta.*?\/>/gmi,"");
            responseText=responseText.replace(/[\n\r\t]/gmi,"");
            
          };
          if (isCut&&(responseText.length>50000)){return responseText.substring(0,50000);}else{return responseText;};
        } catch (err) {
          //return JSON.stringify(err);
          return "#ОШИБКА "+err.message;
        };
      };
    };
    Ответ написан
    Комментировать
  • Как сделать автоматическое заполнение даты при изменении ячейки «статуса»?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Судя по скрину - нужен отлов события отпрвки формы. Делаете функцию onFormSubmit(event), назначаете триггер на отправку формы, внутри функции проверяете данные и правите нужные ячейки. Только непонятно, зачем править данные ответов с формы.
    Если данные всё-таки меняются вручную, то нужно делать то же самое, только используя триггер onEdit(event).
    Ответ написан
  • Как правильно парсить цены на предметы Steam в Google Sheets при помощи Google Apps Script?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    1) Если есть массив url, то лучшим вариантом будет использование fetchAll
    2) Если получилась ошибка - можно подождать 2**i секунд и повторить запрос. i - номер итерации.
    Ответ написан
  • Как сделать чередование цветов строк через макрос для непустых строк дипазона?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    spreadsheet.getRange('A5:M35') >> spreadsheet.getDataRange()
    Ответ написан
    Комментировать
  • Как удалять строчки по истечению времени?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    const currentTime = new Date().getTime();
    содержит и дату и время.
    20:59 скорее всего - только время.
    Чтобы оставить только время, можно сделать как-то так:
    new Date() - new Date().setHours(0,0,0,0)
    Ответ написан
    Комментировать
  • В зависимости от значения выпадающего списка ячейки ставит определенную цифру в соседнюю ячейку?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Не получится формулами сортировать на месте, да и такой вариант - перемешивание статических и динамических данных, что в корне неверно. Это можно сделать скриптом - организовать onEdit() и там проверять значение и пересортировывать весь лист. Но я бы не советовал такой вариант - onEdit может пропускать вызовы, если вызывать его часто. Да и медленно это будет всё, если данных много. Но пробуйте, может быть то что получится и устроит вас.
    Заготовка для onEdit:
    const whiteListSheetNames = [`Лист1`,`Лист2`];
    const whiteListRangeNames = [`H1`, `H2`];
    
    function onEditTrigger(e) {    // установить триггер на "Редактирование". Простой onEdit имеет меньше прав
        let sheet = e.source.getActiveSheet();
        let address = e.range.getA1Notation().toUpperCase();
        let row = e.range.getRow();
        let col = e.range.getColumn();
        let newValue =  e.value;
        let oldValue =  e.oldValue;
    
        if ((whiteListSheetNames.includes(sheet.getName())) && (whiteListRangeNames.includes(address))) { // Проверка по вкусу
    	// сортировка
    	};
    };
    Ответ написан
    Комментировать
  • Как выполнить все формулы заново в google sheets разом?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Формулы пересчитываются автоматически. Единственное что отключено по умолчанию - итеративные вычисления. Но использования их где-то вживую ни разу не видел.
    На уровне скрипта можно сделать
    SpreadsheetApp.flush()
    Ответ написан
    Комментировать
  • Оптимизация кода для Google Sheets (Google App Scripts) с автозаполнением даты?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Возможно, что там и не ноль. Введите константу, число меньше которой можно считать нулём, и используйте:
    //...
    const epsilon = .01;
    if((selectedCell.getColumn() == COLUMNTOCHECK) && (+e.value <= epsilon)) {
    //...
    Ответ написан
  • Какую команду вставить в скрипт для всех гуглтаблиц объединенных с гуглдок?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Всё захардкоженое в функции - вынесите в параметры, и функция автоматически станет универсальной. Останется писать обёртки для неё под каждый конкретный случай, или просто вызывать с нужными параметрами и данными.
    Ответ написан
    Комментировать
  • Как сделать автоматическую сортировку в гугл-таблицах?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    editedCell!=cell2 - бессмысленное условие. Сравниваете значение(...getValue()) с 2D массивом (...getValues())
    Пробуйте запустить с отладчиком и посмотреть на ошибки выполнения, на текущие значения и т.п.
    Ответ написан
    Комментировать
  • Как изменить скрипт?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    function _onEdit(e) {    
        let sheet = e.source.getActiveSheet();
        let address = e.range.getA1Notation().toUpperCase();
        let row = e.range.getRow();
        let col = e.range.getColumn();
        let newValue =  e.value;
        let oldValue =  e.oldValue;
    
        if ((["1"].includes(sheet.getName())) && (col===26) && (newValue==="Обработано")) {
            sheet.getRange(row, 26-2).setValue(new Date());
        };
    };
    Ответ написан
    Комментировать
  • Как сделать так, чтобы разделы Гугл форм отправляли в разные каналы дискорда вебхук сообщения?

    ProgrammerForever
    @ProgrammerForever
    Учитель, автоэлектрик, программист, музыкант
    let foundItem = discordPayload.embeds[0].fields.find(x=>x.name==="Что требуется оформить");
    if(foundItem && foundItem.value==="Отчет по контракту"){
    // 1 вариант
    };
    Ответ написан
  • Как удалить строки по текущей дате?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Меняйте условие тут:
    if (row[2] == 0 || row[2] == '') {
    на что-то вроде:
    const dateFormat = "yyyy-MM-dd";
    let now = Utilities.formatDate(new Date(), "UTC", dateFormat);
    // ...
    if (now===Utilities.formatDate(row[2], "UTC", dateFormat)) {
    Ответ написан