Главная
Статьи
Ресурсы
Информация

Часть II. Использование основных объектов конфигурации. Глава 6 - 7


Глава 6. Оптимизация процедуры проведения документа ОказаниеУслуги

После изучения предыдущей главы вы уже достаточно хорошо знакомы с языком запросов, и мы наконец-то можем приступить к одной из самых важных глав нашей книги - к оптимизации документа «ОказаниеУслуги», и в частности, к полному изменению его обработчика события «ОбработкаПроведения».

«Зачем это нужно?» - можете спросить вы. Тому есть две причины. Во-первых, руководство OOO «На все руки мастер» решило, наконец-то, завершить «эксперименты» по вводу стоимости расходуемых материалов руками и перейти на автоматический расчет стоимости расходуемых материалов «по среднему».

Во-вторых, в обработчике события «Обработка проведения» мы используем обращение к реквизиту «ВидНоменклатуры» справочника «Номенклатура» «через точку». Такое обращение может сильно замедлить скорость выполнения процедуры при больших объемах табличной части документа.

Поэтому, изменения, вносимые нами в документ «ОказаниеУслуги», будут преследовать две цели:

• определение стоимости расходуемых материалов при

проведении документа,

• повышение скорости выполнения процедуры.

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

 

Оптимизация процедуры проведения документа ОказаниеУслз

Особенности использования ссылочных данных

Т

ермином «ссылочные данные» мы будем обозначать данные, хранящиеся в базе данных, доступ к которым возможен при помощи объектов встроенного языка вида Ссылка: СправочникСсылка^имя>, ДокументСсылка.<имя> и т.д. Для того чтобы дальнейшее изложение было более понятным, мы построим объяснение на примере получения ссылки на вид номенклатуры при проведении документа «ОказаниеУслуги».

Не все данные, хранящиеся в базе данных, являются ссылочными. Это связано с тем, что в модели данных 1С:Предприятия 8.0 существует деление на данные, представляющие объектные сущности (справочники, планы счетов, документы и т.д.), и данные, представляющие необъектные сущности (регистры сведений, регистры накопления и т.д.).

С точки зрения системы, некоторая совокупность объектных данных определяется не только значениями своих полей, но и самим фактом своего существования. Другими словами, удалив из базы некоторую совокупность объектных данных, мы не сможем вернуть систему в то же состояние, которое было до удаления. Даже если мы заново создадим ту же самую совокупность объектных данных с теми же самыми значениями полей, с точки зрения системы это будет ДРУГАЯ совокупность объектных данных. Каждую такую совокупность объектных данных, уникальную с точки зрения системы, называют объектом базы данных. Для того чтобы система могла отличить один объект базы данных от другого, каждый объект базы данных (совокупность объектных данных) имеет внутренний идентификатор. Различные объекты базы данных всегда будут иметь различные внутренние идентификаторы. Этот идентификатор хранится вместе с остальными данными объекта в специальном поле «Ссылка».

Необъектные данные хранятся в виде записей, и с точки зрения системы определяются исключительно значениями своих полей. Таким образом, удалив некоторую запись и записав после этого новую, с точно такими же значениями всех полей, мы получим то же самое состояние базы данных, которое было до удаления.

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

 

 

такой указатель в полях других таблиц базы данных, выбирать его в поле ввода, указывать в параметрах запроса при поиске по ссылке и т.д. Во всех этих случаях как раз и будет использоваться объект встроенного языка вида Ссылка. Фактически этот объект хранит только внутренний идентификатор, находящийся в поле «Ссылка».

Например, если взять наш документ «ОказаниеУслуги», то в поле, хранящем реквизит табличной части «Номенклатура» на самом деле находится внутренний идентификатор, указывающий на элемент справочника «Номенклатура»:

 

приводит к тому, что мы просто читаем данные, хранящиеся в оперативной памяти:

Ссылка

Ссылка на Номенклатуру?

 

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

 

Когда в обработчике события «ОбработкаПроведения» документа «ОказаниеУслуги» мы присваиваем з^начение реквизита «Номенклатура» табличной части какой-либо переменной, мы имеем дело с объектом ДокументОбъект.ОказаниеУслуги. Этот объект содержит в себе значения всех реквизитов документа и реквизитов его табличных частей. Поэтому обращение:

 

Если ТекСтрокаПереченьНоменклатуры.Номенклатура.ВидНоменклатуры о

                                Перечисления.ВидыНоменклатуры.Материал Toгда

 

Движение.Материал = ТекСтрокаПереченьНоменклатуры.Номенклатура;

 

 

 

произойдет буквально следующее:

Ссылка на ВидНоменклатуры?

Ссылка ©

 

Поскольку в объекте ДокументОбъект.ОказаниеУслуги есть только ссылка на элемент справочника «Номенклатура» и больше никаких данных об этом элементе нет, система возьмет эту ссылку и обратится по ней в кэш объектов, в надежде найти там данные того объекта, ссылка на который у нее есть. Если кэш объектов не будет иметь нужных данных, он обратится к базе данных с тем, чтобы прочитать все данные объекта, ссылкой на который он обладает. После того, как все данные, хранящиеся в реквизитах нужного элемента справочника и в реквизитах его табличных частей, будут считаны в кэш объектов, кэш объектов вернет запрашиваемую ссылку, хранящуюся в реквизите «ВидНоменклатуры» справочника «Номенклатура».

Как несложно догадаться, подобное обращение к базе данных требует гораздо большего количества времени, нежели просто чтение из оперативной памяти. При интерактивном заполнении документа, подобные задержки ничтожно малы, по сравнению со скоростью работы пользователя. Однако при выполнении большого количества расчетов (например, при проведении больших документов, содержащих несколько тысяч строк), разница во времени может быть довольно заметной.

*? Узнай больше!

Более подробно об устройстве кэша объектов можно прочитать в главе «Кэш объектов» на странице 554.

Из всего вышесказанного можно сделать следующий вывод: если алгоритм проведения документа использует только те данные, которые присутствуют в реквизитах документа (и его табличных частей), вполне достаточно использовать конструктор движений документа (как это было у нас в случае с документом «ПриходнаяНакладная»). Если же в алгоритме проведения требуется анализировать дополнительные реквизиты объектов, ссылки на которые содержатся в документе, а также использовать результаты расчета итогов регистров, - следует использовать запросы для более быстрой выборки данных из базы данных.

To же самое справедливо в отношении выполнения любых участков программы, критичных по производительности. Механизм запросов лучше «читает» информационную базу и может за один раз выбрать все необходимые данные, поэтому, например, в типовых решениях вы практически не увидите использования объекта СправочникВыборка^имя>.

 

Оптимизация документа ОказаниеУслуги

П

ервое, что мы сделаем для оптимизации документа «ОказаниеУслуги» - удалим реквизит табличной части «Стоимость», который нам не понадобится в будущем.

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

После этого можно полностью удалить содержимое обработчика события «ОбработкаПроведения» в модуле документа и создать в нем заготовку процедуры проведения. Текст запроса, выполняемого в режиме оперативного проведения, будет отличаться от запроса, выполняемого при неоперативном проведении, поэтому формирование текста запроса мы включим в условие Если ... Иначе ... КонецЕсли:

Процедура ОбработкаПроведения(Отказ, Режим)

