суббота, 27 сентября 2008 г.

Автоматизация Word из С++

Когда я ещё работал не на себя было у меня такое задание автоматизировать работу Word под создание в нём шаблонов для различных документов. И я тогда с этим естественно столкнулся впервые и много рыл по инету. Много кода всякого нашлось, часть которого мне пригодилась, часть оказалась не нужной.

Вот кусок кода по автоматизации word из С++, который достаточно хорошо раскрывает, что к чему.


_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;

// запускаем word
if (!oWord.CreateDispatch("Word.Application")) {
AfxMessageBox("Word failed to start!");
} else {
// делаем его видимым
oWord.SetVisible(TRUE);

// добавляем новый документ
oDocs = oWord.GetDocuments();
oDoc = oDocs.Add(vtOptional,vtOptional);
CreateMailMergeDataFile(&oWord,&oDoc);

//добавляем адресс
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);

// устанавливаем правое равнение абазца
oParagraphs = oSelection.GetParagraphs();
oParagraphs.SetAlignment(2); // 2 = wdAlignParagraphRight

// вставляем текущюю дату
oSelection.InsertDateTime(COleVariant("dddd, MMMM dd, yyyy"),\
vtFalse,vtOptional);
InsertLines(&oSelection,2);

//меняем выравнивание на Justify
oParagraphs = oSelection.GetParagraphs();
oParagraphs.SetAlignment(3); // 3 = wdAlignParagraphJustify
oSelection.TypeText("Dear ");
oMailMergeFields.Add(oSelection.GetRange(),"FirstName");
oSelection.TypeText(",");
InsertLines(&oSelection,2);

// добавлем сообщение
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);

// добавляем новую таблицу с 9 рядами и 4 колонками
oRange = oSelection.GetRange();
oTables = oDoc.GetTables();
oTable = oTables.Add(oRange,9,4);

// задаём ширину каждой колонки
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

// задаём утенение для 1 ряда как wdGray25
oRows = oTable.GetRows();
oRow = oRows.Item(1);
oCells = oRow.GetCells();
oShading = oCells.GetShading();
oShading.SetBackgroundPatternColorIndex(16); // 16 = wdGray25

// вернуть жирный шрифт для первого ряда
oRange = oRow.GetRange();
oRange.SetBold(TRUE);

// задать выравнивание по сентру для ячейки 1,1
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");

// перейти в конец документа
oSelection.GoTo(COleVariant((short)3), // 3 = wdGoToLine
COleVariant((short)-1),vtOptional,vtOptional); // -1 = wdGoToLast
InsertLines(&oSelection,2);

// добавить текст
StrToAdd = "For additional information regarding the " \
"Department of Electrical Engineering, " \
"you can visit our website at ";
oSelection.TypeText(StrToAdd);

// добавить гипрессылку на домашнюю страничку
oHyperlinks = oSelection.GetHyperlinks();
oHyperlinks.Add(oSelection.GetRange(),
COleVariant("http://www.igvard.blogspot.com"
),vtoptional/);

// завершительная часть текста
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);

// выполнить слияние писем
oMailMerge.SetDestination(0); // 0 = wdSendToNewDocument
oMailMerge.Execute(vtFalse);

// закрыть документ
oDoc.SetSaved(TRUE);
oDoc.Close(vtFalse,vtOptional,vtOptional);
}
}
/////////////////////////////////////////////////////////
void InsertLines(Selection *pSelection, int NumLines)
{
int iCount;

// вставить NumLines пустых линий
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;

// вставить данные в заданную ячейку
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);

// создать источник данных C:\DataDoc.doc содержащий данные
oMailMerge = pDoc->GetMailMerge();
oMailMerge.CreateDataSource(COleVariant("C:\\DataDoc.doc"),
vtOptional,vtOptional, \
COleVariant("FirstName, LastName, Address,CityStateZip"),\
vtOptional, vtOptional,vtOptional,vtOptional,vtOptional);

// открыть документ для вставки данных
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);
// заполнить данными
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");

// сохранить и закрыть файл
oDataDoc.Save();
oDataDoc.Close(vtFalse,vtOptional,vtOptional);
}

Cтатья откуда взят код на английском языке http://support.microsoft.com/kb/278260

1 комментарий:

Di комментирует...

Здравствуйте!
Извините, может отвлекаю,тут описывается как в Word вписывать данные, а вот нам надо наоборот извлекать. Например, как извлечь все абзацы из документа? Потом извлечь все картинки из него? Все заголовки всех уровней? Все таблицы? Т.е. сделать несколько циклов по извлечению всех этих объектов от начала до конца документа.
Потом надо сохранить структуру этого документа в XML, а сами объекты (абзацы,...) в HTML. Т.е. реализовать своеобразный конвертор из Word в html.
Может, Вы знаете, как это осуществить? В Интернете очень мало информации на эту тему. Заранее очень благодарны.
Мой e-mail: diana_pikaso@mail.ru