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