Запрос = Новый Запрос;

Если Режим = РежимПроведенияДокумента.Оперативный Тогда Запрос.Текст =

Иначе Запрос.Текст =

КонецЕсли; КонедПроцедуры

Вызовем конструктор запроса и раскроем таблицу

«ПереченьНоменклатуры»    табличной    части    документа

«ОказаниеУслуги» и выберем из нее поля:

• «Номенклатура»,

• «Количество»,

• «ВидНоменклатуры»,

• «Сумма».

Эти поля будут нужны нам для задания значений измерений регистров и их ресурсов. Кроме того, поле «ВидНоменклатуры» понадобится нам для анализа того, чем является номенклатура, указанная в документе: материалом или услугой:

 

Теперь задумаемся о том, что для указания значений ресурса «Стоимость» регистров «СтоимостьМатериалов» и «Продажи» нам понадобится рассчитать текущую стоимость номенклатуры как частное стоимости остатка этого материала и его оставшегося количества.

Поэтому добавим к списку выбранных таблиц еще две таблицы:

• «РегистрНакопления.СтоимостьМатериалов.Остатки»,

• «РегистрНакопления.ОстаткиМатериалов.Остатки»:

 

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

 

Условие получения данных указывает, что остатки должны быть получены только по тем позициям номенклатуры, которые содержатся в проводимом документе (перед выполнением запроса мы передадим в параметр «СписокНоменклатурыДокумента» список всех позиций номенклатуры, содержащихся в проводимом документе):

 

Кроме того, что подобный вариант снижает производительность конфигурации, могут возникать ситуации, когда результаты, полученные одним и другим способом, будут различны. Такое, например, вполне возможно при использовании виртуальной таблицы регистра сведений «СрезПоследних». Более подробно можно прочитать об этом на диске ИТС (информационно технологического сопровождения) в статье «Использование отборов в запросах с виртуальными таблицами».

После того, как будут заданы параметры обеих виртуальных таблиц регистров накопления, выберем из них поля «СтоимостьОстаток» и «КоличествоОстаток»:

 

f Узнай больше!

Следует внимательно подходить к использованию виртуальных таблиц запросов. В частности, необходимо уделять особое внимание максимально возможному использованию параметров этих таблиц. Например, в нашем случае можно было бы и не использовать параметр «Условие», а ограничить выбранные поля уже в самом запросе, указав вусловии ПОравенство номенклатуры из документа и материала из таблицы остатков. В результате мы получили бы тот же самый результат, однако no производительности этот способ сильно отличался бы от того, который мы используем.

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

Очевидно, что второй вариант будет работать дольше, и время выполнения такого запроса будет зависеть в основном не от количества данных, содержащихся в документе (т.е. реального количества обрабатываемой информации), а от размера регистра накопления.

 

 

Теперь вспомним о том, что документы «ОказаниеУслуги» могут быть проведены как в оперативном, так и в неоперативном режиме.

*" Узнай больше!

О концепции оперативного и неоперативного проведения документов можно прочитать в главе «Концепция оперативного и неоперативного проведения документов» на странице 541.

Поскольку в оперативном режиме нам понадобится контролировать остатки списываемой номенклатуры на складе, выберем еще раз виртуальную таблицу регистра накопления «ОстаткиМатериалов» и переименуем ее в «ОстаткиМатериаловОстаткиНаСкладе»:

 

Для этой виртуальной таблицы мы также укажем    тп

«МоментВремени», а в условии напишем, что материал должен находиться в списке номенклатуры и склад должен быть равен складу указанному в документе:

 

Теперь из этой виртуальной таблицы мы выберем поле «КоличествоОстаток»:

 

На этом формирование списка выбранных полей закончено, и мы можем перейти к заданию условий связи между выбранными таблицами. Каждая из виртуальных таблиц должна быть связана с таблицей документа таким образом, что для всех записей таблицы документа должны подбираться имеющиеся записи виртуальной таблицы, причем номенклатура в таблице документа должна быть равна материалу из виртуальной таблицы:

 

Оптимизация процедуры проведения документа ОказаниеУслуги

Теперь перейдем на закладку «Дополнительно» и установим флаг «Для изменения». Предложение ДЛЯ ИЗМЕНЕНИЯ позволяет заблаговременно заблокировать чтение указанных данных (которые мОгут читаться транзакцией другого соединения) уже при считывании, чтобы исключить взаимные блокировки при записи. Это предложение дает возможность указать в запросе таблицы, считываемые данные которых предполагается изменять.

<*- Узнай больше!

Более подробно об использовании предложения ДЛЯИЗМЕНЕНИЯ можно прочесть на диске ИТС (информационно-технологического сопровождения) в статье «Использование предложения ДЛЯ ИЗМЕНЕНИЯ в языке запросов».

Поскольку мы с вами планируем выполнить запись регистров накопления «ОстаткиМатериалов» и «СтоимостьМатериалов», укажем таблицы этих регистров в качестве таблиц для изменения:

 

 

 

 

Перейдем на закладку «Условия» и зададим условие отбора из таблицы документа только строк проводимого документа (ссылка на него будет передана в параметр запроса «Ссылка»):

Перейдем на закладку «Псевдонимы» и зададим следующИе псевдонимы полей:

•    «НоменклатураВидНоменклатуры» - «ВидНоменклатуры»,

•    «КличествоОстатокЬ> - «КоличествоНаСкладе».

Нажмем «ОК» и посмотрим, какой текст запроса сформировал конструктор:

 

| ОказаниеУслугиПереченьНоменклатуры.Ссылка = &Ссылка

|ДЛЯ ИЗМЕНЕНИЯ

| РегистрНакопления.ОстаткиМатериалов.Остатки, | РегистрНакопления.СтоимостьМатериалов.Остатки"; Иначе Запрос.Текст =

КонецПроцедуры

 

 

 

Процедура ОбработкаПроведения(Отказ, Режим) Запрос = Новый Запрос; Если Режим = РежимПроведенияДокумента.Оперативный Тогда

Запрос.Текст =

"ВЫБРАТЬ

| ОказаниеУслугиПереченьНоменклатуры.Номенклатура,

| ОказаниеУслугиПереченьНоменклатуры.Количество,

| ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры

| КАК ВидНоменклатуры.

I ОказаниеУслугиПереченьНоменклатуры.Сумма,

I ОстаткиМатериаловОстатки.КоличествоОстаток,

I СтоимостьМатериаловОстатки.СтоимостьОстаток,

I ОстаткиМатериаловОстаткиНаСкладе.КоличествоОстаток

I КАК КоличествоОстатокНаСкладе

«ИЗ

I Документ.ОказаниеУслуги.ПереченьНоменклатуры

1 КАК ОказаниеУслугиПереченьНоменклатуры

I ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьМатериалов.Остатки(

I    &МоментВремени,

I    Материал В (&СписокНоменклатурыДокумента))

I КАК СтоимостьМатериаловОстатки

1 ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

t    СтоимостъМатериаловОстатки.Материал

I ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиМатериалов.Остатки(

1    &МоментВремени,

I    Материал В (&СписокНоменклатурыДокумента))

I КАК ОстаткиМатериаловОстатки

I ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

I    ОстаткиМатериаловОстатки.Материал

I ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиМатериалов.Остатки(

I    &МоментВремени,

I    Материал В (&СписокНоменклатурыДокумента) И

I    Склад = &СкладВДокументе)

I КАК ОстаткиМатериаловОстаткиНаСкладе

I ПО ОказаниеУслутиПереченьНоменклатуры.Номенклатура =

I    ОстаткиМатериаловОстаткиНаСкладе.Материал

1ГДЕ    __

Как видите, в запросе нет ничего сложного за исключением, быть может, трех левых соединений с таблицей табличной части документа и использования ключевого предложения ДЛЯ ИЗМЕНЕНИЯ, значение которого было объяснено выше.

Текст запроса для случая неоперативного проведения документа будет практически таким же, за исключением того, что в нем будет отсутствовать третье левое соединение и, соответственно, поле «КоличествоОстатокНаСкладе», т.к. проверку остатков в этом случае мы выполнять не будем:

Иначе

Запрос.Текст = "ВЫБРАТЬ

| ОказаниеУслугиПереченьНоменклатуры.Номенклатура, | ОказаниеУслугиПереченьНоменклатуры.Количеотво, | ОказаниеУслугиПереченьНоменклатуры.Номенклатура.ВидНоменклатуры | КАК ВидНоменклатуры, | ОказаниеУслугиПереченьНоменклатуры.Сумма, | ОстаткиМатериаловОстатки.КоличествоОстаток, | СтоимостьМатериаловОстатки.СтоимостьОстаток |ИЗ

| Документ.ОказаниеУслуги.ПереченьНоменклатуры | КАК ОказаниеУслугиПереченьНоменклатуры | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьМатериалов.Остатки(

&МоментВремени,

Материал В (&СписокНоменклатурыДокумента)) I КАК СтоимостьМатериаловОстатки

I ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

I    СтоимостьМатериаловОстатки .Материал

I ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиМатериалов.Остатки(

I    &МоментВремени,

Материал В (&СписокНоменклатурыДокумента)) I КАК ОстаткиМатериаловОстатки I ПО ОказаниеУслугиПереченьНоменклатуры.Номенклатура =

 

|    ОстаткиМатериаловОстатки.Материал

|

|ГДЕ

| ОказаниеУслугиПереченьНоменклатуры.Ссылка = &Ссылка |

|ДЛЯ ИЗМЕНЕНИЯ

| РегистрНакопления.ОстаткиМатериалов.Остатки, | РегистрНакопления.СтоимостьМатериалов.Остатки"; КонецПроцедуры

Теперь добавим в текст обработчика задание параметров запроса:

Заирос.УстановитъПараметр("СкладВДокументе",Склад);

Иначе

Запрос.Текст = "ВЫБРАТЪ

| РегистрНакопления.ОстаткиМатериалов.Остатки"; КонецЕсли;

Запрос.УстановитьПараметрС'МоментВремени", МоментВремени()); Запрос.УстановитьПараметрО'СписокНоменклатурыДокумента",

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

Обратите внимание, что для формирования списка номенклатуры документа мы используем метод ВыгрузитьКолонку() объекта ДокументТабличнаяЧасть.ОказаниеУслуги.ПереченьНоменклат УРЫ.

После этого добавим получение результата запроса и цикл его обхода:

КонецЕсли;

Запрос.УстановитьПараметрС'МоментВремени", МоментВремени());

Запрос.УстановитьПараметрС'СписокНоменклатурыДокумента",

ПереченъНоменклатуры.ВыгрузитьКолонку(" Номенклатура")); Запрос.УстановитьПараметр("Ссылка",Ссылка);

ВыборкаРезультатаЗапроса = Запрос.Выполнить().Выбрать(); Пока ВыборкаРезультатаЗапроса.Следующий() Цикл

КонецЦикла;

КонецПроцедуры   

Теперь, прежде чем начать формирование движений по регистрам, нам нужно проверить наличие на складе достаточного количества номенклатуры:

КонецЕсли;

