Как программно удалить документ из его формы по нажатию кнопки в 1С?

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

При работе в системе 1С у многих разработчиков и продвинутых пользователей возникает задача программного удаления документов. Это может потребоваться в различных сценариях: от исправления ошибок массового ввода до реализации специфических бизнес-процессов. Особый интерес представляет удаление документа непосредственно из его формы по нажатию кнопки. Давайте разберем этот вопрос подробно, рассмотрим все нюансы и предложим рабочие решения.

Прежде всего, важно понимать, что в 1С существует два принципиально разных подхода к "удалению" документов:

  1. Пометка на удаление: Это безопасный и рекомендуемый способ. Документ физически остается в базе, но помечается специальным флагом. Его можно скрыть из списков и в дальнейшем удалить с помощью регламентного задания, которое проверяет ссылочную целостность.
  2. Прямое физическое удаление: Это немедленное и безвозвратное удаление документа из базы данных. Такой подход требует особой осторожности, так как он может привести к нарушению ссылочной целостности, появлению "битых" ссылок и потере важных данных.

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

1. Механизм пометки на удаление: безопасный подход

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

1.1. Как работает пометка на удаление

При пометке на удаление документ не исчезает из базы данных. Вместо этого у него устанавливается специальный флаг (реквизит объекта) ПометкаУдаления в значение Истина. Системные списки и отчеты могут быть настроены так, чтобы не отображать помеченные объекты. Физическое удаление таких объектов происходит позднее с помощью регламентной операции "Удаление помеченных объектов". Этот механизм обеспечивает проверку ссылочной целостности: система не позволит удалить объект, на который существуют ссылки из других объектов, пока эти ссылки не будут изменены или удалены.

1.2. Реализация пометки на удаление из формы документа

Для реализации пометки на удаление из формы документа по нажатию кнопки, мы можем использовать следующий код. Предположим, у нас есть кнопка "Пометить на удаление" на форме документа.


&НаКлиенте
Процедура УдалитьДокумент(Команда)
    // Вызываем серверную процедуру для выполнения операций с данными
    ПометитьНаУдалениеНаСервере();
    // Закрываем форму текущего документа
    ЭтаФорма.Закрыть();
КонецПроцедуры

&НаСервере
Процедура ПометитьНаУдалениеНаСервере()
    // Перед пометкой на удаление, если документ был проведен,
    // желательно отменить его проведение, чтобы очистить движения по регистрам.
    // Это не обязательный шаг, но рекомендованный для корректной работы.
    Если Объект.Проведен Тогда
        Записать(Новый Структура("РежимЗаписи", РежимЗаписиДокумента.ОтменаПроведения));
    КонецЕсли;
    
    // Устанавливаем флаг пометки на удаление
    Объект.ПометкаУдаления = Истина;
    // Записываем объект с установленной пометкой
    Объект.Записать();
КонецПроцедуры

После выполнения этого кода документ будет помечен на удаление и форма закроется. Чтобы увидеть изменения в списках, возможно, потребуется обновить список документов (например, повторно открыть журнал или нажать кнопку "Обновить").

2. Прямое физическое удаление документа: когда это необходимо и как его реализовать

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

2.1. Основные методы программного удаления объекта

Для прямого удаления объекта в 1С используется метод Удалить(). Этот метод вызывается у объекта документа, который предварительно необходимо получить из базы данных. Мы не можем удалить документ напрямую из его формы, если объект еще не записан или находится в режиме редактирования. Нам потребуется получить актуальный объект из базы данных.

  1. Получение объекта: Прежде чем удалить объект, нам нужно получить его актуальную версию из базы данных. Это делается с помощью метода ПолучитьОбъект(), который возвращает объект документа по ссылке.
  2. Метод Удалить(): После получения объекта мы вызываем у него метод Удалить().

Пример базового кода на сервере:


&НаСервере
Процедура УдалитьОбъектНаСервере(СсылкаНаДокумент)
    // Получаем объект документа по ссылке
    ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
    
    Если ДокОбъект <> Неопределено Тогда
        // Вызываем метод Удалить()
        ДокОбъект.Удалить();
    КонецЕсли;
КонецПроцедуры

2.2. Учет прав доступа и использование привилегированного режима

