Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Borland C++ Builder/Turbo C++ Explorer > Работаем с Word


Автор: Bas 14.04.04, 14:07
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Если у Вас нет на панели инструментов закладки  Servers  - то можно
    проделать следующее :
    Создаем новый пакет с использованием библиотеки типов. Выберите Project | Import
    Type library.
    Из списка зарегистрированных серверов выберите библиотеку типов Word (Microsoft
    Word 9.0 Object Library (на моем компьютере установлен Microsoft Office 2000,
    поэтому в списке присутствует 9.0, для предыдущих версий Office, номера версий
    будут меньше)).
    Укажите имя закладки палитры компонентов (Pallete Page), куда будут установлены
    новые классы - TWordGlobal, TWordApplication, TWordDocument, TWordFont,
    TWordParagraphFormat, TWordLetterContent. Выберите закладку Servers.
     
    Установите флажок General Component Wraper для генерации компонентов на основе
    библиотеки типов и размещения ее на палитре компонент, а затем нажмите кнопку
    Install.
    Установите сервер на палитру компонент.
    Если закладка -  Servers есть то выше перечисленные действия делать не надо.
    Фундаментальным объектом любого приложения является Application. Давайте получим
    к нему доступ .
    ·  создаем новый проект;
    ·  на главную форму выкладываем компонент WordApplication с закладки
    Servers;
    ·  устанавливаем свойства компонента AutoConnect и AutoQuit в True;
    ·  запускаем приложение на выполнение.
     
    Не забудьте добавить в #include <COMOBJ.hpp>.
    #pragma link "Word_2K_SRVR"- для 2000
    #pragma link "Word_97_SRVR"- для 97
    Если у вас обе строки добавлены то не избежать ошибок Ambiguity between
    В большинстве случаев нам надо подключиться  к уже существующему интерфейсу, а
    не создать его заново. Также это может быть необходимо, когда контроллер должен
    отслеживать события, происходящие в COM сервере. Рассмотрим следующий пример:
    ·  создаем новое приложение;
    ·  помещаем на форму компоненты WordApplication и WordDocument;
    ·  устанавливаем в True свойства AutoConnect и AutoQuit компонента
    WordApplication;
    ·  устанавливаем в значение ckAttachToInterface свойство ConnectKind для
    объекта WordDocument;
    ·  для события onDokumentChange прописываем такой код:
    ·      //производим подключение к текущему документу
    ·      WordDocument1->ConnectTo( WordApplication1.ActiveDocument);
    ·      //Контроллер добавляет новую строку в текущий документ
    ·      WordDocument1->Range->InsertAfter(#13+'Переход к документу'+#13+
    ·         WordApplication1->ActiveDocument->Get_FullName+' произведен :'+
    ·         DateTimeToStr(Now));
    для события OnFormCreate прописываем следующее:
    ·      WordApplication1->Visible=true;
      
    После запуска приложения будет автоматически загружен Microsoft Word, создайте в
    нем несколько новых документов и "попереключайтесь" между ними. Вы увидите, что
    контроллер автоматизации добавляет новые строки в текущий активный документ.
    Точно так же можно управлять и сервером ExcelApplication. При создании новой
    рабочей книги на сервере, в контроллере будет проинициализировано событие
    onNewWorkBook, которое можно обработать аналогично примеру с Word.
    Теперь рассмотрим еще один пример.
    Пусть существует необходимость формировать некий отчет в виде документа
    Microsoft Word, для чего нами используется файл-шаблон (к примеру, с именем
    test.doc). Поля, которые должны быть заменены, помечены символом «~» или другим
    сиволом который не встречается в отчете .Необходимо получить данные, а затем
    заменить метки реальными данными, после чего сформированный документ должен быть
    отправлен на печать, сохранен.
     В test.doc имеется шапка таблицы и нам необходимо заполнить таблицу данными из
    запроса (может бать любой контейнер с данными).
    Создадим новый проект и поместим на форму компоненты WordApplication(WApp),
    WordDocument(WDoc) и кнопку (TButton). В качестве обработчика события нажатия на
    кнопку укажем следующий код:
     //Следующие переменные понадобятся нам для выполнения методов сервера
     OleVariant FileName;
     OleVariant oldStr,newStr;
     OleVariant EmptyPar=False;
     OleVariant Yes=True;
     FileName=GetCurrentDir()+"\\test.doc";
     //Открываем шаблон документа
     WApp->Visible=false; // что бы не моргал при заполнении данными но можно
    поставить в true
                          // тогда весь процесс заполнения , замены будет на экране
     WApp->Caption = StringToOleStr("Отчет");//Задание заголовка для окна Word
     WApp->Documents->Add(FileName,EmptyParam);
     WDoc->ConnectTo(WApp->ActiveDocument);  //Связываем компонент с существующим интерфейсом
    /*
     WDoc->ConnectTo(WordApplication1->Documents->Item(ItemIndex));
     Если есть несколько открытых документов.
    */
     //Находим в документе метки и производим их замены
     oldStr=AnsiString("~1");
     newStr=AnsiString("Метка 1");
     WDoc->Range(EmptyParam,EmptyParam)->Find->Execute(oldStr,
     EmptyParam,EmptyParam,EmptyParam,EmptyParam,
     EmptyParam,EmptyParam,EmptyParam,EmptyParam,
     newStr,Yes);
     
    TablePtr MyTable=WApp->ActiveDocument->Tables->Item(1) ;
    // получаем указатель на нашу таблицу
    RangePtr MyRange =MyTable->Range ;
      String s;
      TADOQuery * QF;
    Создадим запрос к примеру «select * from table1» как создавать запросы и
    работать с ними сдесь рассматривать не будем.
    В принципе это могут быть и таблицы (TTable)
     
     String pole;
     int Current=0; //счетчик
     QF->First();
     long j;
    while (!QF->Eof)
     {
      MyTable->Rows->Add(); // вставляем новую строку в таблицу
      int fild= QF->Fields->Count;
      String nPole;
      for (int p=1 ;p<fild-3 ;p++) // цикл по полям
      {
      MyTable->Borders->set_OutsideLineWidth(wdLineWidth300pt);
      MyTable->Borders->set_InsideLineStyle(wdLineStyleThinThickSmallGap);
      nPole=Table1->Fields->Fields[j]->AsString;//Можно делать проверку на тип и
    формат данных
      MyTable->Cell(1,p)->Range->InsertAfter(StringToOleStr(nPole));
      }
      QF->Next();
     }
    FileName= GetCurrentDir()+"\\newtest.doc";
    Сохраняем в формате Word 6.0/95 (*.doc)
    OleVariant EmptyS=StringToOleStr("");
    WDoc->SaveAs(FileName,(OleVariant)104,EmptyParam,
              EmptyS,Yes,EmptyS,
              EmptyParam,EmptyParam,
              EmptyParam,EmptyParam,EmptyParam);
    WDoc->Close(EmptyParam,EmptyParam,EmptyParam);
     WApp->Visible=1;
     WApp->Disconnect();
     
     
    Некоторые полезные замечания :
       MyTable->Cell(j,1)->VerticalAlignment=wdCellAlignVerticalCenter;
       MyTable->Cell(j,1)->Range->Paragraphs->Alignment=wdAlignParagraphCenter;
     
    //Создание таблицы
    WordApplication1->Selection->Font->Bold = false;
    WordApplication1->ActiveDocument->Tables->Add(WordApplication1->Selection->Range
    , MainFrm->Query???->RecordCount + 9, 6);
     
    Этот код, он вставляет данные после таблицы
     
    //   String stn = "\n";
    //   String koltnS;       // строка для форматирования общей суммы в ???
    //   koltnS = koltnS.FormatFloat("0.00000", QF->?????->Value);
    //   stn = stn + "                                Сумма реализации:  "+ koltnS;
    //   WDoc->Range(EmptyParam,EmptyParam)->InsertAfter(StringToOleStr(stn));
    //   WordFont1->ConnectTo(WordDocument1->Sentences->get_Last()->get_Font());
    //   WordFont1->Size = 12;
    //   WordFont1->Bold = true;
    //   WordFont1->Color = wdColorIndigo;
     
    // Если понадобиться код объединения ячеек
     
     WordApplication1->Selection->Tables->Item(1)->Cell(4,1)->
     Merge(WordApplication1->Selection->Tables->Item(1)->Cell(4,6));
     
    Еще вариант сохранения док-та
       stn = MainFrm->DBEdit5->Text;
       int n = stn.Length();
       if (n == 1)   stn = "0" + stn;
       stn = "?????" + stn + MainFrm->Edit1->Text + ".doc";
       //Сохранение документа
       WordDocument1->SaveAs(&TVariant(WideString(stn)),
    &TVariant(wdFormatDocument));

