gifts2017

Пример работы с Word через OLE. Часть 2. Редко используемые элементы.

Опубликовал Николай Крылов (Nikola23) в раздел Программирование - Практика программирования

Часто при создании документа из макета используют метод замены кусков текста. В примере представлен другой вариант выполнения того же действия - с использованием закладок. Также представлен пример построения нумерованного списка, вставки картинки, настройки ее параметров.

Не ленитесь ставить плюсики. Вам все равно - а мне приятно, и повергает еще что-нибудь полезное написать.

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

Для отображения закладок включите эту опцию в настройках вашего Word'а.

В моем примере я заранее создал новый пустой документ, путь к документу и картинке прописан в тексте. Не забудьте указать свои пути.

Тестировалось на Office 2007.

Частично текст повторяет предыдущий пример. Некоторые переменные переименованы по стандарту Office: Text --> Selection. Doc --> ThisDocument.

Вот текст модуля:

Процедура ВыполнитьОбработку() Экспорт

    Попытка

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

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

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

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

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

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

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

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

       
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
       
Selection.MoveDown(, 1);
       
Selection.Delete(1, 1);

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

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

        // Добавим текст "для опытов"
        // 1
       
Selection.TypeText("sdcsdcsdcsdc");
       
Selection.TypeParagraph();
       
// 2
       
Selection.TypeText("sdcsdcsdcsdc");
       
Selection.TypeParagraph();
       
// 3
       
Selection.TypeText("sdcsdcsdcsdc");
       
Selection.TypeParagraph();
       
// 4
       
Selection.TypeText("sdcsdcsdcsdc");
       
Selection.TypeParagraph();
       
// Выделяем введенный текст
       
Selection.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; // можно указать форматирование текста списка

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

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

       
// Добавим картинку
        // Параметры: путь к файлу, создавать ссылку на картинку, сохранять с файлом
       
Picture = Selection.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();
       
Объект = Неопределено;
    КонецПопытки;

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

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

Наименование Файл Версия Размер Кол. Скачив.
ОБработка - образец
.epf 8,59Kb
27.03.10
163
.epf 8,59Kb 163 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Валентин Терёхин (Valet) 27.03.10 13:31
Методика с закладками, по моему шустрее работает, чем с заменой.
Как недостатки, что при отсутствии закладки ошибка проявляется (возможно если один код заполняет шаблоны с разными закладками). А также если имеются одинаковые элементы (к примеру название организации), то на каждый надо свою закладку.
2. Николай Крылов (Nikola23) 27.03.10 13:45
Согласен с (1). Закладкой удобно размечать место где встанет картинка, список, таблица. Так - максимально быстро можно будет указать позицию для вставки. Ранее я, например, последовательно проходил весь текст, определяя начало отметки"таблица" которую в последствии удалял, а потом только вставлял требуемый объект. Для обычной вставки нескольких слов во всех смыслах проще использовать обычную замену контекста.
3. Лариса Тесленко (LarisaT) 31.03.10 11:04
В последнее время актуальной стала задача работы с OpenOffice. Никак не могу найти нормальную информацию по программированию ОО из 1С77. Задача такова. Есть документ ОО Writer. В нем есть таблицы. Необходимо открыть документ, определить количество таблиц в нем, занести в определенные ячейки таблицы текстовую информацию, показать документ на экране. Может кто-то может представить такой код на общее обозрение или прислать мне на lllttt@mail.ru. Можно указать ссылки на соответствующую литературу, можно на материалы в интернете.
4. Andrew Ivanov (andrew76) 07.07.10 10:24
Picture = Selection.InlineShapes.AddPicture("C:\Users\NKrylov\Desktop\Новый.bmp", Ложь, Истина);
// Чтобы установить обтекание текста, конвертируем рисунок в фигуру
Shape = Picture.ConvertToShape();
Shape.WrapFormat.Type = 0; // по контуру...

вопрос-обязательно переводить вставленный рисунок в фигуру?
просто после этой конвертации объект(рисунок) уходит в крайнее левое положение
на странице Word. И ещё ,не работает метод обтекания текстом.Не подскажете?
5. Николай Крылов (Nikola23) 07.07.10 14:38
"вопрос-обязательно переводить вставленный рисунок в фигуру" обязательно.
"просто после этой конвертации объект(рисунок) уходит в крайнее левое положение" - вполне вероятно достаточно выбрать другой вариант обтекания (по левому краю, например).
"И ещё ,не работает метод обтекания текстом" - добиться такого эффекта не удалось. Проверьте правильность кода, напишите макрос на VBA, а затем перепишите на языке 1с
Вот список доступных видов обтекания (константы) и соответствующие этим видам значения:
wdWrapBehind = 5;
wdWrapFront = 3;
wdWrapInline = 7;
wdWrapNone = 3; // это не опечатка. Так написано в браузере объектов VBA
wdWrapSquare = 0;
wdWrapThrough = 2;
wdWrapTight = 1;
wdWrapTopBottom = 4;
6. Николай Крылов (Nikola23) 11.08.10 15:18
(3) Среди моих публикаций появилась примеры работы с Open Office...
7. Armando Armando (Armando) 14.02.11 18:03
Shape = Picture.ConvertToShape();

Почему при использовании метода ConvertToShape() может появляться ошибка 0x80004005 :?:
На одной машине работает, на другой - нет :(
Office 2007

Причем на проблемной машине на VBA эта конструкция работает
8. Ийон Тихий (cool.vlad4) 14.02.11 18:26
Для замены и поиска лучше чем способ регэксами мне кажется нет. А вот закладки пожалуй оригинально. Для картинок как раз самое то, наверное.
9. Артём Кержаков (MECUBO) 18.02.11 10:01
Доброго времени суток. Пришел с целью поиска помощи!
Я делаю программу которая должна редактировать шаблон ворда.
С начала я пытался сделать всё через WordApplication но добился только открытия нового документа и вставки текста.
Ета версия мне не подошла так как мне нужно открыть шаблон! Через некоторое время у меня получилось открыть шаблон через Ole но при любой попытке добавления текста показывает ошибки.
Вот мой скрипт (прошу не обращать внимания на мусор в скрипте так как я занимаюсь программированием совсем не давно).
//---------------------------------------------------------------------------

#include <vcl.h>
#include "Unit1.h"
#include <ComObj.hpp>
#include <utilcls.h>
#include "Unit2.h"
#include <utilcls.h>
#include <word_2K.h>
#include <shellapi.h>


//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "Word_2K_SRVR"
#pragma resource "*.dfm"
TForm1 *Form1;
Variant  vVarApp,vVarDocs,vVarDoc,vVarTable,vVarParagraph;
//---------------------------------------------------------------------------
//void __fastcall TForm1::FormCreate(TObject *Sender)
//{
//SplashForm=new TSplashForm(this);
//SplashForm->ShowModal();
//SplashForm->Free();
//}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{

}
//---------------------------------------------------------------------------

void __fastcall TForm1::N1Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{

TWordApplication
  *WordApplication=0;

TWordDocument
  *WordDocument=0;

AnsiString
  Mess="",
  tmpAnsiString;

float
  FontSize=8;

OleVariant
  Start;

vVarApp = CreateOleObject("Word.Application");
vVarApp.OlePropertySet("Visible",true);
vVarDocs = vVarApp.OlePropertyGet("Documents");
vVarDoc = vVarDocs.OleFunction("Open","I:\\Borland\\CBuilder6\\Projects\\KM-1.DOC");
vVarDoc.OleProcedure("Activate");

//str=RichEdit1->Text;
//vVarParagraph.OlePropertySet("Text",str);

//TVariant ovWhat = wdGoToBookmark;
//TVariant Bookmark = "asdf";
//tmpAnsiString= Bookmark;
//WordApplication->Selection->GoTo(&ovWhat, EmptyParam, EmptyParam, &Bookmark);
//WordApplication->Selection->TypeText(WideString("Èâàíîâ"));

//tmpAnsiString=RichEdit1->Text;
//WordApplication->Selection->Font->Size=7;
//WordDocument->Range(EmptyParam,EmptyParam)->InsertAfter(StringToOleStr(tmpAnsiString));

//tmpAnsiString=ComboBox1->Text;
//WordDocument->Range(EmptyParam,EmptyParam)->InsertAfter(StringToOleStr(tmpAnsiString));

}
//---------------------------------------------------------------------------
...Показать Скрыть

если не затруднит подскажите варианты добавления текста из полей RichEdit и Label по средствам заминения закладок.
10. Alexey Burtsev (alexeyburtsev) 19.10.11 19:28
Большое спасибо за науку, как раз изготавливаю коммерческое предложение.
Обнаружил такое явление.

Bm1=Док.Bookmarks(Букмарка).range;
NewPicture=Bm1.InlineShapes.AddPicture(ФайлФото);
...
NewPicture.ConvertToShape();

Работает, если я переключаюсь в окно Word листаю страницы, наблюдая работу "макроса". Если я этого не делаю - выдается сообщение об ошибке ConvertToShape().

Вылечилось после добавления строки

Док.Bookmarks(Букмарка).range.Select();
11. Николай Крылов (Nikola23) 19.10.11 20:50
(7) Armando, ответ можно найти в комменте (10)

(10) alexeyburtsev, ваш код отличается. Вполне возможно, что и методы к объектам надо применять другие.
12. skunk (skunk) 02.04.14 14:06
13. Andrey (kentavr27) 04.08.15 22:44
(0) Быть может Вы подскажите...
Из 1С-ки создаю документ Word, в таком виде
Синоним переменной: ИмяПеременной
, где "синоним..." это простой текст, а ИмяПеременной -- это есть закладка. Никак не могу совладать, что бы закладкой являлось ИмяПеременной полностью (это как в Word-е выделить слово и выбрать "Вставить закладку"). Мой текст
Selection.TypeText("ИмяПеременной");
//дальше пытаюсь выделить напечатанное слово
Selection.MoveLeft(2, 1);
Закладки=Word.ActiveDocument.Bookmarks();
Закладка=Закладки.Add("ИмяПеременной",Selection.Range());
Selection.TypeParagraph();

Закладка при таких действиях вставляется перед словом "ИмяПеременной" ([]ИмяПеременной) а нужно в виде [ИмяПеременной]
Подскажите пож. как получить желаемый результат
14. Николай Крылов (Nikola23) 11.08.15 23:01
(13) kentavr27,
Что бы понять, какой код необходимо добавить для решения Вашей задачи, запишите макрос и откройте его в редакторе VBA. Все что написано выше, я получил именно этим способом.
15. vovan_victory vovan_victory (vovan_victory) 31.08.15 21:33
Nikola23, ни как не пойму, если в файле несколько страниц,то как вставить картинку на каждую страницу?
Разобрался. Вопрос снят.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа