VS之Excel文件操作


Excel是微软办公套装软件的一个重要的组成部分,它可以进行各种数据的处理、统计分析和辅助决策操作,广泛地应用于管理、统计财经、金融等众多领域。

您可以使用 Excel 创建工作簿(电子表格集合)并设置工作簿格式,以便分析数据和做出更明智的业务决策。特别是,您可以使用 Excel 跟踪数据,生成数据分析模型,编写公式以对数据进行计算,以多种方式透视数据,并以各种具有专业外观的图表来显示数据。简而言之:Excel是用来更方便处理数据的办公软件。

现在的很多数据都是使用Excel存取的,本文通过一个简单的例子实现Excel的操作。

使用工具:VS2008

使用语言:C++

开发步骤:

1.新建对话框应用程序



2.添加文件见附录

BasicExcel.hpp  BasicExcel.cpp

ExcelFormat.h  ExcelFormat.cpp

(源自网络)

3.设置数据结构体和添加数据处理类

ExcelDataInfo.h

#pragma once

#include "ExcelFormat.h"
#include "BasicExcel.hpp"
using namespace YExcel;

#define SEX_BOY		0
#define SEX_GIRL	1

struct tEXCEL_DATA_INFO
{
	CString	sName;//姓名
	DWORD	dwNumber;//编号
	BOOL	bSex;//性别
	UCHAR	ucAge;//年龄
	DOUBLE	dbScore;//分数
	tEXCEL_DATA_INFO()
	{
		sName	=	_T("");
		dwNumber=	0;
		bSex	=	SEX_BOY;
		ucAge	=	0;
		dbScore	=	0;
	}
	tEXCEL_DATA_INFO& operator = (tEXCEL_DATA_INFO& item)
	{
		sName	=	item.sName;
		dwNumber=	item.dwNumber;
		bSex	=	item.bSex;
		ucAge	=	item.ucAge;
		dbScore	=	item.dbScore;
		return* this;
	}
};
typedef CArray<tEXCEL_DATA_INFO,tEXCEL_DATA_INFO&> ArrExcelDataInfoNodes;

struct tEXCEL_DATA_CLASS
{
	DWORD	dwClassNumber;//班级编号
	CString	sClassName;//班级名称
	ArrExcelDataInfoNodes arrExcelDataInfo;//班级里的同学
	tEXCEL_DATA_CLASS()
	{
		dwClassNumber = 0;
		sClassName = _T("");
		arrExcelDataInfo.RemoveAll();
	}
	tEXCEL_DATA_CLASS& operator = (tEXCEL_DATA_CLASS& item)
	{
		dwClassNumber = item.dwClassNumber;
		sClassName = item.sClassName;
		arrExcelDataInfo.RemoveAll();
		int cnt = item.arrExcelDataInfo.GetSize();
		for(int i=0; i<cnt; i++)
		{
			arrExcelDataInfo.Add(item.arrExcelDataInfo[i]);
		}
		return* this;
	}
};
typedef CArray<tEXCEL_DATA_CLASS,tEXCEL_DATA_CLASS&> ArrExcelDataClassNodes;

class CExcelDataInfo
{
public:
	CExcelDataInfo(void);
	~CExcelDataInfo(void);
public:
	ArrExcelDataClassNodes m_arrExcelDataClass;
	DWORD LoadFile(CString sFilePathName);
	DWORD SaveFile(CString sFilePathName);
private:
	void LoadExcelFile(BasicExcelWorksheet* info);
	void SaveExcelFile(BasicExcelWorksheet* info);
	void SaveSheetCellValue(BasicExcelWorksheet *WorkSheet, CString sValue, DWORD row, DWORD column);
	BOOL IsSheetCellEmpty(CString sValue,CString sWorkSheetName, DWORD row, DWORD column);
	char* CStringToChar(CString str);
};


ExcelDataInfo.cpp

#include "StdAfx.h"
#include "ExcelDataInfo.h"

CExcelDataInfo::CExcelDataInfo(void)
{
}

CExcelDataInfo::~CExcelDataInfo(void)
{
}

DWORD CExcelDataInfo::LoadFile(CString sFilePathName)
{
	m_arrExcelDataClass.RemoveAll();

	BasicExcel e;
	e.Load(CStringToChar(sFilePathName));
	BasicExcelWorksheet* info = e.GetWorksheet(_T("INFO"));

	LoadExcelFile(info);

	return 0;
}

DWORD CExcelDataInfo::SaveFile(CString sFilePathName)
{
	CString sCurrentPath = _T("");
	DWORD len = 0;
	DWORD i = 0;

	BasicExcel e;
	e.New(3);//新建3个sheet
	e.RenameWorksheet("Sheet1","INFO");

	BasicExcelWorksheet* info = e.GetWorksheet("INFO");
	SaveExcelFile(info);

	e.SaveAs(CStringToChar(sFilePathName));

	return 0;
}

void CExcelDataInfo::LoadExcelFile(BasicExcelWorksheet* info)
{
	m_arrExcelDataClass.RemoveAll();
	tEXCEL_DATA_CLASS cl;
	tEXCEL_DATA_INFO st;
	size_t maxRows = 0;
	size_t maxCols = 0;
	int r = 0;
	int nSub = 0;
	int nMergedRows = 0;
	int nLine = 1;//从第一行开始读取
	int n=0;
	CString str = _T("");//判断读取内容
	CString sNumber = _T("");//显示数值的字符
	CString sWarning = _T("");//警告
	
	if(info)
	{
		maxRows = info->GetTotalRows();//排数
		maxCols = info->GetTotalCols();//栏数
		for(r=1; r<maxRows; r++)//第0行的数据不用存
		{
			nMergedRows = info->Cell(nLine,0)->GetMergedRows();//合并列
			//班级编号
			cl.dwClassNumber = info->Cell(nLine,0)->GetInteger();
			/*sNumber = info->Cell(nLine,0)->GetString();
			if(IsSheetCellEmpty(sNumber,_T("INFO"),nLine,0))
			{
				cl.dwClassNumber = info->Cell(nLine,0)->GetInteger();
			}
			else
			{
				cl.dwClassNumber = strtoul(info->Cell(nLine,0)->GetString(),NULL,10);
			}*/
			//班级名称
			if(YExcel::BasicExcelCell::STRING == info->Cell(nLine,1)->Type())
			{
				cl.sClassName = info->Cell(nLine,1)->GetString();
			}
			else if(YExcel::BasicExcelCell::WSTRING == info->Cell(nLine,1)->Type())
			{
				cl.sClassName = info->Cell(nLine,1)->GetWString();
			}
			else
			{
				cl.sClassName = _T("");
			}

			//子项
			cl.arrExcelDataInfo.RemoveAll();
			for(n=nLine; n<(nLine+nMergedRows); n++)
			{
				//姓名
				if(YExcel::BasicExcelCell::STRING == info->Cell(n,2)->Type())
				{
					st.sName = info->Cell(n,2)->GetString();
				}
				else if(YExcel::BasicExcelCell::WSTRING == info->Cell(n,2)->Type())
				{
					st.sName = info->Cell(n,2)->GetWString();
				}
				else
				{
					st.sName = _T("");
				}
				//编号
				st.dwNumber = info->Cell(n,3)->GetInteger();
				/*sNumber = info->Cell(n,3)->GetString();
				if(IsSheetCellEmpty(sNumber,_T("INFO"),n,3))
				{
					st.dwNumber = info->Cell(n,3)->GetInteger();
				}
				else
				{
					st.dwNumber = strtoul(info->Cell(n,3)->GetString(),NULL,10);
				}*/
				//性别
				if(YExcel::BasicExcelCell::STRING == info->Cell(n,4)->Type())
				{
					str = info->Cell(n,4)->GetString();
					if(_T("男") == str)
					{
						st.bSex = SEX_BOY;
					}
					else if(_T("女") == str)
					{
						st.bSex = SEX_GIRL;
					}
					else
					{
						st.bSex = SEX_BOY;
					}
				}
				else if(YExcel::BasicExcelCell::WSTRING == info->Cell(n,4)->Type())
				{
					str = info->Cell(n,4)->GetWString();
					if(_T("男") == str)
					{
						st.bSex = SEX_BOY;
					}
					else if(_T("女") == str)
					{
						st.bSex = SEX_GIRL;
					}
					else
					{
						st.bSex = SEX_BOY;
					}
				}
				//年龄
				st.ucAge = info->Cell(n,5)->GetInteger();
				/*sNumber = info->Cell(n,5)->GetString();
				if(IsSheetCellEmpty(sNumber,_T("INFO"),n,5))
				{
					st.ucAge = info->Cell(n,5)->GetInteger();
				}
				else
				{
					st.ucAge = atoi(info->Cell(n,5)->GetString());
				}*/
				//分数
				st.dbScore = info->Cell(n,6)->GetDouble();
				/*sNumber = info->Cell(n,6)->GetString();
				if(IsSheetCellEmpty(sNumber,_T("INFO"),n,6))
				{
					st.dbScore = info->Cell(n,6)->GetInteger();
				}
				else
				{
					st.dbScore = strtoul(info->Cell(n,6)->GetString(),NULL,10);
				}*/
				cl.arrExcelDataInfo.Add(st);
			}

			m_arrExcelDataClass.Add(cl);
			nLine += nMergedRows;
			r = nLine - 1;
		}
	}
}

void CExcelDataInfo::SaveExcelFile(BasicExcelWorksheet* info)
{
	BasicExcelCell* cell;
	int cnt=0, i=0;
	int len=0, j=0;
	int n=0;
	bool bUnicode = false;//区分是中文还是英文
	int k=0;
	int nLength = 0;
	int nSubCnt = 0;//子项个数
	int nSumCnt = 0;
	
	if(info)
	{
		cell = info->Cell(0,0);
		cell->SetWString(L"班级编号");
	//	info->Cell(0,0)->SetWString(L"LID值(hex)");
		info->Cell(0,1)->SetWString(L"班级名称");

		info->Cell(0,2)->SetWString(L"姓名");
		info->Cell(0,3)->SetWString(L"编号");
		info->Cell(0,4)->SetWString(L"性别");
		info->Cell(0,5)->SetWString(L"年龄");
		info->Cell(0,6)->SetWString(L"分数");

		CString str = _T("");
		cnt = m_arrExcelDataClass.GetSize();
		for(i=0; i<cnt; i++)
		{
			nSubCnt = m_arrExcelDataClass[i].arrExcelDataInfo.GetSize();//子项个数
			n = nSumCnt + (1 + i);
			//班级编号
			info->Cell(n,0)->SetMergedRows(nSubCnt);
			//str.Format(_T("%d"),m_arrExcelDataClass[i].dwClassNumber);
			//info->Cell(n,0)->SetString(CStringToChar(str));
			info->Cell(n,0)->SetInteger(m_arrExcelDataClass[i].dwClassNumber);
			//班级名称
			info->Cell(n,1)->SetMergedRows(nSubCnt);
			str = m_arrExcelDataClass[i].sClassName;
			SaveSheetCellValue(info, str, n, 2);
			bUnicode = false;
			len = m_arrExcelDataClass[i].sClassName.GetLength();
			for(j=0;j<len;j++)
			{
				BYTE byte = m_arrExcelDataClass[i].sClassName.GetAt(j);
				if(IsDBCSLeadByte(byte))
				{
					bUnicode = true;
					break;
				}
			}
			if(bUnicode)
			{
				nLength = m_arrExcelDataClass[i].sClassName.GetLength();
				wchar_t* pszBuffer = new wchar_t[nLength + 1];
				_mbstowcsz(pszBuffer, CStringToChar(m_arrExcelDataClass[i].sClassName), nLength + 1);		
				info->Cell(n,2)->SetWString(pszBuffer);
				delete[] pszBuffer;
			}
			else
			{
				info->Cell(n,1)->SetString(CStringToChar(m_arrExcelDataClass[i].sClassName));
			}

			if(0 == nSubCnt)
			{
				nSumCnt += nSubCnt;
			}
			else
			{
				nSumCnt += nSubCnt - 1;
			}
		}

		//子项
		cnt = m_arrExcelDataClass.GetSize();
		n = 0;
		for(i=0; i<cnt; i++)
		{
			nSubCnt = m_arrExcelDataClass[i].arrExcelDataInfo.GetSize();//子项个数
			if(0 == nSubCnt)//如果子项为空,则空一行
			{
				n++;
			}
			for(k=0; k<nSubCnt; k++)
			{
				n++;
				//姓名
				str = m_arrExcelDataClass[i].arrExcelDataInfo[k].sName;
				SaveSheetCellValue(info, str, n, 2);
				//编号
				//str.Format(_T("%d"),m_arrExcelDataClass[i].arrExcelDataInfo[k].dwNumber);
				//SaveSheetCellValue(info, str, n, 3);
				info->Cell(n,3)->SetInteger(m_arrExcelDataClass[i].arrExcelDataInfo[k].dwNumber);
				//性别
				if(SEX_BOY == m_arrExcelDataClass[i].arrExcelDataInfo[k].bSex)
				{
					info->Cell(n,4)->SetWString(L"男");
				}
				else if(SEX_GIRL == m_arrExcelDataClass[i].arrExcelDataInfo[k].bSex)
				{
					info->Cell(n,4)->SetWString(L"女");
				}
				else
				{
					info->Cell(n,4)->SetWString(L"--");
				}
				//年龄
				//str.Format(_T("%d"),m_arrExcelDataClass[i].arrExcelDataInfo[k].ucAge);
				//info->Cell(n,5)->SetString(CStringToChar(str));
				info->Cell(n,5)->SetInteger(m_arrExcelDataClass[i].arrExcelDataInfo[k].ucAge);
				//分数
				//str.Format(_T("%f"),m_arrExcelDataClass[i].arrExcelDataInfo[k].dbScore);
				//info->Cell(n,6)->SetString(CStringToChar(str));
				info->Cell(n,6)->SetDouble(m_arrExcelDataClass[i].arrExcelDataInfo[k].dbScore);
				
			}
		}
	}
}

void CExcelDataInfo::SaveSheetCellValue(BasicExcelWorksheet *WorkSheet, CString sValue, DWORD row, DWORD column)
{
	BOOL bUnicode = false;
	int j=0, len=0, nLength=0;
	len = sValue.GetLength();
	for(j=0;j<len;j++)
	{
		BYTE byte = sValue.GetAt(j);
		if(IsDBCSLeadByte(byte))
		{
			bUnicode = true;
			break;
		}
	}
	if(bUnicode)
	{
		nLength = sValue.GetLength();
		wchar_t* pszBuffer = new wchar_t[nLength + 1];
		_mbstowcsz(pszBuffer, CStringToChar(sValue), nLength + 1);
		WorkSheet->Cell(row,column)->SetWString(pszBuffer);
		delete[] pszBuffer;
	}
	else
	{
		WorkSheet->Cell(row,column)->SetString(CStringToChar(sValue));
	}
}

BOOL CExcelDataInfo::IsSheetCellEmpty(CString sValue,CString sWorkSheetName, DWORD row, DWORD column)
{
	CString str1=_T(""), str2=_T("");
	CString sWarning = _T("");
	if(sValue.IsEmpty())
	{
	//	str1.Format("%d",row+1);
	//	str2.Format("%d",column+1);
	//	sWarning = sWorkSheetName + "的第" + str1 + "行第" + str2 + "列数据错误,请重新编辑!";
	//	AfxMessageBox(sWarning);
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

char* CExcelDataInfo::CStringToChar(CString str)
{
	char *p =(LPSTR)(LPCTSTR)str;
	return p;
}


4.添加数据显示界面

FileExcelDemoDlg.h

// FileExcelDemoDlg.h : 头文件
//

#pragma once

#include "ExcelDataInfo.h"
#include "afxcmn.h"


// CFileExcelDemoDlg 对话框
class CFileExcelDemoDlg : public CDialog
{
// 构造
public:
	CFileExcelDemoDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
	enum { IDD = IDD_FILEEXCELDEMO_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	CExcelDataInfo m_excel;
	CListCtrl m_list;
	afx_msg void OnBnClickedBtnExcelLoad();
	afx_msg void OnBnClickedBtnExcelSave();
	afx_msg void OnBnClickedBtnExcelAdd();
	afx_msg void OnBnClickedBtnExcelEdit();
	afx_msg void OnBnClickedBtnExcelDelete();
	void UpdateListData(void);
	int m_nSelectItem;
	afx_msg void OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult);
	afx_msg void OnBnClickedBtnExcelSub();
};

FileExcelDemoDlg.cpp

// FileExcelDemoDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "FileExcelDemo.h"
#include "FileExcelDemoDlg.h"
#include "ClassDlg.h"
#include "ListDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CFileExcelDemoDlg 对话框




CFileExcelDemoDlg::CFileExcelDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CFileExcelDemoDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CFileExcelDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST1, m_list);
}

BEGIN_MESSAGE_MAP(CFileExcelDemoDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BTN_EXCEL_LOAD, &CFileExcelDemoDlg::OnBnClickedBtnExcelLoad)
	ON_BN_CLICKED(IDC_BTN_EXCEL_SAVE, &CFileExcelDemoDlg::OnBnClickedBtnExcelSave)
	ON_BN_CLICKED(IDC_BTN_EXCEL_ADD, &CFileExcelDemoDlg::OnBnClickedBtnExcelAdd)
	ON_BN_CLICKED(IDC_BTN_EXCEL_EDIT, &CFileExcelDemoDlg::OnBnClickedBtnExcelEdit)
	ON_BN_CLICKED(IDC_BTN_EXCEL_DELETE, &CFileExcelDemoDlg::OnBnClickedBtnExcelDelete)
	ON_NOTIFY(NM_CLICK, IDC_LIST1, &CFileExcelDemoDlg::OnNMClickList1)
	ON_BN_CLICKED(IDC_BTN_EXCEL_SUB, &CFileExcelDemoDlg::OnBnClickedBtnExcelSub)
END_MESSAGE_MAP()


// CFileExcelDemoDlg 消息处理程序

BOOL CFileExcelDemoDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	//属性设置
    m_list.ModifyStyle(LVS_TYPEMASK,LVS_REPORT & LVS_TYPEMASK | LVS_SINGLESEL);//important for show  
    DWORD dwStyle = m_list.GetExtendedStyle();  
    m_list.SetExtendedStyle(dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

	//设置行距
	CImageList image;  
    image.Create(1,20,ILC_COLOR24 | ILC_MASK,4,0);  
    m_list.SetImageList(&image,LVSIL_SMALL); 

	//设置字体
	CFont font;  
    font.CreateFont(  
        16,  
        0,  
        0,  
        0,  
        FW_NORMAL,  
        FALSE,  
        FALSE,  
        0,  
        ANSI_CHARSET,  
        OUT_DEFAULT_PRECIS,  
        CLIP_DEFAULT_PRECIS,  
        DEFAULT_QUALITY,  
        DEFAULT_PITCH | FF_SWISS,  
        _T("宋体"));  
    m_list.SetFont(&font);  
    m_list.GetHeaderCtrl()->SetFont(&font); 

	//标题栏  
    m_list.InsertColumn(0,_T("编号"),LVCFMT_LEFT,100,0);  
    m_list.InsertColumn(1,_T("名称"),LVCFMT_LEFT,100,0);

	m_nSelectItem = -1;

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CFileExcelDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CFileExcelDemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CFileExcelDemoDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CFileExcelDemoDlg::OnBnClickedBtnExcelLoad()
{
	// TODO: 在此添加控件通知处理程序代码
	CString sFilePathName = _T("");
	CString str = _T(""), s = _T("");
	CString sFileType = _T("");
	str = _T("xls");
	s = _T("xls files(*.xls)|*.xls|所有文件(*.*)|*.*||");
	CFileDialog fd(TRUE,str,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR,s,NULL);

	if(IDOK == fd.DoModal())
	{
		sFilePathName = fd.GetPathName();
		sFileType = fd.GetFileExt();
		if(_T("xls") == sFileType)
		{
			m_excel.LoadFile(sFilePathName);
			UpdateListData();//更新界面
			MessageBox(_T("打开文件成功!"));
		}
		else
		{
			MessageBox(_T("打开文件失败!"));
		}
	}
}

void CFileExcelDemoDlg::OnBnClickedBtnExcelSave()
{
	// TODO: 在此添加控件通知处理程序代码
	CString sFilePathName = _T("");
	CString str = _T(""), s = _T("");
	CString sFileType = _T("");
	str = _T("xls");
	s = _T("xls files(*.xls)|*.xls|所有文件(*.*)|*.*||");
	CFileDialog fd(FALSE,str,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR,s,NULL);

	if(IDOK == fd.DoModal())
	{
		sFilePathName = fd.GetPathName();
		if(-1 == sFilePathName.Find(_T(".xls")))
		{
			sFilePathName = sFilePathName + _T(".xls");
		}
		m_excel.SaveFile(sFilePathName);
		MessageBox(_T("保存文件成功!"));
	}
}

void CFileExcelDemoDlg::OnBnClickedBtnExcelAdd()
{
	// TODO: 在此添加控件通知处理程序代码
	DWORD lid = 0;
	DWORD dwValue = 0;
	int cnt = m_list.GetItemCount();
	int i =0;
	for(i=0;i<cnt;i++)
	{
		CString str = m_list.GetItemText(i,0);
		dwValue = atoi(str);
		if(dwValue >= lid)
		{
			lid = dwValue;
		}
	}
	lid++;

	tEXCEL_DATA_CLASS data;
	data.dwClassNumber = lid;
	data.sClassName = _T("--");
	data.arrExcelDataInfo.RemoveAll();

	CString str = _T("");
	str.Format(_T("%d"),data.dwClassNumber);
	m_list.InsertItem(cnt,str);
	m_list.SetItemText(cnt,1,data.sClassName);
	m_excel.m_arrExcelDataClass.Add(data);
}

void CFileExcelDemoDlg::OnBnClickedBtnExcelEdit()
{
	// TODO: 在此添加控件通知处理程序代码
	if(-1 == m_nSelectItem)
	{
		return;
	}

	CClassDlg dlg;
	dlg.m_class = m_excel.m_arrExcelDataClass[m_nSelectItem];
	if(IDOK == dlg.DoModal())
	{
		m_excel.m_arrExcelDataClass[m_nSelectItem] = dlg.m_class;
		UpdateListData();
	}
}

void CFileExcelDemoDlg::OnBnClickedBtnExcelDelete()
{
	// TODO: 在此添加控件通知处理程序代码
	if(-1 == m_nSelectItem)
	{
		return;
	}

	m_list.DeleteItem(m_nSelectItem);
	m_excel.m_arrExcelDataClass.RemoveAt(m_nSelectItem);
	m_nSelectItem = -1;
}

void CFileExcelDemoDlg::UpdateListData(void)
{
	m_list.DeleteAllItems();

	CString str = _T("");
	int cnt = m_excel.m_arrExcelDataClass.GetSize();
	for(int i=0; i<cnt; i++)
	{
		//编号
		str.Format(_T("%d"),m_excel.m_arrExcelDataClass[i].dwClassNumber);
		m_list.InsertItem(i,str);
		//名称
		str = m_excel.m_arrExcelDataClass[i].sClassName;
		m_list.SetItemText(i,1,str);
	}
}

void CFileExcelDemoDlg::OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
	//LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	CPoint CursorPoint;
    if(!GetCursorPos(&CursorPoint))  
    {  
        return;
    }
  
    if(-1 == pNMListView->iItem)  
    {  
        m_nSelectItem = -1;  
        return;  
    }  
    else
    {  
        m_nSelectItem = pNMListView->iItem;  
    }

	*pResult = 0;
}

void CFileExcelDemoDlg::OnBnClickedBtnExcelSub()
{
	// TODO: 在此添加控件通知处理程序代码
	if(-1 == m_nSelectItem)
	{
		return;
	}

	CListDlg dlg;
	dlg.m_data = m_excel.m_arrExcelDataClass[m_nSelectItem];
	if(IDOK == dlg.DoModal())
	{
		m_excel.m_arrExcelDataClass[m_nSelectItem] = dlg.m_data;
		//UpdateListData();
	}
}


5.添加数据操作界面

ListDlg.h

#pragma once

#include "ExcelDataInfo.h"
#include "afxcmn.h"

// CListDlg 对话框

class CListDlg : public CDialog
{
	DECLARE_DYNAMIC(CListDlg)

public:
	CListDlg(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~CListDlg();

// 对话框数据
	enum { IDD = IDD_DIALOG_LIST };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	tEXCEL_DATA_CLASS m_data;
	CListCtrl m_list;
	virtual BOOL OnInitDialog();
	afx_msg void OnBnClickedBtnListAdd();
	afx_msg void OnBnClickedBtnListEdit();
	afx_msg void OnBnClickedBtnListDelete();
	afx_msg void OnBnClickedOk();
	afx_msg void OnBnClickedCancel();
	void UpdateListData(void);
	int m_nSelectItem;
	afx_msg void OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult);
};

ListDlg.cpp

// ListDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "FileExcelDemo.h"
#include "ListDlg.h"
#include "DataDlg.h"


// CListDlg 对话框

IMPLEMENT_DYNAMIC(CListDlg, CDialog)

CListDlg::CListDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CListDlg::IDD, pParent)
{

}

CListDlg::~CListDlg()
{
}

void CListDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST1, m_list);
}


BEGIN_MESSAGE_MAP(CListDlg, CDialog)
	ON_BN_CLICKED(IDC_BTN_LIST_ADD, &CListDlg::OnBnClickedBtnListAdd)
	ON_BN_CLICKED(IDC_BTN_LIST_EDIT, &CListDlg::OnBnClickedBtnListEdit)
	ON_BN_CLICKED(IDC_BTN_LIST_DELETE, &CListDlg::OnBnClickedBtnListDelete)
	ON_BN_CLICKED(IDOK, &CListDlg::OnBnClickedOk)
	ON_BN_CLICKED(IDCANCEL, &CListDlg::OnBnClickedCancel)
	ON_NOTIFY(NM_CLICK, IDC_LIST1, &CListDlg::OnNMClickList1)
END_MESSAGE_MAP()


// CListDlg 消息处理程序

BOOL CListDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  在此添加额外的初始化
	//属性设置
    m_list.ModifyStyle(LVS_TYPEMASK,LVS_REPORT & LVS_TYPEMASK | LVS_SINGLESEL);//important for show  
    DWORD dwStyle = m_list.GetExtendedStyle();  
    m_list.SetExtendedStyle(dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

	//设置行距
	CImageList image;  
    image.Create(1,20,ILC_COLOR24 | ILC_MASK,4,0);  
    m_list.SetImageList(&image,LVSIL_SMALL); 

	//设置字体
	CFont font;  
    font.CreateFont(  
        16,  
        0,  
        0,  
        0,  
        FW_NORMAL,  
        FALSE,  
        FALSE,  
        0,
        ANSI_CHARSET,  
        OUT_DEFAULT_PRECIS,  
        CLIP_DEFAULT_PRECIS,  
        DEFAULT_QUALITY,  
        DEFAULT_PITCH | FF_SWISS,  
        _T("宋体"));  
    m_list.SetFont(&font);  
    m_list.GetHeaderCtrl()->SetFont(&font); 

	//标题栏  
    m_list.InsertColumn(0,_T("姓名"),LVCFMT_LEFT,100,0);  
    m_list.InsertColumn(1,_T("编号"),LVCFMT_LEFT,100,0);  
    m_list.InsertColumn(2,_T("性别"),LVCFMT_LEFT,100,0);
	m_list.InsertColumn(3,_T("年龄"),LVCFMT_LEFT,100,0);
	m_list.InsertColumn(4,_T("分数"),LVCFMT_LEFT,100,0);

	m_nSelectItem = -1;

	UpdateListData();

	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}

void CListDlg::OnBnClickedBtnListAdd()
{
	// TODO: 在此添加控件通知处理程序代码
	CDataDlg dlg;
	if(IDOK == dlg.DoModal())
	{
		m_data.arrExcelDataInfo.Add(dlg.m_data);
		UpdateListData();
	}
}

