gifts2017

Допиливаем форму выбора серий номенклатуры для отображения остатков

Опубликовал Юрий Ачкасов (practik1c) в раздел Программирование - Практика программирования

В этой статье я хочу рассмотреть задачу, которая довольно часто возникает у начинающих (и не только) разработчиков, адаптирующих типовые конфигурации (УТ, КА, УПП) на предприятиях торговли. Речь пойдет про отображение остатков в форме выбора серий номенклатуры при подборе в документы. Это актуально в тех случаях, когда не ведется партионный учет по сериям, либо когда документы вводятся неоперативно и нет возможности воспользоваться волшебной кнопкой "Заполнить и провести". На первый взгляд задача банальна, но я хочу показать некоторые "грабли", на которые часто наступают новички  в процессе ее реализации, а также сопоставлю алгоритмы решения на платформе 8.1 и 8.2.

Не вполне серьезная статья о вполне реальной, но часто неверно решаемой задаче. (Новичкам рекомендуется).

Итак приступим: в качестве подопытной возьмем типовую конфигурацию УТ ред. 10.3. Предполагается, что конфигурация работает на платформе 8.2 и снята с поддержки (включена возможность изменения).

 

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Ну вот, теперь можем приниматься за доработку формы списка...хотя стоп (!), возникает резонный вопрос: а зачем мы тогда ставили эту самую «галку» ? Согласен, мы не будем дорабатывать старую и толстую форму (смайл), а вместо этого создадим новую «тонкую» да к тому же еще и управляемую (хитрый смайл). Но прежде  я мысленно вернусь на несколько лет в прошлое и представлю, как бы все это выглядело имей мы дело со старушкой 8.1 Smile

Собственно, делов-то! Берем форму, добавляем на нее колонку Остаток, ну а получение и вывод на экран конечно же делаем в обработчике ПриВыводеСтроки()табличного поля. Примерно так:

Часто сталкиваюсь с таким кодом. В принципе он рабочий, но методически неверный. Во-первых неверно само размещение запроса на получение остатков в процедуре ПриВыводеСтроки(). Ведь в этом случае при выводе каждой строки будет идти обращение к базе данных и работать все это хозяйство будет неэффективно, в чем мы сможем убедиться, запустив базу в файловом режиме на слабеньком офисном ПК 2005 г.в. (кои встречаются достаточно часто). При большом количестве строк в списке - слайд-шоу гарантировано Smile. На эти грабли наступают многие новички не дошедшие пока в списке обработчиков до события ПриПолученииДанных(), а ведь оно как раз для этих целей и предназначено. Так ладно, с этим понятно, переделаем. Но ведь и  остатки мы получаем не верно: во первых общие по всем складам, а во-вторых на текущую дату. А на практике как правило складов используется несколько, да и документы могут проводится «задним числом». В этом случае ситуация усложняется. Придется каким-то образом передавать в открываемую форму данные по складу и дате остатков. В этом нам поможет обработчик поля ввода СерииНоменклатуры  НачалоВыбора(). Перво-наперво отрубаем СтандартнуюОбработку, присвоив ей значение Ложь. Дальше возможны варианты:

1)  ФормаВыбораСерий = Справочники.СерииНоменклатуры.ПолучитьФормуВыбора(,ЭтаФорма);

     ФормаВыбораСерий.ОткрытьМодально();

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

2) Более правильным представляется вариант с созданием реквизита (или экспортной переменной)  «СтруктураПараметров» (тип Структура) в форме выбора серий, и дальнейшей передачей значений в эту переменную в обработчике  НачалоВыбора(). В этом случае процедура примет вид:

Так, но это еще не все. Если теперь запустить программу в пользовательском режиме и попробовать выбрать серию, мы наступим на очередные «грабли». Когда мы отключили стандартную обработку, у нас потерялась связь серии с ее владельцем номенклатурой, поэтому сперва будет открываться форма выбора номенклатуры, а потом уже подчиненного справочника серий, что конечно же очень антигуманно по отношению к пользователям. Исправить ситуацию нам поможет такое замечательное свойство формы  (замечу только в толстом клиенте, в тонком все выглядит несколько иначе, об этом далее) как ПараметрВыборПоВладельцу, сюда нужно передать ссылку на номенклатуру владельца. Запускаем 1С:Предприятие, открываем документ реализации, нажимаем на педальку выбора серии и вуаля - очередные грабли!

Так, разбираемся...и натыкаемся еще на одно интересное свойство формы ПараметрОтборПоВладельцу. Эврика! Вот она где собака зарыта. Присваиваем ему значение нашей номенклатуры и теперь действительно все работает как надо. Конечно не все нюансы еще учтены. Например мы передаем в качестве параметра «ДатаОстатков» дату документа, но у нас на временной оси в пределах одной секунды может находится множество документов, поэтому правильнее было бы передавать МоментВремени документа, который можно получить используя одноименный метод. Вот как это должно выглядеть:

СтруктураПараметров.Вставить("ДатаОстатков",  МоментВремени());

Но и это еще не все! Laughing  Форма открывается с  отбором по владельцу, остатки показываются, но теперь перестала позиционироваться текущая строка, т.е. при открытии списка она все время находится на первой.

Для решения проблемы нужно в обработчике ПриОткрытии() теперь уже формы выбора серий присваивать свойству  ПараметрТекущаяСтрока значение нашей серии. Вот теперь после стольких мытарств все работает более и менее корректно.

 


 

В общем-то вся эта демагогия была присуща старой версии платформы, и мы сейчас посмотрим как это же самое делается в платформе 8.2 в управляемой форме (помните про галку? Cool ).

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

Итак приступим. Создаем новую форму выбора, тип указываем Управляемая, на следующей вкладке выбираем отображаемые реквизиты, жмякаем ОК - форма готова. А куда нам теперь сваять колонку с остатками? Куда ее добавлять? В элементы (это те, что слева) или в реквизиты (это те что справа)? Я так отвечу: никуда не нужно ничего добавлять, чуть позже она сама волшебным образом появиться на форме.

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

 Рестартим 1С и убеждаемся, что теперь все работатет.

ОК, сделали. Но где теперь искать событие «ПриПолученииДанных», в котором мы будем получать наши остатки? Спешу вас обрадовать, в платфторме 8.2 все делается намного проще, а все благодаря новому замечательному объекту «ДинамическийСписок» и  он-то  у нас является основным реквизитом формы. А это значит, что мы имеем полное на то право воспользоваться одной из его фишек, а именно указанием произвольного запроса. Для этого в свойствах реквизита Список (открывается через палитру свойств) ставим одноименную галку.

Теперь нажимаем на гиперссылку Открыть и видим....минуточку, где-то я это уже видел! Ах да, это та самая СКД, которая в 8.1 использовалась для построения отчетов. А вот в 8.2 на ней построены практически все списки справочников, документов и т.д. Подробно описывать свойства динамического списка я не буду, т.к. это уже выходит за пределы нашего повествования. Для нас сейчас имеет значение лишь возможность указания произвольного запроса, чем мы собственно и займемся!

Итак, у нас открылось вот такое окошко.

 

Нажимаем кнопку конструктор и конструируем наш запрос . Все поля  что были оставляем и добавляем левое соединение к ВТ таблице регистра ТоварыНаСкладахОстатки. Вот так может выглядеть текст запроса.

Сохраняем запрос и закрываем форму редактирования динамического списка. Так, что-то на форме пока не наблюдается никаких изменений, колонки как не было, так и нет. А вот и не правда Wink Она появилась в качестве реквизитов самого списка и теперь нам всего-навсего осталось перетащить ее в поле элементов списка. Вот что должно получиться в результате:

Ну вот, список готов, запрос ждет своего исполнения и все бы хорошо, но теперь не понятно, откуда платформа будет получать значения параметров в ВТ остатков? Видимо должен быть какой-то интерфейс для их передачи в запрос динамического списка. И он действительно есть, а выглядит это очень похоже на установку параметров стандартного запроса:

Список.Параметры.УстановитьЗначениеПараметра(«ИмяПараметра», ЗначениеПараметра);

Ну а дальше скорее всего остается также как и было на 8.1. Создаем структуру, затем передаем ее в реквизит (или параметр?...а может экспортную переменную?), все...алес, приплыли. Эх была ни была, сделаю как в 8.1 (здесь я специально утрирую, чтобы показать реальную ситутацию, а она к сожалению такова, что до сих пор многие работают методом тыка, не особо заботясь о корректности выбранного решения, реботает?...ну и ладно! ). Так бррр..., о чем это я? Ах да, создаем реквизит СтруктураПараметров и передаем ее также из обработчика НачалоВыбора() из документа.

Итак как передавать параметры решили, но как их получать в форме выбора серий? Точнее не как, а где именно? Первое, что приходит в голову - в процедуре ПриОткрытии(). Но это опять же неправильное решение. И вот почему. В платформе 8.2 управляемая форма существует одновременно на сервере и на клиенте, находясь при этом в разных контекстах. Обращение к базе данных возможно только из серверного контекста. Поэтому форма сперва создается на сервере, «приезжает» на клиента и только потом уже в клиентском контексте срабатывает обработчик ПриОткрытии(), который в нашем случае снова будет обращаться к серверу за данными. Таким образом правильно получать и устанавливать параметры запроса в процедуре ПриСозданииНаСервере().

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

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

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

Ну вот наконец-то все готово. Запускаем, пробуем...ура работает! Но не спешите радоваться, не все нюансы мы с вами учли: во первых мы не совсем корректно построили сам запрос. У нас жестко прописаны параметры Номенклатура и Склад, и допустим при открытии из формы документа мы нормально передадим эти параметры и запрос отработает корректно. Но что будет, если пользователь просто откроет форму выбора? Правильно - платформа выдаст ошибку, что значения параметров не установлены. Поэтому включаем смекалку и дорабатываем процедуру ПриСозданииНаСервере() и текст самого запроса. В конечном итого получаем следующие листинги:

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

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

 

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Ю М (mtv:)) 25.09.11 08:36
Статья, безусловно, полезная.
Но очень неудобно то, что код вставлен картинками, а не текстом. Невозможно перенести код простым копированием. Приходится набивать вручную… :( . Это портит общее впечатление от публикации.
Хотя все равно плюс.
Alex_will; +1 Ответить
2. Юрий Ачкасов (practik1c) 29.09.11 00:41
Собственно сделал картинками потому что форматирование кода жутко неудобное да и раскраска не та :)
Но плюсы тоже есть, когда не копипастишь, а набираешь сам - усваяемость сильно лучше! ;)
3. StarkV (starkv) 15.10.11 15:49
Может я что-то и не то сделал, но кажется есть ошибочка, не происходит выбор серии
из-за (Стандартная обработка = ложь)
Я сделал так:

ВыбраннаяСерия = ОткрытьФормуМодально("Справочник.СерииНоменклатуры.ФормаВыбора",СтруктураПараметров);

Если ТипЗнч(ВыбраннаяСерия) = Тип("СправочникСсылка.Серииноменклатуры")Тогда
ТекущиеДанные.СерияНоменклатуры = ВыбраннаяСерия;
КонецЕсли;
ПодводныйТ; zhurba; +2 Ответить
4. Александр Синцов (Sintson) 19.11.11 22:01
мАлАдец, тильки как с извечным вопросом обновления совладать, но это, как говориться ничего личного, больше к 1С вопрос, а так, тема здравая, я так же делал.
5. Дмитрий Виссарионов (Dwiss) 22.12.11 17:54
Помоему здесь ошибочка
ДатаОстатков = <<?>>мТекущяДата(); (Проверка: Толстый клиент (обычное приложение))
ТекущаяДата() работать не будет нужно использовать
ТекущаяУниверсальнаяДата()
Синтаксических ошибок не обнаружено!
6. Денис Лихошерстов (Hans) 08.01.12 17:25
Желательно бы то же самое только для табличной части документа под управляемые формы.
7. Алла Назарова (nav1971) 11.01.12 19:21
а куда делась статья? виднго только описание!
8. Роман Мишкин (smilejka) 13.01.12 09:36
Как раз сегодня планировал заниматься такой задачей. Только мне необходимо реализовать в форме подбора номенклатуры.
Статья интересная +
9. Александр Прокопенко (babylon_5) 15.01.12 14:12
(7) Открой не в IE, а в другом браузере.
10. Сергей Графчиков (Sergeant82) 01.07.12 16:27
Огромное спасибо за публикацию! Очень выручила. Но у меня была не ТЧ, а просто Поле выбора на форме, и заработало только после добавления ", Элемент" в строке:
ОткрытьФормуМодально("Справочник.СерииНоменклатуры.ФормаВыбора",СтруктураПараметров, Элемент)
11. Роман (roma03v1) 22.08.12 20:29
Спасибо большое очень помогло, так как пока плохо программирую, очень сильно сэкономил мне время.
12. Кайрат Сапаров (Astrakhan_man) 29.10.12 12:36
Можно вопрос, как Вы передаете дополнительные параметры (склад) в форму выбора? но я на обычных формах.
13. Кайрат Сапаров (Astrakhan_man) 29.10.12 23:36
я создаю реквизит формы "СтруктураПараметров" с типов Произвольный (не понял как создать с типом структура), передаю в него данные
(ВыбраннаяСерия = ОткрытьФормуМодально("Справочник.СерииНоменклатуры.ФормаВыбора",СтруктураПараметров);)
, но в процедуре в "СправочникСписокПриПолученииДанных" пишет "Поле объекта не обнаружено (Склад)" где у меня ошибка.
14. Кайрат Сапаров (Astrakhan_man) 30.10.12 18:31
переделал на управляемые формы, и при открытие пишет такую ошибку "по причине:
Ошибка получения данных
по причине:
Ошибка создания набора данных "НаборДанныхДинамическогоСписка"
по причине:
Ошибка при исполнении запроса набора данных
по причине:
{(16, 5)}: Не задано значение параметра "Дата"
<<?>>&Дата,
"

в параметрах формы(у списка) я её задал. из формы передаю.
15. Екатерина Перетокина (katavyjob) 03.07.14 14:03
Жаль нет итоговых картинок работы данного механизма в самой программе((
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа