Как правильно реализовать интерактивный выбор данных из справочника при создании документов в 1С 8.3

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия IT и автоматизация бизнеса
← На главную

При переходе с платформы 1С 7.7 на 1С 8.3 программисты часто сталкиваются с архитектурным барьером. В старой версии системы было привычным делом прервать выполнение кода на сервере, выбросить на экран модальное окно с вопросом Вопрос() или вызвать форму выбора справочника Выбрать() прямо внутри цикла загрузки. В современных управляемых формах 1С 8.3 такая логика не только считается «дурным тоном», но и технически невозможна в серверном контексте. Разберем по шагам, как переписать подобную загрузку по современным стандартам.

Почему старый подход больше не работает?

Проанализируем ситуацию: в 1С 8.3 (особенно в веб-клиенте и тонком клиенте) существует жесткое разделение на клиент и сервер. Серверный код не может открывать окна или взаимодействовать с пользователем. Кроме того, современные интерфейсы стремятся к асинхронности. Если вы запустите «бесконечный» цикл на сервере, который будет ждать ответа пользователя, вы заблокируете ресурсы системы. Поэтому современный стандарт разработки (согласно канонам БСП и платформы 8.3) требует разделения процесса на подготовку данных и их финальную запись.

Этап 1: Использование буферной таблицы на форме

Вместо того чтобы пытаться создать документ «на лету» во время чтения файла, мы создадим промежуточное звено. Рассмотрим алгоритм: сначала мы считываем данные из внешнего источника (Excel, CSV, XML) и помещаем их в Таблицу значений, которая отображается на управляемой форме обработки.

Это дает нам ряд преимуществ:

  1. Пользователь видит весь объем загружаемых данных до момента создания документов.
  2. Программа может заранее пометить проблемные строки.
  3. Пользователь может интерактивно дозаполнить недостающие данные.

Для этого создадим реквизит формы ДанныеЗагрузки с типом ТаблицаЗначений. Добавим в неё колонки: НаименованиеИзФайла, Контрагент (тип СправочникСсылка.Контрагенты), Статус (строка или число для индикации состояния).

Этап 2: Автоматическое сопоставление (Валидация)

После того как данные попали в таблицу на форме, необходимо выполнить серверную процедуру поиска соответствий. Разберем пример кода, который выполняет поиск контрагентов по ИНН или наименованию:


&НаСервере
Процедура СопоставитьДанныеНаСервере()
    Для Каждого СтрокаТЗ Из Объект.ДанныеЗагрузки Цикл
        // Сначала ищем по ИНН, так как это самый надежный идентификатор
        Если ЗначениеЗаполнено(СтрокаТЗ.ИНН) Тогда
            НайденныйСсылка = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", СтрокаТЗ.ИНН);
            Если Не НайденныйСсылка.Пустая() Тогда
                СтрокаТЗ.Контрагент = НайденныйСсылка;
                СтрокаТЗ.Статус = "Найден по ИНН";
                Продолжить;
            КонецЕсли;
        КонецЕсли;
        
        // Если по ИНН не нашли, пробуем по наименованию
        НайденныйСсылка = Справочники.Контрагенты.НайтиПоНаименованию(СтрокаТЗ.НаименованиеИзФайла, Истина);
        Если Не НайденныйСсылка.Пустая() Тогда
            СтрокаТЗ.Контрагент = НайденныйСсылка;
            СтрокаТЗ.Статус = "Сопоставлено по имени";
        Иначе
            СтрокаТЗ.Статус = "Контрагент не найден!";
            // Здесь мы ничего не открываем, просто помечаем строку для пользователя
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Этап 3: Интерактивное исправление ошибок пользователем

Теперь выясним, как заменить тот самый «Выбор из справочника». Когда процедура валидации завершена, пользователь видит в таблице строки, где колонка Контрагент пуста, а статус горит красным. В управляемых формах нам не нужно писать специальный код для вызова диалога выбора — достаточно того, что у колонки таблицы Контрагент установлен тип СправочникСсылка.Контрагенты.

Пользователь просто нажимает на кнопку выбора («...») в ячейке таблицы, и открывается стандартная форма выбора справочника. Это происходит интерактивно и асинхронно, не прерывая работу программы. После выбора значения пользователем, данные в строке таблицы обновляются.

Важный совет: Чтобы пользователю было удобнее, можно использовать условное оформление формы, чтобы подсвечивать строки с пустым контрагентом красным фоном.

Этап 4: Финальная загрузка документов

Только когда пользователь проверил все данные и заполнил пустые ячейки (сопоставил всех контрагентов), он нажимает кнопку «Загрузить». В этот момент программа проходит по уже полностью валидной таблице и создает документы без единого вопроса к пользователю.


&НаСервере
Процедура ВыполнитьЗагрузкуНаСервере()
    Для Каждого СтрокаТЗ Из Объект.ДанныеЗагрузки Цикл
        Если СтрокаТЗ.Контрагент.Пустая() Тогда
            // Если пользователь проигнорировал ошибку, пропускаем или выдаем сообщение
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = "Не выбран контрагент в строке с наименованием: " + СтрокаТЗ.НаименованиеИзФайла;
            Сообщение.Сообщить();
            Продолжить;
        КонецЕсли;
        
        // Создаем документ
        НовыйДок = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();
        НовыйДок.Дата = ТекущаяДата();
        НовыйДок.Контрагент = СтрокаТЗ.Контрагент;
        // Заполнение остальных реквизитов...
        НовыйДок.Записать(РежимЗаписиДокумента.Проведение);
    КонецЦикла;
КонецПроцедуры

Использование асинхронных вызовов (если выбор критичен внутри процесса)

Если специфика задачи всё же требует задать вопрос пользователю в процессе выполнения какой-то логики на клиенте, проанализируем механизм ОписаниеОповещения. В 1С 8.3 нельзя написать Если Вопрос(...) = КодВозвратаДиалога.Да Тогда. Нужно использовать следующий подход:


&НаКлиенте
Процедура НачатьОбработкуСтроки(ТекДанные)
    ПараметрыОповещения = Новый ОписаниеОповещения("ПослеВопросаОКонтрагенте", ЭтотОбъект, ТекДанные);
    ТекстВопроса = "Контрагент " + ТекДанные.Наименование + " не найден. Выбрать вручную?";
    ПоказатьВопрос(ПараметрыОповещения, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВопросаОКонтрагенте(Результат, ДополнительныеПараметры) Экспорт
    Если Результат = КодВозвратаДиалога.Да Тогда
        // Открываем форму выбора
        ПараметрыВыбора = Новый Структура("ВыборКонтрагента", Истина);
        ОписаниеВыбора = Новый ОписаниеОповещения("ПослеВыбораКонтрагента", ЭтотОбъект, ДополнительныеПараметры);
        ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыВыбора, ЭтотОбъект, , , , ОписаниеВыбора);
    КонецЕсли;
КонецПроцедуры

Как мы видим, код становится «разрывным». Каждое действие пользователя требует отдельной процедуры-обработчика. Именно поэтому использование буферной таблицы (как описано в этапе 1) является более предпочтительным, чистым и надежным методом разработки в системе 1С:Предприятие 8.3.

Резюме

Проанализировав переход с 7.7 на 8.3, можно выделить главное правило: массовая генерация объектов не должна прерываться диалогами. Подготовьте данные, дайте пользователю инструмент для их визуальной проверки и исправления, и только затем запускайте транзакцию создания документов. Это обеспечит стабильность работы системы и удобство для конечного пользователя.

← На главную