void CListDlg::OnBnClickedBtnListEdit()
{
	// TODO: 在此添加控件通知处理程序代码
	if(-1 == m_nSelectItem)
	{
		return;
	}

	CDataDlg dlg;
	dlg.m_data = m_data.arrExcelDataInfo[m_nSelectItem];
	if(IDOK == dlg.DoModal())
	{
		m_data.arrExcelDataInfo[m_nSelectItem] = dlg.m_data;
		UpdateListData();
	}
}

void CListDlg::OnBnClickedBtnListDelete()
{
	// TODO: 在此添加控件通知处理程序代码
	if(-1 == m_nSelectItem)
	{
		return;
	}

	m_list.DeleteItem(m_nSelectItem);
	m_data.arrExcelDataInfo.RemoveAt(m_nSelectItem);
	m_nSelectItem = -1;
}

void CListDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	OnOK();
}

void CListDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	OnCancel();
}

void CListDlg::UpdateListData(void)
{
	m_list.DeleteAllItems();

	CString str = _T("");
	BOOL bSex = 0;
	int cnt = m_data.arrExcelDataInfo.GetSize();
	for(int i=0; i<cnt; i++)
	{
		//姓名
		m_list.InsertItem(i,m_data.arrExcelDataInfo[i].sName);
		//编号
		str.Format(_T("%d"),m_data.arrExcelDataInfo[i].dwNumber);
		m_list.SetItemText(i,1,str);
		//性别
		bSex = m_data.arrExcelDataInfo[i].bSex;
		if(SEX_BOY == bSex)
		{
			str = _T("男");
		}
		else if(SEX_GIRL == bSex)
		{
			str = _T("女");
		}
		else
		{
			str = _T("--");
		}
		m_list.SetItemText(i,2,str);
		//年龄
		str.Format(_T("%d"),m_data.arrExcelDataInfo[i].ucAge);
		m_list.SetItemText(i,3,str);
		//分数
		str.Format(_T("%f"),m_data.arrExcelDataInfo[i].dbScore);
		m_list.SetItemText(i,4,str);
	}
}

void CListDlg::OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
	//LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<NMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    CPoint CursorPoint;  
    if(!GetCursorPos(&CursorPoint))  
    {  
        return;
    }  
  
    if(-1 == pNMListView->iItem)  
    {  
        m_nSelectItem = -1;  
        return;  
    }  
    else
    {  
        m_nSelectItem = pNMListView->iItem;  
    }
	*pResult = 0;
}

ClassDlg.h

#pragma once

#include "ExcelDataInfo.h"

// CClassDlg 对话框

class CClassDlg : public CDialog
{
	DECLARE_DYNAMIC(CClassDlg)

public:
	CClassDlg(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~CClassDlg();

// 对话框数据
	enum { IDD = IDD_DIALOG_CLASS };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	tEXCEL_DATA_CLASS m_class;
	DWORD m_dwNumber;
	CString m_sName;
	virtual BOOL OnInitDialog();
	afx_msg void OnBnClickedOk();
	afx_msg void OnBnClickedCancel();
};

ClassDlg.cpp

// ClassDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "FileExcelDemo.h"
#include "ClassDlg.h"


// CClassDlg 对话框

IMPLEMENT_DYNAMIC(CClassDlg, CDialog)

CClassDlg::CClassDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CClassDlg::IDD, pParent)
{
	m_dwNumber	=	0;
	m_sName		=	_T("");
}

CClassDlg::~CClassDlg()
{
}

void CClassDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT_NUMBER, m_dwNumber);
	DDX_Text(pDX, IDC_EDIT_NAME, m_sName);
}


BEGIN_MESSAGE_MAP(CClassDlg, CDialog)
	ON_BN_CLICKED(IDOK, &CClassDlg::OnBnClickedOk)
	ON_BN_CLICKED(IDCANCEL, &CClassDlg::OnBnClickedCancel)
END_MESSAGE_MAP()


// CClassDlg 消息处理程序

BOOL CClassDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  在此添加额外的初始化
	UpdateData(TRUE);
	m_dwNumber = m_class.dwClassNumber;
	m_sName = m_class.sClassName;
	UpdateData(FALSE);

	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}

void CClassDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);
	m_class.dwClassNumber = m_dwNumber;
	m_class.sClassName = m_sName;
	UpdateData(FALSE);

	OnOK();
}

void CClassDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	OnCancel();
}

DataDlg.h

#pragma once

#include "ExcelDataInfo.h"

// CDataDlg 对话框

class CDataDlg : public CDialog
{
	DECLARE_DYNAMIC(CDataDlg)

public:
	CDataDlg(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~CDataDlg();

// 对话框数据
	enum { IDD = IDD_DIALOG_DATA };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()
public:
	tEXCEL_DATA_INFO m_data;
	CString m_sName;
	DWORD m_dwNumber;
	UCHAR m_ucAge;
	DOUBLE m_dbScore;
	BOOL m_bSex;
	virtual BOOL OnInitDialog();
	afx_msg void OnBnClickedRadioBoy();
	afx_msg void OnBnClickedRadioGirl();
	afx_msg void OnBnClickedOk();
	afx_msg void OnBnClickedCancel();
};

DataDlg.cpp

// DataDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "FileExcelDemo.h"
#include "DataDlg.h"


// CDataDlg 对话框

IMPLEMENT_DYNAMIC(CDataDlg, CDialog)

CDataDlg::CDataDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDataDlg::IDD, pParent)
{
	m_sName		=	_T("");
	m_dwNumber	=	0;
	m_ucAge		=	0;
	m_dbScore	=	0;
	m_bSex		=	0;
}

CDataDlg::~CDataDlg()
{
}

void CDataDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT_NAME, m_sName);
	DDX_Text(pDX, IDC_EDIT_NUM, m_dwNumber);
	DDX_Text(pDX, IDC_EDIT_AGE, m_ucAge);
	DDX_Text(pDX, IDC_EDIT_SCORE, m_dbScore);
}


BEGIN_MESSAGE_MAP(CDataDlg, CDialog)
	ON_BN_CLICKED(IDC_RADIO_BOY, &CDataDlg::OnBnClickedRadioBoy)
	ON_BN_CLICKED(IDC_RADIO_GIRL, &CDataDlg::OnBnClickedRadioGirl)
	ON_BN_CLICKED(IDOK, &CDataDlg::OnBnClickedOk)
	ON_BN_CLICKED(IDCANCEL, &CDataDlg::OnBnClickedCancel)
END_MESSAGE_MAP()


// CDataDlg 消息处理程序

BOOL CDataDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  在此添加额外的初始化
	UpdateData(TRUE);
	m_sName = m_data.sName;
	m_dwNumber = m_data.dwNumber;
	m_ucAge = m_data.ucAge;
	m_dbScore = m_data.dbScore;

	m_bSex = m_data.bSex;
	if(0 == m_bSex)
	{
		((CButton*)GetDlgItem(IDC_RADIO_BOY))->SetCheck(TRUE);
		((CButton*)GetDlgItem(IDC_RADIO_GIRL))->SetCheck(FALSE);
	}
	else if(1 == m_bSex)
	{
		((CButton*)GetDlgItem(IDC_RADIO_BOY))->SetCheck(FALSE);
		((CButton*)GetDlgItem(IDC_RADIO_GIRL))->SetCheck(TRUE);
	}

	UpdateData(FALSE);

	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}

void CDataDlg::OnBnClickedRadioBoy()
{
	// TODO: 在此添加控件通知处理程序代码
	m_bSex = 0;
}

void CDataDlg::OnBnClickedRadioGirl()
{
	// TODO: 在此添加控件通知处理程序代码
	m_bSex = 1;
}

void CDataDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	UpdateData(TRUE);
	m_data.sName = m_sName;
	m_data.dwNumber = m_dwNumber;
	m_data.bSex = m_bSex;
	m_data.ucAge = m_ucAge;
	m_data.dbScore = m_dbScore;
	UpdateData(FALSE);

	OnOK();
}

void CDataDlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	OnCancel();
}

6.效果演示

运行程序


打开文件
 

添加


编辑
   

删除


编辑子项


子项添加
   

子项编辑
 

子项删除


保存文件


打开保存的文件,可以看到我们保存的数据



7.Excel其他操作

读取一个Excel表中的数据,将其排序,并使用颜色区分数据,存储到另一个Excel表中

如图

 

数据结构体

#include <Afxtempl.h>

struct tSTUDENT
{
	CString sName;
	DWORD   dwID;
	UCHAR   ucChina;
	UCHAR   ucMath;
	UCHAR   ucEnglish;
	WORD    wTotal;

	tSTUDENT()
	{
		sName     =  "";
		dwID      =  0;
		ucChina   =  0;
		ucMath    =  0;
		ucEnglish =  0;
		wTotal    =  0;
	}

	tSTUDENT& operator = (tSTUDENT& item)
	{
		sName     =  item.sName;
		dwID      =  item.dwID;
		ucChina   =  item.ucChina;
		ucMath    =  item.ucMath;
		ucEnglish =  item.ucEnglish;
		wTotal    =  item.wTotal;
		return *this;
	}
};
typedef CArray<tSTUDENT, tSTUDENT&> arrStudentNodes;

数据操作

