Имя: Пароль:
1C
1C 7.7
v7: ТиС 77 Прямой запрос к справочнику Номенклатура
0 Looking
 
09.04.16
12:11
Доброго времени суток!
Конфигурация "Торговля и Склад 7.7". Задача в частичном отображении справочника "Номенклатура", реализую ее через ИспользоватьСписокЭлементов().
Формирование списка который должен отображаться реализовано через задание пользователями списка исключаемых из отображения групп и элементов, то есть при открытии справочника Номенклатура анализируется список исключения и формируется отображаемый список.
Запрос к справочнику пробовал делать и штатным запросом, и прямым - время выполнения в обоих случаях одинаково - 3 сек. Может я что-то не так реализовал, раз время идентично? Может необходимо использовать другие методы?
1 Looking
 
09.04.16
12:12
штатный запрос

ЗапросСпрНоменклатура=СоздатьОбъект("Запрос");

ТекстЗапросаСпрНоменклатура =
     "
     |Номенклатура    = Справочник.Номенклатура.ТекущийЭлемент;      
     |Группировка Номенклатура;
     |Условие(НЕ(Номенклатура в СЗИсключаемойНоменклатуры));
     |";
2 Looking
 
09.04.16
12:12
прямой запрос

ЗапросСпрНоменклатура.Выполнить("Номенклатура=Справочник.Номенклатура.ТекущийЭлемент;
     |Условие(НЕ(Номенклатура в СЗИсключаемойНоменклатуры));
     |Группировка Номенклатура;");
3 Looking
 
09.04.16
12:14
код полностью

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

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


Процедура ПриОткрытии()
//МДВ
ФормированиеСпискаОтбораСправочникаНоменклатура();

      Если ИспользоватьФильтрНомеклатуры=1 Тогда
      ПриСменеИерархии(ИерархическийСписок());
      КонецЕсли;
//МДВ
4 ДенисЧ
 
09.04.16
12:15
Запросы практически эквипенисуальны.
В смысле эквивалентны.
Основное время всё равно уйдёт на передачу списка на сервер и последующее получение данных
5 Mikeware
 
09.04.16
12:42
криво поставленную задачу решать через .оппу, и удивляться...

Если уж прямым запросом (в смысле, классом) то надо типа
ВЫБРАТЬ
СпрНоменклатура.ТекущийЭлемент [Номенклатура $Справочник.Номенклатура]
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СоставФильтраСправочникаНоменклатура СпрФильтр ПО $СпрФильтр.Номенклатура=$СпрНоменклатура.ТекущийЭлемент И $СпрФИльтр.Владелец=:ПеремФильтрСправочникаНоменклатураПользователя
ГДЕ  ISNULL($СпрФильтр.ТекущийЭлемент)=1
6 Mikeware
 
09.04.16
12:43
и да, с какого перепугу (2) стало прямым запросом?
7 Изучаю1С8
 
09.04.16
14:51
(5) +nolock
8 Mikeware
 
09.04.16
14:55
(7) для дбф не обязательно.
9 Looking
 
10.04.16
15:05
(5)ну как криво поставленную. стоит задача, чтобы часть справочника Номенклатура и Контрагенты часть пользователей не видела совсем - не могла выбрать в документах, отчетах, в принципе не знала об их существовании. можно достичь это как-то иначе?
10 Looking
 
10.04.16
15:08
(5)"Справочник.СоставФильтраСправочникаНоменклатура СпрФильтр ПО $СпрФильтр.Номенклатура=$СпрНоменклатура.ТекущийЭлемент"

но ведь чтобы сформировать фильтр все-равно необходимо сначала обратиться к справочнику Номенклатура? ведь в данном случае пользователи задают только то, что нужно исключать, а не то, что нужно отображать. то есть в списке должны отображаться группы и элементы, кроме тех, что укажут пользователи в списке-фильтре.
11 Злопчинский
 
10.04.16
15:18
Если скульная база
То можно поставить патч Ромикса
И перехватывать запросы к скулю
И модифицировать их
12 Looking
 
10.04.16
15:36
(11)база ДБФ
13 Mikeware
 
10.04.16
15:51
(10) а ГДЕ  ISNULL($СпрФильтр.ТекущийЭлемент)=1 ты не заметил?
14 Looking
 
10.04.16
18:19
(13)можете помочь мне в написании запроса под мою конкретную задачу? не бесплатно конечно. с прямыми запросами не работал, а нужно достаточно оперативно проверить, ускорит-ли он данную задачу. написал Вам в ICQ указанную в Вашем профиле.
15 Looking
 
10.04.16
18:19
+(14)1cpp в конфигурации установлена, используется для индексированных таблиц значений
16 Djelf
 
10.04.16
18:50
(0) Класс "ПрямойЗапрос" на dbf использует 1sqlite.
А запросе "В" превращается в "IN".
А в официальной версии 1sqlite используется древний движок sqlite версии 3.7.10
А движок sqlite 3.7.10 не умеет оптимизировать IN. В смысле он не использует по IN индексы, а без индексов, естественно запрос тормозит.
Можешь попробовать мою сборку 1sqlite, она по IN умеет использовать индексы https://cloud.mail.ru/public/9gNb/XTUCTTYVw
Либо не используй "ПрямойЗапрос", а пиши на чистом sql, а  список выгружай во временную таблицу sqlite и используй не IN, а JOIN
17 Looking
 
10.04.16
19:19
(16)у меня база дбф
18 Djelf
 
10.04.16
21:21
(17) Я знаю. В (12) ты об этом уже говорил.
Или ты про слова "пиши на чистом sql"? Ну так все правильно написано. "ПрямойЗапрос" транслирует запрос в чистый sql, который в dbf базе выполняет ВК 1sqlite.
19 Looking
 
10.04.16
21:26
(18)можете реализовать это под мою задачу? сколько это стоит? в итоге должно работать быстрее чем сейчас?
20 Looking
 
10.04.16
21:27
+(19)сам я точно сходу не смогу написать, а мне-бы на днях результат нужен. знающим ведь такая задача не очень трудоемка?
21 Это_mike
 
10.04.16
21:36
(14) я аськууже с полгода не включал...
22 Это_mike
 
10.04.16
21:38
(14) кинь в почту - мой ник на мэйл.ру завтра гляну.
23 Looking
 
10.04.16
21:40
(22)спасибо большое! а что конкретно кинуть нужно? md-ик?
24 Это_mike
 
10.04.16
21:41
(23) вопрос - что сделать нужно.
25 Это_mike
 
10.04.16
21:42
(23) то, что в(5) -не сработало?
26 Looking
 
10.04.16
21:44
(24), (25) я сам не пойму как (5)прописать, никогда прямые запросы не писал, к сожалению.
27 Looking
 
10.04.16
21:45
(24)суть вопроса в ускорении, реально-ли сделать так, чтобы фильтр на справочник накладывался быстрее чем за 3 секунды.
28 Looking
 
10.04.16
21:45
(25)могу удаленный доступ предоставить, может так проще, чтобы сразу на реальной БД отработать?
29 Djelf
 
10.04.16
21:51
(19) Просто попытайся поставить 1sqlite по ссылке (16)
Конечно будет быстрее, сейчас считай это не прямой запрос, а кривой ;)
И кстати, выложи код генерации СпискаИсключения.
Это все можно завернуть в 1 запрос...
30 Это_mike
 
10.04.16
21:52
(28) (27) у меня сейчас база, так там фильр примерно так же накладывается, только не по справочнику дополнительному, с по реувизиту основного. Есть тормоза, но не 3 секунды, конечно.
Но я эту базу стараюсь не ковврять
Завтра попрлбую..
31 Это_mike
 
10.04.16
21:53
(29) он выше это и выложил. А как в один запрс -ч предложил в (5)
32 Looking
 
10.04.16
21:55
(29)"выложи код генерации СпискаИсключения."

в (3)Процедура ФормированиеСпискаОтбораСправочникаНоменклатура()
33 Djelf
 
10.04.16
21:55
(31) Чорд, как то не заметил...
34 Это_mike
 
