Как изменить флажок (чек-бокс) в проведенном документе 1С на УФ без перепроведения?

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

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

Представьте ситуацию: у нас есть проведенный документ, в котором есть булевый реквизит, отображаемый на форме как чек-бокс. Нам нужно изменить значение этого чек-бокса на "Истина" (или "Ложь"), но так, чтобы документ не перепроводился и не затрагивал движения регистров. Это особенно актуально, когда измененный реквизит участвует в условном оформлении формы списка или отчетов, но не влияет на экономическую суть документа.

Подход 1: Прямое изменение реквизита документа с использованием ОбменДанными.Загрузка = Истина

Одним из наиболее прямых и поддерживаемых платформой 1С способов изменить реквизит проведенного документа без его перепроведения является установка флага ОбменДанными.Загрузка в значение Истина перед записью документа. Этот флаг информирует систему, что текущая операция является частью процесса загрузки данных, и позволяет пропустить большинство стандартных обработчиков событий объекта, таких как «ПередЗаписью», «ПриЗаписи», «ОбработкаПроведения» и т.д. Таким образом, движения регистров, формируемые при проведении, не будут затронуты.

Как это работает:

  1. Мы получаем объект документа по его ссылке.
  2. Устанавливаем свойство ОбменДанными.Загрузка объекта документа в значение Истина.
  3. Изменяем значение необходимого реквизита.
  4. Вызываем метод Записать() объекта документа.
  5. После записи не забываем вернуть флаг ОбменДанными.Загрузка в исходное состояние, если это необходимо для дальнейших операций с этим объектом, хотя обычно он сбрасывается при завершении транзакции или получении нового объекта.

Пример из типовых конфигураций:

В типовых конфигурациях 1С, например, в 1С:Бухгалтерии, реализована возможность редактировать комментарии в документах, проведенных в закрытом периоде, без их перепроведения. Этот механизм часто основан именно на принципе использования ОбменДанными.Загрузка = Истина. Это отличный пример того, как платформа допускает и использует данный подход для "несущественных" изменений.

Пример кода: (быстро составить каркас подобного алгоритма поможет консоль кода с ИИ-помощником)

Допустим, у нас есть документ "РеализацияТоваровУслуг" и в нем реквизит "ТребуетВнимания" типа "Булево". Мы хотим установить его в "Истина".


// Предположим, у нас есть ссылка на документ, например, из формы списка
// СсылкаНаДокумент = Элементы.Список.ТекущиеДанные.Ссылка;

Если СсылкаНаДокумент.Пустая() Тогда
    Возврат;
КонецЕсли;

Попытка
    ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

    // Сохраняем текущее значение флага ОбменДанными.Загрузка
    // на случай, если мы работаем в каком-либо процессе, где он уже установлен
    СтароеЗначениеФлагаЗагрузки = ДокОбъект.ОбменДанными.Загрузка;

    ДокОбъект.ОбменДанными.Загрузка = Истина;
    ДокОбъект.ТребуетВнимания = Истина; // Устанавливаем наш флажок

    ДокОбъект.Записать();

    // Опционально: восстанавливаем флаг, хотя в большинстве случаев он будет сброшен
    // при закрытии объекта или окончании транзакции.
    // Если ДокОбъект.ОбменДанными.Загрузка <> СтароеЗначениеФлагаЗагрузки Тогда
    //     ДокОбъект.ОбменДанными.Загрузка = СтароеЗначениеФлагаЗагрузки;
    // КонецЕсли;

    Сообщить("Флажок 'Требует внимания' для документа " + СсылкаНаДокумент + " успешно установлен.");

Исключение
    Сообщить("Ошибка при изменении флажка: " + ОписаниеОшибки());
КонецПопытки;

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

Обновление формы после изменения:

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

Подход 2: Использование Регистров Сведений для хранения флагов

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

Когда применять:

Как это реализовать:

  1. Создаем новый регистр сведений. Назовем его, например, "ФлагиДокументов".
  2. Определяем измерения: Добавляем измерение типа "Ссылка.Документ.НашДокумент" (или "Ссылка.Документ" для универсальности, если флаг может относиться к разным типам документов). Назовем его "Документ".
  3. Определяем ресурсы: Добавляем ресурс типа "Булево". Назовем его, например, "УстановленФлаг".
  4. Устанавливаем периодичность: Если нам нужна история изменений флага, делаем регистр периодическим (например, "По позиции регистратора" или "В пределах секунды"). Если нужна только текущее состояние, делаем его непериодическим. Для данной задачи, скорее всего, подойдет непериодический регистр.

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

Пример кода для работы с регистром сведений:

Допустим, мы создали непериодический регистр сведений "СтатусыДокументов" с измерением "Документ" (тип "ДокументСсылка.РеализацияТоваровУслуг") и ресурсом "ФлагПроверен" (тип "Булево").


// Предположим, у нас есть ссылка на документ, например, из формы списка
// СсылкаНаДокумент = Элементы.Список.ТекущиеДанные.Ссылка;

Если СсылкаНаДокумент.Пустая() Тогда
    Возврат;
КонецЕсли;

Попытка
    // Создаем набор записей для нашего регистра сведений
    НаборЗаписей = РегистрыСведений.СтатусыДокументов.СоздатьНаборЗаписей();

    // Устанавливаем отбор по нашему документу
    НаборЗаписей.Отбор.Документ.Установить(СсылкаНаДокумент);

    // Читаем существующие записи (если есть)
    НаборЗаписей.Прочитать();

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

    // Устанавливаем значение нашего флага
    НоваяЗапись.ФлагПроверен = Истина; // Или Ложь, в зависимости от задачи

    // Записываем набор записей (это сохранит изменения в регистре)
    НаборЗаписей.Записать();

    Сообщить("Флажок 'Проверен' для документа " + СсылкаНаДокумент + " успешно изменен в регистре сведений.");