void CExcelDlg::OnBtnDemo() 
{
	//*********************取数据*********************
	m_arrStudent.RemoveAll();
	tSTUDENT student;
	BasicExcel e;
	e.Load("student.xls");
	BasicExcelWorksheet* sheet = e.GetWorksheet("Sheet1");
	if(sheet)
	{
		size_t maxRows = sheet->GetTotalRows();//排数
		size_t maxCols = sheet->GetTotalCols();//栏数

		for(int r=1; r<maxRows; r++)//第0行的数据不用存
		{
			if(YExcel::BasicExcelCell::STRING == sheet->Cell(r,0)->Type())
			{
				student.sName = sheet->Cell(r,0)->GetString();
			}
			else if(YExcel::BasicExcelCell::WSTRING == sheet->Cell(r,0)->Type())
			{
				student.sName = sheet->Cell(r,0)->GetWString();
			}
			student.dwID = sheet->Cell(r,1)->GetInteger();
			student.ucChina = sheet->Cell(r,2)->GetInteger();
			student.ucMath = sheet->Cell(r,3)->GetInteger();
			student.ucEnglish = sheet->Cell(r,4)->GetInteger();
			student.wTotal = student.ucChina + student.ucMath + student.ucEnglish;
			m_arrStudent.Add(student);
		}
	}

	//*********************存数据*********************
	e.New();
	e.RenameWorksheet("Sheet1","Score");
	BasicExcelWorksheet* score = e.GetWorksheet("Score");
	BasicExcelCell* cell;
	if(score)
	{
		cell = score->Cell(0,0);
		cell->SetWString(L"排名");
	//	score->Cell(0,0)->SetWString(L"排名");
		score->Cell(0,1)->SetWString(L"学号");
		score->Cell(0,2)->SetWString(L"姓名");
		score->Cell(0,3)->SetWString(L"总成绩");
		score->Cell(0,4)->SetWString(L"语文");
		score->Cell(0,5)->SetWString(L"数学");
		score->Cell(0,6)->SetWString(L"外语");
		int cnt = m_arrStudent.GetSize();
		int i=0;
		double dbAll = 0;
		double dbAverage = 0;

		//********数据排序******
		int index = 0;
		tSTUDENT min;
		for(int j=cnt-1;j>0;j--)
		{
			for(i=0;i<j;i++)
			{
				if(m_arrStudent[i].wTotal < m_arrStudent[i+1].wTotal)
				{
				//	TRACE("第 %d 次比较->第 %d个(%d)与 第 %d个(%d)交换位置 \r\n",index,i,m_arrStudent[i].wTotal,i+1,m_arrStudent[i+1].wTotal);
					min = m_arrStudent[i];
					m_arrStudent[i] = m_arrStudent[i+1];
					m_arrStudent[i+1] = min;
				}
				else
				{
				//	TRACE("第 %d 次比较->第 %d个(%d)与 第 %d个(%d)保持不变 \r\n",index,i,m_arrStudent[i].wTotal,i+1,m_arrStudent[i+1].wTotal);
				}
				index++;
			}
		}

		bool bUnicode = false;
		for(i=0; i<cnt; i++)
		{
			int n = i+1;
			score->Cell(n,0)->SetInteger(n);
			score->Cell(n,1)->SetInteger(m_arrStudent[i].dwID);
		/*	int res = IS_TEXT_UNICODE_STATISTICS;
			LPTSTR  p = m_arrStudent[i].sName.GetBuffer(m_arrStudent[i].sName.GetLength() + 1);
			BOOL bFlag = IsTextUnicode(p,m_arrStudent[i].sName.GetLength(),&res);
			CString str;
			str.Format("code : %d" ,bFlag);
			MessageBox(str);*/

			bUnicode = false;
			int len = m_arrStudent[i].sName.GetLength();
			for(int j=0;j<len;j++)
			{
				BYTE byte = m_arrStudent[i].sName.GetAt(j);
				if(IsDBCSLeadByte(byte))
				{
					bUnicode = true;
					break;
				}
			}

		//	if(m_arrStudent[i].sName.GetAt(0) > 128)
		//	LPTSTR  p = m_arrStudent[i].sName.GetBuffer(m_arrStudent[i].sName.GetLength() + 1);
			if(bUnicode)
			{
				int nLength = m_arrStudent[i].sName.GetLength();
				wchar_t* pszBuffer = new wchar_t[nLength + 1];
				_mbstowcsz(pszBuffer, m_arrStudent[i].sName, nLength + 1);		
				score->Cell(n,2)->SetWString(pszBuffer);
				delete[] pszBuffer;
			}
			else
			{
				score->Cell(n,2)->SetString(m_arrStudent[i].sName);
			}
			score->Cell(n,3)->SetInteger(m_arrStudent[i].wTotal);
			score->Cell(n,4)->SetInteger(m_arrStudent[i].ucChina);
			score->Cell(n,5)->SetInteger(m_arrStudent[i].ucMath);
			score->Cell(n,6)->SetInteger(m_arrStudent[i].ucEnglish);

			dbAll += m_arrStudent[i].wTotal;
		}
		dbAverage = dbAll/30;
		score->Cell(11,0)->SetWString(L"全班平均成绩");
		score->Cell(11,3)->SetDouble(dbAverage);

		//**************颜色区分不同分数段***************
		size_t maxRows = sheet->GetTotalRows();//排数
		size_t maxCols = sheet->GetTotalCols();//栏数
		int scores = 0;
		for(int a=1; a<maxRows-1; a++)
		{
			for(int b=4; b<maxCols; b++)
			{
				scores = score->Cell(a,b)->GetInteger();
				if(scores < 60)
				{
					ExcelFormat::ExcelFont font;
					font.set_color_index(2);
				//	font.set_height(height);
				//	font.set_font_name(L"Times New Roman");

					ExcelFormat::XLSFormatManager fmt_mgr(e);
					ExcelFormat::CellFormat fmt(fmt_mgr, font);//设置字体
				//	fmt.set_background(MAKE_COLOR2(ExcelFormat::EGA_MAGENTA,0));	// solid magenta background

					cell = score->Cell(a, b);
					cell->SetFormat(fmt);
				}
				if(scores >= 80)
				{
					ExcelFormat::ExcelFont font;
					font.set_color_index(3);

					ExcelFormat::XLSFormatManager fmt_mgr(e);
					ExcelFormat::CellFormat fmt(fmt_mgr, font);
				//	fmt.set_background(MAKE_COLOR2(ExcelFormat::EGA_MAGENTA,0));//设置背景

					cell = score->Cell(a, b);
					cell->SetFormat(fmt);
				}
			}
		}
		cell = score->Cell(11,0);
		cell->SetMergedRows(2);
		cell->SetMergedColumns(3);

		cell = score->Cell(11,3);
		cell->SetMergedRows(2);
		cell->SetMergedColumns(3);
		ExcelFormat::ExcelFont font;
		font.set_color_index(1);
		ExcelFormat::XLSFormatManager fmt_mgr(e);
		ExcelFormat::CellFormat fmt(fmt_mgr, font);
		fmt.set_background(MAKE_COLOR2(ExcelFormat::EGA_MAGENTA,0));//设置背景
		cell->SetFormat(fmt);
	}

	//*********************新建sheet*********************
	score = e.AddWorksheet("Test",1);
	score = e.GetWorksheet(1);
	if(score)
	{
		cell = score->Cell(0,0);
		cell->SetWString(L"排名");
	//	score->Cell(0,0)->SetWString(L"排名");
		score->Cell(0,1)->SetWString(L"学号");
		score->Cell(0,2)->SetWString(L"姓名");
		score->Cell(0,3)->SetWString(L"总成绩");
		score->Cell(0,4)->SetWString(L"语文");
		score->Cell(0,5)->SetWString(L"数学");
		score->Cell(0,6)->SetWString(L"外语");
	}
	e.SaveAs("score.xls");
}



附录:

BasicExcel.hpp

#ifndef BASICEXCEL_HPP
#define BASICEXCEL_HPP

//MF
#if defined(_MSC_VER) && _MSC_VER<=1200 // VC++ 6.0
#pragma warning(disable: 4786)
#define LONGINT __int64
#define LONGINT_CONST(x) x
#define COMPOUNDFILE
#else	// newer Microsoft compilers
#define LONGINT long long
#define COMPOUNDFILE CompoundFile::
#define LONGINT_CONST(x) x##LL
#endif

#if _MSC_VER>=1400	// VS 2005
#define _CRT_SECURE_NO_WARNINGS //MF
#define _SCL_SECURE_NO_WARNINGS //MF
#endif

#ifdef __GNUC__
#define FMT_SIZE_T	  "%zu"
#define FMT_SSIZE_T   "%zd"
#define FMT_PTRDIFF_T "%zd"
#elif _MSC_VER>=1400	// VS 2005
#define FMT_SIZE_T	  "%Iu"
#define FMT_SSIZE_T   "%Id"
#define FMT_PTRDIFF_T "%Id"
#else
#define FMT_SIZE_T	  "%u"
#define FMT_SSIZE_T   "%d"
#define FMT_PTRDIFF_T "%d"
#endif

#include <algorithm>
#include <cmath>
#include <functional>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <map>
#include <vector>
#include <string>	//MF
using namespace std;

 // get facet from locale for GCC
#ifndef _USE
#define _USE(loc, fac) use_facet<fac >(loc) 
#endif

#include <assert.h> //MF

#define UTF16
#ifdef UTF16
	#define SIZEOFWCHAR_T 2
#else
	#define SIZEOFWCHAR_T sizeof(wchar_t)
#endif

