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

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

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

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

Анализ типичных ошибок при обращении к табличной части

Выясним причину, по которой код разработчика вызывает исключения. Рассмотрим ошибочные конструкции, которые часто пишутся интуитивно:

  1. Обращение через свойство «Колонки»:
    
    // Ошибка: Поле объекта не обнаружено (Колонки)
    Если ЭтотОбъект.Товары.Колонки.СчетУчетаБУ.Код = 2410 Тогда
    

    Коллекция Колонки существует у объекта ТаблицаЗначений, но отсутствует у объекта ТабличнаяЧасть. Кроме того, даже в таблице значений коллекция колонок описывает метаданные (имя, тип), а не содержит конкретные данные строк.

  2. Прямое обращение к реквизиту через имя табличной части:
    
    // Ошибка: Поле объекта не обнаружено (СчетУчетаБУ)
    Если ЭтотОбъект.Товары.СчетУчетаБУ.Код = 2410 Тогда
    

    Объект ТабличнаяЧасть представляет собой коллекцию строк. У самой коллекции нет реквизитов строк (таких как СчетЗатратБУ или Номенклатура) — они принадлежат отдельным строкам коллекции.

  3. Неправильный синтаксис обращения по индексу:
    
    // Ошибка: Поле объекта не обнаружено (Индекс)
    Если ЭтотОбъект.Товары.Индекс[0].СчетЗатратБУ = 2410 Тогда
    

    В платформе 1С получение элемента по индексу выполняется с помощью квадратных скобок непосредственно у самой коллекции: Товары[0].

Вариант 1. Обращение к конкретной строке по индексу

Если требуется проверить значение в строго определенной строке (например, в первой), обратимся к строке по индексу 0. При этом обязательно проверим, что табличная часть не пуста, чтобы не получить исключение «Индекс находится за границами диапазона».

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


Если ЭтотОбъект.Товары.Количество() > 0 Тогда
    СтрокаТЧ = ЭтотОбъект.Товары[0];
    
    // Сравнение кода счета в виде строки
    Если СтрокаТЧ.СчетЗатратБУ.Код = "2410" Тогда
        // Выполняем алгоритм формирования движений
    КонецЕсли;
КонецЕсли;

Вариант 2. Проверка счета внутри цикла обхода строк (Рекомендуемый)

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

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


// Получаем предопределенный счет заранее, чтобы не делать лишних запросов в цикле
СчетОС = ПланыСчетов.Типовой.НайтиПоКоду("2410");

ОперацииОС = Движения.СобытияОСОрганизаций;
ПараметрыАмортизацииОС = Движения.ПараметрыАмортизацииОСБухгалтерскийУчет;

Для Каждого СтрокаТЧ Из Товары Цикл

    // Проверяем счет учета текущей строки
    Если СтрокаТЧ.СчетЗатратБУ = СчетОС Тогда
        
        ТекОС = СтрокаТЧ.СубконтоЗатратБУ1;
        
        // Формируем движения по регистрам ОС
        Движение = ОперацииОС.Добавить();
        Движение.Период = Дата;
        Движение.ОсновноеСредство = ТекОС;
        Движение.Организация = СтруктураШапкиДокумента.Организация;
        Движение.СтруктурноеПодразделение = СтруктураШапкиДокумента.СтруктурноеПодразделение;
        Движение.Событие = СтруктураШапкиДокумента.СобытиеОС;
        Движение.НазваниеДокумента = Строка(Метаданные());
        Движение.НомерДокумента = Номер;
        
        ДвижениеАм = ПараметрыАмортизацииОС.Добавить();
        ДвижениеАм.Период = Дата;
        ДвижениеАм.ОсновноеСредство = ТекОС;
        ДвижениеАм.Организация = СтруктураШапкиДокумента.Организация;
        ДвижениеАм.СтруктурноеПодразделение = СтруктураШапкиДокумента.СтруктурноеПодразделение;
        ДвижениеАм.СрокПолезногоИспользования = СтрокаТЧ.СрокПолезногоИспользованияБУ;
        ДвижениеАм.СтоимостьДляВычисленияАмортизации = СтрокаТЧ.СтоимостьБУ + (СтрокаТЧ.СуммаМодернизацииБУ * СтрокаТЧ.Количество);
        
    КонецЕсли;

КонецЦикла;

Вариант 3. Использование метода НайтиСтроки()

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


СчетОС = ПланыСчетов.Типовой.НайтиПоКоду("2410");

ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("СчетЗатратБУ", СчетОС);

МассивСтрокОС = Товары.НайтиСтроки(ПараметрыОтбора);

Для Каждого СтрокаТЧ Из МассивСтрокОС Цикл
    // Обработка строк, в которых счет затрат равен 2410
КонецЦикла;

Рекомендации по работе со счетами учета и субконто

  1. Сравнение по ссылке, а не по коду: Сравнение СтрокаТЧ.СчетЗатратБУ.Код = "2410" выполняет неявное обращение к базе данных через точку для каждой строки. Рекомендуется один раз получить ссылку на счет (через ПланыСчетов.Типовой... или метод НайтиПоКоду до цикла) и сравнивать ссылки напрямую.
  2. Проверка подчиненности счетов: Если счет «2410» имеет подчиненные субсчета (например, 2411, 2412), прямое равенство не сработает для субсчетов. В таких случаях используйте метод СтрокаТЧ.СчетЗатратБУ.ПринадлежитЭлементу(СчетОС) или ВПодчинении().
  3. Проверка типа субконто: Реквизит СубконтоЗатратБУ1 имеет составной тип. Перед заполнением специализированных регистров внеоборотных активов убедитесь, что в субконто действительно передан элемент нужного справочника:
    
    Если ЗначениеЗаполнено(ТекОС) И ТипЗнч(ТекОС) = Тип("СправочникСсылка.ОсновныеСредства") Тогда
        // Запись в регистры ОС
    КонецЕсли;
    
← На главную