Поместится ли текст в ячейке? (с примерами использования: авторазмер шрифта, перенос строк)

25.04.12

Разработка - Механизмы платформы 1С

Периодически возникает вопрос: поместится ли текст в ячейке табличного документа? Хоть возникает он редко, но всё-таки возникает. В этой статье рассказывается как можно получить ответ на этот вопрос.

Скачать файлы

Наименование Файл Версия Размер
Печать ценников публикация подбор размера шрифта (Оптимизирован)
.epf 12,32Kb
117
.epf 12,32Kb 117 Скачать
Наименование в несколько строк публикация
.epf 8,87Kb
84
.epf 8,87Kb 84 Скачать
Печать ценников публикация подбор размера шрифта
.epf 12,28Kb
44
.epf 12,28Kb 44 Скачать
Подбор размера шрифта в надписи табличного документа
.epf 8,82Kb
40
.epf 8,82Kb 40 Скачать

 

Вступление:

На просторах интернета я встречал различные решения, но все они носили "вероятностный" характер и строились на определении среднего размера символа (или максимального размера), вычислением длины строки, количеством строк, используя всяческие эмпирические коэффициенты, и всё равно не могли гарантировать, что текст поместится в ячейку.

Единственное решение, близкое к задаче, которое я нашел: Автоматический подбор размера шрифта в объекте РисунокТабличногоДокумента. Но оно для размещения текста в РисунокТабличногоДокумента, а не в область как в данной статье. Оно требует предварительной подготовки, но ничего проще именно для РисункаТабличногоДокумента на данный момент мне неизвестно (попытку упрощения см ниже).

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

Сам я эту проблему зачастую обходил теми или иными путями. И это всех удовлетворяло: и меня, и заказчиков. Видимо, из-за того, что встречается она редко:

1. В ценниках. Наименование товара обычно центрируют по высоте, и при очень длинном наименовании его начало и конец имеют риск не поместиться в отведенное ему место (а в ценниках обычно отключают автовысоту). Из этого положения два выхода:

а) Выбирать тот или иной шаблон ценника. Не реализовано в примерах.

б) Подгонять размер текста под ценник. Реализовано в примерах:

Авторазмер текста

 2. И когда наименование нужно написать на несколько строк:

В типовых это реализовано так:

Типовое решение вывода длинного текста

мне же больше по душе выводить его так (с автоматическим переносом слов):

человеческое написание

Решение:

Намучавшись за два вечера, пришел, надеюсь, к простому решению:

Идея такая:

1. Запоминаем исходный размер ячейки в мм.

2. Назначаем ячейке свойство АвтоВыстота = Истина

3. Вставляем текст и опять смотрим высоту ячейки.

4. Если высота ячейки изменилась в большую сторону - значит, текст не помещается.

Высоту ячейки в мм будем измерять с помощью вставки в ячейку Рисунка и измерением его размеров.

Подробно:

Функция получения высоты ячейки:

Функция ВысотаОбластиВмм(пОбласть, пТабДок)
    
    Надпись = пТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);    
    Надпись.Расположить(пОбласть);    
    Высота = Надпись.Высота;    
    пТабДок.Рисунки.Удалить(Надпись);
    
    Возврат(Высота);
    
КонецФункции

Функция для определения вместится ли текст в ячейку:

Функция ТекстУмещаетсяВЯчейке(пОбласть, пТабДок, пТекст)     
        
    ВысотаДо = ВысотаОбластиВмм(пОбласть, пТабДок);    
    
    // Скопируем область в новый табличный документ.
    //  И там уже будем играть с её свойствами.
    ВремТабДок = Новый ТабличныйДокумент;
    ВремТабДок.Вывести(пТабДок);
    ВремОбласть = ВремТабДок.Область(пОбласть.Имя);    
    
    ВремОбласть.АвтоВысотаСтроки = Истина;
    ВремОбласть.ВысотаСтроки     = 0;    
    
    ВремОбласть.Текст = пТекст;        
    ВысотаПосле = ВысотаОбластиВмм(ВремОбласть, ВремТабДок);
                
    Если ВысотаДо >= ВысотаПосле Тогда
        Возврат(Истина);
    Иначе
        Возврат(Ложь);
    КонецЕсли;

КонецФункции

Для возможности использования этого метода необходимо соблюдать следующие условия:

1. Необходимо как-нибудь назвать область.

2. Заполнение области = Текст, а не Параметр или Шаблон. В принципе, можно использовать и то и другое, но код становиться мудрёней. Во всяком случае, я ничего простого не придумал. И так как жизнь это усложняет не сильно не стал заморачиваться из-за этого.

3. Размещение текста = Перенос. Вот это нужно обязательно! Размещение текста програмно поставить можно, но эффект от изменения, насколько я понял, появляется только после отображения табличного документа с этой ячейкой.

4. Область из одной строки. Т.е. объединять ячейки по вертикали нельзя (в тех которых должен проверяться текст). Исправлено в процессе публикации: создается копия табличного документа с областью и уже меняются её свойства, а не самого табличного документа.


 

В файлах вы найдете:

1. Пример с подбором размера шрифта с использованием функций из статьи.

2. Оптимизированный по быстродействию пример подбора размера шрифта с небольшой модификацией кода (но подбор размера шрифта - не оптимальный. Ниже есть некая попытка его вычилить а не уменьшать каждый раз на 1).

3. Вывод длинных строк в несколько ячеек.

4. Подбор размера шрифта в элементе "Рисунок табличного документа".


Рисунок табличного документа (Надпись):

Скажу сразу, на больших текстах, работает ужасно долго.

Так вот, с рисунком табличного документа (далее "надписью") пришлось повозиться. Всё дело в том, что при установленом свойстве "Авторазмер" сами размеры подгоняются под текст только после их отображения. Здесь вариантов два:

1. либо ждать какое время и затем смотреть размеры, например так: ПодключитьОбработчикОжидания("ИзмеритьРазмеры", 0.1, Истина)

2. либо "заставить" эту заразу отображаться принудительно.

Первый - рабочий. Однако код с ним получается сложный. И на каждую иттерацию - минимум по 0.1 секунды. В итоге это очень долго. Но работает (вроверял на поле таблчного документа).

А вот второй. С помощью применения маленькой хитрости - всё шикарно работает. А хитрость в том, что есть у ТабличногоДокумента метод Показать(). Хорош он тем, что как раз после его исполнения, размеры надписи уже становятся реальными, подогнанными под размер текста. Но плох он тем, что окрывает окно, которое программно или не закроешь, или я просто не знаю как.

Думал, я думал. А точнее, экперементировал, я экспериментировал. И вот до чего дошел:

Создаем на форме элемент "ПолеТабличногоДокумента" выводим туда нашу надпись. И вуаля - вызов метода "ЭлементыФормы.ПолеТабличногоДокумента.Показать()" не открывает никаких дополнительных окон, да что там, пользователь вообще этого не заметит. Зато мы это заметим. Да и мало того, что заметим, так еще и поэксплуатируем в своих корыстных целях! Ведь после вызова этого метода все высоты и ширины устанавливаются в соответсвие с установленной настройкой "АвтоРазмер = Истина". Красота. Но самое замечательное, что полеТабличногоДокумента можно даже не отображать! Разве, что форму с этим самым полем надо обязательно открывать, что накладывает некоторые ограничения на использование данного метода. Но эту форму можно с прогрессбаром сделать, и ни у кого не будет вопросов насчет открытия каких-то лишних форм.

Код приводить в человеческий вид мне лень. Если что, то есть файл в примерах.

Хочу отметить пару интересных моментов:

1. Вычисление высоты надписи при её фиксированной ширине.

2. Попытка оптимизировать алгоритм поиска шрифта.


// ;сообщить(...) - отладка