Для выполнения операции прямого удаления у пользователя должны быть соответствующие права. Если у пользователя недостаточно прав на "Интерактивное удаление документа" или полных прав на документ, система выдаст ошибку, и код не будет выполнен. В некоторых случаях, особенно при выполнении операций, которые должны игнорировать стандартные ограничения прав текущего пользователя (например, в фоновом режиме или для административных задач), можно использовать метод УстановитьПривилегированныйРежим().

Пример использования:


&НаСервере
Процедура УдалитьОбъектПривилегированно(СсылкаНаДокумент)
    УстановитьПривилегированныйРежим(Истина); // Включаем привилегированный режим
    Попытка
        ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
        Если ДокОбъект <> Неопределено Тогда
            ДокОбъект.Удалить();
        КонецЕсли;
    Исключение
        Сообщить("Ошибка при удалении документа: " + ОписаниеОшибки());
    КонецПопытки;
    УстановитьПривилегированныйРежим(Ложь);  // Выключаем привилегированный режим
КонецПроцедуры

Используйте привилегированный режим с максимальной осторожностью, поскольку это может создать потенциальные уязвимости в безопасности системы.

2.3. Использование свойства ОбменДанными.ЗагрузкаДанных = Истина

При прямом удалении документа методом Удалить() иногда необходимо установить свойство ОбменДанными.ЗагрузкаДанных = Истина; у объекта документа. Это свойство отключает стандартные проверки, которые выполняются при записи или удалении объектов, и имитирует загрузку данных из внешнего источника.

Зачем это нужно: В некоторых случаях внутренние механизмы платформы или конфигурации могут препятствовать удалению документа (например, если есть специфические проверки при записи/удалении). Установка ОбменДанными.ЗагрузкаДанных = Истина позволяет обойти эти проверки. Однако, это также существенно повышает риск нарушения целостности данных, так как вы фактически "обманываете" систему.

Пример использования:


&НаСервере
Процедура УдалитьОбъектЧерезОбменДанными(СсылкаНаДокумент)
    УстановитьПривилегированныйРежим(Истина);
    Попытка
        ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
        Если ДокОбъект <> Неопределено Тогда
            ДокОбъект.ОбменДанными.ЗагрузкаДанных = Истина; // Отключаем проверки
            ДокОбъект.Удалить();
        КонецЕсли;
    Исключение
        Сообщить("Ошибка при удалении документа: " + ОписаниеОшибки());
    КонецПопытки;
    УстановитьПривилегированныйРежим(Ложь);
КонецПроцедуры

2.4. Удаление движений по регистрам

Когда вы физически удаляете документ, который формировал движения по регистрам (накопления, бухгалтерии, сведений), эти движения обычно удаляются автоматически вместе с документом. Платформа 1С самостоятельно отслеживает связи между документами и их движениями. Однако, в сложных или нетиповых конфигурациях, а также при использовании нестандартных механизмов формирования движений, рекомендуется убедиться, что все связанные данные удалены корректно. При возникновении проблем с остаточными записями регистраторов пригодится обработка для удаления движений по битым ссылкам.

2.5. Проверка ссылочной целостности перед удалением

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

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

Для проверки ссылочной целостности в типовых конфигурациях 1С (особенно построенных на БСП - Библиотеке стандартных подсистем) часто используется функция ОбщегоНазначения.ЕстьСсылкиНаОбъект(). Эта функция позволяет узнать, ссылаются ли на данный объект другие элементы базы данных.

Пример использования:


&НаСервере
Функция ПроверитьСсылкиИУдалить(СсылкаНаДокумент)
    // Проверяем наличие ссылок на документ
    Если ОбщегоНазначения.ЕстьСсылкиНаОбъект(СсылкаНаДокумент) Тогда
        Сообщить("Невозможно удалить документ. На него существуют ссылки из других объектов.");
        Возврат Ложь;
    КонецЕсли;
    
    // Если ссылок нет, приступаем к удалению
    УстановитьПривилегированныйРежим(Истина);
    Попытка
        ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
        Если ДокОбъект <> Неопределено Тогда
            ДокОбъект.ОбменДанными.ЗагрузкаДанных = Истина;
            ДокОбъект.Удалить();
            Сообщить("Документ успешно удален.");
            Возврат Истина;
        Иначе
            Сообщить("Документ не найден.");
            Возврат Ложь;
        КонецЕсли;
    Исключение
        Сообщить("Ошибка при удалении документа: " + ОписаниеОшибки());
        Возврат Ложь;
    КонецПопытки;
    КонецПопытки; // Опечатка, должно быть End Try, но в 1С нет такой конструкции, просто конец Попытки-Исключения.
    УстановитьПривилегированныйРежим(Ложь);