Запрос.УстановитьПараметр("МоментВремени", МоментВремени()); Запрос.УстановитьПараметр("СписокНоменклатурыДокумента",

ПереченьНоменклатуры.ВыгрузитьКолонкуС'Номенклатура")); Запрос.УстановитьПараметр("Ссылка",Ссылка);

ВыборкаРезультатаЗапроса = Запрос.Выполнить().Выбрать(); Пока ВыборкаРезультатаЗапроса.Следующий() Цикл

//Проверить остаток при оперативном проведении -Если Режим = РежимПроведенияДокумента.Оперативный Тогда Если ВыборкаРезультатаЗапроса.ВидНоменклатуры =

Перечисления.ВидыНоменклатуры.Материал Тогда Остаток = ?(Вы6оркаРезультатаЗапроса.КоличествоОстатокНаСкладе = NuH,

0,ВыборкаРезультатаЗапроса.КоличествоОстатокНаСкладе); Если Остаток < ВыборкаРезультатаЗапроса.Количество Тогда Сообщить("Материала " +

СокрЛП(ВыборкаРезультатаЗапроса.Номенклатура) +

" имеется только " + Остаток);

Отказ = Истина;

Возврат;

КонецЕсли;

КонецЕсли;   

 

 

КонедЕсли;

КонецЦикла; КонецПроцедуры

И в заключение добавим формирование движений по регистрам накопления:

КонецЕсли;

Запрос.УстановитьПараметр(" МоментВремени", МоментВремени());

Запрос.УстановитьПараметр(" СписокНоменклатурыДокумента",

ПереченьНоменклатуры.ВыгрузитьКолонкуС'Номенклатура")); Запрос.УстановнтьПараметр(" Ссылка" ,Ссылка);

ВыборкаРезультатаЗапроса = Запрос.Вьшолнить().Выбрать(); Пока ВыборкаРезультатаЗапроса.Следующий() Цикл

//Провернть остаток при оперативном проведении Если Режим — РежимПроведенияДокумента.Оперативный Тогда Если ВыборкаРезультатаЗапроса.ВидНоменклатуры =

Перечисления.ВидыНоменклатуры.МатериалТогда Остаток = ?(ВыборкаРезультатаЗапроса.КоличествоОстатокНаСкладе = Null,

0, ВыборкаРезультатаЗапроса.КоличествоОстатокНаСкладе); Если Остаток < ВыборкаРезультатаЗапроса.Количество Тогда Сообщить("Материала" +

СокрЛП(ВыборкаРезультатаЗапроса.Номенклатура) + " имеется только " + Остаток); Отказ = Истина; Возврат; КонецЕсли; КонецЕсли; КонецЕсли;

//Сформировать движения

Если ВыборкаРезультатаЗапроса.ВидНоменклатуры =

Перечисления.ВидыНоменклатуры.Материал Тогда

// регистр ОстаткиМатериалов Расход

Движение = Движения.ОстаткиМатериалов.Добавить();

Движение.ВидДвижения = ВидДвиженияНакопления.Расход;

Движение.Период = Дата;

Движение.Материал = ВыборкаРезулыатаЗапроса.Ноченклатура;

Движение.Склад = Склад;

Движение.Количество = ВыборкаРезультатаЗапроса.Количество;

// регистр СтоимостьМатериалов Расход

Движение = Движения.СтоимостьМатериалов.Добавить();

 

Движение.ВидДвижения = ВидДвиженияНакопления.Расход;

Движение.Период = Дата;

Движение.Материал = ВыборкаРезультатаЗапроса.Номенклатура;

//расчитать стоимость материала

СтоимостьМатериала =

?(ВыборкаРезультатаЗапроса.КоличествоОстаток = Null, 0, ВыборкаРезультатаЗапроса.СтоимостьОстаток / ВыборкаРезультатаЗапроса.КоличествоОстаток); Движение.Стоимость = СтоимостьМатериала *

ВыборкаРезультатаЗапроса.Количество; КонецЕсли;

// регистр Продажи

Движение = Движения.Продажи.Добавить();

Движение.Период = Дата;

Движение.Номенклатура = ВыборкаРезультатаЗанроса.Номенклатура;

Движение.Клиент = Клиент;

Движение.Мастер = Мастер;

Движение.Количество = ВыборкаРезультатаЗапроса.Количество;

Движение.Выручка = ВыборкаРезультатаЗапроса.Сумма;

Если ВыборкаРезультатаЗапроса.ВидНоменклатуры =

Перечисления.ВидыНоменклатуры.Материал Тогда

Движение.Стоимость = СтоимостьМатериала *

ВыборкаРезультатаЗапроса.Количество; Иначе

Движение.Стоимость = 0; КонецЕсли; КонецЦикла;

// записать движения регистров Движения.ОстаткиМатериалов.Записать();

Движения.СтоимостьМатериалов.Записан,(); Движения.Продажи.Записать();

КонецПроцедуры

Запустим 1С:Предприятие в режиме отладки и проверим работу нового обработчика события «ОбработкаПроведения», перепроведя все документы «ОказаниеУслуги».

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

Как в первом, так и во втором запросах мы использовали условие что материал должен находиться в списке значений, задаваемом одним из параметров запроса:

 

Что нового мы узнали

 

 

 

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьМатериалов.Остатки(

|    &МоментВремени,

Материал В (&СписокНоменклатурыДокумента))

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

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьМатериалов.Остатки(

|    &МоментВремени,

|    Материал В (ВЫБРАТЬ РАЗЛИЧНЫЕ Номенклатура

|    ИЗ

|    Документ.ОказаниеУслуги.ПереченьНоменклатуры

|    КАК ОказаниеУслугиПереченьНоменклатуры

|    ГДЕ ОказаниеУслугиПереченьНоменклатуры.Ссылка =

|    &Ссылка))

Выбор одного или другого решения требует сравнительных тестов

и зависит от конкретной информационной базы, размеров документа,

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

производительности компьютеров и т.д.

Теперь мы можем на некоторое время отвлечься от запросов, с которыми мы достаточно «плотно» работали в этой главе, и обратить свое внимание на не менее интересные возможности, которые предоставляет разработчику платформа 1С:Предприятие 8.0.

 

- как система 1С:Предприятие выполняет обращение к

ссылочным данным - как используется кэш объектов - почему для доступа к массивам данных информационной

базы предпочтительнее использовать запросы - как запросом получить остатки регистра накопления - когда следует использовать ключевое предложение ДЛЯ

ИЗМЕНЕНИЯ - на что следует обращать внимание при задании

параметров виртуальных таблиц запросов - почему при неоперативном проведении документов не

нужно контролировать остатки

- как и зачем можно передать вложенный запрос в параметры виртуальной таблицы

 

Глава 7. План видов характеристик

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

 

Постановка задачи

З

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

Описывать материалы пользователь сможет следующим образом: для каждого материала будет возможность создать некоторые (произвольные) характеристики этого материала (например, цвет, производитель и пр.). Затем, при поступлении материалов можно будет задать конкретные значения интересующих характеристик (например, при поступлении электрических кабелей можно будет указать, что они белого цвета и их сечение равно 2,5 мм2, а при поступлении резиновых шлангов указать, что они черного цвета и произведены на фирме «Fagumit Sp. z о.о.»).

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

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

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

 

Объект конфигурации План видов характеристик

О

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

В сущности, план видов характеристик очень напоминает справочник. Однако план видов характеристик имеет более узкую «специализацию»: он хранит, по сути, информацию только о том, какими видами характеристик может описываться какой-либо объект базы данных. Эта информация состоит из названия вида характеристики и ее типа. Разработчик и, что самое важное, пользователь могут задать в нем любое необходимое им количество видов характеристик.

Для того чтобы разработчик мог задать некий «набор» возможных типов значений, которые могут принимать виды характеристик, у объекта конфигурации План видов характеристик существует свойство Тип значения характеристик. Это свойство определяет составной тип данных, в который входят все типы, которые могут понадобиться при указании типа значения характеристики.

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

Тогда пользователь, создав новый вид характеристики «Цвет»,

сможет создать необходимые значения этого вида характеристики в

справочнике    дополнительных    значений    характеристик.

Примечательно, что этот справочник является подчиненным плану видов характеристик. Таким образом, если затем пользователь

 

пожелает создать новый вид характеристик «Запах» и создать его значения, он будет создавать их в том же самом справочнике дополнительных характеристик, и они не будут «смешиваться» со значениями цвета.

%Для тех, ктоработал с версией 7.7.

В версии 7.7 нет прямого соответствия прикладному объекту конфигурации план видов характеристик. Точнее всего будет сказать, что один план видов характеристик включает в себя me функциональные возможности, которыми в версии 7.7 обладали все объекты конфигурации вида «Вид субконто». Таким образом, в терминах 7.7, планы видов характеристик позволяют создавать несколько «наборов» объектов «Вид субконто».

Однако описание механизма ведения аналитического учета на счетах не является теперь основной задачей для плана видов характеристик. Использование подобного механизма было обобщено в виде возможности задания переменного количества свойств, которые могут описывать объект конфигурации. Причем возможность задания свойств существует как в режиме Конфигуратора, так и в режимеработы пользователя «1С:Предприятие».

Работа с планом счетов рассматривается теперь не как основное предназначение плана видов характеристик, а как частный случай, вытекающий из его возможностей. Конечно, как мы увидим далее, взаимодействие плана видов характеристик с планом счетов максимально автоматизировано средствами платформы (no сравнению с взаимодействием с другими объектами конфигурации). Однако основной акцент делается на универсальность механизма, предоставляемого планом видов характеристик. В частности это видно и из названия объекта, где вместо слова субконто (разрез аналитического учета) теперь используется слово характеристика, обозначающее свойство объекта конфигурации, описанное вне его самого (в другом объекте конфигурации).

<*" Узнай больше!

О структуре объектов встроенного языка, предназначенных для работы с планами видов характеристик, можно прочитать в главе «Планы видов характеристик» на странице 586.

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

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

 

Логическая связь объектов

Д

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

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

 

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

 

обладающие таким значением характеристики, и затем по ним и их владельцам получить остатки регистра накопления.

 

Реализация решения

Создание новых объектов конфигурации

К

ак мы уже говорили, нам понадобится создать несколько новых объектов конфигурации. Создадим объект конфигурации Справочник с именем «ВариантыНоменклатуры» и укажем, что он будет подчинен справочнику «Номенклатура».

Затем создадим еще один объект конфигурации Справочник с именем «ДополнительныеСвойстваНоменклатуры».

После этого создадим объект конфигурации План видов характеристик с именем «СвойстваНоменклатуры». Тип значения характеристик установим следующим:

• Число, длина 15, точность 3,

• Строка, длина 25,

• Дата,

• Булево,

• СправочникСсылка.ДополнительныеСвойстваНоменкла

туры:

 

 

Справочнику «ДополнительныеСвойстваНоменклатуры» укажем владельца - план видов характеристик «СвойстваНоменклатуры» После этого определим, что дополнительные значения характеристик плана видов характеристик будут располагаться в справочнике «ДополнительныеСвойстваНоменклатуры»:

 

В заключение создадим объект конфигурации Регистр сведений с именем «ЗначенияСвойствНоменклатуры».

Измерения регистра:

 

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

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

П

режде всего, в справочнике «Номенклатура» нам нужно обеспечить возможность редактирования варианта материала. Для этого укажем, что справочник «Номенклатура» будет редактироваться теперь обоими способами, в списке и в диалоге, и создадим основную форму элемента при помощи конструктора. Немного раздвинем форму по ширине и высоте и добавим в нее панель (Форма | Вставить элемент управления | Панель):

 

 

тип

• «НаборСвойств»,    ведущее,

СправочникСсылка.ВариантыНоменклатуры,

• «ВидСвойства»,    тип

ПланВидовХарактеристикСсылка.СвойстваНоменклатуры.

Ресурс регистра:

•    «Значение», тип Характеристика.СвойстваНоменклатурЫ-

Обратите внимание, что мы имеем возможность определить тип значения ресурса регистра, как Характеристика.<имя>. По сути, это

 

После того, как мы слегка изменим положение любой из границ панели, появится вопрос:

Теперь мы скорректируем размеры панели и добавим в нее новую страницу (добавление страницы - контекстное меню правой кнопки мыши на поле формы - Добавить страницу...):

 

 

На зтот вопрос мы ответим утвердительно, и все элементы управления переместятся в добавленную панель:

 

Зададим имя и заголовок новой страницы - «Свойства», а первую страницу также переименуем в «Основные» и зададим ей такой же заголовок (группа свойств «Текущая страница» в палитре свойств

формы):

 

 

После этого выделим все элементы управления, расположенные

панели,    и    выполним    команду

Форма | Центрирование | Центрировать по вертикали:

 

Теперь перейдем на страницу «Свойства» и добавим надпись «НадписьВариантыНоменклатуры» с заголовком «Варианты номенклатуры:». Укажем для нее начертание шрифта «Жирный».

Под этой надписью расположим табличное поле с командной

панелью    с    именем    «Варианты»    и    типом

СправочникСписок.ВариантыНоменклатуры. Из табличного поля удалим колонку «Код». Для этого табличного поля установим свойство «Связь по владельцу» - СправочникОбъект.Ссылка:

 

 

 

 

Установка этого свойства будет обеспечивать нам то, что для источника данных этого поля - реквизита формы «Варианты», имеющего тип СправочникСписок.ВариантыНоменклатуры, -значение отбора по владельцу всегда будет равно ссылке на редактируемый элемент справочника «Номенклатура». Иными словами, список справочника, содержащийся в реквизите формы «НаборСвойств» всегда будет содержать только элементы, подчиненные редактируемому элементу справочника «Номенклатура». А значит и табличное поле «Варианты», для которого этот реквизит является источником данных, будет отображать только элементы, подчиненные редактируемому элементу справочника «Номенклатура».

Ниже разместим аналогичным образом еще одну надпись «НадписьЗначенияСвойств» с заголовком «Значения свойств:» и начертанием шрифта «Жирный».:

 

Под ней расположим табличное поле с командной панелью с

именем    «Свойства»    и    типом

РегистрСведенийСписок.ЗначенияСвойствНоменклатуры. Для колонки «НаборСвойств» снимем флаг «Видимость», а для поля ввода в колонке «Значение» установим связь по типу -ЭлементыФормы.Свойства.ТекущиеДанные.ВидСвойства:

 

Связь по типу будет обеспечивать нам то, что тип значений, вводимых в это поле ввода, будет ограничен только типом характеристики, выбранной в поле «Вид свойства». Однако этим мы никак не можем повлиять на само значение, хранимое в этом поле. Если не предпринять никаких дополнительных действий, то получится, что в случае, когда в поле «Значение» было введено какое-либо значение, поменять его на значение другого вида характеристики не удастся. При выборе другого вида характеристики будет возникать несоответствие между типом хранимого значения и типом, которым ограничен ввод в элементе управления. В этом случае, естественно, система будет предлагать вводить тот тип, который имеет хранимое значение.

Чтобы избежать такой ситуации, нам нужно будет при смене значения в поле «Вид свойства» привести значение поля «Значение» к типу характеристики, выбранной в поле «Вид свойства».

Поэтому для поля ввода в колонке «Вид свойства» создадим обработчик события «При изменении»:

Процедура СвойстваВидСвойстваПриИзмененииЭлемент) ДанныеВидСвойства = ЭлементыФормы.Свойства.ТекущиеДанные.ВидСвойства; ЭлементыФормы.Свойства.ТекущиеДанные.Значение = ДанныеВидСвойства.ТипЗначения

.ПривестиЗначение(ЭлементыФормы.Свойства.ТекущиеДанные.Значение);

КоиецПроцедуры   

Теперь нам нужно сделать так, чтобы в табличном поле «Свойства» отображались записи регистра сведений, относящиеся только к выбранному в верхнем табличном поле элементу справочника «ВариантыНоменклатуры».

Поэтому для табличного поля «Варианты» создадим обработчик события «При активизации строки»:

ПроцедураВариантыПриАктивизацииСтрокиСЭлемент)

