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

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

При разработке печатных форм часто возникает необходимость вывести данные, хранящиеся в одном строковом реквизите, в несколько отдельных ячеек макета табличного документа. Типичный пример — когда в комментарии документа через специальный символ-разделитель (например, решетку #) записано несколько разнородных текстовых блоков, которые должны попасть в "Поле 1", "Поле 2" и "Поле 3" печатной формы.

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

Способ 1. Использование встроенной функции СтрРазделить()

Начиная с версии платформы 8.3.6, в 1С появилась встроенная функция СтрРазделить(). Она реализована на уровне платформы (на C++), благодаря чему работает значительно быстрее любых функций-аналогов из общих модулей конфигурации. Рассмотрим, как применить ее для нашей задачи.

Функция принимает на вход три параметра: исходную строку, строку-разделитель и булево значение, указывающее, нужно ли удалять пустые подстроки из результата. Разберем пример кода:


СтрокаКомментарий = "Текст Один#Текст Два#Текст Три";
МассивПодстрок = СтрРазделить(СтрокаКомментарий, "#", Истина);

// Теперь элементы массива содержат очищенные от лишних пробелов части строки
// МассивПодстрок[0] = "Текст Один"
// МассивПодстрок[1] = "Текст Два"
// МассивПодстрок[2] = "Текст Три"

Использование третьего параметра со значением Истина позволяет автоматически избавиться от пустых элементов, если пользователь случайно ввел несколько разделителей подряд (например, "Текст Один##Текст Два").

Способ 2. Разложение строки в старых версиях конфигураций (УПП, УСХП)

Если вы работаете в конфигурации со строгим режимом совместимости со старыми версиями платформы (например, в Управлении производственным предприятием 1.3 или Управлении сельскохозяйственным предприятием 1.3), функция СтрРазделить() может быть недоступна. В этом случае на помощь приходят функции библиотек стандартных подсистем (БСП) или встроенные общие модули.

Проанализируем пример использования функции из общего модуля БСП:


СтрокаКомментарий = ВыборкаДетальныеЗаписи.Комментарий;
МассивПодстрок = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(СтрокаКомментарий, "#");

Этот метод вернет стандартный Массив, элементы которого мы сможем последовательно распределить по параметрам нашего макета.

Важное примечание: Избегайте ручного разбора строк через функции Найти(), Лев(), Сред() и Прав(). Такой код получается громоздким, сложным в отладке и легко ломается, если количество разделителей в строке не совпадает с ожидаемым.

Способ 3. Безопасное заполнение параметров макета печатной формы

Представим ситуацию: в макете печатной формы предусмотрено три параметра: Поле1, Поле2 и Поле3. Если написать код прямого обращения к элементам массива:


Макет.Параметры.Поле1 = МассивПодстрок[0];
Макет.Параметры.Поле2 = МассивПодстрок[1];
Макет.Параметры.Поле3 = МассивПодстрок[2];

То программа неминуемо аварийно завершит работу с ошибкой "Индекс находится за границами соответствия", если пользователь заполнит комментарий без разделителей (например, напишет просто "Текст Один"). В таком случае в массиве будет всего один элемент с индексом 0, а обращение к индексам 1 и 2 вызовет исключение.

Для решения этой проблемы рассмотрим два подхода.

Вариант А. Простой цикл по количеству элементов (с ограничением):


КоличествоЭлементов = Мин(МассивПодстрок.Количество(), 3); // Ограничиваемся максимум 3 полями
Для Индекс = 1 По КоличествоЭлементов Цикл
    Макет.Параметры["Поле" + Индекс] = МассивПодстрок[Индекс - 1];
КонецЦикла;

Вариант Б. Использование структуры и функции ЗаполнитьЗначенияСвойств() (Рекомендуемый):

Этот способ является наиболее изящным и безопасным в стандартах разработки 1С. Функция ЗаполнитьЗначенияСвойств() копирует значения из свойств источника в свойства приемника с совпадающими именами. Если в источнике будет свойство, которого нет в приемнике (например, Поле4), платформа просто проигнорирует его, не вызывая ошибку.


// Создаем структуру для хранения параметров
СтруктураПараметров = Новый Структура;

Для Индекс = 1 По МассивПодстрок.Количество() Цикл
    СтруктураПараметров.Вставить("Поле" + Индекс, МассивПодстрок[Индекс - 1]);
КонецЦикла;

// Заполняем параметры макета из структуры без риска получить ошибку
ЗаполнитьЗначенияСвойств(Макет.Параметры, СтруктураПараметров);

Способ 4. Исправление ошибки «Недостаточно фактических параметров» во внешней печатной форме

При отладке внешней печатной формы часто возникает ситуация, когда через меню "Файл - Открыть" обработка печатает документ без проблем, но при подключении ее в справочник "Внешние обработки" и попытке вызова из документа программа выдает ошибку: «Недостаточно фактических параметров».

Выясним причину этой проблемы. Дело в различиях стандартов вызова механизмов печати в обычных и управляемых формах:

  1. В старых конфигурациях на обычных формах (УПП 1.3, УСХП 1.3, КА 1.1) внешняя печатная форма должна содержать реквизит СсылкаНаОбъект (тип — ссылка на документ). Функция Печать() в модуле объекта такой обработки должна быть объявлена без параметров:
    
    Функция Печать() Экспорт
        // Код формирования печатной формы
        // В запросах и логике используем реквизит "СсылкаНаОбъект" вместо переданного параметра
    КонецФункции
    
  2. Если в модуле вашей обработки функция объявлена как Функция Печать(Ссылка) Экспорт, то при вызове из типового механизма обычного приложения система не передает туда параметр, что и приводит к ошибке "Недостаточно фактических параметров". Для исправления достаточно убрать параметр из объявления функции и использовать реквизит обработки СсылкаНаОбъект.

Способ 5. Пересчет количества товаров в базовые единицы (Килограммы)

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

В конфигурациях на платформе 1С (таких как УПП/УСХП) для каждой номенклатуры задается подчиненный справочник ЕдиницыИзмерения. У этого справочника есть реквизит Вес, в котором хранится вес одной единицы измерения в килограммах (например, для тонны вес будет равен 1000, для коробки — 15, для штуки — вес конкретного изделия).

Для автоматического пересчета в килограммы прямо в запросе мы можем перемножить количество на вес единицы измерения. Рассмотрим пример запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
    |    СУММА(ПоступлениеТоваровУслугТовары.Количество * ЕСТЬNULL(ПоступлениеТоваровУслугТовары.ЕдиницаИзмерения.Вес, 1)) КАК КоличествоВКг
    |ИЗ
    |    Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
    |    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары
    |        ПО ПоступлениеТоваровУслуг.Ссылка = ПоступлениеТоваровУслугТовары.Ссылка
    |ГДЕ
    |    ПоступлениеТоваровУслуг.Ссылка = &Ссылка
    |ГРУППИРОВАТЬ ПО
    |    ПоступлениеТоваровУслуг.Ссылка";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
Результат = Запрос.Выполнить();

В результате выполнения этого запроса мы получим точную сумму веса всех товаров документа в килограммах, независимо от того, какие единицы измерения выбрал пользователь в табличной части документа ПоступлениеТоваровУслуг. Данное значение мы можем напрямую передать в параметр макета: Макет.Параметры.Количество = Выборка.КоличествоВКг;.

← На главную