Изменяющееся контекстное меню в 1С 8.3

06.08.19

Разработка - Работа с интерфейсом

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

Скачать файлы

Наименование Файл Версия Размер
Пример базы с реализованным изменяющемся меню
.dt 40,08Kb
6
.dt 40,08Kb 6 Скачать

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

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

Создадим форму списка документа Приход, а на этой форме у таблицы Список создадим событие ПриАктивизацииЯчейки (в клиентском контексте).

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

Получится следующий код:

&НаКлиенте
Перем ТекущаяСтрока;

&НаКлиенте
Процедура СписокПриАктивизацииЯчейки(Элемент)

    Если ТекущаяСтрока = Элементы.Список.ТекущаяСтрока Тогда
        Возврат;
    КонецЕсли;

    ТекущаяСтрока = Элементы.Список.ТекущаяСтрока;

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

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

&НаКлиенте
Перем ТекущаяСтрока;

&НаКлиенте
Процедура СписокПриАктивизацииЯчейки(Элемент)

    Если ТекущаяСтрока = Элементы.Список.ТекущаяСтрока Тогда
        Возврат;
    КонецЕсли;
    ТекущаяСтрока = Элементы.Список.ТекущаяСтрока;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    ДобавитьСкладыВМенюСписка(ТекущаяСтрока)

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

&НаСервере
Процедура ДобавитьСкладыВМенюСписка(ДокументПриход)

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

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

&НаСервере
Процедура ДобавитьСкладыВМенюСписка(ДокументПриход)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                   |    ПриходСписокТоваров.Склад КАК Склад,
                   |    Склады.Наименование КАК НаименованиеСклада,
                   |    Склады.Код КАК КодСклада
                   |ИЗ
                   |    Документ.Приход.СписокТоваров КАК ПриходСписокТоваров
                   |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Приход КАК Приход
                   |        ПО ПриходСписокТоваров.Ссылка = Приход.Ссылка
                   |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Склады КАК Склады
                   |        ПО ПриходСписокТоваров.Склад = Склады.Ссылка
                   |ГДЕ
                   |    Приход.Ссылка = &Ссылка
                   |
                   |СГРУППИРОВАТЬ ПО
                   |    ПриходСписокТоваров.Склад,
                   |    Склады.Наименование,
                   |    Склады.Код";

    Запрос.УстановитьПараметр("Ссылка",ДокументПриход);
    Результат = Запрос.Выполнить();
    Если Результат.Пустой() Тогда
        Возврат;
    КонецЕсли;
    Выборка = Результат.Выбрать();
    Пока Выборка.Следующий() Цикл

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

Внутри цикла выборки создаем имена для команд, которые связаны со складами, команды, а также элементы формы с типом КнопкаФормы, которые разместим в группе Элементы.Список.КонтекстноеМеню

Пока Выборка.Следующий() Цикл
    ИмяКоманды = "ОткрытиеСклада_" + Выборка.КодСклада;

    Команда = Команды.Добавить(ИмяКоманды);
    Команда.Заголовок = "Открыть склад: " + Выборка.НаименованиеСклада;
    Команда.Действие  = "ОткрытиеФормыСкладаИзКонтекстногоМеню";

    КнопкаКоманды = Элементы.Добавить("КнопкаКоманды" + ИмяКоманды, Тип("КнопкаФормы"),Элементы.Список.КонтекстноеМеню);
    КнопкаКоманды.ИмяКоманды = ИмяКоманды;
КонецЦикла;

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

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

Будем заполнять эту таблицу в конце цикла.

НовСтрока = СвязьКомандыИСклада.Добавить();
НовСтрока.ИмяКоманды = ИмяКоманды;
НовСтрока.Склад = Выборка.Склад;

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

