Ответы пользователя по тегу Google Apps Script
  • Добавление данных в Google Forms из Google Sheets?

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

    Так же возможна разработка своего собственного скрипта.
    Ответ написан
    Комментировать
  • Как сделать сумму прописью в Таблицах?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Можно использовать аддон для Таблиц NUMBERTEXT

    5d9c015768e80721417047.png

    Число прописью в текущей локале

    =NUMBERTEXT(1) // one

    Число прописью в русской локале

    =NUMBERTEXT(1;"ru") // один

    Число прописью в украинской локале

    =NUMBERTEXT(1;"uk") // один

    Число в заданной валюте прописью в текущей локале

    =MONEYTEXT(1; "USD"; "uk") // Один долар США
    Ответ написан
  • Где проблема в скрипте?

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

    Вот этот Utilities.sleep(1000); как мертвому припарка.

    Если вы запускаете скрипт как пользовательскую формулу, то вам нужно делать последовательные вызовы

    5d9bad1a8c877535631892.png

    Пример принципа в Таблице
    Ответ написан
  • Как с помощью UrlFetchApp активировать doGet(e)?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Вам же написали:
    Script function not found: doPost


    Вероятно, это помтому, что вы отправляете не GET, а POST запрос. Как минимум GET не имеет никакого body и payload ему ни к чему.
    Ответ написан
    Комментировать
  • В чем проблема со скриптом импорта данных из гугл таблицы в гугл док?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    У моего линтера кукушку чуть не оторвало. Он даже подумал, что это не JS. Ваш код не валиден для интерпретатора Google Apps Script. Вот форматированный, но непроверенный код

    /* eslint-disable require-jsdoc */
    /* eslint-disable no-undef */
    
    function doAction() {
      var result = readBaseData('22-05-2019');
      // If found data for this date...
      if (result != null) {
        var doc = createNewDoc(' iskovoe ' + result[0][0]);
        fillTemplate(doc, result);
      }
    }
    // inDoc - its a empty template, inData - data for filling template
    function fillTemplate(inDoc, inData) {
      // Getting count of files in folder
      var NUM = DocsList.getFolderById(
        '1a3uCa9wRyOzio-C7FVacOykuLoxCqTs3'
      ).getFiles().length;
    
      // Replace masks (Don't work [NUM] or $NUM or something else)
      inDoc.replaceText(
        'x',
        'https://docs.google.com/spreadsheets/d//edit#gid=0...'
      );
      inDoc.replaceText(
        'x',
        'https://docs.google.com/spreadsheets/d//edit#gid=0...'
      );
      inDoc.replaceText(
        'x',
        'https://docs.google.com/spreadsheets/d//edit#gid=0...'
      );
      inDoc.replaceText(
        'x',
        'https://docs.google.com/spreadsheets/d//edit#gid=0...'
      );
    
      // get first table in document
      var table = curDoc.getTables()[0];
      for (i = 0; i < inData.length; i++) {
        var row = table.appendTableRow();
        row.appendTableCell(inData[i][1]);
        row.appendTableCell(inData[i][2]);
      }
      curDoc.saveAndClose();
    }
    function createNewDoc() {
      // Making copy of blank file
      var blankDoc = DocsList.getFileById(
        '19vYiThaKdgQ6eeiRg5nPewzP_Eab7nkLUwyt49jCC1Q'
      ).makeCopy(iskovoe);
      blankDoc.addToFolder(
        DocsList.getFolderById('1a3uCa9wRyOzio-C7FVacOykuLoxCqTs3')
      );
    
      // return working doc and table base
      return (curDoc = DocumentApp.openById(blankDoc.getId()));
    }
    // get range and sort only for day from parameter
    function readBaseData(inDate) {
      var ssDoc = SpreadsheetApp.openById(
        '1ZCNO6Iae2RwDdKAlQX6TF5mpp4xHHB4v1mXK233uJls'
      ).getActiveSheet();
    
      // get filled range
      var data = ssDoc.getDataRange().getValues();
    
      // create new array with data to inDate,
      // for start from 1 because first row is text column headers
      var filteredData = new Array([]);
      for (i = 1; i < data.length; i++) {
        data[i][0] = convertDate(data[i][0]);
        if (data[i][0] == inDate && data[i][3] == 1) {
          filteredData[i - 1] = data[i];
        }
      }
      return filteredData;
    }


    Что к чему и как - лучше описать в техническом задании и обратиться к специалисту.
    Ответ написан
    Комментировать
  • Google Apps Script как выбрать только гугл таблицы?

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

    var files = DriveApp.searchFiles('mimeType="application/vnd.google-apps.spreadsheet"');


    Про DriveUser. Это объект системы, поэтому вам необходимо воспользоваться одним из его методов, для получения информации. Например,

    ...
    file.getOwner().getEmail()
    ...
    Ответ написан
    3 комментария
  • Как в Google Script библиотеку заменить на веб-приложение?

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

    Вы должны изменить подход к решению задачи. Одним из самых удачных вариантов является использование веб-приложения как центральной программы. Но у нее есть свои ограничения, например, чтобы отправить алерт в какую-то Таблицу, придется попыхтеть. Но если пользователь нажимает на кнопку в самом веб-приложении, то вы можете выдавать алерт на его стороне.
    Ответ написан
    Комментировать
  • Как понять, что введенное значение является датой?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Вопрос больше к JavaScript, а не к Google Apps Script.

    Проверяйте наличие чего-либо в переменной, а потом проверьте, имеет ли эта переменная метод getTime.

    function isDate(value){
      return value && value.getTime;
    }


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

    function isDate(date){
      return date instanceof Date && !isNaN(date.valueOf());
    }


    Решение
    Пример с неопределенным результатом без вызова ошибки
    var birthday1 = ss1.getRange("D8").getValue();
    var birthday = isDate(birthday1) ?
      Utilities.formatDate(birthday1, "GMT+3", "dd-MM-yyyy") : 
      undefined;
    Ответ написан
    2 комментария
  • Удаление символов до определенного сочетания в ячейке таблицы Google Sheets/Excel?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Не получается скриптами, попробуйте для начала формулами. Например,

    =ARRAYFORMULA(REGEXEXTRACT(A2:A;".*?gclid=(.*)$"))

    5c6fcc3c98a59827080515.png

    Пример скрипта. Переписывает данные в диапазоне

    function run() {
      const sheet = SpreadsheetApp.getActiveSpreadsheet()
        .getSheetByName('Решение (скриптами)');
      const range = sheet.getRange('A:A');
      const values = range.getValues();
      const data = values.map(row => {
        const [undefined, value] = String(row[0]).split('gclid=');
        return [value ?? ''];
      });
      range.setValues(data);
    }


    Таблица с примерами https://docs.google.com/spreadsheets/d/1Nll6tQ-I9a...
    Ответ написан
    Комментировать
  • Google forms POST или api?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Единственный на данный момент "правильный" способ управления Формами - использование Google Apps Script. Для реализации API используйте специальный триггер `doGet`.

    У вас должно получиться что-то вроде этого

    function doGet(e){
      /* если `e` содержит параметр на отключение Формы */
      form.setAcceptingResponses(false);
      /* если `e` содержит параметр на разрешение Формы принимать ответы */
      form.setAcceptingResponses(true);
    }


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

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

    function main() {
      var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
        'данные'
      );
      var dataArray = dataSheet.getDataRange().getValues();
      var listSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(
        'список сайтов'
      );
      var listArray = listSheet.getDataRange().getValues();
      // Строим индекс
      var listIndex = listArray.map(function(r){
        return r[0];
      });
      for (var j = 1; j < dataArray.length; j++) {
        if(dataArray[j][0] === '') continue;
        var pos = listIndex.indexOf(dataArray[j][0]);
        if (pos >= 0) {
          // Обновляем
          listSheet.getRange(pos + 1, dataArray[j].length + 1).setValue(new Date());
        } else {
          // Добавляем
          listSheet.appendRow([].concat(dataArray[j], new Date()));
        }
      }
    }
    Ответ написан
    Комментировать
  • Google Apps Script для Google таблиц: как переименовать все листы в таблице скриптом?

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

    Решение

    SpreadsheetApp.openById('blah-blah')
      .getSheets()
      .forEach(function(sheet) {
        var name = sheet.getRange('J2').getValue();
        if (name)
          try {
            sheet.setName(name);
          } catch (error) {
            console.error('CATCHED', error);
          }
      });


    Как делают

    Основная идея заключается в том, чтобы перебрать все элементы массива, отсортировать лишнее, а с выбранными элементаи произвести действие. Функция userActionRenameSheets демонстрирует это.

    /* exported userActionRenameSheets */
    
    /**
     * Действие пользователя или триггера. Внешний вызов без параметров
     */
    function userActionRenameSheets() {
      var spreadsheet = SpreadsheetApp.openById('blah-blah');
    
      /** @type {filterSheets} */
      var filterSheets = function(sheet) {
        return true;
      };
    
      /** @type {renameRule} */
      var renameRule = function(sheet) {
        var name = sheet.getRange('J2').getValue();
        if (name)
          try {
            sheet.setName(name);
          } catch (error) {
            console.error('CATCHED', error);
          }
        return sheet;
      };
    
      var sheets = renameSheetsByCellValue_(spreadsheet, filterSheets, renameRule);
      // Делать что-нибудь дальше
    }
    
    /**
     * Переименовывает листы в Таблице согласно заданным правилам
     *
     * @param {GoogleAppsScript.Spreadsheet.Spreadsheet} spreadsheet Таблица,
     *         в которой производим переименование
     * @param {filterSheets} Фильтр листов на всякий случай, вдруг что-то надо да пропустить
     * @param {renameRule} Правило переименования, может возвращать что угодно
     * @param {any[]} Массив отфильрованных результатов функции renameRule
     */
    function renameSheetsByCellValue_(spreadsheet, filterSheets, renameRule) {
      var res;
      var sheets = spreadsheet.getSheets();
      if (filterSheets) res = sheets.filter(filterSheets) || sheets;
      if (renameRule) res = res.map(renameRule);
      return res;
    }
    
    /**
     * Фильтр листов
     * @callback filterSheets
     * @param {GoogleAppsScript.Spreadsheet.Sheet} sheet Текущий лист
     * @param {number} index Текущий индекс массива
     * @param {GoogleAppsScript.Spreadsheet.Sheet[]} sheets Текущий массив
     * @returns {boolean}
     */
    
    /**
     * Правило переименования
     * @callback renameRule
     * @param {GoogleAppsScript.Spreadsheet.Sheet} sheet Текущий лист
     * @param {number} index Текущий индекс массива
     * @param {GoogleAppsScript.Spreadsheet.Sheet[]} sheets Текущий массив
     * @returns {any}
     */
    Ответ написан
  • Как настроить отправку данных из таблицы в виде одной строки в другую закрытую таблицу?

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

    Замените myFunction на что-то вроде:
    function recordToMain(){
      // Берет диапазон 'Источник!B4:B8' активной Таблицы, т.о. это встроенный скрипт
      var data = SpreadsheetApp.getActive().getRange('Источник!B4:B8')
      .getValues().map(function(row){return row[0];});
      var url = 'https://script.google.com/macros/s/ZZZ/exec';
      var options = {
        method: 'POST',
        headers: {
          ContentType: 'application/json'
        },
        payload: JSON.stringify(data),
        muteHttpExceptions: true
      };
      UrlFetchApp.fetch(url, options); 
    };


    Так же создайте новый проект скриптов, в котором создайте функцию вроде:
    function doPost(e) {
      SpreadsheetApp.openById('YYY') // Должна существовать
      .getSheetByName('Приемник')    // Должен быть лист 'Приемник'
      .appendRow([new Date()].concat(JSON.parse(e.postData.contents)));
    }

    Когда вы опубликуете новый проект для всех от имени себя, то получите url_master для первой функции.
    Ответ написан
  • Загрузка картинок из google drive. Какой правильный путь?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Оба метода сопоставимы и не имеют никакой разницы в контексте инфраструктуры Гугл. Это все сервисы Диска и дергаете вы АПИ Диска. Которое само по себе не дойная корова. Не стоит расчитывать, что при частом запросе изображений вы не увидите отказа в доступе или отказа в соединении. Исполььзуйте Google Cloud Storage. Потратьте уже наконец $10 в год и получите цивильный, быстрый, надежный удобный доступ к сетевому шарингу.
    Ответ написан
  • Как изменить язык в Google Apps Script?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    5c0ffc9a09bee441507346.png
    Ответ написан
    Комментировать
  • Почему неправильно рассчитывается дата?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Ответ на этот вопрос дан на ruSO https://ru.stackoverflow.com/q/882107

    Основная идея в том, чтобы использовать базовые единицы расчета дат (миллисекунды), а не их производные (дни, часы, минуты).

    Хотелось бы добавить, что
    >  new String('Hello world!') == 'Hello world!'
    <· true
    >  new String('Hello world!') === 'Hello world!'
    <· false

    И в данном контексте создание объекта строки неуместно.
    Ответ написан
    Комментировать
  • Как получить значения всех ячеек в колонке?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    /**
     * @param {GoogleAppsScript.Spreadsheet.Sheet} sheet Лист Таблицы
     * @param {number} column Номер столбца
     * @param {number} [startRow] Пропускает количество строк сначала
     * @param {number} [numColums] Количество возвращаемых колонок
     * @returns {Object[][]} Массив значений
     * @see {@link https://toster.ru/q/549725}
     */
    var getValuesFromColumn = function(sheet, column, startRow, numColums) {
        startRow = startRow || 1;
        numColums = numColums || 1;
        var lastRow = sheet.getLastRow();
        return sheet
            .getRange(startRow, column, lastRow - startRow + 1, numColums)
            .getValues();
    };
    
    var arr = getValuesFromColumn(mainSheet, 3, 3, 2);
    Ответ написан
    Комментировать
  • Как можно с помощью google apps script найти все ссылки в google document?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Основной принциип поиска ссылок и базовый код может быть таким
    /**
     * Get an array of all LinkUrls in the document. The function is
     * recursive, and if no element is provided, it will default to
     * the active document's Body element.
     *
     * @param {Element} element The document element to operate on. 
     * .
     * @returns {Array}         Array of objects, vis
     *                              {element,
     *                               startOffset,
     *                               endOffsetInclusive, 
     *                               url}
     */
    function getAllLinks(element) {
      var links = [];
      element = element || DocumentApp.getActiveDocument().getBody();
    
      if (element.getType() === DocumentApp.ElementType.TEXT) {
        var textObj = element.editAsText();
        var text = element.getText();
        var inUrl = false;
        for (var ch=0; ch < text.length; ch++) {
          var url = textObj.getLinkUrl(ch);
          if (url != null) {
            if (!inUrl) {
              // We are now!
              inUrl = true;
              var curUrl = {};
              curUrl.element = element;
              curUrl.url = String( url ); // grab a copy
              curUrl.startOffset = ch;
            }
            else {
              curUrl.endOffsetInclusive = ch;
            }          
          }
          else {
            if (inUrl) {
              // Not any more, we're not.
              inUrl = false;
              links.push(curUrl);  // add to links
              curUrl = {};
            }
          }
        }
      }
      else {
        var numChildren = element.getNumChildren();
        for (var i=0; i<numChildren; i++) {
          links = links.concat(getAllLinks(element.getChild(i)));
        }
      }
    
      return links;
    }


    Источник Get All Links in a Document
    Ответ написан
    Комментировать
  • Как загружать последнюю версию таблицы Google Spreadsheet?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    SpreasheetApp.flush();
    Ответ написан
    Комментировать
  • Как получить названия папок(путь) что хранят файл?

    oshliaer
    @oshliaer Куратор тега Google Apps Script
    Google Products Expert
    Абсолютно бесполезное занятие, которое требует больших ресурсов. Плюс, на Диске могут быть папки в папках своих папок. Как вам такой поворот?

    Решение доступно в этом топике How do I locate the path of the folder in which th...
    Ответ написан
    Комментировать