Как исправить ошибку "Метод объекта не обнаружен (СтавкаНДС)" и правильно рассчитать сумму без НДС в 1С?

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

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

1. Понимание различий между реквизитом и методом в 1С

Первопричина ошибки "Метод объекта не обнаружен (СтавкаНДС)" кроется в фундаментальном непонимании базовых концепций программирования в 1С:Предприятии — различия между реквизитом (свойством) и методом. Разберем эти понятия:

  1. Реквизит (свойство): Это данные, которые хранятся в объекте. Вы можете думать о реквизите как о ячейке памяти, которая содержит определенное значение (число, строка, дата, ссылка на другой объект и т.д.). Для того чтобы получить или установить значение реквизита, мы обращаемся к нему напрямую по имени.
  2. Например, если у нас есть строка табличной части Стр и в ней есть реквизит СтавкаНДС, то для получения его значения мы пишем:

    ЗначениеСтавки = Стр.СтавкаНДС;

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

  3. Метод (функция или процедура): Это подпрограмма, которая выполняет определенное действие над объектом или возвращает вычисленное значение. Вызов метода всегда сопровождается круглыми скобками, даже если у него нет параметров.
  4. Например, чтобы записать документ, мы используем метод Записать():

    Документ.Записать();

    Или, чтобы получить номер нового документа, метод УстановитьНовыйНомер():

    ЗаказПоставщику.УстановитьНовыйНомер();

В вашем первоначальном коде, когда вы получали ошибку "Метод объекта не обнаружен (СтавкаНДС)", система сообщала, что она пытается найти и выполнить метод с именем СтавкаНДС, но такого метода у объекта (строки табличной части) не существует. Это произошло, вероятно, из-за того, что вы (или система в определенном контексте) пытались использовать этот реквизит так, как если бы это был метод.

Важно: Если вы видите ошибку "Метод объекта не обнаружен", первым делом проверьте, не пытаетесь ли вы вызвать реквизит как метод, добавляя к нему скобки. Или же объект, к которому вы обращаетесь, не обладает таким методом.

2. Работа с реквизитом "СтавкаНДС" и ошибка "Преобразование значения к типу Число не может быть выполнено"

После устранения синтаксической ошибки с вызовом несуществующего метода, вы могли столкнуться со следующей проблемой, как в сообщении 14: "Преобразование значения к типу Число не может быть выполнено" при обращении к Стр.СтавкаНдс без скобок. Это указывает на более глубокую причину — значение реквизита СтавкаНДС не является числом напрямую.

В большинстве типовых конфигураций 1С (Бухгалтерия, Управление торговлей, ERP и т.д.) ставка НДС в документах хранится не как простое число, а как:

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

ПроцентСтавкиНДС = Стр.СтавкаНДС.ПроцентНДС;

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

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

3. Правильный расчет СуммыБезНДС и СуммыНДС

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

Формула для расчета суммы без НДС из суммы с НДС выглядит следующим образом:

СуммаБезНДС = СуммаСНДС / (1 + СтавкаНДС / 100)

Или, для получения суммы самого НДС:

СуммаНДС = СуммаСНДС - СуммаБезНДС

Применим это к вашему коду. Исходный код выглядел так:

Стр.СуммаНДС = Стр.Сумма - (Стр.Сумма/(100+Стр.СтавкаНдс)*100);

Здесь Стр.Сумма — это сумма с НДС. Часть (Стр.Сумма/(100+Стр.СтавкаНдс)*100) фактически вычисляет СуммуБезНДС. Таким образом, ваша формула для Стр.СуммаНДС была корректна для получения именно суммы налога, но только если Стр.СтавкаНдс была числом.

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


Для каждого СтрИзПрихода Из Объект.Запасы Цикл
    // Проверяем, что ставка НДС заполнена и является ссылкой
    Если ТипЗнч(СтрИзПрихода.СтавкаНДС) = Тип("СправочникСсылка.СтавкиНДС") Тогда
        // Получаем числовой процент из элемента справочника
        ПроцентСтавкиНДС = СтрИзПрихода.СтавкаНДС.ПроцентНДС; 
    Иначе
        // Если СтавкаНДС не ссылка на справочник, возможно, это число или Неопределено
        // В типовых конфигурациях обычно используют справочник.
        // Если у вас число, то просто используем его:
        Если ТипЗнч(СтрИзПрихода.СтавкаНДС) = Тип("Число") Тогда
            ПроцентСтавкиНДС = СтрИзПрихода.СтавкаНДС;
        Иначе
            // Обработка случая, когда ставка не определена или имеет другой тип
            // Например, принять 0% или выбросить ошибку
            ПроцентСтавкиНДС = 0;
        КонецЕсли;
    КонецЕсли;

    // Вычисляем СуммуБезНДС
    Если ПроцентСтавкиНДС > 0 Тогда
        // Стр.Сумма - это сумма с НДС
        СуммаБезНДС = СтрИзПрихода.Сумма / (1 + ПроцентСтавкиНДС / 100);
        СуммаНДС       = СтрИзПрихода.Сумма - СуммаБезНДС;
    Иначе
        СуммаБезНДС = СтрИзПрихода.Сумма;
        СуммаНДС       = 0;
    КонецЕсли;
    
    // Здесь мы должны заполнить соответствующие реквизиты строки нового документа
    // Например, если в ЗаказеПоставщику есть реквизиты СуммаБезНДС и СуммаНДС
    // Для демонстрации примера, мы покажем, как это можно сделать
    // Но вы должны заполнить это для строки ЗаказПоставщику, а не строки Прихода

    // Пример заполнения для новой строки ЗаказаПоставщику (ТекСтрокаЗаказПоставщику)
    // ТекСтрокаЗаказПоставщику.Сумма = СуммаБезНДС; // Если нам нужна цена без НДС
    // ТекСтрокаЗаказПоставщику.СуммаНДС = СуммаНДС;
    // ТекСтрокаЗаказПоставщику.Цена = СуммаБезНДС / ТекСтрокаЗаказПоставщику.Количество;
КонецЦикла;

Полностью исправленный и оптимизированный код (с учетом лишнего цикла):

В оригинальном коде присутствуют два цикла по Объект.Запасы, что является неоптимальным. Мы можем объединить логику копирования и расчета в один цикл.


&НаСервере
Функция НС_СоздатьЗаказПоставщикуПослеНаСервере()
    Если Объект.Запасы.Количество > 0 Тогда
        ЗаказПоставщику = Документы.ЗаказПоставщику.СоздатьДокумент();
        ЗаполнитьЗначенияСвойств(ЗаказПоставщику, Объект);

        Для Каждого ТекСтрокаПрихода Из Объект.Запасы Цикл
            ТекСтрокаЗаказПоставщику = ЗаказПоставщику.Запасы.Добавить();
            ЗаполнитьЗначенияСвойств(ТекСтрокаЗаказПоставщику, ТекСтрокаПрихода); // Копируем основные реквизиты

            // Получаем числовое значение ставки НДС из реквизита "СтавкаНДС"
            Перем ПроцентСтавкиНДС;
            Если ТипЗнч(ТекСтрокаПрихода.СтавкаНДС) = Тип("СправочникСсылка.СтавкиНДС") Тогда
                ПроцентСтавкиНДС = ТекСтрокаПрихода.СтавкаНДС.ПроцентНДС;
            Иначе
                // Если СтавкаНДС не ссылка на справочник, предполагаем, что это число или 0
                Если ТипЗнч(ТекСтрокаПрихода.СтавкаНДС) = Тип("Число") Тогда
                    ПроцентСтавкиНДС = ТекСтрокаПрихода.СтавкаНДС;
                Иначе
                    ПроцентСтавкиНДС = 0; // Значение по умолчанию
                КонецЕсли;
            КонецЕсли;

            // Расчет СуммыБезНДС и СуммыНДС для новой строки ЗаказаПоставщику
            Перем СуммаБезНДС;
            Перем СуммаНДС;

            Если ПроцентСтавкиНДС > 0 Тогда
                // Стр.Сумма - это сумма с НДС
                СуммаБезНДС = ТекСтрокаПрихода.Сумма / (1 + ПроцентСтавкиНДС / 100);
                СуммаНДС    = ТекСтрокаПрихода.Сумма - СуммаБезНДС;
            Иначе
                // Если НДС нет, то СуммаБезНДС равна исходной сумме, НДС = 0
                СуммаБезНДС = ТекСтрокаПрихода.Сумма;
                СуммаНДС    = 0;
            КонецЕсли;

            // Теперь заполняем реквизиты новой строки ЗаказПоставщику
            // Предполагаем, что в ЗаказПоставщику нам нужна цена без НДС.
            // Если реквизит "Сумма" в ЗаказПоставщику должен быть без НДС:
            ТекСтрокаЗаказПоставщику.Сумма = СуммаБезНДС;
            
            // Если есть отдельные реквизиты для СуммыНДС и СтавкиНДС в ЗаказеПоставщику:
            ТекСтрокаЗаказПоставщику.СуммаНДС = СуммаНДС;
            
            // Важно: СтавкуНДС в ЗаказПоставщику также нужно скопировать
            // Если в ЗаказеПоставщику СтавкаНДС хранится как ссылка на справочник
            ТекСтрокаЗаказПоставщику.СтавкаНДС = ТекСтрокаПрихода.СтавкаНДС;
            // Если в ЗаказеПоставщику СтавкаНДС должна быть числом
            // ТекСтрокаЗаказПоставщику.СтавкаНДС = ПроцентСтавкиНДС;
            
            // Если есть реквизит Цена в ЗаказеПоставщику, вычисляем ее
            Если ТекСтрокаПрихода.Количество <> 0 Тогда
                ТекСтрокаЗаказПоставщику.Цена = СуммаБезНДС / ТекСтрокаПрихода.Количество;
            Иначе
                ТекСтрокаЗаказПоставщику.Цена = 0;
            КонецЕсли;

        КонецЦикла;

        Попытка
            ЗаказПоставщику.УстановитьНовыйНомер();
            ЗаказПоставщику.Записать(РежимЗаписиДокумента.Запись);
            Возврат ЗаказПоставщику.Ссылка;
        Исключение
            Возврат Документы.ЗаказПоставщику.ПустаяСсылка();
        КонецПопытки;
    Иначе
        Возврат Неопределено;
    КонецЕсли;
