HelpF.pro

Работа с MS Word через OLE

В качестве примера использования можно указать вот такую ситуацию: в зависимости от типа клиента (договора, документа и т.п) формируются разные тексты договоров с разным количеством таблиц. В реальности, конечно должены использоваться и макет и описанные здесь динамические механизмы.
В моем примере я заранее создал новый пустой документ.
Тестировалось на Office 2007.
Код 1C v 8.х
 
// "ПутьКФайлу" - строка. Полное имя файла в формате MSWord.
// "Ссылка" - ДокументСсылка (в моем случае - счет).
Процедура ВыполнитьОбработку() Экспорт

Попытка
Объект = ПолучитьCOMОбъект(ПутьКФайлу);
// Покажем документ. Для красоты.
Объект.Application.Visible = 1;
Word = Объект.Application;

Doc = Объект.Application.Documents(1);
Doc.Activate();

// Готовим переменную в которой будет содержимое нашего документа
// (текст, таблицы и проч).
Text = Word.S_election;

// Очистим документ
// Ctrl-A
Text.WholeStory();
// Del
Text.Delete(1, 1);
// Двигаемся на 3 строки ниже. Документ пустой, поэтому добавляем
// строки "Переводами коретки"

Text.TypeText(Символы.ВК);
Text.TypeText(Символы.ВК);
Text.TypeParagraph(); // другой вариант того же действия
// Выводим текст.
Text.TypeText("Обычный текст, набранный первую очередь");

// Курсор в конце строки
// Эмулируем нажатие Shift+Home - выделяем строку
Text.HomeKey(, 1);
// Форматирование выделенной строки
Text.Font.Bold = 9999998;
Text.Font.Size = 14;
Text.Font.Name = "Verdana";

// Сдвигаем курсор. Сдвинуть курсор по строкам возможно, только,
// если эти строки уже содержат текст, иначе ничего не произойдет.
Text.MoveUp(,2); // вверх на 2 строки
//Word.S_election.MoveDown(,числострок); // вниз
//Word.S_election.MoveLeft(,числострок); // влево
//Word.S_election.MoveRight(,числострок);// вправо

// Добавление текста. Текст выводится начиная с текщей позиции
// курсора.
Text.HomeKey(, 1);
Text.TypeText("Обычный текст, набранный во вторую очередь");

Text.MoveDown(,1); // вниз на 2 строки
Text.EndKey(); // в конец строки
Text.TypeParagraph(); // и в начало следующей строки

// Очищаем форматирование
Text.ClearFormatting();
// Добавляем таблицу.
// Получаем текущую позицию курсора
Position = Text.Range();

// Параметры: Позиция, число строк, число колонок,
// последние 2 параметра отвечают за автоподбор высоты и отображение
// границ таблицы
Table = Doc.Tables.Add(Position, 1, 6, 1, 2);

// Устанавливаем ширину колонок
Table.Columns(1).PreferredWidth=10;
Table.Columns(2).PreferredWidth=50;
Table.Columns(3).PreferredWidth=10;
Table.Columns(4).PreferredWidth=10;
Table.Columns(5).PreferredWidth=10;
Table.Columns(6).PreferredWidth=10;

// Задаем заголовки колонок
Row1=Table.Rows(1);
Row1.Cells(1).Range.Text="№ п/п";
Row1.Cells(2).Range.Text="Наименование";
Row1.Cells(4).Range.Text="Кол-во";
Row1.Cells(3).Range.Text="Ед. изм.";
Row1.Cells(5).Range.Text="Цена,руб.";
Row1.Cells(6).Range.Text="Сумма,руб.";

// Построчно выводим содержимое таблицы Товары
НомерСтроки = 1;
Для каждого СтрокаТовары Из Ссылка.Товары Цикл
Row=Table.Rows.Add();
Row.Cells(1).Range.Text=НомерСтроки;
// Выравнивание по левому краю
Row.Cells(1).Range.ParagraphFormat.Alignment = 1;
// В качестве текста можно передать только значение "простого" формата
// все агрегатные объекты, переданные как текст, что нормально для платформы 1с
// вызовут исключение.
Row.Cells(2).Range.Text=СтрокаТовары.Номенклатура.Наименование
+?(ЗначениеЗаполнено(СтрокаТовары.ХарактеристикаНоменклатуры),
" ("+СтрокаТовары.ХарактеристикаНоменклатуры+")","");
Row.Cells(4).Range.Text=Строка(СтрокаТовары.Количество);
Row.Cells(4).Range.ParagraphFormat.Alignment = 1;
Row.Cells(3).Range.Text=?(ЗначениеЗаполнено(СтрокаТовары.Номенклатура.БазоваяЕдиницаИзмерения)
,СтрокаТовары.Номенклатура.БазоваяЕдиницаИзмерения.Наименование,"-");
Row.Cells(3).Range.ParagraphFormat.Alignment = 1;
Row.Cells(5).Range.Text=Формат(СтрокаТовары.Цена,"ЧДЦ=2");
Row.Cells(5).Range.ParagraphFormat.Alignment = 1;
Row.Cells(6).Range.Text=Формат(СтрокаТовары.Сумма,"ЧДЦ=2");
Row.Cells(6).Range.ParagraphFormat.Alignment = 1;
НомерСтроки=НомерСтроки+1;
КонецЦикла;

// Задаем форматирование первой строки
// Если сделать это сразу, то все новые строки таблицы будут
// формироваться с тем же форматом
Row1.Range.Font.Bold = 9999998;
Row1.Range.Font.Size = 14;
Row1.Range.Font.Name = "Verdana";
Row1.Range.ParagraphFormat.Alignment = 1;

// Последняя строка...
Row = Table.Rows.Add();
Row.Range.Font.Bold = 9999998;
Row.Cells(1).Range.Text="Итого:";
Исключение
Doc.Save();
Сообщить(ОписаниеОшибки());
Объект.Application.Quit();
Объект = Неопределено;
КонецПопытки;

Попытка // эта конструкция выдает исключительную ситуацию, но при этом
// результат все-равно работает))
// объединяем ячейки в конце таблицы
Table.cell(НомерСтроки+1, 1).Merge(Table.cell(НомерСтроки+1, 5));
Исключение
КонецПопытки;

Попытка
Row.Cells(1).Range.ParagraphFormat.Alignment = 3;
Row.Cells(2).Range.Text=Формат(Ссылка.Товары.Итог("Сумма"), "ЧДЦ=2");
Row.Cells(2).Range.ParagraphFormat.Alignment = 1;

Doc.Save();
Объект.Application.Quit();
Объект = Неопределено;
Исключение
Doc.Save();
Сообщить(ОписаниеОшибки());
Объект.Application.Quit();
Объект = Неопределено;
КонецПопытки;
КонецПроцедуры


Часто при создании документа из макета используют метод замены кусков текста. В примере представлен другой вариант выполнения того же действия - с использованием закладок. Также представлен пример построения нумерованного списка, вставки картинки, настройки ее параметров.
Пример использования описанных возможностей прост. При формировании коммерческого предложения бывает необходимо описать список условий, добавить изображение образца продукции.
Для отображения закладок включите эту опцию в настройках вашего Word'а.
В моем примере я заранее создал новый пустой документ, путь к документу и картинке прописан в тексте. Не забудте указать свои пути.
Код 1C v 8.х
 Процедура ВыполнитьОбработку() Экспорт

Попытка

//Объект = ПолучитьCOMОбъект(ПутьКФайлу);
Объект = ПолучитьCOMОбъект("C:\Users\NKrylov\Desktop\Тест.docx");
// Покажем документ.
Объект.Application.Visible = 1;
Word = Объект.Application;

ThisDocument = Word.Documents(1);
ThisDocument.Activate();

// Отключим проверку грамматики и вывод информации о грамматических ошибках.
ThisDocument.GrammarChecked=0;
ThisDocument.ShowGrammaticalErrors=0;

// Готовим переменную в которой будет содержимое документа (текст).
S_election = Word.S_election;

// Очистим документ
// Ctrl-A
S_election.WholeStory();
// Del
S_election.Delete(1, 1);

// Уменьшим междустрочный интервал.
S_election.ParagraphFormat.LineSpacingRule = 0; // 1 по умолчанию
S_election.ParagraphFormat.SpaceAfter = 0; // 10 по умолчанию

