При разработке обработок в среде 1С:Предприятие 8.3 (Управляемое приложение) начинающие разработчики часто сталкиваются с ошибкой «Интерактивные операции недоступны». Рассмотрим ситуацию: необходимо программно заполнить штрихкоды для справочника серийных номеров в конфигурации «Розница 2.3». Попытка сделать это через получение формы элемента приводит к аварийному завершению работы кода. Проанализируем ситуацию и выясним, как правильно реализовать эту задачу.
Разберем причину возникновения ошибки по шагам. В управляемом приложении существует жесткое разделение между клиентом и сервером. На сервере выполняется вся работа с базой данных, расчетами и выборками. Однако сервер «ничего не знает» об интерфейсе пользователя. Он не может открывать окна, показывать сообщения или манипулировать формами.
Когда мы вызываем метод ПолучитьФорму() внутри процедуры с директивой компиляции &НаСервере, платформа блокирует выполнение, так как создание визуального объекта (формы) — это интерактивная операция, требующая участия клиентского сеанса. Попытка изменить реквизит Форма.Штрихкод на сервере также обречена на провал, так как объект формы в этом контексте либо недоступен, либо его программная оболочка не связана с реальным отображением данных.
В типовых решениях, таких как «1С:Розница 2.3», штрихкод практически никогда не является реквизитом самого справочника (номенклатуры или серийных номеров). Это реквизит формы, который заполняется динамически при открытии. Сами же данные хранятся в специальном Регистре сведений «Штрихкоды».
Проанализируем пункты, которые необходимо проверить перед написанием кода:
СерийныеНомера нет реквизита Штрихкод, значит, запись в объект справочника ничего не даст.Рассмотрим, как должен выглядеть корректный код для массового заполнения штрихкодов. Вместо того чтобы пытаться «проэмулировать» работу пользователя с формой, мы обратимся напрямую к таблицам базы данных.
Выясним, как создать запись в регистре сведений для каждого серийного номера. Нам понадобится использовать объект РегистрСведенийМенеджерЗаписи.
&НаСервере
Процедура ЗаполнитьШтрихкодыНаСервере()
// Выбираем все серийные номера
Выборка = Справочники.СерийныеНомера.Выбрать();
Пока Выборка.Следующий() Цикл
// Штрихкоды в Рознице 2.3 хранятся в регистре сведений
// Обычно он называется "Штрихкоды"
МенеджерЗаписи = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи();
// Устанавливаем измерения (кто владелец и какой код)
МенеджерЗаписи.Штрихкод = Выборка.КодСерийногоНомера;
МенеджерЗаписи.Владелец = Выборка.Ссылка;
// Устанавливаем тип штрихкода (например, EAN13)
// Типы обычно хранятся в Планах Видов Характеристик
МенеджерЗаписи.ТипШтрихкода = ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
// Пытаемся записать. Если такой штрихкод уже есть,
// метод выдаст ошибку, поэтому можно использовать попытку
Попытка
МенеджерЗаписи.Записать(Истина); // Истина означает замещение существующей записи
Исключение
ЗаписьЖурналаРегистрации("ОшибкаЗаписиШтрихкода", УровеньЖурналаРегистрации.Ошибка,,,
"Не удалось записать штрихкод для: " + Выборка.Ссылка);
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Использование метода Выбрать() для всего справочника — не самый эффективный путь, особенно если база данных большая. Рассмотрим подробнее, как оптимизировать этот процесс с помощью запроса. Это позволит нам отобрать только те серийные номера, у которых уже заполнен код, но еще нет записи в регистре штрихкодов.
&НаСервере
Процедура ОптимизированноеЗаполнениеНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СерийныеНомера.Ссылка КАК Ссылка,
| СерийныеНомера.КодСерийногоНомера КАК Код
|ИЗ
| Справочник.СерийныеНомера КАК СерийныеНомера
|ГДЕ
| СерийныеНомера.КодСерийногоНомера <> """"";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
ТипEAN13 = ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
Пока Выборка.Следующий() Цикл
// Используем набор записей для проверки существования
Набор = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();
Набор.Отбор.Штрихкод.Установить(Выборка.Код);
Набор.Прочитать();
Если Набор.Количество() = 0 Тогда
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Штрихкод = Выборка.Код;
НоваяЗапись.Владелец = Выборка.Ссылка;
НоваяЗапись.ТипШтрихкода = ТипEAN13;
Набор.Записать();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Проанализируем ситуацию с точки зрения безопасности данных. При массовом изменении информации в справочниках и регистрах необходимо придерживаться следующих правил:
КодСерийногоНомера соответствует стандарту выбранного типа (например, 13 цифр для EAN13). Если данные не валидны, типовые механизмы печати этикеток могут не сработать.Таким образом, мы выяснили, что ошибка «Интерактивные операции недоступны» — это сигнал о том, что архитектура кода нарушает правила взаимодействия клиента и сервера. Вместо манипуляций с формами на сервере следует использовать прямую запись в соответствующие объекты метаданных — в данном случае в регистры сведений.