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

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