namespace YCompoundFiles
{

class Block
// PURPOSE: In charge of handling blocks of data from a file
{
public:
	Block();

// File handling functions
	bool Create(const wchar_t* filename);
	bool Open(const wchar_t* filename, ios_base::openmode mode=ios_base::in | ios_base::out);
	bool Close();
	bool IsOpen();

// Block handling functions
	bool Read(size_t index, char* block);
	bool Write(size_t index, const char* block);
	bool Swap(size_t index1, size_t index2);
	bool Move(size_t from, size_t to);
	bool Insert(size_t index, const char* block);
	bool Erase(size_t index);
	bool Erase(vector<size_t>& indices);

// Misc functions
	size_t GetBlockSize() const {return blockSize_;}
	void SetBlockSize(size_t size)
	{
		blockSize_ = size;
		indexEnd_ = fileSize_/blockSize_ + (fileSize_ % blockSize_ ? 1 : 0);
	}

protected:
	vector<char> filename_;
	ios_base::openmode mode_;
	fstream file_;
	size_t blockSize_;
	size_t indexEnd_;
	size_t fileSize_;
};

struct LittleEndian
{
#if defined(_MSC_VER) && _MSC_VER<=1200 // VC++ 6.0
	#define READWRITE(Type) \
	static void Read(const char* buffer, Type& retVal, int pos=0, int bytes=0)	\
	{	\
		retVal = Type(0);	\
		if (bytes == 0) bytes = sizeof(Type);	\
		for (size_t i=0; i<bytes; ++i)	\
		{	\
			retVal |= ((Type)((unsigned char)buffer[pos+i])) << 8*i;	\
		}	\
	}	\
	static void ReadString(const char* buffer, Type* str, int pos=0, int bytes=0)	\
	{	\
		for (size_t i=0; i<bytes; ++i) Read(buffer, str[i], pos+i*sizeof(Type));	\
	}	\
	static void Write(char* buffer, Type val, int pos=0, int bytes=0)	\
	{	\
		if (bytes == 0) bytes = sizeof(Type);	\
		for (size_t i=0; i<bytes; ++i)	\
		{	\
			buffer[pos+i] = (unsigned char)val; \
			val >>= 8;	\
		}	\
	}	\
	static void WriteString(char* buffer, Type* str, int pos=0, int bytes=0)	\
	{	\
		for (size_t i=0; i<bytes; ++i) Write(buffer, str[i], pos+i*sizeof(Type));	\
	}	\
	static void Read(const vector<char>& buffer, Type& retVal, int pos=0, int bytes=0)	\
	{	\
		retVal = Type(0);	\
		if (bytes == 0) bytes = sizeof(Type);	\
		for (size_t i=0; i<bytes; ++i)	\
		{	\
			retVal |= ((Type)((unsigned char)buffer[pos+i])) << 8*i;	\
		}	\
	}	\
	static void ReadString(const vector<char>& buffer, Type* str, int pos=0, int bytes=0)	\
	{	\
		for (size_t i=0; i<bytes; ++i) Read(buffer, str[i], pos+i*sizeof(Type));	\
	}	\
	static void Write(vector<char>& buffer, Type val, int pos=0, int bytes=0)	\
	{	\
		if (bytes == 0) bytes = sizeof(Type);	\
		for (size_t i=0; i<bytes; ++i)	\
		{	\
			buffer[pos+i] = (unsigned char)val; \
			val >>= 8;	\
		}	\
	}	\
	static void WriteString(vector<char>& buffer, Type* str, int pos=0, int bytes=0)	\
	{	\
		for (size_t i=0; i<bytes; ++i) Write(buffer, str[i], pos+i*sizeof(Type));	\
	}	\

	READWRITE(char)
	READWRITE(unsigned char)
	READWRITE(short)
	READWRITE(int)
	READWRITE(unsigned int)
	READWRITE(long)
	READWRITE(unsigned long)
	READWRITE(__int64)
	READWRITE(unsigned __int64)

	#undef READWRITE


	static void Read(const char* buffer, wchar_t& retVal, int pos=0, int bytes=0)
	{
		retVal = wchar_t(0);
		if (bytes == 0) bytes = SIZEOFWCHAR_T;
		for (int i=0; i<bytes; ++i)
		{
			retVal |= ((wchar_t)((unsigned char)buffer[pos+i])) << 8*i;
		}
	}

	static void ReadString(const char* buffer, wchar_t* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Read(buffer, str[i], pos+i*SIZEOFWCHAR_T);
	}

	static void Write(char* buffer, wchar_t val, int pos=0, int bytes=0)
	{
		if (bytes == 0) bytes = SIZEOFWCHAR_T;
		for (int i=0; i<bytes; ++i)
		{
			buffer[pos+i] = (unsigned char)val;
			val >>= 8;
		}
	}

	static void WriteString(char* buffer, wchar_t* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Write(buffer, str[i], pos+i*SIZEOFWCHAR_T);
	}

	static void Read(const vector<char>& buffer, wchar_t& retVal, int pos=0, int bytes=0)
	{
		retVal = wchar_t(0);
		if (bytes == 0) bytes = SIZEOFWCHAR_T;
		for (int i=0; i<bytes; ++i)
		{
			if (pos+i < buffer.size())	//MF
				retVal |= ((wchar_t)((unsigned char)buffer[pos+i])) << 8*i;
		}
	}

	static void ReadString(const vector<char>& buffer, wchar_t* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Read(buffer, str[i], pos+i*SIZEOFWCHAR_T);
	}

	static void Write(vector<char>& buffer, wchar_t val, int pos=0, int bytes=0)
	{
		if (bytes == 0) bytes = SIZEOFWCHAR_T;
		for (int i=0; i<bytes; ++i)
		{
			buffer[pos+i] = (unsigned char)val;
			val >>= 8;
		}
	}

	static void WriteString(vector<char>& buffer, wchar_t* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Write(buffer, str[i], pos+i*SIZEOFWCHAR_T);
	}
#else
	template<typename Type>
	static void Read(const char* buffer, Type& retVal, int pos=0, int bytes=0)
	{
		retVal = Type(0);
		if (bytes == 0) bytes = sizeof(Type);
		for (int i=0; i<bytes; ++i)
		{
			retVal |= ((Type)((unsigned char)buffer[pos+i])) << 8*i;
		}
	}

	template<typename Type>
	static void ReadString(const char* buffer, Type* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Read(buffer, str[i], pos+i*sizeof(Type));
	}

	template<typename Type>
	static void Write(char* buffer, Type val, int pos=0, int bytes=0)
	{
		if (bytes == 0) bytes = sizeof(Type);
		for (int i=0; i<bytes; ++i)
		{
			buffer[pos+i] = (unsigned char)val;
			val >>= 8;
		}
	}

	template<typename Type>
	static void WriteString(char* buffer, Type* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Write(buffer, str[i], pos+i*sizeof(Type));
	}

	template<typename Type>
	static void Read(const vector<char>& buffer, Type& retVal, int pos=0, int bytes=0)
	{
		retVal = Type(0);
		if (bytes == 0) bytes = sizeof(Type);
		for (int i=0; i<bytes; ++i)
		{
			retVal |= ((Type)((unsigned char)buffer[pos+i])) << 8*i;
		}
	}

	template<typename Type>
	static void ReadString(const vector<char>& buffer, Type* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Read(buffer, str[i], pos+i*sizeof(Type));
	}

	template<typename Type>
	static void Write(vector<char>& buffer, Type val, int pos=0, int bytes=0)
	{
		if (bytes == 0) bytes = sizeof(Type);
		for (int i=0; i<bytes; ++i)
		{
			buffer[pos+i] = (unsigned char)val;
			val >>= 8;
		}
	}

	template<typename Type>
	static void WriteString(vector<char>& buffer, Type* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Write(buffer, str[i], pos+i*sizeof(Type));
	}


	static void Read(const char* buffer, wchar_t& retVal, int pos=0, int bytes=0)
	{
		retVal = wchar_t(0);
		if (bytes == 0) bytes = SIZEOFWCHAR_T;
		for (int i=0; i<bytes; ++i)
		{
			retVal |= ((wchar_t)((unsigned char)buffer[pos+i])) << 8*i;
		}
	}

	static void ReadString(const char* buffer, wchar_t* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Read(buffer, str[i], pos+i*SIZEOFWCHAR_T);
	}

	static void Write(char* buffer, wchar_t val, int pos=0, int bytes=0)
	{
		if (bytes == 0) bytes = SIZEOFWCHAR_T;
		for (int i=0; i<bytes; ++i)
		{
			buffer[pos+i] = (unsigned char)val;
			val >>= 8;
		}
	}

	static void WriteString(char* buffer, wchar_t* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Write(buffer, str[i], pos+i*SIZEOFWCHAR_T);
	}

	static void Read(const vector<char>& buffer, wchar_t& retVal, int pos=0, int bytes=0)
	{
		retVal = wchar_t(0);
		if (bytes == 0) bytes = SIZEOFWCHAR_T;
		for (int i=0; i<bytes; ++i)
		{
			if (pos+i < (int)buffer.size()) //MF
				retVal |= ((wchar_t)((unsigned char)buffer[pos+i])) << 8*i;
		}
	}

	static void ReadString(const vector<char>& buffer, wchar_t* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Read(buffer, str[i], pos+i*SIZEOFWCHAR_T);
	}

	static void Write(vector<char>& buffer, wchar_t val, int pos=0, int bytes=0)
	{
		if (bytes == 0) bytes = SIZEOFWCHAR_T;
		for (int i=0; i<bytes; ++i)
		{
			buffer[pos+i] = (unsigned char)val;
			val >>= 8;
		}
	}