Автор: Dimas51 13.07.04, 09:19
У меня не получается выполнить обращение к строке таблицы Word
(RowPtr)(Table->Rows->Item(1))->Select()
Что я делаю не так?

С объектами CellPtr никаких проблем.

Автор: Bas 13.07.04, 09:36
Table->Rows->Item(1)->Select()?
Цитата
Dimas51, 13.07.04, 12:19
(RowPtr*)(Table->Rows->Item(1))->Select()

Автор: Леопольд 17.07.04, 02:24
[У меня не получается выполнить обращение к строке таблицы Word
(RowPtr)(Table->Rows->Item(1))->Select()
Что я делаю не так?

А как добавить строку в конец Таблицы?
В Worde новая строка Tabом создается, а если в проге
суешь "\t" - не хочет

Автор: Bas 17.07.04, 09:27
Цитата
Леопольд, 17.07.04, 05:24
а если в проге
суешь "\t" - не хочет

"\n"

Автор: Budda 07.10.04, 10:38
Цитата

Не забудьте добавить в #include <COMOBJ.hpp>.
#pragma link "Word_2K_SRVR"- для 2000
#pragma link "Word_97_SRVR"- для 97

А для Office XP?

Автор: Bas 07.10.04, 10:54
Цитата Budda, 7.10.04, 13:38
А для Office XP?

А это без разницы, главное версия Word'а

Автор: Budda 07.10.04, 10:58
А если ворд 2002? Кстати, эта штука нужна только для компиляции. Так? У клиента будет работать независимо от указанной строки. Да?

Автор: trainer 07.10.04, 11:10
Цитата Budda, 7.10.04, 14:58
У клиента будет работать независимо от указанной строки. Да?
Не факт. У разных версий Word'а разная функциональность.

Автор: Budda 07.10.04, 13:30
WordDocument1->ConnectTo( WordApplication1.ActiveDocument);
Наверное должно быть так:
WordDocument1->ConnectTo( WordApplication1->ActiveDocument);
Да?

А вот тут проблемы:
На строчку: WordDocument1->Range->InsertAfter
Компилятор ругается:
[C++ Error] untMain.cpp(26): E2288 Pointer to structure required on left side of -> or ->*

Требует что-то поставить после Range. Что делать? И есть ли дока на эти компоненты? WordApplication, WordDocument?

У меня в палитре есть ещё и WordGlobal. Это что и зачем? И ещё много разных компонент. Хотел бы доку почитать, если где-то есть. Дайте, плиз, хотя бы линк

Автор: Bas 07.10.04, 13:39
WordDocument1 это и есть WDoc.
Цитата Bas, 14.04.04, 17:07
WDoc->ConnectTo(WApp->ActiveDocument);


Цитата Bas, 14.04.04, 17:07
WDoc->Range(EmptyParam,EmptyParam)->;


Цитата Bas, 14.04.04, 17:07
// WDoc->Range(EmptyParam,EmptyParam)->InsertAfter(StringToOleStr(stn));

Первое сообщение читали?

Автор: Budda 07.10.04, 14:04
WordDocument1->Range(EmptyPar,EmptyPar)->InsertAfter("Test");

[C++ Error] untMain.cpp(30): E2034 Cannot convert 'char *' to 'wchar_t *'

???

Bas, поделись плиз, источниками инфы, или хотя бы ключевыми словами, по которым искать нужно

Автор: trainer 07.10.04, 14:21
L"Test"

Автор: Bas 07.10.04, 15:02
Цитата Budda, 7.10.04, 17:04
WordDocument1->Range(EmptyPar,EmptyPar)->InsertAfter("Test");

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    WordDocument1->Range(EmptyPar,EmptyPar)->InsertAfter(StringToOleStr("Test"));
Поищи по форуму , кажеться я laifik скидывал и ссылки и архив.
Но всеравно главная инфа в хелпах Word,Excel.

Автор: Budda 07.10.04, 16:11
Bas, Искал, искал... кучу линков топиков на тему нашёл, а вот твоих ссылок и архива - не нашёл...

Сейчас у меня проблема, что при компиляции WordApplication1->Visible получаю сообщение - метод недоступен... :(

А в Ворде - хэлпа нет на такие штуки... ?

Автор: Seva 08.10.04, 05:08
Скорее всего требуется:
WordApplication1->Visible[0]

Автор: Bas 08.10.04, 06:08
Цитата Budda, 7.10.04, 19:11
WordApplication1->Visible

WordApplication1->Visible=true;
Да у меня было чтото похоже когда переустановил систему и установил BCB - день мучался (ведь знал что работало). Но вспомнил что Update'ы не установил. После установки все пошло как надо.
Автоматизация приложений Microsoft Office в примерах

Автор: Budda 08.10.04, 08:44
Цитата
Но вспомнил что Update'ы не установил. После установки все пошло как надо

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

И ещё: Как можно работать с Вордом без компонент, а используя ОЛЕ технологии?

Добавлено
Seva, нет
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    WordApplication1->Visible[0]=true;

При компиляции выдает ошибку:
Цитата
[C++ Error] untMain.cpp(35): E2015 Ambiguity between 'TOLEBOOL::operator bool() const' and 'TOLEBOOL::operator short() const'

Автор: trainer 08.10.04, 11:26
Цитата Budda, 8.10.04, 12:44
Как можно работать с Вордом без компонент, а используя ОЛЕ технологии?
Так же, как и с другими приложениями. :)
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Variant vApp;
    try {
       vApp = Variant::GetActiveObject("Word.Application");
    } catch(EOleSysError &ex) {
       try{
          vApp = Variant::CreateObject("Word.Application");
       } catch(EOleSysError &ex) {
          // не удалось запустить сервер
       } catch(...) {
          // неизвестная ошибка
       }
    } catch(...) {
       // не удалось подключиться к серверу
    }
А далее через OlePropertyGet, OlePropertyPut, OleFunction, OleProcedure
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Variant vDoc = vApp.OlePropertyGet("Documents").OleFunction("Open",имя_файла);
и так далее. :)

Добавлено
P.S. Хотя компоненты работают с соответствующим сервером тоже через OLE :)

Автор: Bas 08.10.04, 12:47
Выписка
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
     
    Аббревиатура OLE обозначает Objects Linked and Embedded (Присоединенные И
    Встроенные Объекты - ПИВО  ;) ). Данные, разделяемые между приложениями
    называются OLE объектом. Приложение, которое может содержать OLE объекты,
    называют OLE контейнером (OLE Container). Приложение, данные из которого
    можно включить в OLE контейнер в виде OLE объекта, называют OLE сервером.
     
    Например, MicroSoft Word может включать в документ графические объекты,
    аудио- и видеоклипы и множество других объектов (такой документ иногда
    называют составным документом - compound document).
     
    Как следует из названия, OLE объекты можно либо присоединить к OLE
    контейнеру, либо включить в него. В первом случае данные будут храниться в
    файле на диске, любое приложение будет иметь доступ к этим данным и сможет
    вносить изменения. Во втором случае данные включаются в OLE контейнер и
    только он сможет просматривать и модифицировать эти данные.
     
    OLE является дальнейшим развитием идеи разделяемых между приложениями
    данных. Если с помощью DDE можно было работать с текстом, то OLE позволяет
    легко встроить в приложение обработку любых типов данных. Как и в случае с
    DDE, для правильной работы приложения-клиента (OLE контейнера) требуется
    наличие приложения OLE сервера. Каждый раз, когда в программе-клиенте
    пользователь обращается к OLE объекту с целью просмотра или редактирования
    данных (обычно двойной щелчок мышкой на объекте), запускается приложение-
    сервер, в котором и происходит работа с данными.
     
    В природе существует несколько видов OLE, отличающихся по способу
    активации OLE сервера. OLE версии 1 запускает сервер в отдельном окне. OLE
    2 реализует то, что называется in-place activation and editing.
     
    Развитие идеи OLE привело к появлению OLE automation - приложение-клиент
    может выполнить часть кода сервера. Тип OLE объекта, помещенного в
    программу-клиент, определяется тем, какую версию OLE поддерживает сервер.