ЭлементыФормы.Свойства.Значение.Отбор.НаборСвойств

.Установить(Элемент.ТекущиеДанные.Ссылка, Истина); КонедПроцедуры

Кроме этого, чтобы не отображать весь регистр при открытии формы, создадим обработчик события формы «ПриОткрытии», содержащий следующий текст:

Процедура ПриОткрытии()

ЭлементыФормы.Свойства.Значение.Отбор.НаборСвойств.Установить(,Истина); КонедПроцедуры

 

Доработка справочника ВариантыНоменклатуры

Т

еперь нам следует доработать    справочник

«ВариантыНоменклатуры» таким образом, чтобы пользователь имел возможность создавать новые свойства материалов не только при редактировании самого материала, но и в процессе ввода документов, когда в табличную часть подбирается набор свойств.

Поэтому для справочника «ВариантыНоменклатуры» укажем, что он будет редактироваться обоими способами (как в списке, так и в диалоге) и создадим с помощью конструктора основную форму элемента.

Доработка    формы    элемента    справочника

«ВариантыНоменклатуры» будет сводиться, по большому счету, к тем же действиям, которые мы выполнили с формой справочника «Номенклатура». В форме нам нужно будет расположить табличное поле, которое должно отображать существующие в регистре сведений записи о значениях свойств для этого элемента справочника.

Откроем основную форму элемента справочника

«ВариантыНоменклатуры» и раздвинем форму вниз. На

освободившемся пространстве поместим табличное поле с именем

«Свойства»,    типом

