Как передать значение реквизита "Остаток" из формы списка в форму элемента справочника "Номенклатура" в 1С?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

При работе с 1С:Предприятием 8.3 часто возникает необходимость отобразить дополнительную информацию из динамического списка прямо в карточке элемента. Одна из таких типовых задач — перенос значения реквизита "Остаток" из формы списка справочника "Номенклатура" в соответствующий реквизит формы элемента. Мы рассмотрим два основных подхода к решению этой задачи, каждый из которых имеет свои преимущества и недостатки.

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

1. Передача значения реквизита "Остаток" как параметр при открытии формы элемента

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

Шаг 1: Подготовка к передаче параметра в форме списка

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

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

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


// Пример обработчика события в форме списка, например, при двойном клике или активации строки
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    Если Элементы.Список.ТекущиеДанные <> Неопределено Тогда
        // Получаем ссылку на текущий элемент номенклатуры
        СсылкаНаЭлемент = Элементы.Список.ТекущиеДанные.Ссылка;
        
        // Получаем значение Остатка из текущей строки динамического списка
        // Предполагаем, что колонка "Остаток" присутствует в данных списка
        ОстатокСтроки = Элементы.Список.ТекущиеДанные.Остаток; 

        // Вызываем серверную процедуру для открытия формы элемента и передачи параметров
        ОткрытьФормуЭлементаСПараметромНаСервере(СсылкаНаЭлемент, ОстатокСтроки);
    КонецЕсли;
КонецПроцедуры

// Серверная процедура, которая фактически открывает форму элемента
&НаСервере
Процедура ОткрытьФормуЭлементаСПараметромНаСервере(СсылкаНаЭлемент, Остаток)

    // Создаем структуру для передачи параметров.
    // Ключевой параметр "Ключ" обязателен для формы элемента справочника.
    ПараметрыОткрытия = Новый Структура("Ключ", СсылкаНаЭлемент);
    
    // Добавляем наш пользовательский параметр "ПереданныйОстаток"
    ПараметрыОткрытия.Вставить("ПереданныйОстаток", Остаток); 

    // Получаем форму элемента и передаем ей параметры открытия
    ФормаЭлемента = ПолучитьФорму("Справочник.Номенклатура.ФормаЭлемента", ПараметрыОткрытия, ЭтаФорма);
    
    // Открываем форму
    ФормаЭлемента.Открыть();

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

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

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

Шаг 2: Создание реквизита и получение параметра в форме элемента

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

  1. Откройте форму элемента справочника "Номенклатура" в конфигураторе.
  2. Перейдите на вкладку "Реквизиты".
  3. Добавьте новый реквизит формы, например, с именем ОстатокНаФорме, типом "Число" и подходящей точностью. Установите флажок "Использовать данные".
  4. Разместите этот реквизит на форме, перетащив его из окна "Реквизиты" в нужную область формы.

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


// В модуле формы элемента, обработчик ПриСозданииНаСервере
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Сначала убедимся, что реквизит формы для остатка существует
    // (мы создали его как "ОстатокНаФорме")

    // Проверяем, был ли передан параметр "ПереданныйОстаток"
    Если Параметры.Свойство("ПереданныйОстаток") Тогда
        // Если параметр существует, присваиваем его значение реквизиту формы
        ЭтаФорма.ОстатокНаФорме = Параметры.ПереданныйОстаток; 
    КонецЕсли;

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

После выполнения этого кода при открытии формы элемента реквизит ОстатокНаФорме будет заполнен значением, которое было передано из формы списка.

Преимущества и недостатки метода с параметрами

Преимущества:

Недостатки:

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

2. Получение актуального значения остатка непосредственно в форме элемента

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

Шаг 1: Определение источника данных для "Остатка"

В 1С:Предприятии "Остаток" номенклатуры, как правило, хранится в регистрах накопления. Для получения текущих остатков используются виртуальные таблицы этих регистров, чаще всего это <ИмяРегистра>.Остатки или <ИмяРегистра>.ОстаткиИОбороты. Например, если у вас есть регистр накопления "ОстаткиТоваров", то для получения остатка мы будем использовать виртуальную таблицу РегистрНакопления.ОстаткиТоваров.Остатки.

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

