При работе в конфигурациях на обычных формах (например, «Управление торговлей 10.3») часто возникает задача автоматизации рутинного ввода данных. Типичный сценарий: у компании есть обработка для парсинга прайс-листов или накладных из Excel, которая создает новый документ и заполняет его. Однако пользователям гораздо удобнее открыть уже существующий или только что созданный (но еще не сохраненный) документ, нажать кнопку и импортировать строки непосредственно в текущую экранную форму.
В этой статье мы подробно разберем, как реализовать такую возможность, проанализируем распространенные архитектурные ошибки разработчиков и рассмотрим два наиболее эффективных способа решения задачи: создание внешней обработки заполнения табличной части и встраивание кнопки напрямую в форму документа.
В процессе обсуждения на форумах часто предлагают решения, связанные с передачей ссылки на документ в обработку загрузки. Например, код вида:
Форма = ОткрытьФорму("Обработка.ЗагрузкаДанныхИзТабличногоДокумента.Форма");
Форма.ЭтотОбъект.СсылкаИсточника = ЭтаФорма.ЭтотОбъект.Ссылка;
Этот подход содержит две серьезные проблемы, которые могут привести к нестабильной работе системы и недовольству пользователей:
ЭтотОбъект.Ссылка вернет пустую ссылку (ДокументСсылка.Пустая()). В результате обработка не сможет определить документ-источник и выдаст ошибку.Записать(), то в базе данных сохраняется новая версия объекта. При этом у пользователя на экране остается открытой старая копия данных. При попытке пользователя нажать «Записать» или «Провести» на форме документа, платформа 1С выдаст критическую ошибку: «Данные были изменены или удалены другим пользователем».Чтобы избежать этих проблем, необходимо передавать в обработку не ссылку на запись в базе данных (ДокументСсылка), а ссылку на сам объект в оперативной памяти компьютера (ДокументОбъект), связанный с текущей открытой формой.
Это наиболее изящный способ, соответствующий стандартам разработки фирмы «1С». Он позволяет решить задачу вообще без изменения конфигурации. База данных останется на полной поддержке, а у пользователя над табличной частью автоматически появится стандартная кнопка «Заполнить».
Рассмотрим пошагово процесс создания такой обработки:
Шаг 1. Создание обработки в конфигураторе. Создайте новую внешнюю обработку. В модуле объекта этой обработки обязательно должна быть объявлена экспортная процедура Инициализировать. Напишем ее код:
Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПоле) Экспорт
// Параметр "Объект" — это и есть ДокументОбъект, открытый на экране у пользователя.
// ИмяТабличнойЧасти — строковое имя заполняемой ТЧ (например, "Товары").
// Получаем форму нашей обработки
ФормаЗагрузки = ПолучитьФорму("Форма");
// Передаем контекст документа напрямую в свойства формы обработки
ФормаЗагрузки.ДокументОбъект = Объект;
ФормаЗагрузки.ИмяТабличнойЧасти = ИмяТабличнойЧасти;
// Открываем форму обработки модально
ФормаЗагрузки.ОткрытьМодально();
КонецПроцедуры
Шаг 2. Настройка формы обработки. В форме создаваемой обработки загрузки в самом верху модуля (в разделе объявления переменных) пропишите экспортные переменные для приема переданных параметров:
Перем ДокументОбъект Экспорт;
Перем ИмяТабличнойЧасти Экспорт;
Теперь напишем алгоритм чтения файла Excel и заполнения строк. Для этого лучше использовать стандартный объект 1С ТабличныйДокумент, который умеет читать файлы .xls и .xlsx напрямую, не требуя установленного пакета Microsoft Office на компьютере пользователя:
Процедура КнопкаВыполнитьНажатие(Кнопка)
// Проверим, переданы ли нам данные документа
Если ДокументОбъект = Неопределено Тогда
Предупреждение("Обработка запущена в автономном режиме. Заполнение невозможно.");
Возврат;
КонецЕсли;
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ПутьКФайлу);
Исключение
Предупреждение("Не удалось прочитать файл Excel! " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Начинаем обход строк таблицы Excel со второй строки (пропуская шапку)
Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
НаименованиеТовара = СокрЛП(ТабДок.Область(НомерСтроки, 1).Текст);
Если ПустаяСтрока(НаименованиеТовара) Тогда
Продолжить; // Пропускаем пустые строки
КонецЕсли;
Количество = Число(ТабДок.Область(НомерСтроки, 2).Текст);
Цена = Число(ТабДок.Область(НомерСтроки, 3).Текст);
// Поиск номенклатуры в справочнике
НайденнаяНоменклатура = Справочники.Номенклатура.НайтиПоНаименованию(НаименованиеТовара, Истина);
Если НайденнаяНоменклатура.Пустая() Тогда
Сообщить("Товар не найден в базе данных: " + НаименованиеТовара, СтатусСообщения.Внимание);
Продолжить;
КонецЕсли;
// Добавляем строку непосредственно в переданный нам объект в памяти
НоваяСтрока = ДокументОбъект[ИмяТабличнойЧасти].Добавить();
НоваяСтрока.Номенклатура = НайденнаяНоменклатура;
НоваяСтрока.Количество = Количество;
НоваяСтрока.Цена = Цена;
НоваяСтрока.Сумма = Количество * Цена;
// Для УТ 10.3 важно также заполнить базовые реквизиты единицы измерения
НоваяСтрока.ЕдиницаИзмерения = НайденнаяНоменклатура.ЕдиницаХраненияОстатков;
НоваяСтрока.Коэффициент = НайденнаяНоменклатура.ЕдиницаХраненияОстатков.Коэффициент;
КонецЦикла;
// Закрываем форму обработки после успешного завершения
Закрыть();
КонецПроцедуры
Шаг 3. Подключение обработки в режиме Предприятия. Запустите 1С в режиме предприятия. Перейдите в меню Сервис — Дополнительные отчеты и обработки — Дополнительные внешние обработки табличных частей. Добавьте созданный файл обработки, укажите в таблице принадлежности документ «Поступление товаров и услуг» и табличную часть «Товары». После этого в документе над списком товаров появится кнопка «Заполнить».
Если бизнес-требования предписывают жесткое наличие индивидуальной кнопки «Загрузить из Excel» прямо в интерфейсе формы документа, выполните следующие действия:
Шаг 1. Размещение кнопки. Откройте форму документа «Поступление товаров услуг» в конфигураторе, добавьте новую кнопку и в ее событии Нажатие пропишите следующий код:
Процедура ДействиеКнопкиИмпортExcel(Кнопка)
// Получаем внешнюю или внутреннюю обработку
ОбработкаОбъект = Обработки.ЗагрузкаДанныхИзФайлаXLS.Создать();
ФормаЗагрузки = ОбработкаОбъект.ПолучитьФорму("Форма");
// Передаем ссылку на текущую форму (контекст выполнения)
ФормаЗагрузки.ДокументОбъект = ЭтотОбъект;
ФормаЗагрузки.ИмяТабличнойЧасти = "Товары";
ФормаЗагрузки.ОткрытьМодально();
КонецПроцедуры
Шаг 2. Прием данных в обработке. На стороне формы обработки логика остается точно такой же, как в первом способе. Поскольку мы передали переменную ЭтотОбъект (которая содержит живой дескриптор открытого документа в памяти), все строки, добавленные внутри обработки, мгновенно отобразятся на экране пользователя сразу после закрытия модального окна. Пользователь сможет визуально перепроверить строки и самостоятельно нажать кнопку «ОК» или «Записать» на форме документа.
На форумах часто советуют использовать стандартную обработку с диска ИТС ЗагрузкаДанныхИзТабличногоДокумента.epf. Она действительно очень гибкая и универсальная, однако имеет свою специфику:
Поэтому для повседневной работы пользователей гораздо эффективнее написать простую специализированную обработку парсинга Excel с использованием объектной модели 1С, как это показано в примерах выше. Это сбережет нервы пользователям и исключит ошибки версионирования объектов в многопользовательском режиме.