Функция ПостроитьШрифт(комШрифт)
Возврат Новый Шрифт(
комШрифт.Name,
комШрифт.Size,
комШрифт.Bold,
комШрифт.Italic,
комШрифт.Underline,
комШрифт.StrikeThrough,
комШрифт.Scaling);
КонецФункции
Функция ПостроитьРамкуЯчейки(комРамка, чисОтступ)
Если комРамка.Visible Тогда
чисСтиль=комРамка.LineStyle;
рТолщина=1;
Если чисСтиль=1 Тогда
рТипЛинии=ТипЛинииЯчейкиТабличногоДокумента.Сплошная;
// если надо, толщину можно сделать подробнее по комРамка.LineWidth
ИначеЕсли чисСтиль=2 Тогда
рТипЛинии=ТипЛинииЯчейкиТабличногоДокумента.Точечная;
ИначеЕсли чисСтиль=5 Тогда
рТипЛинии=ТипЛинииЯчейкиТабличногоДокумента.РедкийПунктир;
ИначеЕсли чисСтиль=6 Тогда
рТипЛинии=ТипЛинииЯчейкиТабличногоДокумента.ЧастыйПунктир;
ИначеЕсли чисСтиль=7 Тогда
рТипЛинии=ТипЛинииЯчейкиТабличногоДокумента.Двойная;
Иначе
рТипЛинии=ТипЛинииЯчейкиТабличногоДокумента.БольшойПунктир;
КонецЕсли;
рОтступ=(чисОтступ>0); // пока так
Возврат Новый Линия(рТипЛинии, рТолщина, рОтступ);
Иначе
Возврат Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.НетЛинии);
КонецЕсли;
КонецФункции
Функция ПолучитьВыравнивание(чисВыравнивание)
// wdListLevelAlignCenter - 1 – По центру wdListLevelAlignLeft - 0 – По левому краю wdListLevelAlignRight - 2 – По правому краю
Если чисВыравнивание=1 Тогда
Возврат ГоризонтальноеПоложение.Центр;
ИначеЕсли чисВыравнивание=2 Тогда
Возврат ГоризонтальноеПоложение.Право;
ИначеЕсли чисВыравнивание=3 Тогда
Возврат ГоризонтальноеПоложение.ПоШирине;
Иначе
Возврат ГоризонтальноеПоложение.Лево;
КонецЕсли;
КонецФункции
Процедура ВывестиТаблицу(комВорд, комТаблица, табДокумент, текСтрока)
рСантиметр=6.25;
рСимвол7=Символ(7);
квоСтрок=комТаблица.Rows.Count;
квоКолонок=комТаблица.Columns.Count;
Для стркДок=1 По квоСтрок Цикл
стлб=1;
Для стлбДок=1 По квоКолонок Цикл
Попытка
комЯчейка=комТаблица.Cell(стркДок,стлбДок);
Исключение
Продолжить;
КонецПопытки;
квоЯчеекМхл=Окр(комВорд.PointsToCentimeters(комЯчейка.Width*4),0,РежимОкругления.Окр15как20); // 1 см. это 4 ячейки мхл
рОбластьЯчейки=табДокумент.Область(текСтрока,стлб,текСтрока,стлб+квоЯчеекМхл-1);
рОбластьЯчейки.Объединить();
Если комЯчейка.FitText или комЯчейка.WordWrap Тогда // пока так
рОбластьЯчейки.РазмещениеТекста=ТипРазмещенияТекстаТабличногоДокумента.Переносить;
Иначе
рОбластьЯчейки.РазмещениеТекста=ТипРазмещенияТекстаТабличногоДокумента.Авто;
КонецЕсли;
рДиапазонЯчейки=комЯчейка.Range;
//
рТекстДиапазонаЯчейки=СокрЛП(рДиапазонЯчейки.Text);
Если Прав(рТекстДиапазонаЯчейки,1)=рСимвол7 Тогда
рТекстДиапазонаЯчейки=Лев(рТекстДиапазонаЯчейки,СтрДлина(рТекстДиапазонаЯчейки)-1);
КонецЕсли;
рОбластьЯчейки.Текст=рТекстДиапазонаЯчейки;
//
рОбластьЯчейки.Шрифт=ПостроитьШрифт(рДиапазонЯчейки.Font);
// на практике удобнее оставлять автовысоту, но иногда может понадобиться:
//рОбластьЯчейки.АвтоВысотаСтроки=Ложь;
//рОбластьЯчейки.ВысотаСтроки=рСантиметр*Окр(комВорд.PointsToCentimeters(комЯчейка.Height),0,РежимОкругления.Окр15как20);
рОбластьЯчейки.ГоризонтальноеПоложение=ПолучитьВыравнивание(рДиапазонЯчейки.ParagraphFormat.Alignment);
// отступ - в пунктах, при необходимости требуется пересчёт!
//Если рОбластьЯчейки.ГоризонтальноеПоложение=ГоризонтальноеПоложение.Лево Тогда
// рОбластьЯчейки.Отступ=комЯчейка.LeftPadding;
//ИначеЕсли рОбластьЯчейки.ГоризонтальноеПоложение=ГоризонтальноеПоложение.Право Тогда
// рОбластьЯчейки.Отступ=комЯчейка.RightPadding;
//КонецЕсли;
вертВыравнивание=комЯчейка.VerticalAlignment;
Если вертВыравнивание=1 Тогда
рОбластьЯчейки.ВертикальноеПоложение=ВертикальноеПоложение.Центр;
ИначеЕсли вертВыравнивание=3 Тогда
рОбластьЯчейки.ВертикальноеПоложение=ВертикальноеПоложение.Низ;
Иначе
рОбластьЯчейки.ВертикальноеПоложение=ВертикальноеПоложение.Верх;
КонецЕсли;
рОбластьЯчейки.ГраницаСверху=ПостроитьРамкуЯчейки(комЯчейка.Borders(-1),комЯчейка.Borders.DistanceFromTop);
рОбластьЯчейки.ГраницаСлева=ПостроитьРамкуЯчейки(комЯчейка.Borders(-2),комЯчейка.Borders.DistanceFromLeft);
рОбластьЯчейки.ГраницаСнизу=ПостроитьРамкуЯчейки(комЯчейка.Borders(-3),комЯчейка.Borders.DistanceFromBottom);
рОбластьЯчейки.ГраницаСправа=ПостроитьРамкуЯчейки(комЯчейка.Borders(-4),комЯчейка.Borders.DistanceFromRight);
стлб=стлб+квоЯчеекМхл;
КонецЦикла;
текСтрока=текСтрока+1;
КонецЦикла;
КонецПроцедуры
// Основная функция
Функция ВывестиДокументВордВМоксель(ИмяФайла)
Попытка
// Для пересчётов использовать комВорд.CentimetersToPoints(ЧислоСМ) и комВорд.PointsToCentimeters(ЧислоПунктов)
рСантиметр=6.25; // в средних символах шрифта (при необходимости пересчитывать по рДиапазон.CharacterWidth - ширина символов, константа WdCharacterWidth
рШиринаСтраницы=75; // эмпирически, довести до ума с учётом //сообщить("стран ширина "+стран.PageWidth+", высота "+стран.PageHeight); // в пунктах, работает
// Типовые настройки документа Ворд:
// 1.25 до номера (отступ первой строки) и 1.89 табуляция (до основного текста)
// Размеры листа А4 в сантиметрах: 21х29.7
комВорд=Новый COMОбъект("Word.Application");
рПодтверждатьПреобразования=Истина;
рТолькоЧтение=Истина;
комДокумент=комВорд.Documents.Open(ИмяФайла, рПодтверждатьПреобразования, рТолькоЧтение);
#Область Проверки
комСтраница=комДокумент.PageSetup;
Если комСтраница.TextColumns.Count>1 Тогда
Сообщить("Текущая версия не обрабатывает многоколонные документы!");
комДокумент.Close(Ложь); // без сохранения
комВорд.Quit(0);
комВорд="";
Возврат Неопределено;
КонецЕсли;
рШиринаСтраницыВорда=Окр(комВорд.PointsToCentimeters(комСтраница.PageWidth),2);
рВысотаСтраницыВорда=Окр(комВорд.PointsToCentimeters(комСтраница.PageHeight),2);
Если НЕ ((20<=рШиринаСтраницыВорда и рШиринаСтраницыВорда<=22) и (28<=рВысотаСтраницыВорда и рВысотаСтраницыВорда<=30)) Тогда
Сообщить("Текущая версия не обрабатывает размеры страницы, отличающиеся от А4!");
комДокумент.Close(Ложь); // без сохранения
комВорд.Quit(0);
комВорд="";
Возврат Неопределено;
КонецЕсли;
#КонецОбласти
// подготовка вывода таблиц
мКомТаблиц=Новый Массив;
Для каждого комТаблица Из комДокумент.Tables Цикл
мКомТаблиц.Добавить(Новый Структура("Начало,Конец,Таблица",комТаблица.Range.Start,комТаблица.Range.End,комТаблица));
КонецЦикла;
#Область ПодготовкаВыводаНумерованныхСписков
// можно, конечно, рСписок.ConvertNumbersToText(ТипНомера) - но это не лучший выход, и это изменение документа
//
соотПараграфовСписков=Новый Соответствие;
Для каждого рСписок Из комДокумент.Lists Цикл // свойство комДокумент.Lists.Count ситуационно-зависимое, не применять!
ОбработкаПрерыванияПользователя();
// рЛист.CountNumberedItems();
Для каждого рПараграфСписка Из рСписок.ListParagraphs Цикл
ОбработкаПрерыванияПользователя();
рФорматСписка=рПараграфСписка.Range.ListFormat;
рТипСписка=рФорматСписка.ListType; // WdListType
Если рТипСписка=0 или рТипСписка=2 или рТипСписка=6 Тогда
// ненумерованные и bullet игнорируем
Иначе
// заниматься иерархией с проверкой погружения (рФорматСписка.ListLevelNumber) не будем, нам достаточно проверить так:
рПредставлениеПункта=СокрЛП(рФорматСписка.ListString);
// выравнивание смотрим по первой позиции уровней (хотя можно перебирать, смотреть по позиции или по NumberFormat)
Попытка рВыравнивание=рФорматСписка.ListTemplate.ListLevels.Item(0).Alignment Исключение рВыравнивание=0 КонецПопытки;
// из первого уровня также можно брать NumberPosition - отступ,если будет надо; он в пунктах, поэтому тоже может потребоваться пересчёт!
Если СтрРазделить(рПредставлениеПункта,".",Ложь).Найти(рФорматСписка.ListValue)=0 Тогда
Сообщить("Внимание! Нарушение нумерации списка для "+рПредставлениеПункта+"!");
КонецЕсли;
// фиксируем для дальнейшего вывода
соотПараграфовСписков.Вставить(рПараграфСписка.Range.Start, Новый Структура("Номер,Выравнивание",рПредставлениеПункта,рВыравнивание));
КонецЕсли;
КонецЦикла;
КонецЦикла;
#КонецОбласти
// FitTextWidth для диапазонов НЕ используем, в т.ч. для комДокумент.Range()
т=Новый ТабличныйДокумент;
#Область ПодготовкаТабДокумента
// устанавливаем ширины рабочих колонок А4
стлб=1;
Пока Истина Цикл
т.Область(1,стлб,1,стлб).ШиринаКолонки=Окр(рСантиметр/4,2);
стлб=стлб+1;
Если т.ШиринаТаблицы>рШиринаСтраницы Тогда
Прервать;
КонецЕсли;
КонецЦикла;
#КонецОбласти
#Область ВыводОсновныхДанных
стрк=1;
рПравыйКрайнийСтолбец=т.ШиринаТаблицы;
рИдётТаблица=Ложь;
Для каждого рПараграф Из комДокумент.Paragraphs Цикл
ОбработкаПрерыванияПользователя();
// к сожалению, рПараграф.ListNumberOriginal использовать ненадёнжно
рДиапазон=рПараграф.Range;
рТекстДиапазона=рДиапазон.Text;
рНачалоДиапазона=рДиапазон.Start;
рКонецДиапазона=рДиапазон.End;
#Область ВыводПозицииНумерованногоСписка
// использовать рДиапазон.ListFormat.ListLevelNumber и рДиапазон.ListFormat.ListValue не рекомендуется
рПараграфСписка=соотПараграфовСписков.Получить(рНачалоДиапазона);
Если рПараграфСписка=Неопределено Тогда
рПредставлениеПункта="";
рВыравнивание=0;
Иначе
рПредставлениеПункта=СокрЛП(рПараграфСписка.Номер);
рВыравнивание=рПараграфСписка.Выравнивание;
КонецЕсли;
Если ПустаяСтрока(рПредставлениеПункта) Тогда
// нумерации списка нет
рГраницаОбластиПараграфа=1;
Иначе // надо выводить № пункта списка
рОбластьНомера=т.Область(стрк,1,стрк,4);
рОбластьНомера.Объединить();
рОбластьНомера.Текст=рПредставлениеПункта;
рОбластьНомера.Шрифт=ПостроитьШрифт(рДиапазон.Font); // или рДиапазон.ListStyle.Font, если они разные
рОбластьНомера.ГоризонтальноеПоложение=ПолучитьВыравнивание(рВыравнивание);
рОбластьНомера.ВертикальноеПоложение=ВертикальноеПоложение.Верх; // по умолчанию
рГраницаОбластиПараграфа=5;
КонецЕсли;
#КонецОбласти
комТаблица=Неопределено;
Для каждого знч Из мКомТаблиц Цикл
Если знч.Начало<=рНачалоДиапазона и рНачалоДиапазона<=знч.Конец
и знч.Начало<=рКонецДиапазона и рКонецДиапазона<=знч.Конец
Тогда // можно было бы рДиапазон.InRange(комТаблица.Range), но оно медленнее
комТаблица=знч.Таблица; Прервать;
КонецЕсли;
КонецЦикла;
Если комТаблица=Неопределено Тогда
рИдётТаблица=Ложь;
#Область ВыводОбычногоАбзаца
// для параграфа и Диапазон.ParagraphFormat, при необходимости:
// рПараграф.FirstLineIndent - Возвращает или устанавливает значение в пунктах для первой линии или отступа.
// рПараграф.LeftIndent - Отступ слева в пунктах.
// рПараграф.RightIndent - Отступ справа в пунктах.
// рПараграф.LineSpacing - Междустрочный интервал.
// рПараграф.PageSetup.PageWidth аналогично ширине документа в целом, можно не заморачиваться
рОбластьПараграфа=т.Область(стрк,рГраницаОбластиПараграфа,стрк,рПравыйКрайнийСтолбец);
рОбластьПараграфа.Объединить();
рОбластьПараграфа.Текст=рТекстДиапазона;
рОбластьПараграфа.Шрифт=ПостроитьШрифт(рДиапазон.Font); // а не рПараграф.Style.Font!
рОбластьПараграфа.ГоризонтальноеПоложение=ПолучитьВыравнивание(рПараграф.Alignment); // или лучше рДиапазон.ParagraphFormat.Alignment?
рОбластьПараграфа.ВертикальноеПоложение=ВертикальноеПоложение.Верх; // по умолчанию
рОбластьПараграфа.РазмещениеТекста=ТипРазмещенияТекстаТабличногоДокумента.Переносить; // по умолчанию
#КонецОбласти
стрк=стрк+1;
Иначе
Если не рИдётТаблица Тогда // выводим таблицу, а далее пропускаем все входящие в неё диапазоны, и идём до её конца
ВывестиТаблицу(комВорд, комТаблица, т, стрк);
КонецЕсли;
рИдётТаблица=Истина;
Продолжить; // стрк уже "промотана" до нужной позиции пост-таблицы
КонецЕсли;
КонецЦикла;
#КонецОбласти
комДокумент.Close(Ложь); // без сохранения
комВорд.Quit(0);
комВорд="";
Возврат т;
Исключение
Сообщить("ВывестиДокументВордВМоксель, общая ошибка: "+ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
КонецФункции