/////////////////////////////////////////////////////////////////////////
// 类名:CSpreadSheet
// 功能:读、写Excel文件或指定分隔符分隔的文本文件类
// 附注:导入、导出指定数据的Excel文件或分隔符文本文件
// 修改:徐景周(jingzhou_xu@163.com)
// 组织:Future Studio
// 日期:2003.1.8
////////////////////////////////////////////////////////////////////////
#ifndef CSPREADSHEET_H
#define CSPREADSHEET_H

#include <odbcinst.h>
#include <afxdb.h>

class CSpreadSheet
{
public:
	CSpreadSheet(CString File, CString SheetOrSeparator, bool Backup = false);			// 为进行读写操作,进行的预处理工作
	~CSpreadSheet();																	// 清理工作
	void Close();

	bool AddHeaders(CStringArray &FieldNames, bool replace = false);					// 添加首行列头
	bool DeleteSheet();																	// 删除分隔符文本文件内容
	bool DeleteSheet(CString SheetName);												// 删除指定表格全部内容,但表格自身不被删除
	bool AddRow(CStringArray &RowValues, long row = 0, bool replace = false);			// 播放或替换一行
	bool AddCell(CString CellValue, CString column, long row = 0, bool Auto = true);	// 使用行号或字母列号替换或添加一单元格
	bool AddCell(CString CellValue, short column, long row = 0);						// 使用行、列号替换或添加一单元格
	bool ReplaceRows(CStringArray &NewRowValues, CStringArray &OldRowValues);			// 在Excel表格中替换行
	bool ReadRow(CStringArray &RowValues, long row = 0);								// 读取一行
	bool ReadColumn(CStringArray &ColumnValues, CString column, bool Auto = true);		// 使用行号、字母列号读取一列
	bool ReadColumn(CStringArray &ColumnValues, short column);							// 使用列号读取一列
	bool ReadCell (CString &CellValue, CString column, long row = 0, bool Auto = true); // 使用行号、字母列号读取单元格
	bool ReadCell (CString &CellValue, short column, long row = 0);						// 使用列号读取单元格
	void BeginTransaction();															// 开始事务
	bool Commit();																		// 保存改变状态
	bool RollBack();																	// 回滚改变状态
	bool Convert(CString SheetOrSeparator);
																						// 获取首行列头名
	inline void GetFieldNames (CStringArray &FieldNames) {FieldNames.RemoveAll(); FieldNames.Copy(m_aFieldNames);} 
	inline long GetTotalRows() {return m_dTotalRows;}									// 获取总行数
	inline short GetTotalColumns() {return m_dTotalColumns;}							// 获取总列数
	inline long GetCurrentRow() {return m_dCurrentRow;}									// 获取当前选中行
	inline bool GetBackupStatus() {return m_bBackup;}									// 获取备份状态. True表示备份, False不进行备份
	inline bool GetTransactionStatus() {return m_bTransaction;}							// 获取事务状态. True表示开始, False表示没有开始或开始时产生错误
	inline CString GetLastError() {return m_sLastError;}								// 获取最后错误信息

private:
	bool Open();																		// 为进行读写打开处理
	void GetExcelDriver();																// 获取Excel-ODBC驱动程序
	short CalculateColumnNumber(CString column, bool Auto);								// 转换Excel字母列号为对应数字列号

	bool	m_bAppend;			// 新建表格还是使用原表格内部标志
	bool	m_bBackup;			// 备份状态内部标志
	bool	m_bExcel;			// 是Excel表格文件还是分隔符文本文件内部标志
	bool	m_bTransaction;		// 事务状态内部标志

	long	m_dCurrentRow;		// 当前行号索引, 起始为1
	long	m_dTotalRows;		// 总行数
	short	m_dTotalColumns;	// Excel文件时总列数,分隔符文本文件中最大列数

	CString m_sSql;				// 打开Excel进行读写SQL语句
	CString m_sDsn;				// 打开Excel进行读写的DSN名
	CString m_stempSql;			// 临时SQL字符串
	CString m_stempString;		// 临时字符串
	CString m_sSheetName;		// Excel表格名
	CString m_sExcelDriver;		// Excel驱动程序名
	CString m_sFile;			// 文件名
	CString m_sSeparator;		// 文本文件分隔符
	CString m_sLastError;		// 错误信息

	CStringArray m_atempArray;	// 临时数组
	CStringArray m_aFieldNames; // 字段数组
	CStringArray m_aRows;		// 行存储

	CDatabase	*m_Database;	// 数据库变量
	CRecordset	*m_rSheet;		// 记录集变量
};

