Как отловить нажатие кнопки "Сохранить как" для табличного документа в 1С?

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

При разработке отчетов и печатных форм в системе «1С:Предприятие 8» часто возникает задача обеспечения безопасности данных. Руководство или служба безопасности могут потребовать ограничить несанкционированную выгрузку конфиденциальной информации в сторонние форматы (например, в Microsoft Excel) или хотя бы фиксировать каждый такой факт в журнале регистрации. Сегодня мы подробно разберем, как решить эту задачу, обойти платформенные ограничения и реализовать надежный механизм перехвата сохранения табличного документа.

Анализ проблемы: почему стандартного события не существует?

Начнем с того, что в платформе «1С:Предприятие» у объекта ТабличныйДокумент действительно отсутствует предопределенное событие вроде ПриСохранении() или ПередЗаписью(). Платформа проектировалась таким образом, что интерактивные действия пользователя с главным меню программы (включая команды «Файл — Сохранить» и «Файл — Сохранить как...») обрабатываются на уровне системного окружения платформы, не вызывая обработчиков в модуле формы отчета.

Давайте проанализируем, какие стандартные механизмы защиты часто путают с решением этой задачи, почему они не работают в полной мере и как с помощью комбинирования штатных средств добиться желаемого результата.

Разбор неэффективных способов защиты

В обсуждениях часто предлагают использовать свойства ограничения редактирования. Рассмотрим типичный пример программного кода:


ТабличныйДокумент.Защита = Истина;
ТабличныйДокумент.ТолькоПросмотр = Истина;

Давайте выясним, к чему приведет выполнение этого кода. Свойства Защита и ТолькоПросмотр заблокируют возможность интерактивного изменения ячеек пользователем. Он не сможет вручную вписать текст или удалить формулы. Однако это никак не помешает ему перейти в главное меню, выбрать пункт «Файл — Сохранить как...» и спокойно выгрузить документ на рабочий стол в формате Excel или PDF. Следовательно, этот способ совершенно не решает задачу контроля выгрузки данных.

Использование свойства «Вывод» для надежной блокировки

Наиболее надежным встроенным инструментом для управления возможностью сохранения печатных форм является свойство Вывод объекта ТабличныйДокумент. Это свойство принимает значения из системного перечисления ИспользованиеВывода.

Когда мы устанавливаем запрет вывода, платформа автоматически отключает все стандартные инструменты копирования и сохранения. Кнопки «Сохранить», «Сохранить как» и «Печать» в системном меню 1С становятся серыми (неактивными) для этого окна, а горячие клавиши Ctrl + S и Ctrl + P перестают работать.

Пропишем это ограничение программно в модуле формы при формировании отчета:


// Для программно созданного табличного документа
ТабличныйДокумент.Вывод = ИспользованиеВывода.Запретить;

// Или непосредственно для элемента управляемой формы (Поля табличного документа)
Элементы.Результат.Вывод = ИспользованиеВывода.Запретить;

Если пользователь или даже сторонний программный алгоритм попытаются вызвать метод Записать() для этого табличного документа, система вызовет исключение с ошибкой «Вывод запрещен». Это отличная отправная точка для построения нашей системы перехвата.

Ограничение на уровне ролей пользователей

Если ваша цель — полностью запретить конкретной группе пользователей выгружать любые отчеты из системы, мы можем сделать это без написания кода, используя Конфигуратор:

  1. Откроем нужную роль в Конфигураторе.
  2. В списке общих прав найдем право «Вывод» (Output).
  3. Снимем с него галочку.

Пользователи с этой ролью потеряют системную возможность сохранять любые табличные документы через главное меню программы. При этом разработчик может точечно разрешить сохранение конкретного важного отчета, прописав в его коде ТабДок.Вывод = ИспользованиеВывода.Разрешить непосредственно перед выводом на экран.

Пошаговый алгоритм: как «отловить» факт сохранения

Теперь перейдем к главной задаче: нам нужно не просто запретить сохранение, а зафиксировать (отловить) факт нажатия кнопки сохранения, выполнить аудит (записать событие в Журнал регистрации) и только после этого разрешить выгрузку файла. Поскольку прямого события нет, мы обойдем это ограничение с помощью подмены стандартного интерфейса.

Разберем этот процесс подробно по шагам.

Шаг 1. Отключаем стандартные команды сохранения на форме

Для начала нам необходимо лишить пользователя возможности использовать штатные кнопки меню. В свойствах элемента формы типа «Поле табличного документа» (например, с именем Результат) настроим параметры отображения:

Шаг 2. Создаем собственную команду сохранения

Добавим на управляемую форму новую команду, например, СохранитьВExcel, и выведем ее в виде кнопки на форму отчета. Эта кнопка будет единственным доступным для пользователя способом экспортировать данные.

Шаг 3. Реализуем обработчик команды с логированием

В модуле управляемой формы напишем обработчик для нашей команды. Здесь мы выполним три ключевых действия: зафиксируем операцию в Журнале регистрации, откроем диалог выбора пути сохранения файла и программно запишем документ.

Посмотрим на пример реализации кода на клиенте и сервере:


&НаКлиенте
Процедура СохранитьВExcel(Команда)

    // Шаг A: Инициализируем диалог выбора файла
    ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
    ДиалогВыбора.Фильтр = "Документ Excel (*.xlsx)|*.xlsx";
    ДиалогВыбора.МножественныйВыбор = Ложь;
    ДиалогВыбора.Заголовок = "Укажите путь для сохранения отчета";
    
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораФайла", ЭтотОбъект);
    ДиалогВыбора.Показать(Оповещение);

КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораФайла(РезультатВыбора, ДополнительныеПараметры) Экспорт

    Если РезультатВыбора = Неопределено Тогда
        Возврат; // Пользователь отменил сохранение
    КонецЕсли;
    
    ПутьКФайлу = РезультатВыбора[0];
    
    // Шаг B: Фиксируем событие в Журнале регистрации на сервере и выполняем запись
    УспешноСохранено = ЗаписатьДокументСЛогированиемНаСервере(ПутьКФайлу);
    
    Если УспешноСохранено Тогда
        ПоказатьПредупреждение(, "Файл успешно сохранен!");
    КонецЕсли;

КонецПроцедуры

Теперь реализуем серверную часть логики. Обратите внимание на то, как мы временно обходим запрет вывода для непосредственной записи файла:


&НаСервере
Функция ЗаписатьДокументСЛогированиемНаСервере(Знач ПутьКФайлу)

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

КонецФункции

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

← На главную