РегистрСведенийСписок.ЗначенияСвойствНоменклатуры и командной панелью. Для колонки «НаборСвойств» снимем флаг видимости:

 

 

Затем для поля ввода, расположенного в колонке «Значение»

зададим    связь    по    типу

ЭлементыФормы.Свойства.ТекущиеДанные.ВидСвойства.

Для поля ввода, расположенного в колонке «ВидСвойства» создадим обработчик события «ПриИзменении»:

И в заключение нужно предусмотреть возможность того, что пользователь может начать задавать новые значения свойств, не записав еще сам элемент справочника «НаборыСвойств».

Поэтому создадим обработчик события табличного поля «ПередНачаломДобавления»:

 

Процедура СвойстваВидСвойстваПриИзменении(Элемент)

ДанныеВидСвойства = ЭлементыФормы.Свойства.ТекущиеДанные.ВидСвойства; ЭлементыФормы.Свойства.ТекущиеДанные.Значение = ДанныеВидСвойства.ТипЗначения

.ПривестиЗначение(ЭлементыФормы.Свойства.ТекущиеДанные.Значение); КоиедПроцедуры

 

Процедура СвойстваЛередНачаломДобавления(Элемент, Отказ, Копирование)

Если ЭтоНовый() Тогда Записать();

КонецЕсли; КонецПроцедуры

 

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

Узнай больше!

О событиях, связанных с формой, можно прочитать в главе «События, связанные с формой» на странице 547.

Прежде    всего,    создадим    обработчик    события

«ПриИзмененииСсылки», в котором установим требуемый нам отбор:

Процедура ПриИзмененииСсылки(ПутьКДанным)

Cвойства.Отбор.Ha6opCвойств.Установить(Cсылка,"Истина"); КонецПроцедуры

 

Доработка регистра ОстаткиМатериалов

Д

ля того чтобы обеспечить учет материалов по значениям

характеристик нам нужно будет изменить структуру регистра

накопления «ОстаткиМатериалов» и добавить в него новое

измерение    «НаборСвойств»    с    типом

СправочникСсылка.ВариантыНоменклатуры:

 

 

 

 

Затем в тело модуля формы добавим вызов этого обработчика:

 

Доработка документа ПриходнаяНакладная

 

 

 

ПодключитьОбработчикИзмененияДанныхССправочникОбъект.Ссылка",

"ПриИзмененииСсылкн");

 

П

 

оследнее, что нам осталось - доработать документ «ПриходнаяНакладная». Для того чтобы при приходовании товаров пользователь мог указывать набор свойств для каждого приходуемого материала, добавим в табличную

 

 

 

часть документа новый реквизит «НаборСвойств» с типом СправочникСсылка.ВариантыНоменклатуры:

 

После этого расположим этот реквизит в табличном поле формы документа (правая кнопка мыши - Размещение данных):

 

 

элементов справочника «ВариантыНоменклатуры», подчиненных материалу, выбранному в колонке «Материал».

В заключение откроем процедуру обработки проведения в модуле документа и добавим к формируемым движениям присвоение значения измерению «НаборСвойств»:

Процедура ОбработкаПроведения(Отказ, Режим) //{{__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ // Данный фрагмент построен конструктором. // При повторном использовании конструктора, // внесенные вручную изменения будут утеряны!!! Для Каждого ТекСтрокаМатериалы Из Материалы Цикл

// регистр ОстаткиМатериалов Приход

Движение = Движения.ОстаткиМатериалов.Добавить();

Движение.ВидДвижения = ВидДвиженияНакопления.Приход;

Движение.Период = Дата;

Движение.Материал = ТекСтрокаМатериалы.Материал;

Движение.НаборСвойств = ТекСтрокаМатериалы.НаборСвойств;

Движение.Склад = Склад;

Движение.Количество = ТекСтрокаМатериалы.Количество; КонецЦикла; Для Каждого ТекСтрокаМатериалы Из Материалы Цикл

// регистр СтоимостьМатериалов Приход

Движение = Движения.СтоимостьМатериалов.Добавить();

Движение.ВидДвижения = ВидДвиженияНакопления.Приход;

Движение.Период = Дата;

Движение.Материал = ТекСтрокаМатериалы.Материал;

Движение.Стоимость = ТекСтрокаМатериалы.Сумма; КонецЦикла;

// записываем движения регистров Движения.ОстаткиМатериалов.Записать(); Движения.СтоимостьМатериалов.Записать(); Движения.Управленческий.Записать();

//}}_KOHCTPУКТР_ДВИЖЕНИЙ_PEГИCTPOB КонецПроцедуры

Теперь запустим 1С:Предприятие в режиме отладки и создадим несколько наборов свойств для наших материалов.

Создание наборов свойств

 

 

 

Для поля ввода, расположенного в колонке «НаборСвойств» снова воспользуемся свойством «Связь по владельцу» ЭлементыФормы.Материалы.ТекущиеДанные.Материал. Теперь при выборе в этом поле ввода будет всегда открываться список

 

О

 

ткроем элемент    справочника «Номенклатура» - «Кабель

электрический».    Перейдем на закладку «Свойства» и

создадим набор    свойств этого элемента под названием

«Белый».

 

Он будет состоять их следующих характеристик:

• «Цвет» - «Белый»,

• «Сечение, мм2» - 2,5:

Этот набор свойств будет называться «Польша» и состоять из следующих характеристик:

• «Цвет» - «Черный»,

• «Производитель» - «Fagumit»:

 

 

 

Затем создадим набор свойств для элемента справочника «Номенклатура» - «Шланг резиновый».

Теперь откроем документ ПриходнаяНакладная No2 и укажем, что был закуплен белый электрический кабель в количестве 2 шт. и польский резиновый шланг.

 

Кроме этого посмотрим на записи, которые содержатся в регистре сведений «ЗначенияСвойствНоменклатуры»:

Затем скопируем первую строку документа и укажем, что был закуплен еще и черный электрический кабель в количестве 3 шт. (в процессе ввода нам придется создать еще один набор свойств для электрического кабеля - «черный», у которого «Цвет» - «Черный» и «Сечение» - 2,5):

 

Проведем документ и посмотрим на движения документа по регистру «ОстаткиМатериалов»:

 

 

 

Отчет ОстаткиМатериаловПоСвойствам

Д

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

Создадим новый объект конфигурации Отчет и назовем его «ОстаткиМатериаловПоСвойствам». Запустим конструктор выходной формы, и займемся конструированием запроса.

Исходными данными для нашего запроса будут являться материал, свойство и значение свойства. Причем нужно предусмотреть возможность того, что материал выбираться не будет, а будут указываться только свойство и его значение.

Таким образом, алгоритм получения результирующих данных будет распадаться на две части: сначала, по указанным свойству и его значению, нам нужно будет выбрать все наборы свойств из регистра сведений «ЗначенияСвойствНоменклатуры», которым сопоставлены указанно свойство с указанным значением. Затем, для выбранных наборов свойств и их владельцев нам нужно будет получить остатки и обороты из регистра накопления «ОстаткиМатериалов».

Для того чтобы обеспечить такую «двухуровневую» выборку данных, мы воспользуемся возможностью создания вложенных запросов.

