Перенос строки в коде 1С 8.3: от Символы.ПС до макетов и запросов
Содержание
Перенос строки в 1С 8.3 даёт системный объект Символы: выражение Символы.ПС возвращает перевод строки (символ с кодом 10), а Символы.ВК — возврат каретки (код 13). Чтобы разбить текст на две строки, достаточно склеить части через этот символ: "Первая строка" + Символы.ПС + "Вторая строка". Тот же результат даёт функция Символ(10).
Частая ошибка новичка — искать в языке «кнопку переноса» или вставлять в строковую константу живой перенос с клавиатуры. В коде так не делают: перенос строки — это обычный символ, который подставляют в выражение. Разберём, как это работает в сообщениях пользователю, в макетах печатных форм, в тексте запроса и при чтении данных из файлов — и почему один и тот же приём по-разному выглядит в толстом и веб-клиенте.
Символ перевода строки: Символы.ПС, Символы.ВК и Символ()
В 1С 8.3 за непечатаемые символы отвечает глобальный объект Символы. Это не перечисление из конфигурации, а встроенное свойство платформы, доступное в любом модуле. Его члены:
- 📄
Символы.ПС— перевод строки, LF, код 10. Основной символ переноса. - ↵
Символы.ВК— возврат каретки, CR, код 13. - ➡️
Символы.Таб— горизонтальная табуляция, код 9. - ⬇️
Символы.ПД— перевод формата (form feed), код 12. - ␣
Символы.НПП— неразрывный пробел, код 160.
Для простого переноса внутри приложения хватает одного Символы.ПС. Пара Символы.ВК + Символы.ПС даёт «виндовый» перенос CRLF — он нужен, когда текст уйдёт во внешний файл или систему, которая ждёт именно такую последовательность.
| Член объекта | Код | Назначение |
|---|---|---|
Символы.ПС | 10 | перевод строки, основной перенос |
Символы.ВК | 13 | возврат каретки, вместе с ПС даёт CRLF |
Символы.Таб | 9 | табуляция, разделитель колонок |
Символы.ПД | 12 | перевод формата (разрыв страницы) |
Символы.НПП | 160 | неразрывный пробел |
Таблица пригодится, когда нужно не вставить, а распознать символ: сравните код через КодСимвола(Строка, Позиция) с нужным числом и поймёте, какой именно перенос пришёл в данных.
// Три равнозначных способа получить перенос
Текст1 = "Строка один" + Символы.ПС + "Строка два";
Текст2 = "Строка один" + Символ(10) + "Строка два";
Текст3 = СтрШаблон("Строка один%1Строка два", Символы.ПС);
Функция Символ(КодСимвола) возвращает символ по его числовому коду Unicode, а КодСимвола(Строка, Позиция) делает обратное — узнаёт код символа. Это запасной путь, когда под рукой нет готового члена Символы: Символ(9) — табуляция, Символ(13) — возврат каретки.
В длинных текстах удобнее СтрШаблон: подставляете %1 вместо символа переноса, и строка остаётся читаемой. Платформа сама склеит части.
Многострочные сообщения пользователю
Самый частый сценарий — вывести пользователю несколько строк одним сообщением. Если тема про перенос строки пришла из задачи «показать текст в несколько абзацев», то речь почти всегда про это.
Метод Сообщить просто склеивает текст, переносы внутри него отрабатывают:
Текст = "Проверка завершена." + Символы.ПС
+ "Найдено ошибок: " + Ошибок + Символы.ПС
+ "Исправлено автоматически: " + Исправлено;
Сообщить(Текст);
Обратите внимание на типизацию: число нельзя «сложить» со строкой через + молча в любой ситуации — платформа приведёт его к строке, но для управляемого вида лучше Формат(Ошибок, "ЧГ=0"), иначе большое число выведется с разделителями групп по умолчанию.
Для привязки сообщения к конкретному полю формы используют объект СообщениеПользователю. В нём переносы в тексте тоже сохраняются:
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не заполнен контрагент." + Символы.ПС + "Укажите его в шапке документа.";
Сообщение.Поле = "Объект.Контрагент";
Сообщение.Сообщить();
Когда строк заранее не известно — например, копите протокол загрузки по ходу цикла — наращивайте текст тем же символом и выводите в конце одним сообщением:
Протокол = "";
Для Каждого Строка Из ЗагружаемыеДанные Цикл
Результат = ЗагрузитьСтроку(Строка);
Протокол = Протокол + Строка.Номер + ": " + Результат + Символы.ПС;
КонецЦикла;
Сообщить(Протокол);
Так пользователь получит один аккуратный список, а не десятки отдельных всплывающих строк.
В окне служебных сообщений очень длинная строка без переносов не переносится по словам автоматически — пользователь увидит горизонтальную прокрутку. Разбивайте сообщение на логические строки сами.
Переносы в макетах и печатных формах
В табличном документе (макете печатной формы) перенос строки работает на двух уровнях — в самом тексте ячейки и в её свойствах.
Фиксированный перенос в тексте ячейки. Когда нужно жёстко разбить надпись внутри ячейки макета, в конфигураторе встаёте в режим редактирования текста ячейки и нажимаете Alt+Enter. Платформа вставит перенос, который сохранится при печати.
Перенос из данных. Если ячейка — параметр, и значение приходит из кода с Символы.ПС, то видимые переносы появятся только при включённом переносе по словам. Откройте свойства ячейки (Alt+Enter на ячейке или палитра свойств) и задайте свойство Размещение = Переносить. Тогда длинный текст и символы Символы.ПС внутри него разложатся на несколько строк по ширине ячейки.
ОбластьМакета.Параметры.Адрес = Город + Символы.ПС + Улица + Символы.ПС + Индекс;
Значения свойства Размещение:
| Значение | Что делает с текстом |
|---|---|
Авто | как у родителя/по умолчанию |
Переносить | переносит по словам, показывает Символы.ПС |
Обрезать | обрезает по границе ячейки |
Забивать | заполняет область повторением |
Если макет строится программно через построитель или компоновку данных, перенос в текст поля удобно класть тем же Символы.ПС при формировании значения параметра — главное не забыть Размещение = Переносить у ячейки-получателя.
Перенос строк в тексте запроса
Здесь кроется распространённое заблуждение. Символ | (вертикальная черта) в тексте запроса — это не перенос данных в результате, а продолжение строковой константы в коде. Он позволяет писать запрос в несколько строк модуля, оставаясь читаемым:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
Черта в начале каждой строки говорит компилятору: «это всё ещё одна строковая константа». В сам текст запроса и в результат эти переносы не попадают.
Вставить перенос строки прямо в выбираемое поле средствами языка запросов нельзя. В запросе нет оператора конкатенации строк через +, поэтому «склеить поле с Символы.ПС» внутри ВЫБРАТЬ не получится. Перенос добавляют уже в коде, после выборки:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СтрокаДляПечати = Выборка.Наименование + Символы.ПС + "Артикул: " + Выборка.Артикул;
// дальше работаем со СтрокаДляПечати
КонецЦикла;
Если же строковое поле в базе уже содержит переносы (например, многострочный реквизит «Комментарий»), запрос вернёт их как есть — ломать или чистить их не нужно.
Разбор многострочного текста из файлов и обменов
Обратная задача — не собрать, а разобрать текст по строкам. Данные из CSV, txt-выгрузки банка или ответа внешнего сервиса приходят одной строкой с разделителями Символы.ПС или Символы.ВК + Символы.ПС.
Самый удобный инструмент — СтрРазделить:
Строки = СтрРазделить(ПолныйТекст, Символы.ПС, Ложь);
Для Каждого Строка Из Строки Цикл
Строка = СокрЛП(Строка); // убираем хвостовой Символы.ВК и пробелы
Если ПустаяСтрока(Строка) Тогда
Продолжить;
КонецЦикла;
ОбработатьСтроку(Строка);
КонецЦикла;
Третий параметр Ложь отбрасывает пустые элементы. Есть и парные функции для построчной работы без разбиения в массив:
СтрЧислоСтрок(Текст)— сколько строк в тексте (считает поСимволы.ПС).СтрПолучитьСтроку(Текст, Номер)— вернуть строку с заданным номером.СтрСоединить(Массив, Символы.ПС)— собрать массив обратно в многострочный текст.
Файлы из Windows приходят с переносом CRLF. Если разделять только по Символы.ПС, в конце каждой строки останется невидимый Символы.ВК (код 13). Он портит сравнение строк и поиск по справочнику. Снимайте его через СокрЛП или СтрЗаменить(Текст, Символы.ВК, "").
Для больших файлов вместо чтения целиком в память берут объект ЧтениеТекста и метод ПрочитатьСтроку() — он сам распознаёт перенос и отдаёт строки по одной.
Обратная операция — выгрузка многострочного текста в файл. Здесь перенос выбираете вы, и для совместимости с Windows-программами берут CRLF:
Запись = Новый ЗаписьТекста("C:\Обмен\выгрузка.txt", КодировкаТекста.UTF8);
Для Каждого Элемент Из Данные Цикл
Запись.ЗаписатьСтроку(Элемент.Код + Символы.Таб + Элемент.Наименование);
КонецЦикла;
Запись.Закрыть();
Метод ЗаписатьСтроку сам добавит перевод строки после каждой записи. Если собираете текст вручную через +, перенос между записями ставьте сами и не забудьте про кодировку: несовпадение кодировки, а не переносов, — вторая по частоте причина «кракозябр» в выгрузке.
Разделитель колонок и разделитель строк — разные вещи. Между полями одной строки ставьте Символы.Таб или ;, а между строками — Символы.ПС. Их путаница ломает разбор файла у получателя.
Отображение переносов в тонком и веб-клиенте
Один и тот же Символы.ПС рисуется по-разному в зависимости от того, куда он попал.
Поле ввода на форме. Чтобы пользователь мог вводить и видеть многострочный текст, у поля задают свойство МногострочныйРежим = Истина. Без него перенос в значении есть, но поле покажет только первую строку.
Надпись (декорация). Элемент-надпись на управляемой форме отображает Символы.ПС как перенос и в тонком, и в веб-клиенте — дополнительной настройки не требуется.
Поле HTML-документа. Если текст выводится через поле типа «Поле HTML документа», переносом служит тег <br>, а не Символы.ПС. Перед выводом замените одно на другое:
ТекстHTML = СтрЗаменить(ИсходныйТекст, Символы.ПС, "<br>");
Веб-клиент и буфер обмена. При копировании многострочного значения из веб-клиента браузер может нормализовать переносы под свою ОС. На бизнес-логику это не влияет: внутри базы хранится ровно то, что вы записали. Если текст уходит во внешнюю систему по жёсткому формату, фиксируйте перенос явно (Символы.ВК + Символы.ПС), не полагаясь на клиента.
Форматированный документ и подсказки. В элементе типа «Поле форматированного документа» перенос ставится самим редактором, а программно — методами объекта ФорматированныйДокумент, где абзацы разделяются своими элементами, а не символом Символы.ПС в тексте. А вот всплывающая подсказка (РасширеннаяПодсказка) и заголовок колонки Символы.ПС понимают и переносят текст в обоих клиентах.
Важный вывод для кроссклиентного кода: логику формирования текста с Символы.ПС пишите один раз на сервере, а особенности отображения закрывайте настройкой конкретного элемента формы. Тогда один и тот же результат корректно покажется и в тонком, и в веб-клиенте без веток «если веб-клиент».
Частые ошибки при работе с переносами
Размещение = Переносить.Символы.ВК (код 13) от CRLF. Очистите строку через СокрЛП или СтрЗаменить(Строка, Символы.ВК, "").Запрос.Выполнить().Символы.ПС. Замените его на тег <br> перед выводом.МногострочныйРежим = Истина.Ещё одна тонкая ошибка — путать Символы.ПС и Символы.ВК. По отдельности для вывода внутри 1С работает любой, но при выгрузке в строго форматированный файл (платёжки, обмены) порядок и состав важны: стандарт Windows — именно Символы.ВК + Символы.ПС, в этом порядке.
Частые вопросы
Чем отличается Символы.ПС от Символы.ВК?
Символы.ПС — перевод строки (LF, код 10), Символы.ВК — возврат каретки (CR, код 13). Для вывода внутри 1С достаточно Символы.ПС. Для файлов в формате Windows нужна пара Символы.ВК + Символы.ПС.Можно ли вставить перенос строки прямо в строковую константу?
"..." + Символы.ПС + "...". Живой перенос с клавиатуры внутри кавычек не делают — для многострочных текстов запроса используют продолжение строки через |.Как посчитать количество строк в многострочном тексте?
СтрЧислоСтрок(Текст) — она считает строки по символу Символы.ПС. Отдельную строку вернёт СтрПолучитьСтроку(Текст, Номер).Почему перенос есть в данных, но не виден на печати?
Размещение = Переносить.Как убрать переносы из строки?
СтрЗаменить(СтрЗаменить(Текст, Символы.ВК, ""), Символы.ПС, " "). Сначала убирают Символы.ВК, затем Символы.ПС.