// 为读写进行打开处理(File -- 文件名,SheetOrSeparator -- Excel表名或文本分隔符,Backup -- 是否创建备份表)
CSpreadSheet::CSpreadSheet(CString File, CString SheetOrSeparator, bool Backup /* = false */) :
m_Database(NULL), m_rSheet(NULL), m_sFile(File),
m_dTotalRows(0), m_dTotalColumns(0), m_dCurrentRow(1),
m_bAppend(false), m_bBackup(Backup), m_bTransaction(false)
{
	// 检测文件是Excel表格还是分隔符文本文件
	m_stempString		= m_sFile.Right(4);
	m_stempString.MakeLower();
	if (m_stempString == ".xls") // 当是Excel表格文件时
	{
		m_bExcel		= true;
		m_sSheetName	= SheetOrSeparator;
		m_sSeparator	= " ,;.?";
	}
	else						// 当是分隔符文本文件时
	{
		m_bExcel		= false;
		m_sSeparator	= SheetOrSeparator;
	}

	// 当文件是Excel文件时
	if (m_bExcel) 
	{
		m_Database = new CDatabase;
		GetExcelDriver();
		m_sDsn.Format("DRIVER={%s};DSN='';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s", m_sExcelDriver, m_sFile, m_sFile);

		if (Open())				// 是否已存在Excel文件及表可以打开
		{
			if (m_bBackup)		// Excel中表存在并可以打开的话,是否做原始备份表
			{
				if ((m_bBackup) && (m_bAppend))
				{
					CString tempSheetName	= m_sSheetName;
					m_sSheetName			= m_sSheetName + "备份";
					m_bAppend				= false;

					// 在此创建备份表
					if (!Commit())
					{
						m_bBackup			= false;
					}
					m_bAppend				= true;
					m_sSheetName			= tempSheetName;
					m_dCurrentRow			= 1;
				}
			}
		}
	}
	else // 当文件是指定分隔符分隔的文本文件时
	{
		if (Open())
		{
			if ((m_bBackup) && (m_bAppend))
			{
				m_stempString	= m_sFile;
				m_stempSql.Format("%s.bak", m_sFile);
				m_sFile			= m_stempSql;
				if (!Commit())
				{
					m_bBackup	= false;
				}
				m_sFile			= m_stempString;
			}
		}
	}
}

// 清理工作
CSpreadSheet::~CSpreadSheet()
{
	Close();
}
// 清理工作
void CSpreadSheet::Close()
{
	if ( NULL != m_rSheet )
	{
		m_rSheet->Close();
		delete m_rSheet;
		m_rSheet = NULL;
	}
	if (NULL != m_Database)
	{
		m_Database->Close();
		delete m_Database;
		m_Database=NULL;
	}
}
// 添加首行列头到表格中
bool CSpreadSheet::AddHeaders(CStringArray &FieldNames, bool replace)
{
	if (m_bAppend)		// 原表格后追加
	{
		if (replace)	// 替换首行而不是添加新列
		{
			if (!AddRow(FieldNames, 1, true))
			{
				return false;
			}
			else
			{
				return true;
			}
		}

		if (ReadRow(m_atempArray, 1)) // 添加新列
		{
			if (m_bExcel)
			{
				// 检查首行列头字段是否重复
				for (int i = 0; i < FieldNames.GetSize(); i++)
				{
					for (int j = 0; j < m_atempArray.GetSize(); j++)
					{
						if (FieldNames.GetAt(i) == m_atempArray.GetAt(j))
						{
							m_sLastError.Format("首行列头字段重复:%s\n", FieldNames.GetAt(i));
							return false;
						}
					}
				}	
			}

			m_atempArray.Append(FieldNames);
			if (!AddRow(m_atempArray, 1, true))
			{
				m_sLastError = "添加列头时产生错误\n";
				return false;
			}

			// 更新总列数
			if (m_atempArray.GetSize() > m_dTotalColumns)
			{
				m_dTotalColumns = m_atempArray.GetSize();
			}
			return true;
		}
		return false;				
	}
	else // 新表格
	{
		m_dTotalColumns = FieldNames.GetSize();
		if (!AddRow(FieldNames, 1, true))
		{
			return false;
		}
		else
		{
			m_dTotalRows = 1;
			return true;
		}
	}
}

// 删除分隔符文本文件内容
bool CSpreadSheet::DeleteSheet()
{
	if (m_bExcel)
	{
		if (DeleteSheet(m_sSheetName))
		{
			return true;
		}
		else
		{
			m_sLastError = "删除表格时产生错误\n";
			return false;
		}
	}
	else
	{
		m_aRows.RemoveAll();
		m_aFieldNames.RemoveAll();
		m_dTotalColumns = 0;
		m_dTotalRows = 0;
		if (!m_bTransaction)
		{
			Commit();			
		}
		m_bAppend = false; // 设置新表格标志

		return true;		
	}
}