&НаКлиенте
Процедура ОткрытиеФормыСкладаИзКонтекстногоМеню(Элемент)
    ИмяКоманды = Элемент.Имя;
    Отбор = Новый Структура("ИмяКоманды",ИмяКоманды);
    МассивСкладов = СвязьКомандыИСклада.НайтиСтроки(Отбор);

    Если МассивСкладов.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;

    СсылкаНаСклад = МассивСкладов[0].Склад;

    ПараметрыОткрытия = Новый Структура("Ключ",СсылкаНаСклад);

    ОткрытьФорму("Справочник.Склады.ФормаОбъекта",
                 ПараметрыОткрытия,,,,,,
                 РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры

Нам осталось в начале процедуры ДобавитьСкладыВМенюСписка очищать команды и элементы формы, которые мы создали ранее.

Для Каждого стрКоманда из СвязьКомандыИСклада Цикл
    ИмяКоманды = стрКоманда.ИмяКоманды;
    ИмяКнопки  = "КнопкаКоманды" + ИмяКоманды;
    Команды.Удалить(Команды[ИмяКоманды]);
    Элементы.Удалить(Элементы[ИмяКнопки]);
КонецЦикла;
СвязьКомандыИСклада.Очистить();

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

Пример выполнен на платформе 8.3.13.1513

управляемые формы контекстное меню практика программирования

См. также

Богатый редактор картинок, хранимых в базе, с возможностью РИСОВАНИЯ. Редактор внешних файлов картинок. Объект, расширяющий возможности работы с картинками из встроенного языка (Три в одном) + Обработка «Стандартизация картинок»

Работа с интерфейсом Рабочее место Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Обработка предназначена для редактирования картинок в режиме «Предприятие», с возможностью РИСОВАТЬ на них. Поддерживается работа как в обычных формах (толстый клиент) так и на управляемых формах (тонкий клиент). Обработка позволяет редактировать как картинки, хранимые в базе, так и графические файлы с диска на файловой системе. Помимо базовых функций (изменение размеров, преобразование формата, обрезание картинки, повороты и т.п.) – редактор имеет богатый набор инструментов для рисования. Доступна функция вставки изображения из буфера обмена. Также обработка может быть использована из встроенного языка как объект для редактирования картинок. Объект может быть использован: на стороне клиента, на стороне сервера, из внешнего соединения. Данная обработка будет особенно полезна тем, кто вносит картинки в базу (изображения номенклатуры, фотографии физических лиц и т.п.). Функционал реализуется с использованием JavaScript и бесплатного ПО ImageMagick (без использования внешних компонент).

6000 руб.

16.01.2015    61712    43    59    

80

[Расширения] Динамическое управление видимостью и доступностью элементов форм (УФ) (8.3.6+)

Работа с интерфейсом Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Механизм «Динамическое управление доступом к элементам форм объектов 1С8» предназначен для обеспечения возможности оперативного управления видимостью и доступностью элементов форм документов и справочников продуктов фирмы «1С» «1С:Предприятие 8». Решение универсальное, встраивается в любую конфигурацию с минимальными доработками, что позволяет без проблем обновлять типовые решения.

5000 руб.

14.01.2016    54320    16    21    

42

Управление дашбордами

Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

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

2400 руб.

29.06.2020    16625    21    4    

35

Новогоднее оформление для 1С

Работа с интерфейсом Платформа 1С v8.3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 Бесплатно (free)

Добавьте новогоднего настроения! Расширение создает декорацию в виде гирлянды на некоторых формах объектов.

27.12.2023    10568    745    elcoan    45    

106

Конструктор HTML, CSS и javascript

Инструментарий разработчика Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

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

2 стартмани

10.04.2023    9488    150    acces969    31    

115

Модель состояния для MVC

Работа с интерфейсом Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

"MVC плохо применима в 1С" - познакомьтесь с моделью состояния и, возможно, ваше мнение поменяется! Представленное решение является эволюционным развитием идеи реализации MVC для 1С. В новой версии добавлены DSL для описания модели состояния, а также параметризация свойств параметров и элементов формы.

1 стартмани

05.07.2022    3582    kalyaka    2    

27

Табло очереди заказов на экран телевизора

WEB-интеграция Работа с интерфейсом Платформа 1С v8.3 1С:Розница 2 Платные (руб)

Связка из веб-приложения и расширения для 1С: Розница 2.3.

3600 руб.

29.04.2022    12013    1    5    

10
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. VmvLer 06.08.19 12:57 Сейчас в теме
в событии ПриАктивизацииЯчейки ячейки динамического списка выполнять запрос на приходы каждый раз?
ну-ну, если приходов в день тысячи, а месяц десятки тысяч, то этот костыль потеряет все свое очарование.

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

Пора в 1С вводить новое свойство функционала: ГлубинаТестированияТаблиц со значениями {Фигня какая-то, Проверено да демке, Проверено в реале на 100К записей, Проверено в реале на 100КК записей}.
Это станет способствовать более высокой степени доверия между бизнесом и разработчиками.

Кроме того,

в ПриАктивизацииЯчейки нельзя использовать серверные методы. Да, иногда они работают через пень-колоду,
но сама передача управления между контекстами в таком обработчике - это уже не двойка, а кол!
Хоть бы во внеконтекст завернули.
Прикрепленные файлы:
shard; criptid; kyrasol; kild; mj-orel; Merkalov; xa1ter; IntellXeon; CyberCerber; NeviD; mentos; oleg-m; berezdetsky; Mettem_Kirill; evvakra; JohnyDeath; YPermitin; kuzyara; a.babenko; ArchLord42; logarifm; ixijixi; ilya2184; khomkolov; +24 4 Ответить
2. signum2009 1024 06.08.19 13:32 Сейчас в теме
(1) Вы внимательно текст смотрели, или просто оставить коммент ради хейтинга?

1) Пример с запросом приведен для удобства дабы не городить огород, основная тема как работать с контекстным меню, а не как оптимально делать запрос;
2) Серверные методы работают нормально, если перед выполнением кода в ПриАктивизацииЯчейки проверять на повторение текущей строки.
5. VmvLer 06.08.19 14:51 Сейчас в теме
(2) Чистые серверные(иногда можно использовать внеконтекстные) методы в обработчиках активизации - это условное зло с костылями, как вы указали.
И какой бы няшной ни казалась реализация, увы, на реальных базах - это зло абослютное.
Это мое объективное мнение.

