Como automatizar o Microsoft Word para executar uma mala direta usando o Visual C++ e o MFC
Resumo
Este artigo demonstra como criar e manipular um documento do Microsoft Word usando a Automação do Microsoft Visual C++ e o MFC (Microsoft Foundation Classes).
Informações adicionais
Este artigo é paralelo a um artigo da Base de Dados de Conhecimento Microsoft que descreve o mesmo processo usando o Microsoft Visual Basic.
Compilando o exemplo de automação
Com o Microsoft Developer Studio, inicie um novo projeto "MFC AppWizard (exe)" chamado "AutoProject".
Na etapa 1 do AppWizard do MFC, escolha "Dialog Based" para o tipo de aplicativo e clique em Concluir.
A caixa de diálogo Novas Informações do Projeto é exibida e indica que as Classes a serem criadas incluem:
Application: CAutoProjectApp in AutoProject.h and AutoProject.cpp Dialog: CAutoProjectDlg in AutoProject.h and AutoProjectDlg.cpp
Clique em OK para criar o projeto.
A caixa de diálogo "IDD_AUTOPROJECT_DIALOG" é aberta na área de design/edição do Visual Studio. Modifique-o de acordo com as instruções nas próximas duas etapas.
Remova o controle Rótulo (IDC_STATIC) e o botão Cancelar (IDCANCEL).
Altere o nome do botão OK para "IDRUN" e a legenda para "Executar". Feche o formulário de design da caixa de diálogo AutoProject.rc.
Clique em ClassWizard no menu Exibir (ou pressione CTRL+W).
Selecione a guia Mapas de Mensagens. Selecione IDRUN na caixa de listagem IDs de objeto e selecione "BN_CLICKED" na caixa de listagem Mensagens. Clique em Adicionar Função e aceite o nome da função "OnRun". Clique em OK para fechar o ClassWizard.
OBSERVAÇÃO:** Esta etapa adiciona uma declaração para o membro da função "OnRun();" ao arquivo de cabeçalho chamado AutoProjectDLG.h. Esta etapa também adiciona uma função de manipulador de mensagens de esqueleto vazia chamada CAutoProjectDlg::OnRun() ao arquivo chamado AutoProjectDLG.cpp.
Clique em ClassWizard no menu Exibir (ou pressione CTRL+W).
Selecione a guia Automação. Clique em Adicionar Classe e escolha "De uma biblioteca de tipos". Navegue para selecionar a biblioteca de objetos do aplicativo que você deseja automatizar (neste exemplo, se você estiver automatizando o Excel 97, escolha a Biblioteca de Objetos do Microsoft Excel 8.0; o local padrão é C:\Arquivos de Programas\Microsoft Office\Office\Excel8.olb).
Se você estiver automatizando o Microsoft Excel 2000, escolha a Biblioteca de Objetos do Microsoft Excel 9.0 para a qual o local padrão é C:\Arquivos de Programas\Microsoft Office\Office\Excel9.olb.
Se você estiver automatizando o Microsoft Excel 2002 e o Microsoft Office Excel 2003, a biblioteca de objetos será inserida no arquivo Excel.exe. O local padrão para Excel.exe no Office 2002 é C:\program Files\Microsoft Office\Office10\Excel.exe. O local padrão para Excel.exe no Office 2003 é C:\program Files\Microsoft Office\Office11\Excel.exe. Depois de selecionar a biblioteca de objetos apropriada, clique em Abrir. Selecione todas as classes na lista Confirmar Classes e clique em OK.
NOTA A caixa de listagem na caixa de diálogo Confirmar Classes contém todas as interfaces IDispatch (que são praticamente idênticas às classes) na biblioteca de tipos do Microsoft Excel. Na metade inferior da caixa de diálogo, você verá que um arquivo de implementação chamado Excel8.cpp contém wrappers de classe gerados derivados de ColeDispatchDriver(), e o arquivo de cabeçalho de declaração apropriado é denominado Excel8.h. (Para Excel 2002 e Excel 2003, os arquivos são denominados Excel.cpp e Excel.h.)
Nota Escolha a biblioteca de tipos correta para a versão do Word que você está automatizando. Consulte a seção de referências abaixo para obter informações sobre como localizar a biblioteca de tipos corretamente.
Clique em OK para fechar a caixa de diálogo ClassWizard do MFC.
Adicione o seguinte código à função CAutoProjectApp::InitInstance(), que carrega e habilita a biblioteca de serviços COM:
BOOL CAutoProjectApp::InitInstance() { if(!AfxOleInit()) // Your addition starts here { AfxMessageBox("Could not initialize COM dll"); return FALSE; } // End of your addition AfxEnableControlContainer(); . . . }
Adicione a seguinte linha às instruções #include na parte superior do arquivo de programa AutoProject.cpp:
#include <afxdisp.h>
Adicione a instrução include para o arquivo de cabeçalho criado acima (msword8.h, msword9.h ou msword.h) em AutoProjectDlg.cpp após a instrução include para stdafx.h. Um exemplo para o Word 97 seria:
#include "stdafx.h" #include "msword8.h"
Adicione o código de Automação ao método CAutoProjectDlg::OnRun para que ele apareça conforme mostrado abaixo:
void CAutoProjectDlg::OnRun() { _Application oWord; Documents oDocs; _Document oDoc; Selection oSelection; Paragraphs oParagraphs; Tables oTables; Table oTable; Range oRange; Columns oColumns; Column oColumn; Rows oRows; Row oRow; Cells oCells; Cell oCell; Shading oShading; Hyperlinks oHyperlinks; MailMerge oMailMerge; MailMergeFields oMailMergeFields; COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR), vtTrue((short)TRUE), vtFalse((short)FALSE); CString StrToAdd; // Create an instance of Word if (!oWord.CreateDispatch("Word.Application")) { AfxMessageBox("Word failed to start!"); } else { // Set the visible property oWord.SetVisible(TRUE); // Add a new document oDocs = oWord.GetDocuments(); oDoc = oDocs.Add(vtOptional,vtOptional); CreateMailMergeDataFile(&oWord,&oDoc); // Add the address header StrToAdd = "State University\r\nElectrical Engineering " \ "Department"; oSelection = oWord.GetSelection(); oParagraphs = oSelection.GetParagraphs(); oParagraphs.SetAlignment(1); // 1 = wdAlignParagraphCenter oSelection.TypeText(StrToAdd); InsertLines(&oSelection,4); oParagraphs.SetAlignment(0); // 0 = wdAlignParagraphLeft oMailMerge = oDoc.GetMailMerge(); oMailMergeFields = oMailMerge.GetFields(); oMailMergeFields.Add(oSelection.GetRange(),"FirstName"); oSelection.TypeText(" "); oMailMergeFields.Add(oSelection.GetRange(),"LastName"); oSelection.TypeParagraph(); oMailMergeFields.Add(oSelection.GetRange(),"Address"); oSelection.TypeParagraph(); oMailMergeFields.Add(oSelection.GetRange(),"CityStateZip"); InsertLines(&oSelection,4); // Set the paragraph alignment to Right justified oParagraphs = oSelection.GetParagraphs(); oParagraphs.SetAlignment(2); // 2 = wdAlignParagraphRight // Insert the current date oSelection.InsertDateTime(COleVariant("dddd, MMMM dd, yyyy"),\ vtFalse,vtOptional); InsertLines(&oSelection,2); // Reset the justification to Justify oParagraphs = oSelection.GetParagraphs(); oParagraphs.SetAlignment(3); // 3 = wdAlignParagraphJustify oSelection.TypeText("Dear "); oMailMergeFields.Add(oSelection.GetRange(),"FirstName"); oSelection.TypeText(","); InsertLines(&oSelection,2); // Add the body of the message StrToAdd = "Thank you for your recent request for next " \ "semester's class schedule for the Electrical " \ "Engineering Department. Enclosed with this letter " \ "is a booklet containing all the classes offered " \ "next semester at State University. Several new " \ "classes will be offered in the Electrical " \ "Engineering Department next semester. These " \ "classes are listed below."; oSelection.TypeText(StrToAdd); InsertLines(&oSelection,2); // Add a new table with 9 rows and 4 columns oRange = oSelection.GetRange(); oTables = oDoc.GetTables(); oTable = oTables.Add(oRange,9,4); // Set the width of each column oColumns = oTable.GetColumns(); oColumn = oColumns.Item(1); oColumn.SetWidth(51.0,0); // 0 = wdAdjustNone oColumn = oColumns.Item(2); oColumn.SetWidth(198.0,0); // 0 = wdAdjustNone oColumn = oColumns.Item(3); oColumn.SetWidth(100.0,0); // 0 = wdAdjustNone oColumn = oColumns.Item(4); oColumn.SetWidth(111.0,0); // 0 = wdAdjustNone // Set the shading for row 1 to wdGray25 oRows = oTable.GetRows(); oRow = oRows.Item(1); oCells = oRow.GetCells(); oShading = oCells.GetShading(); oShading.SetBackgroundPatternColorIndex(16); // 16 = wdGray25 // Turn on BOLD for the first row oRange = oRow.GetRange(); oRange.SetBold(TRUE); // Set the alignment for cell (1,1) to center oCell = oTable.Cell(1,1); oRange = oCell.GetRange(); oParagraphs = oRange.GetParagraphs(); oParagraphs.SetAlignment(1); // 1 = wdAlignParagraphCenter // Fill in the class schedule data FillRow(&oTable,1,"Class Number","Class Name",\ "Class Time","Instructor"); FillRow(&oTable,2, "EE220", "Introduction to Electronics II", \ "1:00-2:00 M,W,F", "Dr. Jensen"); FillRow(&oTable,3, "EE230", "Electromagnetic Field Theory I", \ "10:00-11:30 T,T", "Dr. Crump"); FillRow(&oTable,4, "EE300", "Feedback Control Systems", \ "9:00-10:00 M,W,F", "Dr. Murdy"); FillRow(&oTable,5, "EE325", "Advanced Digital Design", \ "9:00-10:30 T,T", "Dr. Alley"); FillRow(&oTable,6, "EE350", "Advanced Communication Systems", \ "9:00-10:30 T,T", "Dr. Taylor"); FillRow(&oTable,7, "EE400", "Advanced Microwave Theory", \ "1:00-2:30 T,T", "Dr. Lee"); FillRow(&oTable,8, "EE450", "Plasma Theory", \ "1:00-2:00 M,W,F", "Dr. Davis"); FillRow(&oTable,9, "EE500", "Principles of VLSI Design", \ "3:00-4:00 M,W,F", "Dr. Ellison"); // Go to the end of the document oSelection.GoTo(COleVariant((short)3), // 3 = wdGoToLine COleVariant((short)-1),vtOptional,vtOptional); // -1 = wdGoToLast InsertLines(&oSelection,2); // Add closing text StrToAdd = "For additional information regarding the " \ "Department of Electrical Engineering, " \ "you can visit our website at "; oSelection.TypeText(StrToAdd); // Add a hyperlink to the homepage oHyperlinks = oSelection.GetHyperlinks(); oHyperlinks.Add(oSelection.GetRange(),\ COleVariant("http://www.ee.stateu.tld"),vtOptional); // Finish adding closing text StrToAdd = ". Thank you for your interest in the classes " \ "offered in the Department of Electrical " \ "Engineering. If you have any other questions, " \ "please feel free to give us a call at (999) " \ "555-1212.\r\n\r\n" \ "Sincerely,\r\n\r\n" \ "Kathryn M. Hinsch\r\n" \ "Department of Electrical Engineering\r\n"; oSelection.TypeText(StrToAdd); // Perform mail merge oMailMerge.SetDestination(0); // 0 = wdSendToNewDocument oMailMerge.Execute(vtFalse); // Close the original form document oDoc.SetSaved(TRUE); oDoc.Close(vtFalse,vtOptional,vtOptional); } }
Insira o seguinte código acima no código fornecido na etapa 3:
void InsertLines(Selection *pSelection, int NumLines) { int iCount; // Insert NumLines blank lines for (iCount = 1; iCount <= NumLines; iCount++) pSelection->TypeParagraph(); } void FillRow(Table *pTable,int Row, CString Text1, CString Text2, CString Text3, CString Text4) { Cell oCell; Range oRange; // Insert data into the specific cell oCell = pTable->Cell(Row,1); oRange = oCell.GetRange(); oRange.InsertAfter(Text1); oCell = pTable->Cell(Row,2); oRange = oCell.GetRange(); oRange.InsertAfter(Text2); oCell = pTable->Cell(Row,3); oRange = oCell.GetRange(); oRange.InsertAfter(Text3); oCell = pTable->Cell(Row,4); oRange = oCell.GetRange(); oRange.InsertAfter(Text4); } void CreateMailMergeDataFile(_Application *pApp,_Document *pDoc) { _Document oDataDoc; MailMerge oMailMerge; Documents oDocs; Tables oTables; Table oTable; Rows oRows; int iCount; COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR), vtFalse((short)FALSE); // Create a data source at C:\DataDoc.doc containing the field data oMailMerge = pDoc->GetMailMerge(); oMailMerge.CreateDataSource(COleVariant("C:\\DataDoc.doc"), \ vtOptional,vtOptional, \ COleVariant("FirstName, LastName, Address,CityStateZip"),\ vtOptional, vtOptional,vtOptional,vtOptional,vtOptional); // Open the file to insert data oDocs = pApp->GetDocuments(); oDataDoc = oDocs.Open(COleVariant("C:\\DataDoc.doc"), \ vtOptional,vtOptional,vtOptional,vtOptional,\ vtOptional,vtOptional,vtOptional,vtOptional,\ vtOptional); oTables = oDataDoc.GetTables(); oTable = oTables.Item(1); oRows = oTable.GetRows(); for (iCount=1; iCount<=2; iCount++) oRows.Add(vtOptional); // Fill in the data FillRow(&oTable, 2, "Steve", "DeBroux", \ "4567 Main Street", "Buffalo, NY 98052"); FillRow(&oTable, 3, "Jan", "Miksovsky", \ "1234 5th Street", "Charlotte, NC 98765"); FillRow(&oTable, 4, "Brian", "Valentine", \ "12348 78th Street Apt. 214", "Lubbock, TX 25874"); // Save and close the file oDataDoc.Save(); oDataDoc.Close(vtFalse,vtOptional,vtOptional); }
Compile e execute o programa. Clique no botão Executar e o Microsoft Word deverá iniciar e exibir uma carta de exemplo. Observe que alguns métodos foram alterados com o Word 2000 e o Word 2002. Para obter mais informações sobre essas alterações, consulte a seção "Referências".
Referências
Notas para automatizar o Microsoft Word 2000 e o Microsoft Word 2002
Alguns métodos e propriedades foram alterados para o Microsoft Word 2000 e o Microsoft Word 2002.
Para obter mais informações sobre a Automação do Office, visite o site de suporte de desenvolvimento do Microsoft Office em: Suporte da Microsoft