	static void WriteString(vector<char>& buffer, wchar_t* str, int pos=0, int bytes=0)
	{
		for (int i=0; i<bytes; ++i) Write(buffer, str[i], pos+i*SIZEOFWCHAR_T);
	}
#endif
};

class CompoundFile
{
public:
	enum {DUPLICATE_PROPERTY=-6,
		  NAME_TOO_LONG=-5, FILE_NOT_FOUND=-4,
		  DIRECTORY_NOT_EMPTY=-3, DIRECTORY_NOT_FOUND=-2,
		  INVALID_PATH=-1,
		  SUCCESS=1};

	CompoundFile();
	~CompoundFile();

// User accessible functions
public:
	// Compound File functions
	bool Create(const wchar_t* filename);
	bool Open(const wchar_t* filename, ios_base::openmode mode=ios_base::in | ios_base::out);
	bool Close();
	bool IsOpen();

	// Directory functions
	int ChangeDirectory(const wchar_t* path);
	int MakeDirectory(const wchar_t* path);
	int PresentWorkingDirectory(wchar_t* path);
	int PresentWorkingDirectory(vector<wchar_t>& path);
	int RemoveDirectory(const wchar_t* path);
	int DelTree(const wchar_t* path);
	int DirectoryList(vector<vector<wchar_t> >& list, const wchar_t* path=0);

	// File functions
	int MakeFile(const wchar_t* path);
	int RemoveFile(const wchar_t* path);
	int FileSize(const wchar_t* path, size_t& size);
	int ReadFile(const wchar_t* path, char* data);
	int ReadFile(const wchar_t* path, vector<char>&data);
	int WriteFile(const wchar_t* path, const char* data, size_t size);
	int WriteFile(const wchar_t* path, const vector<char>&data, size_t size);

	// ANSI char functions
	bool Create(const char* filename);
	bool Open(const char* filename, ios_base::openmode mode=ios_base::in | ios_base::out);
	int ChangeDirectory(const char* path);
	int MakeDirectory(const char* path);
	int PresentWorkingDirectory(char* path);
	int PresentWorkingDirectory(vector<char>& path);
	int RemoveDirectory(const char* path);
	int DelTree(const char* path);
	int MakeFile(const char* path);
	int RemoveFile(const char* path);
	int FileSize(const char* path, size_t& size);
	int ReadFile(const char* path, char* data);
	int ReadFile(const char* path, vector<char>& data);
	int WriteFile(const char* path, char* data, size_t size);
	int WriteFile(const char* path, vector<char>& data, size_t size);

// Protected functions and data members
protected:
	// General functions and data members
	void IncreaseLocationReferences(vector<size_t> indices);
	void DecreaseLocationReferences(vector<size_t> indices);
	void SplitPath(const wchar_t* path, wchar_t*& parentpath, wchar_t*& propertyname);
	vector<char> block_;
	Block file_;

	// Header related functions and data members
	bool LoadHeader();
	void SaveHeader();
	class Header
	{
	public:
		Header();
		void Write(char* block);
		void Read(char* block);

		LONGINT fileType_;			// Magic number identifying this as a compound file system (0x0000)
		int uk1_;					// Unknown constant (0x0008)
		int uk2_;					// Unknown constant (0x000C)
		int uk3_;					// Unknown constant (0x0010)
		int uk4_;					// Unknown constant (0x0014)
		short uk5_; 				// Unknown constant (revision?) (0x0018)
		short uk6_; 				// Unknown constant (version?) (0x001A)
		short uk7_; 				// Unknown constant (0x001C)
		short log2BigBlockSize_;	// Log, base 2, of the big block size (0x001E)
		int log2SmallBlockSize_;	// Log, base 2, of the small block size (0x0020)
		int uk8_;					// Unknown constant (0x0024)
		int uk9_;					// Unknown constant (0x0028)
		size_t BATCount_;			// Number of elements in the BAT array (0x002C)
		size_t propertiesStart_;	// Block index of the first block of the property table (0x0030)
		int uk10_;					// Unknown constant (0x0034)
		int uk11_;					// Unknown constant (0x0038)
		size_t SBATStart_;			// Block index of first big block containing the small block allocation table (SBAT) (0x003C)
		size_t SBATCount_;			// Number of big blocks holding the SBAT (0x0040)
		size_t XBATStart_;			// Block index of the first block in the Extended Block Allocation Table (XBAT) (0x0044)
		size_t XBATCount_;			// Number of elements in the Extended Block Allocation Table (to be added to the BAT) (0x0048)
		size_t BATArray_[109];		// Array of block indices constituting the Block Allocation Table (BAT) (0x004C, 0x0050, 0x0054 ... 0x01FC)

		size_t bigBlockSize_;
		size_t smallBlockSize_;

	private:
		void Initialize();
	};
	Header header_;

	// BAT related functions and data members
	void LoadBAT();
	void SaveBAT();
	size_t DataSize(size_t startIndex, bool isBig);
	size_t ReadData(size_t startIndex, char* data, bool isBig);
	size_t WriteData(const char* data, size_t size, int startIndex, bool isBig);
	void GetBlockIndices(size_t startIndex, vector<size_t>& indices, bool isBig);
	size_t GetFreeBlockIndex(bool isBig);
	void ExpandBATArray(bool isBig);
	void LinkBlocks(size_t from, size_t to, bool isBig);
	void FreeBlocks(vector<size_t>& indices, bool isBig);
	vector<size_t> blocksIndices_;
	vector<size_t> sblocksIndices_;

	// Properties related functions and data members
	class Property
	{
	public:
		Property();
		void Write(char* block);
		void Read(char* block);
		friend bool operator==(const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs)
		{
			return (!wcscmp(lhs.name_, rhs.name_));
		}
		friend bool operator< (const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs)
		{
			size_t maxLen1 = wcslen(lhs.name_);
			size_t maxLen2 = wcslen(rhs.name_);
			if (maxLen1 < maxLen2) return true;
			else if (maxLen1 > maxLen2) return false;
			else
			{
				int result = wcscmp(lhs.name_, rhs.name_);
				if (result <= 0) return true;
				else return false;
			}
		}
		friend bool operator!=(const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) {return !(lhs == rhs);}
		friend bool operator> (const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) {return (rhs < lhs);}
		friend bool operator<=(const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) {return !(rhs < lhs);}
		friend bool operator>=(const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) {return !(lhs < rhs);}

		wchar_t name_[32];				// A unicode null-terminated uncompressed 16bit string (lblocke the high bytes) containing the name of the property. (0x00, 0x02, 0x04, ... 0x3E)
		short nameSize_;				// Number of characters in the NAME field (0x40)
		unsigned char propertyType_;	// Property type (directory, file, or root) Byte 1 (directory), 2 (file), or 5 (root entry) (0x42)
		unsigned char nodeColor_;		// Node color (0x43)
		size_t previousProp_;			// Previous property index (0x44)
		size_t nextProp_;				// Next property index (0x48)
		size_t childProp_;				// First child property index (0x4c)
		int uk1_;
		int uk2_;
		int uk3_;
		int uk4_;
		int uk5_;
		int seconds1_;					// Seconds component of the created timestamp? (0x64)
		int days1_; 					// Days component of the created timestamp? (0x68)
		int seconds2_;					// Seconds component of the modified timestamp? (0x6C)
		int days2_; 					// Days component of the modified timestamp? (0x70)
		size_t startBlock_; 			// Starting block of the file, used as the first block in the file and the pointer to the next block from the BAT (0x74)
		int size_;						// Actual size of the file this property points to. (used to truncate the blocks to the real size). (0x78)
	};

	class PropertyTree
	{
	public:
		PropertyTree();
		~PropertyTree();
		PropertyTree* parent_;
		Property* self_;
		size_t index_;
		vector<PropertyTree*> children_;
	};
	void LoadProperties();
	void SaveProperties();
	int MakeProperty(const wchar_t* path, Property* property);
	PropertyTree* FindProperty(size_t index);
	PropertyTree* FindProperty(const wchar_t* path);
	PropertyTree* FindProperty(PropertyTree* parentTree, wchar_t* name);
	void InsertPropertyTree(PropertyTree* parentTree, Property* property, size_t index);
	void DeletePropertyTree(PropertyTree* tree);
	void UpdateChildrenIndices(PropertyTree* parentTree);
	void IncreasePropertyReferences(PropertyTree* parentTree, size_t index);
	void DecreasePropertyReferences(PropertyTree* parentTree, size_t index);
	PropertyTree* propertyTrees_;
	PropertyTree* currentDirectory_;
	vector<Property*> properties_;
	vector<PropertyTree*> previousDirectories_;
};

} // YCompoundFiles namespace end


 // reference counting to implement smart pointers

namespace RefCount
{

 // reference counter for SmartPtr managed objects
struct RefCnt
{
	 // On construction the reference counter is initialized with an usage count of 0.
	RefCnt()
	 :	_ref_cnt(0)
	{
	}

	int _ref_cnt;
};

