VC操作word和excel文件,查詢與讀寫[依賴office環境]


2016-07-26 10:15AM 田海濤>>記錄>>合肥工業大學

由於孟師兄的碗扣式支架建模系統需求,須在程序中加入office相關處理,具體為讀取excel文件與生成word文件

Excel讀取未采用第三方封裝類,直接使用com動態鏈接庫調用Windows中的excel.application,word采用網上的第三方封裝類,但是封裝類並不那么健全,自己又添加了幾個實用的或者是自己需要的函數,包括添加字段,調整字體,調整段落格式,插入表格,表格中插入文字,合並表格,調整表格列寬這些函數,原本的封裝類中的函數基本沒用到,不過好在原作者已經將com庫的初始化及掃尾清理工作健全,省去了很多麻煩,現留下源碼以備不時之需。

ms提供的庫函數接口和以前的VBA代碼非常類似,因此自己添加函數時很大程度依賴對office操作過程錄制宏來獲取相應的VBA執行代碼,再將VBA代碼進一步改寫到c/c++平台上,添加函數時msoffice提供的庫函數中的很多函數參數對應的數值分別代表什么意義並不清楚,舉個例子:

假如使用一個庫函數來對word或excel文件中添加一段話,這時庫函數AddParagraph可以直接調用添加,但是如何控制這段文字是左對齊還是右對齊還是居中,就需要一個參數來控制,而這個參數分別是用1,2,3對應左,中,右,但是通過錄制office的VBA代碼看到左中右分別為xLeft,xCenter,xRight,這三個宏定義是VBA中的宏定義,在c語言的庫中並不是這樣定義,或者壓根就沒有定義,因此我們可以通過在office中改寫VBA代碼將xLeft,xCenter,xRight三個宏定義的以整數的形式寫到一個字符串里,將該字符串打印在word中就可以看到這三個宏定義分別是對應那幾個數字,c庫函數中的參數與VB庫中對應函數的參數相比是沒什么改變的,因此我們可以在VC代碼中自己定義相應的xLeft,xCenter,xRight宏定義,就解決了函數參數不明的問題。


////////////////////以下為office服務宏定義,可從office文檔中//////////////////////////////
///////////// 錄制相關動作的宏定義獲知需要哪些宏定義值,並通過改寫vba代碼寫出所需宏值///////////////////////////////
#define xlAscending (long) 1
#define xlDescending (long) 2
#define vOpt COleVariant((long) DISP_E_PARAMNOTFOUND,VT_ERROR)
#define xlHeader (long) 1 // 選取的區域有標題
#define xlNoHeader (long) 2 // 選取的區域無標題,一定要正確確定是否有標題,否則排序可能不成功
#define xlMatchCase COleVariant((long) 1)
#define xlIgnoreCase COleVariant((long) 0)
#define xlTopToBottom (long) 1 // 垂直方向進行排序
#define xlLeftToRight (long) 2 // 水平方向進行排序
#define xlPinYin (long) 1 // this is thedefault // 按字符的中文拼音進行排序
#define xlStroke (long) 2 // 按每個字符中的筆畫數進行排序
////////////////////以上為office服務宏定義/////////////////////////////////////

  圖片

以上excel所需類包含在excel.h,excel.cpp中,可直接從offfice目錄中導入(*:\ProgramFiles (x86)\Microsoft Office\Office14\EXCEL.EXE)

void InputExcel() //讀取excel