Автор: Budda 08.10.04, 13:43
trainer, Спасибо!


Bas, Это ты к чему?

Автор: Bas 08.10.04, 13:48
Цитата Budda, 8.10.04, 16:43
Bas, Это ты к чему?

Для общего развития.

Автор: Budda 08.10.04, 14:03
Bas, та мне бы чего-то попрактичнее, тот код, который Тренер дал - тоже сбоит... Ну просто 3.14здец какой-то.

Может чего-то где-то в настройках.... Может кинешь маленький конкретный пример? seredaom@ukrpost.net.

Автор: trainer 08.10.04, 14:05
Цитата Budda, 8.10.04, 18:03
который Тренер дал - тоже сбоит
В чем это проявляется и покажи свой исходник.

Автор: Bas 08.10.04, 14:08
Исходник в студию или в приват.

Автор: Seva 12.10.04, 05:34
Цитата Budda,8.10.04, 11:44
Seva, нет
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    WordApplication1->Visible[0]=true;

При компиляции выдает ошибку:
Цитата
[C++ Error] untMain.cpp(35): E2015 Ambiguity between 'TOLEBOOL::operator bool() const' and 'TOLEBOOL::operator short() const'

Ну подправь соответствующим образом.
Хочет TOLEBOOL? Попробуй так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
     
    WordApplication1->Visible[0]=TOLEBOOL(true);

