Пост

Флаг "Использовать ПОЧТИ всегда", или Нюанс динамических списков

Небольшая пятничная история по программной работе со строкой динамического списка.


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

Элементы.Список.ТекущиеДанные

Возьмём обычного новичка, который только начинает свой путь в 1С. Некий программист Вася.

Одним прекрасным вечером нашему разработчику понадобилось побыстрее оказаться дома. Но тут пользователь:

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

Звучит просто. И Вася сел за работу.

В первую очередь он “покрасил” кнопку.

Скрин

Ну вот! Уже половина задания сделана.

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

Вася создаёт обработчик события ПриАктивизацииСтроки(). И вносит свой несложный код:

1
2
3
4
5
6
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	
	Элементы.СделатьВсеХорошо.Видимость = ЗначениеЗаполнено(Элементы.Список.ТекущиеДанные.Сумма);
	
КонецПроцедуры

Ну вот, можно запускать!

Скрин

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

1
2
3
4
5
6
7
8
9
10
11
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	
	ТекущиеДанные = Элементы.Список.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Элементы.СделатьВсеХорошо.Видимость = ЗначениеЗаполнено(ТекущиеДанные.Сумма);
	
КонецПроцедуры

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

Скрин

Новая ошибка. Разобравшись в ситуации, наш программист выяснил, что у этого пользователя скрыта колонка “Сумма”.

Скрин

Пользователь отключил колонку через “Изменить форму” со словами “меньше знаю - лучше сплю”.

И в результате - колонка перестала быть доступной в ТекущиеДанные. Это хорошо видно в отладке:

Скрин

Наш Вася хоть и не силён в 1С, но гуглить умеет. И он быстро нашёл решение - установить напротив поля “Сумма” флаг “Использовать всегда”:

Скрин

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

Уже у выхода Вася оглянул сотрудников, которые, как он уверен, с удовольствием пользуются нововведением.

И тут:

Скрин

Что опять сломалось?

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

Скрин

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

Скрин

А в ТекущаяСтрока хранится не ссылка на документ, а “СтрокаГруппировкиДинамическогоСписка”

Скрин

Выходит, что “использовать всегда” не означает, что свойство всегда будет в ТекущиеДанные…

Пояндексив, Вася нашёл самый простой вариант - проверять ТекущиеДанные не только на Неопределено, но и на группировку.

1
2
3
4
5
6
7
8
9
10
11
12
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	
	ТекущиеДанные = Элементы.Список.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено 
		ИЛИ ТипЗнч(ТекущиеДанные) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
		Возврат;
	КонецЕсли;
	
	Элементы.СделатьВсеХорошо.Видимость = ЗначениеЗаполнено(ТекущиеДанные.Сумма);
	
КонецПроцедуры

Теперь точно идеально!

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

А вот ещё это поправьте

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

А на самом деле кнопка должна быть недоступна, ведь это не “документ с заполненной суммой”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	
	ТекущиеДанные = Элементы.Список.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено 
		ИЛИ ТипЗнч(Элементы.Список.ТекущаяСтрока) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
		
		ОтображатьКнопку = Ложь;
		
	Иначе
		
		ОтображатьКнопку = ЗначениеЗаполнено(ТекущиеДанные.Сумма);
		
	КонецЕсли;
	
	Элементы.СделатьВсеХорошо.Видимость = ОтображатьКнопку;
	
КонецПроцедуры

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

Оказалось, что есть БСПшный метод СтандартныеПодсистемыКлиент.ЭтоЭлементДинамическогоСписка()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Проверяет, что текущие данные определены и не являются группировкой.
// Предназначена для обработчиков таблиц формы динамических списков.
//
// Параметры:
//  ТаблицаИлиТекущиеДанные - ТаблицаФормы - таблица формы динамического списка для проверки текущих данных.
//                          - Неопределено
//                          - ДанныеФормыСтруктура
//                          - Структура - текущие данные для проверки.
//
// Возвращаемое значение:
//  Булево
//
Функция ЭтоЭлементДинамическогоСписка(ТаблицаИлиТекущиеДанные) Экспорт
	
	Если ТипЗнч(ТаблицаИлиТекущиеДанные) = Тип("ТаблицаФормы") Тогда
		ТекущиеДанные = ТаблицаИлиТекущиеДанные.ТекущиеДанные;
	Иначе
		ТекущиеДанные = ТаблицаИлиТекущиеДанные;
	КонецЕсли;
	
	Если ТипЗнч(ТекущиеДанные) <> Тип("ДанныеФормыСтруктура")
	   И ТипЗнч(ТекущиеДанные) <> Тип("Структура") Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если ТекущиеДанные.Свойство("ГруппировкаСтроки") Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

И если использовать его, то код будет такой

1
2
3
4
5
6
7
8
9
10
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	
	ТекущиеДанные    = Элементы.Список.ТекущиеДанные;
	
	ОтображатьКнопку = СтандартныеПодсистемыКлиент.ЭтоЭлементДинамическогоСписка(ТекущиеДанные) И ЗначениеЗаполнено(ТекущиеДанные.Сумма);
	
	Элементы.СделатьВсеХорошо.Видимость = ОтображатьКнопку;
	
КонецПроцедуры

А если использовать ещё один типовой метод, то можно сделать и так:

1
2
3
4
5
6
7
8
9
10
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	
	ТекущиеДанные    = Элементы.Список.ТекущиеДанные;
	
	ОтображатьКнопку = СтандартныеПодсистемыКлиент.ЭтоЭлементДинамическогоСписка(ТекущиеДанные) И ЗначениеЗаполнено(ТекущиеДанные.Сумма);
	
	ОбщегоНазначенияКлиентСервер.УстановитьСвойствоЭлементаФормы(Элементы, "СделатьВсеХорошо", "Видимость", ОтображатьКнопку);
	
КонецПроцедуры

А ещё, можно и не проверять на поле группировки, а использовать метод ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры()

1
2
3
4
5
6
7
8
9
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	
	ТекущаяСумма = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Элементы.Список.ТекущиеДанные, "Сумма");
	
	ОбщегоНазначенияКлиентСервер.УстановитьСвойствоЭлементаФормы(
	Элементы, "СделатьВсеХорошо", "Видимость", ЗначениеЗаполнено(ТекущаяСумма));
	
КонецПроцедуры

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

Василий ещё решит, какой код самый “красивый” и “правильный”. Кстати, напишите в комментариях, как, по Вашему мнению, лучше всего?

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

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

Вот несколько примеров из ERP 2.5.6.98 :

Скрин

Скрин

Скрин

Всё это по той причине, что при обращении к свойствам ТекущиеДанные нет проверки на то, является ли данная строка реальной строчкой списка, а не группировкой.

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

Теперь я буду всегда проверять не только на Неопределено, но и на СтрокаГруппировкиДинамическогоСписка

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

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

Вася снова перепишет свою форму списка ещё более “правильно”. Но это будет в понедельник. А пока что впереди целые выходные. Можно отдохнуть.

Скрин

Авторский пост защищен лицензией CC BY 4.0 .