C 實現一個簡單的數據對比工具

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章