Функция ВысотаНадписиПриФиксированнойШирине(пНадпись, пЭлТабДок, пТекст)
        
    СтруктураНачЗначений = Новый Структура("Ширина, Высота, Авторазмер, РазмещениеТекста");
    ЗаполнитьЗначенияСвойств(СтруктураНачЗначений, пНадпись);     
    
    //////////////////////////////////////////////////////////////////////////////
    
    НачШирина = пНадпись.Ширина;
    
    пНадпись.Авторазмер = Истина;
    пНадпись.РазмещениеТекста = ТипРазмещенияТекстаТабличногоДокумента.Обрезать;
        
    ТекТекст = "";
    ВсегоСимволов = СтрДлина(Текст);
    
    ИндексДлиныСтроки = 0;
    
    Для Индекс = 1 По ВсегоСимволов Цикл
        
        ИндексДлиныСтроки = ИндексДлиныСтроки + 1;        
        
        ТекСимвол = Сред(пТекст, Индекс, 1);        
        пНадпись.Текст = ТекТекст + ТекСимвол;
        
        пЭлТабДок.Показать();
        
        Если пНадпись.Ширина > НачШирина Тогда
            
            Если ИндексДлиныСтроки = 1 Тогда // не вместился единственный символ.
                Возврат(Неопределено);
            КонецЕсли;
            
            ТекТекст = ТекТекст + Символы.ПС;            
            Индекс = Индекс - 1; // да, да, я и сам не люблю такие манипуляции со счетчиком цикла, но исправлять лень.
            ИндексДлиныСтроки = 0;
            
        Иначе
            ТекТекст = ТекТекст + ТекСимвол;
        КонецЕсли;
        
    КонецЦикла;
    
    пНадпись.Текст = ТекТекст;
    пЭлТабДок.Показать();
    
    ИтоговаяВысота = пНадпись.Высота;
    
    //////////////////////////////////////////////////////////////////////////////
    
    ЗаполнитьЗначенияСвойств(пНадпись, СтруктураНачЗначений);
    
    Возврат(ИтоговаяВысота);
    
КонецФункции

Функция ПолучитьОптимальныйРазмерШрифта(пМакет, пИмяНадписи, пТекст, пМаксимальныйРазмерШрифта ,пТабДок)
    
    пТабДок.Вывести(пМакет);
    
    Надпись = пТабДок.Рисунки[пИмяНадписи];
    
    //////////////////////////////////////////////////////////////////////////
    // { Подгон размера шрифта
    
    НачВысота = Надпись.Высота;    
    
    РазмерШрифта = пМаксимальныйРазмерШрифта;
    
    Надпись.Шрифт = Новый Шрифт(Надпись.Шрифт, ,РазмерШрифта);
    ТекВысота = ВысотаНадписиПриФиксированнойШирине(Надпись, пТабДок, пТекст);
    
    Если ТекВысота = Неопределено Тогда
        Возврат(Неопределено);
    КонецЕсли;
    
    Пока НачВысота < ТекВысота
        И РазмерШрифта > 0 Цикл
        
        ;Сообщить("РазмерШрифта = "+РазмерШрифта);
                
        НовРазмерШрифта = Цел(РазмерШрифта / (Sqrt(ТекВысота / НачВысота)));        
        
        ;Сообщить("НовРазмерШрифта = "+НовРазмерШрифта);
        
        Если НовРазмерШрифта = РазмерШрифта Тогда НовРазмерШрифта = НовРазмерШрифта - 1 КонецЕсли;
        
        РазмерШрифта = НовРазмерШрифта;
        Надпись.Шрифт = Новый Шрифт(Надпись.Шрифт, ,РазмерШрифта);
        ТекВысота = ВысотаНадписиПриФиксированнойШирине(Надпись, пТабДок, пТекст);
        
    КонецЦикла;
    
    // Точная подгонка (в сторону увеличения)
    
    ИтоговыйРазмерШрифта = РазмерШрифта;
    
    Пока ТекВысота <> Неопределено
        И НачВысота > ТекВысота
        И РазмерШрифта < пМаксимальныйРазмерШрифта Цикл
        
        ИтоговыйРазмерШрифта = РазмерШрифта;
        
        ;Сообщить("РазмерШрифта = "+РазмерШрифта);
                
        НовРазмерШрифта = РазмерШрифта + 1;        
        
        ;Сообщить("НовРазмерШрифта = "+НовРазмерШрифта);
        
        РазмерШрифта = НовРазмерШрифта;
        Надпись.Шрифт = Новый Шрифт(Надпись.Шрифт, ,РазмерШрифта);
        ТекВысота = ВысотаНадписиПриФиксированнойШирине(Надпись, пТабДок, Текст);

    КонецЦикла;    
    
    // }
    ////////////////////////////////////////////////////////////////////

    //Если ТекВысота = Неопределено Тогда
    //    ИтоговыйРазмерШрифта = Неопределено;    
    //КонецЕсли;
    
    Возврат(ИтоговыйРазмерШрифта);    
    
КонецФункции

Процедура КнопкаВыполнитьНажатие(Кнопка)
    
    Макет = ПолучитьМакет("Макет");
    
    ТабДок = ЭлементыФормы.ПолеТабличногоДокумента;    
    ТабДок.Очистить(); // Мы же хотим посмотреть в удобном месте?    
    
    РазмерШрифта = ПолучитьОптимальныйРазмерШрифта(Макет, "Надпись", Текст, 80 ,ТабДок);    
    
    Если РазмерШрифта <> Неопределено Тогда
        
        Надпись = Макет.Рисунки.Надпись;
        Надпись.Шрифт = Новый Шрифт(Надпись.Шрифт, ,РазмерШрифта);        
        Надпись.Текст = Текст;        
        Макет.Показать();
        
    Иначе
        
        Предупреждение("Ошибка подбора размера (даже единственный символ не поместился)!");
        
    КонецЕсли;     
    
КонецПроцедуры
 

Удачных экспериментов!

См. также

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    4527    dsdred    53    

72

Как готовить и есть массивы

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Все мы используем массивы в своем коде. Это один из первых объектов, который дают ученикам при прохождении обучения программированию. Но умеем ли мы ими пользоваться? В этой статье я хочу показать все методы массива, а также некоторые фишки в работе с массивами.

24.01.2024    5294    YA_418728146    25    

63

Планы обмена VS История данных

Обмен между базами 1C Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    6409    dsdred    36    

112

1С-ная магия

Механизмы платформы 1С Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    18473    SeiOkami    46    

118

Дефрагментация и реиндексация после перехода на платформу 8.3.22

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    12088    human_new    27    

74

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    8821    YA_418728146    6    

141

Внешние компоненты Native API на языке Rust - Просто!

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    6279    sebekerga    54    

94

Все скопируем и вставим! (Буфер обмена в 1С 8.3.24)

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    15986    SeiOkami    31    

103
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. i132 122 06.04.12 10:36 Сейчас в теме
Спасибо, за находку, +10$m
предлагаю поменять название на "подгонка размера шрифта под размеры ячейки". - смысл статьи как обходить случаи кода весь текст не помещается в ячейке.
5. yku 372 06.04.12 13:51 Сейчас в теме
(1) Признаться честно, над названием статьи я, наверное, даже больше просидел, чем над самой статьей. Но с предложенным названием не согласен: статья у меня как раз не как обходить такие случаи, а как их выявить программно. С этим возникает сложность. А вот что делать при таких случаях - это уже у кого на что фантазии хватит.
6. yku 372 06.04.12 14:00 Сейчас в теме
(1) и спасибо за 10$m. Я и не знал что их можно перекидывать. Правда, я не знаю что с ними надо делать :)
16. prog-eg 85 19.04.12 12:45 Сейчас в теме
(6) за 10$m можно поднять публикацию
2. Поручик 4670 06.04.12 10:40 Сейчас в теме
Кстати, да, задача редкая, но не тривиальная.
В прошлом году было подобное, но использовал другую методику, основанную на подгонке строки в ячейке и вычислении получившегося количества символов.

Неделю мозг ломал, пока не наткнулся
http://avb1c.narod.ru/rowheight.html

Но получилось достаточно корректно, по крайней мере для того набора строк высота строки вычислялась верно.
mark_oilbass; salexdv; +2 Ответить
4. yku 372 06.04.12 13:41 Сейчас в теме
(2) Да, по ссылке тоже интересное решение. Я б не додумался.
7. mikhailv 19 09.04.12 15:26 Сейчас в теме
Автору огромное спасибо за качественную и достаточно универсальную реализацию недостающей в 1С функции.
(2) Поручик, эта реализация мне понравилась больше, чем указанная вами.