КонецФункции

4. Важность отладчика в 1С

Для эффективного решения подобных проблем, а также для глубокого понимания логики работы вашего кода и данных, крайне важно использовать встроенный отладчик 1С. Отладчик — это ваш лучший друг в разработке. Рассмотрим, как мы можем использовать его для анализа текущей ситуации:

  1. Установка точек останова (Breakpoints): Установите точку останова на строке, где происходит обращение к Стр.СтавкаНДС. Это позволит приостановить выполнение кода непосредственно перед тем, как произойдет ошибка.
  2. Пошаговое выполнение кода: После остановки на точке останова, вы можете выполнять код пошагово (клавиши F10, F11), наблюдая за изменениями переменных.
  3. "Табло" и "Вычислить выражение": В режиме отладки откройте окно "Табло" (или "Вычислить выражение"). Здесь вы можете вводить любые выражения и мгновенно видеть их текущие значения и типы данных.
  4. Например, введите ТекСтрокаПрихода.СтавкаНДС и посмотрите, какой тип данных он возвращает (например, СправочникСсылка.СтавкиНДС). Затем, если это ссылка, попробуйте ТекСтрокаПрихода.СтавкаНДС.ПроцентНДС, чтобы увидеть числовое значение. Это поможет вам точно определить имена реквизитов и их тип, а также убедиться, что вы правильно извлекаете необходимое значение.

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

Заключение

Мы подробно разобрали, как решить проблему с ошибкой "Метод объекта не обнаружен (СтавкаНДС)" и "Преобразование значения к типу Число не может быть выполнено" в 1С. Ключевыми моментами являются:

  1. Понимание разницы между реквизитами и методами: Реквизиты — это данные (обращение Объект.Реквизит), методы — это действия (вызов Объект.Метод()).
  2. Корректное извлечение числового значения ставки НДС: Если реквизит СтавкаНДС является ссылкой на справочник или перечисление, необходимо обратиться к его соответствующему реквизиту (например, Стр.СтавкаНДС.ПроцентНДС) для получения числового значения процента.
  3. Применение правильных формул для расчета: Используйте формулы СуммаБезНДС = СуммаСНДС / (1 + ПроцентСтавкиНДС / 100) и СуммаНДС = СуммаСНДС - СуммаБезНДС.
  4. Использование отладчика: Этот инструмент незаменим для диагностики ошибок, проверки типов данных и значений переменных.
  5. Оптимизация кода: Объединение циклов для повышения производительности и читаемости.

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

← На главную