Как исправить NULL в субконто регистра бухгалтерии в 1С?

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

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

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

Почему появляется NULL и в чем его отличие от Неопределено

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

  1. NULL — это физическое отсутствие записи в подчиненной таблице субконто. Это «дырка» в данных. Обычно возникает, если на счете меняли состав субконто или если свертка базы прошла некорректно.
  2. Неопределено — это значение для составного типа данных, которое означает, что тип еще не выбран.
  3. Пустая ссылка — это значение конкретного типа (например, СправочникСсылка.Контрагенты.ПустаяСсылка()), указывающее на отсутствие выбора элемента.

Если в ОСВ вы видите пустые строки, которые не «схлопываются» между собой, скорее всего, в одном случае там NULL, а в другом — ПустаяСсылка. Платформа 1С при выполнении запросов и расчете итогов по-разному обрабатывает эти состояния, что ведет к дублированию строк и неверным остаткам.

Способ 1. Программная корректировка набора записей

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

Разберем алгоритм исправления по шагам:

  1. Выберем документы ОперацияБух за нужный период.
  2. Для каждого документа создадим набор записей регистра бухгалтерии с отбором по регистратору.
  3. Прочитаем набор и пройдем циклом по каждой записи (проводке).
  4. Для каждого счета (Дт и Кт) проверим все виды субконто.
  5. Применим метод ПривестиЗначение(), чтобы платформа сама определила нужный тип пустой ссылки.

Посмотрим на пример кода, который эффективно решает эту задачу:


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

Важный момент: Обратите внимание на использование Набор.ОбменДанными.Загрузка = Истина. Это критически важно при работе с регистром бухгалтерии. В этом режиме платформа не пытается автоматически «исправлять» субконто обратно или применять стандартные правила валидации, позволяя вам записать очищенные данные.

Способ 2. Физическое удаление субконто для получения NULL

Иногда задача стоит обратная: нужно не убрать NULL, а наоборот, сделать сторнирующую запись, которая будет в точности повторять битую проводку с NULL. Как мы выяснили, простое присвоение NULL не работает. В этом случае нам поможет метод Удалить() коллекции субконто.

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

Рассмотрим пример создания такой проводки:


Проводка = Набор.Добавить();
Проводка.Период = ДатаОперации;
Проводка.СчетДт = ВыбранныйСчет;
// ... заполнение других полей ...

// Допустим, нам нужно, чтобы второе субконто было NULL
ВидСубконтоДляУдаления = Проводка.СчетДт.ВидыСубконто[1].ВидСубконто;

// Вместо присвоения NULL, удаляем элемент из коллекции
Проводка.СубконтоДт.Удалить(ВидСубконтоДляУдаления);

Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать();

Способ 3. Использование XML-сериализации

Если программные методы через объектную модель 1С не помогают (например, из-за специфических ограничений конфигурации), можно прибегнуть к «низкоуровневому» исправлению через выгрузку в XML. Этот метод позволяет напрямую отредактировать структуру записи.

Выясним алгоритм действий:

  1. Выгружаем проблемный документ или набор записей с помощью обработки «Выгрузка и загрузка данных XML».
  2. Открываем полученный файл в текстовом редакторе.
  3. Ищем узел ExtDimensionDr или ExtDimensionCr.
  4. Для установки NULL необходимо, чтобы узел выглядел так: <ExtDimensionDr xsi:nil="true"/>, а соответствующий тип субконто был удален или закомментирован.
  5. Загружаем файл обратно в базу.

Этот способ является трудоемким и требует осторожности, так как нарушение структуры XML-файла сделает его нечитаемым для системы.

Рекомендации и выводы

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

Помните несколько правил:

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

← На главную