10.04.16
21:59
(33) я, правда, 1склайт только на прошлой неделе попообовал, до этого с файловыми не возюкался, и думал, что никогда не придется. Однако пришлось.
35 Looking
 
10.04.16
22:00
(29)по ссылке скачал 1sqlite.dll, у меня она в моменте совсем не подключена. я же говорю, что в моменте совсем не умею с прямыми запросами работать. поэтому и прошу того у кого есть эти знания и навык, написать прямой запрос под мое решение.
36 Looking
 
10.04.16
22:03
+(35)не бесплатно конечно. главное чтобы время нашли.
37 Djelf
 
10.04.16
22:27
(0) Какой тип у ПеремФильтрСправочникаНоменклатураПользователя?
Не Справочник Номенклатура же... Поэтому (5) и не взлетает.
38 Djelf
 
10.04.16
22:33
(35) Как так не подключена? Не может быть такого!!! оО
И даже dll` ки в каталогах ИБ или 1С не было? Не верю!
39 Looking
 
10.04.16
22:35
(37)тип у ПеремФильтрСправочникаНоменклатураПользователя Справочник.ФильтрыСправочникаНоменклатура, у которого в свою очередь подчиненный Справочник.СоставФильтраСправочникаНоменклатура, в этом подчиненном справочнике реквизит Номенклатура, как раз в нем и указываются группы и элементы, которые необходимо исключить из отображения.
40 Looking
 
10.04.16
22:36
(38)ну почему-же не верите, только 1cpp.dll используется из дополнительных внешних компонент.
41 Looking
 
10.04.16
22:39
(39)то есть пользователь-руководитель указывает в справочнике пользователей, что пользователю Иванову задан "Фильтр для менеджеров", а пользователю Петрову "Фильтр для снабженцев" и т.д., а уже в подчиненных справочниках этих фильтров перечислены группы и элементы номенклатуры, которые необходимо исключать из отображения.
42 Злопчинский
 
10.04.16
22:59
а не проще сделать справочник по типу
"Номенклатура-Пользователь", и спр.номенклатура список вообще не открывать?
43 Looking
 
10.04.16
23:06
(42)не совсем понял мысль, ведь номенклатура не статична, постоянно дополняется, видоизменяется, и при каждом таком действии эти изменения справочника Номенклатура должны каким-то образом синхронизироваться со справочниками "Номенклатура менеджеров", "Номенклатура снабженцев" и т.д.?
и опять-же обращение к справочнику Номенклатура идет из целого ряда документов, отчетов, везде необходимо подменить это обращение обращением не к справочнику Номенклатура, а к справочникам "Номенклатура-Пользователь"?
44 Looking
 
10.04.16
23:10
+(43)или я не так понял (42)?
45 Looking
 
10.04.16
23:12
(37)"Какой тип у ПеремФильтрСправочникаНоменклатураПользователя? "

3 сек это с момента начала запроса к справочнику Номенклатура, и к окончанию запроса. или речь о том, что сама конструкция (5) не работает?
46 Djelf
 
10.04.16
23:49
(45) Да (5) не сработает...
У тебя отрицательный фильтр, а в sql с этим мучения ;)

Как то так оно должно выглядеть

    ТекстЗапроса="
    |SELECT
    |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
    |    Справочник_Номенклатура AS СпрНоменклатура
    |LEFT JOIN Справочник_СоставФильтраСправочникаНоменклатура AS СоставФильтра
    |    ON    СпрНоменклатура.ID=СоставФильтра.Номенклатура
    |LEFT JOIN Справочник_ФильтрыСправочникаНоменклатура AS ФильтрПользователя
    |    ON СоставФильтра.PARENTEXT=ФильтрПользователя.ID
    |WHERE СоставФильтра.Номенклатура IS NULL
    |AND СоставФильтра.ID IS NULL
    |";
    База=СоздатьОбъект("SQLiteBase");
    База.Открыть(":memory:");
    Запрос=База.НовыйЗапрос();
    Запрос.Подготовить(ТекстЗапроса);
    Запрос.УстановитьПараметр("@ФильтрПользователя",ФильтрПользователя);
    СЗПодчРод=СоздатьОбъект("СписокЗначений");
    СЗПодчРод=Запрос.ВыполнитьЗапрос(ТекстЗапроса,СЗПодчРод);
47 Djelf
 
10.04.16
23:59
Слегка ошибся...
- СЗПодчРод=Запрос.ВыполнитьЗапрос(ТекстЗапроса,СЗПодчРод);
+ СЗПодчРод=Запрос.Выполнить(СЗПодчРод);
48 Looking
 
11.04.16
00:06
(46), (47) спасибо огромное! скажете что должен! сейчас никак проверить не смогу, утром рано вставать. попробую завтра в течение дня.
49 Mikeware
 
11.04.16
10:22
(46) как раз (5) сработает. второе соединение нафик не нужно.
(48) ну что, сработало? или пробовать?
50 Looking
 
11.04.16
12:02
(49)еще проверяю. что нужно выслать Вам, чтобы пробовать? мд-ик? удаленный доступ по ТВ или АммиАдмин подойдет?
51 Looking
 
11.04.16
13:28
(46)"Запрос.УстановитьПараметр("@ФильтрПользователя",ФильтрПользователя);"

прошу подсказать, какое значение имеет переменная ФильтрПользователя? его нужно самому предварительно заполнять?

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

Запрос.УстановитьПараметр("@ФильтрПользователя",СЗИсключаемойНоменклатуры);
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(910)}: Неверный номер параметра
52 Looking
 
11.04.16
14:25
(5), (49)

показывает ошибку

Запрос.Подготовить(ТекстЗапроса);
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(923)}: Ошибка подстановки текстового параметра ПеремФильтрСправочникаНоменклатураПользователя - Неизвестный параметр
53 Mikeware
 
11.04.16
14:28
(52) это вгде?
54 Mikeware
 
11.04.16
14:29
(52)кинь базу - мд+эти три справочника+справочник пользователей (или где там фильтр фиксируемтя)
55 Looking
 
11.04.16
14:32
а по АммиАдмин или ТимВьювер неудобно подключиться?
56 Mikeware
 
11.04.16
14:33
(55) Не. Даже скайп, и то...
57 Looking
 
11.04.16
14:36
(53)

когда открываю список справочника, то получаю ошибку (52)

Процедура ФормированиеСпискаОтбораСправочникаНоменклатура()
ПеремФильтрСправочникаНоменклатураПользователя=глПользователь.ФильтрСправочникаНоменклатура;
Если ПустоеЗначение(ПеремФильтрСправочникаНоменклатураПользователя)=0 Тогда
СЗИсключаемойНоменклатуры=СоздатьОбъект("СписокЗначений");
СпрСоставФильтраСправочникаНоменклатура=СоздатьОбъект("Справочник.СоставФильтраСправочникаНоменклатура");
СпрСоставФильтраСправочникаНоменклатура.ИспользоватьВладельца(ПеремФильтрСправочникаНоменклатураПользователя);
СпрСоставФильтраСправочникаНоменклатура.ВыбратьЭлементы();
Пока СпрСоставФильтраСправочникаНоменклатура.ПолучитьЭлемент()=1 Цикл
     ПеремНоменклатура=СпрСоставФильтраСправочникаНоменклатура.Номенклатура;  
     Если ПустоеЗначение(ПеремНоменклатура)=0 Тогда
          СЗИсключаемойНоменклатуры.ДобавитьЗначение(ПеремНоменклатура);
     КонецЕсли;    
КонецЦикла;    
СпрСоставФильтраСправочникаНоменклатура.ИспользоватьВладельца("");
Если СЗИсключаемойНоменклатуры.РазмерСписка()>0 Тогда
ТекстЗапроса="
    |ВЫБРАТЬ
    |СпрНоменклатура.ТекущийЭлемент [Номенклатура $Справочник.Номенклатура]
    |ИЗ
    |Справочник.Номенклатура КАК СпрНоменклатура
    |ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СоставФильтраСправочникаНоменклатура СпрФильтр ПО $СпрФильтр.Номенклатура=$СпрНоменклатура.ТекущийЭлемент И $СпрФИльтр.Владелец=:ПеремФильтрСправочникаНоменклатураПользователя
    |ГДЕ  ISNULL($СпрФильтр.ТекущийЭлемент)=1
    |";  
    
    База=СоздатьОбъект("SQLiteBase");
    База.Открыть(":memory:");
    Запрос=База.НовыйЗапрос();
    Запрос.Подготовить(ТекстЗапроса);
    //Запрос.УстановитьПараметр("@ФильтрПользователя",СЗИсключаемойНоменклатуры);
    СЗИсключаемойНоменклатуры=СоздатьОбъект("СписокЗначений");
    СЗИсключаемойНоменклатуры=Запрос.Выполнить(СЗИсключаемойНоменклатуры);    
Иначе
     ИспользоватьФильтрНомеклатуры=0;
КонецЕсли;    
Иначе
    ИспользоватьФильтрНомеклатуры=0;
КонецЕсли;    
КонецПроцедуры
58 Mikeware
 
11.04.16
14:39
Запрос.УстановитьПараметр("ПеремФильтрСправочникаНоменклатураПользователя",ТутПеременнаяПоКоторойТыИщешьРазрешеннуюНоменклатуру);

То, что у тебя в (3) было в
СпрСоставФильтраСправочникаНоменклатура.ИспользоватьВладельца(ПеремФильтрСправочникаНоменклатураПользователя);
59 Looking
 
11.04.16
14:49
(58) в (3) у меня ПеремФильтрСправочникаНоменклатураПользователя=глПользователь.ФильтрСправочникаНоменклатура;

то есть это значение реквизита ФильтрСправочникаНоменклатура справочника Пользователи, которое имеет тип значения Справочник.ФильтрыСправочникаНоменклатура.

если я указываю

Запрос.УстановитьПараметр("@ФильтрПользователя",ПеремФильтрСправочникаНоменклатураПользователя);  

то при открытии формы получаю ошибку

Запрос.УстановитьПараметр("@ФильтрПользователя",ПеремФильтрСправочникаНоменклатураПользователя);  
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(924)}: Неверный номер параметра
60 Mikeware
 
11.04.16
14:51
ухххххххххххкакязол!

Запрос.УстановитьПараметр("ПеремФильтрСправочникаНоменклатураПользователя",глПользователь.ФильтрСправочникаНоменклатура);
61 Looking
 
11.04.16
15:04
(60)не работает так, показывает ошибку.
можно смысл пояснить?
структура понятна? что в фильтре пользователей нет фильтра - это элемент справочника, у которого есть подчиненный справочник, в котором перечислены те группы и элементы, которые необходимо исключить из отображения.
62 Looking
 
11.04.16
15:11
+(61)Запрос.УстановитьПараметр("ФильтрПользователя",глПользователь.ФильтрСправочникаНоменклатура);
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(926)}: Неверный номер параметра
63 Mikeware
 
11.04.16
15:15
(61) смысл такой
справочник.номенклатура соединяется со справочнником СоставФильтраНоменклатура, левым соединением по 1)равенству номенлатуры (номеклатура в справочнике номенклатура равен реквизиту номенклатура в справочнике СоставФильтраНоменклатура), и 2)по условию поле Владелец справочника СоставФильтра... равен твоей переменной.

получается табличка с двумя колонками - в одной колонке _весь_ справочник номенклатура, во во второй дибо соответвующий эдемент из справочника СоставФильтра, либо пусто.

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

гы?
64 Looking
 
11.04.16
15:25
(63)спасибо большое! на неверный номер параметра ругается, так как ранее в запросе не задан сам параметр?
65 Mikeware
 
11.04.16
15:25
(64) блин, ну кинь базу
66 Djelf
 
11.04.16
15:25
Эх... недокурил я вчера запрос... Исправленный

    ТекстЗапроса="
    |SELECT
    |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
    |    Справочник_Номенклатура AS СпрНоменклатура
    |LEFT JOIN
    |    (SELECT
    |        СоставФильтра.Номенклатура AS Номенклатура
    |    FROM Справочник_СоставФильтраСправочникаНоменклатура AS СоставФильтра
    |    INNER JOIN Справочник_ФильтрыСправочникаНоменклатура AS ФильтрПользователя
    |    ON СоставФильтра.PARENTEXT=ФильтрПользователя.ID
    |    AND ФильтрПользователя.ID=@ФильтрПользователя
    |) AS Фильтр ON Фильтр.Номенклатура=СпрНоменклатура.ID
    |WHERE Фильтр.Номенклатура IS NULL
    |";


@ФильтрПользователя - элемент Справочника ФильтрыСправочникаНоменклатура
67 Mikeware
 
11.04.16
15:28
(64) если скуллайт - попробуй     Запрос.Подставлять("...",...);
68 Djelf
 
11.04.16
15:28
Одна печаль - в индекс по справочнику номенклатура никак не попасть. Сколько выполняется "SELECT id FROM Справочник_Номенклатура"?
69 Mikeware
 
11.04.16
15:30
(66) имхо, как раз _пере_курил
70 Mikeware
 
11.04.16
15:31
(65) а лучше - посавь вандаловский класс ПрямойЗапрос
71 Looking
 
11.04.16
15:57
(68)работает! и гораздо быстрее. говорите что должен.

на базе без пользователей, не в монопольном режиме
я по отладчику смотрю

Справочник.Номенклатура.ФормаСписка.ФормаСписка    945    Запрос.Подготовить(ТекстЗапроса);    1    0.000890    0.38

или нужно как-то иначе смотреть?

Выборку подчиненных элементов ПриВыбореРодителя() тоже прямым запросом можно делать? Можете подсказать текст запроса?

Процедура ПриВыбореРодителя(Элемент)
    Если ИспользоватьФильтрНомеклатуры=1 Тогда
    СЗПодчРод=СоздатьОбъект("СписокЗначений");
    СпрНоменклатура=СоздатьОбъект("Справочник.Номенклатура");
    СпрНоменклатура.ИспользоватьРодителя(Элемент);
    СпрНоменклатура.ВыбратьЭлементы();
    Пока СпрНоменклатура.ПолучитьЭлемент(0)=1 Цикл
        ТекНоменклатура=СпрНоменклатура.ТекущийЭлемент();
        Если СЗОтображаемойНоменклатуры.НайтиЗначение(ТекНоменклатура)>0 Тогда
            СЗПодчРод.ДобавитьЗначение(ТекНоменклатура);
        КонецЕсли;
    КонецЦикла;
    ИспользоватьСписокЭлементов(СЗПодчРод);
    КонецЕсли;
КонецПроцедуры
72 Mikeware
 
11.04.16
16:09
(71)
|SELECT
    |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
    |    Справочник_Номенклатура AS СпрНоменклатура
    |WHERE  СпрНомерклатура.PARENTID=:ВыбРодитель

а лучше - поставь ПрямойЗапрос, и пиши "на русском"
зы. почту глянь
73 Djelf
 
11.04.16
16:30
Обидно на прямом запросе тратить на саму подготовку столько же времени сколько выполняется сам запрос ;)

Ну и на прямом вот так не получится!

> Все товары в группе, +_Родитель  для ускоренной группировки в ИндексированнойТаблице
WITH RECURSIVE Goods(ID,PARENTID,ISFOLDER) AS (
    SELECT ID,PARENTID,ISFOLDER
    FROM [Справочник.Номенклатура]
    WHERE ID   IN('     2Б  ')
    UNION SELECT Спр.ID,Спр.PARENTID,Спр.ISFOLDER
    FROM [Справочник.Номенклатура] AS Спр
    INNER JOIN Goods ON Goods.ID = Спр.PARENTID
)
SELECT
    Goods.ID  [Номенклатура $Справочник.Номенклатура],
    Goods.PARENTID [Номенклатура_Родитель $Справочник.Номенклатура]
FROM Goods
WHERE Goods.ISFOLDER=2
74 Looking
 
11.04.16
17:04
(72)письмо получил, спасибо огромное! изучаю!

опять у меня ошибка
Запрос.Подготовить(ТекстЗапроса);
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(951)}: Ошибка подстановки текстового параметра ВыбРодитель - Неизвестный параметр

ВыбРодитель необходимо через Запрос.УстановитьПараметр() задавать?
75 Looking
 
11.04.16
17:05
(73)это просто пример? в моей задаче он не применим?
76 Looking
 
11.04.16
17:06
(72)что я должен за проделанную Вами работу?
77 Mikeware
 
11.04.16
17:07
(76) Научился? вот и хорошо!
78 Mikeware
 
11.04.16
17:07
(74) Запрос.Подставлять("...",...);
79 Djelf
 
11.04.16
17:46
Поддерживаю (77) но в нагрузку нужно прочитать
http://www.script-coding.com/Direct_queries.html
и документацию по 1sqlite https://snegopat.ru/downloads/1sqlite/
Ты же на этом с прямыми запросами не остановишься?

(73) пример то работоспособный и полезный, только он потребует мою сборку 1sqlite, в оригинальном СТЕ запросы не работают.
80 Looking
 
11.04.16
18:24
(77), (79) спасибо вам огромное за науку! но если что я осознаю, и готов понести наказание рублем за свое незнайство )))

(78), (79)а когда открывается корневой каталог, например, при первоначальном открытии формы списка справочника, то есть группа-родитель отсутствует, нужно это как-то дополнительным условием в запросе отражать? или ограждать запрос от этой ситуации дополнительными условиями?

(79)" только он потребует мою сборку 1sqlite"

у меня как-раз она и установлена, с Вашей помощью
81 Looking
 
11.04.16
21:36
(72)если использую такой запрос, то получаю ошибку

Запрос.Подготовить(ТекстЗапроса);
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(952)}: Ошибка подстановки текстового параметра ВыбРодитель - Неизвестный параметр


если добавляю
База=СоздатьОбъект("SQLiteBase");
База.Открыть(":memory:");
Запрос=База.НовыйЗапрос();
Запрос.Подготовить(ТекстЗапроса);
Запрос.Подставлять("ВыбРодитель", Элемент);    

то получаю ошибку

Запрос.Подготовить(ТекстЗапроса);
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(950)}: Ошибка подстановки текстового параметра ВыбРодитель - Неизвестный параметр


прошу извинить и помочь.
82 Злопчинский
 
11.04.16
21:45
Короче склифасовский
Как отладишь все - расписываешь все подробно и выкладываешь
Технологию и сами запросы
Ибо надо делится типа
http://catalog.mista.ru/public/76287/
83 Djelf
 
11.04.16
21:54
(82) Не будь таким жестоким ;)
Различие между "Подставлять" и "УстановитьПараметр" новичка могут ввести в ступор.

(81) Руководство по 1sqlite "Объекты компоненты"/"Объект SQLiteQuery"/"Подготовить / Prepeare"

Там все хорошо разжёвано. Главное этот раздел найти!!!
84 Злопчинский
 
11.04.16
22:01
(83) "Различие между "Подставлять" и "УстановитьПараметр" новичка могут ввести в ступор." - я уже в ступоре. ничегго не поннял...
85 Looking
 
11.04.16
22:07
(83)поймите меня правильно, я очень благодарен, что помощь в ключе обучения, такая помощь лучшая, развивающая. Но мне проще летом с этим сесть и спокойно разбираться, а сейчас отчетность, куча разноплановых вопросов как всегда в это время года. Поэтому я и прошу знающих написать, согласен на оплату. Я позднее с удовольствием сам во все вникну, а сейчас просто физически не смогу грамотно сам это сделать. Очень прошу помочь написать(71) через прямой запрос.
86 Djelf
 
11.04.16
22:17
Ладно... попытаюсь объяснить!
Есть объект Запрос.
У Запроса есть 2 метода "Подставлять" и "УстановитьПараметр".
Перед выполнением Запрос должен быть Подготовлен.
Подготовкой считается вычисление плана выполнения Запроса.
Метод Подставлять должен быть сделан до момента Подготовки.
После Подготовки уже не меняется, фактически это установка константы для запроса.
А вот УстановитьПараметр нужно делать после Подготовки.
Т.к. у нас уже есть не просто Запрос, а ПодготовленныйЗапрос!!!

Кто то что то понял? Я нет... Это надо попробовать несколько раз и вот тогда оно в голове уляжется ;)
87 Злопчинский
 
11.04.16
22:20
(85)  фигня все
Я по такому пути так прямые запросы и не освоил
Бо когда надо - здесь шаблон пишут или за денежку покупаю
Сделал, пустил в продакшн и забыл
А когда не надо - оно и не надо, ведь уже работает
88 Djelf
 
11.04.16
22:21
(85) в (71) Используется метод Подставлять
Поэтому

Запрос.Подготовить(ТекстЗапроса);
Запрос.Подставлять("ВыбРодитель", Элемент);    

пишется наоборот

Запрос.Подставлять("ВыбРодитель", Элемент);    
Запрос.Подготовить(ТекстЗапроса);
89 Злопчинский
 
11.04.16
22:21
(86)  то есть красная или синяя...?
90 Djelf
 
11.04.16
22:23
(89) Я обе уже съел, и зеленую тоже ;)
91 Djelf
 
11.04.16
22:41
(85) Если для УстановитьПараметр то (71) так

    ТекстЗапроса="
    |SELECT
    |   СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
    |    Справочник_Номенклатура AS СпрНоменклатура
    |WHERE  СпрНоменклатура.PARENTID = @ВыбРодитель
    |";
    Запрос.Подготовить(ТекстЗапроса);
    Запрос.УстановитьПараметр("@ВыбРодитель",ВыбРодитель);
    СЗПодчРод=СоздатьОбъект("СписокЗначений");
    СЗПодчРод=Запрос.ВыполнитьЗапрос(ТекстЗапроса,СЗПодчРод);
92 Djelf
 
11.04.16
22:45
+(91) Редко использую Подставлять, только если сильно уверен что там не окажутся всякие кавычками и т.п. УстановитьПараметр работает надежнее - жрет все.
93 Злопчинский
 
12.04.16
02:27
(90) дальтоник?
94 Looking
 
12.04.16
07:14
(86), (88), (91)спасибо огромное за подробное осмысленное пояснение и пример!

размещать Подставлять до Подготовить я также пробовал, получаю ошибку
Запрос.Подготовить(ТекстЗапроса);
{Справочник.Номенклатура.ФормаСписка.ФормаСписка.Модуль(954)}: no such column: СпрНомерклатура.PARENTID

а вот (91) через УстановитьПараметр работает!
95 Looking
 
12.04.16
07:24
только отбор по фильтру не осуществляется, так как в (71) есть условие
ТекНоменклатура=СпрНоменклатура.ТекущийЭлемент();
Если СЗОтображаемойНоменклатуры.НайтиЗначение(ТекНоменклатура)>0 Тогда
СЗПодчРод.ДобавитьЗначение(ТекНоменклатура);
КонецЕсли;

а в прямом запросе такого условия нет, его можно в тело запроса прописать? или-же после запроса его результат обработать, например так?

СЗПодчРод=СоздатьОбъект("СписокЗначений");
СЗПодчРод=Запрос.Выполнить(СЗПодчРод);
    
Для СчСЗПодчРод=-СЗПодчРод.РазмерСписка() по -1 Цикл
        СЗПодчРодТекЗнач=СЗПодчРод.ПолучитьЗначение(-СчСЗПодчРод);
        Если СЗОтображаемойНоменклатуры.НайтиЗначение(СЗПодчРодТекЗнач)=0 Тогда
             СЗПодчРод.УдалитьЗначение(-СчСЗПодчРод);
        КонецЕсли;
    КонецЦикла;
96 Mikeware
 
12.04.16
07:26
(95) чиво надобно-то?
97 Ёпрст
 
12.04.16
07:29
(84) если запрос выполняется один раз, по Подставлять. Если много раз один и тот же запрос с разными параметрами, например, в форме списка - то Подготовить + УстановитьПараметр.
Усё.
98 Mikeware
 
12.04.16
07:35
(95) давай в темпе чата, если вопросы есть. у меня 30 минут, и убегаю...
99 Looking
 
12.04.16
07:53
(96)при выборе родителя должен накладываться фильтр по списку значений отображаемой номенклатуры.
100 Looking
 
12.04.16
07:53
+(99)вот это условие

ТекНоменклатура=СпрНоменклатура.ТекущийЭлемент();
Если СЗОтображаемойНоменклатуры.НайтиЗначение(ТекНоменклатура)>0 Тогда

СЗПодчРод.ДобавитьЗначение(ТекНоменклатура);
КонецЕсли;
101 Mikeware
 
12.04.16
07:54
(100) какой запрос у тебя сейчас обирает  СЗОтображаемойНоменклатуры ?
102 Looking
 
12.04.16
07:56
(101)

ТекстЗапроса="
    |SELECT

    |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
    |    Справочник_Номенклатура AS СпрНоменклатура
    |LEFT JOIN
    |    (SELECT
    |        СоставФильтра.Номенклатура AS Номенклатура
    |    FROM Справочник_СоставФильтраСправочникаНоменклатура AS СоставФильтра
    |    INNER JOIN Справочник_ФильтрыСправочникаНоменклатура AS ФильтрПользователя
    |    ON СоставФильтра.PARENTEXT=ФильтрПользователя.ID
    |    AND ФильтрПользователя.ID=@ФильтрПользователя
    |) AS Фильтр ON Фильтр.Номенклатура=СпрНоменклатура.ID
    |WHERE Фильтр.Номенклатура IS NULL
    |";

    База=СоздатьОбъект("SQLiteBase");
    База.Открыть(":memory:");
    Запрос=База.НовыйЗапрос();
    Запрос.Подготовить(ТекстЗапроса);
    Запрос.УстановитьПараметр("@ФильтрПользователя",глПользователь.ФильтрСправочникаНоменклатура);
    
    СЗОтображаемойНоменклатуры=СоздатьОбъект("СписокЗначений");
    СЗОтображаемойНоменклатуры=Запрос.Выполнить(СЗОтображаемойНоменклатуры);
103 Looking
 
12.04.16
07:58
+(102)ПриВыбореРодителя() пока вот так выглядит

Процедура ПриВыбореРодителя(Элемент)
    Если ИспользоватьФильтрНомеклатуры=1 Тогда

    ТекстЗапроса="    
    |SELECT
    |СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
    |Справочник_Номенклатура AS СпрНоменклатура
    |WHERE  СпрНоменклатура.PARENTID = @ВыбРодитель
    |";
    
    База=СоздатьОбъект("SQLiteBase");
    База.Открыть(":memory:");
    Запрос=База.НовыйЗапрос();
    Запрос.Подготовить(ТекстЗапроса);
    
    Запрос.УстановитьПараметр("@ВыбРодитель",Элемент);
    
    СЗПодчРод=СоздатьОбъект("СписокЗначений");
    СЗПодчРод=Запрос.Выполнить(СЗПодчРод);
    
    Для СчСЗПодчРод=-СЗПодчРод.РазмерСписка() по -1 Цикл
        СЗПодчРодТекЗнач=СЗПодчРод.ПолучитьЗначение(-СчСЗПодчРод);
        Если СЗОтображаемойНоменклатуры.НайтиЗначение(СЗПодчРодТекЗнач)=0 Тогда
             СЗПодчРод.УдалитьЗначение(-СчСЗПодчРод);
        КонецЕсли;
    КонецЦикла;
        
    ИспользоватьСписокЭлементов(СЗПодчРод);  
    
    КонецЕсли;
КонецПроцедуры
104 Mikeware
 
12.04.16
07:59
|WHERE Фильтр.Номенклатура IS NULL
AND СпрНоменклатура.PARENTID=Родитель

Ну и Родитель - устанавливай
105 Mikeware
 
12.04.16
07:59
мля. юзверь в мизде есть такой, оказывается
106 Mikeware
 
12.04.16
08:00
|WHERE Фильтр.Номенклатура IS NULL
AND СпрНоменклатура.PARENTID=@РодительНоменклатуры

Ну и @РодительНоменклатуры - устанавливай методом УстановитьПараметр
107 Looking
 
12.04.16
08:04
(104), (106) у меня условие по родителю работает, вопрос в том, можно и нужно-ли запихивать условие по вхождению в СЗОтображаемойНоменклатуры, или как у меня сейчас после выгрузки результата запроса в список значений обрезать его обратным циклом?
Для СчСЗПодчРод=-СЗПодчРод.РазмерСписка() по -1 Цикл
        СЗПодчРодТекЗнач=СЗПодчРод.ПолучитьЗначение(-СчСЗПодчРод);
        Если СЗОтображаемойНоменклатуры.НайтиЗначение(СЗПодчРодТекЗнач)=0 Тогда
             СЗПодчРод.УдалитьЗначение(-СчСЗПодчРод);
        КонецЕсли;
    КонецЦикла;
108 Mikeware
 
12.04.16
08:07
(107) при каждой смене родителя - если иерархия включена - выполняй (102)+(106), и будешь получать список для фильтра.
109 Looking
 
12.04.16
08:09
(108)пробую
110 Looking
 
12.04.16
08:35
(108)у меня почему-то, когда открываю справочник с отключенной иерархией, то фильтр перестает работать, ищу причину. то есть достаточно иерархию отключить, как отображается весь список, я уже попробовал запрос продублировать в процедуру ПриСменеИерархии(Способ), все-равно, как только отображаю без иерархии-показывает все элементы, не фильтруя их. может это запрос так делает?
111 Mikeware
 
12.04.16
08:52
(110) Если иерархию отключаешь - убирай из запроса фильтр по родителю.
112 Looking
 
12.04.16
09:32
(111)убираю конечно, но почему-то раньше работал запрос, а теперь выводит весь список, без фильтра

Процедура ПриСменеИерархии(Способ)
    
    Если Способ=0 Тогда
    
    ТекстЗапроса="
    |SELECT

    |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
    |    Справочник_Номенклатура AS СпрНоменклатура
    |LEFT JOIN
    |    (SELECT
    |        СоставФильтра.Номенклатура AS Номенклатура
    |    FROM Справочник_СоставФильтраСправочникаНоменклатура AS СоставФильтра
    |    INNER JOIN Справочник_ФильтрыСправочникаНоменклатура AS ФильтрПользователя
    |    ON СоставФильтра.PARENTEXT=ФильтрПользователя.ID
    |    AND ФильтрПользователя.ID=@ФильтрПользователя
    |) AS Фильтр ON Фильтр.Номенклатура=СпрНоменклатура.ID
    |WHERE Фильтр.Номенклатура IS NULL
    |";

    База=СоздатьОбъект("SQLiteBase");
    База.Открыть(":memory:");
    Запрос=База.НовыйЗапрос();
    Запрос.Подготовить(ТекстЗапроса);
    Запрос.УстановитьПараметр("@ФильтрПользователя",глПользователь.ФильтрСправочникаНоменклатура);
    
    СЗОтображаемойНоменклатуры=СоздатьОбъект("СписокЗначений");
    СЗОтображаемойНоменклатуры=Запрос.Выполнить(СЗОтображаемойНоменклатуры);    
    
    ИспользоватьСписокЭлементов(СЗОтображаемойНоменклатуры);
    Иначе
        ПриВыбореРодителя(ТекущийЭлемент().Родитель);
    КонецЕсли;

КонецПроцедуры
113 Looking
 
12.04.16
09:52
+(112)в общем запрос перестал фильтровать, и никак вернуть не могу. он не ругается, выполняется, но выводит полный список, без наложения фильтра.
114 Mikeware
 
12.04.16
09:55
(113) я ж говорю - кинь базу
115 Looking
 
12.04.16
09:59
(114)она большая, попробую создать пустую и в ней пример набросать.

как я понял запрос в (112) исключает только ГРУППУ, а все входящие в нее элементы не исключает. то есть в списке элементов группы нет, а все входящие в нее элементы есть.
116 Mikeware
 
12.04.16
10:00
(115) мд+ четыре справочника: пользователи, номенклатура, и два справлчника фильтров.
117 Looking
 
12.04.16
11:19
(116)базу подготовил, скоро вышлю.
но столкнулся с другим моментом - при таком способе работы пользователи не смогут добавлять новые элементы в справочник?
118 Looking
 
12.04.16
11:57
+(117)базу выслал, также выложу на файлообменник и дам ссылку в теме.
настройки произведены в Форме списка справочника номенклатура.  Справочники отбора настроены под пользователем Менеджер.
Что в моменте работает не так - когда разворачиваем справочник общим списком, то есть отключаем иерархию, то исключаются только группы, а элементы в них входящие не исключаются. например, можно, отключить иерархию, и открыть форму списка справочника - будут видны все элементы, кроме исключаемых групп (только групп, но не подчиненных им элементов и групп).
Второй момент - так как использование списка не позволяет вводить новые элементы в справочник, то придется использование списка оставить только для вывода без иерархии, а при выводе с иерархией нужно запретить открывать каталоги исходя из запрещающего фильтра. я так понимаю это нужно также прямыми запросами писать. сейчас пишу непрямыми запросами, чтобы понятно было о чем речь идет.
119 Looking
 
12.04.16
12:07
+(118)БД в файлообменнике http://my-files.ru/b7np1a
размер 13 Мб.
120 Mikeware
 
12.04.16
12:11
слил. щазз.
121 Looking
 
12.04.16
12:28
(120)видите как работает? открываем общим списком справочник номенклатура под пользователем Менеджер. при этом группы Для руководителей не видны, а элементы, которые внутри этих групп, видны.
122 Looking
 
12.04.16
13:11
(120)заковыристо?
123 Mikeware
 
12.04.16
13:19
(122) да отвлекли. и вздрючили попутно :-( накосячил...
124 Looking
 
12.04.16
13:40
(123)сочувствую (((
125 Looking
 
12.04.16
14:09
что-же в этом запросе не так, что он выбрасывает только группу, но оставляет входящие в нее вложения - группы и элементы

ТекстЗапроса="
    |SELECT

    |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
    |FROM
    |    Справочник_Номенклатура AS СпрНоменклатура
    |LEFT JOIN
    |    (SELECT
    |        СоставФильтра.Номенклатура AS Номенклатура
    |    FROM Справочник_СоставФильтраСправочникаНоменклатура AS СоставФильтра
    |    INNER JOIN Справочник_ФильтрыСправочникаНоменклатура AS ФильтрПользователя
    |    ON СоставФильтра.PARENTEXT=ФильтрПользователя.ID
    |    AND ФильтрПользователя.ID=@ФильтрПользователя
    |) AS Фильтр ON Фильтр.Номенклатура=СпрНоменклатура.ID
    |WHERE Фильтр.Номенклатура IS NULL
    |";
126 Mikeware
 
12.04.16
14:40
(124) ээээээээээ!
    СЗОтображаемойНоменклатуры=Запрос.Выполнить(СЗОтображаемойНоменклатуры);
127 Mikeware
 
12.04.16
14:42
а, все, сам тупанул
128 Looking
 
12.04.16
14:59
(127)верно? Сам эффект видите наглядно? Как в списке справочника отображаются элементы вложенные в исключаемую группу?
129 Djelf
 
12.04.16
21:07
(100) Творчески же надо!!!
Берешь запрос из (66) и добавляешь к нему условие на группу из (91). Все...
130 Looking
 
12.04.16
21:14
(129) очень прошу посмотреть БД в (119) дело в том, что запрос (66) отбирает неверно - исключает только группу, а все что в нее вложено - оставляет. То есть в список попадают все элементы вложенные в исключаемую группу.
131 Это_mike
 
12.04.16
21:23
(130) завтра попытаюсь додедать. Но как-то неадекватно себя 1склайт ведет...
132 Djelf
 
12.04.16
21:26
(131) Да не... адекватно...
Ему видимо надо чтобы при отрицательном блоке по группе исключались не только товары в самой группе но и все по иерархии.
(130) Так?
133 Это_mike
 
12.04.16
21:29
(132) юез иерархии запрос пусьой список влзвращает...
134 Looking
 
12.04.16
21:36
(132)я полагал, что всю иерархию исключает. но сейчас не исключаются даже вложенные непосредственно в группу элементы. Посмотрите пример в БД, она маленькая. Из списка справочника исчезает только группа, а товары группы остаются.
135 Looking
 
12.04.16
22:12
(132)посмотрите скриншот http://s017.radikal.ru/i400/1604/de/030064502596.jpg

групп Для руководства 001 и Для руководства 002 нет, а элементы в них вложенные (непосредственно в них) отображаются.
136 Looking
 
13.04.16
12:13
Может прямой фильтр проще реализовать и он будет работать? То есть чтобы в справочнике фильтра указывать не исключаемые группы, а те что должны отображаться.
137 Djelf
 
13.04.16
12:15
Жутки запросик получился, зато вроде работает...

WITH RECURSIVE
Goods(ID,PARENTID,ISFOLDER) AS ( -- вся номенклатура в группе
    SELECT t0.ID,t0.PARENTID,t0.ISFOLDER
    FROM Справочник_Номенклатура AS t0
        WHERE t0.ID=@Группа
    UNION SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    FROM Справочник_Номенклатура AS t1
    INNER JOIN Goods ON Goods.ID = t1.PARENTID
),
NoGoods(ID,PARENTID,ISFOLDER) AS ( -- вся запрещенная  номенклатура
    SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    FROM Справочник_СоставФильтраСправочникаНоменклатура AS t0
    LEFT JOIN Справочник_Номенклатура AS t1
        ON t0.Номенклатура=t1.ID
    WHERE t0.PARENTEXT=@ФильтрПользователя
    UNION SELECT t3.ID,t3.PARENTID,t3.ISFOLDER
    FROM Справочник_Номенклатура AS t3
    INNER JOIN NoGoods ON t3.PARENTID=NoGoods.ID
)
SELECT
    Goods.ID     [NoGoods $Справочник.Номенклатура]
FROM Goods
LEFT JOIN NoGoods ON NoGoods.ID=Goods.ID
WHERE NoGoods.ID IS NULL


138 Looking
 
13.04.16
12:59
(137)с таким вариантом при отключенной иерархии отображает полностью пустой список, то есть ничего нет, не групп, не элементов.

Процедура ПриСменеИерархии(Способ)
    
    Если Способ=0 Тогда
    
//    ТекстЗапроса="
//    |SELECT
//
//    |    СпрНоменклатура.ID [Номенклатура $Справочник.Номенклатура]
//    |FROM
//    |    Справочник_Номенклатура AS СпрНоменклатура
//    |LEFT JOIN
//    |    (SELECT
//    |        СоставФильтра.Номенклатура AS Номенклатура
//    |    FROM Справочник_СоставФильтраСправочникаНоменклатура AS СоставФильтра
//    |    INNER JOIN Справочник_ФильтрыСправочникаНоменклатура AS ФильтрПользователя
//    |    ON СоставФильтра.PARENTEXT=ФильтрПользователя.ID
//    |    AND ФильтрПользователя.ID=@ФильтрПользователя
//    |) AS Фильтр ON Фильтр.Номенклатура=СпрНоменклатура.ID
//    |WHERE Фильтр.Номенклатура IS NULL
//    |";
    
    ТекстЗапроса="
    |WITH RECURSIVE
    |Goods(ID,PARENTID,ISFOLDER) AS ( -- вся номенклатура в группе
    |SELECT t0.ID,t0.PARENTID,t0.ISFOLDER
    |FROM Справочник_Номенклатура AS t0
    |    WHERE t0.ID=@Группа
    |UNION SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    |FROM Справочник_Номенклатура AS t1
    |INNER JOIN Goods ON Goods.ID = t1.PARENTID
    |),
    |NoGoods(ID,PARENTID,ISFOLDER) AS ( -- вся запрещенная  номенклатура
    |SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    |FROM Справочник_СоставФильтраСправочникаНоменклатура AS t0
    |LEFT JOIN Справочник_Номенклатура AS t1
    |    ON t0.Номенклатура=t1.ID
    |WHERE t0.PARENTEXT=@ФильтрПользователя
    |UNION SELECT t3.ID,t3.PARENTID,t3.ISFOLDER
    |FROM Справочник_Номенклатура AS t3
    |INNER JOIN NoGoods ON t3.PARENTID=NoGoods.ID
    |)
    |SELECT
    |Goods.ID     [NoGoods $Справочник.Номенклатура]
    |FROM Goods
    |LEFT JOIN NoGoods ON NoGoods.ID=Goods.ID
    |WHERE NoGoods.ID IS NULL
    |";


    База=СоздатьОбъект("SQLiteBase");
    База.Открыть(":memory:");
    Запрос=База.НовыйЗапрос();
    Запрос.Подготовить(ТекстЗапроса);
    Запрос.УстановитьПараметр("@ФильтрПользователя",глПользователь.ФильтрСправочникаНоменклатура);
    
    СЗОтображаемойНоменклатуры=СоздатьОбъект("СписокЗначений");
    СЗОтображаемойНоменклатуры=Запрос.Выполнить(СЗОтображаемойНоменклатуры);    
    
    ИспользоватьСписокЭлементов(СЗОтображаемойНоменклатуры);
    Иначе
        ПриВыбореРодителя(ТекущийЭлемент().Родитель);
    КонецЕсли;

КонецПроцедуры
139 Djelf
 
13.04.16
13:03
фильтр на группу поставь, пустое значение <> пустое значение справочника
140 Looking
 
13.04.16
13:42
(139)в прямом запросе необходимо фильтр поставить?
141 Djelf
 
13.04.16
14:00
Запрос то посмотри внимательно, в нем 2 параметра

WHERE t0.ID=@Группа
WHERE t0.PARENTEXT=@ФильтрПользователя

А у тебя установлен только @ФильтрПользователя
Значит чему равна группа? Ничему, пустому значению, вот ничего и не выводит.
142 Looking
 
13.04.16
14:30
(141)извиняюсь.

в процедуре ПриСменеИерархии() закомментировал строку
//|    WHERE t0.ID=@Группа

и вроде-бы работает корректно.

а вот в процедуре ПриВыбореРодителя()

пробую добавить через условие

Если Пустоезначение(Элемент)=0 Тогда
    ТекстЗапроса=ТекстЗапроса+"
    |    WHERE t0.ID=@Группа
    |";
КонецЕсли;  

Если Пустоезначение(Элемент)=0 Тогда
Запрос.УстановитьПараметр("@Группа",Элемент);
КонецЕсли;


Но при этом, при выборе группы появляется дополнительный элемент со знаком вопроса, при выборе корня помимо групп еще 4 элемента со знаком вопроса. Неправильно я условие поставил?
143 Looking
 
13.04.16
14:36
+(142)вот как процедура выглядит

Процедура ПриВыбореРодителя(Элемент)
  
    ТекстЗапроса="
    |WITH RECURSIVE
    |Goods(ID,PARENTID,ISFOLDER) AS ( -- вся номенклатура в группе
    |SELECT t0.ID,t0.PARENTID,t0.ISFOLDER
    |FROM Справочник_Номенклатура AS t0    
    |";
    
    Если Пустоезначение(Элемент)=0 Тогда
    ТекстЗапроса=ТекстЗапроса+"
    |    WHERE t0.ID=@Группа
    |";
    КонецЕсли;
    
    ТекстЗапроса=ТекстЗапроса+"
    |UNION SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    |FROM Справочник_Номенклатура AS t1
    |INNER JOIN Goods ON Goods.ID = t1.PARENTID
    |),
    |NoGoods(ID,PARENTID,ISFOLDER) AS ( -- вся запрещенная  номенклатура
    |SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    |FROM Справочник_СоставФильтраСправочникаНоменклатура AS t0
    |LEFT JOIN Справочник_Номенклатура AS t1
    |    ON t0.Номенклатура=t1.ID
    |WHERE t0.PARENTEXT=@ФильтрПользователя
    |UNION SELECT t3.ID,t3.PARENTID,t3.ISFOLDER
    |FROM Справочник_Номенклатура AS t3
    |INNER JOIN NoGoods ON t3.PARENTID=NoGoods.ID
    |)
    |SELECT
    |Goods.ID     [NoGoods $Справочник.Номенклатура]
    |FROM Goods
    |LEFT JOIN NoGoods ON NoGoods.ID=Goods.ID
    |WHERE NoGoods.ID IS NULL
    |";
    
    База=СоздатьОбъект("SQLiteBase");
    База.Открыть(":memory:");
    Запрос=База.НовыйЗапрос();
    Запрос.Подготовить(ТекстЗапроса);
    
    Запрос.УстановитьПараметр("@ФильтрПользователя",глПользователь.ФильтрСправочникаНоменклатура);
    Если Пустоезначение(Элемент)=0 Тогда
    Запрос.УстановитьПараметр("@Группа",Элемент);
    КонецЕсли;
    
    СЗПодчРод=СоздатьОбъект("СписокЗначений");
    СЗПодчРод=Запрос.Выполнить(СЗПодчРод);
    
    ИспользоватьСписокЭлементов(СЗПодчРод);  
    
КонецПроцедуры
144 Looking
 
13.04.16
14:38
+(143)и при этом когда нахожусь в корне справочника в иерархическом режиме, то помимо групп отображаются ниже все 4-ре элемента со знаками вопроса, а когда захожу в группу, то отображаются над элементами группы один элемент со знаком вопроса.
145 Djelf
 
13.04.16
17:07
Это же баян... Пустая строка в этом режиме это элементы списка не той иерархии. Сама группа в списке то и не нужна так что замени
WHERE t0.ID=@Группа на WHERE t0.PARENTID=@Группа
146 Djelf
 
13.04.16
17:09
Ну и пустые подчиненные элементы пофикси
    |INNER JOIN Goods ON Goods.ID = t1.PARENTID
+   |    WHERE t1.PARENTID=@Группа
147 Looking
 
13.04.16
17:41
(145), (146) спасибо большое! теперь внутри групп элементы со знаками вопроса ушли. но в корне, когда отображаю иерархически, под группами есть 4 элемента со знаками вопроса.

запрос в моменте выглядит следующим образом

Процедура ПриВыбореРодителя(Элемент)
  
    ТекстЗапроса="
    |WITH RECURSIVE
    |Goods(ID,PARENTID,ISFOLDER) AS ( -- вся номенклатура в группе
    |SELECT t0.ID,t0.PARENTID,t0.ISFOLDER
    |FROM Справочник_Номенклатура AS t0    
    |";
    
    Если Пустоезначение(Элемент)=0 Тогда
    ТекстЗапроса=ТекстЗапроса+"
    |WHERE t0.PARENTID=@Группа
    |";
    КонецЕсли;      

    ТекстЗапроса=ТекстЗапроса+"
    |UNION SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    |FROM Справочник_Номенклатура AS t1
    |    WHERE t1.PARENTID=@Группа  
    |),
    |NoGoods(ID,PARENTID,ISFOLDER) AS ( -- вся запрещенная  номенклатура
    |SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    |FROM Справочник_СоставФильтраСправочникаНоменклатура AS t0
    |LEFT JOIN Справочник_Номенклатура AS t1
    |    ON t0.Номенклатура=t1.ID
    |WHERE t0.PARENTEXT=@ФильтрПользователя
    |UNION SELECT t3.ID,t3.PARENTID,t3.ISFOLDER
    |FROM Справочник_Номенклатура AS t3
    |INNER JOIN NoGoods ON t3.PARENTID=NoGoods.ID
    |)
    |SELECT
    |Goods.ID     [NoGoods $Справочник.Номенклатура]
    |FROM Goods
    |LEFT JOIN NoGoods ON NoGoods.ID=Goods.ID
    |WHERE NoGoods.ID IS NULL
    |";
    
    База=СоздатьОбъект("SQLiteBase");
    База.Открыть(":memory:");
    Запрос=База.НовыйЗапрос();
    Запрос.Подготовить(ТекстЗапроса);
    
    Запрос.УстановитьПараметр("@ФильтрПользователя",глПользователь.ФильтрСправочникаНоменклатура);
    Если Пустоезначение(Элемент)=0 Тогда
    Запрос.УстановитьПараметр("@Группа",Элемент);
    КонецЕсли;
    
    СЗПодчРод=СоздатьОбъект("СписокЗначений");
    СЗПодчРод=Запрос.Выполнить(СЗПодчРод);
    
    ИспользоватьСписокЭлементов(СЗПодчРод);  
    
КонецПроцедуры
148 Djelf
 
13.04.16
17:49
(147) А (146) добавить?
149 Looking
 
13.04.16
18:05
(148)может не в том месте добавляю?

ТекстЗапроса="
    |WITH RECURSIVE
    |Goods(ID,PARENTID,ISFOLDER) AS ( -- вся номенклатура в группе
    |SELECT t0.ID,t0.PARENTID,t0.ISFOLDER
    |FROM Справочник_Номенклатура AS t0    
    |";
    
    Если Пустоезначение(Элемент)=0 Тогда
    ТекстЗапроса=ТекстЗапроса+"
    |WHERE t0.PARENTID=@Группа
    |";
    КонецЕсли;      

    ТекстЗапроса=ТекстЗапроса+"
    |UNION SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    |FROM Справочник_Номенклатура AS t1
    |INNER JOIN Goods ON Goods.ID = t1.PARENTID
    |WHERE t1.PARENTID=@Группа  
    |),
    |NoGoods(ID,PARENTID,ISFOLDER) AS ( -- вся запрещенная  номенклатура
    |SELECT t1.ID,t1.PARENTID,t1.ISFOLDER
    |FROM Справочник_СоставФильтраСправочникаНоменклатура AS t0
    |LEFT JOIN Справочник_Номенклатура AS t1
    |    ON t0.Номенклатура=t1.ID
    |WHERE t0.PARENTEXT=@ФильтрПользователя
    |UNION SELECT t3.ID,t3.PARENTID,t3.ISFOLDER
    |FROM Справочник_Номенклатура AS t3
    |INNER JOIN NoGoods ON t3.PARENTID=NoGoods.ID
    |)
    |SELECT
    |Goods.ID     [NoGoods $Справочник.Номенклатура]
    |FROM Goods
    |LEFT JOIN NoGoods ON NoGoods.ID=Goods.ID
    |WHERE NoGoods.ID IS NULL
    |";
150 Looking
 
13.04.16
18:07
+(149)так и отображает в корне при отображении по группам внизу под группами четыре элемента со знаками вопроса.
151 Djelf
 
13.04.16
19:02
Убери это и т.п. Если Пустоезначение(Элемент)=0 Тогда
Верхняя группа пустое значение, чтобы не было вопросиков надо устанавливать фильтр на пустое значение верхней группы, а ты его не устанавливаешь.
И вообще сделай переменную Запрос и инициализируй запрос методом подготовить только 1с раз, а дальше только подставляй параметры и выполняй.
152 Looking
 
13.04.16
20:15
(151) Фуф! Спасибо огроменное! Если все-таки что-то должен, то напишите обязательно, очень здорово помогли! Конечно основной тест в реальной работе пользователями, но пока сам не смог найти некорректного режима работы!

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

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

ПриСменеИерархии(ИерархическийСписок());

а в процедуре ПриВыбореРодителя() условие

Если глПользователь.РедакторСправочникаНоменклатура=0 Тогда

ПРЯМОЙ ЗАПРОС

Иначе
    
    ИспользоватьСписокЭлементов();      
        
    Если СЗИсключаемойНоменклатуры.НайтиЗначение(Элемент)<>0 Тогда
         Предупреждение("Запрет на открытие данной группы номенклатуры");
         СтатусВозврата(0);
         Возврат;
КонецЕсли;
        
КонецЕсли;
153 Looking
 
13.04.16
20:18
(152)можно попросить прямой запрос формирования списка исключаемой номенклатуры? если конечно не сильно надоел еще. мне-бы пример такого простого запроса помог лучше понять, чтобы не только сложный запрос был, но и для более простых ситуаций

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

ПеремФильтрСправочникаНоменклатураПользователя=глПользователь.ФильтрСправочникаНоменклатура;
    СЗИсключаемойНоменклатуры=СоздатьОбъект("СписокЗначений");
    СпрСоставФильтраСправочникаНоменклатура=СоздатьОбъект("Справочник.СоставФильтраСправочникаНоменклатура");
    СпрСоставФильтраСправочникаНоменклатура.ИспользоватьВладельца(ПеремФильтрСправочникаНоменклатураПользователя);
    СпрСоставФильтраСправочникаНоменклатура.ВыбратьЭлементы();
    Пока СпрСоставФильтраСправочникаНоменклатура.ПолучитьЭлемент()=1 Цикл
     ПеремНоменклатура=СпрСоставФильтраСправочникаНоменклатура.Номенклатура;  
     Если ПустоеЗначение(ПеремНоменклатура)=0 Тогда
          СЗИсключаемойНоменклатуры.ДобавитьЗначение(ПеремНоменклатура);
     КонецЕсли;    
     КонецЦикла;    
     СпрСоставФильтраСправочникаНоменклатура.ИспользоватьВладельца("");
154 Djelf
 
13.04.16
21:04
Так вторая часть запроса NoGoods это оно и есть.
Убери запрос Googs, оставь NoGoods и select id from NoGoods
155 Ёпрст
 
14.04.16
08:29
Всё делается проще.
В справочнике пользователей, каждому пользователю можно настроить список товаров, который он может "видеть".
В справочнике Номенклатура видны все товары, и это нормально.
А вот во все отчеты, принудительно ставится фильтр по номенклатуре (или чему угодно) из справочника Пользователи.
Юзверь ничего не замечает, и будет получать отчеты, только те, что может.
У нас так сделано.
А ограничивать сам справочник - моветон, теряется иерархия , отборы и т.д и т.п.
156 Looking
 
14.04.16
09:22
(155)"А ограничивать сам справочник - моветон, теряется иерархия , отборы и т.д и т.п."

иерархия не теряется. отборы да, но вроде-бы ими не пользуются.
157 Looking
 
14.04.16
09:22
(154)спасибо! попробую.
158 Ёпрст
 
14.04.16
09:27
(156) и прям все формы списка отфильтровал, все подборы во всех документах ?
И в отчетах ничего не видать ?
Мартышкиным трудом занимаешься.
Люди должны знать весь продаваемый ассортимент.
159 Mikeware
 
14.04.16
09:30
(158) так форм у  списка немного
160 Looking
 
14.04.16
09:56
(158)формы всего 3 - списка, для выбора и подбора. причем в форме списка пришлось делать иначе, см (152), чтобы могли вводить новые номенклатурные позиции. сами группы видны, а вот войти в них нельзя.

"Мартышкиным трудом занимаешься.
Люди должны знать весь продаваемый ассортимент."

задача так поставлена специфично, руководство в справочники добавляет еще свою информацию, так у них давно заведено, и ее не должно быть видно остальным. предлагал вводить эту информацию иначе, отказываются, хотят именно так.
161 Ёпрст
 
14.04.16
09:58
(160) открываем любой отчет и.. видим всё, что запрещено.
162 Ёпрст
 
14.04.16
09:59
и это.. при использоватьсписокэлементов, как говоришь, элементы то заводят у вас новые ?
163 Mikeware
 
14.04.16
10:03
(161) запретить в отчетах "без отбора", или если сден без отбора - накладывать список.
геморно, но можно.
164 Mikeware
 
14.04.16
10:04
(162) у них "список запрещенных"
165 Looking
 
14.04.16
10:05
(161)про отчеты знаю, их кончено также буду закрывать.

(162)см (152) и (160). в форме списка пришлось делать иначе, см (152), чтобы могли вводить новые номенклатурные позиции. сами группы видны, а вот войти в них нельзя.
166 Mikeware
 
14.04.16
10:05
(162) Ты Вандаловский ПрямойЗапрос не юзал?
167 Ёпрст
 
14.04.16
10:09
(166) неа, так, посмотрел , как сделано и всё.
:)
Пользователь не знает, чего он хочет, пока не увидит то, что он получил. Эдвард Йодан