{
CFileDialog file(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
_T("EXCEL文件t(*.xls;*.xlsx)|*.xls;*.xlsx||"),AfxGetMainWnd());
file.m_ofn.lpstrTitle = _T("導入位移文件...");
if(file.DoModal()!=IDOK)
{
AfxMessageBox("選擇窗口打開失敗");
return;
}
CString strFile=file.GetPathName();
m_Path.SetWindowText(strFile);
int i=0,j=0,k=0;
CString tempstr = "";
vector < CString > CellsVal(20);
CellsVal.resize(20);

_ApplicationE app;
_Workbook book;
_Worksheet sheet;
Workbooks books;
Worksheets sheets;
Range range;
LPDISPATCH lpDisp;
COleVariant vResult;
COleVariant covTrue((short)TRUE);
COleVariant covFalse((short)FALSE);
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
//創建Excel服務器(啟動Excel)
if(!app.CreateDispatch("Excel.Application"))
{
AfxMessageBox("無法啟動Excel服務器!");
return;
}
app.SetVisible(FALSE); //使Excel不可見
books.AttachDispatch(app.GetWorkbooks());
lpDisp = books.Open(strFile, //打開所需excel文件
covOptional, covFalse, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional);

//得到Workbook
book.AttachDispatch(lpDisp);

//得到Worksheets
sheets.AttachDispatch(book.GetWorksheets());//

//如果有單元格正處於編輯狀態中,此操作不能返回,會一直等待
lpDisp=sheets.GetItem(COleVariant(short(1)));//獲取第一個sheet作為操作對象
sheet.AttachDispatch(lpDisp);

//讀取已經使用區域的信息,包括已經使用的行數、列數、起始行、起始列
Range usedRange;
usedRange.AttachDispatch(sheet.GetUsedRange());
range.AttachDispatch(usedRange.GetRows());
long RowNum=range.GetCount(); //已經使用的行數
range.ReleaseDispatch();
range.AttachDispatch(usedRange.GetColumns());
long ColNum=range.GetCount()-1; //獲取有效列數目,獲取結果總比實際多1
CString EndCellCode = "";
EndCellCode.Format("%s%d",TranslateColName(ColNum),
RowNum);// TranslateColName()函數用於將col號碼由數字轉換為26進制字母組合
VARIANT key1; //定義變量容納排序關鍵列
V_VT(&key1) = VT_DISPATCH; // 排序時,關鍵字的vt設置為VT_DISPATCH

V_DISPATCH(&key1) = sheet.GetRange(COleVariant("H1"),
COleVariant("H1")); // 設置按哪個關鍵字進行排序 選擇單元意為:按此列(或行)為主關鍵字進行排序
Range iRange = sheet.GetRange(COleVariant("C3"),COleVariant(EndCellCode));//設置排序范圍為C3到表格末尾
iRange.Sort(key1, xlAscending, vOpt, vOpt, xlAscending, vOpt,xlAscending,
xlNoHeader,vOpt,xlIgnoreCase,xlTopToBottom,
xlPinYin,0,0,0); //設置排序 無標題時一定要設置為xlNoHeader 否則不起作用,這里參數為宏定義,具體定義值通過office宏錄制可以獲取,方法參照VBA語言格式,Selection.TypeText Val=Str(xlNoHeader)即可將xlNoHeader值顯示出來,其他宏定義量同理得到。

CString tempSCell = "";
CString tempECell = "";
tempSCell.Format("C3");
tempECell.Format("C4");
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
VARIANT varRead = iRange.GetValue2();
COleSafeArray olesaRead(varRead);
GetValFromArry(&olesaRead,&CellsVal);
olesaRead.Detach();
CString minHcodeCVal0 = CellsVal[0];


tempSCell.Format("C%d",RowNum);
tempECell.Format("C%d",RowNum+1);
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
olesaRead.Clear();
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);//自定義GetValFromArry()函數獲取指定格子的數據,傳入CellsVal中,
CString maxHcodeCVal0 = CellsVal[0];
/////////////////////////////////////////////////////////////////////////////////////////

V_DISPATCH(&key1) = sheet.GetRange(COleVariant("I1"),COleVariant("I1"));
// 設置按哪個關鍵字進行排序 選擇單元意為:按此列(或行)為主關鍵字進行排序
//range=sheet.GetRange(COleVariant(L"A1"),COleVariant(CellName));
// 選擇對哪些區域內的單元格進行排序
iRange = sheet.GetRange(COleVariant("C3"),COleVariant(EndCellCode));
iRange.Sort(key1, xlAscending, vOpt, vOpt, xlAscending, vOpt,xlAscending,
xlNoHeader,vOpt,xlIgnoreCase,xlTopToBottom,xlPinYin,0,0,0);
//設置排序 無標題時一定要設置為xlNoHeader 否則不起作用

tempSCell.Format("C3");
tempECell.Format("C4");
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
olesaRead.Detach();
CString minIcodeCVal0 = CellsVal[0];
//AfxMessageBox(minJcodeCVal);


tempSCell.Format("C%d",RowNum);
tempECell.Format("C%d",RowNum+1);
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
olesaRead.Clear();
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
CString maxIcodeCVal0 = CellsVal[0];
///////////////////////////////////////////////////////////////////////////////////

V_DISPATCH(&key1) = sheet.GetRange(COleVariant("J1"),COleVariant("J1"));
// 設置按哪個關鍵字進行排序 選擇單元意為:按此列(或行)為主關鍵字進行排序
//range=sheet.GetRange(COleVariant(L"A1"),COleVariant(CellName));
// 選擇對哪些區域內的單元格進行排序
iRange = sheet.GetRange(COleVariant("C3"),COleVariant(EndCellCode));
iRange.Sort(key1, xlAscending, vOpt, vOpt, xlAscending, vOpt,xlAscending,
xlNoHeader,vOpt,xlIgnoreCase,xlTopToBottom,xlPinYin,0,0,0);
//設置排序 無標題時一定要設置為xlNoHeader 否則不起作用

tempSCell.Format("C3");
tempECell.Format("C4");
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
olesaRead.Detach();
CString minJcodeCVal0 = CellsVal[0];
//AfxMessageBox(minJcodeCVal);