Пригодилось в печати спецификации на "разлинованной" таблице.

Пока внедрял, наткнулся на то, что 1С (рел. 8.2.13.219) при крайних значениях заполнения в ячейке (когда текст чуть-чуть не умещается и переносится на другую строку) не правильно отрабатывает высоту (через картинку). При отладке видно, что текст ПЕРЕНЁССЯ, а высота картинки возвращается такой же, как и без переноса.
Решил проблему дополнительной проверкой с добавлением одного символа:

//Функция для определения вместится ли текст в ячейку:
Функция ТекстУмещаетсяВЯчейке(пОбласть, пТабДок, пТекст)

ВысотаДо = ВысотаОбластиВмм(пОбласть, пТабДок);

// Скопируем область в новый табличный документ.
// И там уже будем играть с её свойствами.
ВремТабДок = Новый ТабличныйДокумент;
ВремТабДок.Вывести(пТабДок);
ВремОбласть = ВремТабДок.Область(пОбласть.Имя);

ВремОбласть.АвтоВысотаСтроки = Истина;
ВремОбласть.ВысотаСтроки = 0;

ВремОбласть.Текст = пТекст;
ВысотаПосле = ВысотаОбластиВмм(ВремОбласть, ВремТабДок);

Если ВысотаДо >= ВысотаПосле Тогда
//Попробуем отловить умещение "на грани": добавим символ
ВремОбласть.Текст = пТекст + "Щ";
ВысотаПослеСимв = ВысотаОбластиВмм(ВремОбласть, ВремТабДок);
Если ВысотаДо >= ВысотаПослеСимв Тогда
Возврат(Истина);
Иначе
Возврат(Ложь);
КонецЕсли;

Иначе
Возврат(Ложь);
КонецЕсли;

КонецФункции

Также на базе этой функции написал ПолучитьМассивУмещающихсяСтрок(пОбласть, пТабДок, пТекст), в которой текст разбивается на несколько умещающихся в указанную ячейку строк.
8. Поручик 4670 09.04.12 15:34 Сейчас в теме
(7) Я её и сам бы не стал использовать, если бы тогда появилась эта статья. Но времени на эксперименты особо не было.
9. yku 372 09.04.12 17:08 Сейчас в теме
(7) Пожалуйста. Надо будет подправить публикацию. А почему бы букву не добавить сразу, а не во второй итерации?
Вот так:

//Функция для определения вместится ли текст в ячейку:
Функция ТекстУмещаетсяВЯчейке(пОбласть, пТабДок, пТекст)

ВысотаДо = ВысотаОбластиВмм(пОбласть, пТабДок);

// Скопируем область в новый табличный документ.
// И там уже будем играть с её свойствами.
ВремТабДок = Новый ТабличныйДокумент;
ВремТабДок.Вывести(пТабДок);
ВремОбласть = ВремТабДок.Область(пОбласть.Имя);

ВремОбласть.АвтоВысотаСтроки = Истина;
ВремОбласть.ВысотаСтроки = 0;

//ВремОбласть.Текст = пТекст;
ВремОбласть.Текст = пТекст+"Щ"; // Для исключения ситуаций вида "на грани переноса"
ВысотаПосле = ВысотаОбластиВмм(ВремОбласть, ВремТабДок);

Если ВысотаДо >= ВысотаПосле Тогда
Возврат(Истина);
Иначе
Возврат(Ложь);
КонецЕсли;

КонецФункции
10. mikhailv 19 09.04.12 17:15 Сейчас в теме
(9) Согласен, ваш вариант лучше:)
3. Поручик 4670 06.04.12 10:42 Сейчас в теме
11. Ortos 10.04.12 10:14 Сейчас в теме
Хороший метод, для ячейки табличного документа самое оно!
12. krylovim 18.04.12 19:29 Сейчас в теме
Хороший метод, спасибо автору!

Только есть одно узкое место - производительность:
у меня в печатной форме выводилось 9 строк с обязательным переносом, в случае не помещения текста в ячейку. Все это дело формировалось ~9 секунд - на мой взгляд слишком долго для небольшой печатной формы.
Замер производительности показал, что самым узким местом оказался вывод исходного табличного документа (пТабДок) во временный (ВремТабДок).
Вместо работы во временном табличном документе я предпочел сохранение/восстановление изменяемых свойств (АвтоВысотаСтроки, ВысотаСтроки и Текст) и работу оставил в исходном таб. документе.
Результат - 0,35 сек, т.е. практически в 30 раз быстрее.
13. yku 372 18.04.12 23:56 Сейчас в теме
(12) lonelylockly,
Спасибо за замечания. Да, я тоже заметил, что так медленней, но на моих задач замедление не было критичным и не выходило за рамки пары секунд.

Кстати, сначала я тоже непосредственно менял в самой области. Но заметил, что если "тестируемая" область содержит объединенную ячейку в несколько строк, то высота не восстанавливается. А как сделать чтобы она восстанавливалась, я не знаю. И я решил пожертвовать быстродействием и выиграть в универсальности.

PS. И если бы скачали вротой файл ("Наименование в несколько строк публикация"), то там как раз такой способ (менять его мне было лень):
Функция ТекстУмещаетсяВЯчейке(пОбласть, пТабДок, пТекст) 	
		
	// Сохраним настройки области
	СтруктураЗначений = Новый Структура("Текст, АвтовысотаСтроки, ВысотаСтроки");	
	ЗаполнитьЗначенияСвойств(СтруктураЗначений, пОбласть);
	
	////////////////////////////////////////////////////////////­//////////////////
		
	пОбласть.Текст = "";		
	ВысотаДо = ВысотаОбластиВмм(пОбласть, пТабДок);	
					
	пОбласть.АвтоВысотаСтроки = Истина;
	пОбласть.ВысотаСтроки     = 0;	
	
	пОбласть.Текст = пТекст;		
	ВысотаПосле = ВысотаОбластиВмм(пОбласть, пТабДок);
	    		
	////////////////////////////////////////////////////////////­//////////////////	
	
	// Восстановим настройки области
	ЗаполнитьЗначенияСвойств(побласть, СтруктураЗначений);
	
	Если ВысотаДо >= ВысотаПосле Тогда
		Возврат(Истина);
	Иначе
		Возврат(Ложь);
	КонецЕсли;

КонецФункции
Показать
14. yku 372 19.04.12 00:01 Сейчас в теме
(12) Протестировал как со старым методом, так и с новым. В лидерах по медлительности "Высота = Надпись.Высота;". А вот сразу за ним как раз "ВремТабДок.Вывести(пТабДок);". Чуть-чуть отстает.
19. krylovim 25.04.12 22:40 Сейчас в теме
(14) у меня такой разрыв скорее всего (~99%) связан с тем, что в области, которая копировалась во временный таб. док. находился рисунок(картинка). Не проверял, но практически уверен в этом. Так что грамотная организация именованных областей и формирование табличного документа окажутся гораздо более простым решением =)
15. yku 372 19.04.12 00:04 Сейчас в теме
(12) Вот так флуд я устроил. Вот метод и быстро выполняющийся и поддерживающий возможность объединения ячеек (копия табличного документа создается вне цикла):
Функция ВысотаОбластиВмм(пОбласть, пТабДок)
	
	Надпись = пТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);	
	Надпись.Расположить(пОбласть);	
	Высота = Надпись.Высота;    
	пТабДок.Рисунки.Удалить(Надпись);
	
	Возврат(Высота);
	
КонецФункции

