При формировании печатных форм (особенно сложных многостраничных документов, таких как типовые договоры для клиентов) в системе 1С:Предприятие 7.7 разработчики часто используют внешнюю компоненту Йоксель. Она позволяет создавать качественные табличные документы, настраивать автовысоту строк и перенос текста. Однако при сохранении полученного макета в формат MS Excel пользователи регулярно сталкиваются с неприятным эффектом: в самом проигрывателе Йокселя или в 1С макет выглядит идеально, но после открытия файла в Excel текст в ячейках оказывается "подрезанным" снизу. Строки буквально теряют последние несколько символов или целые предложения из-за нехватки высоты ячейки.
В этой статье мы подробно разберем, почему возникает данная техническая проблема, проанализируем внутренние механизмы рендеринга Excel и Йокселя, а также рассмотрим несколько проверенных практических способов её решения — от простых "костылей" до фундаментальных архитектурных изменений.
Прежде чем переходить к устранению бага, выясним причину его появления. Здесь играют роль сразу три технических фактора:
AutoFit) принципиально не работает для объединенных ячеек. Йоксель при экспорте пытается жестко зафиксировать высоту строки в пунктах, рассчитанную по правилам 1С, а Excel не может автоматически скорректировать ее под свои стандарты отображения.Ниже мы подробно разберем методы решения этой проблемы, начиная с самых простых программных доработок макета 1С и заканчивая альтернативными вариантами выгрузки документов.
---
Если структура вашего договора достаточно проста, мы можем принудительно задавать высоту строки программными методами в модуле формирования печатной формы 1С 7.7. Для этого перед выводом секции мы анализируем длину выводимого текста и устанавливаем высоту с заведомым запасом.
Рассмотрим пример реализации такого алгоритма:
// Функция устанавливает высоту строки в зависимости от объема текста
Процедура КорректироватьВысотуСтроки(Таб, НомерСтроки, ТекстЯчейки)
ДлинаТекста = СтрДлина(СокрЛП(ТекстЯчейки));
// Эмпирически подбираем высоту строки для шрифта Arial 10pt
// При ширине колонки примерно в 80-100 символов
Если ДлинаТекста < 100 Тогда
Таб.Область(НомерСтроки).ВысотаСтроки(18);
ИначеЕсли ДлинаТекста < 200 Тогда
Таб.Область(НомерСтроки).ВысотаСтроки(32);
ИначеЕсли ДлинаТекста < 300 Тогда
Таб.Область(НомерСтроки).ВысотаСтроки(46);
ИначеЕсли ДлинаТекста < 500 Тогда
Таб.Область(НомерСтроки).ВысотаСтроки(70);
Иначе
// Для совсем длинных абзацев рассчитываем высоту пропорционально
КоличествоСтрок = Цел(ДлинаТекста / 90) + 1;
Таб.Область(НомерСтроки).ВысотаСтроки(КоличествоСтрок * 14 + 10);
КонецЕсли;
КонецПроцедуры
Этот метод хорош тем, что он работает "малой кровью" непосредственно внутри кода 1С и не требует внешних манипуляций с установленным ПО на стороне пользователя.
---
Как мы уже выяснили, главной преградой для корректной работы автовысоты в Excel являются объединенные ячейки. Мы можем полностью обойти это ограничение, перенастроив свойства ячеек в макете 1С:
При таком подходе физически текст будет находиться только в самой первой (левой) ячейке строки, а визуально — распределяться по всей ширине. При экспорте через Йоксель Excel распознает эту ячейку как обычную (не объединенную) и сможет без труда применить к ней штатный механизм автовысоты AutoFit без обрезания границ.
---
Быстрый практический прием, позволяющий визуально отодвинуть нижнюю границу текста от рамки ячейки — добавление пустых строк в конец выводимого текста. В 1С v7.7 для этого используется константа РазделительСтрок.
Проанализируем пример модификации выводимого текста:
// Принудительно добавляем пустую строку в самый конец текстового блока
ТекстДоговора = СокрЛП(Выборка.Текст) + РазделительСтрок + " ";
Таб.Область(ТекущаяСтрока, 1).Текст = ТекстДоговора;
Добавление пробела после разделителя строк заставляет Йоксель и Excel зарезервировать высоту под еще одну дополнительную строку текста. Даже если Excel "сожмет" межстрочные интервалы, пострадает только пустая невидимая строка в самом низу ячейки, а значащая часть текста останется полностью видимой и доступной для распечатки.
---
Если документ обязательно должен быть сохранен именно в формате XLS/XLSX, и при этом в нем присутствуют объединенные ячейки, мы можем применить программное управление Excel через COM-объект. Сразу после того, как Йоксель сохранил файл на диск, мы открываем его в фоновом режиме через OLE и принудительно пересчитываем высоты строк по специальному алгоритму.
Разберем готовый скрипт интеграции:
// Процедура корректировки высоты строк в сохраненном Excel-файле
Процедура СкорректироватьФайлExcel(ПутьКФайлу)
Попытка
Excel = СоздатьОбъект("Excel.Application");
Excel.DisplayAlerts = 0; // Отключаем предупреждения
РабочаяКнига = Excel.Workbooks.Open(ПутьКФайлу);
Лист = РабочаяКнига.ActiveSheet;
// Перебираем заполненные строки файла
ВсегоСтрок = Лист.UsedRange.Rows.Count;
Для НомерСтроки = 1 По ВсегоСтрок Цикл
ТекущаяСтрока = Лист.Rows(НомерСтроки);
// Если в строке есть объединенные ячейки с переносом текста
Если ТекущаяСтрока.MergeCells = 1 Тогда
// Запоминаем параметры объединения ячеек
ОбластьОбъединения = ТекущаяСтрока.Cells(1, 1).MergeArea;
СуммарнаяШирина = 0;
Для ИндКолонки = 1 По ОбластьОбъединения.Columns.Count Цикл
СуммарнаяШирина = СуммарнаяШирина + ОбластьОбъединения.Columns(ИндКолонки).ColumnWidth;
КонецЦикла;
// Временно отменяем объединение ячеек для корректного расчета AutoFit
ТекущаяСтрока.Cells(1, 1).MergeCells = 0;
ТекущаяСтрока.Cells(1, 1).ColumnWidth = СуммарнаяШирина;
// Вызываем системный автоподбор высоты строки в Excel
ТекущаяСтрока.EntireRow.AutoFit();
ВычисленнаяВысота = ТекущаяСтрока.RowHeight;
// Возвращаем настройки объединения обратно
ОбластьОбъединения.Merge();
// Устанавливаем высоту строки с небольшим коэффициентом запаса (например, +15%)
ТекущаяСтрока.RowHeight = ВычисленнаяВысота * 1.15;
КонецЕсли;
КонецЦикла;
РабочаяКнига.Save();
РабочаяКнига.Close();
Excel.Quit();
Excel = 0;
Исключение
Предупреждение("Ошибка оптимизации Excel: " + ОписаниеОшибки());
Если ПустоеЗначение(Excel) = 0 Тогда
Excel.Quit();
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Данный способ является наиболее надежным с технической точки зрения, поскольку расчет высоты выполняет сам движок MS Excel непосредственно на компьютере пользователя, учитывая локальные настройки принтера и установленные шрифты.
---
Для создания полноценных договоров использование табличного процессора (Excel) изначально является компромиссным решением. Excel предназначен для работы с таблицами, формулами и числами. Для работы с текстом и соблюдения строгих межстрочных интервалов гораздо лучше подходит текстовый процессор MS Word.
Мы можем создать файл-шаблон в формате .dot или .doc, разместить в нем специальные текстовые метки (например, [НомерДоговора], [ДатаДоговора], [Клиент]) и программно заполнять их из 1С 7.7.
Посмотрим на пример реализации заполнения шаблона Word:
// Процедура формирования договора на основе шаблона MS Word
Процедура СформироватьДоговорВWord(ПутьКШаблону, НомерДок, ДатаДок, КонтрагентНаименование)
Попытка
WordApp = СоздатьОбъект("Word.Application");
НовыйДок = WordApp.Documents.Add(ПутьКШаблону);
// Делаем окно приложения видимым для пользователя
WordApp.Visible = 1;
// Получаем объект поиска и замены
ПоискИЗамена = WordApp.Selection.Find;
// Заполняем реквизиты договора
ПоискИЗамена.Execute("[НомерДоговора]", , , , , , , , , СокрЛП(НомерДок), 2);
ПоискИЗамена.Execute("[ДатаДоговора]", , , , , , , , , НРД(ДатаДок), 2);
ПоискИЗамена.Execute("[Контрагент]", , , , , , , , , СокрЛП(КонтрагентНаименование), 2);
// Активизируем готовый документ
WordApp.Activate();
Исключение
Предупреждение("Ошибка при работе с MS Word: " + ОписаниеОшибки());
Если ПустоеЗначение(WordApp) = 0 Тогда
WordApp.Quit();
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Использование MS Word полностью решает проблемы с переносом строк, масштабированием при печати и обрезанием текста. Документ выглядит солидно, легко редактируется пользователем и гарантированно распечатывается "один в один".
---
Если договор отправляется клиенту только для ознакомления или печати и не требует последующего редактирования, лучшим решением будет отказаться от формата Excel в пользу кроссплатформенного формата PDF.
Для реализации этого метода можно использовать бесплатные виртуальные PDF-принтеры (например, PDFCreator, Bullzip PDF Printer или встроенный принтер Microsoft Print to PDF в Windows 10/11):
В формате PDF шрифты и высоты строк "впекаются" в документ намертво, что гарантирует абсолютную идентичность отображения договора на любых компьютерах, планшетах и смартфонах без смещений и обрезки текста.