// 删除指定Excel表格内容,表格自身不被删除
bool CSpreadSheet::DeleteSheet(CString SheetName)
{
	if (m_bExcel)	// 当是Excel表格时
	{
		// 删除表格
		m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);
		SheetName = "[" + SheetName + "$A1:IV65536]";
		m_stempSql.Format ("DROP TABLE %s", SheetName);
		try
		{
			m_Database->ExecuteSQL(m_stempSql);
			m_Database->Close();
			m_aRows.RemoveAll();
			m_aFieldNames.RemoveAll();
			m_dTotalColumns = 0;
			m_dTotalRows = 0;
		}
		catch(CDBException *pEx)
		{
			m_sLastError = pEx->m_strError;
			m_Database->Close();
			pEx->Delete();

			return false;
		}
		return true;
	}
	else			// 当是分隔符文本文件时
	{
		return DeleteSheet();
	}
}

// 播放或替换一行到表格中,默认为添加一新行 
bool CSpreadSheet::AddRow(CStringArray &RowValues, long row, bool replace)
{
	long tempRow;
	
	if (row == 1)
	{
		if (m_bExcel) 
		{
			// 检查Excel表格首行列头字段是否重复
			for (int i = 0; i < RowValues.GetSize(); i++)
			{
				for (int j = 0; j < RowValues.GetSize(); j++)
				{
					if ((i != j) && (RowValues.GetAt(i) == RowValues.GetAt(j)))
					{
						m_sLastError.Format("首行列头字段重复:%s\n", RowValues.GetAt(i));
						return false;
					}
				}
			}
			
			// 检查首行列头数是否减小
			if (RowValues.GetSize() < m_dTotalColumns)
			{
				m_sLastError = "新列头数不能小于原列头数";
				return false;
			}
			m_dTotalColumns = RowValues.GetSize();
		}

		// 更新首行(列头)
		m_aFieldNames.RemoveAll();
		m_aFieldNames.Copy(RowValues);
	}
	else
	{
		if (m_bExcel)
		{
			if (m_dTotalColumns == 0)
			{
				m_sLastError = "没有列头,首先要加入列头\n";
				return false;
			}
		}
	}

	if (m_bExcel)	// Excel表格文件时
	{
		if (RowValues.GetSize() > m_aFieldNames.GetSize())
		{
			m_sLastError = "列数大于表格中总列数\n";
			return false;
		}
	}
	else			// 分隔符文本文件时
	{
		// 更新最大列数
		if (RowValues.GetSize() > m_dTotalColumns)
		{
			m_dTotalColumns = RowValues.GetSize();
		}
	}

	// 转换行值
	m_stempString.Empty();
	for (int i = 0; i < RowValues.GetSize(); i++)
	{
		if (i != RowValues.GetSize()-1) // 不是最后一列
		{
			m_stempSql.Format("\"%s\"%s", RowValues.GetAt(i), m_sSeparator);
			m_stempString += m_stempSql;
		}
		else							// 最后一列
		{
			m_stempSql.Format("\"%s\"", RowValues.GetAt(i));
			m_stempString += m_stempSql;
		}
	}
	
	if (row)
	{
		if (row <= m_dTotalRows)	// 不用添加新行
		{
			if (replace)			// 替换行
			{
				m_aRows.SetAt(row-1, m_stempString);
			}
			else					// 插入行
			{
				m_aRows.InsertAt(row-1, m_stempString);
				m_dTotalRows++;
			}

			if (!m_bTransaction)
			{
				Commit();
			}
			return true;
		}
		else						// 添加新行
		{
			// 插入空行直到指定行号
			m_dCurrentRow = m_dTotalRows;
			m_stempSql.Empty();
			CString nullString;
			for (int i = 1; i <= m_dTotalColumns; i++)
			{
				if (i != m_dTotalColumns)
				{
					if (m_bExcel)
					{
						nullString.Format("\" \"%s", m_sSeparator);
					}
					else
					{
						nullString.Format("\"\"%s", m_sSeparator);
					}
					m_stempSql += nullString;
				}
				else
				{
					if (m_bExcel)
					{
						m_stempSql += "\" \"";
					}
					else
					{
						m_stempSql += "\"\"";
					}
				}
			}
			for (int j = m_dTotalRows + 1; j < row; j++)
			{
				m_dCurrentRow++;
				m_aRows.Add(m_stempSql);
			}
		}
	}
	else
	{
		tempRow = m_dCurrentRow;
		m_dCurrentRow = m_dTotalRows;
	}

	// 插入一新行
	m_dCurrentRow++;
	m_aRows.Add(m_stempString);
	
	if (row > m_dTotalRows)
	{
		m_dTotalRows	= row;
	}
	else if (!row)
	{
		m_dTotalRows	= m_dCurrentRow;
		m_dCurrentRow	= tempRow;
	}
	if (!m_bTransaction)
	{
		Commit();
	}

	return true;
}

// 使用行号、字母列号替换或添加一单元格到Excel表格中,默认为添加单元格到一新行中,
// 如果你想使用字母列号作为列头名可将Auto置为false
bool CSpreadSheet::AddCell(CString CellValue, CString column, long row, bool Auto)
{
	short columnIndex = CalculateColumnNumber(column, Auto);
	if (0 == columnIndex)
	{
		return false;
	}

	if (AddCell(CellValue, columnIndex, row))
	{
		return true;
	}

	return false;
}

