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

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

При разработке и доработке управляемых форм в 1С начинающие разработчики часто сталкиваются с ситуацией, когда условие проверки значения реквизита не срабатывает, либо код вызывает ошибки времени выполнения. Разберем по шагам типичные ошибки, возникающие при сравнении договора контрагента со строковыми значениями, выясним причину их появления и рассмотрим правильные варианты реализации логики.

Анализ основных ошибок при работе с реквизитами на управляемой форме

Рассмотрим распространенные ошибки, которые допускаются при попытке сопоставить ссылочное поле с текстовым значением:

  1. Сравнение ссылки со строковым литералом: реквизит Объект.ДоговорКонтрагента содержит значение ссылочного типа (СправочникСсылка.ДоговорыКонтрагентов), а не текст. Конструкция вида Если Объект.ДоговорКонтрагента = "Договор № 61" всегда возвращает Ложь, так как типы данных не совпадают.
  2. Попытка получения реквизитов через точку на клиенте: в режиме тонкого клиента обращение к реквизитам ссылочного объекта через точку (например, Объект.ДоговорКонтрагента.Код или Объект.ДоговорКонтрагента.Наименование) вызывает ошибку «Поле объекта не обнаружено», так как на клиенте ссылка не содержит данных самого объекта.
  3. Обращение к менеджерам справочников на клиенте: глобальная коллекция Справочники доступна только на стороне сервера. При вызове Справочники.ДоговорыКонтрагентов.НайтиПоНаименованию(...) в процедуре с директивой &НаКлиенте платформа выдает ошибку «Переменная не определена (Справочники)».
  4. Присвоение строки ссылочному реквизиту: попытка записать строку в реквизит шапки Объект.БанковскийСчетОрганизации приводит к тому, что поле очищается платформой, поскольку строковое значение не может быть преобразовано в ссылку справочника банковских счетов.

Вариант 1. Проверка наименования на сервере

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


&НаКлиенте
Процедура ДоговорКонтрагентаПриИзменении(Элемент)
    ДоговорКонтрагентаПриИзмененииНаСервере();
КонецПроцедуры

&НаСервере
Процедура ДоговорКонтрагентаПриИзмененииНаСервере()
    Если Не ЗначениеЗаполнено(Объект.ДоговорКонтрагента) Тогда
        Возврат;
    КонецЕсли;

    // На сервере обращение через точку к реквизитам ссылки допустимо
    Если Объект.ДоговорКонтрагента.Наименование = "Договор № 61/ВЭ от 10.07.2017" Тогда
        // Устанавливаем соответствующий банковский счет
        УстановитьБанковскийСчетПоУмолчанию();
    КонецЕсли;
КонецПроцедуры

Вариант 2. Поиск ссылки на сервере и точное сравнение

В случаях, когда выполняется поиск конкретного элемента через менеджер справочника, важно сравнивать полученную ссылку со ссылкой в документе, а не с текстом. Проанализируем правильный пример:


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

Особенности установки банковского счета организации

Справочник банковских счетов является подчиненным (владельцем выступает организация или контрагент). Если выполнять поиск по наименованию без указания владельца, метод НайтиПоНаименованию вернет пустую ссылку, из-за чего реквизит документа очистится. Кроме того, наименование счета в базе данных (например, «Расчетный в рублях») часто не совпадает с наименованием самого банка.

Посмотрим на корректный поиск банковского счета с явным указанием владельца:


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

Рекомендации по архитектуре и отказу от жесткого кодирования

Рассмотрим, почему «зашивать» конкретные наименования и коды в программный код не рекомендуется, и какие альтернативы следует использовать:

  1. Типовой механизм договора: в типовых конфигурациях 1С в карточке договора контрагента предусмотрен реквизит для указания банковского счета организации. При выборе такого договора типовой функционал автоматически подставляет связанный счет без необходимости ручной модификации кода.
  2. Использование дополнительных реквизитов: создание дополнительного реквизита или непериодического регистра сведений позволяет настраивать соответствия между договорами и счетами в режиме «1С:Предприятие» без вмешательства в конфигуратор.
  3. Поиск по уникальному идентификатору (GUID): если привязка к конкретному предопределенному элементу базы неизбежна, обращение по строке наименования ненадежно (пользователи могут отредактировать название). Надежнее использовать метод получения ссылки по GUID: Справочники.БанковскиеСчетаОрганизаций.ПолучитьСсылку(Новый УникальныйИдентификатор("...")).
← На главную