Сначала мы создадим вторую часть нашего алгоритма - запрос к регистру накопления «ОстаткиМатериалов».

 

Выберем виртуальную таблицу регистра накопления «ОстаткиМатериалов.ОстаткиИОбороты». В параметрах виртуальной таблицы зададим условие отбора таким, что значение измерения регистра «НаборСвойств» должно находиться в списке, передаваемом в качестве параметра «СписокСвойств»:

 

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

Из виртуальной таблицы регистра накопления ;<ОстаткиМатериалов.ОстаткиИОбороты» выберем следующие поля:

• «ОстаткиМатериаловОстаткиИОбороты.Материал»,

• «ОстаткиМатериаловОстаткиИОбороты.НаборСвойств,

• «ОстаткиМатериаловОстаткиИОбороты.КоличествоНачальны

йОстаток»,

• «ОстаткиМатериаловОстаткиИОбороты.КоличествоПриход»,

• «ОстаткиМатериаловОстаткиИОбороты.КоличествоРасход»,

• «ОстаткиМатериаловОстаткиИОбороты.КоличествоКонечный

Остаток»:

 

 

 

 

После этого на закладке «Объединения/Псевдонимы» псевдонимы числовых полей без слова «Количество»:

 

зададим

 

На закладке «Отчет» сбросим флаг «Использовать построитель отчета», а на закладке «ВыходнаяФорма» укажем, что не нужно редактировать в форме параметр «СписокСвойств».

На этом создание первого запроса завершено. Нажмем «ОК».

Откроем модуль формы и удалим элементы текста, которые нам не

понадобятся.    В    процедуре

«ДействияФормыОстаткиМатериаловПоСвойствамСформировать»

 

удалим второй параметр при «ОстаткиМатериаловПоСвойствам»:

 

вызове

 

процедуры

 

//Запрос.УстановитьПараметр("СписокСвойств",СписокСвойств);

Результат = Запрос.Выполнить();

 

 

 

ПроцедураДействияФормыОстаткиМатериаловПоСвойствамСформировать(Кнопка) //{{КОНСТРУКТОР_ВЫХОДНЫХ_ФОРМ_ПРОЦЕДУРА_ВЫЗОВА( //ОстаткиМатериаловПоСвойствам) // Данный фрагмент построен конструктором. // При повторном использовании конструктора, // внесенные вручную изменения будут утеряны!!!

ТабДок = ЭлементыФормы.ПолеТабличногоДокумента; ОстаткиМатериаловПоСвойствам(ТабДок);

//}}КОНСТРУКТОР_ВЫХОДНИЫХ ФОРМ_ПРОЦЕДУРА_ВЫЗОВА

КонецПроцедуры

После этого в процедуре «ОстаткиМатериаловПоСвойствам» соответствующим образом изменим строку объявления процедуры и затем удалим строку, устанавливающую параметр запроса:

Процедура ОстаткиМатериаловПоСвойствам(ТабДок) Экспорт //{{КОНСТРУКТОР_ВЫХОДНЫХ_ФОРМ(ОстаткиМатериаловПоСвойствам) //Данный фрагмент построен конструктором. // При повторном использовании конструктора, // внесенные вручную изменения будут утеряны!!!

Макет = ОтчетОбъект.ПолучитьМакет("ОстаткиМатериаловПоСвойствам"); Запрос = Новый Запрос; Запрос.Текст * "ВЫБРАТЬ

|ОстаткиМатериаловОстаткиИОбороты.Материал, |ОстаткиМатериаловОстаткиИОбороты.Материал.Представление, |ОстаткиМатериаловОстаткиИОбороты. НаборСвойств, |ОстаткиМатериаловОстаткиИОбороты.НаборСвойств.Представление, |ОстаткиМатериаловОстаткиИОбороты.КоличествоНачальныйОстаток

|КАК НачальныйОстаток, |ОстаткиМатериаловОстаткиИОбороты.КоличествоПриход

|КАК Приход, |ОстаткиМатериаловОстаткиИОбороты.КоличествоРасход

|КАК Расход, |ОстаткиМатериаловОстаткиИОбороты.КоличествоКонечныйОстаток

|КАК КонечныйОстаток |ИЗ |РегистрНакопления.ОстаткиМатериалов.ОстаткиИОбороты(,,,,

|НаборСвойств В (&СписокСвойств))

|КАК ОстаткиМатериаловОстаткиИОбороты";    ^   

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

Обладая достаточными навыками написания запросов, мы могли бы вручную, вместо «&СписокСвойств» написать текст вложенного запроса. Но, поскольку мы только осваиваем язык запросов, воспользуемся более комфортным способом: создадим текст вложенного запроса при помощи конструктора, а затем просто скопируем его в нужное нам место модуля. Для этого выполним команду Текст | Конструктор запроса...

В качестве исходных данных вложенного запроса выберем таблицу регистра сведений «ЗначенияСвойствНоменклатуры». Из нее выберем единственное поле - «ЗначенияСвойствМатериалов.НаборСвойств».

Зададим условия выборки. Прежде всего, владелец набора свойств должен быть равен переданному в параметре «Материал» материалу:

ЗначенияСвойствНоменклатуры.НаборСвойств.Владелед = &Материал

Затем укажем, что вид свойства должен быть равен переданному в параметре «ВидСвойства» значению:

ЗначенияСвойствНоменклатуры.ВидСвойства = &ВидСвойства

 

 

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

ЗначенияСвойствНоменклатуры.Значение = &Значение

 

 

|    из

I    РегистрСведений.ЗначенияСвойствНоменклатуры

I    КАК ЗначенияСвойствНоменклатуры

I

I    ГДЕ

I    ЗначенияСвойствНоменклатуры.НаборСвойств.Владелец = &Материал И

I    ЗначенияСвойствНоменклатуры.ВидСвойства = &ВидСвойства И

I    ЗначенияСвойствНоменклатуры.Значение = &Значение))

|    КАК ОстаткиМатериаловОстаткиИОбороты";

Результат = Запрос.Выполнить();

 

 

 

Вложенный запрос готов. Теперь нажмем кнопку «Запрос», расположенную в нижней части окна конструктора запроса, выделим и скопируем текст запроса в буфер обмена Windows. Закроем окно с текстом запроса и нажмем «Отмена» в конструкторе запроса. Теперь вставим текст из буфера обмена вместо параметра в созданный нами ранее запрос:

Процедура ОстаткиМатериаловПоСвойствам(ТабДок) Экспорт //{{КОНСТРУКТОРЗЬПГОДНЬГХ^ЮРМСОстаткиМатериаловПоСвойствам) // Данный фрагмент построен конструктором. // При повторном использовании конструктора, // внесенные вручную изменения будут утеряны!!!

Макет = ОтчетОбъект.ПолучитьМакетС'ОстаткиМатериаловПоСвойствам"); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ

| ОстаткиМатериаловОстаткиИОбороты.Материал, | ОстаткиМатериажовОстаткиИОбороты.Материал.Представление, | ОстаткиМатериаловОстаткиИОбороты.НаборСвойств, | ОстаткиМатериаловОстаткиИОбороты.НаборСвойств.Представление, | ОстаткиМатериаловОстаткиИОбороты.КоличествоНачальныйОстаток | КАК НачальныйОстаток,

