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