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);
}


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值