Процедура ВывестиТекстВОбласть(пОбласть, пТабДок, пТекст, пМаксимальныйРазмерТекста = 60)
	
	// Запомним высоту исходной ячейки.
	НачальнаяВысота = ВысотаОбластиВмм(пОбласть, пТабДок);	
	
	// Создадим копию области и изменим её свойства.
	
	ВремТабДок = Новый ТабличныйДокумент;
	ВремТабДок.Вывести(пТабДок);
	ВремОбласть = ВремТабДок.Область(пОбласть.Имя);	
	
	ВремОбласть.АвтоВысотаСтроки = Истина;
	ВремОбласть.ВысотаСтроки     = 0;
	
	ВремОбласть.Текст = пТекст + "Щ"; // +"Щ" - исключение ситуации "на грани переноса"
	
	// Подберем зармер шрифта
	
	РазмерТекста = пМаксимальныйРазмерТекста;
	ВремОбласть.Шрифт = Новый Шрифт(ВремОбласть.Шрифт, ,РазмерТекста);
	
	ТекВысота = ВысотаОбластиВмм(ВремОбласть, ВремТабДок);
	
	Пока ТекВысота > НачальнаяВысота И РазмерТекста > 0 Цикл
			
		РазмерТекста = РазмерТекста - 1;
		ВремОбласть.Шрифт = Новый Шрифт(ВремОбласть.Шрифт, ,РазмерТекста);
		ТекВысота = ВысотаОбластиВмм(ВремОбласть, ВремТабДок);
		
	КонецЦикла;		
	
	// Изменим размер шрифта исходной области и выведем текст.
	
	пОбласть.Шрифт = Новый Шрифт(пОбласть.Шрифт, ,РазмерТекста);
	пОбласть.Текст = пТекст;
	
КонецПроцедуры
Показать
17. Ortos 25.04.12 08:57 Сейчас в теме
Второй метод с элементом "Рисунок" подходит для любого шрифта, это плюс. Однако он дико медленный. Пробовал я тоже так делать сперва, отверг такой метод - для большого количества рисунков в которых много текста не подходит абсолютно.
18. yku 372 25.04.12 11:52 Сейчас в теме
(17) Ortos,
Попробовал на длинной строке... Можно состариться пока посчитает. Надо бы объединить два метода. Чтобы сначала анализировал длину строки, потом выбирал алгоритм поиска. Если строка длинная, то берет твой метод (надеюсь, можно на "ты").

Только хочу модифицировать. Для каждого символа чтобы определял высоту и ширину этого символа и высоту строк. Затем высчитывал уже необходимый размер шрифта. Или не для каждого символа, а как у тебя, для буквы "Щ".

А может, и полностью перейти на второй алгоритм. Вот только с работой завал.
20. i132 122 27.04.12 15:00 Сейчас в теме
По моим замерам в вашей обрабтке около 15 процентов уходит на создание/удаление временых ячеек и рисунков.
Если хранить ссылоку на временную ячейку -- ее размеры меняются при изменнии текста и шрифта.
Мой код:
ВремТабДок = Новый ТабличныйДокумент;
ВремТабДок.Вывести(ОбластьМакета);
ВремОбласть = ВремТабДок.Область("Комментарий");	
ВремОбласть.АвтоВысотаСтроки = Истина;
ИсходныйШрифт = ВремОбласть.Шрифт;

ПроверямНадпись = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);	
ПроверямНадпись.Расположить(ВремОбласть);	

МаксВысота = ПроверямНадпись.Высота;
Пока Выборка.Следующий() Цикл
	ПараметрыМакета.Комментарий		= Выборка.Описание;
	ТабДокумент.Вывести(ОбластьМакета);
	
	флНадоменитьШрифт =ложь;
	ВремОбласть.ВысотаСтроки =0;
	ВремОбласть.тЕКСТ = Выборка.Описание;
	
	ВремОбласть.Шрифт = ИсходныйШрифт;
	Пока ПроверямНадпись.Высота>МаксВысота Цикл
		флНадоменитьШрифт =Истина;
		ВремОбласть.Шрифт = Новый Шрифт(ВремОбласть.Шрифт,,ВремОбласть.Шрифт.Размер-1);
		Если ВремОбласть.Шрифт.Размер=1 Тогда
			Прервать;
		Конецесли;	
	КонецЦикла;
	Если флНадоменитьШрифт Тогда
		ПравимОбласть = ТабДокумент.Область("Комментарий");
		ПравимОбласть.Шрифт = ВремОбласть.Шрифт;
	КонецЕсли;	
КонецЦикла;
Показать

Работает в том числе и для ячеек заполняемых по параметру. Правда для случая объединных ячеек не проверял.
Первоначальные размеры шрифта, по моему лучше брать из исходной ячейки.
Egovigor; kimskiysanya; yku; kobets-meloman; +4 Ответить
21. yku 372 27.04.12 16:32 Сейчас в теме
(20) i132, Интересно. Действительно так быстрее. А можно еще и шрифт не подбирать, а после первого прогона его рассчитать
НовРазмерШрифта = Цел(РазмерШрифта / (Sqrt(ТекВысота / НачВысота)));

Так рассчитывается, но не очень точно, может ошибиться на 1-3 кегля.
Т.е. в первом проходе его рассчитали, а потом уже перебором можно уточнить.

Но все эти улучшения, я, пожалуй, так и оставлю вне статьи, то бишь в комментариях. Ведь я лишь хотел показать, что возможно узнать вместиться ли текст в ячейку или нет. И чтобы ни у кого не возникло сомнений в необходимости этого, привел пару примеров. А оптимизация под конкретные задачи тут уж кто во что горазд.

Но за алгоритм спасибо.
22. kobets-meloman 15.08.12 05:40 Сейчас в теме
(20)Что у Вас за область "Комментарий"? Это на макете та самая область, шрифт которой изменяется??? Возможно вместо названия области задать ее диапазон вида что-то вроде "R2C2:R2C7" ?
23. i132 122 15.08.12 11:41 Сейчас в теме
(22) kobets-meloman, да "Комментарий" это область на мекете размер шрифта которой можно менять, задать адрес в стиле "R2C2:R2C7" можно - но тогда надо следить за адресами при следующих доработках макета - проще сразу дать название области.
24. kobets-meloman 20.08.12 05:33 Сейчас в теме
(20) Еще такой вопрос. Кусок кода не приводит к зацикливанию? В этом цикле мне непонятно, где меняется "ПроверямНадпись.Высота"... Хотя нет, по логике зацикливания не будет. Цикл завершится, когда размер шрифта станет равным 1. А все-таки хочется, чтобы цикл завершался при условии "ПроверямНадпись.Высота>МаксВысота"
Пока ПроверямНадпись.Высота>МаксВысота Цикл
      флНадоменитьШрифт =Истина;
      ВремОбласть.Шрифт = Новый Шрифт(ВремОбласть.Шрифт,,ВремОбласть.Шрифт.Размер-1);
      Если ВремОбласть.Шрифт.Размер=1 Тогда
         Прервать;
      Конецесли;   
   КонецЦикла;


Извиняюсь за, наверное, глупый вопрос. Просто реально непонятно...
25. yku 372 20.08.12 10:14 Сейчас в теме
(24) kobets-meloman,
Еще такой вопрос. Кусок кода не приводит к зацикливанию?

Нет.
В этом цикле мне непонятно, где меняется "ПроверямНадпись.Высота"...

Она напрямую не меняется.
Область ограничена по ширине. В эту область вставлен текст. Нас интересует вариант когда текст из-за ограничений ширины выводится в несколько строк. Чем больше шрифт, тем больше строк. Меняем размер шрифта - 1С меняет размер области (подгоняет под текст), а мы смотрим её высоту. Как только высота области стала меньше, чем МаксВысота, размер шрифта стал максимальным, при котором текст вмещается в нашу область. Он то нам и нужен.

Хотя нет, по логике зацикливания не будет. Цикл завершится, когда размер шрифта станет равным 1. А все-таки хочется, чтобы цикл завершался при условии "ПроверямНадпись.Высота>МаксВысота"

Всем нам хочется того же. Что мы и получаем, разве нет? "Размер шрифта >= 1" - ограничение. Так как меньшие размеры шрифта в нашей задаче не интересены.

PS. Немного смущают такие вопросы.
36. Makushimo 160 10.12.14 13:21 Сейчас в теме
(20) i132,
вот тут

ВремОбласть.Текст = пТекст


ругается "поле недоступно для записи"