// 使用数字行号、列号替换或添加一个单元格到表格中,默认为添加单元格到一新行
bool CSpreadSheet::AddCell(CString CellValue, short column, long row)
{
	if (0 == column)
	{
		m_sLastError = "列数不能为0\n";
		return false;
	}

	long tempRow;

	if (m_bExcel)	// 当是Excel表格文件时
	{
		if (column > m_aFieldNames.GetSize() + 1)
		{
			m_sLastError = "指定列号大于表格中存在的总列数\n";
			return false;
		}
	}
	else			// 当是分隔符文本文件时
	{
		// 更新最大列数
		if (column > m_dTotalColumns)
		{
			m_dTotalColumns = column;
		}
	}

	if (row)
	{
		if (row <= m_dTotalRows)
		{
			ReadRow(m_atempArray, row);
	
			// 改变指定行
			m_atempArray.SetAtGrow(column-1, CellValue);

			if (row == 1)
			{
				if (m_bExcel) // 检查列头字段是否重复
				{										
					for (int i = 0; i < m_atempArray.GetSize(); i++)
					{
						for (int j = 0; j < m_atempArray.GetSize(); j++)
						{
							if ((i != j) && (m_atempArray.GetAt(i) == m_atempArray.GetAt(j)))
							{
								m_sLastError.Format("首行字段重复(列头):%s\n", m_atempArray.GetAt(i));
								return false;
							}
						}
					}
				}

				// 更新首行(列头)
				m_aFieldNames.RemoveAll();
				m_aFieldNames.Copy(m_atempArray);
			}	

			if (!AddRow(m_atempArray, row, true))
			{
				return false;
			}

			if (!m_bTransaction)
			{
				Commit();
			}
			return true;
		}
		else
		{
			// 插入空行直到指定行号
			m_dCurrentRow = m_dTotalRows;
			m_stempSql.Empty();
			CString nullString;
			for (int i = 1; i <= m_dTotalColumns; i++)
			{
				if (i != m_dTotalColumns)
				{
					if (m_bExcel)
					{
						nullString.Format("\" \"%s", m_sSeparator);
					}
					else
					{
						nullString.Format("\"\"%s", m_sSeparator);
					}
					m_stempSql		+= nullString;
				}
				else
				{
					if (m_bExcel)
					{
						m_stempSql	+= "\" \"";
					}
					else
					{
						m_stempSql	+= "\"\"";
					}
				}
			}
			for (int j = m_dTotalRows + 1; j < row; j++)
			{
				m_dCurrentRow++;
				m_aRows.Add(m_stempSql);
			}
		}
	}
	else
	{
		tempRow = m_dCurrentRow;
		m_dCurrentRow = m_dTotalRows;
	}

	// 插入单元格
	m_dCurrentRow++;
	m_stempString.Empty();
	for (int j = 1; j <= m_dTotalColumns; j++)
	{
		if (j != m_dTotalColumns) // 没有最后一列
		{
			if (j != column)
			{
				if (m_bExcel)
				{
					m_stempSql.Format("\" \"%s", m_sSeparator);
				}
				else
				{
					m_stempSql.Format("\"\"%s", m_sSeparator);
				}
				m_stempString += m_stempSql;
			}
			else
			{
				m_stempSql.Format("\"%s\"%s", CellValue, m_sSeparator);
				m_stempString += m_stempSql;
			}
		}
		else					// 最后一列
		{
			if (j != column)
			{
				if (m_bExcel)
				{
					m_stempString += "\" \"";
				}
				else
				{
					m_stempString += "\"\"";
				}
			}
			else
			{
				m_stempSql.Format("\"%s\"", CellValue);
				m_stempString += m_stempSql;
			}
		}
	}	

	m_aRows.Add(m_stempString);
	
	if (row > m_dTotalRows)
	{
		m_dTotalRows	= row;
	}
	else if (!row)
	{
		m_dTotalRows	= m_dCurrentRow;
		m_dCurrentRow	= tempRow;
	}
	if (!m_bTransaction)
	{
		Commit();
	}
	return true;
}

