Google Apps Script: Получение папки по имени

Что такое Google Apps Script и его возможности для работы с Google Drive

Google Apps Script (GAS) — это облачная платформа для разработки на JavaScript, позволяющая расширять функциональность приложений Google Workspace, таких как Drive, Sheets, Docs и Gmail. В контексте Google Drive, GAS предоставляет мощные инструменты для автоматизации управления файлами и папками: создание, перемещение, удаление, изменение прав доступа и, что особенно важно, поиск.

Обзор класса `Folder` в Google Apps Script

Центральным элементом при работе с папками в Google Drive через GAS является класс Folder. Экземпляры этого класса представляют собой конкретные папки на вашем Диске. Класс Folder предоставляет методы для взаимодействия с папкой: получение ее имени, ID, родительских папок, содержимого (файлов и подпапок), а также для создания новых элементов внутри нее.

Важность поиска папок по имени

Во многих сценариях автоматизации необходимо взаимодействовать с папками, структура которых заранее известна или подчиняется определенным правилам именования. Например, при обработке ежемесячных отчетов, которые складываются в папки с названием вида "Отчеты за Месяц Год", или при поиске папки конкретного проекта. Возможность программно найти папку по ее имени является ключевой для таких задач, избавляя от необходимости жестко прописывать ID папок, которые могут меняться.

Основные методы получения папки по имени в Google Apps Script

Использование `getFoldersByName(name)` для поиска папок

Основным методом для поиска папок по имени в Google Apps Script является DriveApp.getFoldersByName(name) (для поиска по всему Диску пользователя) или Folder.getFoldersByName(name) (для поиска подпапок внутри конкретной папки). Этот метод принимает строковый аргумент — имя искомой папки.

Важно отметить, что Google Drive допускает существование нескольких папок с одинаковым именем в одной и той же локации. Поэтому метод getFoldersByName спроектирован так, чтобы потенциально находить несколько совпадений.

Понимание ограничений `getFoldersByName(name)` (возвращает итератор)

Метод getFoldersByName(name) возвращает не массив папок, а объект типа FolderIterator. Итератор — это специальный объект, который позволяет последовательно перебирать элементы коллекции (в данном случае, найденные папки), не загружая их все сразу в память. Это эффективно при работе с большим количеством потенциальных совпадений.

Для работы с итератором используются два основных метода:

hasNext(): Возвращает true, если в итераторе есть еще папки, и false в противном случае.

next(): Возвращает следующую папку (Folder) из итератора и перемещает "указатель" итератора вперед.

Преобразование итератора в массив для удобной работы

Хотя работа с итератором эффективна, часто удобнее иметь дело с обычным массивом папок. Преобразовать FolderIterator в массив можно с помощью простого цикла while:

/**
 * Находит все папки с заданным именем и возвращает их в виде массива.
 * Поиск осуществляется по всему Google Drive пользователя.
 *
 * @param {string} name Имя папки для поиска.
 * @return {GoogleAppsScript.Drive.Folder[]} Массив найденных папок.
 */
function getAllFoldersByNameAsArray(name) {
  const folders = [];
  const folderIterator = DriveApp.getFoldersByName(name);

  while (folderIterator.hasNext()) {
    const folder = folderIterator.next();
    folders.push(folder);
  }

  return folders;
}

// Пример использования:
const reportFolders = getAllFoldersByNameAsArray('Ежемесячные отчеты');
Logger.log(`Найдено папок: ${reportFolders.length}`);

Реализация функции для получения первой папки по имени

Часто возникает задача найти одну конкретную папку, и мы предполагаем, что папка с таким именем уникальна (или нам достаточно первого найденного экземпляра).

Написание функции `getFolderByName(name)`

/**
 * Находит первую папку с указанным именем на Google Drive.
 *
 * @param {string} name Имя папки.
 * @return {GoogleAppsScript.Drive.Folder | null} Найденная папка или null, если папка не найдена.
 */
function getFolderByName(name) {
  const folderIterator = DriveApp.getFoldersByName(name);

  if (folderIterator.hasNext()) {
    return folderIterator.next();
  } else {
    return null;
  }
}

Обработка случаев, когда папка с указанным именем не найдена

В приведенной выше функции, если folderIterator.hasNext() возвращает false, это означает, что папок с таким именем не найдено. В этом случае функция вернет null. Важно всегда проверять результат вызова этой функции перед тем, как пытаться использовать возвращенный объект папки.

Пример использования функции `getFolderByName(name)`

// Попытка получить папку для клиентских данных
const clientDataFolderName = 'Client CRM Data';
const clientFolder = getFolderByName(clientDataFolderName);

if (clientFolder) {
  Logger.log(`Папка найдена: ${clientFolder.getName()} (ID: ${clientFolder.getId()})`);
  // Здесь можно выполнять операции с папкой, например, создавать файлы
  // clientFolder.createFile('new_report.txt', 'Содержимое отчета');
} else {
  Logger.log(`Папка с именем '${clientDataFolderName}' не найдена.`);
  // Здесь можно реализовать логику создания папки, если она отсутствует
}
Реклама