в ВремТабДок и ВремОбласть свойство Защита = ложь;
26. ZhokhovM 724 06.11.12 16:01 Сейчас в теме
Добрый день! Кто-нибудь проверял на управляемой форме? У меня почему текст полностью переносит на следующую строку вместо текущей...
27. SinglCOOLer 217 16.12.12 12:15 Сейчас в теме
на 1С:Предприятие 8.1 (8.1.15.14) отказывается работать, в этом месте Высота = Надпись.Высота всегда возвращается одна и та же высота :(
28. yku 372 16.12.12 13:13 Сейчас в теме
(27) SinglCOOLer,
Странно, в теории поведение должно быть одинаковое. Быть может, некорректно перенесли в 8.1? А так, для меня 8.1 утратила актуальность.
29. SinglCOOLer 217 16.12.12 13:16 Сейчас в теме
проверял этот же код (обработку сконвертил под 8.2) на 8.2 все срабатывает
30. galinka1c8 16.05.13 15:02 Сейчас в теме
Автору большое спасибо, как раз пригодилось, задача хоть и редкая, но довольно занятная.
31. echo77 1868 09.09.13 08:47 Сейчас в теме
Функция ТекстУмещаетсяВЯчейке() иногда тупит и упорно говорит что текст не умещается в ячейке, я подправил её следующим образом:

Функция ТекстУмещаетсяВЯчейке(пОбласть, пТабДок, пТекст)

// Скопируем область в новый табличный документ.
// И там уже будем играть с её свойствами.
ВремТабДок = Новый ТабличныйДокумент;
ВремТабДок.Вывести(пТабДок);
ВремОбласть = ВремТабДок.Область(пОбласть.Имя);

ВысотаДо = ВысотаОбластиВмм(ВремОбласть, ВремТабДок);

ВремОбласть.АвтоВысотаСтроки = Истина;
ВремОбласть.ВысотаСтроки = 0;

ВремОбласть.Текст = пТекст;
ВысотаПосле = ВысотаОбластиВмм(ВремОбласть, ВремТабДок);

Если ВысотаДо >= ВысотаПосле Тогда
Возврат(Истина);
Иначе
Возврат(Ложь);
КонецЕсли;

КонецФункции
32. via 92 16.09.13 14:22 Сейчас в теме
переделал в однопроцедурный вариант

Процедура ПоигратьсяСоШрифтамиОбласти(ТабДокумент,ИмяОбласти,знач МинимальныйШрифт=5,знач МаксимальныйШрифт=80) Экспорт
	ВремТабДокумент = Новый ТабличныйДокумент;
	ВремТабДокумент.Вывести(ТабДокумент.ПолучитьОбласть(ИмяОбласти)); 
	ВремОбласть = ВремТабДокумент.Область(ИмяОбласти);
	Надпись = ВремТабДокумент.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);    
	Надпись.Расположить(ВремОбласть);    
	МинимальныйШрифт = Мин(МинимальныйШрифт,ВремОбласть.Шрифт.Размер);
	МаксимальныйШрифт = Макс(МаксимальныйШрифт,ВремОбласть.Шрифт.Размер);
	ВысотаИсходная = Надпись.Высота;
	ВремОбласть.АвтоВысотаСтроки = Истина;
	ВремОбласть.ВысотаСтроки = 0;
	Высота = Надпись.Высота;
	Если ВысотаИсходная < Высота Тогда // Попробуем уменьшить
		Пока 1=1 Цикл
			Если Высота <= ВысотаИсходная Тогда
				ТабДокумент.Область(ИмяОбласти).Шрифт = Новый Шрифт(ВремОбласть.Шрифт,,ВремОбласть.Шрифт.Размер);
				Возврат;
			КонецЕсли; 
			Если ВремОбласть.Шрифт.Размер <= МинимальныйШрифт Тогда
				ТабДокумент.Область(ИмяОбласти).Шрифт = Новый Шрифт(ВремОбласть.Шрифт,,МинимальныйШрифт);
				Возврат;
			КонецЕсли; 
			ВремОбласть.Шрифт = Новый Шрифт(ВремОбласть.Шрифт,,ВремОбласть.Шрифт.Размер-1);
			Высота = Надпись.Высота;
		КонецЦикла; 
	ИначеЕсли Высота < ВысотаИсходная Тогда // Попробуем увеличить
		Пока 1=1 Цикл
			Если ВысотаИсходная < Высота Тогда
				ТабДокумент.Область(ИмяОбласти).Шрифт = Новый Шрифт(ВремОбласть.Шрифт,,ВремОбласть.Шрифт.Размер-1);
				Возврат;
			КонецЕсли;
			Если МаксимальныйШрифт <= ВремОбласть.Шрифт.Размер Тогда
				ТабДокумент.Область(ИмяОбласти).Шрифт = Новый Шрифт(ВремОбласть.Шрифт,,МаксимальныйШрифт);
				Возврат;
			КонецЕсли; 
			ВремОбласть.Шрифт = Новый Шрифт(ВремОбласть.Шрифт,,ВремОбласть.Шрифт.Размер+1);
			Высота = Надпись.Высота;
		КонецЦикла; 
	КонецЕсли; 
КонецПроцедуры

Показать
корум; a_a_burlakov; user757518; mark_oilbass; BigB; yku; shumvlesu; supermax2000; +8 Ответить
33. fokas 29.10.13 18:22 Сейчас в теме
Не обязательно использовать элемент формы или .Показать() для изменения высоты ячейки под текст. Обнаружил, что переприсваивание например ширины любой из ячеек табличного документа действует так же. Т.е.:
ТабДок = Новый ТабличныйДокумент;
...
ТабДок.Область(1,1,1,1).ШиринаКолонки = ТабДок.Область(1,1,1,1).ШиринаКолонки; // вместо ТабДок.Показать()
mark_oilbass; json; yku; +3 Ответить
34. yku 372 29.10.13 20:43 Сейчас в теме
35. Светлый ум 406 21.03.14 12:32 Сейчас в теме
Мои пять копеек:

"Высота строки ТабДок - Программно"

ОбластьЯчейки = Макет.ПолучитьОбласть("ШиринаСтроки|Строка");
пНадпись  = ОбластьЯчейки.ТекущаяОбласть;
НачШирина = пНадпись.ШиринаКолонки;
Стр = СтрДлина(ВыборкаСтрок.Номенклатура);


КоэффициентВысотыСтроки      = Цел(Стр/НачШирина) + 1; 
ВысотаОднойСтрокиПоУмолчанию = Число("12,5");
РасчетнаяВысотаСтроки        = ВысотаОднойСтрокиПоУмолчанию * КоэффициентВысотыСтроки;
ТекущаяВысотаСтроки          = ОбластьМакета.ТекущаяОбласть.ВысотаСтроки;
Показать

37. nghtmn_cmth 8 01.02.16 11:54 Сейчас в теме
Кто не хочет сильно заморачиваться:
1. Определяете сколько символов может войти в строку без переноса

СтрокаС = СтрЗаменить(СтрокаС,Символы.ПС, " ");
	Длинна =  СтрДлина(СтрокаС);
	КолСтрок =Окр( Длинна/Максимальное число символов+0.5,0,0);
	Позиция = 1;
	Для а=1 по КолСтрок Цикл
		ПодСтр = Сред(СтрокаС,Позиция,Максимальное число символов);
		Позиция= Позиция+Максимальное число символов;
		Сообщить(ПодСтр);
	КонецЦикла;
Показать
38. yku 372 01.02.16 15:29 Сейчас в теме
(37) nghtmn_cmth,
Проблема в том, что вот 10 символов "i"
iiiiiiiiii
а вот 10 символов "W"
WWWWWWWWWW
разница существенная.

А тем, кто не хочет "сильно заморачиваться", скорее всего эта статья вообще не нужна :)
39. nghtmn_cmth 8 02.02.16 10:07 Сейчас в теме
(38) определяем сколько самых широких символов входит в строку и переносим, останется конечно часть строки пустой, но ведь мы не заморачиваемся
40. CheBurator 3119 02.02.16 22:09 Сейчас в теме
я решил достаточно просто - для печати ценников подходит идеально, не зависит от размеров типов шрифтов.
http://infostart.ru/public/181223/