// 检索和替换Excel表格中行数据
bool CSpreadSheet::ReplaceRows(CStringArray &NewRowValues, CStringArray &OldRowValues)
{
	if (m_bExcel) // 当是Excel表格文件时
	{
		// 打开或创建Excel文件
		m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);
		m_stempSql.Format("UPDATE [%s] SET ", m_sSheetName);
		for (int i = 0; i < NewRowValues.GetSize(); i++)
		{
			m_stempString.Format("[%s]='%s', ", m_aFieldNames.GetAt(i), NewRowValues.GetAt(i));
			m_stempSql = m_stempSql + m_stempString;
		}
		m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
		m_stempSql = m_stempSql + " WHERE (";
		for (int j = 0; j < OldRowValues.GetSize()-1; j++)
		{
			m_stempString.Format("[%s]='%s' AND ", m_aFieldNames.GetAt(j), OldRowValues.GetAt(j));
			m_stempSql = m_stempSql + m_stempString;
		}
		m_stempSql.Delete(m_stempSql.GetLength()-4, 5);
		m_stempSql += ")";

		try
		{
			m_Database->ExecuteSQL(m_stempSql);
			m_Database->Close();
			Open();
			return true;
		}
		catch(CDBException *pEx)
		{
			m_sLastError = pEx->m_strError;
			m_Database->Close();
			pEx->Delete();
			return false;
		}
	}
	else		// 当是分隔符的文本文件时
	{
		m_sLastError = "这个涵数对分隔符文本文件无效\n";
		return false;
	}
}

// 读取表格中一行,默认为读取下一行
bool CSpreadSheet::ReadRow(CStringArray &RowValues, long row)
{
	// 检查指定行号是否大于表格中总行数
	if (row <= m_aRows.GetSize())
	{
		if (0 != row)
		{
			m_dCurrentRow = row;
		}
		else if (m_dCurrentRow > m_aRows.GetSize())
		{
			return false;
		}

		// 读取指定行
		RowValues.RemoveAll();
		m_stempString = m_aRows.GetAt(m_dCurrentRow-1);
		m_dCurrentRow++;

		// 检索分隔行的分隔符
		int separatorPosition;
		m_stempSql.Format("\"%s\"", m_sSeparator);
		separatorPosition = m_stempString.Find(m_stempSql); // 如果分隔符是字符"?"
		if (separatorPosition != -1)
		{
			// 保存列
			int nCount = 0;
			int stringStartingPosition = 0;
			while (separatorPosition != -1)
			{
				nCount = separatorPosition - stringStartingPosition;
				RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));
				stringStartingPosition = separatorPosition + m_stempSql.GetLength();
				separatorPosition = m_stempString.Find(m_stempSql, stringStartingPosition);
			}
			nCount = m_stempString.GetLength() - stringStartingPosition;
			RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));

			// 删除第一列引用符号
			m_stempString = RowValues.GetAt(0);
			m_stempString.Delete(0, 1);
			RowValues.SetAt(0, m_stempString);
			
			// 删除最后列引用符号
			m_stempString = RowValues.GetAt(RowValues.GetSize()-1);
			m_stempString.Delete(m_stempString.GetLength()-1, 1);
			RowValues.SetAt(RowValues.GetSize()-1, m_stempString);

			return true;
		}
		else
		{
			// 保存列
			separatorPosition = m_stempString.Find(m_sSeparator); // 当分隔符是字符"?"
			if (separatorPosition != -1)
			{
				int nCount = 0;
				int stringStartingPosition = 0;
				while (separatorPosition != -1)
				{
					nCount = separatorPosition - stringStartingPosition;
					RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));
					stringStartingPosition = separatorPosition + m_sSeparator.GetLength();
					separatorPosition = m_stempString.Find(m_sSeparator, stringStartingPosition);
				}
				nCount = m_stempString.GetLength() - stringStartingPosition;
				RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));
				return true;
			}
			else	// 表格只有一列时
			{
				// 如果存在在,删除开始和结束时的引用符号
				int quoteBegPos = m_stempString.Find('\"');
				int quoteEndPos = m_stempString.ReverseFind('\"');
				if ((quoteBegPos == 0) && (quoteEndPos == m_stempString.GetLength()-1))
				{
					m_stempString.Delete(0, 1);
					m_stempString.Delete(m_stempString.GetLength()-1, 1);
				}

				RowValues.Add(m_stempString);
			}
		}
	}

	m_sLastError = "指定行大于表格中总行数\n";

	return false;
}

// 使用字母列号从Excel表格中读取一列,如果想将字母列作为列号的话将Auto置为false
bool CSpreadSheet::ReadColumn(CStringArray &ColumnValues, CString column, bool Auto)
{
	short columnIndex = CalculateColumnNumber(column, Auto);
	if (0 == columnIndex)
	{
		return false;
	}

	if (ReadColumn(ColumnValues, columnIndex))
	{
		return true;
	}
	return false;
}

// 使用数字列号从表格中读取一列
bool CSpreadSheet::ReadColumn(CStringArray &ColumnValues, short column)
{
	if (0 == column)
	{
		m_sLastError = "列数不能为0\n";
		return false;
	}

	int tempRow = m_dCurrentRow;
	m_dCurrentRow = 1;
	ColumnValues.RemoveAll();
	for (int i = 1; i <= m_aRows.GetSize(); i++)
	{
		// 读取每一行
		if (ReadRow(m_atempArray, i))
		{
			// 在指定列中获取单元格内容
			if (column <= m_atempArray.GetSize())
			{
				ColumnValues.Add(m_atempArray.GetAt(column-1));
			}
			else
			{
				ColumnValues.Add("");
			}
		}
		else
		{
			m_dCurrentRow = tempRow;
			m_sLastError = "读取行时产生错误\n";
			return false;
		}
	}
	m_dCurrentRow = tempRow;
	return true;
}

