В процессе разработки печатных форм или заполнения макетов часто возникает задача: собрать данные из таблицы, расположенной на форме, и вывести их в одну строку через запятую. На первый взгляд задача кажется тривиальной, но начинающие разработчики часто сталкиваются с ошибками типизации и неоптимальным кодом. В этой статье мы подробно разберем, как правильно обращаться к данным формы, избегать ошибок преобразования типов и использовать современные возможности платформы 1С:Предприятие 8.3.
Рассмотрим ситуацию, с которой столкнулся автор темы. При попытке собрать строку в цикле 1С выдает ошибку. Выясним причину этого поведения. Проблема кроется в неявном приведении типов. В языке 1С, если в выражении сложения первым операндом выступает число, система пытается привести все последующие значения к числу.
Проанализируем ошибочный код:
Для каждого Стр Из Учёт Цикл
Номерок = Номерок + Стр.Пломба + ",";
КонецЦикла;
Если переменная Номерок не была инициализирована перед циклом или была инициализирована нулем (по умолчанию для некоторых типов), то при выполнении первой итерации система видит: 0 + "ЗначениеПломбы". Поскольку 0 — это число, 1С пытается превратить строку в число, что и вызывает критическую ошибку. Чтобы этого избежать, мы должны явно указать системе, что работаем со строками.
Самый простой способ исправить ситуацию — это инициализировать переменную пустой строкой. Рассмотрим, как это сделать правильно:
// Инициализируем переменную как пустую строку
Номерок = "";
Для каждого Стр Из Учёт Цикл
// Добавляем значение колонки, принудительно преобразуя его в строку
Номерок = Номерок + Строка(Стр.Пломба) + ", ";
КонецЦикла;
// Убираем последнюю лишнюю запятую и пробел
Если ЗначениеЗаполнено(Номерок) Тогда
Номерок = Лев(Номерок, СтрДлина(Номерок) - 2);
КонецЕсли;
В этом примере мы используем функцию Строка(). Это хорошая практика, так как в колонке таблицы может оказаться Null, число или ссылка, и прямое сложение может привести к ошибке. Также мы добавили блок удаления последнего разделителя, чтобы строка выглядела аккуратно.
Начиная с версии платформы 8.3.6, разработчикам доступен более элегантный и быстрый способ объединения строк — функция СтрСоединить. Проанализируем, почему этот метод лучше:
+ работает медленно, так как каждый раз создает новую строку в памяти. СтрСоединить работает с массивом и делает это значительно быстрее.Посмотрим на пример реализации этого метода для таблицы на форме:
// Создаем массив для хранения значений
МассивПломб = Новый Массив;
// Заполняем массив значениями из таблицы
Для каждого Стр Из Учёт Цикл
Если ЗначениеЗаполнено(Стр.Пломба) Тогда
МассивПломб.Добавить(Строка(Стр.Пломба));
КонецЕсли;
КонецЦикла;
// Объединяем массив в одну строку с разделителем
Номерок = СтрСоединить(МассивПломб, ", ");
Важно понимать разницу между объектами, с которыми мы работаем. Таблица на управляемой форме — это не ТаблицаЗначений, а объект типа ДанныеФормыКоллекция.
Рассмотрим нюансы использования метода РеквизитФормыВЗначение. Многие разработчики по привычке пишут:
ТаблицаОбъект = РеквизитФормыВЗначение("Учёт");
Это действие переводит данные из легкого экранного объекта в тяжелый объект сервера. Делать это нужно только в том случае, если вам требуются специфические методы таблицы значений, такие как Свернуть(), НайтиСтроки() (с использованием структуры) или ВыгрузитьКолонку(). Если вам нужно просто перебрать строки циклом Для каждого, используйте Учёт напрямую — это сэкономит ресурсы сервера и ускорит работу программы.
Теперь объединим всё вышесказанное в контексте задачи заполнения макета, которую решал автор. Разберем полный цикл действий программиста:
&НаСервере
Процедура ПечатьНаСервере(ТабДок)
Макет = ПолучитьМакет("МойМакет"); // Замените на имя вашего макета
ОбластьНомер = Макет.ПолучитьОбласть("Номер");
// Собираем данные из таблицы формы "Учёт"
МассивЗначений = Новый Массив;
Для каждого СтрокаТаблицы Из Учёт Цикл
Если ЗначениеЗаполнено(СтрокаТаблицы.Пломба) Тогда
МассивЗначений.Добавить(Строка(СтрокаТаблицы.Пломба));
КонецЕсли;
КонецЦикла;
// Заполняем параметр области
ОбластьНомер.Параметры.Номер = СтрСоединить(МассивЗначений, ", ");
// Выводим область в табличный документ
ТабДок.Вывести(ОбластьНомер);
КонецПроцедуры
Обратите внимание: если ваш код находится не в модуле формы, а в общем модуле или модуле объекта, вам придется передать таблицу формы как параметр или предварительно преобразовать её. Но в рамках модуля формы обращение к Учёт (имени реквизита) происходит напрямую.
Выясним, на что еще стоит обратить внимание при работе с такими задачами:
ЗначениеЗаполнено() перед добавлением в строку, чтобы не получить строку вида "Пломба1, , Пломба3".СокрЛП() для очистки лишних пробелов: МассивЗначений.Добавить(СокрЛП(Строка(СтрокаТаблицы.Пломба)));.Мы проанализировали основные ошибки при работе с коллекциями данных формы и выяснили, что наиболее надежным и современным способом сборки строк является использование массива и функции СтрСоединить с предварительной инициализацией переменных строковыми типами.