Как вычислить высоту строки таблицы.

 

У ячеек таблиц в 1С есть свойство контроль, там можно выбрать "Переносить" и тогда не помещающийся по ширине текст будет автоматически переноситься на следующие строки в ячейке. Если высоту строки установить в "Авто", высота строки будет автоматически изменяться в зависимости от высоты введенного текста. Т.е. строки в отчёте получатся самопереносящимися и самораздвигающимися.

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

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

Таб = СоздатьОбъект("Таблица");
Для Х = 1 По 255 Цикл
  Таб.Область(Х, 1).Текст = СтрЗаменить(Формат("", "С500"), " ", Симв(Х))
КонецЦикла;
Таб.Область(1, 1, 255, 1).Контроль(4);
Таб.Область(1, 1).ШиринаСтолбца(100);
Таб.Показать();

Затем вручную сократил текст во всех 255 строках до той длины, при которой текст помещается в одной строке. Сохранил таблицу в файл.

Таб = СоздатьОбъект("Таблица");
Таб.Открыть("МояТаблица.mxl");
Сп = СоздатьОбъект("СписокЗначений");
Для Х=1 По 255 Цикл
  Ч = СтрДлина(Таб.Область(Х, 1).Текст);
  Сп.ДобавитьЗначение(?(Ч = 0, 0, Окр(100/(Ч + 0.5), 3)));
КонецЦикла;
ЗначениеВФайл("Arial8.txt", Сп);

Вопрос "Что это за 0.5?" возникает? А это те пол-символа, которые среднестатистически ещё могли бы влезть в заданную ширину. Имя файла выбрано таким не случайно, оно содержит название и размер шрифта в "раздвижных" ячейках таблицы. Т.е. при использовании другого шрифта или размера вам придётся проделать всю эту работу ещё раз.

Чтобы избежать возможных ошибок, строки желательно раздвигать программно, т.е. высоту строки не устанавливать в "Авто". Поэтому необходимо также узнать высоту "однострочной" строки для текущего шрифта и приращение этой высоты, когда текст разбивается на две строки. Это я сделал просто, сначала посмотрел высоту "однострочной" строки (11.25), потом "двухстрочной" (21.75), приращение получилось - 10.5. Значения 11.25 и 10.5 имеет смысл добавить в наш список соответственно 256 и 257 значениями.

Теперь у нас есть всё необходимое для вычисления высоты строки.

Функция ПолучитьВысотуСтроки(Стр, ШиринаСтолбца, Шрифт)
  Длина = 0;
  Пробел = 0;
  Количество = 1;
  Для Х = 1 По СтрДлина(Стр) Цикл
    Код=КодСимв(Сред(Стр, Х, 1));
    Если Код = 32 Тогда Пробел = Длина КонецЕсли;
    Длина = Длина + Шрифт.ПолучитьЗначение(Код);
    Если Длина > ШиринаСтолбца Тогда
      Длина = ?(Пробел = 0, 0, Длина - Пробел);
      Количество = Количество + 1;
      Пробел = 0;
    КонецЕсли;
  КонецЦикла;
  Возврат Шрифт.ПолучитьЗначение(256) + (Количество - 1) * Шрифт.ПолучитьЗначение(257);
КонецФункции

Для проверки сделайте таблицу, в первой колонке которой, заполните текстом произвольной длины 10 строк. Установите контроль у заполненных ячеек в "Переносить". Сохраните с именем "ТестоваяТаблица.mxl".

Процедура Тест()
  Таб = СоздатьОбъект("Таблица");
  Таб.Открыть("ТестоваяТаблица.mxl");
  ШиринаСтолбца = Таб.Область(1, 1).ШиринаСтолбца();
  Шрифт = ЗначениеИзФайла("arial8.txt");
  Для Х = 1 По 10 Цикл
    ВысотаСтроки = ПолучитьВысотуСтроки(Таб.Область(Х, 1).Текст, ШиринаСтолбца, Шрифт);
    Таб.Область(Х, 1).ВысотаСтроки(ВысотаСтроки);
  КонецЦикла;
  Таб.Показать();
КонецПроцедуры

Такое вычисление оказывается весьма точным, наткнуться на "лишнюю" или "невлезшую" строку оказывается почти нереальным.

В заключении, хочу предложить всем, взявшим методику на вооружение, организовать обмен файликами ширин символов. Присылайте мне, буду выкладывать здесь. А для затравки выложу свой тестовый Arial8.txt :))


Arial 8pt normal by avb

Arial 9pt normal by wert
Arial 9pt bold by wert
Код функции, учитывающий разделители строк, by wert

Times New Roman 8pt normal by avb
Times New Roman 9pt normal by avb
Times New Roman 10pt normal by avb

Arial 10pt normal by Козлов Виктор




Hosted by uCoz