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

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    The parameters (number,number,number,null) don't match the method signature for SpreadsheetApp.Sheet.getRange.


    Означает, что вы в метод getRange передаете аргументы несвойственные его сигнатуре. Обратите внимание, что четвертый аргумент null, а это значит, что ваш вызов arr[0].length возвращает null. Что в свою очередь означает, что ваш массив arr содержит первый элемент, у которго отсутствует свойство length. Что очевидно, т.к. obj - не массив, см. тут obj[sh.getName()] = sh.getDataRange().getValues();

    Дальше мне было лень

    Давайте починим код. Ошибка возникает из-за того, что вы пытаетесь использовать метод `getRange(1, 1, arr.length, arr[0].length)` с некорректными параметрами. Кроме того, есть несколько других проблем в коде, которые нужно исправить:

    1. Пустые URL-адреса: Вы фильтруете массив ссылок, но не проверяете, действительно ли они являются действительными URL-адресами.
    2. Структура данных: В вашем коде arr становится объектом, а не массивом, и это вызывает проблемы при использовании setValues.
    3. Логика записи данных: Метод setValues ожидает двумерный массив, но ваша структура данных не соответствует этому требованию.


    Вот исправленная версия кода:

    function sv21() {
      // Открываем основную таблицу
      var ss1 = SpreadsheetApp.openByUrl('URL_ОСНОВНОЙ_ТАБЛИЦЫ'); // Замените на реальный URL
      var sheet1 = ss1.getSheetByName('ссылки');
      
      // Получаем ссылки из столбца B
      var urls = sheet1.getRange('B3:B').getValues().flat(); // Берем значения из столбца B
      urls = urls.filter(function (url) { // Удаляем пустые строки
        return url !== '' && url.startsWith('https://'); // Проверяем, что это действительно URL
      });
    
      var allData = []; // Здесь будем хранить все данные
    
      // Проходимся по каждой ссылке
      for (var i = 0; i < urls.length; i++) {
        try {
          var ss = SpreadsheetApp.openByUrl(urls[i]); // Открываем таблицу по URL
          ss.getSheets().forEach(function (sh) {
            var data = sh.getDataRange().getValues(); // Получаем данные с листа
            allData = allData.concat(data); // Добавляем данные в общий массив
          });
        } catch (e) {
          Logger.log('Ошибка при обработке URL: ' + urls[i] + '. Подробности: ' + e.message);
        }
      }
    
      // Если есть данные для записи
      if (allData.length > 0) {
        // Открываем целевую таблицу и записываем данные
        var targetSheet = SpreadsheetApp.openByUrl('URL_ЦЕЛЕВОЙ_ТАБЛИЦЫ') // Замените на реальный URL
          .getSheetByName('все расчеты');
        
        // Очищаем предыдущие данные
        targetSheet.clearContents();
        
        // Записываем новые данные
        targetSheet.getRange(1, 1, allData.length, allData[0].length).setValues(allData);
      } else {
        Logger.log('Нет данных для записи.');
      }
    }


    Что было исправлено:
    1. Обработка URL-адресов:
    - Добавлена проверка на то, что ссылка начинается с https://.
    - Используется метод `.flat()` для преобразования многомерного массива в одномерный.

    2. Сбор данных:
    - Все данные собираются в массив allData, который затем используется для записи в целевую таблицу.

    3. Запись данных:
    - Перед записью данных очищается содержимое целевого листа (clearContents).
    - Проверяется, что массив allData не пустой, прежде чем выполнять запись.

    4. Обработка ошибок:
    - Добавлен блок try-catch для обработки ошибок при открытии таблицы по URL.

    5. Логирование:
    - Логируется информация об ошибках, чтобы легче было находить проблемы.

    Как использовать:

    1. Замените 'URL_ОСНОВНОЙ_ТАБЛИЦЫ' и 'URL_ЦЕЛЕВОЙ_ТАБЛИЦЫ' на реальные URL-адреса ваших таблиц.
    2. Убедитесь, что у скрипта есть необходимые права доступа к таблицам.


    Теперь код должен работать корректно!
    Ответ написан
    2 комментария
  • Как создать копию листа через макрос в Google, и перенести туда только значения?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Все очень просто, даже Жпт справится:

    1. Копируете лист
    2. Очищаете только от данных
    3. Берете данные из оригинального листа
    4. Вставляете в копию
    5. Переименовываете копию, как надо
    6. Готово
    Ответ написан
    Комментировать
  • Как настроить логирование действий других пользователей?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    К сожалению, у Session.getActiveUser().getEmail() есть серьезные ограничения

    getEmail() Получает адрес электронной почты пользователя, если он доступен. Если политики безопасности не разрешают доступ к адресу электронной почты пользователя, этот метод возвращает пустую строку. Обстоятельства, при которых адрес электронной почты доступен, различаются: например, адрес электронной почты пользователя недоступен ни в одном контексте, который позволяет скрипту запускаться без авторизации этого пользователя, например, простой триггер onOpen(e) или onEdit(e), пользовательские функции в Google Таблицах или веб-приложение, развернутое для "выполнения от моего имени" (то есть авторизованное разработчиком вместо пользователя). Однако эти ограничения, как правило, не применяются, если разработчик сам запускает скрипт или принадлежит к тому же домену Google Workspace, что и пользователь.

    https://developers.google.com/apps-script/referenc...

    Т.о. то, что вы запускаете, может отработать только в Googlw Workspace
    Ответ написан
  • Как создать выпадающий список через DataValidationBuilder с диапазоном данных в относительных ссылках?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Програмно этого сделать нельзя. Покрайней мере на данный момент.
    Ответ написан
    Комментировать
  • Как получить ответы на свою форму для формирования статистики?

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

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Apps Script поддерживает только HTTP и JDBC, что логично. Вы должны создать сервис-прослойку, который будет взаимодействовать со Скриптами по HTTP.
    Ответ написан
    Комментировать
  • Как сделать текст жирным при конкатенации строк?

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

    Вот рабочий код на Google Apps Script

    /* exported combineCells */
    /**
     * Combines strings from two cells in a row into a single cell.
     * The combined string is bolded if the first cell is not empty.
     */
    function combineCells() {
      const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
      const sheet = spreadsheet.getSheetByName('Соединение строк построчно');
      const dataRange = sheet.getDataRange();
      const values = dataRange.getValues();
    
      const newValues = values.map((row) => {
        const cellA = row[0];
        const cellB = row[1];
    
        let formattedText = null;
        if (String(cellA).length > 0) {
          formattedText = SpreadsheetApp.newRichTextValue()
            .setText(String(cellA) + ' ' + String(cellB))
            .setTextStyle(0, String(cellA).length, SpreadsheetApp.newTextStyle().setBold(true).build());
        } else {
          formattedText = SpreadsheetApp.newRichTextValue().setText(String(cellB));
        }
    
        return [formattedText?.build()];
      });
    
      const targetRange = dataRange.offset(0, 2, dataRange.getNumRows(), 1);
      targetRange.setRichTextValues(newValues);
    }


    Пример в Таблице https://docs.google.com/spreadsheets/d/1qdh4mQLiEL...
    Как запускать Скрипты https://googlesheets.ru/script-editor-guide/
    Ответ написан
    Комментировать
  • Почему после переноса на корпоратиный google-disk перестали работать развертывания apps scripts?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Это проблема развертывания приложения. Обратитесь к поддержке.
    Ответ написан
    Комментировать
  • Как настроить проставление даты при изменении соседней ячейки в Google Sheets?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Скрипт для вставки даты и времени при редактировании ячейки в Google Таблицах

    Задача:
    Иногда возникает необходимость автоматически записывать дату и время внесения изменений в определенные ячейки. Это может быть полезно для отслеживания активности, ведения журналов изменений и обеспечения контроля над обновлениями данных.

    Когда это полезно:
    1. Отслеживание изменений: Ведение журнала изменений данных для аудита или анализа.
    2. Контроль сроков выполнения: Отслеживание времени выполнения задач или обновлений информации.
    3. Повышение прозрачности: Учет времени и даты изменений для повышения прозрачности и ответственности сотрудников.

    Решение:
    Для автоматического добавления даты и времени при редактировании ячеек используем скрипт Google Apps Script.

    /**
     * Триггер события EDIT
     *
     * @param {GoogleAppsScript.Events.SheetsOnEdit} e
     */
    function onEdit(e){
      // Определяем имя листа, на котором обрабатываем событие редактирования ячейки
      const watchingSheet = 'Добавить дату в строке при изменении ячейки';
      // Определяем индекс столбца в котором обрабатываем событие редактирования ячейки 
      const watchingColIndex = 6;
      // Определяем индекс столбца в который будем записывать дату/время 
      const targetColIndex = 8;
      // Из объекта события получаем измененный диапазон и из диапазона лист, на котором он расположен
      const sheet = e.range.getSheet();
    
      // Проверяем, что имя листа, на котором произошло событие соответствует указанному в переменной `targetSheetName`
      if (sheet.getName() !== watchingSheet) {
        // И, если событие произошло на другом листе, то прекращаем выполнение функции
        return;
      }
    
      // Определяем индекс столбца в котором произошло событие
      const column = e.range.getColumn();
      // Проверяем, в нужном ли столбце произошло событие
      // и соответствует ли новое значение нужному нам
      // проверку на значение можно убрать
    
      // для этого нужно удалить этот фрагмент: "&& e.value === 'Готово'"
      if (column == watchingColIndex && e.value === 'Готово') {
        // Устанавливаем дату и время в ячейку на пересечении строки, в которой было изменение
        // и столбца, указанного в переменной `targetColIndex` 
        e.source.getActiveSheet().getRange(e.range.getRow(), targetColIndex).setValue(new Date());
      }
    }


    Пример тут https://docs.google.com/spreadsheets/d/1IHDKe-5Tzv...

    Оригинал тут https://t.me/GoogleSheets_ru/213
    Ответ написан
    Комментировать
  • Как автоматически переносить данные из одного листа на другой ячейки определенного цвета?

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

    1. Необходимо создать пользовательскую функцию
    2. Функция смотрит, на каком листе она находится
    3. На основании параметров цветов функция вытягивает нужные данные из источника


    Пожалуйста, не нарушайте правила! Заказывайте работы на Фрилансим
    Ответ написан
    Комментировать
  • Как осуществить скрапинг данных steam баланса и суммы инвентаря?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Используйте для этого доступные интерфейсы Steam.
    Ответ написан
    Комментировать
  • Как извлечь ссылку на файл из чипа?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Экспортируйте файл в XLSX, распакуйте его и распарсите. Получите ссылки на файлы. Не очень удобно, но возможно.
    Ответ написан
    2 комментария
  • Как свести учет рабочего времени, если данные из Ардуино?

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

    =MAXIFS(
      INDIRECT("Sheet1!$B$2:$B"),
      INDIRECT("Sheet1!$C$2:$C"), "=863705125",
      INDIRECT("Sheet1!$A$2:$A"), "=7/1/2024"
    )
    Ответ написан
    1 комментарий
  • Что означает ошибка TypeError: Cannot read properties of undefined (reading 'match')?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Эта ошибка означает то, что переменная, для которой вы хотите применить метод match является undefined

    На самом деле код вполне рабочий

    667e8ce901b8d123359329.gif

    Пример в Таблице https://docs.google.com/spreadsheets/d/11zQ949jIwe...

    Код в проекте под именем того же листа.
    Ответ написан
    Комментировать
  • Как копировать много строк?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    ss2.getRange(lr + 1, 1, values.length, values[0].length).setValues(values);


    Неужели так сложно было вставить код?
    Ответ написан
    6 комментариев
  • Как получить адрес нужной мне ячейки в буквенном формате?

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

    Способ первый, это вычисление имени колонки по номеру колонки

    function base26ABCfrom10_(number) {
      let num = number;
      let sfx = '';
      while (num > 0) {
        const cd = (num - 1) % 26;
        sfx = String.fromCharCode(65 + cd) + sfx;
        num = Math.floor((num - cd) / 26);
      }
      return sfx;
    }


    Второй способ, это получение координат диапазона. Этот метод как раз может быть с тормозами

    6666fe9535aa8106659507.png

    Пример в Таблице https://docs.google.com/spreadsheets/d/11zQ949jIwe...
    Ответ написан
    2 комментария
  • Как сделать Минутомер?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Это задание, а не вопрос. Задания отправляют сюда https://freelance.habr.com/

    Ваша задача решается с использованием триггера на редактирование и правильной расстановкой условий.
    Ответ написан
    1 комментарий
  • Можно ли изменить значение или формат в зависимости от того, кто заполнил ячейку?

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

    Для Скриптов в Google Workspace среде это возможно без ограничений.
    Ответ написан
    Комментировать
  • Сокрытие строки при нуле в какой-либо ее ячейке?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Это возможно сделать, используя Google Apps Script или другую программу, эксплуатирующую Google Sheets API.
    Ответ написан
    Комментировать
  • Как пропустить ошибку, если при создании листа копированием такой лист уже есть?

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

    Добавить со случайным именем:

    const nameTo = ss.getSheetByName(name) ? `${name}_${new Date().getTime()}` :  name;
    sheetTemp.setName(nameTo);


    Удалить перед вставкой нового:

    if(ss.getSheetByName(name)) {
      ss.deleteSheet(name);
    }


    Просто пропустить, ничего не делать:

    if(!ss.getSheetByName(name)) {
      sheetTemp.setName(name);
    }
    Ответ написан
    Комментировать