Как исправить ошибку «Вид субконто не доступен для данной записи» при программном изменении проводок?

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

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

Проанализируем причину возникновения ошибки

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

Рассмотрим ситуацию: на счете 76.10 установлена аналитика «Работники организаций», а на счете 76.05 такой аналитики нет. Если мы в коде пишем:


Строка.СчетКт = ПланыСчетов.Хозрасчетный.РасчетыСПрочимиПоставщикамиИПодрядчиками; // Это счет 76.05

То в этот момент в коллекции СубконтоКт все еще остается «ключ» (индекс), указывающий на вид субконто «Работники организаций», который был актуален для предыдущего счета. Даже если вы попытаетесь присвоить этому субконто значение Неопределено, ошибка не исчезнет. Почему? Потому что само обращение к Строка.СубконтоКт[ВидСубконто] подтверждает системе, что этот вид субконто должен присутствовать в записи. А так как для нового счета (76.05) этот вид аналитики не предусмотрен в плане счетов, платформа выдает ошибку при попытке записи набора.

Решение №1: Использование метода Очистить() — самый быстрый и правильный путь

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


&После("ОбработкаПроведения")
Процедура ИмяРасширения_ОбработкаПроведенияПосле(Отказ, РежимПроведения)
    
    ДвиженияХозрасчетный = Движения.Хозрасчетный;
    
    Для Каждого Строка Из ДвиженияХозрасчетный Цикл
        
        // Проверяем, нужно ли менять счет
        Если Строка.СчетКт = ПланыСчетов.Хозрасчетный.ПрочиеРасчетыСФизическимиЛицами Тогда
            
            // 1. Сохраняем необходимые данные из старого субконто во временные переменные
            ФизЛицо = Строка.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.РаботникиОрганизаций];
            
            // 2. Меняем счет
            Строка.СчетКт = ПланыСчетов.Хозрасчетный.РасчетыСПрочимиПоставщикамиИПодрядчиками;
            
            // 3. КРИТИЧЕСКИЙ ШАГ: Полностью очищаем коллекцию субконто.
            // Это удаляет все старые связи с видами субконто, которые были у счета 76.10
            Строка.СубконтоКт.Очистить();
            
            // 4. Заполняем новую аналитику для счета 76.05
            // Теперь коллекция инициализируется заново на основании метаданных нового счета
            Строка.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты] = ФизЛицо.Контрагент;
            Строка.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры] = ФизЛицо.ДоговорКонтрагента;
            
        КонецЕсли;
        
    КонецЦикла;
    
    // Не забываем, что если мы меняем движения после основного проведения, 
    // нужно убедиться, что набор записей будет записан.
    Движения.Хозрасчетный.Записывать = Истина;

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

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

Решение №2: Выгрузка в Таблицу Значений

Разберем еще один надежный способ, который часто применяют опытные разработчики при массовом изменении проводок. Этот метод помогает избежать конфликтов с метаданными в процессе итерации по коллекции движений. Суть заключается в том, что в Таблице Значений нет жесткой проверки типов субконто в момент присвоения значений.

Выполним следующие шаги:

  1. Выгрузим текущие движения в таблицу значений с помощью метода Выгрузить().
  2. Обработаем данные в таблице: заменим счета и заполним колонки субконто.
  3. Очистим текущий набор записей регистра.
  4. Загрузим измененную таблицу обратно с помощью метода Загрузить().

Рассмотрим пример реализации:


ТаблицаДвижений = Движения.Хозрасчетный.Выгрузить();

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

// Загружаем данные обратно в набор записей
Движения.Хозрасчетный.Загрузить(ТаблицаДвижений);

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

Почему присвоение «Неопределено» не является решением?

Многие начинающие программисты полагают, что строка Строка.СубконтоКт[ВидСубконто] = Неопределено; эквивалентна удалению субконто. Проанализируем, почему это не так. В регистре бухгалтерии значение Неопределено для субконто трактуется как «значение не выбрано, но сам разрез аналитики существует». То есть вы не удаляете вид субконто из записи, а лишь обнуляете его значение. Система продолжает считать, что этот вид субконто «привязан» к данной проводке, и при записи обнаруживает несоответствие новому счету.

Важные рекомендации при работе с движениями

Чтобы избежать подобных ошибок в будущем, рекомендуем соблюдать строгую последовательность действий при программном формировании или изменении проводок:

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

← На главную