При разработке различных обработок по загрузке или выгрузке данных в 1С программисты часто сталкиваются с необходимостью предоставить пользователю возможность интерактивного выбора файла на диске. Казалось бы, задача тривиальная: создаем элемент на форме, вешаем на него событие начала выбора, пишем стандартный код вызова диалога — и готово. Однако на практике разработчики (особенно начинающие или те, кто возвращается к поддержке старых конфигураций на обычных формах) натыкаются на неприятный визуальный баг: файл успешно выбирается диалоговым окном, код отрабатывает без ошибок, но само поле на форме остается абсолютно пустым.
В этой статье мы подробно проанализируем, почему возникает такая проблема, разберем ключевые различия между элементами управления формы, исправим критические ошибки в коде интерактивного выбора и рассмотрим, как правильно перенести эту технологию на современные управляемые формы 1С с поддержкой асинхронности.
Давайте подробно разберем ситуацию, описанную автором темы на форуме. Разработчик создал на обычной форме элемент управления и привязал его к реквизиту с именем ВыбратьФайл (тип реквизита — произвольный). На событие начала выбора был назначен программный обработчик. При запуске код отрабатывал, открывалось стандартное окно операционной системы для выбора файла Microsoft Excel, пользователь выбирал файл, нажимал «Открыть», но путь к файлу в поле на форме не отображался.
Причина такого поведения кроется в фундаментальном различии между элементами управления «Поле ввода» и «Поле выбора» (в терминологии других языков программирования — ComboBox).
Элемент формы ПолеВыбора жестко ориентирован на работу со списком значений (свойство СписокВыбора). Когда мы программно присваиваем связанному реквизиту текстовую строку с путем к файлу (например, "C:\Users\User\Documents\Report.xlsx"), платформа пытается найти эту строку среди элементов своего предопределенного списка выбора. Поскольку этого файла в списке нет, элемент управления не может сопоставить значение и отображает пустое поле. Физически в самом реквизите путь к файлу сохраняется и с ним можно работать в коде, но пользователь видит лишь пустую строку, что вводит его в заблуждение.
Элемент формы ПолеВвода, напротив, разработан для свободного ввода текстовых, числовых или иных данных произвольного формата. Оно способно отображать любые строковые значения без необходимости их предварительной регистрации в каких-либо списках. Именно поэтому для задач выбора файлов на диске всегда следует использовать исключительно ПолеВвода.
Выяснив причину проблемы, разберем по шагам, как правильно настроить форму и написать работоспособный код для обычных форм 1С.
Шаг 1. Настройка элемента управления в конфигураторе.
Прежде всего, откроем форму нашей обработки или документа в конфигураторе и настроим свойства элемента:
Данные и свяжем его с реквизитом обработки (например, реквизит ПутьКФайлу с типом Строка произвольной длины).КнопкаВыбора в значение Истина (Да). Это действие выведет в правой части поля привычную кнопку с троеточием «...».РежимВыбораИзСписка установлено в значение Ложь (Нет).Шаг 2. Написание программного кода.
В исходном коде автора темы на форуме была допущена еще одна критическая ошибка: отсутствовало управление параметром СтандартнаяОбработка. Рассмотрим правильный шаблон кода для обычной формы:
Процедура ПутьКФайлуНачалоВыбора(Элемент, СтандартнаяОбработка) Экспорт
// Блокируем стандартное поведение платформы
СтандартнаяОбработка = Ложь;
// Инициализируем диалог выбора файла
ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
ДиалогВыбора.Заголовок = "Выберите файл Excel";
ДиалогВыбора.ПолноеИмяФайла = "";
ДиалогВыбора.Фильтр = "Таблицы (*.xls,*.xlsx)|*.xls;*.xlsx|Microsoft Excel 97/2000/XP/2003 (*.xls)|*.xls|Microsoft Excel 2007/2010 (*.xlsx)|*.xlsx";
// Открываем диалог в модальном режиме
Если ДиалогВыбора.Выбрать() Тогда
// Присваиваем реквизиту формы выбранный путь
ПутьКФайлу = ДиалогВыбора.ПолноеИмяФайла;
КонецЕсли;
КонецПроцедуры
Разберем подробнее строчку СтандартнаяОбработка = Ложь;. По умолчанию, когда пользователь нажимает кнопку выбора «...», платформа 1С пытается выполнить заложенное в конфигурации стандартное действие (например, открыть справочник или окно выбора типа данных, если реквизит не типизирован). Если не установить этот флаг в значение Ложь, то поверх нашего диалога выбора файла может открыться стандартное окно выбора типа данных, либо значение, выбранное нами, будет сразу стерто последующей стандартной очисткой платформы.
Технологии 1С не стоят на месте, и использование синхронных вызовов (таких как метод Выбрать() объекта ДиалогВыбораФайла) в современном коде крайне нежелательно, а на управляемых формах в тонком или веб-клиенте — полностью запрещено на уровне платформы. При попытке выполнить такой код в веб-клиенте система выдаст ошибку аварийного завершения работы.
Рассмотрим, как решить аналогичную задачу на управляемых формах двумя способами: классическим асинхронным методом и современным методом через ключевые слова Асинх / Ждать.
Этот подход применялся в версиях платформы 1С:Предприятие от 8.3.3 до 8.3.17. Для его реализации нам потребуется создать две процедуры: одну для инициализации диалога, вторую — для обработки результата выбора.
&НаКлиенте
Процедура ПутьКФайлуНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл для загрузки";
Диалог.Фильтр = "Файлы Excel (*.xls;*.xlsx)|*.xls;*.xlsx";
// Создаем описание оповещения, указывая процедуру обратного вызова
Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
// Показываем диалог асинхронно
Диалог.Показать(Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораФайла(ВыбранныеФайлы, ДополнительныеПараметры) Экспорт
Если ВыбранныеФайлы <> Неопределено И ВыбранныеФайлы.Количество() > 0 Тогда
// Записываем путь к файлу в реквизит управляемой формы
Объект.ПутьКФайлу = ВыбранныеФайлы[0];
КонецЕсли;
КонецПроцедуры
Этот метод полностью рабочий, однако он имеет существенный недостаток: код размывается по модулю формы, становится сложным для чтения и поддержки из-за обилия процедур-колбэков.
В современных релизах платформы разработчикам доступен лаконичный и красивый механизм асинхронного программирования на основе обещаний (Promise). Мы используем модификатор процедуры Асинх и оператор ожидания Ждать.
&НаКлиенте
Асинх Процедура ПутьКФайлуНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл для обработки";
Диалог.Фильтр = "Таблицы Excel (*.xlsx)|*.xlsx";
// Платформа приостановит выполнение процедуры до закрытия диалога пользователем
РезультатВыбора = Ждать Диалог.ВыбратьАсинх();
Если РезультатВыбора <> Неопределено Тогда
// Метод ВыбратьАсинх() возвращает массив путей выбранных файлов
Объект.ПутьКФайлу = РезультатВыбора[0];
КонецЕсли;
КонецПроцедуры
Проанализируем этот код подробнее. Использование ключевого слова Ждать позволяет писать асинхронный код так, будто он выполняется последовательно (синхронно). При этом интерфейс программы не блокируется, а сама процедура не требует разделения на несколько частей. Это стандарт разработки, к которому необходимо стремиться при написании современных конфигураций. Для практического изучения этой темы можно использовать методику асинхронного выбора и чтения файлов в 1С, которая на конкретном примере демонстрирует лаконичный подход к работе с данными.
Работая в управляемом интерфейсе, особенно через веб-браузер, важно понимать: простое получение пути к локальному файлу (например, "C:\MyFolder\file.xlsx") не дает серверу 1С возможности прочитать этот файл напрямую. Сервер физически не имеет доступа к жесткому диску клиентского компьютера.
Если ваша обработка должна выполняться на сервере (например, чтение данных из файла Excel и запись их в информационную базу), то вместо простого сохранения пути необходимо использовать механизм временного хранилища. Для этого применяется асинхронная функция ПоместитьФайлНаСерверАсинх, которая не просто возвращает путь, а загружает сам файл в память сервера 1С, возвращая уникальный адрес во временном хранилище.
Давайте подытожим основные правила, которые мы выработали в процессе совместного решения этой технической задачи:
ПолеВыбора для ввода путей к файлам. Для этих целей предназначено исключительно ПолеВвода.СтандартнаяОбработка = Ложь;.Диалог.Выбрать(), но для управляемых форм применяйте только асинхронные методы: Диалог.Показать() для старых версий или связку Асинх / Ждать / ВыбратьАсинх() для актуальных релизов платформы 1С.