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

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

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

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

«Запись не верна! Вид субконто "..." не доступен для данной записи! (Регистр бухгалтерии: ...)»

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

Выясняем причину: почему простая очистка через «Неопределено» не работает?

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

Когда вы выполняете код вида:

СтрокаПроводки.СубконтоКт.НоменклатурныеГруппы = Неопределено;

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

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

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

Решение 1. Полная очистка коллекции субконто с помощью метода «Очистить()»

Если для нового счета вообще не требуется ведение аналитики (на нем нет субконто) или если вы планируете заполнить всю аналитику с нуля, самым простым и быстрым решением будет полная очистка коллекции субконто для данной стороны проводки.

Для этого у объекта коллекции субконто существует стандартный метод Очистить(). Давайте посмотрим на практический пример кода, выполняющего эту операцию:


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

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

// Записываем обновленный набор движений
НаборЗаписей.Записать();

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

Решение 2. Точечное удаление конкретного вида субконто методом «Удалить()»

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

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


// Удаляем только конкретный вид субконто, ставший неактуальным
ВидСубконтоДляУдаления = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.НоменклатурныеГруппы;
Проводка.СубконтоКт.Удалить(ВидСубконтоДляУдаления);

Этот метод полностью стирает ключ аналитики из коллекции проводки. При записи система больше не увидит запрещенного вида субконто и успешно примет изменения.

Решение 3. Универсальный динамический алгоритм очистки лишних субконто

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

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

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


// Массив для хранения видов субконто, подлежащих удалению
ЛишниеСубконто = Новый Массив;

// Шаг 1. Анализируем субконто Кредита проводки
Для Каждого КлючИЗначение Из Проводка.СубконтоКт Цикл
    ТекущийВидСубконто = КлючИЗначение.Ключ;
    
    // Проверяем, настроен ли данный вид субконто на новом счете Кт
    Если Проводка.СчетКт.ВидыСубконто.Найти(ТекущийВидСубконто) = Неопределено Тогда
        // Если вид субконто не найден на новом счете, помечаем его на удаление
        ЛишниеСубконто.Добавить(ТекущийВидСубконто);
    КонецЕсли;
КонецЦикла;

// Шаг 2. Физически удаляем неподдерживаемые виды субконто
Для Каждого ВидСубконто Из ЛишниеСубконто Цикл
    Проводка.СубконтоКт.Удалить(ВидСубконто);
КонецЦикла;

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

Решение 4. Использование механизмов БСП (Библиотеки Стандартных Подсистем)

Если ваша конфигурация построена на базе БСП (а это практически все современные конфигурации: «Бухгалтерия предприятия», «ERP», «Комплексная автоматизация», «Управление торговлей»), разработчики 1С уже позаботились о решении этой проблемы за нас.

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

Синтаксис использования выглядит следующим образом:


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

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

Важная деталь: «Неопределено» против Пустой ссылки

Завершая разбор работы с субконто, рассмотрим важный стандарт разработки фирмы «1С», пренебрежение которым часто приводит к логическим ошибкам в отчетах.

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

Например, вместо установки Неопределено для незаполненной номенклатурной группы используйте следующий код:


Проводка.СубконтоКт.НоменклатурныеГруппы = Справочники.НоменклатурныеГруппы.ПустаяСсылка();

Почему это важно? Если в регистр будет записано значение Неопределено для поддерживаемого субконто, то стандартные бухгалтерские отчеты (такие как Оборотно-сальдовая ведомость или Анализ субконто) могут отображать незаполненную аналитику некорректно — пустые строки будут раздваиваться на системные группы «<...>» (соответствующую пустой ссылке) и пустое поле «Неопределено». Запись пустых ссылок гарантирует корректность ведения и отображения итогов по счетам учета.

← На главную