// 从Excel表格中使用首行(列头)、字母列号读取单元格内容,默认为在下一行中读取下一个单元格内容
// 如果你想将字母列作为列头名的话可将Auto置为false 
bool CSpreadSheet::ReadCell (CString &CellValue, CString column, long row, bool Auto)
{
	short columnIndex = CalculateColumnNumber(column, Auto);
	if (0 == columnIndex)
	{
		return false;
	}

	if (ReadCell(CellValue, columnIndex, row))
	{
		return true;
	}
	return false;
}

// 在表格文件中使用行、列号读取单元格内容,默认(row无效)为下一行中读取下一个单元格
bool CSpreadSheet::ReadCell (CString &CellValue, short column, long row)
{
	if (0 == column)
	{
		m_sLastError		= "列不能为0\n";
		return false;
	}

	int tempRow				= m_dCurrentRow;
	if (row)
	{
		m_dCurrentRow		= row;
	}
	if (ReadRow(m_atempArray, m_dCurrentRow))
	{
		// 获取指定列中单元格数据
		if (column <= m_atempArray.GetSize())
		{
			CellValue		= m_atempArray.GetAt(column-1);
		}
		else
		{
			CellValue.Empty();
			m_dCurrentRow	= tempRow;
			return false;
		}
		m_dCurrentRow		= tempRow;
		return true;
	}
	m_dCurrentRow			= tempRow;
	m_sLastError			= "读取行时产生错误\n";

	return false;
}

// 事务开始
void CSpreadSheet::BeginTransaction()
{
	m_bTransaction = true;
}

// 提交改变的数据到表格或文本文件中,在此创建Excel中表
bool CSpreadSheet::Commit()
{
	if (m_bExcel) // 当是Excel表格文件时
	{
		// 打开或创建Excel文件
		m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);

		if (m_bAppend)
		{
			// 如果已经存在表格,则删除它
			m_stempString= "[" + m_sSheetName + "$A1:IV65536]";
			m_stempSql.Format ("DROP TABLE %s", m_stempString);
			try
			{
				m_Database->ExecuteSQL(m_stempSql);
			}
			catch(CDBException *pEx)
			{
				m_sLastError = pEx->m_strError;
				m_Database->Close();
				pEx->Delete();
				return false;
			}
			
			// 创建一个新的表格
			m_stempSql.Format("CREATE TABLE [%s$A1:IV65536] (", m_sSheetName);
			for (int j = 0; j < m_aFieldNames.GetSize(); j++)
			{
				m_stempSql = m_stempSql + "[" + m_aFieldNames.GetAt(j) +"]" + " char(255), ";
			}
			m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
			m_stempSql += ")";
		}
		else
		{
			// 创建一个新的表格
			m_stempSql.Format("CREATE TABLE [%s] (", m_sSheetName);
			for (int i = 0; i < m_aFieldNames.GetSize(); i++)
			{
				m_stempSql = m_stempSql + "[" + m_aFieldNames.GetAt(i) +"]" + " char(255), ";
			}
			m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
			m_stempSql += ")";
		}

		try
		{
			m_Database->ExecuteSQL(m_stempSql);
			if (!m_bAppend)
			{
				m_dTotalColumns = m_aFieldNames.GetSize();
				m_bAppend		= true;
			}
		}
		catch(CDBException *pEx)
		{
			m_sLastError		= pEx->m_strError;
			m_Database->Close();
			pEx->Delete();

			return false;
		}

		// 保存已改变的数据
		for (int k = 1; k < m_dTotalRows; k++)
		{
			ReadRow(m_atempArray, k+1);

			// 创建插入行SQL语句
			m_stempSql.Format("INSERT INTO [%s$A1:IV%d] (", m_sSheetName, k);
			for (int i = 0; i < m_atempArray.GetSize(); i++)
			{
				m_stempString.Format("[%s], ", m_aFieldNames.GetAt(i));
				m_stempSql = m_stempSql + m_stempString;
			}
			m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
			m_stempSql += ") VALUES (";
			for (int j = 0; j < m_atempArray.GetSize(); j++)
			{
				m_stempString.Format("'%s', ", m_atempArray.GetAt(j));
				m_stempSql = m_stempSql + m_stempString;
			}
			m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
			m_stempSql += ")";

			// 插入行
			try
			{
				m_Database->ExecuteSQL(m_stempSql);
			}
			catch(CDBException *pEx)
			{
				m_sLastError = pEx->m_strError;
				m_Database->Close();
				pEx->Delete();
				return false;
			}
		}
		m_Database->Close();
		m_bTransaction = false;
		return true;
	}
	else // 当文件是分隔符分隔的文本文件时
	{
		try
		{
			CFile *File = NULL;
			File = new CFile(m_sFile, CFile::modeCreate | CFile::modeWrite  | CFile::shareDenyNone);
			if (File != NULL)
			{
				CArchive *Archive = NULL;
				Archive = new CArchive(File, CArchive::store);
				if (Archive != NULL)
				{
					for (int i = 0; i < m_aRows.GetSize(); i++)
					{
						Archive->WriteString(m_aRows.GetAt(i));
						Archive->WriteString("\r\n");
					}
					delete Archive;
					delete File;
					m_bTransaction = false;
					return true;
				}
				delete File;
			}
		}
		catch(...)
		{
		}
		m_sLastError = "写文件时产生错误\n";
		return false;
	}
}

