Почему не сохраняются и не отображаются цены в документе «Установка цен номенклатуры» при программном расчете?

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

При разработке обработок или доработке типовых конфигураций 1С на обычных формах (таких как «Управление торговлей 10.3» или «УПП 1.3») программисты часто сталкиваются со странным поведением документа Установка цен номенклатуры. Суть проблемы заключается в следующем: вы пишете код для пересчета цен, запускаете его, отладчик показывает, что в табличной части объекта данные изменились, но на самой форме документа колонки с ценами остаются пустыми или старыми. Разберем подробно, почему это происходит и как правильно реализовать заполнение цен.

Анализ архитектуры документа «Установка цен номенклатуры»

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

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


Процедура КоманднаяПанельТоварыУстЦену(Кнопка)
    ВидЦены = Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Оптовая");
    Для каждого стр из товары цикл
        стр.ТипЦен = ВидЦены;
        стр.Цена = стр.Номенклатура.БазаРозница; // Допустим, цена берется из реквизита номенклатуры
    КонецЦикла;
КонецПроцедуры

В этом примере мы напрямую меняем строки в табличной части Товары. Однако форма «не знает», что данные внутри объекта изменились, так как она отображает свою внутреннюю таблицу. Даже вызов метода ЭтаФорма.Обновить() часто не помогает, так как связь между физической ТЧ и визуальной таблицей сложнее, чем кажется.

Роль реквизита «ИндексСтрокиТаблицыЦен»

Выясним причину существования реквизита ИндексСтрокиТаблицыЦен. В документе «Установка цен номенклатуры» одна и та же номенклатура может встречаться в табличной части Товары несколько раз (по одной строке на каждый тип цены). Чтобы на форме это выглядело как одна строка с разными колонками-ценами, система использует механизм индексации.

ИндексСтрокиТаблицыЦен — это связующее звено. Если вы программно добавляете строки в Товары, но не проставляете этот индекс или проставляете его неверно, механизм синхронизации данных формы «ломается». Рассмотрим правильную логику: для каждой уникальной номенклатуры в документе должен быть один и тот же индекс, независимо от типа цены. Именно по этому индексу форма группирует данные в одну строку для отображения пользователю.

Решение 1: Использование типовых механизмов синхронизации

Самый правильный путь — не пытаться изобрести велосипед, а использовать экспортные процедуры, заложенные разработчиками конфигурации. В модуле формы документа «Установка цен номенклатуры» обычно есть процедуры, отвечающие за обновление визуальных данных на основе данных объекта.

Посмотрим на пример правильного вызова обновления формы:


// В обработчике нажатия кнопки на форме
Процедура КоманднаяПанельТоварыУстЦену(Кнопка)
    
    // 1. Сначала вносим изменения в объект
    Для каждого СтрокаТЧ Из ЭтотОбъект.Товары Цикл
        // Ваша логика расчета цены
        СтрокаТЧ.Цена = СтрокаТЧ.Номенклатура.БазаРозница * 1.1; // Пример наценки
    КонецЦикла;
    
    // 2. Вызываем обновление визуальной таблицы (имена процедур могут отличаться в УТ и УПП)
    // Обычно это процедура ЗаполнитьТаблицуЦен() или ОбновитьДанныеТаблицыЦен()
    ЗаполнитьТаблицуЦен(); 
    
КонецПроцедуры

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

Решение 2: Прямая работа с визуальной таблицей

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

Выясним, как это сделать. На форме документа табличное поле обычно связано с переменной ТаблицаЦен. Каждая колонка в этой таблице соответствует определенному типу цены и называется по шаблону (например, Цена_<УникальныйИдентификаторТипаЦены>).

Рассмотрим пример обращения к текущим данным формы:


ТекущаяСтрока = ЭлементыФормы.ТаблицаЦен.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
    // Прямое изменение значения в колонке формы
    // Имя колонки можно узнать через отладчик или метаданные
    ТекущаяСтрока.Цена_Оптовая = 1500; 
    
    // После этого нужно вызвать механизм, который перенесет 
    // данные из визуальной таблицы обратно в ТЧ "Товары"
    // Обычно это происходит в событии ПриИзменении ячейки
КонецЕсли;

Однако помните, что ручное манипулирование именами колонок типа Цена_UUID — это плохая практика, так как идентификаторы могут меняться. Лучше всегда использовать первый способ (изменение ТЧ объекта + вызов метода обновления формы).

Важные замечания по коду

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

ВидЦены = Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию(" Оптовая");

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

Рекомендуем использовать предопределенные элементы (если они есть) или выносить выбор типа цен в настройки/параметры обработки.

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

  1. Проверьте контекст: Вы работаете с формой или с объектом? Если код в модуле формы, используйте ЭтотОбъект.Товары.
  2. Проверьте наличие индекса: Убедитесь, что реквизит ИндексСтрокиТаблицыЦен в строках ТЧ заполнен корректно (он должен соответствовать номеру строки в визуальной таблице на форме).
  3. Синхронизация: После изменения цен в цикле по Товары, обязательно найдите и вызовите процедуру модуля формы, которая отвечает за перестроение таблицы (например, ЗаполнитьТаблицуЦен()).
  4. Обновление элементов: В некоторых случаях после программного изменения данных требуется вызвать ЭлементыФормы.ИмяВашейТаблицы.СоздатьКолонки(), чтобы заставить платформу перерисовать интерфейс.

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

← На главную