В процессе разработки приложений на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью организации выбора файлов пользователем. Стандартный диалог открытия файлов предоставляет удобный интерфейс для этой задачи, но иногда возникает вопрос: как настроить фильтр таким образом, чтобы он одновременно показывал файлы с несколькими разными расширениями? Например, нам может потребоваться отобразить все файлы изображений, включая форматы BMP, JPG, JPEG и PNG, без необходимости многократного переключения между фильтрами.
Давайте вместе разберем, как эффективно решить эту задачу, используя как стандартные возможности платформы, так и, при необходимости, более продвинутые подходы.
Рассмотрим основной способ решения задачи, который оказался рабочим и проверенным многими разработчиками 1С. Поскольку диалог выбора файлов в 1С на платформе Windows часто использует системные компоненты операционной системы, он подчиняется стандартным правилам форматирования строки фильтра, принятым в Windows API и .NET Framework.
Формат строки фильтра.
Строка фильтра в диалоге выбора файлов 1С (при использовании объектов ДиалогВыбораФайла или глобальной функции ПолучитьИмяФайла) имеет четкую структуру, которую мы сейчас детально изучим. Она состоит из пар "Описание фильтра|Маска фильтра", разделенных символом вертикальной черты |. Для указания нескольких расширений внутри одной маски используется символ точки с запятой ;.
"Описание фильтра 1|*.расширение1;*.расширение2|Описание фильтра 2|*.расширение3"
Разберем каждый компонент этого формата:
Описание фильтра: Это текстовая строка, которую видит пользователь в выпадающем списке "Тип файлов" в диалоге выбора. Она должна быть информативной, например, "Файлы изображений" или "Документы Word". Желательно также указать в скобках основные расширения, которые будут отображены, например "Файлы изображений (*.bmp, *.jpg)".
Символ "|" (вертикальная черта): Этот символ выступает в роли разделителя между описанием фильтра и его маской, а также между различными вариантами фильтров (например, "Все файлы изображений|*.bmp;*.jpg|Текстовые файлы|*.txt").
Маска фильтра: Это строка, содержащая шаблоны файлов, которые должны быть показаны. Здесь используются символы подстановки (например, * для любого количества любых символов). Расширения указываются после *., например *.bmp.
Символ ";" (точка с запятой): Это ключевой элемент для решения нашей задачи. Он позволяет объединить несколько масок расширений в рамках одной записи фильтра. Например, *.bmp;*.jpg;*.jpeg;*.png укажет диалогу показать все файлы с этими расширениями, если выбран соответствующий фильтр.
Пример для файлов изображений.
Давайте применим эти знания к нашей исходной задаче – отображению файлов BMP, JPG, JPEG и PNG. Строка фильтра для этого будет выглядеть следующим образом:
Фильтр = "Файлы изображений (*.bmp, *.jpg, *.jpeg, *.png)|*.bmp;*.jpg;*.jpeg;*.png";
// Пример использования с объектом ДиалогВыбораФайла
ФайлДиалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ФайлДиалог.Заголовок = "Выберите файл изображения";
ФайлДиалог.Фильтр = Фильтр;
ФайлДиалог.МножественныйВыбор = Ложь; // Или Истина, если нужно выбрать несколько файлов
ИмяВыбранногоФайла = "";
Если ФайлДиалог.Выбрать() Тогда
ИмяВыбранногоФайла = ФайлДиалог.ПолноеИмяФайла; // Или ПолученныеФайлы для множественного выбора
Сообщить("Выбран файл: " + ИмяВыбранногоФайла);
Иначе
Сообщить("Выбор файла отменен.");
КонецЕсли;
В этом примере мы видим, как в описательной части мы указываем все типы файлов для удобства пользователя, а в маске фильтра через точку с запятой перечисляем все необходимые расширения. Этот подход является стандартным для Windows и прекрасно работает в 1С.
Использование метода ПолучитьИмяФайла().
Аналогично, если вы используете глобальный метод ПолучитьИмяФайла(), который является более простым способом вызова диалога:
// В качестве второго параметра передаем нашу строку фильтра
ИмяФайла = ПолучитьИмяФайла(РежимДиалогаВыбораФайла.Открытие, "Файлы изображений (*.bmp, *.jpg, *.jpeg, *.png)|*.bmp;*.jpg;*.jpeg;*.png");
Если Не ПустаяСтрока(ИмяФайла) Тогда
Сообщить("Выбран файл: " + ИмяФайла);
Иначе
Сообщить("Выбор файла отменен.");
КонецЕсли;
Мы видим, что принцип использования строки фильтра остается тем же.
Стандартные диалоги выбора файлов в Windows, а следовательно, и в 1С, поддерживают не только перечисление расширений, но и более сложные маски с использованием символов подстановки. Рассмотрим их подробнее.
Символ "*" (звездочка):
Звездочка * обозначает любое число произвольных символов. Мы уже использовали ее в сочетании с расширениями (например, *.txt), но ее можно применять и в других частях имени файла. Например, Отчет*.xls будет соответствовать файлам "Отчет 2023.xls", "Отчет за год.xls" и так далее.
Символ "?" (знак вопроса):
Знак вопроса ? обозначает один произвольный символ. Это полезно, когда нам нужно задать фильтр для файлов, имена которых отличаются всего на один символ. Например, Документ?.pdf будет соответствовать "Документ1.pdf", "ДокументА.pdf", но не "Документ10.pdf".
Классы символов "[]":
Квадратные скобки [] позволяют определить класс символов, которым может соответствовать один символ в имени файла. Это мощный инструмент для более тонкой фильтрации. Мы можем указать:
Перечисление символов: [abc].txt будет соответствовать "a.txt", "b.txt", "c.txt".
Диапазон символов: Используя дефис -, можно задать диапазон. Например, [0-9].log будет соответствовать файлам "0.log", "1.log" ... "9.log". Аналогично, [A-Z].doc для букв верхнего регистра.
Исключение символов: Если после открывающей скобки [ указать восклицательный знак !, то класс будет описывать все символы, кроме указанных. Например, [!0-9].txt соответствует текстовым файлам, имена которых начинаются не с цифры.
Пример, приведенный в документации 1С, демонстрирует использование классов символов для учета регистра: *.[tT][xX][tT]. Такая маска позволит найти файлы с расширением TXT, независимо от того, написано оно в верхнем, нижнем или смешанном регистре (например, "файл.txt", "файл.TXT", "файл.TxT").
Пример использования.
Давайте посмотрим на примеры, демонстрирующие применение этих расширенных возможностей:
// Фильтр для текстовых файлов с расширением TXT, написанным в любом регистре
ФильтрТекст = "Текстовые документы (*.txt)|*.[tT][xX][tT]";
// Фильтр для документов Word с конкретным префиксом и цифрой
// Например, "doc0.docx", "doc1.docx" и т.д.
ФильтрДокументы = "Специальные документы Word (doc[0-9].docx)|doc[0-9].docx";
// Пример объединения различных сложных фильтров в одном диалоге
ОбщийФильтр = "Текстовые или специальные документы|*.[tT][xX][tT];doc[0-9].docx";
// Применение фильтра
// ... (используем ФильтрТекст, ФильтрДокументы или ОбщийФильтр в ДиалогВыбораФайла.Фильтр
// или вторым параметром ПолучитьИмяФайла)
Особенности и ограничения.
Важно понимать, что хотя платформа 1С через свой Синтакс-Помощник может описывать поддержку таких сложных паттернов, их фактическая работа может зависеть от конкретной реализации системного диалога в операционной системе. В частности, учет регистра с помощью [tT] может не всегда корректно работать в стандартных диалогах Windows для файловых систем, которые по умолчанию не чувствительны к регистру. Однако, для большинства задач, включая простое перечисление расширений через ;, стандартные механизмы фильтрации являются надежными и достаточными.
Мы должны всегда тестировать более сложные маски на целевой операционной системе, чтобы убедиться в их корректной работе.
В некоторых случаях, когда стандартный диалог выбора файлов не предоставляет необходимой гибкости, или требуется реализовать специфическую логику (например, отбор по метаданным файла, загрузку с удаленного сервера или более сложную визуализацию), мы можем рассмотреть вариант создания собственной формы выбора файла в 1С. Это дает полный контроль над процессом.
Преимущества собственной формы.
Полный контроль: Мы можем реализовать любую логику фильтрации, сортировки, отображения файлов и папок.
Интеграция с данными: Возможность отображать файлы, хранящиеся не только на диске, но и в базе данных, облачных хранилищах или других источниках.
Пользовательский интерфейс: Создание интерфейса, максимально соответствующего специфике нашей задачи и корпоративному стилю.
Расширенная функциональность: Добавление предпросмотра, работы с архивами, сравнения файлов и других специализированных функций.
Основные шаги по реализации.
Давайте пошагово разберем, как мы можем подойти к созданию такой формы:
Шаг 1: Создание формы.
Мы создаем новую управляемую форму (например, "ФормаВыбораФайла") и добавляем в нее необходимые реквизиты: ПутьКТекущемуКаталогу (Тип: Строка), СписокФайлов (Тип: ТаблицаЗначений) и ФильтрРасширений (Тип: Строка).
Шаг 2: Элементы управления.
На форму добавляем следующие элементы:
Поле ввода для отображения и изменения текущего пути к каталогу.
Кнопки "Вверх", "Открыть", "Выбрать" для навигации и действия.
Таблица (на основе реквизита СписокФайлов) для отображения содержимого текущего каталога (имя файла/папки, размер, дата изменения, тип). Возможно использование ДеревоЗначений для иерархического отображения папок.
Поле ввода для задания пользователем фильтра по расширениям (например, "jpg;png").
Кнопка "Применить фильтр".
Шаг 3: Чтение содержимого каталогов.
Нам потребуется функция, которая будет получать список файлов и подкаталогов в указанном пути. Мы можем использовать объект Файл и его методы, например ПолучитьФайлы() и ПолучитьКаталоги(), или метод НайтиФайлы().
// Пример получения списка файлов в каталоге
&НаСервере
Функция ПолучитьСписокЭлементовВКаталоге(ПутьККаталогу)
СписокЭлементов = Новый ТаблицаЗначений;
СписокЭлементов.Колонки.Добавить("Имя");
СписокЭлементов.Колонки.Добавить("ПолныйПуть");
СписокЭлементов.Колонки.Добавить("Тип", Новый ОписаниеТипов("Строка")); // "Каталог" или "Файл"
СписокЭлементов.Колонки.Добавить("Расширение");
СписокЭлементов.Колонки.Добавить("Размер", Новый ОписаниеТипов("Число"));
СписокЭлементов.Колонки.Добавить("ДатаИзменения", Новый ОписаниеТипов("Дата"));
Попытка
КаталогФайл = Новый Файл(ПутьККаталогу);
Если КаталогФайл.Существует() И КаталогФайл.ЭтоКаталог() Тогда
// Добавляем каталоги
Для Каждого ЭлементФС Из КаталогФайл.ПолучитьКаталоги() Цикл
НоваяСтрока = СписокЭлементов.Добавить();
НоваяСтрока.Имя = ЭлементФС.Имя;
НоваяСтрока.ПолныйПуть = ЭлементФС.ПолноеИмя;
НоваяСтрока.Тип = "Каталог";
КонецЦикла;
// Добавляем файлы
Для Каждого ЭлементФС Из КаталогФайл.ПолучитьФайлы() Цикл
НоваяСтрока = СписокЭлементов.Добавить();
НоваяСтрока.Имя = ЭлементФС.Имя;
НоваяСтрока.ПолныйПуть = ЭлементФС.ПолноеИмя;
НоваяСтрока.Тип = "Файл";
НоваяСтрока.Расширение = ЭлементФС.Расширение;
НоваяСтрока.Размер = ЭлементФС.Размер;
НоваяСтрока.ДатаИзменения = ЭлементФС.ДатаИзменения;
КонецЦикла;
КонецЕсли;
Исключение
// Обработка ошибок, например, нет доступа к каталогу
Сообщить("Ошибка при чтении каталога " + ПутьККаталогу + ": " + ОписаниеОшибки());
КонецПопытки;
Возврат СписокЭлементов;
КонецФункции
// Пример вызова на клиенте для обновления отображения
&НаКлиенте
Процедура ОбновитьСписокФайловНаКлиенте()
Если ПустаяСтрока(ПутьКТекущемуКаталогу) Тогда
// Устанавливаем каталог по умолчанию или из настроек пользователя
ПутьКТекущемуКаталогу = "C:\";
КонецЕсли;
СписокФайлов = ПолучитьСписокЭлементовВКаталоге(ПутьКТекущемуКаталогу);
// Дополнительная фильтрация на клиенте, если нужно
СписокФайлов = ОтфильтроватьФайлы(СписокФайлов, ФильтрРасширений);
КонецПроцедура;
Мы должны предусмотреть обработку ошибок, например, когда пользователь указывает несуществующий путь или у нас нет прав доступа к каталогу.
Шаг 4: Реализация пользовательского фильтра.
После получения полного списка файлов в каталоге мы применяем к нему пользовательский фильтр. Фильтр будет представлен строкой, где расширения разделены точкой с запятой (например, "bmp;jpg;png").
// Пример фильтрации списка файлов на основании расширений
Функция ОтфильтроватьФайлы(СписокВсехЭлементов, МаскаРасширений)
Если ПустаяСтрока(МаскаРасширений) Тогда
Возврат СписокВсехЭлементов; // Если фильтр не задан, возвращаем все
КонецЕсли;
ОтфильтрованныйСписок = Новый ТаблицаЗначений;
Для Каждого Колонка Из СписокВсехЭлементов.Колонки Цикл
ОтфильтрованныйСписок.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);
КонецЦикла;
МассивРасширений = СтрРазделить(НижРегистр(МаскаРасширений), ";", Ложь);
Для Каждого СтрЭлемент Из СписокВсехЭлементов Цикл
Если СтрЭлемент.Тип = "Каталог" Тогда
ОтфильтрованныйСписок.Добавить(СтрЭлемент); // Каталоги всегда показываем
Продолжить;
КонецЕсли;
РасширениеФайла = НижРегистр(СтрЭлемент.Расширение);
Для Каждого МаскаРасширения Из МассивРасширений Цикл
// Сравниваем расширение файла с маской (удаляем ведущую точку, если есть)
Если СтрДлина(МаскаРасширения) > 0 И Лев(МаскаРасширения, 1) = "." Тогда
МаскаРасширения = Сред(МаскаРасширения, 2);
КонецЕсли;
Если РасширениеФайла = МаскаРасширения Тогда
ОтфильтрованныйСписок.Добавить(СтрЭлемент);
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат ОтфильтрованныйСписок;
КонецФункции;
Эта функция будет вызываться каждый раз, когда пользователь изменяет путь или фильтр.
Шаг 5: Выбор файла и возврат результата.
При нажатии кнопки "Выбрать" мы фиксируем путь к выбранному файлу (или файлам, если предусмотрен множественный выбор) и возвращаем его вызвавшему коду. Это можно сделать через параметр формы или, если форма открывается модально, через ее результат:
// В обработчике команды кнопки "Выбрать" на форме выбора файла
&НаКлиенте
Процедура ВыбратьФайл(Команда)
Если Элементы.ТаблицаФайлов.ТекущиеДанные <> Неопределено Тогда
ВыбранныйФайл = Элементы.ТаблицаФайлов.ТекущиеДанные.ПолныйПуть;
Если Не ПустаяСтрока(ВыбранныйФайл) Тогда
Закрыть(ВыбранныйФайл); // Возвращаем выбранный путь как результат формы
Иначе
Сообщить("Не выбран файл для выбора.");
КонецЕсли;
Иначе
Сообщить("Не выбран файл для выбора.");
КонецЕсли;
КонецПроцедура;
// В модуле, откуда вызывается форма
&НаКлиенте
Процедура ОткрытьМоюФормуВыбораФайла(Команда)
Форма = ПолучитьФорму("ОбщаяФорма.МояФормаВыбораФайла");
РезультатВыбора = Форма.ОткрытьМодально();
Если РезультатВыбора <> Неопределено И Не ПустаяСтрока(РезультатВыбора) Тогда
Сообщить("Пользователь выбрал файл: " + РезультатВыбора);
Иначе
Сообщить("Выбор файла отменен или не произведен.");
КонецЕсли;
КонецПроцедура;
Как мы с вами убедились, платформа 1С:Предприятие 8.3 предоставляет достаточно гибкие механизмы для работы с диалогами выбора файлов. В большинстве случаев для фильтрации по нескольким расширениям достаточно использовать стандартный формат строки фильтра с разделителем ;, который корректно обрабатывается системными диалогами Windows. Для более сложных сценариев, требующих уникальной логики или интерфейса, у нас всегда есть возможность создать собственную форму выбора файлов, что обеспечивает полный контроль над процессом. Используя эти подходы, мы сможем сделать работу пользователей с файлами максимально удобной и интуитивно понятной.