tempSCell.Format("C%d",RowNum);
tempECell.Format("C%d",RowNum+1);
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
olesaRead.Clear();
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
CString maxJcodeCVal0 = CellsVal[0];
V_DISPATCH(&key1) = sheet.GetRange(COleVariant("C1"),COleVariant("C1"));
// 設置按哪個關鍵字進行排序 選擇單元意為:按此列(或行)為主關鍵字進行排序
lpDisp = sheet.GetRange(COleVariant("C3"), COleVariant(EndCellCode));
iRange.AttachDispatch(lpDisp);
iRange.Sort(key1, xlAscending, vOpt, vOpt, xlAscending, vOpt,xlAscending,
xlNoHeader,vOpt,xlIgnoreCase,xlTopToBottom,xlPinYin,0,0,0);
//設置排序 無標題時一定要設置為xlNoHeader 否則不起作用
///////////////////////////////////////////////////////////////////////////////////
GetCVal0.clear();//以下多個vector數組用於儲存excel中讀取的各列數據
GetDVal0.clear();
GetHVal0.clear();
GetIVal0.clear();
GetJVal0.clear();
GetCVal0.resize(40);
GetDVal0.resize(40);
GetHVal0.resize(40);
GetIVal0.resize(40);
GetJVal0.resize(40);
ValCount0=0;
for(int SRow=3;SRow<=RowNum;SRow++)
{
tempSCell.Format("C%d",SRow);
tempECell.Format("C%d",SRow+1);
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
olesaRead.Detach();
//下面語句用於通過讀取每行excel數據並進行判斷,一旦發現有符合篩選條件的數據,
//即進行該行的某些列數據的存儲,GetValFromArry用於取得所需格子數據的自定義函數
if((minHcodeCVal0 == CellsVal[0])||(maxHcodeCVal0 == CellsVal[0])||
(minIcodeCVal0 == CellsVal[0])||(maxIcodeCVal0 == CellsVal[0])||
(minJcodeCVal0 == CellsVal[0])||(maxJcodeCVal0 == CellsVal[0]))
{
GetCVal0[ValCount0].Format("%d",atoi(CellsVal[0]));
tempSCell.Format("D%d",SRow);
tempECell.Format("D%d",SRow+1);
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
olesaRead.Detach();
GetDVal0[ValCount0]=CellsVal[0];

tempSCell.Format("H%d",SRow);
tempECell.Format("H%d",SRow+1);
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
olesaRead.Detach();
GetHVal0[ValCount0]=CellsVal[0];

tempSCell.Format("I%d",SRow);
tempECell.Format("I%d",SRow+1);
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
olesaRead.Detach();
GetIVal0[ValCount0] = CellsVal[0];

tempSCell.Format("J%d",SRow);
tempECell.Format("J%d",SRow+1);
lpDisp = sheet.GetRange(COleVariant(tempSCell), COleVariant(tempECell));
iRange.AttachDispatch(lpDisp);
varRead = iRange.GetValue2();
olesaRead.Attach(varRead);
GetValFromArry(&olesaRead,&CellsVal);
olesaRead.Detach();
GetJVal0[ValCount0++] = CellsVal[0];

}
}


//book.Save();//讀取完畢后根據需要決定是否保存,並關閉服務,釋放個com變量
book.Close(covFalse,COleVariant(strFile),covOptional);
books.Close();
app.Quit();
range.ReleaseDispatch();
sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch();
books.ReleaseDispatch();
app.ReleaseDispatch();
return;
}
CString TranslateColName(long ColNum)//列名轉換函數
{
char ColumnCode[3]={0};
ColumnCode[1]=ColNum%26+'A'-1;
if(ColNum>26)
{
ColumnCode[0]=ColNum/26+'A'-1;
}
else
{
ColumnCode[0]=ColumnCode[1];
ColumnCode[1]=0;
}
CString result("");
result.Format("%s",ColumnCode);
return result;

}

圖片
以上word所需類包含在msword.h,msword.cpp中,可直接從offfice目錄中導入(*:\ProgramFiles (x86)\Microsoft Office\Office14\MSWORD.OLB),msword.cpp文件通過第三方封裝類WordOffice內部使用。程序調用封住類即可,示例如下:

