• Как сделать месяц прописью в Гугл документе?

    @bbc1989
    =VLOOKUP(MONTH(TODAY());{1\"январь";2\"февраль";3\"март";4\"апрель";5\"май";6\"июнь";7\"июль";8\"август";9\"сентябрь";10\"октябрь";11\"ноябрь";12\"декабрь"};2;)
    Ответ написан
    Комментировать
  • Почему условное форматирование не подсвечивает весь выбранный диапазон?

    oshliaer
    @oshliaer Куратор тега Google Sheets
    Google Products Expert
    Сравните

    6658bd7ff35ac723867682.png

    и

    6658be06a2305396176869.png

    Если вы хотите "обойти" диапазон форматирования по строкам, вы должны поставить знак $ перед цифрой в адресе, а если "обойти" по колонкам, то знак должен стоять перед буквой.

    Такие правила.
    Ответ написан
    Комментировать
  • Какую информацию Portable приложения в Windows получают о системе?

    xez
    @xez Куратор тега Железо
    TL Junior Roo
    Что portable версия программы может узнать о системе?

    Все то же самое, что и «не порабл».

    Разница в этих вариантах установки, скорее в том, что «обычная» устанавливает приложение в системные папки и, возможно, использует установленные библиотеки, а «портабл» - полностью самодостаточна и поэтому без разницы куда ее устанавливать.
    Ответ написан
    Комментировать
  • Какую информацию Portable приложения в Windows получают о системе?

    @Everything_is_bad
    Что portable версия программы может узнать о системе?
    ту же самую что и не "portable" версия.
    Ответ написан
    Комментировать
  • Как создать формулу для фильтра?

    Geleoss
    @Geleoss
    Любитель таблиц
    Вопрос не такой легкий, как может показаться на первый взгляд.
    И причина этого в том, что фильтр при его создании берёт сразу значение из ячейки. И даже если значение в ячейке изменится - фильтр автоматически ничего не обновит. Но выход есть - использовать скрипт, который пересоздаёт фильтр когда будет изменяться (редактироваться) значение в ячейке.
    ПРИМЕР
    66530358a4b51975443760.png
    Формула для фильтра: =OR($F$1="";A2=$F$1)
    A2=$F$1 - основа фильтра
    OR($F$1=""; ..) - сделано для того, чтобы фильтр можно "отключить" просто удалив значение из ячейки F1.

    А теперь изюминка - скрипт.
    function onEdit(e) {
      sheet = e.range.getSheet();
      if (sheet.getName() == "Здесь должно быть имя страницы" && e.range.getA1Notation() == "F1") {
        let filter = sheet.getFilter();
        let filterCriteria = filter.getColumnFilterCriteria(1).copy().build();
        filter.setColumnFilterCriteria(1, filterCriteria);
      }
    }


    PS. При необходимости можете создать триггер onEdit, а функицию переименовать.
    Ответ написан
    1 комментарий
  • Как в Google Sheets через query вывести все столбцы, кроме тех в строках которых нет значений?

    Geleoss
    @Geleoss
    Любитель таблиц
    6652ed944b461985066486.png
    Вывод всех полностью заполненых строк из диапазона с помощью QUERY
    =ArrayFormula(QUERY(A1:E4;"where Col1 = 'Иран' and "&
    TEXTJOIN(" and ";;"Col"&
    SEQUENCE(1;COLUMNS(A1:E4))&" is not null")))

    Но вообще говоря, не QUERY единым таблицы полны. Есть, например, Filter:
    =FILTER(A1:E4; A1:A4="Иран"; byrow(A1:E4; LAMBDA(row; AND(row<>""))))

    ПРИМЕР.
    Ответ написан
    Комментировать
  • Какая формула подходит в правилах условного форматирования?

    Geleoss
    @Geleoss
    Любитель таблиц
    ПРИМЕР
    Правило УФ для "заголовка" A2:B2, если есть строки совпадающие с ним:
    =SUMPRODUCT($A2&$B2=$A3:A23&$B3:B23)
    66530c843efbe514215219.png
    И дополнительно, пример одного из правил УФ для выделения строк, которые совпадают с заголовком:
    =$A$2&$B$2=$A3&$B3
    6652d8064d34a454600985.png
    Ответ написан
    3 комментария
  • Как автоматически выполнять скрипт каждые 5 минут на Apps Script?

    Fzero0
    @Fzero0
    Вечный студент
    Привет, тригерры можно создать двумя способами или в ручную
    или программно
    function myFunction() {
      Logger.log('1')
    }
    
    function createTimeDrivenTriggers() {
      ScriptApp.newTrigger('myFunction')
            .timeBased()
            .everyMinutes(1)
            .create();
    }

    6202b62c49f96736861078.png
    Одна проблема что у них есть ограничения. Общая продолжительность работы функций, запущенных триггером, не может превышать одного часа в день: это один из лимитов системы Apps Scripts. Если вызывать каждые 5 минут, получается 288 запусков в день, т.е. 12 секунд на каждый (в среднем). Предполагаю, что Ваш скрипт не укладывается в это время. Надо или оптимизировать, или запускать не так часто.
    Ответ написан
    1 комментарий
  • Как в apps script при вставке через setvalues Не перезаписывать данные ячейки, если в массиве значение пусто?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Apps Script
    Учитель, автоэлектрик, программист, музыкант
    1) Получить значения
    2) Заменить пустые значения в заменяемых данных на старые значения
    3) Записать значения
    oldValues = range.getValues();
    arr = arr.map((row,ri)=>row.map((val, ci)=>val===undefined?oldValues[ri][ci]:val));
    range.setValues(arr);
    Ответ написан
    Комментировать
  • Как создать таблицу, чтобы была взаимосвязь цена—кол-во—стоимость?

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

    Класс

    class Recalculator {
      constructor(calcs) {
        this.calcs = calcs;
      }
    
      calc(params, fix) {
        if (params.filter((p) => p === '' || isNaN(p)).length > 1)
          return params.map((p) => (isNaN(p) || p === '' ? '' : Number(p)));
        const index = params.map((p) => (isNaN(p) || p === '' ? '' : Number(p))).findIndex((p) => p === '');
        if (index === -1) return params.map((v, i) => (i === fix ? v : ''));
        const res = this.calcs[index](params);
        const out = [...params];
        out[index] = Number.isInteger(res) ? res : Number(res).toFixed(2);
        return out;
      }
    }


    Применение
    const recalc = new Recalculator([([_, b, c]) => c - b, ([a, _, c]) => c - a, ([a, b, _]) => a + b]);
        const range = sheet.getRange('B3:F3');
        const [a, _, b, __, c] = range.getValues()[0];
        const params = [a, b, c];
    
        const [a1, b1, c1] = recalc.calc(params, fix);
        range.setValues([[a1, _, b1, __, c1]]);


    64b19aeb57f0b767372525.gif

    Пример в Таблице https://docs.google.com/spreadsheets/d/1KTNtoZqQBp...
    Ответ написан
    Комментировать
  • Как в гугл таблицах сделать пример типа 2+3=5, что бы при изменении любого из 3 значений остальные подстраивались?

    BasiC2k
    @BasiC2k
    .NET developer (open to job offers)
    Скриптом.
    Скрипт отслеживает через onEdit изменение значения в 2 или 3 ячейке.
    Если данные изменены в 2 ячейке, они берутся для расчёта и результат вставляется в 3 ячейку.
    Если данные изменены в 3 ячейке, они берутся для расчёта и результат вставляется в 2 ячейку.
    В обоих случаях, для расчёта также используются значение из 1 ячейки.
    Ответ написан
    1 комментарий
  • Ajax в OpenCart 3 — как?

    ThunderCat
    @ThunderCat Куратор тега PHP
    {PHP, MySql, HTML, JS, CSS} developer
    $('#btn-account-edit-popup').on('click', function(e) {
    e.preventDefault();
    ...

    И по уму обработчик вешается на субмит формы, а не на клик кнопки. Почему - подумайте самостоятельно.
    Ответ написан
    1 комментарий
  • Как запустить триггер при редактировании определенной ячейки, определенного листа?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Вероятно, вот так должно сработать

    /**
     * @param {GoogleAppsScript.Events.SheetsOnEdit} e
     */
    function onEdit(e) {
      if (
        e.range.getSheet().getName() === 'Sheet1' &&
        e.range.getA1Notation() === 'M2'
      )
        CopyList();
    }
    
    /**
     *
     */
    function CopyList() {
      var sss = SpreadsheetApp.openById('ID-ТАБЛИЦЫ1');
      var ss = sss.getSheetByName('Sheet1');
    
      var from = ss;
      var fromValues = from.getDataRange().getValues();
      var fromData = fromValues;
    
      var tss = SpreadsheetApp.openById('ID-ТАБЛИЦЫ2');
      var ts = tss.getSheetByName('Sheet2');
    
      ts.getRange(
        ts.getLastRow() + 1,
        1,
        fromData.length,
        fromData[0].length
      ).setValues(fromData);
    }
    Ответ написан
    Комментировать
  • Как запустить onEdit из редактора или программным способом?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Насколько я понимаю, вы пробуете вызвать функцию onEdit из другой функции или из редактора.

    Разбор ошибки

    Ошибка
    TypeError: Cannot read property 'range' of undefined (строка 3, файл se)

    Означает, что в некотором файле se в 3й строке есть некоторая переменная со значением undefined, свойство range которой прочитать невозможно. Тут все очевидно - у undefined нет свойств.

    Если посмотреть на код, то становится ясно, что имя этой переменной e. И мы ее получаем в системную функцию onEdit. Это означает, что система сама передает контекст в эту функцию.

    ОК. Значит, чтобы протестировать эту функцию, нужно передать параметр самостоятельно.

    Например,

    /**
     * Тестирование триггера для события EDIT
     */
    function runOnEdit() {
      var source = SpreadsheetApp.getActive();
      var range = source.getRangeByName('Sheet!!B26');
      /**
       * @type {GoogleAppsScript.Events.SheetsOnEdit}
       */
      var e = {
        authMode: ScriptApp.AuthMode.LIMITED,
        oldValue: undefined, // ну или что хотите
        range: range,
        value: range.getValue(),
        source: source,
        triggerUid: 0,
        user: Session.getActiveUser(),
      };
    
      onEdit(e);
    }
    
    /**
     *
     * @param {GoogleAppsScript.Events.SheetsOnEdit} e
     */
    function onEdit(e) {
      // Работает простой триггер
    }


    Проверьте - этот код будет работать точно так же, как если бы пользователь внес изменения в Таблице.
    Ответ написан
    1 комментарий
  • Как добавить список имён в диапазоны ячеек, которые находятся в разных местах Таблицы?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Попробуйте вот это

    function run() {
      const book = SpreadsheetApp.getActive();
      const data = book.getSheetByName('dataBase').getRange('A:A').getValues();
      const main = book.getSheetByName('main');
      ['E9:E13', 'J9:J13', 'E23:E27', 'J23:J27'].forEach(addr => {
        console.log(addr);
        const range = main.getRange(addr);
        range.setValues(data.splice(0, range.getNumRows()));
      });
    }


    Важно, чтобы число строк басы всегда было больше или равно заполняемым диапазонам.

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

    633737ff92e3c161305303.png
    Ответ написан
    5 комментариев
  • Как подружить VS Code + Remote SSH + WSL?

    bingo347
    @bingo347
    Crazy on performance...
    Ваша проблема в том, то Вы абсолютно не понимаете как работает WSL. Давайте немного объясню.

    Начиная с WSL2 подсистема Linux крутится в полноценной виртуальной машине. И винда кстати тоже. Это работает следующим образом: когда Вы запускаете свой компьютер первой загружается на самом деле не винда, а гипервизор HyperV. Для пользователя происходит все прозрачно, так как HyperV настроен сразу запускать 2 виртуальные машины - с виндой и с линем. В машину с виндой HyperV сразу прокидывает все Ваши устройства (видеокарту, USB и прочее). Так же HyperV поднимает виртуальную сеть между этими двумя виртуалками. В машине с линем еще не Ваша Ubuntu, там легковесная ОС состоящая только из ядра и оркестратора LXC контейнерами (с ней кстати можно по взаимодействовать по сети, как это делает Docker Desktop например, ну или утилита wsl.exe). Ваша Ubuntu запускается в контейнере, так попросту быстрее ее запускать и останавливать, ибо ядро всегда висит в памяти. Опционально в линь монтируются папки (диски) из винды, делается это посредством патча ядра Linux от Microsoft. Обратный доступ предоставляется из винды посредством сетевого ресурса wsl$.
    Главное что тут стоит понять - винда и линь в WSL по сути работают на разных компах, пусть и виртуальных.

    Теперь ответьте на вопрос, на каком из этих компов работает Ваш VSCode?
    Правильный ответ на винде. А значит и взаимодействовать он будет с виндой. И искать ключи для подключения к ssh будет в домашней папке юзера в винде.

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

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Если вам не надо чтобы каждый человек одинаково часто работал с каждым другим, то подойдет обощение решения, предложенного в комментариях Alexandroppolus и Сергей Сергей.

    Допустим количество работ (N) и количество людей (M) взаимно просты.

    Тогда сгенерируйте M строчек беря людей подряд:
    1, 2, 3
    4, 5, 1
    2, 3, 4
    5, 1, 2
    3, 4, 5

    Тут каждый человек одинаковое количество раз (по одному разу) будет на каждой работе. И дни, когда он будет работать будут максимально равномерно распределены (минимальное расстояние и максимальное между соседними работами будут различаться максимум на 1 и равны floor(N/M) и ceil(N/M)). Это идеальное с точки зрения равенства расписание. Но у него минус - частоты пар работников будут не одинаковыми. 1 гораздо чаще будет работать с 2 и 5, чем с 3 и 4.

    Теперь, если N и M не взяимно просты. Пусть D = GCD(N,M) - наибольший общий делитель.

    Разбейте всех людей на D групп по N'=N/D человек. N' и M взяимно просты, поэтому можно применить алгоритм выше к каждой группе.

    Дальше эти D расписаний надо перемешать. Для максимальной равномерности - сначала взять все первые строки всех расписаний, потом все вторые, и т.д.

    На i-ом месте будет день i / N' из расписания i % N' (если индексация с 0).

    Так, например, решение для 2 работ и 6 людей:

    N' = 3. 2 группы.
    В первой:
    1 2
    3 1
    2 3

    Во второй:
    4 5
    6 4
    5 6

    В итоге:
    1 2
    4 5
    3 1
    6 4
    2 3
    5 6
    Ответ написан
    Комментировать
  • Как составить все возможные сочетания из элементов одного массива, но размер сочетания = N?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    const combinations = (arr, num) => {
      const result = [];
      const comb = (arr, n, idx, cur) => {
        for (let i = idx; i <= arr.length - n; i += 1) {
          cur.push(arr[i]);
          if (n === 1) {
            result.push([...cur]);
          } else {
            comb(arr, n - 1, i + 1, cur);
          }
          cur.pop();
        }
      };
      comb(arr, num, 0, []);
      return result;
    }
    console.log(combinations([1, 2, 3, 4], 3));
    // Array(4) [ (3) […], (3) […], (3) […], (3) […] ]
    ​//   0: Array(3) [ 1, 2, 3 ]
    //​   1: Array(3) [ 1, 2, 4 ]
    ​//   2: Array(3) [ 1, 3, 4 ]
    ​//   3: Array(3) [ 2, 3, 4 ]
    /​/   length: 4
    Ответ написан
    4 комментария
  • Как перемешать строки так, чтобы их значения повторялись не менее чем через 4 строки?

    ProgrammerForever
    @ProgrammerForever Куратор тега Google Sheets
    Учитель, автоэлектрик, программист, музыкант
    1) Отсортировать
    2) Взять в порядке 1-5-10...2-6-11...3-7-12...
    const a = [1,2,2,3,34,54,3,4,45,34,53,45,4,1,23,12,3,235,2,5,1,2,6,76,54,6,84,5,23,2,34,6,735];
    
      let outData = [];
      const n = 5; // Ширина блока
      for(let offset=0; offset<n; offset++){
        for(let i=offset; i<a.length; i+=n){
          outData.push(a[i]);
        };
      };
    
      Logger.log(JSON.stringify(outData));
    //Проверка на то, что все элементы исходного массива включены
      Logger.log(JSON.stringify(outData.sort()));
      Logger.log(JSON.stringify(a.sort()));
    Ответ написан
    2 комментария