Исключение
    Сообщить("Ошибка при изменении флажка в регистре сведений: " + ОписаниеОшибки());
КонецПопытки;

// После изменения записи в регистре сведений, для обновления формы списка,
// если она отображает данные из этого регистра (через соединение),
// также может потребоваться ее обновление.
// Элементы.Список.ОбновитьСтроки();

Преимущества регистра сведений: (для работы с большим объемом данных подойдет групповая корректировка записей регистров)

Подход 3: Использование Дополнительных Реквизитов и Сведений

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

Дополнительные реквизиты:

Дополнительные сведения:

Как настроить и использовать:

  1. Настройка: Перейдите в раздел "Администрирование" -> "Общие настройки" -> "Дополнительные реквизиты и сведения".
  2. Создание: Для нужного вида объекта (например, "Документ.РеализацияТоваровУслуг") добавьте новый дополнительный реквизит или сведение. Выберите тип значения "Булево" и укажите, должен ли он отображаться как флажок на форме.
  3. Доступ:
    • Для дополнительных реквизитов доступ к ним осуществляется через коллекцию Объект.ДополнительныеРеквизиты.
    • Для дополнительных сведений используются специальные команды на форме или функции из общих модулей, работающие с регистром "ДополнительныеСведения".
  4. Оба вида дополнительных свойств могут быть булевого типа и отображаться как чекбоксы на форме. Их можно использовать в условном оформлении, отборах и отчетах.

Пример кода для Дополнительных сведений (концептуальный):

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


// Пример получения значения дополнительного сведения
// ЗначениеСведения = ДополнительныеСведения.ПолучитьЗначениеДополнительногоСведения(СсылкаНаОбъект, "ИмяНашегоСведения");

// Пример установки значения дополнительного сведения
// ДополнительныеСведения.УстановитьЗначениеДополнительногоСведения(СсылкаНаОбъект, "ИмяНашегоСведения", Истина);

Вам потребуется найти или создать соответствующие функции в вашей конфигурации, которые инкапсулируют работу с регистром "ДополнительныеСведения".

Интерфейсное решение: Кнопка на форме списка или в контекстном меню документа

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

Наиболее удобные варианты:

  1. Кнопка на форме списка документов: Размещаем кнопку на командной панели формы списка. При нажатии на эту кнопку, выбранный (или несколько выбранных) документ(ов) обрабатывается по выбранному алгоритму (Подход 1, 2 или 3). Это позволяет пользователю быстро изменить флаг для нескольких документов, не открывая каждый из них.
  2. Команда (кнопка) в контекстном меню списка документов: Аналогично предыдущему пункту, но команда доступна по правой кнопке мыши на выбранном документе в списке. Это более компактное решение, не занимающее место на основной командной панели.
  3. Кнопка непосредственно на форме документа: Если изменение флага требуется часто и только для текущего открытого документа, можно разместить кнопку прямо на форме документа. Эта кнопка будет вызывать аналогичный программный код.

Реализация команд:

Для добавления команды на форму списка или в контекстное меню мы создаем новую команду в конфигураторе для объекта "Форма.НашДокументСписок". В обработчике команды на клиенте вызываем серверную процедуру, которая и будет выполнять программные действия.


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

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

    // Вызываем серверную процедуру для выполнения действия
    УстановитьФлагВниманияНаСервере(СсылкаНаДокумент);

    // Обновляем текущую строку, чтобы увидеть изменения
    Элементы.Список.ОбновитьСтроки();
КонецПроцедуры

// В модуле формы списка на сервере (или в общем модуле, если нужно универсально)
&НаСервере
Процедура УстановитьФлагВниманияНаСервере(СсылкаНаДокумент)
    // Здесь мы используем выбранный подход, например, Подход 1
    Попытка
        ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
        ДокОбъект.ОбменДанными.Загрузка = Истина;
        ДокОбъект.ТребуетВнимания = Истина;
        ДокОбъект.Записать();
        СообщитьНаКлиенте("Флажок для документа " + СсылкаНаДокумент + " установлен.");
    Исключение
        СообщитьНаКлиенте("Ошибка при установке флажка: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

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

Выбор оптимального решения

Выбор конкретного метода зависит от нескольких факторов:

  1. Природа флага: Если флаг является частью основного контекста документа и в будущем может повлиять на его логику или печатные формы, но при этом не должен влиять на движения – Подход 1 (ОбменДанными.Загрузка) может быть предпочтительнее.
  2. Независимость и расширяемость: Если флаг является вспомогательной информацией, которая может меняться независимо от документа, или если мы хотим избежать изменения структуры документа – Подход 2 (Регистр сведений) или Подход 3 (Дополнительные сведения) будут более "архитектурно чистыми" и гибкими решениями. Регистр сведений дает полный контроль над хранением, а дополнительные сведения предоставляют типовой механизм с удобным интерфейсом.
  3. Требования к истории: Если требуется сохранять историю изменения флага – выбираем периодический регистр сведений.
  4. Простота реализации и поддержки: Для небольших и простых задач ОбменДанными.Загрузка может быть быстрее в реализации. Для более сложных систем с большим количеством вспомогательных флагов, регистры сведений или дополнительные сведения будут более масштабируемыми.

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

← На главную