| ОстаткиМатериаловОстаткиИОбороты.КоличествоПриход | КАК Приход,

| ОстаткиМатериаловОстаткиИОбороты.КоличествоРасход | КАК Расход,

| ОстаткиМатериаловОстаткиИОбороты.КоличествоКонечныйОстаток | КАК КонечныйОстаток |ИЗ

| РегистрНакопления.ОстаткиМатериалов.ОстаткиИОбороты(,,,, | НаборСвойств В (ВЫБРАТЬ |ЗначенияСвойствНоменклатуры.НаборСвойств

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

Процедура ОетаткиМатериаловПоСвойствамСТабДок) Экспорт //{{КОНСТРУКТОР_ВЬКОДНЫХ_ФОРМ(ОстаткиМатериаяовПоСвойствам) // Данный фрагмент построен конструктором. // При повторном использовании конструктора, // внесенные вручную изменения будут утеряны!!!

Макет = ОтчетОбъект.ПолучитьМакетС'ОстаткиМатериаловПоСвойствам");

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ОстаткиМатериаловОстаткиИОбороты.Материал,

| ОстаткиМатериаловОстаткиИОбороты.Материал.Представление,

| ОстаткиМатериаловОстаткиИОбороты.НаборСвойств,

| ОстаткиМатериаловОстаткиИОбороты.НаборСвойств.Представление,

| ОстаткиМатериаловОстаткиИОбороты, КоличествоНачальныйОстаток

| КАК НачальныйОстаток,

| ОстаткиМатериаловОстаткиИОбороты.КоличествоПриход

| КАК Приход,

| ОстаткиМатериаловОстаткиИОбороты.КоличествоРасход

| КАК Расход,

| ОстаткиМатериаловОстаткиИОбороты.КоличествоКонечныйОстаток

| КАК КонечныйОстаток

|И3

| РегистрНакопления.ОстаткиМатериалов.ОстаткиИОбороты(,,,,

|    НаборСвойствВ (ВЫБРАТЬ

|    ЗначенияСвойствНоменклатуры.НаборСвойств

|    ИЗ

|    РегистрСведений.ЗначенияСвойствНоменклатуры

|    КАК ЗначенияСвойствНоменклатуры

 

 

I    ГДЕ

l";

Если Не Материал.ПустаяО тогда Запрос.Текст = Запрос.Текст +

"ЗначенияСвойствНоменклатуры.НаборСвойств.Владелец = Материал И

|"; КонецЕсли;

Запрос.Текст = Запрос.Текст +

ЗначенияСвойствНоменклатуры.ВидСвойства = &ВидСвойства И

I    ЗначенияСвойствНоменклатуры.Значение = &Значение))

I    КАК ОстаткиМатериаловОстаткиИОбороты";

Результат = Запрос.Выполнить();

После этого добавим в текст модуля установку параметров запроса:

Процедура ОстаткиМатериаловПоСвойетвам(ТабДок) Экспорт //{{КОНСТРУКТОР_ВЫХОДНИЫХ ФОРМ) // Данный фрагмент построен конструктором. // При повторном использовании конструктора, // внесенные вручную изменения будут утеряны!!!

 

Если Не Материал.Пустая() тогда Запрос.Текст = Запрос.Текст +

"ЗначенияСвойствНоменклатуры.НаборСвойств.Владелец = &Материал И

КонецЕсли;

Запрос.Текст = Запрос.Текст +

"    ЗначенияСвойствНоменклатуры.ВидСвойства = &ВидСвойства И

|    ЗначенияСвойствНоменклатуры.Значение = &Значение))

|    КАК ОстаткиМатериаловОстаткийОбороты";

Если Не Материал.Пустая() тогда

Запрос.УстановитьПараметр('' Материал", Материал); КонецЕсли;

Запрос.УстановитьПараметр("ВидСвойства", ВидСвойства); Запрос.УстановитьПараметр('Значение", Значение);

Результат = Запрос.Выполнить();

Теперь последнее, что нам осталось сделать - это разместить в форме поля для ввода параметров запроса.

Макет = ОтчетОбъект.ПолучитьМакет("ОстаткиМатериаловПоСвойствам"); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЪ

|ОстаткиМатериаловОстаткиИОбороты.Материал, |ОстаткиМатериаловОстаткиИОбороты.Материал.Представление, |ОстаткиМатериаловОстаткиИОбороты.НаборСвойств, |ОстаткиМатериаловОстаткиИОбороты.НаборСвойств.Представление, |ОстаткиМатериаловОстаткиИОбороты.КоличествоНачальныйОстаток

|КАК НачальныйОстаток, |ОстаткиМатериаловОстаткиИОбороты.КоличествоПриход

|КАК Приход, |ОстаткиМатериаловОстаткиИОбороты.КояичествоРасход

|КАК Расход, |ОстаткиМатериаловОстаткиИОбороты.КоличествоКонечныйОстаток

|КАК КонечныйОстаток |ИЗ

|РегистрНакопления.ОстаткиМатериалов.ОстаткиИОбороты(,,,, |НаборСвойств В (ВЫБРАТЬ

|ЗначенияСвойствНоменклатуры.НаборСвойств |ИЗ |РегистрСведений.ЗначенияСвойствНоменклатуры

|КАК ЗначенияСвойствНоменклатуры |ГДЕ

 

Откроем форму отчета и разместим на ней три поля ввода:

• «Материал» с типом СправочникСсылка.Номенклатура,

• «ВидСвойства»    с    типом

ПланВидовХарактеристикСсылка.СвойстваНоменклатур

ы,

• «Значение»    с    типом

Характеристика.СвойстваНоменклатуры:

 

Для поля ввода «Материал» установим свойство «Выбор групп и элементов» как «Элементы».

Для поля ввода «Значение» установим связь по типу с реквизитом «ВидСвойства». А для поля ввода «ВидСвойства» создадим обработчик события «ПриИзменении»:

На этом создание отчета завершено. Запустим 1С:Предприятие в режиме отладки и посмотрим, какие результаты можно получить с помощью нашего отчета.

Сначала посмотрим, какие у нас есть материалы с сечением 2,5

мм2:

 

Затем посмотрим, какие у нас есть материалы черного цвета:

 

 

Процедура ВидСвойстваПриИзменении(Элемеит)

Значение = ВидСвойства.ТипЗначения.ПривестиЗначение(Значение); КонецПроцедуры

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

 

Что нового мы узнали

 

 

Таким образом, вы убедились в том, что при использовании данной логической схемы мы имеем теперь возможность вести учет материалов в произвольном количестве разрезов свойств и их значений.

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

 

- для чего предназначен объект конфигурации План видов характеристик

- в чем принципиальное отличие плана вида характеристик

от справочника - что такое тип значения характеристик

- зачем нужны дополнительные значения характеристик - как, используя план видов характеристик, организовать

учет по переменному количеству характеристик - как создать план видов характеристик

- как добавить новую панель в форму и добавить страницы - как перенести элементы управления в новую панель - что такое связь по типу - что такое связь по владельцу - как обработать конфликтные ситуации при работе со

связью по типу

- как назначить обработчик события изменения данных - как ограничить выборку виртуальной таблицы результатом вложенного запроса

 

 



  Copyright © 2007 Udex.Ru

Hosted by uCoz