本来以为把MFC里CFileDialog类的文件类型过滤器szFileters加个 *.xlsx 这样的类型,就可以导入导出xlsx了,但是完全是想当然啊(没试过你永远不知道结果是否是预期的!)
本文目的旨在用纯c/c++代码导入导出csv/excel等格式文件!
话不多说,首先创建一个类似这样的窗口,在文件菜单设置子菜单 导入和导出
这里需要知道csv和excel文件的区别:csv文件是以逗号分隔的纯文本文件,而excel文件带有格式,这就决定了我们需要用不同方法导入或者导出。
所以在导入/导出csv文件时,直接用文件读写的方式就ok了。比如导入:
csv内容如下:
这里要记得,导入之前一定要把文件关了,不然无法导入,因为文件占用打不开!(浪费了我半天时间,以为程序写错了~~)
在最最开始的时候,我用了一个函数批量生成一些数据,放在了OnInitDialog()函数里,rowPitch是列间距,我设置的70
//初始化列名
mList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
colCount = COL_END; //列数
rowCount = 25; //行数
colName.push_back(_T("序号"));
colName.push_back(_T("名字"));
colName.push_back(_T("年龄"));
colName.push_back(_T("住址"));
colName.push_back(_T("工资"));
for(int i = 0; i < colCount; i++)
mList.InsertColumn(i,colName[i],LVCFMT_CENTER,rowPitch);
//初始化列表信息
CString rowName;//行名
for(int row = 0; row < rowCount; row++){
//添加一行
rowName.Format(_T(" %d"),row+1);
mList.InsertItem(row,rowName);//行名为序号,又因为从第二行开始计数
//为添加的行插入数据
mList.SetItemText(row,COL_NAME,_T("张三丰"));
mList.SetItemText(row,COL_AGE,_T("99"));
mList.SetItemText(row,COL_ADDRESS,_T("北京"));
mList.SetItemText(row,COL_SALARY,_T("99000"));
}
当然,如果是导入的话,这些数据都没有用,所以先清空一下,这里需要注意,要把列名也清空掉! 不然插入数据的时候,会出现两行列名!
实现代码如下:
void FileDlg::OnBnClickedClearList()
{
//清空列表
mList.DeleteAllItems();//清空list列表
colName.clear();//清空原有列名容器
while(mList.DeleteColumn(0));//清空列
mList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
}
接着是导入导出了,比如导入csv文件到程序里,实现如下,
//导入csv文件到程序中
void FileDlg::OnImport()
{
CFileDialog fileOpenDlg(TRUE,_T("*.xlsx"),NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,
_T("csv file(*.csv)|*.csv|Microsoft Excel 工作表(*.xlsx)|*.xlsx|All files (*.*)|*.*||"),NULL);
fileOpenDlg.m_ofn.lpstrTitle = _T("Open File");
if(fileOpenDlg.DoModal() == IDOK)//导入对话框打开
{
CString szLine;
CStdioFile file;
if(file.Open(fileOpenDlg.GetPathName(),CFile::modeRead))//打开选中的文件
{
//清空列表
mList.DeleteAllItems();//清空list列表
colName.clear();//清空原有列名容器
while(mList.DeleteColumn(0));//清空列
mList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
//获取文件首行de列名,并插入到list列表
file.ReadString(szLine);//把文件中列名那一行读走
if(szLine.GetLength() > 2)
{
CStringArray strColName;
SplitString(szLine,',',strColName);//获取文件中首行内容,去掉分隔符‘,’
for(int startRow = 0;startRow < strColName.GetCount(); startRow++)
{
colName.push_back(strColName.GetAt(startRow));//保存首行到列名容器
mList.InsertColumn(startRow,strColName.GetAt(s