Имя: Пароль:
1C
1С v8
Подскажите оптимальный поиск по справочнику
0 cube033
 
23.11.12
12:57
Подскажите пожалуйста оптимальный поиск по справочнику
Цель проверить: есть ли в справочнике элемент с определенным наименованием, не являющийся группой. Если такого элемента нет - создать его. Если есть - записать в переменную как объект.
Вроде всё просто, но запутавшись в типах данных делал это целый день и пришел к громоздкому коду (работает):



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

.............................................

НовоеЗдание=СД.ПолучитьОбъект();
1 Нуф-Нуф
 
23.11.12
12:59
ухтыепт
2 kosts
 
23.11.12
12:59
(0) А зачем попытка?
3 Нуф-Нуф
 
23.11.12
12:59
кури ПОДОБНО
4 cube033
 
23.11.12
12:59
Попытка осталась со времён, когда код не работал)
5 kosts
 
23.11.12
13:00
В запрос можно добавить "Первые 1"
6 cube033
 
23.11.12
13:01
Да хотелось бы вообще без запроса
7 zbv
 
23.11.12
13:01
ВыборкаЗдания = Запрос.Выполнить().Выбрать();            
Если ВыборкаЗдания.Следующий() тогда
// по идее надо еще расмотреть ситуацию когда есть несколько позиций с одинаковым наименованием.
  НовоеЗдание = ВыборкаЗдания.Ссылка.ПолучитьОбъект();

Иначе
// тут создаем новый элемент.

КонецЕсли;
8 cube033
 
23.11.12
13:01
Типа НайденныеСтроки = ТаблицаДокумента_АРМ_ЛС.НайтиСтроки(Поиск);
9 rs_trade
 
23.11.12
13:01
(4) а попытка то не бесплатно работает. таки требует она доп. затрат.
10 kosts
 
23.11.12
13:03
(6) А смысл без запроса делать?
11 Heckfy
 
23.11.12
13:04
(6)
СправочникМенеджер.<Имя справочника>.НайтиПоРеквизиту (CatalogManager.<Имя справочника>.FindByAttribute)
СправочникМенеджер.<Имя справочника> (CatalogManager.<Имя справочника>)
НайтиПоРеквизиту (FindByAttribute)
Синтаксис:

НайтиПоРеквизиту(<ИмяРеквизита>, <ЗначениеРеквизита>, <Родитель>, <Владелец>)
Параметры:

<ИмяРеквизита> (обязательный)

Тип: Строка.
Имя реквизита, как он задан в конфигураторе, по значению которого осуществляется поиск. Тип значения произвольный, кроме ХранилищеЗначения и строк произвольной длины.
<ЗначениеРеквизита> (обязательный)

Тип: Произвольный.
Значение реквизита, по которому должен выполняться поиск.
<Родитель> (необязательный)

Тип: СправочникСсылка.
Родитель, в пределах которого нужно выполнять поиск. Если не указан, то поиск будет проводиться во всем справочнике.
<Владелец> (необязательный)

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

Тип: СправочникСсылка.
Ссылка на найденный элемент справочника. Если не существует ни одного элемента с требуемым значением реквизита, то будет возвращена пустая ссылка.
Описание:

Осуществляет поиск элемента по значению реквизита.

Доступность:

Сервер, толстый клиент, внешнее соединение.
Примечание:

Если существует несколько элементов с указанным значением реквизита, то будет найдет только один из них.
Для реквизитов типа Строка поиск осуществляется по точному соответствию.
Пример:

СтрокаНаименования = "Доллары США";
Валюты = Справочники.Валюты;
НайденнаяСсылка = Валюты.НайтиПоРеквизиту("ПолноеНаименование",
                                          СтрокаНаименования);
Если НайденнаяСсылка = Валюты.ПустаяСсылка() Тогда
   Сообщить("Валюты """ + СтрокаНаименования + """ еще нет.");
Иначе
   Сообщить("Нашли такую.");
КонецЕсли;
12 Heckfy
 
23.11.12
13:05
Сорри:

СправочникМенеджер.<Имя справочника> (CatalogManager.<Имя справочника>)
НайтиПоНаименованию (FindByDescription)
Синтаксис:

НайтиПоНаименованию(<Наименование>, <ТочноеСоответствие>, <Родитель>, <Владелец>)
Параметры:

<Наименование> (обязательный)

Тип: Строка.
Строка, содержащая искомое наименование.
<ТочноеСоответствие> (необязательный)

Тип: Булево.
Определяет режим поиска по полному соответствию.
Поиск будет успешным, если строка поиска: в случае значения параметра Ложь - будет соответствовать левой части наименования; в случае значения параметра Истина - будет полностью совпадать с наименованием (за исключением "хвостовых" пробелов в наименовании).
Значение по умолчанию: Ложь
<Родитель> (необязательный)

Тип: СправочникСсылка.
Родитель, в пределах которого нужно выполнять поиск. Если не указан, то поиск будет проводиться во всем справочнике.
<Владелец> (необязательный)

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

Тип: СправочникСсылка.<Имя справочника>; Неопределено.
Ссылка на найденный элемент справочника.
Если не существует ни одного элемента с требуемым наименованием, то будет возвращена пустая ссылка.
Если для справочника наименование не задано (длина = 0), то будет возвращено Неопределено.
Описание:

Осуществляет поиск элемента по его наименованию.

Доступность:

Сервер, толстый клиент, внешнее соединение.
Примечание:

Если существует несколько элементов с указанным наименованием, то будет найден только один из них.
Пример:

СтрокаНаименования = "USD";
Валюты = Справочники.Валюты;
НайденнаяСсылка = Валюты.НайтиПоНаименованию(СтрокаНаименования);
Если НайденнаяСсылка = Валюты.ПустаяСсылка() Тогда
   Сообщить("Валюты """ + СтрокаНаименования + """ еще нет");
КонецЕсли;
13 kosts
 
23.11.12
13:06

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

Если Выборка.Следующий() Тогда
   НовоеЗдание = Выборка.Ссылка.ПолучитьОбъект();
Иначе
   НовоеЗдание = Справочники.ФизическиеЛица.СоздатьЭлемент();
   НовоеЗдание.Наименование = Наименование;
   НовоеЗдание.Записать(); // <- Тут теоретически может не записаться
КонецЕсли;


Сегодня все добрые
14 cube033
 
23.11.12
13:06
ВыборкаЗдания = Запрос.Выполнить().Выбрать();            
Если ВыборкаЗдания.Следующий() тогда

Вот на эту конструкцию ругался конфигуратор - мол нет такого метода "следующий". Пока метод был Выбрать, а не выгрузить - вообще не работало


Основная беда в типах данных была,
что при одинаковом "Выборка=Запрос.Выполнить().Выбрать();"
в моём запросе было доступно "Выборка.Получить()", а в другом запросе "Выборка.ПолучитьОбъект()" - не могу понять.
15 cube033
 
23.11.12
13:08
НайтиПоНаименованию - первое что пробовал, но попадались группы
16 kosts
 
23.11.12
13:10
(14) Типы выборок разные
17 Alexperumov
 
23.11.12
13:10
(15) Ну добавь отсев по ЭтоГруппа
18 cube033
 
23.11.12
13:14
НайтиПоНаименованию(<Наименование>, <ТочноеСоответствие>, <Родитель>, <Владелец>) - не вижу - куда добавить отсев по ЭтоГруппа.
19 Heckfy
 
23.11.12
13:16
Поиск=НайтиПоНаименованию(<Наименование>, <ТочноеСоответствие>, <Родитель>, <Владелец>);
Если Поиск.ЭтоГруппа()=Истина Тогда
Иначе
КонецЕсли;
20 Reset
 
23.11.12
13:19
(19)
А если есть и группа и элемент с одинаковым наименованием?
Тогда уж (если без запроса) СпрМенеджер.Выбрать( с отбором по наименованию и перебирать выборку. Но лучше запросом
21 cube033
 
23.11.12
13:19
Мне в итоге нужно найти элемент, если он существует, в случае если группа и элемент будут иметь одинаковое наименование - не получиться, так как данный метод находит только первое значение из подобных.
22 Heckfy
 
23.11.12
13:21
(20) Запросом по любому лучше эту задачу решать.
23 Reset
 
23.11.12
13:21
(22) А я что сказал? :)
24 Heckfy
 
23.11.12
13:22
(23) А ТС хочет без запроса. :)
25 kosts
 
23.11.12
13:28
Задание такое без запроса, или так хочется?
26 cube033
 
23.11.12
13:31
"так хочется" - так как моментов подобных в процедуре встретиться около 5, каждый раз не хочется писать запрос.
Найти по наименованию гораздо короче, к тому же сейчас я указал параметр Истина для "точного поиска" - группы не находит.

Не могу понять - почему у меня не работает метод выбрать(), вместо выгрузить()
27 zbv
 
23.11.12
13:33
(26) код покажи где Выбрать() используешь.
28 cube033
 
23.11.12
13:33
вследствие нет метода Следующий() для  Выборка. Предлагает ВыбратьСтроку(), ВыбратьКолонку() итд как будто не тот тип переменной
29 cube033
 
23.11.12
13:34
Запрос = Новый Запрос;
   Запрос.Текст =
   "ВЫБРАТЬ
   |    Здания.Ссылка,
   |    Здания.Наименование
   |ИЗ
   |    Справочник.КВП_Здания КАК Здания
   |ГДЕ
   |    НЕ Здания.ЭтоГруппа
   |    И Здания.Наименование = &АдресСД";
               Запрос.УстановитьПараметр("АдресСД",АдресСД);
ВыборкаЗдания = Запрос.Выполнить().Выбрать();
30 Reset
 
23.11.12
13:35
В (29) не будет говорить (28)
31 cube033
 
23.11.12
13:35
Сейчас точнее скажу
32 cube033
 
23.11.12
13:41
Вспомнил (точнее попробовал снова)

ВыборкаЗдания = Запрос.Выполнить().Выбрать();

В данном случае ВыборкаЗдания - пустая переменная с правильным типом, при попытке показать значения в отладчике пишет:
Наименование - ошибка чтения значения
Ссылка       - ошибка чтения значения

только меняю Выбрать на выполнить - сразу работает
33 cube033
 
23.11.12
13:43
На счет правильного типа погорячился - тип прочитал не внимательно, но вроде правильный
34 kosts
 
23.11.12
13:44
(32) Выборка не позиционирована
35 cube033
 
23.11.12
13:46
Не сталкивался. Можно чуть больше теории?
36 kosts
 
23.11.12
13:49
(35) Для позиционирования на первой строке можно применить Выборка.Следующий()
37 kosts
 
23.11.12
13:50
Синтаксис:

Следующий()
Возвращаемое значение:

Тип: Булево. Истина - следующая запись выбрана; Ложь - достигнут конец выборки.
Описание:

Получает следующую запись из результата запроса. Для обхода результата запроса нужно после получения выборки вызвать данный метод для позиционирования на первый элемент и далее вызывать до тех пор, пока не будет возвращено значение Ложь.
38 cube033
 
23.11.12
13:55
Спасибо всем буду пробовать.