Флаг "Использовать ПОЧТИ всегда", или Нюанс динамических списков
Небольшая пятничная история по программной работе со строкой динамического списка.
Думаю, всем разработчикам хоть раз да понадобится программно обратиться к какому-то свойству текущей строки динамического списка.
Элементы.Список.ТекущиеДанные
Возьмём обычного новичка, который только начинает свой путь в 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 :
Всё это по той причине, что при обращении к свойствам ТекущиеДанные нет проверки на то, является ли данная строка реальной строчкой списка, а не группировкой.
И таких ошибок очень много. Ведь разработчик, когда нажимает галочку “Использовать всегда” предполагает, что это является гарантией наличия свойства в ТекущиеДанные. Но, как видите, это не совсем так.
Теперь я буду всегда проверять не только на Неопределено, но и на СтрокаГруппировкиДинамическогоСписка
Гордый проделанным исследованием и своими решительными выводами юный разработчик Вася блаженно уснул. Ему снились воздушные динамические списки, крылатые группировки, вкусные свойства и лавандовые проверки на ошибки.
Он ещё не знает, что рано утром в понедельник ему придётся изучить ещё одну статью про его доработку: Серверные вызовы, которые нельзя вызывать
Вася снова перепишет свою форму списка ещё более “правильно”. Но это будет в понедельник. А пока что впереди целые выходные. Можно отдохнуть.