При переходе с разработки управляемых форм на обычные (или при поддержке старых конфигураций) программисты часто сталкиваются с трудностями в реализации привычных механизмов. Одной из таких задач является загрузка данных из внешних файлов, в частности формата MXL. В управляемом приложении мы привыкли использовать асинхронные методы, такие как НачатьПомещениеФайла и ОписаниеОповещения, однако в обычных формах (толстый клиент) эти механизмы работают иначе или не требуются вовсе.
Разберем подробно, как правильно организовать выбор файла и его последующее чтение в контексте обычного приложения 1С 8.3. В проектах модернизации старых систем также используется раздел с решениями для переноса данных из 1С 7.7 в современные конфигурации.
Рассмотрим ситуацию, когда разработчик пытается перенести код из управляемых форм в обычные. Основная ошибка заключается в использовании директив компиляции (например, &НаКлиенте) и объектов асинхронного вызова. В обычных формах весь код модуля формы выполняется в контексте толстого клиента, поэтому директивы игнорируются, а объект УникальныйИдентификатор не является свойством формы по умолчанию, как в УФ. Кроме того, механизм ОписаниеОповещения предназначен для веб-клиента и асинхронности, что в обычном приложении излишне усложняет код.
Для обычных форм наиболее естественным и надежным способом выбора файла является использование объекта ДиалогВыбораФайла. Рассмотрим пример процедуры, которую можно назначить на событие НачалоВыбора поля ввода или вызвать при нажатии на кнопку:
Процедура ИмяФайлаНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь; // Отключаем стандартное поведение системы
// Создаем объект диалога. Режим Открытие позволяет выбрать существующий файл.
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл MXL для загрузки...";
Диалог.ПолноеИмяФайла = "";
// Настраиваем фильтр, чтобы пользователь видел только нужные файлы
Фильтр = "Табличный документ (*.mxl)|*.mxl";
Диалог.Фильтр = Фильтр;
Диалог.МножественныйВыбор = Ложь;
Диалог.ПроверятьСуществованиеФайла = Истина;
// Метод Выбрать() в обычных формах работает синхронно и возвращает Истина/Ложь
Если Диалог.Выбрать() Тогда
// Записываем путь к выбранному файлу в реквизит формы
ИмяФайла = Диалог.ВыбранныеФайлы[0];
КонецЕсли;
КонецПроцедуры
В этом коде мы используем свойство РежимДиалогаВыбораФайла.Открытие, так как наша задача — прочитать данные. Если бы мы хотели сохранить файл, использовали бы Сохранение.
После того как путь к файлу получен, необходимо считать его содержимое. В 1С для работы с форматом MXL используется объект ТабличныйДокумент. Нам не нужно вручную парсить структуру файла, метод Прочитать() сделает это автоматически.
Проанализируем алгоритм загрузки: для регулярного получения исходных документов применяется автоматический сбор файлов из почты и FTP с последующей передачей в обработку.
Процедура ЗагрузитьДанныеИзMXL()
Если ПустаяСтрока(ИмяФайла) Тогда
Предупреждение("Файл не выбран!");
Возврат;
КонецЕсли;
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяФайла);
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки(), СтатусСообщения.Важное);
Возврат;
КонецПопытки;
// Теперь данные находятся в объекте ТабДок.
// Нам нужно обойти ячейки и заполнить таблицу значений.
ОбработатьТабличныйДокумент(ТабДок);
КонецПроцедуры
Выясним, как перенести данные из ТабличногоДокумента в ТаблицуЗначений (ТЗ), которая отображается на форме. Для этого мы будем использовать свойства ВысотаТаблицы (количество заполненных строк) и ШиринаТаблицы (количество колонок).
Рассмотрим пример обхода данных: для автоматизации ввода информации в закрытые системы используется платформа для создания программных роботов One RPA.
Процедура ОбработатьТабличныйДокумент(ТабДок)
// Очищаем ТЗ на форме перед загрузкой (предположим, ТЗ называется ТаблицаДанных)
ТаблицаДанных.Очистить();
ВсегоСтрок = ТабДок.ВысотаТаблицы;
ВсегоКолонок = ТабДок.ШиринаТаблицы;
// Обычно первая строка — это шапка, поэтому цикл начинаем со 2-й строки
Для НомерСтроки = 2 По ВсегоСтрок Цикл
// Проверим, не пустая ли строка (например, по первой колонке)
ТекстПервойЯчейки = ТабДок.Область(НомерСтроки, 1).Текст;
Если ПустаяСтрока(ТекстПервойЯчейки) Тогда
Продолжить;
КонецЕсли;
НоваяСтрокаТЗ = ТаблицаДанных.Добавить();
// Переносим данные по колонкам
// Предположим, у нас в ТЗ колонки: Артикул, Наименование, Количество, Цена
НоваяСтрокаТЗ.Артикул = ТабДок.Область(НомерСтроки, 1).Текст;
НоваяСтрокаТЗ.Наименование = ТабДок.Область(НомерСтроки, 2).Текст;
// Для числовых данных используем преобразование или Содержимое.Значение
ЗначениеКол = ТабДок.Область(НомерСтроки, 3).Текст;
НоваяСтрокаТЗ.Количество = Число(СтрЗаменить(ЗначениеКол, Символы.НПП, ""));
ЗначениеЦена = ТабДок.Область(НомерСтроки, 4).Текст;
НоваяСтрокаТЗ.Цена = Число(СтрЗаменить(ЗначениеЦена, Символы.НПП, ""));
КонецЦикла;
Сообщить("Загрузка завершена. Обработано строк: " + ТаблицаДанных.Количество());
КонецПроцедуры
При работе с MXL в обычных формах следует учитывать несколько важных моментов:
Область().Текст всегда возвращает строку. Если в ячейках MXL содержатся числа, даты или ссылки, лучше пытаться получить их через свойство Область().Содержимое.Значение (если оно заполнено) или выполнять явное преобразование типов.Область() в больших циклах (более 10 000 строк) может работать медленно. В таких случаях старайтесь минимизировать количество обращений к объекту ТабличныйДокумент или предварительно выгружайте данные в массив.&НаКлиенте и &НаСервере внутри одной формы. Весь код работает в едином контексте, что значительно упрощает доступ к файловой системе пользователя.Таким образом, мы рассмотрели классический и наиболее эффективный способ загрузки данных из MXL для обычного приложения. Использование ДиалогВыбораФайла и ТабличныйДокумент позволяет реализовать задачу быстро и без ошибок, связанных с несовместимостью контекстов исполнения.