// 回滚文件改变为改变前状态
bool CSpreadSheet::RollBack()
{
	if (Open())
	{
		m_bTransaction = false;
		return true;
	}

	m_sLastError = "在回滚先前状态时产生错误\n";

	return false;
}

// 转换为指定分隔符的文本或表格文件
bool CSpreadSheet::Convert(CString SheetOrSeparator)
{
	// 文件名
	m_stempString = m_sFile;
	m_stempString.Delete(m_stempString.GetLength()-4, 4);
	if (m_bExcel) // 当文件是Excel文件时
	{
		m_stempString += ".csv";
		CSpreadSheet tempSheet(m_stempString, SheetOrSeparator, false);
		
		// 如果指定文本文件已存在,存不转换直接返回
		if (0 != tempSheet.GetTotalColumns())
		{
			return false;
		}

		tempSheet.BeginTransaction();

		for (int i = 1; i <= m_dTotalRows; i++)
		{
			if (!ReadRow(m_atempArray, i))
			{
				return false;
			}
			if (!tempSheet.AddRow(m_atempArray, i))
			{
				return false;
			}
		}
		if (!tempSheet.Commit())
		{
			return false;
		}
		return true;
	}
	else		// 当文件是分隔符分隔的文本文件时
	{
		m_stempString += ".xls";
		CSpreadSheet tempSheet(m_stempString, SheetOrSeparator, false);

		// 如果指定Excel文件已存在,则直接返回
		if (0 != tempSheet.GetTotalColumns())
		{
			return false;
		}

		GetFieldNames(m_atempArray);

		// 检查首行(列头)字段是否重复
		bool duplicate = false;
		for (int i = 0; i < m_atempArray.GetSize(); i++)
		{
			for (int j = 0; j < m_atempArray.GetSize(); j++)
			{
				if ((i != j) && (m_atempArray.GetAt(i) == m_atempArray.GetAt(j)))
				{
					m_sLastError.Format("首行(列头)字段重复:%s\n", m_atempArray.GetAt(i));
					duplicate = true;
				}
			}
		}

		if (duplicate) // 重复时创建哑元首行(列头)
		{
			m_atempArray.RemoveAll();
			for (int k = 1; k <= m_dTotalColumns; k++)
			{
				m_stempString.Format("%d", k);
				m_atempArray.Add(m_stempString);
			}

			if (!tempSheet.AddHeaders(m_atempArray))
			{
				return false;
			}

			for (int l = 1; l <= m_dTotalRows; l++)
			{
				if (!ReadRow(m_atempArray, l))
				{
					return false;
				}
				if (!tempSheet.AddRow(m_atempArray, l+1))
				{
					return false;
				}
			}
			return true;
		}
		else
		{
			if (!tempSheet.AddHeaders(m_atempArray))
			{
				return false;
			}

			for (int l = 2; l <= m_dTotalRows; l++)
			{
				if (!ReadRow(m_atempArray, l))
				{
					return false;
				}
				if (!tempSheet.AddRow(m_atempArray, l))
				{
					return false;
				}
			}
			return true;
		}
	}
}