Реализация функции для получения всех папок по имени

Если необходимо обработать все папки с одинаковым именем (например, папки проектов разных лет, имеющие одинаковую структуру).

Написание функции `getAllFoldersByName(name)`

Эта функция фактически повторяет код преобразования итератора в массив, который мы рассмотрели ранее, но оформлен как отдельная переиспользуемая функция.

/**
 * Находит все папки с заданным именем на Google Drive.
 *
 * @param {string} name Имя папки для поиска.
 * @return {GoogleAppsScript.Drive.Folder[]} Массив найденных папок. Может быть пустым.
 */
function getAllFoldersByName(name) {
  const folders = [];
  const folderIterator = DriveApp.getFoldersByName(name);

  while (folderIterator.hasNext()) {
    folders.push(folderIterator.next());
  }

  return folders;
}

Использование массива для хранения результатов

Функция инициализирует пустой массив folders. В цикле while каждая найденная папка добавляется в этот массив с помощью метода push(). По завершении цикла функция возвращает массив, содержащий все найденные папки.

Пример использования функции `getAllFoldersByName(name)`

// Поиск всех папок с маркетинговыми материалами за разные периоды
const campaignFolderName = 'Marketing Campaign Assets';
const campaignFolders = getAllFoldersByName(campaignFolderName);

if (campaignFolders.length > 0) {
  Logger.log(`Найдено ${campaignFolders.length} папок с именем '${campaignFolderName}':`);
  campaignFolders.forEach((folder, index) => {
    Logger.log(`  ${index + 1}. ID: ${folder.getId()}, Родительская папка: ${folder.getParents().hasNext() ? folder.getParents().next().getName() : 'Мой диск'}`);
    // Здесь можно выполнить операции с каждой найденной папкой
  });
} else {
  Logger.log(`Папки с именем '${campaignFolderName}' не найдены.`);
}

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

Учет регистра при поиске (приведение к нижнему регистру)

Метод getFoldersByName(name) по умолчанию выполняет поиск без учета регистра. То есть, getFoldersByName('Reports') найдет папки с именами ‘Reports’, ‘reports’, ‘REPORTS’ и т.д. Если по какой-то причине требуется строгий поиск с учетом регистра, стандартного метода для этого нет. Придется получать все папки с именем без учета регистра, а затем фильтровать результат в скрипте:

/**
 * Находит все папки с точным совпадением имени (с учетом регистра).
 *
 * @param {string} name Имя папки (с учетом регистра).
 * @return {GoogleAppsScript.Drive.Folder[]} Массив найденных папок.
 */
function getAllFoldersByNameCaseSensitive(name) {
  const allFolders = getAllFoldersByName(name); // Получаем все без учета регистра
  return allFolders.filter(folder => folder.getName() === name);
}

Поиск подпапок в определенной папке

Если нужно искать папку не по всему Диску, а внутри конкретной родительской папки, используйте метод getFoldersByName() экземпляра класса Folder:

/**
 * Ищет подпапки с заданным именем внутри указанной родительской папки.
 *
 * @param {string} name Имя искомой подпапки.
 * @param {GoogleAppsScript.Drive.Folder} parentFolder Родительская папка.
 * @return {GoogleAppsScript.Drive.Folder[]} Массив найденных подпапок.
 */
function getSubFoldersByName(name, parentFolder) {
  if (!parentFolder) {
    Logger.log('Родительская папка не предоставлена.');
    return [];
  }

  const folders = [];
  const folderIterator = parentFolder.getFoldersByName(name);

  while (folderIterator.hasNext()) {
    folders.push(folderIterator.next());
  }

  return folders;
}

// Пример: Найти 'Архив' внутри папки 'Проект Альфа'
const projectAlphaFolder = getFolderByName('Проект Альфа');
if (projectAlphaFolder) {
  const archiveFolders = getSubFoldersByName('Архив', projectAlphaFolder);
  Logger.log(`В папке 'Проект Альфа' найдено ${archiveFolders.length} подпапок 'Архив'.`);
}

Обработка ошибок и логирование

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

Используйте try...catch для отлова непредвиденных ошибок (например, проблем с доступом) и Logger.log() или сервис console (для V8 среды выполнения) для записи информации о ходе выполнения скрипта, найденных элементах или возникших проблемах. Это значительно упрощает отладку и поддержку ваших скриптов.

try {
  const sensitiveFolder = getFolderByName('Strictly Private');
  if (sensitiveFolder) {
    // ... работа с папкой
    Logger.log(`Успешно обработана папка ${sensitiveFolder.getName()}`);
  } else {
    Logger.warning('Конфиденциальная папка не найдена.');
  }
} catch (error) {
  Logger.log(`Произошла ошибка при поиске или обработке папки: ${error.message}`);
  // Дополнительные действия по обработке ошибки
}

Добавить комментарий