Как программно очистить значение субконто в 1С:Предприятии 8 без ошибок и задвоения итогов?

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

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

На первый взгляд задача кажется тривиальной: достаточно прочитать набор записей регистра, обойти проводки в цикле и присвоить нужному субконто значение Неопределено. Однако на практике такой подход либо вообще не изменяет данные в базе (изменения «тихо» игнорируются системой), либо приводит к катастрофическим последствиям для учета, таким как задвоение строк в оборотно-сальдовой ведомости (ОСВ) и зависание остатков. В этой статье мы подробно разберем, почему так происходит, проанализируем внутренние механизмы платформы 1С и выработаем надежное, безопасное решение.

Почему простая передача «Неопределено» не работает?

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


// Пример неработающего кода
Для Каждого Проводка Из НаборЗаписей Цикл
    БухгалтерскийУчет.УстановитьСубконто(Проводка.СчетДт, Проводка.СубконтоДт, НомерСубконто, Неопределено);
КонецЦикла;
НаборЗаписей.Записать();

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

Если мы заглянем внутрь общего модуля БухгалтерскийУчет (или обратимся к аналогичным механизмам в старых конфигурациях вроде УПП), то увидим следующую проверку типов перед записью аналитики:


Если ВидСубк.ТипЗначения.СодержитТип(ТипЗнч(ЗначениеСубконто)) Тогда
    Субконто.Вставить(ВидСубк, ЗначениеСубконто);
КонецЕсли;

Здесь кроется ключевой нюанс работы платформы: у каждого субконто на конкретном счете жестко задан тип значения (например, СправочникСсылка.Контрагенты или ДокументСсылка.РеализацияТоваровУслуг). Тип данных Неопределено не входит в это описание типов. Метод СодержитТип() возвращает значение Ложь, программа игнорирует попытку записи и молча переходит к следующей итерации. В итоге в базе данных сохраняются старые значения.

Опасность использования «Неопределено» и скрытые угрозы для учета

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

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

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

Пошаговое руководство: как правильно очистить субконто

Для того чтобы корректно очистить субконто, нам потребуется решить две задачи:

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

Рассмотрим подробнее каждый шаг на практическом примере.

Шаг 1. Отказ от числовых индексов (номеров) субконто

Использование порядкового номера (например, передача тройки в качестве третьего параметра) крайне ненадежно. На одном счете «Номенклатура» может быть первым субконто, а на другом — вторым или третьим. Более того, при обновлении конфигурации или изменении плана счетов порядок субконто может поменяться.

Правильный подход — обращаться к субконто напрямую через ссылку на План видов характеристик. Например, так:

ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты

Шаг 2. Динамическое получение пустой ссылки типа субконто

Для того чтобы автоматически получить пустую ссылку нужного типа (независимо от того, справочник это, документ или перечисление), мы воспользуемся методом ПривестиЗначение() объекта ОписаниеТипов, который хранится в реквизите ТипЗначения вида субконто.

Проанализируем этот изящный способ получения пустой ссылки:


// Получаем вид субконто (ПВХ)
ВидСубконто = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры;

// Метод ПривестиЗначение() без параметров возвращает пустую ссылку для данного ОписанияТипов
ПустоеЗначениеСубконто = ВидСубконто.ТипЗначения.ПривестиЗначение();

Этот способ универсален. Если тип субконто числовой — мы получим 0, если строковый — пустую строку "", если ссылочный — корректную пустую ссылку нужного объекта метаданных.

Полный пример корректного кода для очистки субконто

Объединим все наши выводы в одну готовую процедуру. Этот код безопасно и корректно очищает конкретное субконто (например, «Документы расчетных документов» или «Договоры») в проводках выбранного документа:


Процедура ОчиститьАналитикуВДокументе(ДокументСсылка) Экспорт

    // Определяем вид субконто, который необходимо очистить
    ВидСубконтоДляОчистки = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры;
    
    // Получаем корректное пустое значение (пустую ссылку) для этого субконто
    ПустоеЗначение = ВидСубконтоДляОчистки.ТипЗначения.ПривестиЗначение();

    // Создаем набор записей для работы с движениями документа
    НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);
    НаборЗаписей.Прочитать();

    Модифицировано = Ложь;

    Для Каждого Проводка Из НаборЗаписей Цикл
        
        // Проверяем наличие нужного вида субконто в дебете счета
        Если Проводка.СубконтоДт.Свойство(ВидСубконтоДляОчистки) Тогда
            // Устанавливаем именно пустую ссылку, а не Неопределено!
            БухгалтерскийУчет.УстановитьСубконто(Проводка.СчетДт, Проводка.СубконтоДт, ВидСубконтоДляОчистки, ПустоеЗначение);
            Модифицировано = Истина;
        КонецЕсли;
        
        // Проверяем наличие нужного вида субконто в кредите счета
        Если Проводка.СубконтоКт.Свойство(ВидСубконтоДляОчистки) Тогда
            БухгалтерскийУчет.УстановитьСубконто(Проводка.СчетКт, Проводка.СубконтоКт, ВидСубконтоДляОчистки, ПустоеЗначение);
            Модифицировано = Истина;
        КонецЕсли;
        
    КонецЦикла;

    // Записываем набор только в случае реального изменения данных
    Если Модифицировано Тогда
        НаборЗаписей.Записать();
    КонецЕсли;

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

Особенности работы с составными типами данных

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

В такой ситуации платформа при вызове метода ПривестиЗначение() без параметров вернет Неопределено. Для составных типов данных запись значения Неопределено является легитимным действием платформы и не приводит к расхождениям в итогах, так как система понимает отсутствие конкретного выбранного типа среди множества возможных вариантов. Наш предложенный универсальный алгоритм автоматически и корректно обработает и этот сложный случай!

← На главную