При работе с классическими конфигурациями 1С, такими как Комплексная автоматизация 1.1 или Управление производственным предприятием 1.3, разработчики часто сталкиваются с необходимостью автоматизации заполнения табличных частей (ТЧ) документов. Несмотря на то что эти системы считаются «антиквариатом», механизмы их расширения через внешние обработки остаются мощным инструментом. Разберем подробнее, как устроена работа таких обработок, почему возникают задержки при выполнении кода и как правильно организовать взаимодействие между формой обработки и документом.
Для начала проанализируем, как система вызывает внешнюю обработку заполнения. В обычных формах кнопка «Заполнить», расположенная над табличной частью, обращается к справочнику ВнешниеОбработки. Когда пользователь выбирает нужный пункт, система создает объект обработки и ищет в его модуле экспортную процедуру Инициализировать.
Рассмотрим типовую структуру этой процедуры:
Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПолеОбъекта) Экспорт
// Объект — это сам документ (или его копия в памяти)
// ИмяТабличнойЧасти — строка с именем ТЧ (например, "Товары")
// ТабличноеПолеОбъекта — элемент управления формы документа
// Здесь обычно открывается форма обработки для настройки параметров
Форма = ПолучитьФорму("Форма");
Форма.ОткрытьМодально();
// ВНИМАНИЕ: код ниже выполнится только ПОСЛЕ закрытия формы
ЗаполнитьТабличнуюЧасть(Объект, ИмяТабличнойЧасти);
КонецПроцедуры
Выясним причину основной проблемы: почему данные переносятся в документ только после закрытия окна обработки? Все дело в методе ОткрытьМодально(). Этот метод полностью останавливает поток выполнения кода в модуле объекта до тех пор, пока пользователь не закроет форму. Это и создает иллюзию того, что процедура «срабатывает на закрытие», хотя на самом деле она просто «просыпается» после него.
Проанализируем ситуацию: если нам нужно, чтобы данные загружались из Excel и сразу отображались в документе без закрытия формы обработки, нам следует изменить архитектуру решения. Вместо того чтобы ждать завершения работы формы в модуле объекта, мы можем делегировать управление самой форме.
Рассмотрим пошагово правильный алгоритм реализации:
Инициализировать мы создаем форму, но передаем ей ссылку на документ-владелец или сам объект.Посмотрим на пример реализации процедуры Инициализировать, которая передает параметры в форму:
Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПолеОбъекта) Экспорт
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ДокументОбъект", Объект);
ПараметрыФормы.Вставить("ИмяТЧ", ИмяТабличнойЧасти);
Форма = ПолучитьФорму("Форма", ПараметрыФормы);
Форма.Открыть(); // Используем обычное открытие, если не нужна модальность
КонецПроцедуры
Теперь разберем, как в модуле формы обработки принять эти данные и использовать их. В процедуре ПриОткрытии мы можем считать переданные параметры:
Перем мДокументОбъект;
Перем мИмяТЧ;
Процедура ПриОткрытии()
Если ТипЗнч(Параметры) = Тип("Структура") Тогда
Параметры.Свойство("ДокументОбъект", мДокументОбъект);
Параметры.Свойство("ИмяТЧ", мИмяТЧ);
КонецЕсли;
КонецПроцедуры
Когда пользователь нажимает кнопку «Перенести» на форме обработки (например, после загрузки данных из Excel в промежуточную таблицу на форме), выполняется следующий код:
Процедура КнопкаПеренестиНажатие(Кнопка)
ТЧ_Документа = мДокументОбъект[мИмяТЧ];
// Очищаем ТЧ документа, если это необходимо
ТЧ_Документа.Очистить();
Для Каждого СтрокаИзExcel Из ТаблицаНаФорме Цикл
НоваяСтрока = ТЧ_Документа.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИзExcel);
КонецЦикла;
// Оповещаем форму документа о том, что данные изменились
ОповеститьОбИзменении(мДокументОбъект);
// Если нужно закрыть форму после переноса:
// ЭтаФорма.Закрыть();
КонецПроцедуры
Часто заполнение ТЧ связано с чтением внешних файлов. Проанализируем важный технический нюанс: при работе с COMОбъект("Excel.Application") крайне важно корректно завершать процесс. Если логика загрузки прерывается или форма закрывается с ошибкой, процесс excel.exe может остаться в памяти сервера или клиентской машины.
Рекомендуем всегда использовать блок Попытка...Исключение при работе с внешними компонентами:
Попытка
Эксель = Новый COMОбъект("Excel.Application");
Книга = Эксель.Workbooks.Open(ПутьКФайлу);
// ... логика чтения ...
Исключение
Сообщить("Ошибка при работе с Excel: " + ОписаниеОшибки());
Если Эксель <> Неопределено Тогда
Эксель.Quit();
КонецЕсли;
КонецПопытки;
Если вы все же решили оставить часть кода в процедуре Инициализировать в модуле объекта, но хотите управлять его выполнением из формы, используйте переменные состояния. Например, в форме обработки можно определить переменную ПереносВыполнен. В процедуре Инициализировать после закрытия формы проверяйте это свойство:
Форма = ПолучитьФорму("Форма");
Форма.ОткрытьМодально();
Если Форма.ПереносВыполнен Тогда
// Выполняем финальные действия, если кнопка "Перенести" была нажата
КонецЕсли;
Однако, как показывает практика и советы опытных разработчиков, наиболее чистым и управляемым подходом является полное исключение тяжелой логики из процедуры Инициализировать. Рассмотрим это как «точку входа», которая лишь инициализирует интерфейс, а всю содержательную работу (чтение файлов, расчеты, заполнение строк) переносит в специализированные методы формы обработки.
Таким образом, мы выяснили причину странного поведения внешней обработки в КА 1.1 и разобрали архитектурно правильный способ реализации заполнения табличных частей. Использование прямого управления объектом документа через параметры формы позволяет сделать процесс интерактивным и удобным для пользователя.