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