void Outputword()
{
CFileDialog dlg(FALSE,NULL,"*.doc",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"*.doc",NULL);
dlg.m_ofn.lpstrTitle = _T("導出到...");
int rc= dlg.DoModal();
if(rc != IDOK)
{
if(rc==IDCANCEL)
{
return;
}
AfxMessageBox("保存窗口打開失敗!");
return;
}
if(rc == IDOK)
{
CWordOffice m_Word;
m_Word.Create();
m_Word.AddParagraph("碗扣式滿堂支架監測方案\n\n",22,TRUE,"宋體",1,0);

m_Word.AddParagraph("1.應力測點布置方案\n",12,TRUE,"宋體",0,2);
m_Word.AddParagraph("根據Midas/Civil有限元分析軟件計算結果,"
"布置碗扣式滿堂支架應力監測測點布置方案如下所示。\n",12,FALSE,"宋體",0,2);
CString tempLastCVal ="";
int tempCount = 0;
for(i=0;i<ValCount;i++)
{
if(tempLastCVal==GetCVal[i])
tempCount++;
tempLastCVal=GetCVal[i];
}
if(ValCount>0)
{
ValCount=ValCount-tempCount;
tempLastCVal=GetCVal[0];
}
m_Word.InsertTable(ValCount*5+1+GradeID*6*5, 5);
m_Word.SetTableText(m_Word.m_wdTable,1,1,"序號",12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,1,2,"單元編號",12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,1,3,"坐標",12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,1,4,"荷載階段",12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,1,5,"應力值(MPa)",12,FALSE,"宋體",1);
CString OrderNum = "";
for(i=0,j=0;i<ValCount+GradeID*6;i++)
{
OrderNum.Format("%d",i+1);
m_Word.CellsMerge(m_Word.m_wdTable,i*5+2,1,i*5+6,1,OrderNum);
m_Word.CellsMerge(m_Word.m_wdTable,i*5+2,2,i*5+6,2,"單元號");
m_Word.CellsMerge(m_Word.m_wdTable,i*5+2,3,i*5+6,3,"x,y,z");
m_Word.SetTableText(m_Word.m_wdTable,i*5+2,4,"第一次預壓",12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,i*5+3,4,"第二次預壓",12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,i*5+4,4,"第三次預壓",12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,i*5+5,4,"第一次澆築",12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,i*5+6,4,"第二次澆築",12,FALSE,"宋體",1);
if(i<ValCount)
{
for(;j<ValCount+tempCount;)
{
if(tempLastCVal==GetCVal[j])
{
m_Word.SetTableText(m_Word.m_wdTable,i*5+2,2,tempLastCVal,12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,i*5+2,3,GetXYZ(atoi(tempLastCVal),m,n,r),12,FALSE,"宋體",1);
if(GetDVal[j]=="第一次預壓")
m_Word.SetTableText(m_Word.m_wdTable,i*5+2,5,GetJVal[j],12,FALSE,"宋體",1);
else if(GetDVal[j]=="第二次預壓")
m_Word.SetTableText(m_Word.m_wdTable,i*5+3,5,GetJVal[j],12,FALSE,"宋體",1);
else if(GetDVal[j]=="第三次預壓")
m_Word.SetTableText(m_Word.m_wdTable,i*5+4,5,GetJVal[j],12,FALSE,"宋體",1);
else if(GetDVal[j]=="第一次澆築")
m_Word.SetTableText(m_Word.m_wdTable,i*5+5,5,GetJVal[j],12,FALSE,"宋體",1);
else if(GetDVal[j]=="第二次澆築")
m_Word.SetTableText(m_Word.m_wdTable,i*5+6,5,GetJVal[j],12,FALSE,"宋體",1);
else
{};
j++;
}
else
{
tempLastCVal=GetCVal[j];
break;
}
}
}
else
{
OrderNum.Format("%d",L1_L6[(i-ValCount)/6][(i-ValCount)%6]);
m_Word.SetTableText(m_Word.m_wdTable,i*5+2,2,OrderNum,12,FALSE,"宋體",1);
m_Word.SetTableText(m_Word.m_wdTable,i*5+2,3,GetXYZ(atoi(OrderNum),m,n,r),12,FALSE,"宋體",1);
}
}
m_Word.SetColWidth(m_Word.m_wdTable,1,8.5);
m_Word.SetColWidth(m_Word.m_wdTable,2,12.9);
m_Word.SetColWidth(m_Word.m_wdTable,3,12.9);
m_Word.SetColWidth(m_Word.m_wdTable,4,15.2);
if(m_Word.SaveDocumentAs(dlg.GetPathName()))
{
AfxMessageBox("導出成功!");
}
else
AfxMessageBox("導出失敗!");
m_Word.CloseApp();
}
}
值得一提的是,測試word過程中發現office2010與office2007存在不兼容問題,經查證發現不兼容點位於_Document類中的SaveAs2函數中,office2007的_Document中並不包含該函數,而是SavaAs函數,因此修改官方類來保證兩函數均存在於_Document中,函數如下:

void _Document::SaveAs2(VARIANT* FileName, 
VARIANT* FileFormat,
VARIANT* LockComments,
VARIANT* Password,
VARIANT* AddToRecentFiles,
VARIANT* WritePassword,
VARIANT* ReadOnlyRecommended,
VARIANT* EmbedTrueTypeFonts,
VARIANT* SaveNativePictureFormat,
VARIANT* SaveFormsData,
VARIANT* SaveAsAOCELetter,
VARIANT* Encoding,
VARIANT* InsertLineBreaks,
VARIANT* AllowSubstitutions,
VARIANT* LineEnding,
VARIANT* AddBiDiMarks,
VARIANT* CompatibilityMode)
{
static BYTE parms[] = VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT;
InvokeHelper(0x238, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
FileName, FileFormat, LockComments, Password,
AddToRecentFiles, WritePassword, ReadOnlyRecommended,
EmbedTrueTypeFonts, SaveNativePictureFormat, SaveFormsData,
SaveAsAOCELetter, Encoding, InsertLineBreaks, AllowSubstitutions,
LineEnding, AddBiDiMarks, CompatibilityMode);
}

void _Document::SaveAs( VARIANT* FileName,
VARIANT* FileFormat,
VARIANT* LockComments,
VARIANT* Password,
VARIANT* AddToRecentFiles,
VARIANT* WritePassword,
VARIANT* ReadOnlyRecommended,
VARIANT* EmbedTrueTypeFonts,
VARIANT* SaveNativePictureFormat,
VARIANT* SaveFormsData,
VARIANT* SaveAsAOCELetter,
VARIANT* Encoding,
VARIANT* InsertLineBreaks,
VARIANT* AllowSubstitutions,
VARIANT* LineEnding,
VARIANT* AddBiDiMarks)
{
static BYTE parms[] = VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT
VTS_PVARIANT VTS_PVARIANT;
InvokeHelper(0x178, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
FileName, FileFormat, LockComments, Password,
AddToRecentFiles, WritePassword, ReadOnlyRecommended,
EmbedTrueTypeFonts, SaveNativePictureFormat, SaveFormsData,
SaveAsAOCELetter, Encoding, InsertLineBreaks, AllowSubstitutions,
LineEnding, AddBiDiMarks);
}

添加完畢后發現office2010與office2007均可使用SaveAs函數,只是SaveAs2較SaveAs多了一個參數,必然多了一個功能,因此扔保留兩個函數,不久將來待2007完全淘汰,以保證該修改官方類扔可繼續使用。

網上找的第三方封裝類WordOffice經過本人補充自己所需功能后code如下:

WordOffice.h

#include "msword.h"
#include <atlbase.h>

class CWordOffice
{
//private:
public:
_ApplicationW m_wdApp;
Documents m_wdDocs;
_Document m_wdDoc;
Selection m_wdSel;
RangeW m_wdRange;
InlineShapes m_wdInlineShapes;
InlineShape m_wdInlineShape;
_Font m_wdFont;
Paragraph m_wdParagraph;
Paragraphs m_wdParagraphs;
Cell m_wdCell;
Cells m_wdCells;
Table m_wdTable;
Tables m_wdTables;
Border m_wdBorder;
Borders m_wdBorders;
CWordOffice();
virtual ~CWordOffice();

public:
void SetColWidth(Table m_Table,int Col,float Percent);
LPDISPATCH InsertTable(int Row,int Col);
void CellsMerge(Table m_Table, int SX, int SY, int EX, int EY,CString TextStr);
void AddParagraph(CString szText,float FontSize,BOOL IfBold,CString FontName,int AlignFlag,float FirstLineSpace);
void SetTableText(Table m_Table,int RowNum,int ColNum,CString szText,
float FontSize,BOOL IfBold,CString FontName,int AlignFlag);
//操作
//**********************創建新文檔*******************************************
BOOL CreateApp(); //創建一個新的WORD應用程序
BOOL CreateDocuments(); //創建一個新的Word文檔集合
BOOL CreateDocument(); //創建一個新的Word文檔
BOOL Create(); //創建新的WORD應用程序並創建一個新的文檔
void ShowApp(); //顯示WORD文檔
void HideApp(); //隱藏word文檔

//**********************打開文檔*********************************************
BOOL OpenDocument(CString fileName);//打開已經存在的文檔。
BOOL Open(CString fileName); //創建新的WORD應用程序並打開一個已經存在的文檔。
BOOL SetActiveDocument(short i); //設置當前激活的文檔。

//**********************保存文檔*********************************************
BOOL SaveDocument(); //文檔是以打開形式,保存。
BOOL SaveDocumentAs(CString fileName);//文檔以創建形式,保存。
BOOL CloseDocument();
void CloseApp();

//**********************文本書寫操作*****************************************
void WriteText(CString szText); //當前光標處寫文本
void WriteNewLineText(CString szText, int nLineCount = 1); //換N行寫字
void WriteEndLine(CString szText); //文檔結尾處寫文本
void WriteEndLine(CString szText,float FontSize,BOOL IfBold,CString FontName);
void WholeStory(); //全選文檔內容
void Copy(); //復制文本內容到剪貼板
void InsertFile(CString fileName); //將本地的文件全部內容寫入到當前文檔的光標處。

//**********************圖片插入操作*****************************************
void InsertShapes(CString fileName);//在當前光標的位置插入圖片

//**********************超鏈接插入操作*****************************************
void InsertHyperlink(CString fileLink);//超級鏈接地址,可以是相對路徑。
};
WordOffice.cpp

#include "WordOffice.h"

CWordOffice::CWordOffice()
{

}
CWordOffice::~CWordOffice()
{
COleVariant vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_wdApp.Quit(vFalse, // SaveChanges.
vTrue, // OriginalFormat.
vFalse // RouteDocument.
);
//釋放內存申請資源
m_wdFont.ReleaseDispatch();
m_wdParagraph.ReleaseDispatch();
m_wdParagraphs.ReleaseDispatch();
m_wdCell.ReleaseDispatch();
m_wdCells.ReleaseDispatch();
m_wdTable.ReleaseDispatch();
m_wdTables.ReleaseDispatch();
m_wdBorder.ReleaseDispatch();
m_wdBorders.ReleaseDispatch();
//m_wdPagesetup.ReleaseDispatch();

m_wdInlineShape.ReleaseDispatch();
m_wdInlineShapes.ReleaseDispatch();
//m_wdTb.ReleaseDispatch();
m_wdRange.ReleaseDispatch();
m_wdSel.ReleaseDispatch();
//m_wdFt.ReleaseDispatch();
m_wdDoc.ReleaseDispatch();
m_wdDocs.ReleaseDispatch();
m_wdApp.ReleaseDispatch();
}

//操作
BOOL CWordOffice::CreateApp()
{
if (FALSE == m_wdApp.CreateDispatch("Word.Application"))
{
AfxMessageBox("Application創建失敗,請確保安裝了word 2000或以上版本!", MB_OK|MB_ICONWARNING);
return FALSE;
}
return TRUE;
}

BOOL CWordOffice::CreateDocuments()
{
if (FALSE == CreateApp())
{
return FALSE;
}
m_wdDocs.AttachDispatch(m_wdApp.GetDocuments());
if (!m_wdDocs.m_lpDispatch)
{
AfxMessageBox("Documents創建失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
return TRUE;
}

BOOL CWordOffice::CreateDocument()
{
if (!m_wdDocs.m_lpDispatch)
{
AfxMessageBox("Documents為空!", MB_OK|MB_ICONWARNING);
return FALSE;
}

COleVariant varTrue(short(1),VT_BOOL),vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
CComVariant Template(_T("")); //沒有使用WORD的文檔模板
CComVariant NewTemplate(false),DocumentType(0),Visible;

m_wdDocs.Add(&Template,&NewTemplate,&DocumentType,&Visible);

//得到document變量
m_wdDoc = m_wdApp.GetActiveDocument();
if (!m_wdDoc.m_lpDispatch)
{
AfxMessageBox("Document獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
//得到selection變量
m_wdSel = m_wdApp.GetSelection();
if (!m_wdSel.m_lpDispatch)
{
AfxMessageBox("Select獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
//得到RangeW變量
m_wdRange = m_wdDoc.RangeW(vOptional,vOptional);
if(!m_wdRange.m_lpDispatch)
{
AfxMessageBox("RangeW獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}

return TRUE;
}

BOOL CWordOffice::Create()
{
if (FALSE == CreateDocuments())
{
return FALSE;
}
return CreateDocument();
}

void CWordOffice::ShowApp()
{
m_wdApp.SetVisible(TRUE);
}

void CWordOffice::HideApp()
{
m_wdApp.SetVisible(FALSE);
}

BOOL CWordOffice::OpenDocument(CString fileName)
{
if (!m_wdDocs.m_lpDispatch)
{
AfxMessageBox("Documents為空!", MB_OK|MB_ICONWARNING);
return FALSE;
}

COleVariant vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR),
vZ((short)0);
COleVariant vFileName(_T(fileName));

//得到document變量
m_wdDoc.AttachDispatch(m_wdDocs.Open(
vFileName, // FileName
vTrue, // Confirm Conversion.
vFalse, // ReadOnly.
vFalse, // AddToRecentFiles.
vOptional, // PasswordDocument.
vOptional, // PasswordTemplate.
vOptional, // Revert.
vOptional, // WritePasswordDocument.
vOptional, // WritePasswordTemplate.
vOptional, // Format. // Last argument for Word 97
vOptional, // Encoding // New for Word 2000/2002
vOptional, // Visible
//如下4個是word2003需要的參數。本版本是word2000。
vOptional, // OpenAndRepair
vZ, // DocumentDirection wdDocumentDirection LeftToRight
vOptional, // NoEncodingDialog
vOptional

) // Close Open parameters
); // Close AttachDispatch

if (!m_wdDoc.m_lpDispatch)
{
AfxMessageBox("Document獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
//得到selection變量
m_wdSel = m_wdApp.GetSelection();
if (!m_wdSel.m_lpDispatch)
{
AfxMessageBox("Select獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
//得到全部DOC的RangeW變量
m_wdRange = m_wdDoc.RangeW(vOptional,vOptional);
if(!m_wdRange.m_lpDispatch)
{
AfxMessageBox("RangeW獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
return TRUE;
}

BOOL CWordOffice::Open(CString fileName)
{
if (FALSE == CreateDocuments())
{
return FALSE;
}
return OpenDocument(fileName);
}

BOOL CWordOffice::SetActiveDocument(short i)
{
COleVariant vIndex(_T(i)),vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

m_wdDoc.AttachDispatch(m_wdDocs.Item(vIndex));
m_wdDoc.Activate();
if (!m_wdDoc.m_lpDispatch)
{
AfxMessageBox("Document獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
//得到selection變量
m_wdSel = m_wdApp.GetSelection();
if (!m_wdSel.m_lpDispatch)
{
AfxMessageBox("Select獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
//得到全部DOC的RangeW變量
m_wdRange = m_wdDoc.RangeW(vOptional,vOptional);
if(!m_wdRange.m_lpDispatch)
{
AfxMessageBox("RangeW獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
HideApp();
return TRUE;
}

BOOL CWordOffice::SaveDocument()
{
if (!m_wdDoc.m_lpDispatch)
{
AfxMessageBox("Document獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
m_wdDoc.Save();
return TRUE;
}

BOOL CWordOffice::SaveDocumentAs(CString fileName)
{
if (!m_wdDoc.m_lpDispatch)
{
AfxMessageBox("Document獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
COleVariant vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
COleVariant vFileName(_T(fileName));

m_wdDoc.SaveAs(//
vFileName, //VARIANT* FileName
vOptional, //VARIANT* FileFormat
vOptional, //VARIANT* LockComments
vOptional, //VARIANT* Password
vOptional, //VARIANT* AddToRecentFiles
vOptional, //VARIANT* WritePassword
vOptional, //VARIANT* ReadOnlyRecommended
vOptional, //VARIANT* EmbedTrueTypeFonts
vOptional, //VARIANT* SaveNativePictureFormat
vOptional, //VARIANT* SaveFormsData
vOptional, //VARIANT* SaveAsAOCELetter
vOptional,
vOptional,
vOptional,
vOptional,
//vOptional,
vOptional
);
return TRUE;
}

BOOL CWordOffice::CloseDocument()
{
COleVariant vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_wdDoc.Close(vFalse, // SaveChanges.
vTrue, // OriginalFormat.
vFalse // RouteDocument.
);
m_wdDoc.AttachDispatch(m_wdApp.GetActiveDocument());
if (!m_wdDoc.m_lpDispatch)
{
AfxMessageBox("Document獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
//得到selection變量
m_wdSel = m_wdApp.GetSelection();
if (!m_wdSel.m_lpDispatch)
{
AfxMessageBox("Select獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
//得到全部DOC的RangeW變量
m_wdRange = m_wdDoc.RangeW(vOptional,vOptional);
if(!m_wdRange.m_lpDispatch)
{
AfxMessageBox("RangeW獲取失敗!", MB_OK|MB_ICONWARNING);
return FALSE;
}
return TRUE;
}

void CWordOffice::CloseApp()
{
COleVariant vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_wdDoc.Save();
m_wdApp.Quit(vFalse, // SaveChanges.
vTrue, // OriginalFormat.
vFalse // RouteDocument.
);
//釋放內存申請資源
m_wdInlineShape.ReleaseDispatch();
m_wdInlineShapes.ReleaseDispatch();
//m_wdTb.ReleaseDispatch();
m_wdRange.ReleaseDispatch();
m_wdSel.ReleaseDispatch();
//m_wdFt.ReleaseDispatch();
m_wdDoc.ReleaseDispatch();
m_wdDocs.ReleaseDispatch();
m_wdApp.ReleaseDispatch();
}

void CWordOffice::WriteText(CString szText)
{
m_wdSel.TypeText(szText);
}
/*void CWordOffice::WriteText(CString szText,CString FontVal,int FontSize,BOOL IfBold,)
{
m_wdSel.TypeText(szText);
}*/

void CWordOffice::WriteNewLineText(CString szText, int nLineCount /* = 1 */)
{
int i;
if (nLineCount <= 0)
{
nLineCount = 0;
}
for (i = 0; i < nLineCount; i++)
{
m_wdSel.TypeParagraph();
}
WriteText(szText);
}

void CWordOffice::WriteEndLine(CString szText)
{
m_wdRange.InsertAfter(szText);
}

void CWordOffice::WriteEndLine(CString szText,float FontSize,BOOL IfBold,CString FontName)
{

m_wdRange.InsertAfter(szText);
m_wdFont = m_wdRange.GetFont();
m_wdFont.SetSize(FontSize);
m_wdFont.SetBold(IfBold);
m_wdFont.SetName(FontName);
m_wdRange.SetFont(m_wdFont);


}

void CWordOffice::WholeStory()
{
m_wdRange.WholeStory();
}

void CWordOffice::Copy()
{
m_wdRange.CopyAsPicture();
}

void CWordOffice::InsertFile(CString fileName)
{
COleVariant vFileName(fileName),
vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR),
vNull(_T(""));

m_wdSel.InsertFile(
fileName,
vNull,
vFalse,
vFalse,
vFalse
);
}

void CWordOffice::InsertShapes(CString fileName)
{
COleVariant vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_wdInlineShapes=m_wdSel.GetInlineShapes();
m_wdInlineShape=m_wdInlineShapes.AddPicture(fileName,vFalse,vTrue,vOptional);
}

void CWordOffice::InsertHyperlink(CString fileLink)
{
COleVariant vAddress(_T(fileLink)),vSubAddress(_T(""));
RangeW aRange = m_wdSel.GetRange();
Hyperlinks vHyperlinks(aRange.GetHyperlinks());
vHyperlinks.Add(
aRange, //Object,必需。轉換為超鏈接的文本或圖形。
vAddress, //Variant 類型,可選。指定的鏈接的地址。此地址可以是電子郵件地址、Internet 地址或文件名。請注意,Microsoft Word 不檢查該地址的正確性。
vSubAddress, //Variant 類型,可選。目標文件內的位置名,如書簽、已命名的區域或幻燈片編號。
vAddress, //Variant 類型,可選。當鼠標指針放在指定的超鏈接上時顯示的可用作“屏幕提示”的文本。默認值為 Address。
vAddress, //Variant 類型,可選。指定的超鏈接的顯示文本。此參數的值將取代由 Anchor 指定的文本或圖形。
vSubAddress //Variant 類型,可選。要在其中打開指定的超鏈接的框架或窗口的名字。
);
vHyperlinks.ReleaseDispatch();
}

LPDISPATCH CWordOffice::InsertTable(int Row, int Col)
{
COleVariant vTrue((short)TRUE),
vFalse((short)FALSE),
vOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_wdRange = m_wdSel.GetRange();
m_wdTables = m_wdDoc.GetTables();
m_wdTable=m_wdTables.Add(m_wdRange,Row,Col,vOptional,vOptional);
m_wdBorders=m_wdTable.GetBorders();
m_wdBorders.SetEnable(1);
m_wdSel.EndKey(COleVariant((short)6),COleVariant((short)0));
return m_wdTable;

}

void CWordOffice::AddParagraph(CString szText,float FontSize,BOOL IfBold,CString FontName,int AlignFlag,float FirstLineSpace)
{
m_wdParagraphs=m_wdDoc.GetParagraphs();
m_wdParagraph=m_wdParagraphs.GetLast();
m_wdParagraph.SetAlignment(AlignFlag);
m_wdParagraph.SetCharacterUnitFirstLineIndent(FirstLineSpace);
m_wdFont = m_wdSel.GetFont();
m_wdFont.SetSize(FontSize);
m_wdFont.SetName(FontName);
m_wdFont.SetBold(IfBold);
m_wdSel.TypeText(szText);
m_wdSel.EndKey(COleVariant((short)6),COleVariant((short)0));
}

void CWordOffice::SetTableText(Table m_Table,int RowNum,int ColNum,CString szText,float FontSize,BOOL IfBold,CString FontName,int AlignFlag)
{
Cell m_Cell;
RangeW m_RangeW;
_Font m_Font;
m_Cell.AttachDispatch(m_Table.Cell(RowNum,ColNum));
m_RangeW.AttachDispatch(m_Cell.GetRange());
m_RangeW.SetText(szText);
m_Font.AttachDispatch(m_RangeW.GetFont());
m_Font.SetSize(FontSize);
m_RangeW.Select();
_ParagraphFormat m_ParagraphFormat = ((Selection)(m_wdApp.GetSelection())).GetParagraphFormat();
m_ParagraphFormat.SetAlignment(AlignFlag);
((Selection)(m_wdApp.GetSelection())).SetParagraphFormat(m_ParagraphFormat);
((Cells)((Selection)(m_wdApp.GetSelection())).GetCells()).SetVerticalAlignment(1);
m_Font.SetName(FontName);
m_Font.SetBold(IfBold);
m_RangeW.SetFont(m_Font);
m_Cell.ReleaseDispatch();
m_RangeW.ReleaseDispatch();
m_wdSel.EndKey(COleVariant((short)6),COleVariant((short)0));

return ;

}

void CWordOffice::CellsMerge(Table m_Table, int SX, int SY, int EX, int EY,CString TextStr)
{
Cell m_Cell;
m_Cell.AttachDispatch(m_Table.Cell(SX,SY));
m_Cell.Merge(m_Table.Cell(EX,EY));
m_Cell.ReleaseDispatch();
SetTableText(m_Table,SX,SY,TextStr,12,FALSE,"宋體",1);
}

void CWordOffice::SetColWidth(Table m_Table, int Col, float Percent)
{
((Column)(((Columns)(m_Table.GetColumns())).Item(Col))).SetPreferredWidthType(2);
((Column)(((Columns)(m_Table.GetColumns())).Item(Col))).SetPreferredWidth(Percent);
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com