// Разметим документ. Это можно сделать и предварительно в макете
ThisDocument.Bookmarks.Add("Закладка1", S_election.Range());
S_election.TypeParagraph();
S_election.TypeText("34r3 ");
S_election.HomeKey(, 1);
ThisDocument.Bookmarks.Add("Закладка2", S_election.Range());
S_election.EndKey();
S_election.TypeParagraph();
ThisDocument.Bookmarks.Add("Закладка3", S_election.Range());
S_election.TypeParagraph();
ThisDocument.Bookmarks.Add("Закладка4", S_election.Range());
S_election.EndKey();

// Так можно работать с текстом только в конкреной области документа - это и будет замена метода Find-Execute.
ThisDocument.Bookmarks("Закладка3").Range.S_elect();
S_election = Word.S_election;

Bookmark = ThisDocument.Bookmarks("Закладка3");
Table = ThisDocument.Tables.Add(Bookmark.Range(),1,5,1,2);
Table.Rows(1).Cells(1).Range.Text = 1;
Table.Rows(1).Cells(2).Range.Text = 2;
Table.Rows(1).Cells(3).Range.Text = 3;
Table.Rows(1).Cells(4).Range.Text = 4;
Table.Rows(1).Cells(5).Range.Text = 5;

// После вывода таблицы, появится "лишняя строка", удалим ее
// в результате курсор встанет в область закладки 4
S_election.MoveDown(, 1);
S_election.Delete(1, 1);

// Этот текст будет выведен не с последней позиции курсора, а в активной области.
// в данном случае - в области закладки 2
ThisDocument.Bookmarks("Закладка2").Range.S_elect();
S_election = Word.S_election;
Text = S_election.Range.Text;
S_election.TypeText(Text + " sdcsdcs");
// При выводе текста закладка "сбросилась". Восстановим.
// "Победить" эту проблему я так и не смог((
// Хотя на практике, закладка больше и не понадобится.
// Дважды выводить текст в одну и ту же область - не имеет смысла.
S_election.HomeKey(, 1);
ThisDocument.Bookmarks.Add("Закладка2", S_election.Range());
S_election.EndKey();

// В области закладки 4 сформируем нумерованный список
ThisDocument.Bookmarks("Закладка4").Range.S_elect();
S_election = Word.S_election; // активная (выделенная) область будет начинаться
// от закладки 4)

// Добавим текст "для опытов"
// 1
S_election.TypeText("sdcsdcsdcsdc");
S_election.TypeParagraph();
// 2
S_election.TypeText("sdcsdcsdcsdc");
S_election.TypeParagraph();
// 3
S_election.TypeText("sdcsdcsdcsdc");
S_election.TypeParagraph();
// 4
S_election.TypeText("sdcsdcsdcsdc");
S_election.TypeParagraph();
// Выделяем введенный текст
S_election.MoveUp(,4,1);

// Настроим шаблон объекта галереи списков
// Галереи списков бывают несккольких типов, 2 - нумерованные списки
ListTemplate = Word.ListGalleries(2).ListTemplates(1).ListLevels(1);
// Формат нумератора списка - точка после символа нумерации
ListTemplate.NumberFormat = "%1.";
// стиль нумератора - арабские цифры
ListTemplate.NumberStyle = 0; // wdListNumberStyleArabic
// 4 - маленькие латинские буквы.
// 2 - маленькие римские цифры.
// 58- меленькие русские буквы.
// Font = Template.Font; // можно указать форматирование текста списка

// Применим шаблон к выделенному тексту
S_election.Range.ListFormat.ApplyListTemplateWithLevel( Word.ListGalleries(2).ListTemplates(1));

// Перейдем в конец текста
S_election.EndKey(6);

// Добавим картинку
// Параметры: путь к файлу, создавать ссылку на картинку, сохранять с файлом
Picture = S_election.InlineShapes.AddPicture("C:\Users\NKrylov\Desktop\Новый.bmp", Ложь, Истина);
// Зададим размер
Picture.Height = 100;
Picture.Width = 150;

// Чтобы установить обтекание текста, конвертируем рисунок в фигуру
Shape = Picture.ConvertToShape();
Shape.WrapFormat.Type = 0; // по контуру...

ThisDocument.Save();
//Объект.Application.Quit();
Объект = Неопределено;
Исключение
ThisDocument.Save();
Сообщить(ОписаниеОшибки());
//Объект.Application.Quit();
Объект = Неопределено;
КонецПопытки;

КонецПроцедуры

Автор: Крылов Николай
Опубликовано на сайте: https://HelpF.pro
Прямая ссылка: https://HelpF.pro/faq/view/1031.html