Если я захочу ублажить какую-то блонди в ларьке, то я с удовольствием использую вашу идею.
Все остальное мимо и относительно.
7. ixijixi 1761 06.08.19 21:27 Сейчас в теме
(2) Товарищ конечно часто хейтит, но тут он прав. Зачем соединение с таблицей документа, если ни одного поля из нее не выбираем? Зачем группировка, если ни одно поле не агрегируем? И да, где &БезКонтекста?

Событие вешать надо на ПриАктивизацииСтроки с подключением обработки ожидания, чтобы не тормозило.

Спорным является и решение с сопоставлением команд и складов, но тут надо тестировать.
fanast2; CyberCerber; berezdetsky; Lazio; triviumfan; +5 Ответить
15. Cyberhawk 135 30.09.19 18:03 Сейчас в теме
(7)
Событие вешать надо на ПриАктивизацииСтроки с подключением обработки ожидания, чтобы не тормозило
Как в этом случае предлагается добиваться отображения пунктов в контекстном меню, уже успевшем отобразиться?
8. dhurricane 06.08.19 21:44 Сейчас в теме
(2) Все таки я бы поостерегся использовать контекстные серверные методы в обработчике активизации строки, т.к. в синтакс-помощнике они явно запрещены:
ТаблицаФормы (FormTable)
ПриАктивизацииСтроки (OnActivateRow)
Синтаксис:
ПриАктивизацииСтроки()
Описание:
Вызывается при активизации строки таблицы.
Примечание:
В обработчике данного события нельзя использовать серверные методы формы с директивой компиляции &НаСервере.

