1с 77 установить фильтр

Обновлено: 07.07.2024

1С 7.7 Множественный фильтр в полном журнале или пример работы компоненты vk_hook1C.dll

Думаю, что каждому программисту, который пишет или писал на "семерке", хотя бы раз заказчик задавал вопрос "А можно ли настроить отбор по нескольким полям в общем журнале?".

Дело в том, что стандартными средствами реализовать такое нельзя, отбор можно делать только по одному из реквизитов - "вид документа", "контрагент", "автор" и т.д. Можно написать обработку, которая внешним видом будет напоминать обычный журнал, но при этом пользователь будет иметь возможность указывать несколько фильтров для отбора документов. Однако в этом случае мы очень сильно будем терять в производительности работы такого "псевдо-журнала". Любая подобная обработка будет работать на порядок медленнее обычного журнала.

Остается смотреть в сторону нестандартных подходов в решении проблемы. Один из таких подходов и будет описан в данной статье, его суть заключается в применении внешней библиотеки vk_hook1C.dll.

Сразу стоит отметить, что данный метод подходит только для 1С SQL-версии. Т.к. основная задача библиотеки в том, чтобы перехватывать запросы, посылаемые 1С в базу SQL Server и подставлять в них требуемые значения.

Итак, исходные данные:

- SQL Server 2005 (2000 тоже подойдет, насчет версий старше 2005 ничего не могу сказать)

- 1С, сопряженная с SQL Server

- описание структуры таблиц 1С в SQL (подходит и для DBF-версии)

Копируем содержимое архива в каталог БД. Подключаем компоненту при запуске 1С

Далее создаем "Обычный журнал", устанавливаем в нем несколько видов отбора. В моем случае это: "Вид документа", "Автор", "Флаг Проведенные/Непроведенные", "Флаг Помеченные на удаление/Не помеченные на удаление".

Изображение

Для отбора можно устанавливать любые "общие реквизиты" документов и некоторые стандартные поля для таблицы журнала (вроде "флага проведения").

Список полей, которые можно использовать в качестве фильтра можно посмотреть либо в таблице "_1SJOURN" в базе SQL, либо в файле 1cv7.dds, который хранит в себе полное описание всех структур таблиц базы SQL.

Пишем код, который отключает стандартный отбор журнала и включает наш "расширенный" отбор.

(т.к. вставка фрагмента кода подглючивает (уж простите, администрация) - напишу обычным текстом)

//Устанавливаем произвольный отбор, чтобы сбросить настройку отбора журнала
УстановитьОтбор("ПКО");

////Генерим событие (оно будет изловлено в ОбработкаВнешнегоСобытия)
vk_hook.ВызватьСобытие("vk_hook","Отбор","Журнал");

//*******************************************
//Преобразует объект в идентификатор, который понимает SQL
Функция ПолучитьИД(прм_Объект)
стр=СокрЛП(ЗначениеВСтрокуВнутр(прм_Объект));
стр=Сред(стр,2,СтрДлина(стр)-2); //Убираем <>
сз=СоздатьОбъект("СписокЗначений");
сз.ИзСтрокиСРазделителями(стр);
стр=сз.ПолучитьЗначение(7);
иб=Прав(стр,3);
стр=Лев(стр, СтрДлина(стр)-3); //Убираем последние 3 символа
стр=_IdToStr(стр);
стр=стр+иб;

Пока СтрДлина(стр) стр=" "+стр;
КонецЦикла;

Возврат стр;
КонецФункции // ПолучитьИД

//*******************************************
Процедура ОбработкаВнешнегоСобытия(прм_Источник,прм_Событие,прм_Данные)
Сообщить(прм_Источник+" "+прм_Событие+" "+прм_Данные);
Если (прм_Источник="vk_hook") и (прм_Событие="Отбор") и (прм_Данные="Журнал") Тогда
стр="";
Если ПустоеЗначение(ВыбАвтор)=0 Тогда
стр=стр+"SP74='"+ПолучитьИД(ВыбАвтор)+"' and ";
КонецЕсли;
Если СписокДокументов.ТекущаяСтрока()>1 Тогда
стр=стр+"IDDOCDEF="+СписокДокументов.ПолучитьЗначение(СписокДокументов.ТекущаяСтрока())+" and ";
КонецЕсли;
Если Проведенные=1 Тогда
стр=стр+"CLOSED='1' and ";
КонецЕсли;
Если НеПомеченныеНаУдаление=1 Тогда
стр=стр+"ISMARK='0' and ";
КонецЕсли;

vk_hook.ТекстSQL="Select * from _1SJOURN(NOLOCK INDEX=JOURNAL) where IDJOURNAL=? and DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC vk_hook.НовыйSQL="Select * from _1SJOURN(NOLOCK INDEX=JOURNAL) where "+стр+" IDJOURNAL=? and DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC vk_hook.УстановитьЗаменуSQL();

vk_hook.ТекстSQL="Select COUNT(*) from _1SJOURN(NOLOCK) where IDJOURNAL=? and DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC vk_hook.НовыйSQL="Select COUNT(*) from _1SJOURN(NOLOCK) where "+стр+" IDJOURNAL=? and DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC vk_hook.УстановитьЗаменуSQL();
УстановитьОтбор("");

СписокДокументов.ДобавитьЗначение("все");
СписокДокументов.ДобавитьЗначение(2457,"заявка покупателя");
СписокДокументов.ДобавитьЗначение(1611,"реализация");
СписокДокументов.ДобавитьЗначение(1656,"возврат от покупателя");
СписокДокументов.ДобавитьЗначение(2742,"заказ поставщику");
СписокДокументов.ДобавитьЗначение(1582,"поступление ТМЦ");
СписокДокументов.ДобавитьЗначение(1684,"возврат поставщику");
СписокДокументов.ДобавитьЗначение(2196,"ПКО");
СписокДокументов.ДобавитьЗначение(2225,"РКО");
СписокДокументов.ДобавитьЗначение(8980,"транзит денежных средств");
СписокДокументов.ТекущаяСтрока(1);

Пояснение по коду:

1. Процедура ф_Отбор() устанавливается на все элементы, изменение которых должно автоматически фильтровать журнал документов.

2. При помощи функции ПолучитьИД(прм_Объект) мы можем получить идентификатор объекта 1С, чтобы строить по нему фильтр в запросе.

3. В список значений уже добавлены типы документов с их идентификаторами (их можно найти в файле 1cv7.dds). К примеру, на рисунке показан идентификатор к документу "ЗаявкаПокупателя".

Изображение

SQL-запрос мы "склеиваем" как обычную строку.

В коде встречаются 4 идентификатора полей таблицы SQL в которые мы передаем наши значения фильтров:

SP74 - это поле, в котором хранится "автор документа"

IDDOCDEF - в этом поле хранится идентификатор вида документа

CLOSED - флаг проведения

ISMARK - флаг пометки удаления

Как уже было сказано ранее, принцип работы компоненты в подмене SQL-запросов, поступающих из 1С в базу данных SQL.

Изначально запрос выглядит вот так:

vk_hook.ТекстSQL Select * from _1SJOURN(NOLOCK INDEX=JOURNAL) where "+стр+" IDJOURNAL=? and DATE_TIME_IDDOC>=? and DATE_TIME_IDDOC

Практически ничего не изменилось, за исключением добавления условия "where".

Команда vk_hook.УстановитьЗаменуSQL(), собственно и активизирует эту подмену.

На практике это выглядит примерно так:

1. Журнал без отборов

Изображение

2. Журнал с отбором по типу документа

Изображение

3. Журнал с отбором по типу документа и автору

Изображение

4. Журнал с отбором только проведенных документов по типу документа и автору

Изображение

Теперь время пришло сказать о недостатках описанного варианта организации множественного отбора, а точнее возможных его глюках. Дело в том, что данный метод отказывался корректно работать со сложным запросом (вложенной командой SELECT или множественным фильтром по одному из параметров, допустим выборе в качестве фильтра сразу 2-х типов документов). Фильтр вроде бы отрабатывал корректно, но при перемещении курсора внутри журнала, сам журнал вдруг "вешался" и все документы выборки пропадали. По всей видимости, это недоработки именно в самой компоненте. Не хотелось бы, чтобы для Вас это стало неприятной неожиданностью, в случае, если решите использовать этот способ на практике.

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

Делала и так
Если СпрПодр.НайтиПоНаименованию("ДистанционныеПродажи",0,0) = 1 Тогда
ПризнакДОставки.УстановитьОтбор("Отдел",СпрПодр.ТекущийЭлемент());
ОткрытьФорму("Журнал.ДоставленныеНакладные.РасходнаяНакладная");
КонецЕсли;

ОткрытьФорму("Журнал.ДоставленныеНакладные.РасходнаяНакладная",КонтекстЖурнала);

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

то что желтым в этом случае не надо. оно надо если устанавливаете отбор уже в форме списка открываемого журнала (тогда красное надо)

проверьте нет ли ничего в форме списка журнала что могло бы переопределить отбор после открытия ?

там скиньте флаг стандартного отбора (ФСО) в нолик и открывайте журнал в нём устанавливая отбор, таким образом мы заменим стандартную обработку выбора значения

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

В форме списка журнала доставленных накладных пишу
Процедура ПриОткрытии()
Если ТипЗначенияСтр(Форма.Параметр) = "СписокЗначений" Тогда
ФормаОтдел = Форма.Параметр.Получить("Отдел");
КонецЕсли;

Здравствуйте. Есть вопрос по фильрации общего журнала. Есть Графа отбора "ФакультетДляОтбора" которая включает два разных документа. Есть общий журнал, в котором стоит отбор по этой графе (ФакультетАдмин - элемент формы, по которому фильтруют данные):

