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方法