Подсистема БСП "ПодключаемыеКоманды" также предоставляет возможность динамически обновлять меню команд, правда банальным изменением видимости уже созданных кнопок, поэтому серверные вызовы не используются. Тем не менее для такой операции в обработчике активизации строки используется подключение обработчика ожидания с небольшой паузой в 200 мс.
CyberCerber; swenzik; Aleskey_K; Brawler; acanta; +5 Ответить
6. json 3294 06.08.19 20:56 Сейчас в теме
(1) там у него в запросе отбор стоит по ссылке. А это кластерный индекс (загугли что это значит), Там хоть 100 млн. записей - будет отрабатывать за доли секунды, пользователь не ощутит задержку.

Ладно бы не разбирался ты в запросах и учился у других. А вместо этого пытаешься умничать и критиковать.
botokash; swenzik; dimadeev; triviumfan; +4 Ответить
3. acanta 06.08.19 13:39 Сейчас в теме
Классный пример, спасибо большое.
Можно и отчеты добавить (к примеру, сохраненные пользователем с настройками вариантов) и ввод на основании с указанием дополнительных значений.

Правильно ли я понимаю, что платформа перехватывает метод активизации ячейки, а вовсе не правый/левый клик мышки и меню обновляется при перемещении стрелками вверх-вниз-право-лево по списку?
4. signum2009 1024 06.08.19 13:41 Сейчас в теме
(3) оно обновляется, только когда активизируется другая строка (или ячейка другой строки), для этого в самом начале выполняется проверка:
    Если ТекущаяСтрока = Элементы.Список.ТекущаяСтрока Тогда
        Возврат;
    КонецЕсли;
9. logarifm 1116 06.08.19 21:51 Сейчас в теме
Вообщим скажу только одно.
Решение нормальное - но не оптимальное. Человек же сходу написал, что решал специфичную задачу вот и просто показал свой вариант решения. Ест-но, что когда у тебя в СПИКЕ 100000 ККК записей то это вообще другой подход ВОВСЕ даже штатные подходы нервно курят в уголке. Так что давайте не сортесь девочки...
10. kuzyara 1896 07.08.19 04:54 Сейчас в теме
Код грамотно разбит по статье, приятно читать. Возьму на заметку подход.
11. PerlAmutor 129 07.08.19 06:27 Сейчас в теме
А я меню создаю с помощью объектов СКД.
acanta; json; +2 Ответить
12. vasilev2015 2677 07.08.19 09:02 Сейчас в теме
Здравствуйте !

у меня недавно была похожая обработка ))

https://infostart.ru/public/1070951/
13. triviumfan 91 07.08.19 11:40 Сейчас в теме
(12) Видимо она никому не интересна, т.к. в ПриАктивацииОбласти(), ПриАктивацииСтроки() ещё 10 лет назад создавали меню.
14. Montirey 13.08.19 08:44 Сейчас в теме
основная идея статьи понятна и интересна.

А то, что код нужно оптимизировать - дело тоже нужное, но все же вторичное.
Кому идея покажется интересной - при использовании сам до ума доведет.
adhocprog; +1 Ответить
16. ovasiliev 6 30.07.20 01:16 Сейчас в теме
Для тех, кто не понимает ограничение серверных вызовов в событиях ПриАктивизации таблиц формы - поставьте внутри них точку останова и погоняйте форму в пользовательском режиме. Увидите, сколько для них будет неочевидных сработок, включая даже при пустой таблице. При открытии формы, например.
И вы резонно предположите, что вызов серверных методов ПриАктивизации зачастую вызывает срабатывание события ПриАктивизации, что вызывает серверные методы, что вызывает... вы понимаете, о чём я?..
Оставьте свое сообщение