При разработке внешних печатных форм в среде 1С:Предприятие 8.3 начинающие разработчики часто сталкиваются с загадочной ситуацией: в печатной форме для одних строк документа единицы измерения (например, «т» или «г») выводятся корректно, а для других (чаще всего «кг») поле остается пустым. На первый взгляд это кажется парадоксом, ведь код обработки одинаков для всех строк. В данной статье мы подробно разберем, почему возникает эта ошибка, как работает механизм хранения единиц измерения в типовых конфигурациях и как правильно составить запрос для вывода данных.
Для начала проанализируем ситуацию с точки зрения архитектуры данных 1С. В современных конфигурациях (таких как УТ 11, ERP, КА 2 или БП 3.0) реализована оптимизация хранения реквизитов в табличных частях. Рассмотрим механизм работы поля ЕдиницаИзмерения (или Упаковка) в документах. Если товар отгружается в своей основной единице хранения, которая указана в карточке номенклатуры как базовая, система зачастую оставляет поле ЕдиницаИзмерения в табличной части документа пустым (значение ПустаяСсылка).
Почему «т» и «г» выводятся, а «кг» — нет? Как правило, «т» (тонны) или «г» (граммы) являются дополнительными упаковками или единицами измерения. Когда пользователь выбирает их в документе, ссылка на них явно записывается в строку таблицы. А вот «кг» (килограммы) часто являются основной единицей хранения. Система «подразумевает», что если в строке ничего не выбрано, значит, используется значение по умолчанию из карточки номенклатуры. Именно поэтому при прямой выборке данных из табличной части мы получаем пустое поле вместо ожидаемого «кг».
Если вы только начинаете и используете простой перебор строк табличной части, можно применить проверку на заполнение. Рассмотрим, как программно проверить наличие значения и подставить данные из справочника Номенклатура, если в строке документа поле пустое.
Для Каждого ТекущаяСтрока Из СсылкаНаОбъект.Товары Цикл
// Проверяем, заполнена ли единица измерения в строке
Если Не ЗначениеЗаполнено(ТекущаяСтрока.ЕдиницаИзмерения) Тогда
// Если пусто — берем основную единицу из карточки номенклатуры
ЕдиницаДляПечати = ТекущаяСтрока.Номенклатура.ЕдиницаИзмерения;
Иначе
// Если заполнено — используем значение из строки
ЕдиницаДляПечати = ТекущаяСтрока.ЕдиницаИзмерения;
КонецЕсли;
// Передаем значение в параметры области макета
ОбластьСтрока.Параметры.ЕдиницаИзмерения = ЕдиницаДляПечати;
ТабличныйДокумент.Вывести(ОбластьСтрока);
КонецЦикла;
Однако стоит помнить, что такой подход (обращение через точку к реквизитам в цикле) крайне неэффективен с точки зрения производительности, так как порождает множество мелких запросов к базе данных. Правильным решением будет получение всех данных одним запросом.
Разберем, как реализовать ту же логику на уровне языка запросов 1С. Мы будем использовать конструкцию ВЫБОР, которая позволяет прямо в теле запроса определить: откуда брать единицу измерения. Проанализируем пример запроса, который собирает данные для печатной формы:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.НомерСтроки КАК НомерСтроки,
| Товары.Номенклатура КАК Номенклатура,
| Товары.Количество КАК Количество,
| ВЫБОР
| КОГДА Товары.ЕдиницаИзмерения = ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка)
| ТОГДА Товары.Номенклатура.ЕдиницаИзмерения
| ИНАЧЕ Товары.ЕдиницаИзмерения
| КОНЕЦ КАК ЕдиницаИзмерения,
| Товары.Цена КАК Цена,
| Товары.Сумма КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, Выборка);
ТабличныйДокумент.Вывести(ОбластьСтрока);
КонецЦикла;
В данном примере мы используем функцию ЗНАЧЕНИЕ(Справочник.ИмяСправочника.ПустаяСсылка) для проверки поля. Если условие выполняется, запрос автоматически «подтягивает» единицу измерения из связанного справочника Номенклатура.
Еще один важный момент, на который стоит обратить внимание — это то, что именно выводится в печатную форму. Ссылка на объект (тип СправочникСсылка) при выводе в табличный документ автоматически преобразуется в строку, используя Наименование. Но иногда для корректного отображения (например, вывода кода по ОКЕИ или полного наименования) лучше явно указать поле в запросе.
Рассмотрим варианты получения строкового значения:
ЕдиницаИзмерения.Представление позволяет получить текст, настроенный в конфигурации по умолчанию.Рекомендуется в параметрах макета использовать именно строковые типы данных, чтобы избежать проблем с форматированием.
Проанализируем ситуацию: как понять, что именно возвращает запрос, не загружая каждый раз файл во внешние обработки? Для эффективной работы воспользуемся следующей методикой:
&Ссылка на конкретный документ, где не выводится «кг». Если в колонке ЕдиницаИзмерения вы увидите пустую ячейку — значит, проблема в логике выбора (нужно проверить, из того ли реквизита номенклатуры вы берете данные).Выборка.Важно: Всегда проверяйте, какой именно реквизит в вашей конфигурации отвечает за хранение единицы. В некоторых случаях это может быть ЕдиницаХранения, в других — ЕдиницаДляОтчетов или ссылка на классификатор ОКЕИ. Выясним это, заглянув в дерево метаданных справочника Номенклатура.
Подводя итог, можно сказать, что решение проблемы «невидимых параметров» всегда кроется в детальном анализе данных в базе. Использование запросов с проверкой на пустые значения — это стандарт индустрии 1С, который обеспечит стабильную работу ваших печатных форм вне зависимости от того, какая единица измерения выбрана пользователем.