Но возникла такая ситуация, что в данный общий журнал надо добавить закладки и на каждой закладке фильтровать не только по факультету, но и по виду документа, т.е. на каждой вкладке виден документ определенного вида. Вид см. на рисунке.
Насколько я понимаю дважды УстановитьОтбор использовать нельзя. Может кто подскажет, как можно решить этот вопрос штатными средствами 1С без ВК и т.п.? __________________
Помощь в написании контрольных, курсовых и дипломных работ здесь

Удаление документов 1с77
Понадобилось удалить тучу документов в базе ТиС 8.7 (около 500.000). Зачем - не спрашивайте.

журнал документов
Доброго времени суток. Простите за такой простой вопрос, но может кто знает, нельзя ли в 1с 8 при.

журнал документов
как создать внешний журнал документов и новые документы в нем (тоже внешние). а также удаление.

Журнал документов + ТЗ
Всем Хай. В академических целях интересует: Возможно ли в Фоме Журнала документов оганизовать.

Я делал. Но трудно это. Можно решить только с таким условие: набор закладок фиксированн.
Тогда
1. закладки создаются не ЗакладкиОтбора(), а вручную

Код ( (Unknown Language)):
ЗакладкиОтбора("", 1);
Форма.ИспользоватьЗакладки(1);
Форма.Закладки.УдалитьВсе();
Для ТекНом = 1 По КоличествоЗакладок Цикл
Форма.Закладки.ДобавитьЗначение(ИмяЗакладки);
КонецЦикла;
где ИмяЗакладки например = Вид()

2. Потом
// Дополнительно отбор
Если ФакультетАдмин.Выбран() = 1 Тогда
УстановитьОтбор("ФакультетАдмин", Формат(Админ.Код, "Ч(0)5.0") +
Форма.Закладки.Получить(ОтборПоВиду));
Иначе
УстановитьОтбор("Факультет", ОтборПоВиду));
КонецЕсли;

У меня есть несколько вопросиков:
1) КоличествоЗакладок я так понимаю это количество документов, которые я хочу, чтобы отображались как закладки. А как подсчитать это количество, если это общий журнал и мне нужно только два вида документов?
2)

// Дополнительно отбор
Если ФакультетАдмин.Выбран() = 1 Тогда
УстановитьОтбор("ФакультетАдмин", Формат(Админ.Код, "Ч(0)5.0") +
Форма.Закладки.Получить(ОтборПоВиду));

Здесь "ОтборПоВиду" что в нем храниться и где должно присваиваться значение этому отбору? Для чего здесь нужен Админ.Код и что за реквизит Админ, может вы имели ввиду ФакультетАдмин, т.е. код факультета использовать?

Иначе
УстановитьОтбор("Факультет", ОтборПоВиду));
КонецЕсли; Здесь я так понимаю вы имели ввиду УстановитьОтбор("ФакультетАдмин", ОтборПоВиду));?
PS: извиняюсь за множество вопросов, просто хочется разобраться в этом вопросе)))

Давайте еще раз:

* Краеугольный момент:
- В обоих документах создать Реквизит строка тип Строка который содержит буковки скомбинированные от
<БуковкаДокумента>+ Администратор.Код. И процедурой ПриЗаписи() их заполнять. Например: А001, Б003
- Создать в конф-ре Отбор "ФакультетАдмин" завязанный на этот реквизит. параметр "Отбирать пустные" - нет галочки

* При Открытии() Создали 2 закладки фиксированные.
Форма.ИспользоватьЗакладки(1);
Форма.Закладки.УдалитьВсе();
Форма.Закладки.ДобавитьЗначение("ВидДокаА", "Его красивое название");
Форма.Закладки.ДобавитьЗначение("ВидДокаБ", "Его красивое название");

* Создаем ПриВыбореЗакладки(НомерЗакладки, ЗначениеЗакладки). В ней
ВидДока = "";
Форма.Закладки.ПолучитьЗначение(НомерЗакладки, ВидДока);
ВидДока - получил значение вида дока. Например "ВидДокаА".
Программа устанавливает нужный отбор по виду дока. Это если не мешает Админ.
УстановитьОтбор(ОтборПоВиду);

А из-за него усложняем этот фрагмент:
Если Админ.Выбран() = 1 Тогда
ПоЧемОтбирать = Лев(ВидДока, 1) + Администратор.Код;
УстановитьОтбор("ФакультетАдмин", ПоЧемОтбирать);
Иначе
УстановитьОтбор(ОтборПоВиду);
КонецЕсли;

* А дальше совершенствуем:
- выделить этот фрагмент в отдельную процедуру и также вызывать после выбора Админ
- Не забыть вызвать при открытии.
- Отреагировать на изменение пользователем интервала:
Процедура ПриУстановкеИнтервала(ДатаНач,ДатаКон)
УстановитьИнтервал(ДатаНач, ДатаКон);
ВводВидОтбора();
КонецПроцедуры

Читайте также: