Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Поиск в справочнике  (Прочитано 22723 раз)
0 Пользователей и 1 Гость смотрят эту тему.
schnibbl
Гость
« : 24-02-2005 07:48 » 

Всем привет, проблема такого толка:
нужно найти элемент справочника, можно так:
пока справочник.получитьЭлемент() = 1 поехали - и впринципе тогда проблем нет отследить в какой группе найденый элемент находится и обхватываем весь справочник.....(вопрос есть только тупой перебор или существуют методы сортировки ?) а можно с помощью метода НайтиПоКоду()/ПоНаименованию. Нахожу этими вещами элемент в справочнике, далее стоит вопрос как узнать в какой группе он находится ? и главное в справочнике существует несколько элементов в разных группах с одинаковыми например наименованиями при методе НайтиПоХХХ, находит первый попавшийся и на этом успокаивается,хотя флаг ставлю "0 - поиск во всем справочнике вне зависимости от родителя" , как заставить искать далее ?
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 25-02-2005 17:00 » 

Цитата
как узнать в какой группе он находится
Спр.Родитель; Спр.ПолныйКод(); Спр.ПолноеНаименование();
Цитата
хотя флаг ставлю "0 - поиск во всем справочнике вне зависимости от родителя"
Этот флаг влияет на результат поиска таким образом, что если у тебя указано Спр.ИспользоватьРодителя(Родитель);,
флаг сброшен и нету элемента который ты ищешь в этой группе - НайтиПоХХХ() вернет 0,
а если установлен - найдет просто в другой группе
Цитата
находит первый попавшийся и на этом успокаивается,...  как заставить искать далее
Тут к сожалению без перебора не обойдешься, но его можно несколько ускорить (не доходя до конца списка). Делаем так:
Код:
Спр=СоздатьОбъект("Справочник.ВидСправочника");
Спр.ПорядокКодов(); // Спр.ПорядокНаименований();
Найдено=0;
Спр.ВыбратьЭлементы(0); // Без учета иерархии, например - для подчиненных
Пока Спр.ПолучитьЭлемент(1)=1 Цикл // выбираем все элементы
Если Спр.Код<>КодИщем Тогда // Если Спр.Наименование<>НаимИщем Тогда
Если Найдено=0 Тогда Продолжить; КонецЕсли; // еще не дошли
Прервать; // уже пошли новые
КонецЕсли;
Найдено=1;

// Вот здесь получаем все элементы, которые хотим
Сообщить(""+Спр.Код+" "+Спр.Наименование);
КонецЦикла;
Записан
schnibbl
Гость
« Ответ #2 : 28-02-2005 13:08 » 

по поводу первых двух цитат спасибо, а с кодом, щас помазгую, подумаю Улыбаюсь. Тут кстати мне еще посоветовали Запросами обойтись, вот заодно и их почитаю.
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 28-02-2005 13:36 » 

Ага. Про запрос совсем забыл Жаль (редко ими пользуюсь)
Код:
ИщемКод="Код";
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"Код = Справочник.КодыТоваров.Код;
|Группировка Код;
|Условие(Код=ИщемКод);
|";
// Если ошибка в запросе, то выход из процедуры
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда Возврат; КонецЕсли;

Пока Запрос.Группировка(1) = 1 Цикл
// Заполнение полей Код
КонецЦикла;
Записан
schnibbl
Гость
« Ответ #4 : 28-02-2005 13:40 » 

Если справочники немеренно толстенные, будет ли находиться быстрее с помощью запросов или там такая же технология поиска что разници во времени между перебором и запросом нету ?
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 28-02-2005 14:59 » 

Точно не знаю. Сильно зависит не только от размеров, но и от "похожести" названий/кодов по которым ищешь. По идее - запросом должно быть быстрее на больших справочниках
Проверь сам - кода вроде немного для этого надо...
Записан
schnibbl
Гость
« Ответ #6 : 01-03-2005 15:16 » 

В продолжении истории, может подскажет кто как заставить следующую конструкцию работать:
Н_Реквизит="""Адрес"""
Справочник.ПолучитьАтрибут(Н_Реквизит)
Тоесть поиск может осуществляться по любому реквизиту, и естественно алгоритм поиска один и тотже, и как тогда получив от пользователся в виде текста имя реквизита (реально существующего), подставить это имя в функции по работе с справочниками, получается использование переменной не по имени а по значению... и вообще можно ли так сделать, а то несколько раз копировать один и тот же цикл поиска из-за того что пользователь может не помнить значение 1 реквизита, но точно знает значение другого, как-то глупо..
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 12-03-2005 10:19 » 

1. Пользователя лучше не просить ввести имя реквизита, а выбрать его из выпадающего списка (Поле со списком, идентификатор спРекв), при этом заполним его реквизитами из метеданных (например в процедуре при открытии):
Код:
спРекв.УдалитьВсе();
МетаСпр=Метаданные.Справочник("НазваниеСправочника");
Если МетаСпр.ДлинаКода>0 Тогда
спРекв.ДобавитьЗначение("Код"," Код");
КонецЕсли;
Если МетаСпр.ДлинаНаименования>0 Тогда
спРекв.ДобавитьЗначение("Наименование"," Наименование");
КонецЕсли;
Для И1=1 По МетаСпр.Реквизит() Цикл
МетаРекв=МетаСпр.Реквизит(И1);
спРекв.ДобавитьЗначение(МетаРекв.Идентификатор, Строка(МетаРекв));
КонецЦикла;
спРекв.Сортировать();
спРекв.ТекущаяСтрока(1);
2. Формируем текст запроса используя Шаблон():
Код:
Рекв=спРекв.ПолучитьЗначение(спРекв.ТекущаяСтрока());
ТекстЗапроса =Шаблон(
"Рекв = Справочник.НазваниеСправочника.[Рекв];
|Группировка Рекв;
|Условие(Рекв=ИщемРекв);
|");
Далее - по тексту.
Домашнее задание: проверить, как это будет работать с периодическими реквизитами
Записан
schnibbl
Гость
« Ответ #8 : 01-04-2005 09:50 » 

еще один вопросик по обычным методам справочника. Тут такое дело справочник разбит на очень много групп, номера элементов и групп не уникальные, таким образом имеем допустим в 3 вложенности две одинаковые группы с повторяющимся элементом. Существуют ли способ однозначно определить именно тот элемент который нужен (группаХ/группа/наименование а не группаУ/группа/наименование) кроме полного перебора справочника с использованием справочник.ПолноеНаименование() ?
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 02-04-2005 08:19 » 

Однозначно определить - это найти?
Вариант 1: НайтиПоКоду(<Код>,<ФлагПоиска>)
<ФлагПоиска> - флаг поиска (необязателен):
  ...
  2 - поиск по полному коду через разделитель.

Вариант 2: ЗначениеВСтрокуВнутр() - преобразовывает объект в строку, уникальную (в пределах данной базы)
ЗначениеИзСтрокиВнутр() - обратное преобразование из строки, полученной пред. функцией к объекту БД (документ, элемент справочника, перечисление, ...)
Записан
schnibbl
Гость
« Ответ #10 : 03-05-2005 07:00 » 

дальше задачка Улыбаюсь
Имеем в справочнике много групп. нужно искать только в нужных группах (на одной глубине) .
ТОесть имеем:
здания/памятники/ыфывыв/фывфыв
здания/не памятники/фывфвыф/фвыфыв
здания/архив/фывфвыф/фвыфыв
здания/еще чего нить/фываываыва/фывафыва
Если бы мы искали только в группе памятники мы бы сделали так:
       флаг=0;
       СОС=СоздатьОбъект("Справочник.ОсновныеСредства");
    флаг=СОС.НайтиПоНаименованию("памятники",0);
    Если флаг = 1 Тогда
      флаг=СОС.ЭтоГруппа(); 
    КонецЕсли;
   Если флаг=0 тогда Предупреждение("Не найдена группа ""Памятники"""); возврат; конецЕсли;
   СОС.ИспользоватьРодителя(СОС,0);
   СОС.ВыбратьЭлементы(1);
Теперь усложняем задачу нам нужно выбрать элементы из группы Памятники и Не памятники, а все остальные откинуть Не понял?
как такое устроить за 1 проход ? (нечто вроде сложения множеств).
« Последнее редактирование: 03-05-2005 07:02 от schnibbl » Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 04-05-2005 12:17 » 

А что в твоем понимании значит "за один проход"?
Я решал бы этот вопрос так:
Код:
ИскатьВГруппах="Памятники, Не памятники";
Пока ПустаяСтрока(ИскатьВГруппах)=0 Цикл
Спр=СоздатьОбъект("Справочник.ОсновныеСредства");

// Выделяем следующую группу из строки
Поз=Найти(ИскатьВГруппах, ",");
Если Поз>0 Тогда
ТекГруппа=СокрЛП(Лев(ИскатьВГруппах, Поз-1));
ИскатьВГруппах=Сред(ИскатьВГруппах,Поз+1);
Иначе
ТекГруппа=СокрЛП(ИскатьВГруппах);
ИскатьВГруппах="";
КонецЕсли;

// Ищем группу в справочнике
Если Спр.НайтиПоНаименованию(ТекГруппа, 0, 1)=0 Тогда
Сообщить("Не найдена группа: "+ТекГруппа,"!");
Продолжить;
КонецЕсли;
Если Спр.ЭтоГруппа()=0 Тогда
Сообщить("Элемент не является группой: "+Спр.ТекущийЭлемент(),"!");
Продолжить;
КонецЕсли;

// Выбираем элементы по текущей группе
Спр.ИспользоватьРодителя(Спр.ТекущийЭлемент(),0);
Спр.ВыбратьЭлементы(1);
КонецЦикла;
Записан
schnibbl
Гость
« Ответ #12 : 04-05-2005 12:59 » 

Да достойное решение, спасибо за предложенный вариант. а то у меня уже некое однобокость мышления в алгоритмах выработалась с этой 1С :о)
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 04-05-2005 14:26 » 

Странно....
Я как раз множество новых вариантов придумал в связи с ограниченностью языка Улыбаюсь
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines