使用VC操作EXCEL
1. 方法概述
使用VC写EXCEL主要是通过COM方式。导入EXCEL类的方式如下:
创建一个MFC工程
直接根据需求创建一个MFC工程即可。
导入EXCEL类
在工程上点击右键选择添加类,在模板上选择TypeLib中的MFC类
在后面的从类型库添加向导中选择从文件添加类,然后选中在本机中EXCEL.EXE的位置,如果是老版本的EXCEL可能需要选择EXCEL9.OLB(EXCEL2000)这样的文件。然后在接口中选择我们所需要的操作EXCEL的接口,也可以全选中所有的接口,但是大部分的接口并不是我们所需要的,所以我们只需要选择我们需要的那些接口就行了,一般我们需要选择的是_Application、_Workbook、_Worksheet、Font、Worksheets、Workbooks、Range、Ranges,点击确定,我们每一个选择的接口都会生成一个类,如果使用老版本的VS和EXCEL会生成一个excel.h文件,在文件中包括这些所有的类。如果使用VS2005以上的版本每个类都会生成一个头文件和一个.cpp文件。
然后我们就成功的导入了所需要的函数。我们可以在后面进行调用了。基本的使用COM的方式无论C和TCL基本上都是类似的。
2. 打开文件
Excel接口类中层次如下所示:
_Application
Workbooks 工作薄集合
_Workbook 工作薄
Worksheets 工作表集合
_Worksheet 工作表
Range单元格区域
故要操作表,必须先逐步获取Workbooks—>Workbook —>Worksheets —>Worksheet —>Range。使用_Application创建一个EXCEL进程,定义_Application m_ExcelApp。使用m_ExcelApp.CreateDispatch(_T("Excel.Application"),NULL)创建一个EXCEL进程,在这里需要对创建是否成功进行判断,CreateDispatch失败返回FALSE。 然后可以对进程进行设置m_ExcelApp.SetUserControl(TRUE/FALSE)可以设置是否允许其他用户控制EXCEL,m_ExcelApp.SetVisible(TRUE/FALSE )可以设置EXCEL是否可视。m_ExcelApp.SetDisplayAlerts(TRUE/FALSE)可以设置EXCEL是否报警,比如合并单元格的时候EXCEL是否会报警。
然后打开Workbooks使用m_ExcelBooks = m_ExcelApp.GetWorkbooks();
接着可以选择打开文件使用一个LPDISPATCH lpDisp;
LPDISPATCH是COM编程中的一个接口应用,主要负责支持自动化的接口调用。
lpDisp = m_ExcelBooks.Open( strFileFullName, covOptional, covOptional,covOptional, covOptional, covOptional, covOptional,covOptional, covOptional, covOptional, covOptional,covOptional, covOptional, covOptional, covOptional);
strFileFullName是文件的路径。
使用m_ExcelBook.AttachDispatch(lpDisp),可以将打开的文件加入工作簿集。
然后,获得WorkSheets,使用m_ExcelSheets = m_ExcelBook.GetSheets()
获得打开的sheet:m_ExcelSheet = GetActiveSheet()
3. 关闭文件
关闭文件的时候需要一个个的释放申请的资源需要根据申请资源的顺序相反调用ReleaseDispatch();workbook需要先调用m_ExcelBook.Close( covOptional, COleVariant( strOutFileName ), covOptional ); 再释放,m_ExcelBooks也需要先调用m_ExcelBooks.Close();再释放,最后退出并释放Application,过程如下:
m_ExcelRange.ReleaseDispatch();
m_ExcelRanges.ReleaseDispatch();
m_ExcelSheet.ReleaseDispatch();
m_ExcelSheets.ReleaseDispatch();
m_ExcelBook.Close( covOptional, COleVariant( strOutFileName ), covOptional );
m_ExcelBook.ReleaseDispatch();
m_ExcelBooks.Close();
m_ExcelBooks.ReleaseDispatch();
m_ExcelApp.Quit();
m_ExcelApp.ReleaseDispatch();
4. 读文件
读文件主要是从文件中指定的单元格获得数据。可以根据指定的行和列确定单元格。方法如下:
首先需要定义一个Ole的变量类型 COleVariant vResult。
COleVariant 封装了VARIANT类型,VARIANT的结构可以参考头文件OAIDL.H中关于结构体tagVARIANT的定义。它主要包括两部分,一部分是VARTYPE指明变量的类型,另一部分是union。对VARIANT的赋值分为两步:首先给vt成员赋值,指明数据类型;然后对union中相同数据类型的变量赋值。
例如:如果为整型:
VARIANT va;
int a = 3021;
va.vt=VT_I4; //指明为整型数据
va.lVal=a; //赋值
如果为浮点数:
VARIANT va;
float a=20.1;
va.vt=VT_R4; //指明为浮点型数据
va.ftlVal=a; //赋值
然后获得指定的Range,使用方法m_ExcelRange.AttachDispatch(m_ExcelRanges.GetItem( COleVariant( nRow ), COleVariant( nCol ) ).pdispVal)先获得指定的Range,然后调用Range类的GetValue2方法
vResult = m_ExcelRange.GetValue2();然后根据不同的数据类型进行转换。方法如下:
CString CExcelApp::GetValueCell( short nRow, short nCol )
{
COleVariant vResult;
CString strValue;
m_ExcelRange.AttachDispatch( m_ExcelRanges.GetItem( COleVariant( nRow ), COleVariant( nCol ) ).pdispVal );
vResult = m_ExcelRange.GetValue2();
switch ( vResult.vt )
{
case VT_BSTR:
{
strValue = vResult.bstrVal;
}
break;
case VT_R8:
{
strValue.Format( _T("%f"), vResult.dblVal );
}
break;
case VT_DATE:
{
COleDateTime dDate;
dDate = vResult.date;
strValue = dDate.Format( _T("%Y-%m-%d") );
}
break;
case VT_EMPTY:
{
strValue = _T("");
}
break;
default:
strValue = _T("");
break;
}
return strValue;
}
5. 写文件
写文件的方法很简单只需要调用range类的SetItem就行了。
void CExcelApp::SetValueCell( short nRow, short nCol, CString strValue )
{
m_ExcelRanges.SetItem( COleVariant ( nRow ),
COleVariant( nCol ),
COleVariant( strValue ) );
}
6. 设置字体格式
设置字体主要包括设置字体大小,格式。在设置前首先需要定义一个Font类,然后调用range.GetFont();进行初始化然后调用Font.SetName(COleVariant(_T(“黑体”)))这样就可以设置字体了,字体大小调用Font.SetSize可以设置。方法如下:
void CExcelApp::SetFont( Range & rRange, CString font, int size)
{
m_ExcelFont = rRange.GetFont();
m_ExcelFont.SetName(COleVariant(font));
VARIANT varUnit;
VariantInit(&varUnit);
varUnit.vt = VT_I4;
varUnit.lVal = size;
if (size != 0)
{
m_ExcelFont.SetSize(varUnit);
}
}
7. 改变字体的颜色
改变字体颜色和上面是类似的调用字体Font类的SetColor方法即可。但是首先需要设定一个颜色定义变量VARIANT varUnit;初始化变量VariantInit(&varUnit);定义变量的格式:varUnit.vt = VT_UI4;然后设定变量的值varUnit.uintVal = RGB(0, 0, 0); RGB颜色:000可以替换成响应的值。RGB(0,0,0)代表黑色,RGB(255,255,255)代表黑色。方法如下
void CExcelApp::ChangeColor( Range & rRange, int color)
{
m_ExcelFont = rRange.GetFont();
VARIANT varUnit;
VariantInit(&varUnit);
varUnit.vt = VT_UI4;
switch(color)
{
case 0:
varUnit.uintVal = RGB(0, 0, 0);
break;
case 1:
varUnit.uintVal = RGB(255, 0, 0);
break;
case 2:
varUnit.uintVal = RGB(0, 255, 0);
break;
case 3:
varUnit.uintVal = RGB(0, 0, 255);
break;
default:
varUnit.uintVal = RGB(255, 255, 255);
}
m_ExcelFont.SetColor(varUnit);
}
8. 单元格操作
单元格操作是EXCEL操作中比较重要的内容之一,这里主要介绍合并单元格,拆分单元格,和获得合并的单元格等操作。
合并单元格
合并单元格就是将一部分单元格合并成一个单元格。首先,获得我们需要的range然后调用Range.Merge(COleVariant( (long)0 ))即可。获得指定的区域的方法是,获得单元格的起始位置和结束位置,然后调用m_ExcelRange.AttachDispatch( m_ExcelSheet.GetRange( CellStart, CellEnd ) );
即可以获得一块range。
拆分单元格
拆分单元格同上例一样,先获得range,然后调用rRange.UnMerge();即可。
获得合并的单元格
有时候我们需要判断我们选中的单元格是否是合并的单元格可以用如下方法:首先传入一个区域range,然后使用range.GetMergeArea获得整块合并的区域。然后,用整块区域的range获得所有行,然后使用GetCount计算总单元格数,即可得到行数,同理可得到列数,如果行列均为1则不是合并的单元格。方法如下:
BOOL CExcelApp::GetMergeRange( Range & rRange, int &nrow, int &ncolumn)
{
Range rangeMerge;
rangeMerge.AttachDispatch( rRange.GetMergeArea(), TRUE );
// 合并行数
rangeMerge.AttachDispatch( rangeMerge.GetRows(), TRUE );
nrow = rangeMerge.GetCount();
// 合并列数
rangeMerge.AttachDispatch( rangeMerge.GetColumns(), TRUE );
ncolumn = rangeMerge.GetCount();
if (1 == nrow && 1 == ncolumn)
{
return FALSE;
}
else
{
return TRUE;
}
}
获得合并单元格的左上角坐标
根据一个range然后获得它的合并区域,然后根据获得合并区域的行坐标和列坐标。方法如下:
void CExcelApp::GetRangePos( Range & rRange, int &row, int &column)
{
Range rangeMerge;
rangeMerge.AttachDispatch( rRange.GetMergeArea(), TRUE );
row = rangeMerge.GetRow();
column = rRange.GetColumn();
}
9. 插入一行和删除一行
首先需要定义EXCEL的移动方向值up为-4162,down为-4121插入一行就是获得要插入的Range后然后在上方插入空行。方法如下:
void CExcelApp::InsertRow( short nRowIndex, short nCount )
{
m_ExcelRange.AttachDispatch( m_ExcelSheet.GetRows() );
m_ExcelRange.AttachDispatch( m_ExcelRange.GetItem( COleVariant( nRowIndex ), vtMissing ).pdispVal );
for ( int i = 0; i < nCount; i++ )
m_ExcelRange.Insert( COleVariant( (long)xlUp ), vtMissing );
}
获得删除的行后,调用range.delete方法即可以删除一行
void CExcelApp::DeleteRow( short nRowIndex )
{
m_ExcelRange.AttachDispatch( m_ExcelSheet.GetRows() );
m_ExcelRange.AttachDispatch( m_ExcelRange.GetItem( COleVariant( nRowIndex ), vtMissing ).pdispVal );
m_ExcelRange.Delete( COleVariant( (long)xlUp ) );
}
10. 获得EXCEL有效行数和有效列数
获得EXCEL有效行和有效列的方法。Sheet类中有一个GetUsedRange方法,然后可以将获得的指针Attach到Range上,然后对Range类调用方法GetRows()将获得的指针Attach到Range上,然后获得Range的所有单元格就行了。获得有效列的方法类似。
long CExcelApp::GetRowCount()
{
Range rgRange;
rgRange.AttachDispatch(m_ExcelSheet.GetUsedRange(),TRUE);
Range rgRow;
long lRows;
rgRow.AttachDispatch(rgRange.GetRows(),TRUE);
lRows = rgRow.GetCount();
return lRows;
}
long CExcelApp::GetColumnCount()
{
Range rgRange;
rgRange.AttachDispatch(m_ExcelSheet.GetUsedRange(),TRUE);
Range rgColumn;
long lColumns;
rgColumn.AttachDispatch(rgRange.GetColumns(),TRUE);
lColumns = rgColumn.GetCount();
return lColumns;
}
11. 保存文件
保存文件分为保存和另存为两种形式。保存的时候直接调用excelbook.Save()就可以了。
另存为需要调用saveas的方法,具体如下:
void CExcelApp::SaveAs( CString strFileFullName )
{
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_ExcelBook.SaveAs( COleVariant( strFileFullName ), covOptional, covOptional,
covOptional, covOptional, covOptional, 0, covOptional,
covOptional, covOptional, covOptional, covOptional );
m_strSaveAsFilePath = strFileFullName;
}
12. 插入图片
插入图片,需要定义一个Shapes类型调用shapes的AddPicture方法
LPDISPATCH AddPicture(LPCTSTR Filename, //文件路径
long LinkToFile, //连接类型
long SaveWithDocument, //保存类型
float Left, //相对文件左上角
float Top, //相对文件顶部位置
float Width, //宽度
float Height) //高度
参数2和参数3都是MsoTriState类型:
对于参数2:
MsoTriState 可为以下 MsoTriState 常量之一。
msoCTrue
msoFalse 使图片成为其源文件的独立副本。
msoTriStateMixed
msoTriStateToggle
msoTrue 建立图片与其源文件之间的链接。
对于参数3:
MsoTriState 可为以下 MsoTriState 常量之一。
msoCTrue
msoFalse 在文档中只保存链接信息。
msoTriStateMixed
msoTriStateToggle
msoTrue 将链接图片与该图片插入的文档一起保存。如果 LinkToFile 为 msoFalse,则该参数必须为 msoTrue。
插入图片的基本方法就是获得要插入的位置,然后根据是否缩放控制图片的宽度和高度,然后调用AddPicture就行了,具体如下:
void CExcelApp::PictureInsert( Range &rRange, CString strFileFullName, BOOL bZoom )
{
Shapes shapes = m_ExcelSheet.GetShapes();
float fLeft, fTop, fWidth, fHeight;
fLeft = (float)rRange.GetLeft().dblVal;
fTop = (float)rRange.GetTop().dblVal;
if ( bZoom )
{
// 图片进行缩放,保持与指定Range区域大小一致
fWidth = (float)rRange.GetWidth().dblVal;
fHeight = (float)rRange.GetHeight().dblVal;
}
else
{
// 图片保持原大小
BITMAP bm;
HBITMAP hbitmap;
hbitmap = (HBITMAP) LoadImage(NULL, strFileFullName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(hbitmap, sizeof(bm), &bm);
fWidth = (float)bm.bmWidth;
fHeight = (float)bm.bmHeight;
}
shapes.AddPicture( strFileFullName, false, true, fLeft, fTop, fWidth, fHeight );
}
13. 设置边框
调用Range类的BorderAround(const VARIANT& LineStyle, long Weight, long ColorIndex, const VARIANT& Color)方法,四个参数分别代表线型,粗细,颜色,颜色。
void CExcelApp::SetBoarder( Range & rRange, int style, int thickness, int color)
{
_variant_t vRange1; // 设置单元格的线;
_variant_t vRange2;
_variant_t vRange3;
_variant_t vRange4;
// 线的样式:- no line; 1-solid; 2-big dot;3-small dot;4-dash dot; 5-dash dot dot;
vRange1.vt = VT_I2;
vRange1.lVal = style;
// 线的粗细程度
vRange2.vt = VT_I2;
vRange2.lVal = thickness;
//线的颜色1-black;2-white;3-red;4-green;5-blue; 6-yellow; 7-pink;8-dark blue;
vRange3.vt = VT_I2;
vRange3.lVal = color;
vRange4.vt = VT_I2;
vRange4.lVal = RGB(0,0,0);
rRange.BorderAround(vRange1, vRange2, vRange3, vRange4);
}
14. 设置行高和列宽
调用Range类的SetColumnWidth可以设置列宽,SetRowHight可以设置行高。
VARIANT ab;
ab.vt = VT_I4;
ab.intVal = 100;
range.SetColumnWidth(ab);
range.SetRowHeight(ab);
//ExecelAPP.h
#pragma once
#include "excel.h"
class CExcelApp
{
public:
CExcelApp();
virtual ~CExcelApp();
// Attributes
public:
BOOL m_bUserControl; // 是否允许其它用户控制Excel
BOOL m_bVisible; // Excel是否可视
BOOL m_bDisplayAlerts; // 是否显示警告
enum XlDirection
{
xlDown = -4121,
xlToLeft = -4159,
xlToRight = -4161,
xlUp = -4162
};
public:
_Application m_ExcelApp;
_Workbook m_ExcelBook;
_Worksheet m_ExcelSheet;
Workbooks m_ExcelBooks;
Worksheets m_ExcelSheets;
Range m_ExcelRange;
Range m_ExcelRanges;
xlsFont m_ExcelFont;
private:
CString m_strSaveAsFilePath;
CString m_strOpenFilePath;
// Operations
public:
//------------------------------------------------------------------------------
// 函数功能:
// 创建Excel服务
//
// 参数说明:
//
// 返回值:
// 成功返回TRUE,失败返回FALSE
//------------------------------------------------------------------------------
BOOL InitExcelApp();
//------------------------------------------------------------------------------
// 函数功能:
// 释放Excel所有应用 ( Range、Sheet、Sheets、…Application)
//
// 参数说明:
//
// 返回值:
//
//------------------------------------------------------------------------------
void ReleaseAll();
//------------------------------------------------------------------------------
// 函数功能:
// 打开已存在的xls文件
//
// 参数说明:
// 1) [IN ] CString strFileFullName // 文件全路径名称
//
// 返回值:
// 成功返回TRUE,失败返回FALSE
//------------------------------------------------------------------------------
BOOL Open( CString strFileFullName );
//------------------------------------------------------------------------------
// 函数功能:
// 获取Sheet页总数
//
// 参数说明:
//
// 返回值:
// Sheet页总数
//------------------------------------------------------------------------------
short GetSheetCount();
//------------------------------------------------------------------------------
// 函数功能:
// 依据Sheet索引号选择Sheet页并将其激活
//
// 参数说明:
// 1) [IN ] short nSheetIndex // Sheet页索引号
//
// 返回值:
// 返回成员WorkSheet的引用
//------------------------------------------------------------------------------
_Worksheet& SelectSheet( short nSheetIndex );
//------------------------------------------------------------------------------
// 函数功能:
// 依据Sheet页名称选择Sheet页并将其激活
//
// 参数说明:
// 1) [IN ] CString strSheetName // Sheet页名称
//
// 返回值:
// 返回成员WorkSheet的引用
//------------------------------------------------------------------------------
_Worksheet& SelectSheet( CString strSheetName );
//------------------------------------------------------------------------------
// 函数功能:
// 返回当前被激活的Sheet页
//
// 参数说明:
//
// 返回值:
// 返回成员WorkSheet的引用
//------------------------------------------------------------------------------
_Worksheet& GetActiveSheet();
//------------------------------------------------------------------------------
// 函数功能:
// 指定单元格进行赋值
//
// 参数说明:
// 1) [IN ] short nRow // 单元格行号
// 2) [IN ] short nCol // 单元格列号
// 3) [IN ] CString strValue // 单元格内容
//
// 返回值:
//
//------------------------------------------------------------------------------
void SetValueCell( short nRow, short nCol, CString strValue );
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定单元格的内容
//
// 参数说明:
// 1) [IN ] short nRow // 单元格行号
// 2) [IN ] short nCol // 单元格列号
//
// 返回值:
// 以字符串形式返回单元格的内容
//------------------------------------------------------------------------------
CString GetValueCell( short nRow, short nCol );
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定区域
//
// 参数说明:
// 1) [IN ] CString strCellStart // 起始单元格,如("C1")
// 2) [IN ] CString strCellEnd // 起始单元格,如("C2")
//
// 返回值:
// Range对象
//------------------------------------------------------------------------------
Range& GetRange( CString strCellStart, CString strCellEnd );
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定区域
//
// 参数说明:
// 1) [IN ] short nStartRow // 起始单元格行号
// 2) [IN ] short nStartCol // 起始单元格列号
// 3) [IN ] short nEndRow // 结束单元格行号
// 4) [IN ] short nEndCol // 结束单元格列号
//
// 返回值:
// 以字符串形式返回单元格的内容
//------------------------------------------------------------------------------
Range& GetRange( short nStartRow, short nStartCol, short nEndRow, short nEndCol );
//------------------------------------------------------------------------------
// 函数功能:
// 另存Excel文件
//
// 参数说明:
// 1) [IN ] CString strFileFullName // xls文件全路径名称
//
// 返回值:
//
//------------------------------------------------------------------------------
void SaveAs( CString strFileFullName );
//------------------------------------------------------------------------------
// 函数功能:
// 保存Excel文件
//
// 参数说明:
//
// 返回值:
//
//------------------------------------------------------------------------------
void Save();
//------------------------------------------------------------------------------
// 函数功能:
// 在指定行号上方插入若干行
//
// 参数说明:
// 1) [IN ] short nRowIndex // Excel行号
// 2) [IN ] short nCount // 插入的行数
//
// 返回值:
//
//------------------------------------------------------------------------------
void InsertRow( short nRowIndex, short nCount );
//------------------------------------------------------------------------------
// 函数功能:
// 删除指定行
//
// 参数说明:
// 1) [IN ] short nRowIndex // Excel行号
//
// 返回值:
//
//------------------------------------------------------------------------------
void DeleteRow( short nRowIndex );
//------------------------------------------------------------------------------
// 函数功能:
// 重新获取该sheet页的Range集合(说明:一般用在本Sheet页进行增删行导致Rang集合发生变化后,需要重置一次)
//
// 参数说明:
//
// 返回值:
//
//------------------------------------------------------------------------------
void ReSetRanges();
//------------------------------------------------------------------------------
// 函数功能:
// 合并单元格
//
// 参数说明:
// 1) [IN ] Range rRange // Range区域
//
// 返回值:
//
//------------------------------------------------------------------------------
void MergeRange( Range &rRange );
//------------------------------------------------------------------------------
// 函数功能:
// 在指定区域插入本地图片
//
// 参数说明:
// 1) [IN ] Range rRange // Range区域
// 2) [IN ] CString strFileFullName // 图片全路径文件名
// 3) [IN ] BOOL bZoom // 图片是否按指定区域大小进行缩放
//
// 返回值:
//
//------------------------------------------------------------------------------
void PictureInsert( Range &rRange, CString strFileFullName, BOOL bZoom );
//------------------------------------------------------------------------------
// 函数功能:
// 取消合并单元格
//
// 参数说明:
// 1) [IN ] Range rRange // Range区域
//
// 返回值:
//
//------------------------------------------------------------------------------
void UnMergeRange( Range & rRange );
//------------------------------------------------------------------------------
// 函数功能:
// 设置字体
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [IN ] Cstring font // 字体
// 3) [IN ] int size // 字号
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::SetFont( Range & rRange, CString font, int size = 0 );
//------------------------------------------------------------------------------
// 函数功能:
// 设置字体颜色
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [IN ] int color // 字体颜色0白,1红,2绿,3蓝
//
// 返回值:
//
//------------------------------------------------------------------------------
void ChangeColor( Range & rRange, int color = 4);
//------------------------------------------------------------------------------
// 函数功能:
// 获得单元格是否合并的信息,返回合并的行和列
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [IN ] int color // 字体颜色0白,1红,2绿,3蓝
//
// 返回值:
// TRUE: 是合并的单元格
// FALSE: 不是合并的单元格
//
//------------------------------------------------------------------------------
BOOL CExcelApp::GetMergeRange( Range & rRange, int &nrow, int &ncolumn);
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定单元格
//
// 参数说明:
// 1) [IN ] CString strCell // 单元格名,如("C1")
//
// 返回值:
// Range对象
//------------------------------------------------------------------------------
Range& GetCell( CString strCell);
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定单元格
//
// 参数说明:
// 1) [IN ] short nRow // 单元格行号
// 2) [IN ] short nCol // 单元格列号
//
// 返回值:
// Range对象
//------------------------------------------------------------------------------
Range& GetCell( short nRow, short nCol);
//------------------------------------------------------------------------------
// 函数功能:
// 获取EXCEL的有效行
//
// 参数说明:
//
// 返回值:
// long
//------------------------------------------------------------------------------
long GetRowCount();
//------------------------------------------------------------------------------
// 函数功能:
// 获取EXCEL的有效列
//
// 参数说明:
//
// 返回值:
// long
//------------------------------------------------------------------------------
long CExcelApp::GetColumnCount();
//------------------------------------------------------------------------------
// 函数功能:
// 获得单元格的左上角坐标,返回行坐标和列坐标
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [OUT] int & row // 行坐标
// 3) [OUT] int & column // 列坐标
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::GetRangePos( Range & rRange, int &row, int &column);
//------------------------------------------------------------------------------
// 函数功能:
// 设置边框
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [IN ] int style // 样式
// 3) [IN ] int thickness // 粗细
// 4) [IN ] int color // 颜色
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::SetBoarder( Range & rRange, int style, int thickness, int color);
protected:
private:
};
//ExecelAPP.cpp
#include "StdAfx.h"
#include "ExecelAPP.h"
#include <comdef.h>
CExcelApp::CExcelApp()
{
m_bUserControl = TRUE;
m_bVisible = FALSE;
m_bDisplayAlerts = FALSE;
m_strSaveAsFilePath = _T("");
m_strOpenFilePath = _T("");
}
CExcelApp::~CExcelApp()
{
}
//------------------------------------------------------------------------------
// 函数功能:
// 创建Excel服务
//
// 参数说明:
//
// 返回值:
// 成功返回TRUE,失败返回FALSE
//------------------------------------------------------------------------------
BOOL CExcelApp::InitExcelApp()
{
if ( !m_ExcelApp.CreateDispatch( _T("Excel.Application"), NULL ) )
return FALSE;
// 是否允许其他用户控制Excel
m_ExcelApp.SetUserControl( m_bUserControl );
// Excel程序是否可视
m_ExcelApp.SetVisible( m_bVisible );
m_ExcelApp.SetDisplayAlerts(m_bDisplayAlerts);
// 屏幕实时刷新是否关闭
// …
return TRUE;
}
//------------------------------------------------------------------------------
// 函数功能:
// 打开已存在的xls文件
//
// 参数说明:
// [IN ] CString strFileFullName // 文件全路径名称
//
// 返回值:
// 成功返回TRUE,失败返回FALSE
//------------------------------------------------------------------------------
BOOL CExcelApp::Open( CString strFileFullName )
{
LPDISPATCH lpDisp; //接口指针
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_ExcelBooks = m_ExcelApp.GetWorkbooks();
lpDisp = m_ExcelBooks.Open( strFileFullName, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional
);
m_strOpenFilePath = strFileFullName;
// 得到WorkBook
m_ExcelBook.AttachDispatch( lpDisp );
// 得到WorkSheets
m_ExcelSheets = m_ExcelBook.GetSheets();
// 得到WorkSheet
m_ExcelSheet = GetActiveSheet();
return TRUE;
}
//------------------------------------------------------------------------------
// 函数功能:
// 依据Sheet索引号选择Sheet页并将其激活
//
// 参数说明:
// [IN ] short nSheetIndex // Sheet页索引号
//
// 返回值:
// 返回成员WorkSheet的引用
//------------------------------------------------------------------------------
_Worksheet& CExcelApp::SelectSheet( short nSheetIndex )
{
m_ExcelSheet = m_ExcelSheets.GetItem( COleVariant( nSheetIndex ) );
m_ExcelRanges.AttachDispatch( m_ExcelSheet.GetCells() );
return m_ExcelSheet;
}
//------------------------------------------------------------------------------
// 函数功能:
// 依据Sheet页名称选择Sheet页并将其激活
//
// 参数说明:
// [IN ] CString strSheetName // Sheet页名称
//
// 返回值:
// 返回成员WorkSheet的引用
//------------------------------------------------------------------------------
_Worksheet& CExcelApp::SelectSheet( CString strSheetName )
{
m_ExcelSheet = m_ExcelSheets.GetItem( COleVariant( strSheetName ) );
m_ExcelRanges.AttachDispatch( m_ExcelSheet.GetCells() );
return m_ExcelSheet;
}
//------------------------------------------------------------------------------
// 函数功能:
// 获取Sheet页总数
//
// 参数说明:
//
// 返回值:
// Sheet页总数
//------------------------------------------------------------------------------
short CExcelApp::GetSheetCount()
{
return (short)m_ExcelSheets.GetCount();
}
//------------------------------------------------------------------------------
// 函数功能:
// 返回当前被激活的Sheet页
//
// 参数说明:
//
// 返回值:
// 返回成员WorkSheet的引用
//------------------------------------------------------------------------------
_Worksheet& CExcelApp::GetActiveSheet()
{
m_ExcelSheet = m_ExcelBook.GetActiveSheet();
m_ExcelRanges.AttachDispatch( m_ExcelSheet.GetCells() );
return m_ExcelSheet;
}
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定区域
//
// 参数说明:
// 1) [IN ] CString strCellStart // 起始单元格,如("C1")
// 2) [IN ] CString strCellEnd // 起始单元格,如("C2")
//
// 返回值:
// Range对象
//------------------------------------------------------------------------------
Range& CExcelApp::GetRange( CString strCellStart, CString strCellEnd )
{
m_ExcelRange.AttachDispatch( m_ExcelSheet.GetRange( COleVariant( strCellStart ), COleVariant( strCellEnd ) ) );
return m_ExcelRange;
}
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定区域
//
// 参数说明:
// 1) [IN ] short nStartRow // 起始单元格行号
// 2) [IN ] short nStartCol // 起始单元格列号
// 3) [IN ] short nEndRow // 结束单元格行号
// 4) [IN ] short nEndCol // 结束单元格列号
//
// 返回值:
// Range对象
//------------------------------------------------------------------------------
Range& CExcelApp::GetRange( short nStartRow, short nStartCol, short nEndRow, short nEndCol )
{
VARIANT CellStart, CellEnd;
CellStart = m_ExcelRanges.GetItem( COleVariant( nStartRow ), COleVariant( nStartCol ) );
CellEnd = m_ExcelRanges.GetItem( COleVariant( nEndRow ), COleVariant( nEndCol ) );
m_ExcelRange.AttachDispatch( m_ExcelSheet.GetRange( CellStart, CellEnd ) );
return m_ExcelRange;
}
//------------------------------------------------------------------------------
// 函数功能:
// 指定单元格进行赋值
//
// 参数说明:
// 1) [IN ] short nRow // 单元格行号
// 2) [IN ] short nCol // 单元格列号
// 3) [IN ] CString strValue // 单元格内容
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::SetValueCell( short nRow, short nCol, CString strValue )
{
m_ExcelRanges.SetItem( COleVariant ( nRow ),
COleVariant( nCol ),
COleVariant( strValue ) );
}
//------------------------------------------------------------------------------
// 函数功能:
// 另存Excel文件
//
// 参数说明:
// 1) [IN ] CString strFileFullName // xls文件全路径名称
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::SaveAs( CString strFileFullName )
{
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_ExcelBook.SaveAs( COleVariant( strFileFullName ), covOptional, covOptional,
covOptional, covOptional, covOptional, 0, covOptional,
covOptional, covOptional, covOptional, covOptional );
m_strSaveAsFilePath = strFileFullName;
}
//------------------------------------------------------------------------------
// 函数功能:
// 保存Excel文件
//
// 参数说明:
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::Save()
{
m_ExcelBook.Save();
}
//------------------------------------------------------------------------------
// 函数功能:
// 释放Excel所有应用 ( Range、Sheet、Sheets、…Application)
//
// 参数说明:
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::ReleaseAll()
{
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
CString strOutFileName;
// 关闭所有的Books,退出Excel
if ( m_strSaveAsFilePath.IsEmpty() )
strOutFileName = m_strOpenFilePath;
else
strOutFileName = m_strSaveAsFilePath;
m_ExcelRange.ReleaseDispatch();
m_ExcelRanges.ReleaseDispatch();
m_ExcelSheet.ReleaseDispatch();
m_ExcelSheets.ReleaseDispatch();
m_ExcelBook.Close( covOptional, COleVariant( strOutFileName ), covOptional );
m_ExcelBook.ReleaseDispatch();
m_ExcelBooks.Close();
m_ExcelBooks.ReleaseDispatch();
m_ExcelApp.Quit();
m_ExcelApp.ReleaseDispatch();
}
//------------------------------------------------------------------------------
// 函数功能:
// 在指定行号上方插入若干行
//
// 参数说明:
// 1) [IN ] short nRowIndex // Excel行号
// 2) [IN ] short nCount // 插入的行数
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::InsertRow( short nRowIndex, short nCount )
{
m_ExcelRange.AttachDispatch( m_ExcelSheet.GetRows() );
m_ExcelRange.AttachDispatch( m_ExcelRange.GetItem( COleVariant( nRowIndex ), vtMissing ).pdispVal );
for ( int i = 0; i < nCount; i++ )
m_ExcelRange.Insert( COleVariant( (long)xlUp ), vtMissing );
}
//------------------------------------------------------------------------------
// 函数功能:
// 删除指定行
//
// 参数说明:
// 1) [IN ] short nRowIndex // Excel行号
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::DeleteRow( short nRowIndex )
{
m_ExcelRange.AttachDispatch( m_ExcelSheet.GetRows() );
m_ExcelRange.AttachDispatch( m_ExcelRange.GetItem( COleVariant( nRowIndex ), vtMissing ).pdispVal );
m_ExcelRange.Delete( COleVariant( (long)xlUp ) );
}
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定单元格的内容
//
// 参数说明:
// 1) [IN ] short nRow // 单元格行号
// 2) [IN ] short nCol // 单元格列号
//
// 返回值:
// 以字符串形式返回单元格的内容
//------------------------------------------------------------------------------
CString CExcelApp::GetValueCell( short nRow, short nCol )
{
COleVariant vResult;
CString strValue;
m_ExcelRange.AttachDispatch( m_ExcelRanges.GetItem( COleVariant( nRow ), COleVariant( nCol ) ).pdispVal );
vResult = m_ExcelRange.GetValue2();
switch ( vResult.vt )
{
case VT_BSTR:
{
strValue = vResult.bstrVal;
}
break;
case VT_R8:
{
strValue.Format( _T("%f"), vResult.dblVal );
}
break;
case VT_DATE:
{
COleDateTime dDate;
dDate = vResult.date;
strValue = dDate.Format( _T("%Y-%m-%d") );
}
break;
case VT_EMPTY:
{
strValue = _T("");
}
break;
default:
strValue = _T("");
break;
}
return strValue;
}
//------------------------------------------------------------------------------
// 函数功能:
// 重新获取该sheet页的Range集合(说明:一般用在本Sheet页进行增删行导致Rang集合发生变化后,需要重置一次)
//
// 参数说明:
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::ReSetRanges()
{
m_ExcelRanges.AttachDispatch( m_ExcelSheet.GetCells() );
}
//------------------------------------------------------------------------------
// 函数功能:
// 合并单元格
//
// 参数说明:
// 1) [IN ] Range rRange // Range区域
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::MergeRange( Range & rRange )
{
rRange.Merge( COleVariant( (long)0 ) );
}
#define PICTURE
#ifdef PICTURE
//------------------------------------------------------------------------------
// 函数功能:
// 在指定区域插入本地图片
//
// 参数说明:
// 1) [IN ] Range rRange // Range区域
// 2) [IN ] CString strFileFullName // 图片全路径文件名
// 3) [IN ] BOOL bZoom // 图片是否按指定区域大小进行缩放
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::PictureInsert( Range &rRange, CString strFileFullName, BOOL bZoom )
{
Shapes shapes = m_ExcelSheet.GetShapes();
float fLeft, fTop, fWidth, fHeight;
fLeft = (float)rRange.GetLeft().dblVal;
fTop = (float)rRange.GetTop().dblVal;
if ( bZoom )
{
// 图片进行缩放,保持与指定Range区域大小一致
fWidth = (float)rRange.GetWidth().dblVal;
fHeight = (float)rRange.GetHeight().dblVal;
}
else
{
// 图片保持原大小
BITMAP bm;
HBITMAP hbitmap;
hbitmap = (HBITMAP) LoadImage(NULL, strFileFullName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(hbitmap, sizeof(bm), &bm);
fWidth = (float)bm.bmWidth;
fHeight = (float)bm.bmHeight;
}
shapes.AddPicture( strFileFullName, false, true, fLeft, fTop, fWidth, fHeight );
}
#endif
//------------------------------------------------------------------------------
// 函数功能:
// 取消合并单元格
//
// 参数说明:
// 1) [IN ] Range rRange // Range区域
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::UnMergeRange( Range & rRange )
{
rRange.UnMerge();
}
//------------------------------------------------------------------------------
// 函数功能:
// 设置字体
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [IN ] Cstring font // 字体
// 3) [IN ] int size // 字号默认为不改变
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::SetFont( Range & rRange, CString font, int size)
{
m_ExcelFont = rRange.GetFont();
m_ExcelFont.SetName(COleVariant(font));
VARIANT varUnit;
VariantInit(&varUnit);
varUnit.vt = VT_I4;
varUnit.lVal = size;
if (size != 0)
{
m_ExcelFont.SetSize(varUnit);
}
}
//------------------------------------------------------------------------------
// 函数功能:
// 设置字体颜色
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [IN ] int color // 字体颜色0白,1红,2绿,3蓝
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::ChangeColor( Range & rRange, int color)
{
m_ExcelFont = rRange.GetFont();
VARIANT varUnit;
VariantInit(&varUnit);
varUnit.vt = VT_UI4;
switch(color)
{
case 0:
varUnit.uintVal = RGB(0, 0, 0);
break;
case 1:
varUnit.uintVal = RGB(255, 0, 0);
break;
case 2:
varUnit.uintVal = RGB(0, 255, 0);
break;
case 3:
varUnit.uintVal = RGB(0, 0, 255);
break;
default:
varUnit.uintVal = RGB(255, 255, 255);
}
m_ExcelFont.SetColor(varUnit);
}
//------------------------------------------------------------------------------
// 函数功能:
// 获得单元格是否合并的信息,返回合并的行和列
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [IN ] int & nrow // 合并的行数
// 3) [IN ] int & ncolumn // 合并的列数
//
// 返回值:
// TRUE: 是合并的单元格
// FALSE: 不是合并的单元格
//
//------------------------------------------------------------------------------
BOOL CExcelApp::GetMergeRange( Range & rRange, int &nrow, int &ncolumn)
{
Range rangeMerge;
rangeMerge.AttachDispatch( rRange.GetMergeArea(), TRUE );
// 合并行数
rangeMerge.AttachDispatch( rangeMerge.GetRows(), TRUE );
nrow = rangeMerge.GetCount();
// 合并列数
rangeMerge.AttachDispatch( rangeMerge.GetColumns(), TRUE );
ncolumn = rangeMerge.GetCount();
if (1 == nrow && 1 == ncolumn)
{
return FALSE;
}
else
{
return TRUE;
}
}
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定单元格
//
// 参数说明:
// 1) [IN ] CString strCell // 单元格名,如("C1")
//
// 返回值:
// Range对象
//------------------------------------------------------------------------------
Range& CExcelApp::GetCell( CString strCell)
{
return GetRange(strCell, strCell);
}
//------------------------------------------------------------------------------
// 函数功能:
// 获取指定单元格
//
// 参数说明:
// 1) [IN ] short nRow // 单元格行号
// 2) [IN ] short nCol // 单元格列号
//
// 返回值:
// Range对象
//------------------------------------------------------------------------------
Range& CExcelApp::GetCell( short nRow, short nCol)
{
return GetRange(nRow, nCol, nRow, nCol);
}
//------------------------------------------------------------------------------
// 函数功能:
// 获取EXCEL的有效行
//
// 参数说明:
//
// 返回值:
// long
//------------------------------------------------------------------------------
long CExcelApp::GetRowCount()
{
Range rgRange;
rgRange.AttachDispatch(m_ExcelSheet.GetUsedRange(),TRUE);
Range rgRow;
long lRows;
rgRow.AttachDispatch(rgRange.GetRows(),TRUE);
lRows = rgRow.GetCount();
return lRows;
}
//------------------------------------------------------------------------------
// 函数功能:
// 获取EXCEL的有效行
//
// 参数说明:
//
// 返回值:
// int
//------------------------------------------------------------------------------
long CExcelApp::GetColumnCount()
{
Range rgRange;
rgRange.AttachDispatch(m_ExcelSheet.GetUsedRange(),TRUE);
Range rgColumn;
long lColumns;
rgColumn.AttachDispatch(rgRange.GetColumns(),TRUE);
lColumns = rgColumn.GetCount();
return lColumns;
}
//------------------------------------------------------------------------------
// 函数功能:
// 获得单元格的左上角坐标,返回行坐标和列坐标
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [OUT] int & row // 行坐标
// 3) [OUT] int & column // 列坐标
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::GetRangePos( Range & rRange, int &row, int &column)
{
Range rangeMerge;
rangeMerge.AttachDispatch( rRange.GetMergeArea(), TRUE );
row = rangeMerge.GetRow();
column = rRange.GetColumn();
}
//------------------------------------------------------------------------------
// 函数功能:
// 设置边框
//
// 参数说明:
// 1) [IN ] Range & rRange // Range区域
// 2) [IN ] int style // 样式
// 3) [IN ] int thickness // 粗细
// 4) [IN ] int color // 颜色
//
// 返回值:
//
//------------------------------------------------------------------------------
void CExcelApp::SetBoarder( Range & rRange, int style, int thickness, int color)
{
_variant_t vRange1; // 设置单元格的线;
_variant_t vRange2;
_variant_t vRange3;
_variant_t vRange4;
// 线的样式:0- no line; 1-solid; 2-big dot;3-small dot;4-dash dot; 5-dash dot dot;
vRange1.vt = VT_I2;
vRange1.lVal = style;
// 线的粗细程度
vRange2.vt = VT_I2;
vRange2.lVal = thickness;
//线的颜色 1-black;2-white;3-red;4-green;5-blue; 6-yellow; 7-pink;8-dark blue;
vRange3.vt = VT_I2;
vRange3.lVal = color;
vRange4.vt = VT_I2;
vRange4.lVal = RGB(0,0,0);
rRange.BorderAround(vRange1, vRange2, vRange3, vRange4);
}