Аналогичный подход использую (с мелкой хитростью) для гарантированной печати "неотрывного" подвала.
41. Automatik 914 21.07.16 07:38 Сейчас в теме
Возврат ВысотаДо >= ВысотаПосле;
42. Smilk 23.09.16 11:51 Сейчас в теме
ФункцияТекстУмещаетсяВЯчейке(пОбласть, пТабДок, пТекст )    
        
    ВысотаДо = ВысотаОбластиВмм(пОбласть, пТабДок);    
    
    ВремТабдок = Новый ТабличныйДокумент;
    
   	ВремТабдок .ПолеСверху                         = 0;
	ВремТабдок .ПолеСнизу                           = 0;
	ВремТабдок .РазмерКолонтитулаСверху = 0;
	ВремТабдок .РазмерКолонтитулаСнизу   = 0;
	ВремТабдок .РазмерСтраницы = "Custom";	
	ВремТабдок .ВысотаСтраницы = ВысотаДо ;
        
        пОбласть.Параметры.Значение = пТекст;

        Возврат	ВремТабдок .ПроверитьВывод(пОбласть);

КонецФункции
Показать

Можно создать временный табличный документ, с высотой страницы = высотой ячейки в вашем макете. И проверять помещается ли текст на эту страницу. Ну и тут же можно сразу баловаться шрифтом в цикле,


Пока НЕ ВремТабДок.ПроверитьВывод(пОбласть) Цикл 
        пОбласть.ТекущаяОбласть.Шрифт = Новый Шрифт(пОбласть.ТекущаяОбласть.Шрифт, пОбласть.ТекущаяОбласть.Шрифт.Имя, пОбласть.ТекущаяОбласть.Шрифт.Размер - 1);     
КонецЦикла;


// Или шаг уменьшения сделать больше, чтобы было меньше итераций. При таком подходе ВремТабдок создается 1 раз, а в цикле выполняется метод ПроверитьВывод(), так гораздо быстрее.
yku; BigB; +2 Ответить
56. Shipilov_ivan 14.09.22 19:03 Сейчас в теме
(42)
пОбласть

Спасибо. Ваш метод мне помог решить эту проблему.

Высота рисунка до заполнения текстом с превышающей длиной и после заполнения текстом - оказывалась одинаковая.
43. mark_oilbass 06.06.18 20:45 Сейчас в теме
Подскажите пожалуйста, как быть когда ячейка состоит из нескольких строк? Авто высота делает ячейку сильно большой из за того что она состоит из 11 строк.
44. mark_oilbass 06.06.18 21:30 Сейчас в теме
Решил пока вопрос так: получаю первую строку с первой по последнюю колонку R1C1:R11C62 потом объединяю так как строка разбивается на ячейки.

ИмяОбласти = "R1C1:R1C62";

ОбластьСТоваром = ОбластьТаб.ПолучитьОбласть(ИмяОбласти);
ОбластьСТоваром.Область(ИмяОбласти).Объединить();
45. vasiliy_09_05 6 09.03.19 11:38 Сейчас в теме
Доброго времени суток Дамы и Господа.
Всех Дам с прошедшим праздником 8 Марта :)

