При работе с системой 1С:Предприятие на управляемых формах часто возникает задача изменить незначительный реквизит проведенного документа, например, флажок-чекбокс, без необходимости повторного проведения документа. Повторное проведение может быть нежелательным или даже невозможным, если документ уже находится в закрытом периоде, или если это повлечет за собой пересчет сложных движений по регистрам, что займет много времени и ресурсов. Рассмотрим несколько подходов, которые позволяют реализовать такой механизм работы.
Представьте ситуацию: у нас есть проведенный документ, в котором есть булевый реквизит, отображаемый на форме как чек-бокс. Нам нужно изменить значение этого чек-бокса на "Истина" (или "Ложь"), но так, чтобы документ не перепроводился и не затрагивал движения регистров. Это особенно актуально, когда измененный реквизит участвует в условном оформлении формы списка или отчетов, но не влияет на экономическую суть документа.
Одним из наиболее прямых и поддерживаемых платформой 1С способов изменить реквизит проведенного документа без его перепроведения является установка флага ОбменДанными.Загрузка в значение Истина перед записью документа. Этот флаг информирует систему, что текущая операция является частью процесса загрузки данных, и позволяет пропустить большинство стандартных обработчиков событий объекта, таких как «ПередЗаписью», «ПриЗаписи», «ОбработкаПроведения» и т.д. Таким образом, движения регистров, формируемые при проведении, не будут затронуты.
Как это работает:
ОбменДанными.Загрузка объекта документа в значение Истина.Записать() объекта документа.ОбменДанными.Загрузка в исходное состояние, если это необходимо для дальнейших операций с этим объектом, хотя обычно он сбрасывается при завершении транзакции или получении нового объекта.Пример из типовых конфигураций:
В типовых конфигурациях 1С, например, в 1С:Бухгалтерии, реализована возможность редактировать комментарии в документах, проведенных в закрытом периоде, без их перепроведения. Этот механизм часто основан именно на принципе использования ОбменДанными.Загрузка = Истина. Это отличный пример того, как платформа допускает и использует данный подход для "несущественных" изменений.
Пример кода: (быстро составить каркас подобного алгоритма поможет консоль кода с ИИ-помощником)
Допустим, у нас есть документ "РеализацияТоваровУслуг" и в нем реквизит "ТребуетВнимания" типа "Булево". Мы хотим установить его в "Истина".
// Предположим, у нас есть ссылка на документ, например, из формы списка
// СсылкаНаДокумент = Элементы.Список.ТекущиеДанные.Ссылка;
Если СсылкаНаДокумент.Пустая() Тогда
Возврат;
КонецЕсли;
Попытка
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
// Сохраняем текущее значение флага ОбменДанными.Загрузка
// на случай, если мы работаем в каком-либо процессе, где он уже установлен
СтароеЗначениеФлагаЗагрузки = ДокОбъект.ОбменДанными.Загрузка;
ДокОбъект.ОбменДанными.Загрузка = Истина;
ДокОбъект.ТребуетВнимания = Истина; // Устанавливаем наш флажок
ДокОбъект.Записать();
// Опционально: восстанавливаем флаг, хотя в большинстве случаев он будет сброшен
// при закрытии объекта или окончании транзакции.
// Если ДокОбъект.ОбменДанными.Загрузка <> СтароеЗначениеФлагаЗагрузки Тогда
// ДокОбъект.ОбменДанными.Загрузка = СтароеЗначениеФлагаЗагрузки;
// КонецЕсли;
Сообщить("Флажок 'Требует внимания' для документа " + СсылкаНаДокумент + " успешно установлен.");
Исключение
Сообщить("Ошибка при изменении флажка: " + ОписаниеОшибки());
КонецПопытки;
// После программного изменения реквизита документа, может потребоваться обновить
// отображение данных на форме, если мы выполняем это из формы документа
// или формы списка, не переоткрывая ее.
// Для формы документа:
// Прочитать();
// Для формы списка (если изменили текущий элемент):
// Элементы.Список.ОбновитьСтроки(); // или оповестить форму списка об изменении
Обновление формы после изменения:
Если мы изменяем реквизит документа программно из его же формы или из формы списка, после вызова Записать() нам может потребоваться обновить отображение данных. Для этого в форме документа можно использовать метод Прочитать(). Если изменение происходит из формы списка (например, по кнопке), и мы хотим обновить конкретную строку, можно использовать методы типа ОбновитьСтроки() для динамического списка или ОповеститьОбИзменении() с указанием ссылки на измененный объект.
Предложение использовать регистр сведений является очень гибким и "архитектурно чистым" способом. Регистры сведений предназначены для хранения произвольной информации в различных разрезах (измерениях) и могут быть связаны с документами. Этот подход позволяет хранить флаг отдельно от основных данных документа, что делает его изменение полностью независимым от логики проведения документа.
Когда применять:
Как это реализовать:
Изменения записей в таком регистре не влияют напрямую на движения регистров основного документа и не требуют его перепроведения. Мы просто записываем или изменяем записи в отдельном регистре, используя универсальную обработку для работы с регистрами.
Пример кода для работы с регистром сведений:
Допустим, мы создали непериодический регистр сведений "СтатусыДокументов" с измерением "Документ" (тип "ДокументСсылка.РеализацияТоваровУслуг") и ресурсом "ФлагПроверен" (тип "Булево").
// Предположим, у нас есть ссылка на документ, например, из формы списка
// СсылкаНаДокумент = Элементы.Список.ТекущиеДанные.Ссылка;
Если СсылкаНаДокумент.Пустая() Тогда
Возврат;
КонецЕсли;
Попытка
// Создаем набор записей для нашего регистра сведений
НаборЗаписей = РегистрыСведений.СтатусыДокументов.СоздатьНаборЗаписей();
// Устанавливаем отбор по нашему документу
НаборЗаписей.Отбор.Документ.Установить(СсылкаНаДокумент);
// Читаем существующие записи (если есть)
НаборЗаписей.Прочитать();
// Проверяем, есть ли уже запись для данного документа
Если НаборЗаписей.Количество() = 0 Тогда
// Если нет, добавляем новую запись
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Документ = СсылкаНаДокумент;
Иначе
// Если есть, используем существующую запись (первую, так как отбор по уникальной ссылке)
НоваяЗапись = НаборЗаписей[0];
КонецЕсли;
// Устанавливаем значение нашего флага
НоваяЗапись.ФлагПроверен = Истина; // Или Ложь, в зависимости от задачи
// Записываем набор записей (это сохранит изменения в регистре)
НаборЗаписей.Записать();
Сообщить("Флажок 'Проверен' для документа " + СсылкаНаДокумент + " успешно изменен в регистре сведений.");
Исключение
Сообщить("Ошибка при изменении флажка в регистре сведений: " + ОписаниеОшибки());
КонецПопытки;
// После изменения записи в регистре сведений, для обновления формы списка,
// если она отображает данные из этого регистра (через соединение),
// также может потребоваться ее обновление.
// Элементы.Список.ОбновитьСтроки();
Преимущества регистра сведений: (для работы с большим объемом данных подойдет групповая корректировка записей регистров)
Платформа 1С предоставляет встроенные механизмы "Дополнительные реквизиты" и "Дополнительные сведения" для расширения объектов метаданных (таких как документы и справочники) без изменения конфигурации. Эти механизмы могут быть удобны, особенно в типовых решениях, где изменение структуры документа напрямую нежелательно.
Дополнительные реквизиты:
ОбменДанными.Загрузка = Истина, как описано в Подходе 1.Дополнительные сведения:
Как настроить и использовать:
Объект.ДополнительныеРеквизиты.Пример кода для Дополнительных сведений (концептуальный):
Хотя прямой код для дополнительных сведений может быть более объемным из-за необходимости работы с универсальным регистром, логика будет аналогична работе с обычным регистром сведений. В типовых конфигурациях существуют общие функции для работы с дополнительными сведениями, например:
// Пример получения значения дополнительного сведения
// ЗначениеСведения = ДополнительныеСведения.ПолучитьЗначениеДополнительногоСведения(СсылкаНаОбъект, "ИмяНашегоСведения");
// Пример установки значения дополнительного сведения
// ДополнительныеСведения.УстановитьЗначениеДополнительногоСведения(СсылкаНаОбъект, "ИмяНашегоСведения", Истина);
Вам потребуется найти или создать соответствующие функции в вашей конфигурации, которые инкапсулируют работу с регистром "ДополнительныеСведения".
Какой бы из подходов мы ни выбрали для программной реализации, крайне важно предусмотреть удобный пользовательский интерфейс для активации изменения флага. Иначе вся красота внутреннего алгоритма останется недоступной для пользователя.
Наиболее удобные варианты:
Реализация команд:
Для добавления команды на форму списка или в контекстное меню мы создаем новую команду в конфигураторе для объекта "Форма.НашДокументСписок". В обработчике команды на клиенте вызываем серверную процедуру, которая и будет выполнять программные действия.
// В обработчике команды на клиенте (например, в модуле формы списка)
&НаКлиенте
Процедура УстановитьФлагВнимания(Команда)
Если Элементы.Список.ТекущиеДанные = Неопределено Тогда
Сообщить("Выберите документ для установки флага.");
Возврат;
КонецЕсли;
СсылкаНаДокумент = Элементы.Список.ТекущиеДанные.Ссылка;
// Вызываем серверную процедуру для выполнения действия
УстановитьФлагВниманияНаСервере(СсылкаНаДокумент);
// Обновляем текущую строку, чтобы увидеть изменения
Элементы.Список.ОбновитьСтроки();
КонецПроцедуры
// В модуле формы списка на сервере (или в общем модуле, если нужно универсально)
&НаСервере
Процедура УстановитьФлагВниманияНаСервере(СсылкаНаДокумент)
// Здесь мы используем выбранный подход, например, Подход 1
Попытка
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ДокОбъект.ОбменДанными.Загрузка = Истина;
ДокОбъект.ТребуетВнимания = Истина;
ДокОбъект.Записать();
СообщитьНаКлиенте("Флажок для документа " + СсылкаНаДокумент + " установлен.");
Исключение
СообщитьНаКлиенте("Ошибка при установке флажка: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Аналогично можно реализовать и другие подходы, вызывая соответствующие серверные функции.
Выбор конкретного метода зависит от нескольких факторов:
ОбменДанными.Загрузка) может быть предпочтительнее.ОбменДанными.Загрузка может быть быстрее в реализации. Для более сложных систем с большим количеством вспомогательных флагов, регистры сведений или дополнительные сведения будут более масштабируемыми.Таким образом, мы рассмотрели различные способы, как можно изменить булевый реквизит (чек-бокс) в проведенном документе 1С на управляемых формах, не затрагивая его проведения и движения регистров. Каждый из методов имеет свои преимущества и области применения, а выбор зависит от специфики вашей задачи и требований к системе.