Как реализовать запись в регистр сведений из обработки по нажатию кнопки?

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

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

Архитектура вызова: Клиент — Сервер

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

Проанализируем правильную цепочку вызова:

  1. Пользователь нажимает кнопку на форме.
  2. Вызывается клиентская процедура-обработчик команды (с директивой &НаКлиенте).
  3. Из клиентской процедуры вызывается серверная процедура (с директивой &НаСервере), внутри которой происходит непосредственная работа с регистром.

Посмотрим на пример структуры кода, который должен быть в модуле формы:


&НаКлиенте
Процедура КомандаЗаписатьДанные(Команда)
    // Здесь можно выполнить проверки перед отправкой на сервер
    ЗаписатьДанныеВРегистрНаСервере();
    Сообщить("Данные успешно сохранены!");
КонецПроцедуры

&НаСервере
Процедура ЗаписатьДанныеВРегистрНаСервере()
    // Основная логика работы с РегистрыСведений
КонецПроцедуры

Разбор работы с Набором записей

Для записи данных в регистр сведений в 1С чаще всего используется объект РегистрСведенийНаборЗаписей. Этот объект позволяет работать с данными порциями, ограниченными определенным фильтром (отбором). Если мы не установим отбор и вызовем метод Записать(), система может перезаписать (очистить) весь регистр, что является критической ошибкой.

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


&НаСервере
Процедура ЗаписатьДанныеПервичныхПациентовВРегистр()
    Для Каждого Строка Из Объект.ПервичныеПациенты Цикл
        НаборЗаписей = РегистрыСведений.ПервичныеПациенты.СоздатьНаборЗаписей();
        
        // Установка отбора по измерениям обязательна!
        НаборЗаписей.Отбор.Пациент.Установить(Строка.Пациент);
        НаборЗаписей.Отбор.Врач.Установить(Строка.Врач);
        
        НаборЗаписей.Прочитать();
        
        Если НаборЗаписей.Количество() = 0 Тогда
            НоваяЗапись = НаборЗаписей.Добавить();
            ЗаполнитьЗначенияСвойств(НоваяЗапись, Строка);
        Иначе
            // Если запись уже существует, обновляем ресурсы
            Запись = НаборЗаписей[0];
            ЗаполнитьЗначенияСвойств(Запись, Строка);
        КонецЕсли;
        
        НаборЗаписей.Записать();
    КонецЦикла;
КонецПроцедуры

В данном примере мы используем метод Прочитать(). Он заполняет набор данными из базы, соответствующими установленным отборам. Если записей нет — добавляем новую, если есть — редактируем существующую. Метод ЗаполнитьЗначенияСвойств значительно упрощает код, копируя данные из колонок таблицы в ресурсы регистра по совпадению имен.

Почему данные пропадают (в отладчике «Ложь»)?

Выясним причину, по которой пользователь отмечает флажки (булево) в таблице на форме, но в серверной процедуре они оказываются пустыми. Рассмотрим три основные причины:

  1. Данные не зафиксированы: В управляемых формах изменения в текущей строке таблицы передаются в реквизит Объект только в момент потери фокуса или завершения редактирования строки. Если пользователь поставил галочку и сразу нажал кнопку «Записать» (не уходя со строки), платформа может не успеть синхронизировать данные. Чтобы этого избежать, в начале клиентской процедуры рекомендуется вызвать ЭтаФорма.ПроверитьЗаполнение() или просто явно сменить фокус.
  2. Неверный путь к данным (DataPath): Убедитесь, что колонки таблицы на форме привязаны именно к реквизиту Объект.ПервичныеПациенты, а не к созданной вручную таблице значений на форме, которая не передается на сервер автоматически.
  3. Очистка при чтении: Если в форме прописаны обработчики событий типа ПриЧтенииНаСервере или ПриПовторномОткрытии, они могут заново инициализировать таблицу, затирая введенные пользователем данные перед началом основной процедуры записи.

Оптимизация: Запись набора вне цикла

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

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

Пошаговая инструкция по диагностике

Если запись по-прежнему не происходит, выполним следующие шаги:

  1. Использование Сообщить(): Добавьте в серверную процедуру вывод текста: Сообщить("Количество строк: " + Объект.ПервичныеПациенты.Количество());. Если выведется 0, значит, данные таблицы не видны серверу.
  2. Точка останова в отладчике: Установите точку останова на строке НаборЗаписей.Записать(). Проверьте содержимое переменной Строка и НаборЗаписей[0]. Если там Ложь вместо Истина, ищите причину в потере фокуса на клиенте.
  3. Замер производительности: Запустите замер в конфигураторе, нажмите кнопку и посмотрите, какие процедуры вызываются. Иногда срабатывают скрытые подписки на события или обработчики ПриИзменении, которые очищают реквизиты.

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

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

← На главную