Товарищи, нужна Ваша помощь!
Я понимаю, что публикация старая, но я взял ее за основу и у меня никак не выходит "Каменный цветок" :(

Смысл озвучен в публикации -подобрать шрифт под ячейку.

Но при попытке использования любого кода из публикации и комментариев программа возвращает мне не высоту строки по картинке, а среднюю погоду по России :(

Подскажите пожалуйста, что я делаю не так.
Код не выкладываю, та как он большой, выложил обработку

Буду благодарен за любую помощь!!!
Прикрепленные файлы:
BeeStock_ПечатьЭтикеток_4.epf
46. CheBurator 3119 09.03.19 17:32 Сейчас в теме
есть такая штука: ПроверитьВывод() - есои у тебя получается 2 страницы - значит - сильно лишнее, уменьшая шрифт, проверяй повторно до тех пор пока не влезет на 1 стр. Пример на 77 - можно посмотреть здесь - и адаптировать его под 8-ку.. https://infostart.ru/public/181223/
47. vasiliy_09_05 6 09.03.19 20:19 Сейчас в теме
Доброго времени суток.
Спасибо за ответ.
Этот вариант уже предложил многоуважаемый Smilk в 42 посте, но у меня так же, даже если размер шрифта over 100 в приложенной мной обработке так же показывает, что этикетка поместиться на одном листе.
Поэтому и обратился на форум, так как не пойму, то ли упустил нюансы работы с табличного документа или области, то ли затык в формировании конкретно этой обработке.

Обработка данной публикации у меня работает без проблем, а в обработе, приложенной мной не хочет работать ни с одним вариантом, предложенном в этой публикации и комментариях :(
48. Merkalov 8 05.04.19 10:47 Сейчас в теме
Долго бился, давно бы бросил, если бы не знал, что померить гребанную строку всё же возможно.

В итоге пришёл к такому варианту

Функция ПолучитьВысотуСтроки(ТабДок, ОбластьТекста, ОбластьМакета, Текст)    
	
	ОбластьМакета.Параметры.ПоСопрДокументам = Текст;
	
	ВремТабДок = Новый ТабличныйДокумент;
	ВремТабДок.Вывести(ТабДок);
	ВремТабДок.Вывести(ОбластьМакета);
	
	Область = ВремТабДок.Область(ОбластьТекста);
	Рисунок = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);
	Рисунок.Расположить(Область); // вписание рисунка в область, он сам подгоняет размеры под нее
	
	Возврат Рисунок.Высота;
	
КонецФункции
Показать


ВысотаСтроки = ПолучитьВысотуСтроки(ТабДок, "R28C1:R28C1", ОбластьПоСопрДокПерваяСтрока, стрПоСопрДокументам); 


//ОбластьТекста - это Область ячеек, конкретная, на макете, можно взять первую ячейке в строке высота которой вас интересует, я так и
//сделал.
//ОбластьМакета - это Область = Макет.ПолучитьОбласть("ИмяОбласти");
//Текст - выводимый текст который нужно примерить.


И получается, что если высота строки >4 ТОГДА СЛУЧИЛСЯ ПЕРЕНОС, у обычной строки в моём макете высота 3,9, в вашем макете -нужно просто посмотреть в отладчике.

Если ВысотаСтроки > 4 Тогда
Тут решаем проблему со строкой, делим/пилим. У меня получился огромный кусок когда, но задача специфична, поэтому приводить его не вижу смысла.

Суть поста помочь новичкам, ибо я с первого раза не въехал почему у меня ничего не работает, данный пост немного разжует такому же ньюфагу как и я.
49. CheBurator 3119 05.04.19 12:54 Сейчас в теме
а есть ли в 8-ке такая вещь типа
на форме - надпись.
текст в надписи может быть переменной длины в надписб максимально возможным шрифтом.
50. user1086697 17.05.19 17:01 Сейчас в теме
Здравствуйте, определение высоты области через рисунки табличного документа выдает на многих тестах неверный результат. Поэтому долго мучаюсь и не понимаю почему такая проблема
Прикрепленные файлы:
ВысотаРисунки.epf
51. Grivba 14 19.06.19 22:50 Сейчас в теме
Сделал на основе обсуждения.
ПечатнаяФорма.ТабличныйДокумент.Вывести(Область);
//Обработка текста
Для Каждого Параметр из Область.Параметры Цикл
	ТабДок = ПечатнаяФорма.ТабличныйДокумент;
	//ТабДок.Вывести(Область);
	Ячейки = ТабДок.НайтиТекст(Параметр,,, Ложь);
	ОбластьЯчеек = ТабДок.Область(Ячейки.Верх, Ячейки.Лево);
	Если Ячейки.РазмещениеТекста = ТипРазмещенияТекстаТабличногоДокумента.Переносить Тогда
		Если ОбластьЯчеек.АвтоВысотаСтроки Тогда
			Рисунок = ТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
			Рисунок.РазмерКартинки = РазмерКартинки.Растянуть;
			Рисунок.Расположить(ОбластьЯчеек); 
			стВысота = Рисунок.Высота;
			ТабДок.Рисунки.Удалить(Рисунок);
			ОбластьЯчеек.РазмещениеТекста = ТипРазмещенияТекстаТабличногоДокумента.Переносить;
			
			ВремТабДок = Новый ТабличныйДокумент;
			ВремТабДок.Вывести(ТабДок.ПолучитьОбласть(Ячейки.Имя));
			
			ЯчейкиВремТабДок = ВремТабДок.НайтиТекст(Параметр,,, Ложь);
			измОбластьЯчеек = ВремТабДок.Область(ЯчейкиВремТабДок.Верх, ЯчейкиВремТабДок.Лево);
			измОбластьЯчеек.ШиринаКолонки = ОбластьЯчеек.ШиринаКолонки;
			измОбластьЯчеек.ВысотаСтроки = 0;					
			измОбластьЯчеек.АвтоВысотаСтроки = Истина;
			Рисунок = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);
			Рисунок.Расположить(измОбластьЯчеек); 
			Высота = Рисунок.Высота;
			Размер = Ячейки.Шрифт.Размер;
			
			Шрифт = ЯчейкиВремТабДок.Шрифт;
			
			Пока стВысота <= Высота Цикл
				Размер = ЯчейкиВремТабДок.Шрифт.Размер;
				ВремТабДок.Рисунки.Удалить(Рисунок);
				Шрифт = ЯчейкиВремТабДок.Шрифт;
				ЯчейкиВремТабДок.Шрифт = Новый Шрифт(Шрифт,, Размер-1);
				Рисунок = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
				Рисунок.РазмерКартинки = РазмерКартинки.Растянуть;
				Рисунок.Расположить(измОбластьЯчеек); 
				Высота = Рисунок.Высота;
			КонецЦикла;
		    Ячейки.Шрифт = Шрифт;
			ТабДок.Рисунки.Удалить(Рисунок);
		Иначе
			стВысота = 0;
			РазборАдреса = ОбластьЯчеек.Имя;
			
			РезультатАдрес = "";
			
			РазборАдреса = СтрЗаменить(РазборАдреса, ":", "_");
			
			//Ищем буквы
			Для Сч =1 По СтрДлина(РазборАдреса) Цикл
				Знак = Сред(РазборАдреса, Сч,1);
				Если Найти("0123456789",Знак)>0 Тогда
					РезультатАдрес = РезультатАдрес+"_";
				Иначе
					РезультатАдрес = РезультатАдрес+Строка(Знак);
				КонецЕсли;
			КонецЦикла;
			
			мБуквенныхАдресов = СтрРазделить(РезультатАдрес, "_", Ложь);
			РезультатАдрес = "";
			//Ищем цифры
			Для Сч =1 По СтрДлина(РазборАдреса) Цикл
				Знак = Сред(РазборАдреса, Сч,1);
				Если Найти("0123456789",Знак)>0 Тогда
					РезультатАдрес = РезультатАдрес+Строка(Знак);
				Иначе
					РезультатАдрес = РезультатАдрес+"_";
				КонецЕсли;
			КонецЦикла;
				
			мЦифровыхАдресов = СтрРазделить(РезультатАдрес, "_", Ложь);
			
			Если мЦифровыхАдресов.Количество()>2 Тогда
				ЭтоОбласть = Истина;
			Иначе
				ЭтоОбласть = Ложь;
			КонецЕсли;
			
			НачальныйСчетчик = Число(мЦифровыхАдресов.Получить(0));
			КонечныйСчетчик = ?(мЦифровыхАдресов.Количество()>2, Число(мЦифровыхАдресов.Получить(2)), Число(мЦифровыхАдресов.Получить(0)));
			
			Пока НачальныйСчетчик <= КонечныйСчетчик Цикл
				
				ИскомыйАдрес = мБуквенныхАдресов[0]+НачальныйСчетчик+мБуквенныхАдресов[1]+мЦифровыхАдресов[1];
				стВысота = стВысота+ТабДок.ПолучитьОбласть(ИскомыйАдрес).ВыделенныеОбласти[0].ВысотаСтроки;											
				НачальныйСчетчик = НачальныйСчетчик+1;
				
			КонецЦикла;
			
			ВремТабДок = Новый ТабличныйДокумент;
			ВремТабДок.Вывести(ТабДок.ПолучитьОбласть(Ячейки.Имя));
			ЯчейкиВремТабДок = ВремТабДок.НайтиТекст(Параметр,,, Ложь);
			измОбластьЯчеек = ВремТабДок.Область(ЯчейкиВремТабДок.Верх, ЯчейкиВремТабДок.Лево);
			измОбластьЯчеек.ШиринаКолонки = ?(ОбластьЯчеек.ШиринаКолонки=0,Ячейки.ШиринаКолонки, ОбластьЯчеек.ШиринаКолонки);
			измОбластьЯчеек.ВысотаСтроки = 0;					
			измОбластьЯчеек.АвтоВысотаСтроки = Истина;
			Рисунок = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);
			Рисунок.Расположить(измОбластьЯчеек); 
			Высота = Рисунок.Высота;
			Размер = Ячейки.Шрифт.Размер;
			
			Шрифт = ЯчейкиВремТабДок.Шрифт;
			
			Пока стВысота <= Высота Цикл
				Размер = ЯчейкиВремТабДок.Шрифт.Размер;
				ВремТабДок.Рисунки.Удалить(Рисунок);
				Шрифт = ЯчейкиВремТабДок.Шрифт;
				ЯчейкиВремТабДок.Шрифт = Новый Шрифт(Шрифт,, Размер-1);
				Рисунок = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
				Рисунок.РазмерКартинки = РазмерКартинки.Растянуть;
				Рисунок.Расположить(измОбластьЯчеек); 
				Высота = Рисунок.Высота;
			КонецЦикла;
		    Ячейки.Шрифт = Шрифт;
			ТабДок.Рисунки.Удалить(Рисунок);

			
			
			КонецЕсли;
	КонецЕсли;								

КонецЦикла;
Показать


Работает на 100%, когда нет одинаковых параметров, т.е. один и тот же параметр выведен в области используется только 1 раз.
52. Grivba 14 20.06.19 19:37 Сейчас в теме
(51) Ошибка вышла. На тесте с простыми табличными документами все отрабатывало норм.
Перенес на основу..... Все рухнуло.
Пришлось все переделывать.

Цель - в зависимости от длинны теста в параметре (в макете минимум обычного текста, остальное параметры, шаблоны) подбирать максимально близкий размер текста к указанному в макете.

Перенес начало работы с размером текста на Макет (все пытаются это сделать на ТабДоке).
1. Заполняем нужный нам параметр.
	Область.Параметры[ПараметрШаблона.Значение] = СтрокаДанных[НаименованиеКолонки]; 

2. Получаем область ячеек (вдруг область объединенная, у меня такие все)
Ячейка = Область.НайтиТекст(ПараметрШаблона.Значение);
ОбластьЯчеек = Область.Область(Ячейка.Верх, Ячейка.Лево);

3. Узнаем размер ячейки
Рисунок = Область.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Прямоугольник);
Рисунок.Расположить(ОбластьЯчеек); 
стВысота = Рисунок.Высота;                     //высота нашей ячейки 
стШирина = Рисунок.Ширина;                   //Ширина ячейки
Область.Рисунки.Удалить(Рисунок);        //удаляем рисунок

4. Создаем временный ТабДок в который будем выводить текст
ВремТабДок = Новый ТабличныйДокумент;
ВремТабДок.Вывести(Область.ПолучитьОбласть(Ячейка.Имя));

