1、首先这个工具是基于MFC的,先建立一个基于对话框的项目
2、引入exce.h和excel.cpp文件,要在stdafx.h添加:
(1)、#include"excel.h",#pragma comment(lib,"comsupp.lib"),与project->setting中Link中设置一样
(2)、typedef std::wstring PMTSTRING;我的代码里使用了PMTSTRING这种类型
2、操作Excel的文件
(1).h
class CExcelOpr
{
public:
//private:
CExcelOpr() ;
public:
virtual ~CExcelOpr();
// static CExcelOpr & Instance() ;
public:
/// 启动excel
void StartExcel() ;
/// 释放资源
void ReleaseExcel() ;
/// 启动excel
void OpenBook( const PMTSTRING & strFileName ) ;
/// 关闭
void CloseBook() ;
///
void LoadSheet( const int iIndex);
///
void LoadSheet( const CString & strSheetName ) ;
///
int GetRowCount() ;
///
int GetColCount();
///
CString GetCell( const int iCol , const int iRow );
///
int GetSheetCount() ;
///
CString GetSheetName( const int iIndex ) ;
/// 关闭excel
void CloseExcel() ;
/// 获取指定表格的内容
PMTSTRING GetText( const PMTSTRING & strRange ) ;
///
BOOL IsMergeCell( const int iSrcRow , const int iSrcCol , CString & strText ) ;
CString GetRangeText( Range & range ) ;
public:
void SetCell( const int iCol , const int iRow , const PMTSTRING & strValue ) ;
void SaveBook( const PMTSTRING & strFileName ) ;
void NewExcelBook(const PMTSTRING & strFileName);
void MergeCell(const int iCol, const int iRow);
private:
/// excel app 操作
_Application m_app;
///
Workbooks m_books;
///
_Workbook m_book;
/// sheet 页
Worksheets m_sheets;
/// 单个sheet 页
_Worksheet m_sheet;
/// 处理范围
Range m_range;
long m_lFileFormat ;
};
(2).cpp实现方法,网上有许多实现方法,我是直接引入的Excel操作方法,我只写上没有的
//新建表
void CExcelOpr::NewExcelBook(const PMTSTRING& strFileName)
{
CopyFile(_T("G:\\sys.xlsx"), strFileName.c_str(), TRUE);
/*m_books = m_app.GetWorkbooks();
m_book = m_books.Add(COleVariant(strFileName.c_str()); //这个新建Excel表方法总是跳出Add方法无效
m_book = m_books.Add(covOptional); //
m_sheets = m_book.GetSheets();
m_sheet = m_sheets.GetItem(COleVariant((short)1)); */
}
//合并单元格并居中
void CExcelOpr::MergeCell(const int iCol, const int iRow)
{
m_range.AttachDispatch(m_sheet.GetCells());
m_range.AttachDispatch(m_range.GetItem(COleVariant((long)1), COleVariant((long)1)).pdispVal);
m_range.AttachDispatch(m_range.GetResize(COleVariant((long)iRow), COleVariant((long)iCol)));
m_range.Merge(COleVariant((long)0)); //合并单元格
m_range.SetHorizontalAlignment(_variant_t((long)-4108)); //水平居中
}
我的新建Excel总是出现Add方法无效,暂时我也解决不了,我就在本地建立一个空白表格,每次新建表去复制它,还有一个CreatFile方法,但是Open又会出现错误,说什么格式不对打不开。
3、对话框部分
在下面属性对话框修改空间内容、格式,我们可以通过ID实现代码控件关联
(1)、这是对话框自动生成的.h文件
public:
afx_msg void OnBnClickedButtonleftpath();
afx_msg void OnBnClickedButtonrightpath();
CString m_strLeftPath; //self
CString m_strRightPath; //self
afx_msg void OnBnClickedOk();
CString strNewDesPath; //这是新建表文件名称,可以实现参数CString strNewDesPath = _T("G:\\测试数据.xlsx");
CString StrcatValue= _T("误差数据表.xlsx");
(1)、这是对话框自动生成的.cpp文件
CExcelDateDlg::CExcelDateDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_EXCELDATE_DIALOG, pParent)
, m_strLeftPath(_T("")) //初始化
, m_strRightPath(_T(""))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CExcelDateDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_strLeftPath); //对话框做数据交换
DDX_Text(pDX, IDC_EDIT2, m_strRightPath);
}
//.........省略很多行
void CExcelDateDlg::OnBnClickedButtonleftpath()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(true); //打开对话框,false另存为对话框
if (IDOK == dlg.DoModal()) //用户是否点击了确认按钮
{
CString strPathName = dlg.GetPathName();
m_strLeftPath = strPathName;
UpdateData(FALSE); //对话框空间更新显示:赋值,true,用在访问变量之前调用,了解对话框输入内容,取值
}
}
void CExcelDateDlg::OnBnClickedButtonrightpath()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(true); //打开对话框,false另存为对话框
if (IDOK == dlg.DoModal()) //用户是否点击了确认按钮
{
CString strPathName = dlg.GetPathName();
m_strRightPath = strPathName;
UpdateData(FALSE); //对话框空间更新显示:赋值,true,用在访问变量之前调用,了解对话框输入内容,取值
}
}
void CExcelDateDlg::OnBnClickedOk()
{
UpdateData();
CDialogEx::OnOK();
CImportTable importTable;
strNewDesPath=importTable.MyStrcat(m_strRightPath,StrcatValue);
importTable.ImportTable((PMTSTRING)m_strLeftPath, (PMTSTRING)m_strRightPath, (PMTSTRING)strNewDesPath); //
// TODO: 在此添加控件通知处理程序代码
}
4、实现你的功能操作部分
(1).h文件
#pragma once
class CImportTable
{
public :
CImportTable();
~CImportTable();
public:
virtual void ImportTable(const PMTSTRING &strlExcelPath, const PMTSTRING &strRExcelPath, const PMTSTRING &strNewExcelPath);
virtual CString MyStrcat(const CString strRExcelPath, const CString StrcatValue);
CString MiddleExcelPath;
protected:
virtual void InitData();
protected:
struct SetData
{
static int m_iFieldCol; /// 列名开始列 static
static int m_iFieldRow; /// 列名所在的行
};
};
namespace dataservice{
enum {
eNum_0 = 0
, eNum_1 = 1
, eNum_2 = 2
, eNum_3 = 3
, eNum_4 = 4
};
}
(2).cpp文件
#include "stdafx.h"
#include "ImportTable.h"
#include "Pdbt_ExcelOpr.h " //self
//#include<vector>
using std::vector;
CImportTable::CImportTable()
{
}
CImportTable::~CImportTable()
{
}
int CImportTable::SetData::m_iFieldCol = -1;
int CImportTable::SetData::m_iFieldRow = -1;
void CImportTable::InitData()
{
CImportTable::SetData ::m_iFieldRow = dataservice::eNum_1;
CImportTable::SetData ::m_iFieldCol = dataservice::eNum_1;
}
CString CImportTable::MyStrcat(const CString strRExcelPath, const CString StrcatValue) {
int index=strRExcelPath.Find(_T("."));
MiddleExcelPath = strRExcelPath.Left(index); //strPath.GetLength() - 16
CString ret= MiddleExcelPath + StrcatValue;
return ret;
}
void CImportTable::ImportTable(const PMTSTRING &strLExcelPath, const PMTSTRING &strRExcelPath, const PMTSTRING &strNewExcelPath)
{
CExcelOpr tableOld, tableNew;
{
tableOld.StartExcel(); //启动Excel
tableOld.OpenBook(strLExcelPath);
tableOld.LoadSheet(1);
tableNew.StartExcel(); //启动Excel
tableNew.OpenBook(strRExcelPath);
tableNew.LoadSheet(1);
}
int iRowCount = tableOld.GetRowCount(); //获取已使用行数
int iColCount = tableOld.GetColCount(); //获取已使用列数
int rRowCount = tableNew.GetRowCount(); //获取已使用行数
int rColCount = tableNew.GetColCount(); //获取已使用列数
int iRow = CImportTable::SetData::m_iFieldRow + dataservice::eNum_2;
int iCol = CImportTable::SetData::m_iFieldRow + dataservice::eNum_2;
//判断行列数是否相等
int iExcelRow, iExcelCol;
if (iRowCount >= rRowCount)
{
iExcelRow = iRowCount;
}else{
iExcelRow = rRowCount;
}
if (iColCount >= rColCount)
{
iExcelCol = iColCount;
}else{
iExcelCol = rColCount;
}
CExcelOpr tableDiff, excelOpr;
bool NewBook = false;
for (;iRow <= iExcelRow; ++iRow)
{
for (iCol=1;iCol <= iExcelCol; ++iCol) {
CString strOld = tableOld.GetCell(iCol, iRow);
CString strNew = tableNew.GetCell(iCol, iRow);
if (strOld != strNew)
{
if (NewBook==false)
{
tableDiff.StartExcel();
tableDiff.NewExcelBook(strNewExcelPath); //不能每次都新建表,打开表
tableDiff.OpenBook(strNewExcelPath);
tableDiff.LoadSheet(1);
NewBook = true; //新建表执行一次
}
if (tableOld.IsMergeCell(iRow, iCol, strOld)&&tableNew.IsMergeCell(iRow, iCol, strNew)) {
//不是合并的单元格,将第一个单元格合并成2行,3列
tableDiff.MergeCell(iCol,iRow);
}
tableDiff.SetCell( iCol, iRow, (PMTSTRING)strNew);
}
}
}
tableDiff.SaveBook((PMTSTRING)strNewExcelPath);
excelOpr.CloseBook();
excelOpr.ReleaseExcel();
excelOpr.CloseExcel();
}
7、注意:报错
(1)、tableOld.StartExcel()报错:在你建立的工程自动生成的.cpp文件下类似BOOL CExcelDateApp::InitInstance()里添加:
AfxOleInit(); //Excel启动报错,添加home环境的初始化
(2)、tableOld.LoadSheet(1);这个纯属我的问题,开始一直传的0值,这个写的LoadSheet方法要对应上
(3)、最后就是新建表的问题了,使用了CopyFile方法