Здравствуйте, пытаюсь реализовать контроль уникальности наименования Справочника
Процедура проверяет на дубли и выводит предупреждение, но все равно остается возможность записи В чем ошибка?

```1c
    Процедура ПередЗаписью(Отказ, Элемент, Источник)
    Если ТипЗнч(Наименование) = Тип("Строка") Тогда
    Если Ссылка.Наименование <> Наименование Тогда
    Н = СправочникОбъект.Наименование;
    Если Не Справочники.ТМЦ.НайтиПоНаименованию(Н) = Справочники.ТМЦ.ПустаяСсылка() Тогда
    Текст = "ru = "Справочник не уникален!"";
    Предупреждение(НСтр(Текст), 10);
    Отказ = Истина;
    Возврат;
    КонецЕсли;
    КонецЕсли;
    КонецЕсли;
    КонецПроцедуры
```
---
Оказывается если сделать так, то все сработает:

```1c
    Процедура ПередЗаписью(Отказ,)
    Если Не Справочники.ТМЦ.НайтиПоНаименованию(Наименование) = Справочники.ТМЦ.ПустаяСсылка() Тогда
    Текст = "ru = "Наименование записи справочника не уникально!"";
    Предупреждение(НСтр(Текст), 10);
    Отказ = Истина;
    ЭтаФорма.Закрыть(Отказ);
    Возврат;
    КонецЕсли;
    КонецПроцедуры
```

Всем спасибо за участие в теме
---
В смысле "остается возможность записи"?
Если предупреждение выдало, то форма должна остаться открытой, а изменения не записанными (форма со звездочкой в заголовке).
При повторной попытке должно быть то же самое - выдать предупреждение и не записать.
А у вас что происходит?
---
Вот как раз при повторе все записывается, второй день голову ломаю
---
Предупреждение при повторе выдает?
---
нет
---
Значит, либо при повторе не срабатывает одно из условий (отладчиком ловите), либо повтор записи вызывается мимо стандартного интерактива.
Повтор вызывается повторным нажатием на кнопку записать? Или как-то иначе?
---
повторным нажатием
---
```1c
    Процедура ПередЗаписью(Отказ, Элемент, Источник)
    Если ОбменДанными.Загрузка = Истина Тогда
    Возврат;
    КонецЕсли;

    Если ТипЗнч(Наименование) = Тип("Строка") Тогда
    Если Ссылка.Наименование <> Наименование Тогда
    Н = СправочникОбъект.Наименование;
    Если Не Справочники.ТМЦ.НайтиПоНаименованию(Н) = Справочники.ТМЦ.ПустаяСсылка() Тогда
    Текст = "ru = "Справочник не уникален!"";
    Предупреждение(НСтр(Текст), 10);
    Отказ = Истина;
    //Возврат;
    КонецЕсли;
    КонецЕсли;
    КонецЕсли;
    КонецПроцедуры
```

попробуй так
---
спасибо, теперь при повторной записи выдает ошибку:

ОбщийМодуль.УникальностьТМЦ.Модуль(3)}: Значение не является значением объектного типа (Загрузка)
                   Если ОбменДанными.Загрузка = Истина Тогда
---
не заметил что есть объект потому и ругается
---
если убрать, при повторе так же записывает
полностью пустая база, обучалка
---
СправочникОбъект.ОбменДанными.Загрузка
---
У него в форме проверка. Нафига ему признак загрузки анализировать?
(25) С чего бы условие на равенство по индексированному полю вызвало жуткие тормоза, коллега?
---
У него в форме проверка в смысле в форме?
---
в смысле в форме?
См. (4)
---
"ПередЗаписью" откуда вызывается ?
---
в модуле формы в событии "ПередЗаписью"
---
А зачем вы сравниваете Наименование записываемого элемента с этим же элементом в БД? Просто сразу выполняйте проверку на поиск в справочнике по наименованию.
---
правильнее в модуле объекта
---
Пробовал и так, проблема та же
---
Что такое в вашем коде "СправочникОбъект"? Где и как "это" инициализируется?
Вопрос снимается. Уже забыл обычные формы :)
---
Меня смущает обращение к наименованию через СправочникОбъект. Пока не понимаю, как это может влиять, но давайте для начала упростим код и искать будем по полному совпадению:

```1c
    Процедура ПередЗаписью(Отказ, Элемент, Источник)
    Если ЗначениеЗаполнено(Справочники.ТМЦ.НайтиПоНаименованию(Наименование, Истина)) Тогда
    Отказ = Истина;
    Предупреждение(НСтр("ru = "Справочник не уникален!""), 10);
    КонецЕсли;
    КонецПроцедуры
```
---
все так же
---
А у тебя случайно нет реквизитов и переменных с именем "Наименование"? Чую, неспроста это обращение через СправочникОбъект. Явно каких-то костылей нагорожено.
---
По большому счету Справочник.Объект не влияет, можно сказать - это мои жалкие попытки реализовать процедуру, реквизитов нет, к примеру если все заменить на код как в (15) - обрабатывает с такой же проблемой. Справочник "толькочто" созданный. Вопрос почему код, грубо говоря игнорит, "Отказ = Истина"
---
Вопрос почему код, грубо говоря игнорит, "Отказ = Истина"
Не игнорит. С твоих слов выполнение вообще в эту ветку не попадает (не выдает предупреждение).
Если совсем печаль - запусти отладчик и поставь точку останова, уже советовал.
---
что за конфа то?
---
а покажи весь коддд
---
Короче, вот это должно работать как надо:

```1c
    Процедура ПередЗаписью(Отказ, Элемент, Источник)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ ПЕРВЫЕ 1
    | Номенклатура.Ссылка
    |ИЗ
    | Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    | Номенклатура.Ссылка <> &Ссылка
    | И Номенклатура.Наименование = &Наименование";
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    Запрос.УстановитьПараметр("Наименование", СправочникОбъект.Наименование);
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
    Сообщить("В базе уже есть элемент с указанным наименованием", СтатусСообщения.Важное);
    Отказ = Истина;
    КонецЕсли;

    КонецПроцедуры
```
---
|ГДЕ
    | Номенклатура.Ссылка <> &Ссылка
    | И Номенклатура.Наименование = &Наименование";
это ж жуткие тормоза, коллега
---
С чего это тормоза? Вполне нормальный запрос...
---
но если учесть ваше замечание и оптимизировать то можно вот так:

```1c
    Процедура ПередЗаписью(Отказ, Элемент, Источник)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ ПЕРВЫЕ 1
    | Номенклатура.Ссылка
    |ИЗ
    | Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    | И Номенклатура.Наименование = &Наименование";
    Запрос.УстановитьПараметр("Наименование", СправочникОбъект.Наименование);
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
    Если Выборка.Ссылка=Ссылка Тогда
    Возврат;
    КонецЕсли;
    Сообщить("В базе уже есть элемент с указанным наименованием", СтатусСообщения.Важное);
    Отказ = Истина;
    КонецЕсли;

    КонецПроцедуры
```
---
Ну вы тут проблему устроили из ничего )) в (23) точно должно работать, я бы туда добавил еще проверку на заполненность наименования, а то вдруг забыли его заполнить...
---
Вот так вот:

```1c
    Процедура ПередЗаписью(Отказ, Элемент, Источник)
    Если Не Справочники.ТМЦ.НайтиПоНаименованию(Объект.Наименование) = Справочники.ТМЦ.ПустаяСсылка() Тогда
    Текст = "ru = "Наименование записи справочника не уникально!"";
    Предупреждение(НСтр(Текст), 10);
    Отказ = Истина;
    Возврат;
    КонецЕсли;
    КонецПроцедуры
```
---
Можно ещё ЭтаФорма.Закрыть(Отказ); в конце, если не поможет. "Контрольный", так сказать... :-)
---
Проверка типов не нужна, поскольку источник не может быть неопределённым и наименование справочника всегда типа "Строка(150)".
---
То есть вот так вот прям точно всё станет срабатывать:

```1c
    Процедура ПередЗаписью(Отказ, Элемент, Источник)
    Если Не Справочники.ТМЦ.НайтиПоНаименованию(Объект.Наименование) = Справочники.ТМЦ.ПустаяСсылка() Тогда
    Текст = "ru = "Наименование записи справочника не уникально!"";
    Предупреждение(НСтр(Текст), 10);
    Отказ = Истина;
    ЭтаФорма.Закрыть(Отказ);
    Возврат;
    КонецЕсли;
    КонецПроцедуры
```
---
этот проверка только для новых корректна?
а что будет, если изменить не наименование, а другой реквизит. запишется?

(1) если sql, то я б решил все на стороне скуля созданием уникального индекса (первичного ключа) и без единой строки кода на стороне 1с. хотя это конечно не тру программирование, потом лицензии и все такое...
---
Сработает корректно и для новых, и для записанных элементов. Если изменится другой реквизит, запись пройдёт: мы ведь только наименование проверяем.
---
Не пройдет повторная запись, в справочнике элемент уже записан, значит НайтиПоНаименованию вернет непустую ссылку а значит отказ.
---
Тогда вываливается вот это :

```1c
    Значение не является значением объектного типа (Наименование)
    Если Не Справочники.ТМЦ.НайтиПоНаименованию(Объект.Наименование) = Справочники.ТМЦ.ПустаяСсылка() Тогда
```

Если убрать - не дает вообще возможность записи, даже с именем которое не используется
---
Раз ругается на Объект, значит он у Вас, видимо, типа "Управляемая форма", а не элемент справочника. К сожалению, сведений о конфигурации и варианте приложения Вы не предоставили, догадаться по коду не получается :-) Используйте "ЭтотОбъект", вместо "Объект".
---
Почему? нет, форма обычного приложения
---
Оказывается если сделать так, то все сработает:

```1c
    Процедура ПередЗаписью(Отказ,)
    Если Не Справочники.ТМЦ.НайтиПоНаименованию(Наименование) = Справочники.ТМЦ.ПустаяСсылка() Тогда
    Текст = "ru = "Наименование записи справочника не уникально!"";
    Предупреждение(НСтр(Текст), 10);
    Отказ = Истина;
    ЭтаФорма.Закрыть(Отказ);
    Возврат;
    КонецЕсли;
    КонецПроцедуры
```

Всем спасибо за участие в теме
---
Вы пробовали повторно записать уже ранее записанный элемент?
Как я понимаю при текущем коде он найдет сам себя и будет неприлично ругаться :)
---
Новый элемент от записанного отличается только неопределёнными значениями "Ссылка" и "ВерсияОбъекта".
---
Капец :-) А вы не хотите проверить объект на новый?
Короче

```1c
    Процедура ПередЗаписью(Отказ, Элемент, Источник)
    Если ЭтоНовый() Тогда // Для УФ Если Не Параметры.Ключ.Пустая() Тогда
    Если Не Справочники.ТМЦ.НайтиПоНаименованию(Объект.Наименование) .Пустая() Тогда
    Отказ = Истина;
    КонецЕсли;
    КонецЕсли;
    КонецПроцедуры;
```

(14)
(15)
(23)
---
Извините, но "капец" у Вас в коде: метод "ЭтоНовый()" не рекомендуется 1С-ой к использованию ;-)
---
А проверять, новый ли объект, 1С предлагает проверкой свойства "Ссылка" на равенство "Неопределено".
---
не нравится пишите запрос и в параметр ссылку
возврат истина или ложь и не тычте 1с-ом Вы сами па наименованию ищите
---
Опять же, проверять надо не только новые записи: мало ли, может наименование поменяют и получится дубль по наименованию, чего и хочет избежать автор.
---
это только для кода!
---
И к сведению "НайтиПоНаименованию" будет по скорости хуже чем запрос
---
А вопрос странный можно ? а нафига закрывать форму при ошибке ? И возврат зачем то запихнули...она и без возврата отработает...