Ответы пользователя по тегу Google Sheets
  • Как сделать так, чтобы данные из ячейки падали в сумму?

    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();//Пользователь(работает только при вручную назначенном триггере)
      
      //Делаем что-то
    };

    Ответ написан
    Комментировать
  • Как с помощью 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 Куратор тега Excel
    Учитель, автоэлектрик, программист, музыкант
    =ДВССЫЛ("'БД'!B"&ПОИСКПОЗ(A2;'БД'!A:A;0))
    Но, скорее всего, можно обойтись обычным ВПР()
    Ответ написан
    Комментировать
  • Как сделать автоматическое заполнение даты при изменении ячейки «статуса»?

    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)
    Ответ написан
    Комментировать
  • Возможно ли извлечь данные через =IMPORTXML с Wildberries?

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

    /**
    * Открывает 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;
        };
      };
    };


    Или в IMPORTXML поставить * в запросе
    Ответ написан
    Комментировать
  • В зависимости от значения выпадающего списка ячейки ставит определенную цифру в соседнюю ячейку?

    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))) { // Проверка по вкусу
    	// сортировка
    	};
    };
    Ответ написан
    Комментировать
  • Как сделать, чтобы флажок проставлялся от логического условия, данные для которого получены от формулы?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    А что тут делается? Тут всегда будет FALSE
    =AND(B30>=5;TRUE;C30>=5;TRUE;D30>=5;TRUE;E30>=5;TRUE;F30>=5;TRUE;FALSE)

    Предполагаю что тут имелось ввиду
    =AND(B30>=5;C30>=5;D30>=5;E30>=5;F30>=5)
    Думаю что проблема в "0", это строка, а должно быть просто 0
    Ответ написан
  • Как выполнить все формулы заново в google sheets разом?

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

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Ну, например, столбец J:
    2 строка = A2 = R2C1
    3 строка = B2 = R2C2
    4 строка = C2 = R2C3
    5 строка = A2 = R3C1
    6 строка = B2 = R3C2
    7 строка = C2 = R3C3

    Итоговая формула такая:
    =ДВССЫЛ("R"&(ОКРУГЛВНИЗ((СТРОКА()-2)/3)+2)&"C"&(ОСТАТ(СТРОКА()-2;3)+1);0)

    Или можно так, чуть нагляднее:
    =LAMBDA(r;c;ДВССЫЛ("R"&r&"C"&c;0))
    (
    	ОКРУГЛВНИЗ((СТРОКА()-2)/3)+2
    	;ОСТАТ(СТРОКА()-2;3)+1
    )
    Ответ написан
  • Как сформулировать условие (написать формулу), проверяющее день между датами в Гугл Таблицах?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Закрашивает если Дата<=ДатаНачала или Дата>=ДатаНачала
    =(IF($G1:$G<=ДатаНачала;1;0)+IF($G1:$G>=ДатаОкончания;1;0))>0

    Закрашивает если Дата>=ДатаНачала и Дата<=ДатаНачала
    =(IF($G1:$G>=ДатаНачала;1;0)*IF($G1:$G<=ДатаОкончания;1;0))=1

    ,где ДатаНачала и ДатаОкончания как-то задаются.
    • Значением в формуле через ДАТА(), например ДАТА(2022;1;1)
    • Ссылками на 2 фиксированные ячейки, например $E$1
    • Ссылками на данные в той же строке, например ДВССЫЛ("RC5";0)
    Ответ написан
  • Как сделать выпадающий список для всех пользователей, а не только для редакторов?

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

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    =ЕЧИСЛО(ПОИСКПОЗ(ДВССЫЛ("RC";0);ДВССЫЛ("R1C:R[-1]C";0);0))
    Ответ написан
    6 комментариев
  • Оптимизация кода для Google Sheets (Google App Scripts) с автозаполнением даты?

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

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Я так понял, вам нужно сделать PIVOT наоборот. Когда у меня был такой кейс, сделал себе по-быстрому такую функцию:
    /**
     * Разворачивает данные в плоскую таблицу
     *
     * @author Boew Grigory (ff.nspu@gmail.com)
     * @param {Array} data Исходные данные
     * @param {Boolean} [isRemoveNull=true] Удалять ли из выдачи пустые, нулевые и ложные значения
     * @customfunction
    */
    function unPivot(data, isRemoveNull=true) {
      let colHeaders = [...(data[0])].slice(1);
      let rowHeaders = data.slice(1).map(row=>row[0]);
    
      let outData = [];
      rowHeaders.forEach((rowHeader,ri)=>{
        colHeaders.forEach((colHeader,ci)=>{
          let value = data[1+ri][1+ci];
          if(!isRemoveNull || value){
            outData.push([rowHeader, colHeader, value]);
          };
        });
      });
    
      if(!outData.length){
        return [[]];
      };
      return outData;
    };

    А в полученном массиве можно найти всё что угодно через ВПР.
    Ответ написан
  • Смещение данных при автоматической сборке общего диапазона из нескольких с использованием query. Как исправить?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    Из этих трех таблиц, собирается одна, ... и вручную проставляются фактические даты и тип счета.

    Не мешайте динамичские и статичные данные, это плохая практика.
    Или сделайте ID для каждой строки, отдельную таблицу сопоставлений ID и новых данных, и сборку всего в кучу в третьей таблице. Но это - не решение проблемы, а разбиение больших граблей на несколько мелких. Лучше изначально сделать всё по-другому, чтобы не быть китайским коммунистом, который содаёт себе проблем, а потом их героически решает.
    Если собираете что-то ежедневно с нескольких пользователей - сделайте форму.
    Если с нескольких таблиц (условно, по 100 строк в день), то делайте ID для каждой строки, хотя это не решение, как я писал выше
    Ответ написан
    Комментировать
  • Как организовать поиск по массиву по нескольким условиям?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    =FILTER(C:C;A:A;(IF(B:B=D1;1;0)+IF(B:B=E1;1;0))>0)
    Как вывести значение ячеек столбца "C",
    FILTER(C:C;
    если в СТОЛБЦЕ "B" встречаются значения из ячейки D1 ИЛИ E1,
    (IF(B:B=D1;1;0)+IF(B:B=E1;1;0))>0
    при этом в строке столбца А =TRUE
    =FILTER(C:C;A:A
    Ответ написан
    Комментировать
  • Как получить номера строки и столбца Google таблицы выделенной в данный момент ячейки?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    function onSelectionChange(e) {
      SpreadsheetApp
        .getActiveSheet()
          .getRange("A1")
          .setValue(e.range.getA1Notation());
    }
    Ответ написан
    Комментировать