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