При этом в него переносим Только текст (в ячейке у нас только текст)
6. А далее самое интересное.
В табличный документ в 1-у ячейку (получается - R1C1) мы переносим текст, и после этого устанавливаем ее размеры
При этом высота ячеек установится сама а вот Ширину колонки необходимо рассчитать и в этом поможет стШирина. При этом не забываем что по какой то волшебной причине, ед изм ширины колонок не соответствует ед изм ширины рисунка. (присвоить ширину старой ячейки не выйдет, и старой области ячеек аналогично)

	ЯчейкиВремТабДок = ВремТабДок.НайтиТекст(СтрокаДанных[НаименованиеКолонки],,, Ложь); 
	измОбластьЯчеек = ВремТабДок.Область(ЯчейкиВремТабДок.Верх, ЯчейкиВремТабДок.Лево);
	измОбластьЯчеек.ШиринаКолонки = (стШирина/1.85)-1;          //вычисляем ширину колонки и отнимаем 1 единицу для гарантии.
	измОбластьЯчеек.ВысотаСтроки = 0;					
	измОбластьЯчеек.АвтоВысотаСтроки = Истина;
	измОбластьЯчеек.РазмещениеТекста = ТипРазмещенияТекстаТабличногоДокумента.Переносить;
	Рисунок = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Прямоугольник);
	Рисунок.Расположить(измОбластьЯчеек); 
	Высота = Рисунок.Высота;
	Размер = Ячейка.Шрифт.Размер;

Показать


7. Ну а далее простой перебор

		Шрифт = ЯчейкиВремТабДок.Шрифт;
					
	        Пока стВысота <= Высота Цикл

		Если Размер = 2 Тогда
			Прервать;                      //Защита от дурака
		КонецЕсли;

		Размер = ЯчейкиВремТабДок.Шрифт.Размер;
		ВремТабДок.Рисунки.Удалить(Рисунок);
		Шрифт = ЯчейкиВремТабДок.Шрифт;
		ЯчейкиВремТабДок.Шрифт = Новый Шрифт(Шрифт,, Размер-1);
		Рисунок = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
		Рисунок.РазмерКартинки = РазмерКартинки.Растянуть;
		Рисунок.Расположить(измОбластьЯчеек); 
		Высота = Рисунок.Высота;
	КонецЦикла;

	ОбластьЯчеек.Шрифт = Новый Шрифт(Шрифт,, Размер-1);          //В очередной раз уменьшаем шрифт. 
	Область.Рисунки.Удалить(Рисунок);

Показать


И УСЕ, потом выводим макет в таб док. Надеюсь я не пытаюсь изобрести велосипед.
53. kurator1C 11.09.20 20:42 Сейчас в теме
Прошло 8.5 лет с публикации и начала обсуждения, а воз и ныне там, проблемы всё те же.

У рисунка вписанного в не прямоугольную область (типа строка), например "R5:R5" или "Подвал", верх всегда = 0.
Поэтому пришлось самому разбираться.
В результате, используя принцип увиденный здесь \\Рисунок.Расположить(ОбластьЯчеек),
получил 3 функции, имхо более универсальные:

&НаСервере
Функция ВерхОбластиВмм(пОбласть, пТабДок)
    НадписьВерх = пТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);    
    НадписьВерх.Расположить(пТабДок.Область(СтрЗаменить("R" + пТабДок.Область(пОбласть).Верх + "C1", Символы.НПП, "")));
	НадписьВерх.Имя = "РисВерх";
	
    ВерхОбласти = НадписьВерх.Верх;
    пТабДок.Рисунки.Удалить(НадписьВерх);
    
    Возврат(ВерхОбласти);
КонецФункции // ВерхОбластиВмм

&НаСервере
Функция НизОбластиВмм(пОбласть, пТабДок)
    НадписьНиз = пТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);    
    НадписьНиз.Расположить(пТабДок.Область(СтрЗаменить("R" + пТабДок.Область(пОбласть).Низ + "C1", Символы.НПП, "")));
	НадписьНиз.Имя = "РисВерх";
	
    НизОбласти = НадписьНиз.Верх + НадписьНиз.Высота;
    пТабДок.Рисунки.Удалить(НадписьНиз);
    
    Возврат(НизОбласти);
КонецФункции // ВерхОбластиВмм

&НаСервере
Функция ВысотаОбластиВмм(пОбласть, пТабДок)
    Возврат НизОбластиВмм(пОбласть, пТабДок) - ВерхОбластиВмм(пОбласть, пТабДок);
КонецФункции  // ВысотаОбластиВмм
Показать
54. kurator1C 11.09.20 20:54 Сейчас в теме
Ну и до кучи высота всего табличного документа:

&НаСервере
Функция ВысотаТаДокаВмм(мТабДок)
	Рис = мТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);
	
	ПослСтрока = мТабДок.ВысотаТаблицы;
	
	Рис.Расположить(мТабДок.Область(СтрЗаменить("R" + (ПослСтрока) + "C1", Символы.НПП, "")));
	Рис.Имя = "РисунокДляПодсчетаВысоты";
	Рез = мТабДок.Рисунки.РисунокДляПодсчетаВысоты.Верх + мТабДок.Рисунки.РисунокДляПодсчетаВысоты.Высота;
	
	ТабДок.Рисунки.Удалить(Рис);
	Возврат Рез;
КонецФункции  // ВысотаТаДокаВмм
Показать


З.Ы. Область (первый параметр в первых трёх функциях) задаётся строкой. Сделано так, чтобы функции можно было вызывать и с клиента и с сервера.
55. Angel_19 6 14.09.21 12:00 Сейчас в теме
От масштаба зависит....
Смотришь в масштабе 100% - переносит, масштаб 125% - не переносит, и еще много места.
Печатаем на бумагу - получаем вариант как с масштабом 125% - не переносит и еще есть свободное место.
57. Serg2000mr 311 22.05.23 01:27 Сейчас в теме
(55) Согласен, метод с картинками ненадежный.


&НаКлиенте
Процедура ПоказатьДок(Команда)
		
	ТабДок = ПоказатьДокНаСервере();
	ТабДок.Показать();
	
КонецПроцедуры



&НаСервере
Функция ПоказатьДокНаСервере()
	
	НачСимволов = 10;
	
	Шрифт = Новый Шрифт("Arial", 10);
	
	ТабДок = Новый ТабличныйДокумент;
	ОбластьВсе = ТабДок.Область(1, 1, 255, 1);
	ОбластьВсе.ШиринаКолонки = 100;
	ОбластьВсе.РазмещениеТекста = ТипРазмещенияТекстаТабличногоДокумента.Переносить;
	ОбластьВсе.Шрифт = Шрифт;
	
	Строка = "A B C D E F G H I J K L M N O P R S T U V W X Y Z";
	Массив = СтрРазделить(Строка, " ", Ложь);	
	
	Для НомерСимвола = 0 По Массив.ВГраница() Цикл
		выбРяд = НомерСимвола + 1;
		выбСимвол = Массив[НомерСимвола];
		
		Область = ТабДок.Область(выбРяд, 1);
		Область.Текст = СтроковыеФункцииКлиентСервер.СформироватьСтрокуСимволов(выбСимвол, НачСимволов);
		
		ВысотаДо = ПолучитьВысотуСтроки(ТабДок, "R" + выбРяд + "C1");
		
		Для Сч = 1 По 1000 Цикл
			
			Область.Текст = СтроковыеФункцииКлиентСервер.СформироватьСтрокуСимволов(выбСимвол, НачСимволов + Сч);
			
			ВысотаПосле = ПолучитьВысотуСтроки(ТабДок, "R" + выбРяд + "C1");
			
			Если ВысотаПосле > ВысотаДо Тогда
                                //откатываем длину строки до того, как она вызвала перенос
				Область.Текст = Лев(Область.Текст, СтрДлина(Область.Текст) - 1);
				Сообщить(Область.Текст);
				Прервать;
			КонецЕсли;
			
		КонецЦикла;
		
                ТабДок.Область(выбРяд, 2).Текст = "СтрДлина: " + СтрДлина(Область.Текст); 
		
	КонецЦикла;
		
	Возврат ТабДок;
	
КонецФункции

&НаСервере
Функция ПолучитьВысотуСтроки(ТабДок, ОбластьТекста)    
    
    ВремТабДок = Новый ТабличныйДокумент;
    ВремТабДок.Вывести(ТабДок);
    
    Область = ВремТабДок.Область(ОбластьТекста);
    Рисунок = ВремТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Текст);
    Рисунок.Расположить(Область); // вписание рисунка в область, он сам подгоняет размеры под нее
    
    Возврат Рисунок.Высота;
    
КонецФункции
Показать


Данный код должен вывести строки с разным текстом, но одинаковой длины. Можно убедиться, насколько все вкривь и вкось
Оставьте свое сообщение