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