Автор: dallas0713 06.04.08, 04:54
Подскажите, пожалуйста, где скачать компоненты для работы с Office 2007.

Автор: Seva 07.04.08, 05:28
Цитата dallas0713 @
Подскажите, пожалуйста, где скачать компоненты для работы с Office 2007.

Читай эту тему с начала.

Автор: sanchos91 04.07.11, 17:59
Люди, подскажите пожалуйста, почему происходит следующее: при запуске программы в среде C++ Builder 6, она работает нормально, но когда запускаю экзешник вне среды, работает не совсем так как надо ???

Программа должна выполнять следующие действия:
1. Открыть файл *.doc, в котором есть формулы.
2. Сохранить во временный файл, но уже с расширением *.docx (Open XML Format)
3. Извлечь из временного файла формулы в виде картинок.

В среде выполняется всё норм. А "автономно" просит сохранить файл.

Вот код:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    //---------------------------------------------------------------------------
     
    #include <vcl.h>
    #pragma hdrstop
     
    #include "Unit1.h"
     
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma link "Word_2K_SRVR"
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
     
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    AnsiString fname;
            OpenDialog1->Execute();
            fname=OpenDialog1->FileName;
            if (fname!="")
            {
            WordApplication1->Connect();
            WordApplication1->set_Visible(false);
            WordApplication1->GetDefaultInterface()->Visible = false;
            WordApplication1->set_DisplayAlerts(false);
     
            WordApplication1->Documents->Open(TVariant(fname));
            WordApplication1->ActiveDocument->Select();
            WordApplication1->Selection->Copy();
            WordApplication1->Documents->Add(EmptyParam, EmptyParam);
            WordDocument1->ConnectTo(WordApplication1->ActiveDocument);
            WordDocument1->Activate();
            WordApplication1->Selection->Paste();
            WordDocument1->SaveAs(TVariant("c:\\~temp.docx"));
            WordDocument1->Close(TVariant(false));
            WordApplication1->Quit(TVariant(false));
            WordApplication1->Disconnect();
     
            ZipForge1->FileName="c:\\~temp.docx";
            ZipForge1->OpenArchive(fmOpenRead);
            ZipForge1->ExtractFiles(L"*.wmf");
            ZipForge1->CloseArchive();
            DeleteFileA("c:\\~temp.docx");
            }
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
    ShellExecute(NULL,"open","word\\media", NULL, NULL, SW_SHOWNORMAL);
     
    }
    //---------------------------------------------------------------------------

Заранеее благодарен ! :thanks:

Автор: trainer 05.07.11, 10:00
При каком действии просит? Покажи скриншот диалога.

Автор: #SI# 05.07.11, 11:43
На будущее:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    void __fastcall TForm1::Button1Click(TObject *Sender) {
      if (!OpenDialog1->Execute())
        return;
      //-------------------------------------
      AnsiString fname = OpenDialog1->FileName;
      WordApplication1->Connect();
      // и всё остальное
    }

Автор: sanchos91 05.07.11, 12:52
Выяснил почему в среде разработки было норм, а сам экзешник не пахал...
У меня стоит на компе: Windows 7 Pro x86, MS Office 2007, BCB 6.
И я впомнил, что Борланд, я ставил в режиме совместимости с WinXP SP3, тогда работало. Потому попробывал совместить и сам экзешник... о, чудо, заработало. Думаю на WinXP будет работать.

Да, в коде нужно исправить WordApplication1->set_DisplayAlerts(wdAlertsNone);
но это было не существенно.

Изените, пожалуйста за беспокойство!!! Спасибо :thanks: !!!

Добавлено
Цитата #SI# @
На будущее:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    void __fastcall TForm1::Button1Click(TObject *Sender) {
      if (!OpenDialog1->Execute())
        return;
      //-------------------------------------
      AnsiString fname = OpenDialog1->FileName;
      WordApplication1->Connect();
      // и всё остальное
    }

Спасибо, эту проверку завтыкал... :blush:

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)