 // reference counting smart pointer
template<typename T> struct SmartPtr
{
	 // default constructor
	SmartPtr()
	 :	_ptr(NULL)
	{
	}

	 // The initialized SmartPtr constructor increments the reference counter in struct RefCnt.
	SmartPtr(T* p)
	 :	_ptr(p)
	{
		if (p)
			++_ptr->_ref_cnt;
	}

	 // The copy constructor increments the reference counter.
	SmartPtr(const SmartPtr& other)
	 :	_ptr(other._ptr)
	{
		if (_ptr)
			++_ptr->_ref_cnt;
	}

	 // The destructor decreases the reference counter and
	 // frees the managed memory as the counter reaches zero.
	~SmartPtr()
	{
		if (_ptr) {
			if (!--_ptr->_ref_cnt)
				delete _ptr;
		}
	}

	 // The assignment operator increments the reference counter.
	SmartPtr& operator=(T* p)
	{
		if (_ptr) {
			if (!--_ptr->_ref_cnt)
				delete _ptr;

			_ptr = NULL;
		}

		if (p) {
			_ptr = p;

			++_ptr->_ref_cnt;
		}

		return *this;
	}

	 // operator bool() to check for non-empty smart pointers
	operator bool() const {return _ptr != NULL;}

	 // operator!() to check for empty smart pointers
	bool operator!() const {return !_ptr;}

	 // operator->() to access the managed objects
	T* operator->() {return _ptr;}
	const T* operator->() const {return _ptr;}

	 // Derefence pointed memory
	T& operator*() {return *_ptr;}
	const T& operator*() const {return *_ptr;}

private:
	T* _ptr;
};

} // namespace RefCount


//MF
namespace ExcelFormat {
struct CellFormat;
}


namespace YExcel
{
using namespace YCompoundFiles;

struct CODE
{
	enum {	FORMULA=0x0006, 		//Token array and the result of a formula cell.
			YEOF=0x000A,			//End of a record block with leading BOF record.
			CALCCOUNT=0x000C,		//Maximum number of times the forumlas should be iteratively calculated
			CALCMODE=0x000D,		//Calculate formulas manually, automatically, or automatically except for multiple table operations
			PRECISION=0x000E,		//Whether formulas use the real cell values for calculation or the values displayed on the screen.
			REFMODE=0x000F, 		//Method used to show cell addresses in formulas.
			DELTA=0x0010,			//Maximum change of the result to exit an iteration.
			ITERATION=0x0011,		//Whether iterations are allowed while calculating recursive formulas.
			PROTECT=0x0012, 		//Whether worksheet or a workbook is protected against modification.
			PASSWORD=0x0013,		//16-bit hash value, calculated from the worksheet or workbook protection password.
			HEADER=0x0014,			//Page header string for the current worksheet.
			FOOTER=0x0015,			//Page footer string for the current worksheet.
			EXTERNSHEET=0x0017, 	//List with indexes to SUPBOOK records
			NAME=0x0018,			//Name and token array of an internal defined name.
			WINDOWPROTECT=0x0019,	//Whether the window configuration of the document is protected.
			SELECTION=0x001D,		//Addresses of all selected cell ranges and position of the active cell for a pane in the current sheet.
			DATEMODE=0x0022,		//Base date for displaying date values.
			EXTERNNAME=0x0023,		//Name of an external defined name, name of an add-in function, a DDE item or an OLE object storage identifier.
			LEFTMARGIN=0x0026,		//Left page margin of the current worksheet.
			RIGHTMARGIN=0x0027, 	//Right page margin of the current worksheet.
			TOPMARGIN=0x0028,		//Top page margin of the current worksheet.
			BOTTOMMARGIN=0x0029,	//Bottom page margin of current worksheet
			PRINTHEADERS=0x002A,	//Whether row and column headers (the areas with row numbers and column letters) will be printed.
			PRINTGRIDLINES=0x002B,	//Whether sheet grid lines will be printed.
			FILEPASS=0x002F,		//Information about the read/write password of the file.
			FONT=0x0031,			//Information about a used font, including character formatting.
			TABLE=0x0036,			//Information about a multiple operation table in the sheet.
			CONTINUE=0x003C,		//Continue from previous record
			WINDOW1=0x003D, 		//General settings for the workbook global settings.
			BACKUP=0x0040,			//Make backup of file while saving?
			PANE=0x0041,			//Position of window panes.
			CODEPAGE=0x0042,		//Text encoding used to encode byte strings
			DCONREF=0x0051,
			DEFCOLWIDTH=0x0055, 	//Default column width for columns that do not have a specific width set
			XCT=0x0059, 			//Number of immediately following CRN records.
			CRN=0x005A, 			//Contents of an external cell or cell range.
			FILESHARING=0x005B, 	//Information about write protection, for instance the write protection password.
			WRITEACCESS=0x005C, 	//Name of the user that has saved the file.
			UNCALCED=0x005E,		//Formulas have not been recalculated before the document was saved.
			SAVERECALC=0x005F,		//"Recalculate before save" option
			OBJECTPROTECT=0x0063,	//Whether objects of the current sheet are protected.
			COLINFO=0x007D, 		//Width for a given range of columns
			GUTS=0x0080,			//Layout of outline symbols.
			WSBOOL=0x0081,			//16-bit value with boolean options for the current sheet.
			GRIDSET=0x0082, 		//Whether option to print sheet grid lines has ever been changed.
			HCENTER=0x0083, 		//Sheet is centred horizontally when printed.
			VCENTER=0x0084, 		//Whether sheet is centred vertically when printed.
			BOUNDSHEET=0x0085,		//Sheet inside of the workbook
			WRITEPROT=0x0086,		//Whether file is write protected.
			COUNTRY=0x008C, 		//User interface language of the Excel version that has saved the file, system regional settings at the time the file was saved.
			HIDEOBJ=0x008D, 		//Whether and how to show objects in the workbook.
			SORT=0x0090,			//Last settings from the "Sort" dialogue for each sheet.
			PALETTE=0x0092, 		//Definition of all user-defined colours available for cell and object formatting.
			SETUP=0x00A1,			//Page format settings of the current sheet.
			SHRFMLA=0x00BC, 		//Token array of a shared formula.
			MULRK=0x00BD,			//Cell range containing RK value cells. All cells are located in the same row.
			MULBLANK=0x00BE,		//Cell range of empty cells. All cells are located in the same row.
			DBCELL=0x00D7,			//Relative offsets to calculate stream position of the first cell record for each row.
			BOOKBOOL=0x00DA,		//Save values linked from external workbooks records and XCT records?
			SCENPROTECT=0x00DD, 	//Whether scenarios of the current sheet are protected.
			XF=0x00E0,				//Formatting information for cells, rows, columns or styles.
			MERGEDCELLS=0x00E5, 	//All merged cell ranges of the current sheet.
			SST=0x00FC, 			//List of all strings used anywhere in the workbook.
			LABELSST=0x00FD,		//Cell that contains a string.
			EXTSST=0x00FF,			//Create a hash table with stream offsets to the SST record to optimise string search operations.
			LABELRANGES=0x015F, 	//Addresses of all row and column label ranges in the current sheet.
			USESELFS=0x0160,		//Whether formulas in the workbook can use "natural language formulas".
			DSF=0x0161, 			//Whether file contains an addition BIFF5/BIFF7 workbook stream.
			SUPBOOK=0x01AE, 		//URL of an external document and a list of sheet names inside this document.
			CONDFMT=0x01B0, 		//List of cell range addresses for all cells with equal conditional formatting.
			CF=0x01B1,				//Condition and the formatting attributes applied to the cells specified in the CONDFMT record, if the condition is met
			DVAL=0x01B2,			//List header of the data validity table in the current sheet.
			HLINK=0x01B8,			//One cell address or a cell range where all cells contain the same hyperlink.
			DV=0x01BE,				//Data validity settings and a list of cell ranges which contain these settings.
			DIMENSIONS=0x0200,		//Range address of the used area in the current sheet.
			BLANK=0x0201,			//Empty cell, contains cell address and formatting information
			NUMBER=0x0203,			//Cell that contains a floating-point value.
			BOOLERR=0x0205, 		//Error value cell
			STRING=0x0207,			//Result of a string formula.
			ROW=0x0208, 			//Properties of a single row in the sheet.
			INDEX=0x020B,			//Range of used rows and stream positions of several records of the current sheet.
			ARRAY=0x0221,			//Token array of an array formula
			WINDOW2=0x023E, 		//Additional settings for the window of a specific worksheet.
			RK=0x027E,				//Cell that contains an RK value (encoded integer or floating point value).
			STYLE=0x0293,			//Name of a user-defined cell style or specific options for a built-in cell style.
			FORMAT=0x041E,			//Number format.
			SHRFMLA1=0x04BC,		//Token array of a shared formula (added).
			QUICKTIP=0x0800,		//Cell range and text for a tool tip.
			BOF=0x0809, 			//Beginning of file
			SHEETLAYOUT=0x0862, 	//Colour of the tab below the sheet containing the sheet name.
			SHEETPROTECTION=0x0867, //Additional options for sheet protection.
			RANGEPROTECTION=0x0868	//Information about special protected ranges in a protected sheet.
		};
};

class Record
{
public:
	Record();
	virtual ~Record();
	virtual size_t Read(const char* data);
	virtual size_t Write(char* data);
	virtual size_t DataSize();
	virtual size_t RecordSize();
	short code_;
	vector<char> data_;
	size_t dataSize_;
	size_t recordSize_;
	vector<size_t> continueIndices_;
};

struct BOF : public Record
{
	BOF();
	virtual size_t Read(const char* data);
	virtual size_t Write(char* data);
	short version_;
	short type_;
	short buildIdentifier_;
	short buildYear_;
	int fileHistoryFlags_;
	int lowestExcelVersion_;
};

struct YEOF : public Record
{
	YEOF();
};

 // String with 1 byte length field
struct SmallString
{
	SmallString();
	~SmallString();
	SmallString(const SmallString& s);

	SmallString& operator=(const SmallString& s);
	const SmallString& operator=(const char* str);
	const SmallString& operator=(const wchar_t* str);

	void Reset();
	size_t Read(const char* data);
	size_t Write(char* data);
	size_t DataSize();
	size_t RecordSize();
	size_t StringSize();

	wch
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值