// 为进行读写打开Excel或分隔符分隔文本文件
bool CSpreadSheet::Open()
{
	if (m_bExcel)	// 当文件是Excel电子表格文件时
	{
		// 打开或创建Excel文件
		m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);

		// 创建记录集并查询表
		m_rSheet = new CRecordset( m_Database );
		m_sSql.Format("SELECT * FROM [%s$A1:IV65536]", m_sSheetName);
		try
		{
			// 查询表
			m_rSheet->Open(CRecordset::forwardOnly, m_sSql, CRecordset::readOnly);
		}
		catch(...)
		{
			// 表不存在
			delete m_rSheet;
			m_rSheet = NULL;
			m_Database->Close();
			return false;
		}

		// 得到列数
		m_dTotalColumns = m_rSheet->m_nResultCols;

		if (m_dTotalColumns != 0)
		{
			m_aRows.RemoveAll();
			m_stempString.Empty();
			m_bAppend = true;
			m_dTotalRows++;					// 总行数
			
			// 获取首行(列头)字段名
			for (int i = 0; i < m_dTotalColumns; i++)
			{
				m_stempSql = m_rSheet->m_rgODBCFieldInfos[i].m_strName;
				m_aFieldNames.Add(m_stempSql);

				// 将所有列合并到一个字符串中
				if (i != m_dTotalColumns-1) // 不是最后一列
				{
					m_stempString = m_stempString + "\"" + m_stempSql + "\"" + m_sSeparator;
				}
				else						// 最后一列
				{	
					m_stempString = m_stempString + "\"" + m_stempSql + "\"";
				}				
			}
			
			// 存储内存中首行(列头)
			m_aRows.Add(m_stempString);

			// 读取并存储内存中其它行
			while (!m_rSheet->IsEOF())
			{
				m_dTotalRows++;							// 总行数

				try
				{
					// 获取一行中所有列
					m_stempString.Empty();
					for (short column = 0; column < m_dTotalColumns; column++)
					{
						m_rSheet->GetFieldValue(column, m_stempSql);

						// 将所有列合并到一个字符串中
						if (column != m_dTotalColumns-1) // 不是最后列时
						{
							m_stempString = m_stempString + "\"" + m_stempSql + "\"" + m_sSeparator;
						}
						else							// 最后一列时
						{	
							m_stempString = m_stempString + "\"" + m_stempSql + "\"";
						}
					}

					// 存储内存中已包含的行
					m_aRows.Add(m_stempString);
					m_rSheet->MoveNext();
				}
				catch (...)
				{
					m_sLastError = "读取行时产生错误\n";
					delete m_rSheet;
					m_rSheet = NULL;
					m_Database->Close();

					return false;
				}
			}		
		}
		
		m_rSheet->Close();
		delete m_rSheet;
		m_rSheet = NULL;
		m_Database->Close();
		m_dCurrentRow = 1;

		return true;
	}
	else			// 当文件是指定分隔符分隔的文本文件时
	{
		try
		{
			CFile *File = NULL;
			File = new CFile(m_sFile, CFile::modeRead | CFile::shareDenyNone);
			if (File != NULL)
			{
				CArchive *Archive = NULL;
				Archive = new CArchive(File, CArchive::load);
				if (Archive != NULL)
				{
					m_aRows.RemoveAll();
					// 读取并存储内存中所有行
					while(Archive->ReadString(m_stempString))
					{
						m_aRows.Add(m_stempString);
					}
					ReadRow(m_aFieldNames, 1); // 得到首行的字段名(列头)
					delete Archive;
					delete File;

					// 得到总行数
					m_dTotalRows = m_aRows.GetSize();

					// 获取最大总列数
					for (int i = 0; i < m_aRows.GetSize(); i++)
					{
						ReadRow(m_atempArray, i);
						if (m_atempArray.GetSize() > m_dTotalColumns)
						{
							m_dTotalColumns = m_atempArray.GetSize();
						}
					}

					if (m_dTotalColumns != 0)
					{
						m_bAppend = true;
					}
					return true;
				}
				delete File;
			}
		}
		catch(...)
		{
		}

		m_sLastError = "打开文件时产生错误\n";

		return false;
	}
}

// 转换Excle中字母列号为对应数字列号
short CSpreadSheet::CalculateColumnNumber(CString column, bool Auto)
{
	if (Auto)
	{	
		column.MakeUpper();

		int firstLetter, secondLetter;
		if (1 == column.GetLength())
		{
			firstLetter = column.GetAt(0);
			return (firstLetter - 65 + 1);									// ASCII码中大写字母A为65
		}
		else if (2 == column.GetLength())
		{
			firstLetter		= column.GetAt(0);
			secondLetter	= column.GetAt(1);
			return ((firstLetter - 65 + 1)*26 + (secondLetter - 65 + 1));	// ASCII码中大写字母A为65
		}
	}

	// 检查是否是有效的字段名,有效直接返回
	for (int i = 0; i < m_aFieldNames.GetSize(); i++)
	{
		if (!column.Compare(m_aFieldNames.GetAt(i)))
		{
			return (i + 1);
		}
	}

	m_sLastError = "无效字段名或字母列号\n";

	return 0;	
}

// 获取Excel-ODBC驱动程序名字
void CSpreadSheet::GetExcelDriver()
{
	char szBuf[2001];
	WORD cbBufMax = 2000;
	WORD cbBufOut;
	char *pszBuf = szBuf;

	// 获取已安装驱动程序的名字 (需要包含头文件"odbcinst.h")
	if(!SQLGetInstalledDrivers(szBuf,cbBufMax,& cbBufOut))
	{
		m_sExcelDriver = "";
	}
	
	// 寻找Excel驱动程序...
	do
	{
		if( NULL != strstr( pszBuf, "Excel" ) )
		{
			// 找到!
			m_sExcelDriver = CString( pszBuf );
			break;
		}
		pszBuf = strchr( pszBuf, '\0' ) + 1;
	}
	while( '\0' != pszBuf[1] );
}

#endif