Шаг 2: Реализация запроса в форме элемента

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

Давайте посмотрим на пример такой функции:


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

    // Устанавливаем параметр запроса - ссылку на текущую номенклатуру
    Запрос.УстановитьПараметр("Номенклатура", Объект.Ссылка);

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

    // Если есть данные, возвращаем остаток, иначе - 0
    Если Выборка.Следующий() Тогда
        Возврат Выборка.Остаток;
    Иначе
        Возврат 0; // Или Неопределено, в зависимости от логики
    КонецЕсли;

КонецФункции

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

Шаг 3: Место вызова запроса и обновление данных

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

  1. При открытии формы: Самое очевидное место – это обработчик ПриСозданииНаСервере() формы элемента. В этом случае остаток будет загружен сразу при открытии карточки номенклатуры.
    
    // В модуле формы элемента, обработчик ПриСозданииНаСервере
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        // ... (возможно, здесь же обрабатывались параметры, если вы используете оба подхода) ...
    
        // Вызываем нашу функцию для получения актуального остатка
        ЭтаФорма.ОстатокНаФорме = ПолучитьАктуальныйОстатокНаСервере();
    
    КонецПроцедуры
    
  2. По требованию пользователя (кнопка "Обновить"): Если требуется обновлять остаток без перезакрытия формы, вы можете добавить на форму кнопку, например, "Обновить остаток". При нажатии на эту кнопку будет вызываться функция получения остатка, и значение реквизита на форме будет обновляться.

    Для этого:

    1. Создайте команду формы, например, ОбновитьОстатокКоманда.
    2. Разместите эту команду на форме в виде кнопки.
    3. В обработчике команды на клиенте вызовите серверную функцию и обновите отображение данных.
    
    // В модуле формы элемента, обработчик команды ОбновитьОстатокКоманда
    &НаКлиенте
    Процедура ОбновитьОстатокКоманда(Команда)
        // Вызываем серверную функцию для получения актуального остатка
        ЭтаФорма.ОстатокНаФорме = ПолучитьАктуальныйОстатокНаСервере();
                
        // Важно: После изменения значения реквизита на клиенте, 
        // необходимо обновить отображение данных формы, чтобы изменения стали видны.
        ЭтаФорма.ОбновитьОтображениеДанных();
    КонецПроцедуры
    

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

Преимущества и недостатки метода с запросом

Преимущества:

Недостатки:

Этот метод рекомендуется для случаев, когда актуальность информации об остатках является критически важной.

Дополнительные соображения и лучшие практики

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

Актуальность данных против производительности

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

Оптимизация запросов

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

  1. Соединение с минимальным количеством таблиц: В идеале, используйте одну основную таблицу (например, виртуальную таблицу остатков регистра накопления).
  2. Избегайте сложных конструкций: Старайтесь избегать глубоких вложенных запросов, сложных соединений с большим количеством таблиц, если это не абсолютно необходимо. Это может значительно замедлить выполнение запроса.
  3. Использование виртуальных таблиц: Для получения остатков всегда используйте виртуальные таблицы регистров накопления (.Остатки, .ОстаткиИОбороты). Они специально оптимизированы для этой задачи.

Проверка стандартной функциональности

Прежде чем приступать к собственной разработке, всегда стоит проверить, возможно, аналогичная функциональность уже реализована в типовой конфигурации 1С, которую вы используете. Многие типовые решения (например, "1С:Управление торговлей", "1С:ERP Управление предприятием") уже имеют механизмы для просмотра остатков номенклатуры. Например, в форме списка номенклатуры может быть опция "Остатки товаров на складах", которая при наведении курсора на позицию показывает ее остатки и цены. Также существуют готовые расширения, добавляющие колонки с остатками и настройками по складам прямо в список номенклатуры. Изучение стандартных возможностей может сэкономить значительное время и ресурсы.

Обновление данных в многопользовательской среде

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

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

← На главную