КонецФункции

2.6. Комплексный пример кода для прямого удаления из формы документа

Теперь давайте объединим все рассмотренные шаги в одном комплексном примере, который можно применить для удаления текущего документа из его формы по нажатию кнопки. Предположим, у нас есть кнопка "УдалитьТекущийДокумент" на форме документа.


&НаКлиенте
Процедура УдалитьТекущийДокумент(Команда)
    // Предупреждаем пользователя о безвозвратности операции
    Ответ = Вопрос("Вы уверены, что хотите безвозвратно удалить этот документ? Операция необратима и может привести к проблемам с данными, если на документ есть ссылки.", РежимДиалогаВопрос.ДаНет, 0);
    Если Ответ = КодВозвратаДиалога.Нет Тогда
        Возврат;
    КонецЕсли;

    // Вызываем серверную процедуру для выполнения удаления
    Если УдалитьОбъектПолностьюНаСервере() Тогда
        // Если удаление прошло успешно, закрываем форму
        ЭтаФорма.Закрыть();
    КонецЕсли;
КонецПроцедуры

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

    // 2. Включаем привилегированный режим и отключаем проверки
    УстановитьПривилегированныйРежим(Истина);
    Попытка
        // Получаем объект документа по ссылке
        ДокОбъект = СсылкаНаТекущийДокумент.ПолучитьОбъект();
        
        Если ДокОбъект <> Неопределено Тогда
            // Отменяем проведение, если документ был проведен.
            // Это желательно для корректной очистки движений, хотя при прямом удалении они тоже удалятся.
            Если ДокОбъект.Проведен Тогда
                ДокОбъект.Записать(Новый Структура("РежимЗаписи", РежимЗаписиДокумента.ОтменаПроведения));
            КонецЕсли;

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

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

3. Контекст выполнения: Клиент или Сервер

В управляемых формах 1С важно понимать разницу между клиентским и серверным контекстом выполнения кода. Операции, которые взаимодействуют с базой данных (запись, чтение, удаление объектов), всегда должны выполняться на сервере. Клиентский код предназначен для взаимодействия с пользовательским интерфейсом (например, отображение форм, реакция на нажатия кнопок).

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

4. Последствия прямого удаления и альтернативные подходы

Мы настоятельно рекомендуем тщательно взвесить все "за" и "против" перед использованием прямого физического удаления документов.

4.1. Основные последствия:

  1. Потеря данных для аудита и отчетности: Прямое удаление полностью стирает информацию о документе, что может быть критично для исторического анализа, аудита и выполнения требований законодательства.
  2. Нарушение ссылочной целостности: Если не выполнить тщательную проверку, появление "битых" ссылок практически гарантировано, что приведет к ошибкам в других частях системы.
  3. Необратимость операции: Восстановить случайно удаленный документ без резервной копии будет невозможно.

4.2. Альтернативы "реальному" удалению, если цель — не отображать в списках:

  1. Пометка на удаление: Как мы уже подробно рассмотрели, это самый безопасный вариант. Документ не виден, но его можно восстановить.
  2. Изменение статуса: Можно добавить в документ дополнительный реквизит, например, "Статус" (со значениями "Действующий", "Аннулирован", "Архивный"). Затем настроить списки документов и отчеты так, чтобы они не отображали документы с определенным статусом. Это позволяет сохранить полную историю документа и управлять его видимостью.
  3. Перемещение в архив: Для редко используемых или устаревших документов можно создать механизм их перемещения в архивную базу данных или специальные регистры. Это уменьшит объем основной базы и повысит производительность, сохраняя при этом доступ к историческим данным.

В целом, подход "скрыть, но не удалить" часто является более предпочтительным с точки зрения безопасности данных и гибкости системы.

Мы рассмотрели различные аспекты программного удаления документов в 1С. Выяснили, что самый безопасный способ — это пометка на удаление, но при необходимости прямого физического удаления можно использовать методы объекта Удалить() в сочетании с ПолучитьОбъект(), привилегированным режимом УстановитьПривилегированныйРежим() и отключением проверок через ОбменДанными.ЗагрузкаДанных = Истина. Самое главное — всегда выполняйте проверку ссылочной целостности с помощью функций вроде ОбщегоНазначения.ЕстьСсылкиНаОбъект(). Помните, что каждое такое действие может иметь серьезные последствия для данных вашей информационной системы.

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

← На главную