/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 							  													*
 * Modification Log:				 											*
 * Hong 12/24/06 CONVERT_INFINTE_TO_MISSING_VALUE								*
 * Hong 12/24/06 QA80-8698 FIX_CHANNEL_GROUP_DATA_WITH_ID						*
 * Hong 04/05/07 v.8.0596e MOVE_TO_USER_PARAMETERS								*
 * Sim 04-18-2007 FIX_PROGRESS_CANCEL_ISSUE										*
 * Hong 07/09/07 v8.0655 IMPORT_RAW_DATA_FOR_MAY_FORMULA						*
 * Sim 09-08-2007 FIX_MORE_THAN_100_PERCENT_PROGRESS							*
 *	Hong 07/07/09 QA80-13884 ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
 *	Hong 0509/07/09 QA80-14278 MDF_SUPPORT_ASCET_FILE_WHICH_NO_OF_RECORD_IS_ONE	*
 *	Kenny 12/24/2009 QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST*
 *	Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE	*
 *	Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE			*
 *	Hong 07/07/09 QA80-13884-P2 FIX_MDF_IMPOR_BY_GROUP_FAIL_ADD_SPARKLINE_TO_ALL_SHEET
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
////////////////////////////////////////////////////////////////////////////////////
#include <..\originlab\import_utils.h>   // later need put file_utils.h together
///---Sim 09-26-2006 SUPPORT_SPARKLINES
#include <..\originlab\XFunctionEx.h> 
#include <..\originlab\fu_utils.h>
#include <oExtFile.h>
///---END SUPPORT_SPARKLINES
#include "MDFFile.h" 
#include <ocm.h> // Hong 12/24/06 CONVERT_INFINTE_TO_MISSING_VALUE
///---Sim 11-10-2006 MOVE_TO_VC_LEVEL
/*
static bool apply_mdf_formular1(vector& vdData, vector& vdPara)
{
	int nPSize = vdPara.GetSize();
	if(nPSize%2)
		return false;
	for(int ii = 0; ii< vdData.GetSize(); ii++)
	{
		if(vdData[ii] < vdPara[0])
			vdData[ii] = vdPara[1];
		else if(vdData[ii] >= vdPara[nPSize-2])
			vdData[ii] = vdPara[nPSize-1];
		else
		{
			for(int jj = 0; jj < nPSize - 3 ; jj+=2)
			{
				if(vdData[ii] >= vdPara[jj])
				{
					vdData[ii] = (vdPara[jj+3] - vdPara[jj+1])*(vdData[ii] - vdPara[jj])/(vdPara[jj+2]-vdPara[jj]) + vdPara[jj+1]; 
					break;
				}
			}
		}
	}
	return true;
}
static bool apply_mdf_formular2(vector& vdData, vector& vdPara)
{
	int nPSize = vdPara.GetSize();
	if(nPSize%2)
		return false;
	for(int ii = 0; ii< vdData.GetSize(); ii++)
	{
		if(vdData[ii] < vdPara[0])
			vdData[ii] = vdPara[1];
		else
		{
			for(int jj = 0; jj < nPSize - 3 ; jj+=2)
			{
				if(vdData[ii] >= vdPara[jj])
				{
					vdData[ii] = vdPara[jj];
					break;
				}
			}
		}
	}
	return true;
		
}
*/
///---END MOVE_TO_VC_LEVEL

/// Hong 9/25/06 ADD_TYPE_SUPPORT_BTYE_ARRA
#define	FSI_BYTEARRAY	11


static bool ConvertData(Dataset& dsTemp, vector<byte> vec, int iFormulaID)
{
	switch(iFormulaID)
	{
		case 132:
			int jj = 6, nDataNum = vec.GetSize()/7;
			for(int ii=0; ii < nDataNum; ii++)
			{
				string strTemp;
				strTemp.Format("%d:%d:%d:%d:%d:%d", vec[jj], vec[jj-1], vec[jj-2] & 0x0F, vec[jj-3] & 0x0F,
				vec[jj-4] & 0x1F, (vec[jj-5] >> 8)+ vec[jj-6]);
				dsTemp.SetText(ii, strTemp);
				jj += 7;
			}
			break;
		case 133:
			int jj = 5, nDataNum = vec.GetSize()/6;
			for(int ii=0; ii < nDataNum; ii++)
			{
				string strTemp;
				strTemp.Format("%d:%d", vec[jj], (vec[jj-1] >> 8)+ vec[jj-2], (vec[jj-3] >> 24) +
				(vec[jj-4] >> 16)+(vec[jj-5] >> 8)+ vec[jj-6]);
				dsTemp.SetText(ii, strTemp);
				jj += 6;
			}
			break; 
		default:
			out_str("Unfinished part, please contact with Justin or Andrew!");  // for other formular need file format
			return false;
	}
	return true;
}
/// END ADD_TYPE_SUPPORT_BTYE_ARRAY

#define LOAD_PARAMETER_GROUP(_CCFORMATFORMULA, _PFML, _NUMPARA) \
	int _nParaSize = sizeof(_CCFORMATFORMULA) * _NUMPARA; \
	_CCFORMATFORMULA *_PFML =  (_CCFORMATFORMULA*)malloc(_nParaSize); \
	Seek(ParaOffset, file::begin); \
	Read(_PFML, _nParaSize);

#define RELEASE_PARAMETER_GROUP(_PFML) \
	free(_PFML);
	
#define STORE_PARAMETERS_TO_TREE(_PFML, _TRMDFFORMULA, _NUMPARA) \
	string _strParaNo; \
	for ( int _j = 0; _j < _NUMPARA; _j++ ) \
	{ \
		_strParaNo.Format("T%d", _j+1); \
		TreeNode _trPara = _TRMDFFORMULA.Parameters.AddNode(_strParaNo); \
		_trPara = _PFML[_j]; \
	}
	
/// AW 07/10/06 SPEED_READ_MDF
///---Sim 09-25-2006 VARIABLE_PARAMETER
//BOOL MDFFile::ApplyFormular(Column& colCC, vector<double>& vdPara, int iFormulaID)
/// Hong 07/09/07 v8.0655 IMPORT_RAW_DATA_FOR_MAY_FORMULA
//BOOL MDFFile::ApplyFormular(Column& colCC, TreeNode& trCN)
BOOL MDFFile::ApplyFormular(Column& colCC, TreeNode& trCN, int& nC1, int& nC2)
/// end IMPORT_RAW_DATA_FOR_MAY_FORMULA
///---END VARIABLE_PARAMETER
{
	///---Sim 09-25-2006 VARIABLE_PARAMETER
	/*
	int nParaNum = vdPara.GetSize(); 
	if ( nParaNum <= 0 )
		return true;
	*/
	int ParaOffset = trCN.PCCBlock.nVal + sizeof(CCBlockStruc);
	int nNumBits = trCN.NumberBits.nVal;
	int nDataType = trCN.GetNode("DataType").nVal;
	TreeNode trCC = trCN.GetNode("CC");
	///---Sim 11-08-2006 HANDLE_CC_IS_INVALID_MEAN_NO_FORMULA
	if ( !trCC.IsValid() ) // no formula
		return false;
	///---END HANDLE_CC_IS_INVALID_MEAN_NO_FORMULA
	int iFormulaID = trCC.FormulaID.nVal; 
	int nNumPara = trCC.NumberValuePairs.nVal;
	///---END VARIABLE_PARAMETER
	string strColName = colCC.GetName();
	strColName = "Col(" + strColName + ")";
	string strFormular = "";
	///---Sim 10-10-2006 STORE_FORMULA_INFO
	Tree trMDFFormula;
	trMDFFormula.AddNode("FormulaID");
	trMDFFormula.FormulaID.nVal = iFormulaID;
	trMDFFormula.AddNode("Parameters");
	trMDFFormula.AddNode("FormulaExp");
	///---END STORE_FORMULAR_INFO
	bool bApplyFormula = false; ///---Sim 10-12-2006 MORE_FORMULA_SUPPORT
	switch( iFormulaID )
	{
		case 0: // parametric, linear
			///---Sim 09-25-2006 VARIABLE_PARAMETER
			CCFormatFormula0 f0;
			Seek(ParaOffset, file::begin);
			Read(&f0, sizeof(f0));
			///---Sim 10-10-2006 STORE_FORMULA_INFO
			//strFormular.Format("%f + %f * %s", vdPara[0], vdPara[1], strColName );
			//strFormular.Format("%f + %f * %s", f0.P1, f0.P2, strColName );
			strFormular.Format("P1 + P2 * %s", strColName );
			trMDFFormula.Parameters = f0;
			///---END STORE_FORMULA_INFO
			///---END VARIABLE_PARAMETER
			//colCC.SetInternalDataType(FSI_DOUBLE, OCD_RESTORE);
			break;
		///Justin 09/22/2006 QA70-8698 FUL_SUPPORT_MDF300
		case 1: // tabular with interpolation
		{
			///---Sim 09-25-2006 VARIABLE_PARAMETER
			LOAD_PARAMETER_GROUP(CCFormatFormula1, pf1, nNumPara);

			trMDFFormula.ParameterNumber.nVal = nNumPara;
			STORE_PARAMETERS_TO_TREE(pf1, trMDFFormula, nNumPara);
			
			RELEASE_PARAMETER_GROUP(pf1);
			///---END VARIABLE_PARAMETER
			break;
		}
		case 2: // tabular
			///---Sim 09-25-2006 VARIABLE_PARAMETER
			LOAD_PARAMETER_GROUP(CCFormatFormula2, pf2, nNumPara);

			trMDFFormula.ParameterNumber.nVal = nNumPara;
			STORE_PARAMETERS_TO_TREE(pf2, trMDFFormula, nNumPara);

			RELEASE_PARAMETER_GROUP(pf2);
			///---END VARIABLE_PARAMETER
			break;
		case 6: // polynomial function
			///---Sim 09-25-2006 VARIABLE_PARAMETER
			CCFormatFormula6 f6;
			Seek(ParaOffset, file::begin);
			Read(&f6, sizeof(f6));
			
			// unknow more detail formular information, need research
			/*
			int P6_max = 0;
			if ( 8 == nNumBits )
				P6_max = 256;
			else if ( 16 == nNumBits )
				P6_max = 65536;
			*/
			
			///---Sim 10-10-2006 STORE_FORMULA_INFO
			//strFormular.Format("(%f - %f*(%s - % f))/(%f*(%s-%f)-%f)", vdPara[1], vdPara[3], strColName, vdPara[4]- vdPara[5], vdPara[2], vdPara[4]-vdPara[5], vdPara[0]);
			//strFormular.Format("(%f - %f * (%s - % f))/(%f * (%s - %f) - %f)", f9.P2, f9.P4, strColName, f9.P5 - f9.P6, f9.P3, strColName, f9.P5 - f9.P6, f9.P1);
			strFormular.Format("(P2 - P4 * (%s - P5 - P6))/(P3 * (%s - P5 - P6) - P1)", strColName, strColName);
			trMDFFormula.Parameters = f6;
			///---END STORE_FORMULA_INFO
			//colCC.SetInternalDataType(FSI_DOUBLE, OCD_RESTORE);
			///---END VARIABLE_PARAMETER
			break;
		case 7: // exponential function
			///---Sim 09-25-2006 VARIABLE_PARAMETER
			CCFormatFormula7 f7;
			Seek(ParaOffset, file::begin);
			Read(&f7, sizeof(f7));
			///---Sim 10-10-2006 STORE_FORMULA_INFO
			/*
			if ( 0 == f6.P1 )
				strFormular.Format("ln((%f / (%s - %f) - %f) / %f) / %f", f6.P3, strColName, f6.P7, f6.P6, f6.P4, f6.P5);
			else
				strFormular.Format("ln(((%s - %f) * %f - %f) / %f) / %f", strColName, f6.P7, f6.P6, f6.P3, f6.P1, f6.P2);
			*/
			if ( 0 == f7.P1 )
				strFormular.Format("ln((P3 / (%s - P7) - P6) / P4) / P5", strColName);
			else
				strFormular.Format("ln(((%s - P7) * P6 - P3) / P1) / P2", strColName);
			trMDFFormula.Parameters = f7;
			///---END STORE_FORMULA_INFO
			//colCC.SetInternalDataType(FSI_DOUBLE, OCD_RESTORE);
			///---END VARIABLE_PARAMETER
			break;
		case 8: // logarithmic function
			///---Sim 09-25-2006 VARIABLE_PARAMETER
			CCFormatFormula8 f8;
			Seek(ParaOffset, file::begin);
			Read(&f8, sizeof(f8));
			///---Sim 10-10-2006 STORE_FORMULA_INFO
			/*
			if ( 0 == f8.P4 )
				strFormular.Format("exp(((%s - %f) * %f - %f) / %f) / %f", strColName, f8.P7, f8.P6, f8.P3, f8.P1, f8.P2);
			if ( 0 == f8.P1 )
				strFormular.Format("exp((%f / (%s - %f) - %f) / %f) / %f", f8.P3, strColName, f8.P7, f8.P6, f8.P4, f8.P5);
			*/
			if ( 0 == f8.P4 )
				strFormular.Format("exp(((%s - P7) * P6 - P3) / P1) / P2", strColName);
			if ( 0 == f8.P1 )
				strFormular.Format("exp((P3 / (%s - P7) - P6) / P4) / P5", strColName);
			trMDFFormula.Parameters = f8;
			///---END STORE_FORMULA_INFO
			//colCC.SetInternalDataType(FSI_DOUBLE, OCD_RESTORE);
			///---END VARIABLE_PARAMETER
			break;
		case 9: // ASAP2 Rational conversion formula
			///---Sim 09-25-2006 VARIABLE_PARAMETER
			CCFormatFormula9 f9;
			Seek(ParaOffset, file::begin);
			Read(&f9, sizeof(f9));
			///---Sim 10-10-2006 STORE_FORMULA_INFO
			//strFormular.Format("(%f * sqr(%s) + %f * %s + %f)/(%f * sqr(%s) + %f * %s + %f)", f7.P1, strColName, f7.P2, strColName, f7.P3, f7.P4, strColName, f7.P5, strColName, f7.P6);
			strFormular.Format("(P1 * sqr(%s) + P2 * %s + P3)/(P4 * sqr(%s) + P5 * %s + P6)", strColName, strColName, strColName, strColName);
			trMDFFormula.Parameters = f9;
			///---END STORE_FORMULA_INFO
			//colCC.SetInternalDataType(FSI_DOUBLE, OCD_RESTORE);
			///---END VARIABLE_PARAMETER
			break;
		case 10:
			break;
		case 11: // ASAM-MCD2 Text Table
		{
			///---Sim 10-12-2006 MORE_FORMULA_SUPPORT
			// load parameter group
			//CCFormatFormula11 *pf11 = new CCFormatFormula11[nNumPara];
			LOAD_PARAMETER_GROUP(CCFormatFormula11, pf11, nNumPara);

			// store parameters to tree info
			trMDFFormula.ParameterNumber.nVal = nNumPara;
			STORE_PARAMETERS_TO_TREE(pf11, trMDFFormula, nNumPara);

			// get column data
			vectorbase& vb = colCC.GetDataObject();
			
			// apply formula and convert data to text
			int nSize = vb.GetSize();
			int nTableLength = nNumPara;
			vector<string> vs;
			vs.SetSize(nSize);
			for ( int i = 0; i < nSize; i++ )
			{
				//vs[i].Format("%g", (double)vb[i]);
				vs[i] = "Unknow Value";
				for ( int j = 0; j < nTableLength; j++ )
					if ( pf11[j].interp == vb[i] )
					{
						vs[i] = pf11[j].strtext;
						break;
					}
			}
			
			// store data to column as text
			/*
			colCC.SetInternalDataType(FSI_TEXT, 0);
			int nCol = colCC.GetIndex();
			Worksheet wks;
			colCC.GetParent(wks);
			for ( int ii = 0; ii < nSize; ii++ )
				wks.SetCell(ii, nCol, vs[ii]);
			*/
			/// Hong 07/09/07 v8.0655 IMPORT_RAW_DATA_FOR_MAY_FORMULA
			if ( m_bImportRawData )
			{
				Worksheet wks;
				colCC.GetParent(wks);				
				if ( nC2 < nC1 )
				{
					string strColName;
					wks.InsertCol(++nC2, NULL, strColName);
				}
				Column colRawData(wks, nC1++);				
				colRawData.SetLongName(colCC.GetLongName() + "(Raw Data)");
				colRawData.SetInternalDataType(colCC.GetInternalDataType(), 0); // make sure is NOT FSI_TEXT type, otherwise runtime for GetDataObject
				vectorbase &vbRawData = colRawData.GetDataObject();
				vbRawData = vb;
			}
			/// end IMPORT_RAW_DATA_FOR_MAY_FORMULA
			colCC.SetFormat(OKCOLTYPE_TEXT);
			colCC.PutStringArray(vs);
			
			// release parameters buffer
			//delete[] pf11;
			RELEASE_PARAMETER_GROUP(pf11);
			
			bApplyFormula = true;
			///---END MORE_FORMULA_SUPPORT
			break;
		}
		case 12:
			break;
		case 132:
			break;
		case 133:
			break;
		case 65535:
			break;
		//end 
		default:
			out_str("Unfinished part, please contact with Justin or Andrew!");  // for other formular need file format
			return false;
	}
	
	///---Sim 10-10-2006 APPLY_FORMULA
	bool bOK = true;
	//bOK =  colCC.SetFormula(strFormular);
	if (colCC && MDF_FM_NONE != iFormulaID)
	{
		//colCC.SetFormula(strFormular);
		trMDFFormula.FormulaExp.strVal = strFormular;
		colCC.PutBinaryStorage(MDF_FORMULA_TAGNAME, trMDFFormula);
		
		/*
		if ( bOK )
			bOK = colCC.ExecuteFormula(-1,-1,false);
		*/
		
		if ( !bApplyFormula )
		{
			vectorbase& vb = colCC.GetDataObject();
			vector<double> vv;
			vv = vb;
			
			bOK = mdf_apply_formula(vv, vv.GetSize(), &trMDFFormula);
			
			//vb = vv;
			
			colCC.SetInternalDataType(FSI_DOUBLE, 0); // must convert to double type
			Dataset ds(colCC);
			/// Hong 12/24/06 CONVERT_INFINTE_TO_MISSING_VALUE
			ocm_check_infinite_value(vv, vv.GetSize());
			/// end CONVERT_INFINTE_TO_MISSING_VALUE
			ds = vv;
		}
	}
	ASSERT(bOK);
	return bOK;
	///---END APPLY_FORMULA
	
}
/// END SPEED_READ_MDF  

int MDFFile::ReadCNInf(int nPos, TreeNode&trParent, TreeNode& trCNRet)
{
	//string strTX; ///---Sim 10-20-2006 NO_NEED_TO_CREATE strTX is created inside READ_CN_BLOCK()
	//TreeNode trCN;
	// read CC information 
	READ_CN_BLOCK(cnBS, nPos, trParent, trCNRet)
	// set CN format and read CC information
	if ( trCNRet.IsValid() )
	{
		trCNRet.AddNumericNode(getDataTypeFromat(cnBS.NumberBits, cnBS.SignalType ), "DataType");
		int nCCPos = cnBS.PCCBlock;
		if ( nCCPos > 0 )
		{	
			READ_CC_BLOCK(ccBS, nCCPos, trCNRet, trCC) 
			//---Sim 10-13-2006 NOT_RIGHT_LAOD_PARAMETERS 
			/*
			int nNumberValuePairs = ccBS.NumberValuePairs > 16 ? 16 : ccBS.NumberValuePairs;
			if ( nNumberValuePairs > 0 )
			{
				ADD_CC_PARA(trCC, nNumberValuePairs)
			}
			*/
			//---END NOT_RIGHT_LAOD_PARAMETERS 
		}
	}
	return CER_NO_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
}

#define STRING_LEFT(_STR, _COUNT) _STR = _STR.Left(_COUNT); ///---Sim 10-24-2006 CHECK_STRING_OVER_LENGTH

/// AW 07/12/06 MOVE_MDF_TO_XF
//int MDFFile::ReadFile(LPCSTR lpcszFilePath)
int MDFFile::ReadHeader(LPCSTR lpcszFileName, TreeNode& trFileInfo)
/// END MOVE_MDF_TO_XF
{
	
	int nRet = CER_NO_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	string strTX;
	
/// AW 07/12/06 MOVE_MDF_TO_XF
//	if ( !Open(lpcszFilePath, file::modeRead|file::typeBinary|file::shareDenyNone) )
//		return ERR_OPEN_FILE;
/// END MOVE_MDF_TO_XF

	if ( !Open(lpcszFileName) ) 
		return IMPERR_FAILED_OPEN; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	// Read ID information
	
	READ_ID_BLOCK(idBS, trFileInfo, trId) 
	///---Sim 10-24-2006 CHECK_STRING_OVER_LENGTH
	STRING_LEFT(trId.BlockID.strVal, 8);
	STRING_LEFT(trId.FormatID.strVal, 8);
	STRING_LEFT(trId.ProgramID.strVal, 8);
	///---END CHECK_STRING_OVER_LENGTH
	
	string strFileID = idBS.BlockID;
	string strFormatID = idBS.FormatID;
	/// Hong 10/17/06 ADD_MORE_TYPE_SUPPORT
	/*
	if ( !strFileID.Match("MDF*") || !(strFormatID.Match("2.00*") || strFormatID.Match("3.00*")) )
	*/
	unsigned short nVersNumber = idBS.VersNumber;
	///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	//if ( !strFileID.Match("MDF*") || !(strFormatID.Match("2.00*") || strFormatID.Match("3.00*") || (nVersNumber >= 200 && nVersNumber <= 300)) )
		//return IMPERR_FILE_TYPE;
	if ( !strFileID.Match("MDF*") )
		return IMPERR_UNKNOW_TYPE;
	
	bool bValidVersion;
	bValidVersion = ( strFormatID.Match("2.00*") || strFormatID.Match("3.00*") || (nVersNumber >= 200 && nVersNumber <= 300) );
	if ( !bValidVersion )
		return IMPERR_UNSUPPORT_VERSION;
 	///---END HANDLE_ERROR_MESSAGE
 	/// END ADD_MORE_TYPE_SUPPORT
	 
	// read HD information
	READ_HD_BLOCK(hdBS, HD_BALOCK_START_POS, trFileInfo, trHD)
	///---Sim 10-24-2006 CHECK_STRING_OVER_LENGTH
	STRING_LEFT(trHD.BlockID.strVal, 2);
	STRING_LEFT(trHD.date.strVal, 10);
	STRING_LEFT(trHD.time.strVal, 8);
	STRING_LEFT(trHD.Author.strVal, 32);
	STRING_LEFT(trHD.department.strVal, 32);
	STRING_LEFT(trHD.ProjName.strVal, 32);
	STRING_LEFT(trHD.MeasObj.strVal, 32);
	///---END CHECK_STRING_OVER_LENGTH
	if (hdBS.PTXBlock !=0) 
	{ 
		READ_AND_ADD_TX_BLOCK(hdBS.PTXBlock, trHD, "TX") 
	} 
	if (hdBS.PProgBlock !=0) 
	{ 
		READ_AND_ADD_TX_BLOCK(hdBS.PProgBlock, trHD, "Prog")
	}
	
	// read DG information
	int nNextDGPos = hdBS.PDGBlock;
	int nNextCGPos, nNextCNPos, nCCPos, nNumberChannels;
	int nDG = 0, nCG = 0, nCN = 0;
	int nNumberDataGroup = hdBS.NumberDataGroups;
	TreeNode trDG0 = trFileInfo.AddNode("DG0");
	TreeNode trDG, trCG, trCN, trCN0;
	for ( int ii = 0; ii < nNumberDataGroup; ii++ )
	{
		if ( nNextDGPos <= 0 )  // || nCG > 399 ???
			break;
		READ_DG_BLOCK(dgBS, nNextDGPos)
		nNextDGPos = dgBS.PNextDGBlock;
		
		// read CG information
		nNextCGPos = dgBS.PNextChannel;
		READ_CG_BLOCK(cgBS, nNextCGPos)
		
		// check valid CG and DG
		///justin 7/10/2006 ONLY_EXCLUDE_NO_RECORD_DG
		//if ( strTX.Find(STR_SINGLE_SHORT_GROUP) < 0 && cgBS.NumberRecords > 2)  
		//if ( cgBS.NumberRecords > 0) 
		//{ 
			//ADD_BLOCK_IN_TREE2(dgBS, trDG0, trDG, "DG") 
			//ADD_BLOCK_IN_TREE2(cgBS, trDG, trCG, "CG") 
			//trCG.AddTextNode(strTX, STR_REMARK_TITLE); 
			//trCN0 = trCG.AddNode("CN0");
		//}
//
		//// get CN and CC
		//
		////if ( nRet = ReadCNInf(cgBS.PFirstChannel, trCN0, trCN, cgBS.NumberRecords) )
			////return nRet;
		////
		////nNextCNPos = trCN.PNextBlock.nVal;
		//nNextCNPos = cgBS.PFirstChannel;
		//nNumberChannels = cgBS.NumberChannels;
//
		//for (int jj = 0; jj < nNumberChannels; jj++ )
		//{
			//if ( nNextCNPos <= 0 )
				//break;
//
			//if ( nRet = ReadCNInf(nNextCNPos, trCN0, trCN) )
				//return nRet;
			//nNextCNPos = trCN.PNextBlock.nVal;
		//}
		if ( cgBS.NumberRecords > 0) 
		{ 
			ADD_BLOCK_IN_TREE2(dgBS, trDG0, trDG, "DG") 
			ADD_BLOCK_IN_TREE2(cgBS, trDG, trCG, "CG") 
			trCG.AddTextNode(strTX, STR_REMARK_TITLE); 
			trCN0 = trCG.AddNode("CN0");
		
			// get CN and CC
			nNextCNPos = cgBS.PFirstChannel;
			nNumberChannels = cgBS.NumberChannels;

			for (int jj = 0; jj < nNumberChannels; jj++ )
			{
				if ( nNextCNPos <= 0 )
					break;

				if ( nRet = ReadCNInf(nNextCNPos, trCN0, trCN) )
					return nRet;
				nNextCNPos = trCN.PNextBlock.nVal;
			}
		}
		///end ONLY_EXCLUDE_NO_RECORD_DG
	}

	return nRet;	
}


/// Hong 07/07/09 QA80-13884 ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
void MDFFile::SetDataGroup(bool bEnable)
{
	m_bEnableDataGroup = bEnable;
}
int  MDFFile::GetDataSelection(LPCSTR lpcszFileName, TreeNode& trFileNode)
{
	Tree		trStruct;
	int			nRet = ReadHeader(lpcszFileName, trStruct);
	if ( CER_NO_ERROR != nRet )
		return nRet;
	
	TreeNode 	trSelection;
	trSelection = trFileNode.AddNode("DataSelection", TRGP_BRANCH);
	trSelection.SetAttribute(STR_LABEL_ATTRIB, _L("Data Selection"));	
	trSelection.SetAttribute(STR_ATTRIB_BRANCH, GETNBRANCH_CHECK_CONTROL | GETNBRANCH_OPEN|GETNBRANCH_CHECK_CONTROL_ONE_EVENT);
	
	// Walk all data group on file struct
	TreeNode trDataGroup;
	string strDataGroupName;
	int nDataGroupIndex = 1;
	TreeNode trDG0 = trStruct.GetNode("DG0");
	if ( !(trDG0 && trDG0.IsValid()) )
		return false;
	
	int nCGIndex = 0; /// Hong 06/19/07 v8.0644 FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
	foreach ( TreeNode trDG in trDG0.Children )
	{
		// Only support one channel group on data group
		TreeNode 		trCG = trDG.GetNode("CG");
		if ( !trCG )
			continue ;
		TreeNode 		trCN0 = trCG.GetNode("CN0");
		if ( !trCN0 )
			continue ;
		
		if ( m_bEnableDataGroup )
		{
			strDataGroupName.Format("Data Group #%d", nDataGroupIndex++);
			trDataGroup = trSelection.AddNumericNode(1, "DataGroupName");
			trDataGroup.SetAttribute(STR_LABEL_ATTRIB, strDataGroupName);
		}
		else
			trDataGroup = trSelection;
		
		// Walk all channel on channel group
		TreeNode trChannel;
		string strChannelName;
		int nChannelIndex = 1;
		foreach ( TreeNode trCN in trCN0.Children )
		{
			strChannelName.Format("Channel #%d", nChannelIndex++);
			/// Hong 12/24/06 MORE_INFO
			if( !trCN.UniqueName.IsEmpty() )
				strChannelName = trCN.UniqueName.strVal;
			/// Hong 06/15/07 QA80-9251-P11 FIX_MISS_LABEL_IF_NO_UNIQUENAME
			else if ( !trCN.SignalName.IsEmpty() )
			{
				strChannelName = trCN.SignalName.strVal;
			}
			/// end FIX_MISS_LABEL_IF_NO_UNIQUENAME						
			/// end MORE_INFO
			/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
			//trChannel = trChannelGroup.AddNumericNode(1, "ChannelName", TRGP_CHECK);
			trChannel = trDataGroup.AddNumericNode(1, "ChannelName", TRGP_CHECK);
			/// end IMPORT_ALL_DATA_TO_ONE_SHEET
			trChannel.SetAttribute(STR_LABEL_ATTRIB, strChannelName);
			//trChannel.SetAttribute(STR_ATTRIB_DISPFMT, DISPLAY_EDITOR_CHECK_ON_LEFT); // Hong 03/13/07 AVOID_LABEL_TRUNCATED
			//trChannel.Use = 1;
			///---END ADD_CHECK_ALL_UNCHECK_ALL_OPTION
			/// Hong 01/18/07 HIDDEN_TIME_ON_SELECTION
			if( 1 == trCN.ChannelType.nVal ) // x-axis
				trChannel.Show = false;
			/// end HIDDEN_TIME_ON_SELECTION
			/// Hong 06/19/07 v8.0644 FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
			trChannel.SetAttribute(STR_CHANNEL_GROUP_INDEX, nCGIndex);
			/// end FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
		}
		nCGIndex++; /// Hong 06/19/07 v8.0644 FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
	}
	
	return CER_NO_ERROR;
}

static void _uncheck_x_col_no_assicated_y_imported(TreeNode& trNode, TreeNode& trXCol, int& nCGIndex, bool& bAllYUnchecked, int& nDataTotalNumber)
{
	int nCGIndexTemp;
	trNode.GetAttribute(STR_CHANNEL_GROUP_INDEX, nCGIndexTemp);
	if ( nCGIndexTemp != nCGIndex )
	{			
		if ( trXCol && bAllYUnchecked )		
			trXCol.nVal = 0;
		
		bAllYUnchecked = true;
		nCGIndex = nCGIndexTemp;
	}
	/// end FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
	if ( 0 == trNode.Show ) // we hidden X column variable in XF, need uncheck it if all related Y is unchecked
	{	
		/// Hong 06/19/07 v8.0644 FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
		//if ( trXCol && bAllYUnchecked )
		//	trXCol.nVal = 0;
		//bAllYUnchecked = true;
		/// end FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
		trXCol = trNode;
	}
	else if ( 1 == trNode.nVal )
	{
		nDataTotalNumber++;
		bAllYUnchecked = false;
	}
}
/// end ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT

#define NUM_VALID_SELECTION "NumberOfValidSelection"///---Sim 01-17-2007 FILTRATE_EMPTY_SELECTION_AND_SET_IT_BE_INVALID

/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
/*
	/// AW 07/12/06 MOVE_MDF_TO_XF
	//int MDFFile::GetResult()
	///---Sim 09-26-2006 SUPPORT_SPARKLINES
	//int MDFFile::ReadData(LPCSTR lpcszFileName, WorksheetPage& wkspg, TreeNode& trFileInfo)
	///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
	//int MDFFile::ReadData(LPCSTR lpcszFileName, WorksheetPage& wkspg, TreeNode& trFileInfo, bool bSparklines) // = FALSE
	int MDFFile::ReadData(LPCSTR lpcszFileName, WorksheetPage& wkspg, TreeNode& trFileInfo, TreeNode& trFileNode, bool bSparkLines) // = NULL, FALSE);
	///---END SUPPORT_DATA_SELECTION
	///---END SUPPORT_SPARKLINES
	/// END MOVE_MDF_TO_XF
	{
		int nRet = CER_NO_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
		
		/// temp testing, put data in wks here
		TreeNode trHD = trFileInfo.GetNode("HD");
		int nBlockSize = trHD.BlockSize.nVal;
		
		TreeNode trDG0 = trFileInfo.GetNode("DG0");
		int nIndex = 0;
		int nIndexLayer = wkspg.Layers().GetIndex(); ///---Sim 09-26-2006 SUPPORT_MULTI_FILE_IMPORT_MODE
		/// AW 07/10/06 SPEED_READ_MDF
	//	wkspg.Create("origin.otw");   /// AW 07/12/06 MOVE_MDF_TO_XF
	
		///---Sim 10-25-2006 COUNT_AVAILABLE_DATA_GROUP
		//int nLastLayerIndex = trDG0.GetNodeCount() - 1;
		int nLastLayerIndex = -1; // initial layer number is 0, index is number-1
		///---END COUNT_AVAILABLE_DATA_GROUP
	
		/// END SPEED_READ_MDF
		Worksheet wks;
		
		///---Sim 02-03-2007 RENAME_CENTRALIZED
*/		/*
		string strNameTemp;
		strNameTemp = trHD.ProjName.strVal;
		if ( strNameTemp.IsEmpty() )
		{
			strNameTemp = GetFileName(lpcszFileName);
		}
		wkspg.Rename(strNameTemp, false, true);
		wkspg.TitleShow = WIN_TITLE_SHOW_BOTH;
		*/
/*
		///---END RENAME_CENTRALIZED
	
		///---Sim 09-26-2006 SUPPORT_SPARKLINES
		XFunction xfSparkLine;
		TreeNode trXFSparkLine;
		
		if ( bSparkLines )
		{
			if(!xfSparkLine.Load(&trXFSparkLine, "sparklines", 0, true, true, true))
			{
				//XF_THROW(IMPERR_IMPORT_FUNC_ERR);// a better global err for not matching book would be better
				return CER_FAILED_LOAD_SPK_LINE_XF; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
			}
			xfSparkLine.SetArg("sel", 0);
		}
		///---END SUPPORT_SPARKLINES
		
		///---Sim 10-10-2006 SUPPORT_PROGRESS_SHOW
		m_pProgress = new progressBox(lpcszFileName, PBOX_TOPMOST);
		int nDataTotalNumber = 0;
	
		// count number of all date column that prepare to imported, this counting for show progress box
		{
			TreeNode trDGSetting;
			if ( trFileNode && trFileNode.IsValid() )
				trDGSetting = trFileNode.DataSelection.FirstNode;
			foreach (TreeNode trDG in trDG0.Children )
			{
				///---Sim 01-17-2007 FILTRATE_EMPTY_SELECTION_AND_SET_IT_BE_INVALID
				int nNumXChannels = 0;
				int nNumYChannels = 0;
				///---END FILTRATE_EMPTY_SELECTION_AND_SET_IT_BE_INVALID
				//if ( !(trDGSetting && trDGSetting.IsValid()) || 1 == trDGSetting.Use ) ///---Sim 01-17-2007 ADD_CHECK_ALL_UNCHECK_ALL_OPTION
				{
					TreeNode trCG = trDG.GetNode("CG");
					TreeNode trCN0 = trCG.GetNode("CN0");
					
					TreeNode trCNSetting, trCGSetting;
					if ( trDGSetting && trDGSetting.IsValid() )
					{
						trCGSetting = trDGSetting.FirstNode; 
						// only one channel group
						if ( trCGSetting && trCGSetting.IsValid() )
							trCNSetting = trCGSetting.FirstNode; 
					}
					//if ( !(trCGSetting && trCGSetting.IsValid()) || 1 == trCGSetting.Use ) ///---Sim 01-17-2007 ADD_CHECK_ALL_UNCHECK_ALL_OPTION
						foreach (TreeNode trCN in trCN0.Children )
						{
							if ( !(trCNSetting && trCNSetting.IsValid()) || 1 == trCNSetting.nVal )
							{
								///---Sim 01-17-2007 FILTRATE_EMPTY_SELECTION_AND_SET_IT_BE_INVALID
								//nDataTotalNumber++;
								if ( 1 == trCN.ChannelType.nVal ) // x-axis
								 	nNumXChannels++;
								else
									nNumYChannels++;
								///---END FILTRATE_EMPTY_SELECTION_AND_SET_IT_BE_INVALID
							}
							trCNSetting = trCNSetting.NextNode;
						}
	
					//nLastLayerIndex++; ///---Sim 10-25-2006 COUNT_AVAILABLE_DATA_GROUP	///---Sim 01-17-2007 FILTRATE_EMPTY_SELECTION_AND_SET_IT_BE_INVALID remove
				}
				///---Sim 01-17-2007 FILTRATE_EMPTY_SELECTION_AND_SET_IT_BE_INVALID
				if ( nNumYChannels > 0 ) // x-axis is not a data, not in data selection
				{
					nLastLayerIndex++;
					nDataTotalNumber += nNumXChannels + nNumYChannels;
				}
				
				if ( trDGSetting && trDGSetting.IsValid() )
					trDGSetting.SetAttribute(NUM_VALID_SELECTION, nNumYChannels);
				///---END FILTRATE_EMPTY_SELECTION_AND_SET_IT_BE_INVALID
				
				trDGSetting = trDGSetting.NextNode;
			}	
		}
		
		m_pProgress->SetRange(0, nDataTotalNumber);
		m_nDataCount = 0;
		m_bUserCancel = false;
		///---END SUPPORT_PROGRESS_SHOW
		
		///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
		TreeNode trDGSetting;
		if ( trFileNode && trFileNode.IsValid() )
			trDGSetting = trFileNode.DataSelection.FirstNode;
		///---END SUPPORT_DATA_SELECTION
	
		int nIndexDG = 0; ///---Sim 02-12-2007 ADD_RANGE_INFO
		foreach (TreeNode trDG in trDG0.Children )
		{
			///---Sim 10-10-2006 SUPPORT_USER_CANCEL_PROGRESS
			if ( m_bUserCancel )
				break;
			///---END SUPPORT_USER_CANCEL_PROGRESS
			
			///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
			// import data when tree setting check value is true, or tree node is node
			
			///---Sim 01-17-2007 ADD_CHECK_ALL_UNCHECK_ALL_OPTION
			int nNumSels = 0;
			if ( trDGSetting && trDGSetting.IsValid() )
				trDGSetting.GetAttribute(NUM_VALID_SELECTION, nNumSels);
			//if ( !(trDGSetting && trDGSetting.IsValid()) || 1 == trDGSetting.Use )
			if ( !(trDGSetting && trDGSetting.IsValid()) || nNumSels > 0 )
			///---END ADD_CHECK_ALL_UNCHECK_ALL_OPTION
			{
			///---END SUPPORT_DATA_SELECTION
				/// AW 07/10/06 SPEED_READ_MDF
				// Load_DG_Data(wks, trDG, -1);
				// nIndex++;
				///---Sim 09-26-2006 SUPPORT_MULTI_FILE_IMPORT_MODE
				//wks = wkspg.Layers(nIndex);
				wks = wkspg.Layers(nIndexLayer);
				///---Sim 09-29-2006 FIX_FIX_EXCESSIVE_EMPTY_SHEET
*/				/*
				if ( !is_sheet_empty(wks) )
				{
					nIndexLayer = wkspg.AddLayer();
					wks = wkspg.Layers(nIndexLayer);
				}
				*/
/*				
				///---END FIX_FIX_EXCESSIVE_EMPTY_SHEET
				///---END SUPPORT_MULTI_FILE_IMPORT_MODE
				///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
				//ReadDGData(wks, trDG, -1);
				///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
				//ReadDGData(wks, trDG, -1, trDGSetting);
				if (nRet = ReadDGData(wks, lpcszFileName, trDG, -1, trDGSetting) )
					break; // need delete m_pProgress
				///---END HANDLE_ERROR_MESSAGE
				///---END SUPPORT_DATA_SELECTION
				///---Sim 09-26-2006 SUPPORT_SPARKLINES
				//int nLine4 = -1;
				if( bSparkLines )
				{
					xfSparkLine.SetArg("wks", wks);
					if ( !xfSparkLine.Evaluate() )
					{
						//XF_THROW(XFERR_INVALID_MATOBJ);
						return CER_SPK_LINE_RUN_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
					}
					//nLine4 = RCLT_SPARKLINE;
				}
				//wks_set_show_labels(ws, RCLT_LONG_NAME, RCLT_UNIT, RCLT_COMMENT, nLine4);
				///---END SUPPORT_SPARKLINES
			
				///---Sim 02-12-2007 ADD_RANGE_INFO
				nIndexDG++; 
				m_orng.Add(wks, 0, "DG" + nIndexDG, wks.GetNumCols() - 1);
				///---END ADD_RANGE_INFO
				
				if ( nIndex < nLastLayerIndex )
				///---Sim 09-26-2006 SUPPORT_MULTI_FILE_IMPORT_MODE
				{
					//nIndex = wkspg.AddLayer();
					nIndex++;
					nIndexLayer++;
					if ( wkspg.Layers.Count() < nIndexLayer + 1 )
						nIndexLayer = wkspg.AddLayer();
				}
				///---END SUPPORT_MULTI_FILE_IMPORT_MODE
				/// END SPEED_READ_MDF
			///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
			}
			trDGSetting = trDGSetting.NextNode;
			//nIndex++;
			///---END SUPPORT_DATA_SELECTION
		}
		
		///---Sim 10-10-2006 SUPPORT_PROGRESS_SHOW
		delete m_pProgress;
		///---END SUPPORT_DATA_SELECTION
		
		return nRet; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	}
*/
int MDFFile::ReadData(LPCSTR lpcszFileName, Worksheet& wks, TreeNode& trFileInfo, TreeNode& trFileNode, int nC1, int nC2)
{
	int nRet = CER_NO_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
		
	TreeNode trDG0 = trFileInfo.GetNode("DG0");	
	
	int nDataTotalNumber = 0;
	
	TreeNode trXCol;
	bool bAllYUnchecked = true;
	int nCGIndex = -1; 	/// Hong 06/19/07 v8.0644 FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN 
	foreach (TreeNode trNode in trFileNode.DataSelection.Children)
	{
		/// Hong 07/07/09 QA80-13884 ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
		/*
	/// Hong 06/13/07 v8.0640c UNCHECK_X_COLUMN_IF_ALL_Y_UNCHECK_IN_CHANNELS
	//	if ( 1 == trNode.nVal && 0 != trNode.Show )
	//		nDataTotalNumber++;		
		/// Hong 06/19/07 v8.0644 FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
		int nCGIndexTemp;
		trNode.GetAttribute(STR_CHANNEL_GROUP_INDEX, nCGIndexTemp);
		if ( nCGIndexTemp != nCGIndex )
		{			
			if ( trXCol && bAllYUnchecked )		
				trXCol.nVal = 0;
			
			bAllYUnchecked = true;
			nCGIndex = nCGIndexTemp;
		}
		/// end FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
		if ( 0 == trNode.Show ) // we hidden X column variable in XF, need uncheck it if all related Y is unchecked
		{	
			/// Hong 06/19/07 v8.0644 FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
			//if ( trXCol && bAllYUnchecked )
			//	trXCol.nVal = 0;
			//bAllYUnchecked = true;
			/// end FIX_FAIL_CORRECT_UNCHECK_ACCORDING_X_COLUMN
			trXCol = trNode;
		}
		else if ( 1 == trNode.nVal )
		{
			nDataTotalNumber++;
			bAllYUnchecked = false;
		}
		*/
		if ( !m_bEnableDataGroup )
			_uncheck_x_col_no_assicated_y_imported(trNode, trXCol, nCGIndex, bAllYUnchecked, nDataTotalNumber);
		else
		{
			foreach ( TreeNode trDG in trNode.Children )
				_uncheck_x_col_no_assicated_y_imported(trDG, trXCol, nCGIndex, bAllYUnchecked, nDataTotalNumber);
		}
		/// end ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
	}
	
	if ( trXCol && bAllYUnchecked ) // uncheck last X column if no Y selected
		trXCol.nVal = 0;

	if ( 0 == nDataTotalNumber )
		return XFERR_NO_DATA_SELECT;
	/// end UNCHECK_X_COLUMN_IF_ALL_Y_UNCHECK_IN_CHANNELS
	/// Kenny 12/24/2009 QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST
	//m_pProgress = new progressBox(lpcszFileName, PBOX_TOPMOST);
	m_pProgress = new progressBox(lpcszFileName, PBOX_DEFAULT_STYLE);
	/// End QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST
	
	m_pProgress->SetRange(0, nDataTotalNumber);
	m_nDataCount = 0;
	m_bUserCancel = false;
	
	/// Hong 07/07/09 QA80-13884 ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
	WorksheetPage		wp;
	wks.GetParent(wp);
	TreeNode			trDataGroup;
	trDataGroup = trFileNode.DataSelection.FirstNode;
	int					nIndex = wks.GetIndex();
	/// end ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
	int nStartCol = nC1, nEndCol = nC2;
	TreeNode trChannel = trFileNode.DataSelection.FirstNode;
	foreach (TreeNode trDG in trDG0.Children )
	{
		/// Hong 07/07/09 QA80-13884 ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
		if ( m_bEnableDataGroup )
		{
			trChannel = trDataGroup.FirstNode;
			if ( 0 == trChannel.nVal ) // no column group selected
			{
				trDataGroup = trDataGroup.NextNode;
				continue;
			}
			
			wks = wp.Layers(nIndex++);
			if ( !wks )
			{
				nIndex = wp.AddLayer();
				wks = wp.Layers(nIndex++);
			}
			wks.SetSize(-1, 0);
			nStartCol = 0;
			nEndCol = -1;
			/// Hong 07/07/09 QA80-13884-P2 FIX_MDF_IMPOR_BY_GROUP_FAIL_ADD_SPARKLINE_TO_ALL_SHEET
			m_orng.Add(wks, nStartCol, STR_RANGE_STR, nEndCol);
			/// end FIX_MDF_IMPOR_BY_GROUP_FAIL_ADD_SPARKLINE_TO_ALL_SHEET
			
			TreeNode 	trCG = trDG.GetNode("CG");
			TreeNode 	trCGRemark = trCG.GetNode("Remark");
			if ( trCGRemark.IsValid() && !trCGRemark.strVal.IsEmpty() )
				wks.SetName(trCGRemark.strVal, OCD_ENUM_NEXT);
		}
		/// end ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
		nRet = ReadDGData(wks, lpcszFileName, trDG, trChannel, nStartCol, nEndCol);
		/// Hong 07/07/09 QA80-13884 ADD_OPTION_TO_SUPPORT_WHETHER_IMPORT_WITH_DATA_GROUP_OR_NOT
		if ( m_bEnableDataGroup )
			trDataGroup = trDataGroup.NextNode;
	}
	if ( !m_bEnableDataGroup ) /// Hong 07/07/09 QA80-13884-P2 FIX_MDF_IMPOR_BY_GROUP_FAIL_ADD_SPARKLINE_TO_ALL_SHEET
		m_orng.Add(wks, nC1, STR_RANGE_STR, nEndCol);
	
	delete m_pProgress;
	
	return nRet;
}
/// end IMPORT_ALL_DATA_TO_ONE_SHEET

///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
//int MDFFile::Import(LPCSTR lpcszFileName, WorksheetPage& wkspg, TreeNode& trFileInfo, bool bSparklines) // = FALSE
/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
//int MDFFile::Import(LPCSTR lpcszFileName, WorksheetPage& wkspg, TreeNode& trFileInfo, TreeNode& trFileNode, bool bSparkLines) // = NULL, FALSE
/// Hong 07/09/07 v8.0655 IMPORT_RAW_DATA_FOR_MAY_FORMULA
//int MDFFile::Import(LPCSTR lpcszFileName, Worksheet& wks, TreeNode& trFileInfo, TreeNode& trFileNode, int nC1, int nC2) // = NULL, = 0, = -1
int MDFFile::Import(LPCSTR lpcszFileName, Worksheet& wks, TreeNode& trFileInfo, TreeNode& trFileNode, int nC1, int nC2, bool bImportRawData) // = NULL, = 0, = -1, = false
/// end IMPORT_RAW_DATA_FOR_MAY_FORMULA
/// end IMPORT_ALL_DATA_TO_ONE_SHEET
///---END SUPPORT_DATA_SELECTION
{
	///---Sim 02-12-2007 ADD_RANGE_INFO
	if ( m_orng )
		m_orng.Reset();
	///---END ADD_RANGE_INFO
	
	m_bImportRawData = bImportRawData; /// Hong 07/09/07 v8.0655 IMPORT_RAW_DATA_FOR_MAY_FORMULA
	///justin 09/22/2006 QA70-8698 FULL_SUPPORT_MDF300
	//int nRet = 0;
	//if ( nRet = ReadHeader(lpcszFileName, trFileInfo) )
		//return nRet;
	//return ReadData( lpcszFileName, wkspg, trFileInfo );
	int nRet = CER_NO_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	Tree trStruct; ;
	if ( nRet = ReadHeader(lpcszFileName, trStruct) )
		return nRet;
	
	///---Sim 10-10-2006 GET_SHOWING_FILE_INFO
	//ConvertFileInfo(trFileInfo, trStruct); //---Sim 10-10-2006 GET_FILE_HEADER_INFO
	TreeNode trUsefulInfo = trFileInfo.AddNode("HeaderInfo");
	GetUsefulFileInfo(trUsefulInfo, trStruct, trFileNode);
	///---END GET_SHOWING_FILE_INFO

	///---Sim 09-26-2006 SUPPORT_SPARKLINES
	//return ReadData( lpcszFileName, wkspg, trStruct );
	///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
	//return ReadData( lpcszFileName, wkspg, trStruct, bSparklines );
	/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
	//return ReadData( lpcszFileName, wkspg, trStruct, trFileNode, bSparkLines );
	if ( -1 == nC2 || nC2 < nC1 )
		nC2 = wks.GetNumCols() - 1;
		
	return ReadData( lpcszFileName, wks, trStruct, trFileNode, nC1, nC2);
	/// end IMPORT_ALL_DATA_TO_ONE_SHEET
	///---END SUPPORT_DATA_SELECTION
	///---END SUPPORT_SPARKLINES
	//end 
}

///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
//int MDFFile::ReadDGData(Worksheet &wks, TreeNode& trDG, int iFirstCol )
/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
//int MDFFile::ReadDGData(Worksheet &wks, LPCSTR lpcszFileName, TreeNode& trDG, int iFirstCol, TreeNode& trDGSetting ) // = NULL
int MDFFile::ReadDGData(Worksheet &wks, LPCSTR lpcszFileName, TreeNode& trDG, TreeNode& trChannel, int& nC1, int& nC2) // = NULL
/// end IMPORT_ALL_DATA_TO_ONE_SHEET
///---END SUPPORT_DATA_SELECTION
{
	int nRet = CER_NO_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	if( !wks.IsValid())
		return CER_INVALID_WKS; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	
	TreeNode trCG = trDG.GetNode("CG");
	/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
	/*
	/// AW 07/10/06 SPEED_READ_MDF
	//while(wks.DeleteCol(0)){} 
	TreeNode trCGRemark = trCG.GetNode("Remark");
	if ( trCGRemark.IsValid() )
		//wks.SetName(trCGRemark.strVal);
		wks.SetName(trCGRemark.strVal, OCD_ENUM_NEXT); // Hong 12/21/06 FIX_SHORT_NAME_NOT_UNIQUE
	/// END SPEED_READ_MDF
	*/
	/// end IMPORT_ALL_DATA_TO_ONE_SHEET
	TreeNode trCN0 = trCG.GetNode("CN0");
	int nRecordsPos = trDG.PDataRecords.nVal;
	int nNumRecords = trCG.NumberRecords.nVal;
	int nRecordSize = trCG.RecordSize.nVal;

	if( nNumRecords < 1 || nRecordsPos == 0) 
		return IMPERR_MDF_NOT_CHANNEL_DATA_IN_DATA_GROUP; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	
	int nDGDataSize = nRecordSize * nNumRecords;
	byte* pBuffer =(byte*)malloc(nDGDataSize);
	if( !pBuffer ) 
		return CER_MEMORY_ALLOCATE_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
	
	Seek(nRecordsPos, file::begin);
	Read(pBuffer, nDGDataSize);
	
	//Dataset dsColTemp; 
	//vector<double> vdDataTemp;
	//int iIndexCol = iFirstCol; /// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
	string strNameTemp;

	/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
	/*
	///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
	TreeNode trCNSetting, trCGSetting;
	if ( trDGSetting && trDGSetting.IsValid() )
	{
		trCGSetting = trDGSetting.FirstNode; 
		// only one channel group
		if ( trCGSetting && trCGSetting.IsValid() )
		{
			trCNSetting = trCGSetting.FirstNode; 
		}
	}
	///---END SUPPORT_DATA_SELECTION
	*/
	/// end IMPORT_ALL_DATA_TO_ONE_SHEET
	
	///---Sim 09-29-2006 ONLY_SUPPORT_ONE_CHANNEL_GROUP
	//if ( !(trCGSetting && trCGSetting.IsValid()) || 1 == trCGSetting.Use ) ///---Sim 01-17-2007 ADD_CHECK_ALL_UNCHECK_ALL_OPTION
	{
	///---END ONLY_SUPPORT_ONE_CHANNEL_GROUP
		///---Sim 10-12-2006 CREATE_ALL_APPLICABLE_DATA_COLUMN
		int nNumCols = 0;
		
		// count applicable data for create column
		/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
		/*
		TreeNode trCountCNSetting;
		if ( trCGSetting && trCGSetting.IsValid() )
			trCountCNSetting = trCGSetting.FirstNode; 
		foreach (TreeNode trCountCN in trCN0.Children )
		{
			if ( !(trCountCNSetting && trCountCNSetting.IsValid()) || 1 == trCountCNSetting.nVal )
				nNumCols++;
			trCountCNSetting = trCountCNSetting.NextNode;
		}
		//wks.SetSize(nNumRecords, nNumCols);
		if ( wks.GetNumCols() < nNumCols ) // not delete any original columns
			wks.SetSize(-1, nNumCols);		
		
		int nCurrentCol = 0;
		*/			
		/// end IMPORT_ALL_DATA_TO_ONE_SHEET
		///---END CREATE_ALL_APPLICABLE_DATA_COLUMN
		
		foreach (TreeNode trCN in trCN0.Children )
		{
			///---Sim 10-10-2006 SUPPORT_USER_CANCEL_PROGRESS
			if ( m_bUserCancel )
				break;
			///---END SUPPORT_USER_CANCEL_PROGRESS
			
			///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
			// import data when tree setting check value is true, or tree node is node
			/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
			//if ( !(trCNSetting && trCNSetting.IsValid()) || 1 == trCNSetting.nVal )
			if ( !(trChannel && trChannel.IsValid()) || 1 == trChannel.nVal )
			/// end IMPORT_ALL_DATA_TO_ONE_SHEET
			{			
			///---END SUPPORT_DATA_SELECTION
				///---Sim 10-12-2006 ALREADY_CREATE_COLUMN
				//Column colCC( wks, wks.AddCol() );
				/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
				//Column colCC( wks, nCurrentCol++ );
				if ( nC2 < nC1 )
				{
					string strColName;
					wks.InsertCol(++nC2, NULL, strColName);
				}
				
				Column colCC( wks, nC1++ );
				/// end IMPORT_ALL_DATA_TO_ONE_SHEET				
				///---END ALREADY_CREATE_COLUMN
				/// Hong 10/11/06 CHANGE_INFO_SETTING
				/*
				//colCC.SetLabel(trCN.SignalName.strVal);
				colCC.SetName(trCN.SignalName.strVal);   /// AW 07/10/06 SPEED_READ_MDF
				///---Sim 10-11-2006 FIX_SET_LONG_NAME
				//colCC.SetLabel(trCN.SignalDescr.strVal); /// AW 07/10/06 SPEED_READ_MDF
				colCC.SetLongName(trCN.SignalDescr.strVal);
				///---END FIX_SET_LONG_NAME
				*/
				///---Sim 10-20-2006 USE_UNIQUE_NAME_WITH_LONG_SIZE
				if ( !trCN.UniqueName.IsEmpty() )
					colCC.SetLongName(trCN.UniqueName.strVal);
				else
					colCC.SetLongName(trCN.SignalName.strVal);
				///---END USE_UNIQUE_NAME_WITH_LONG_SIZE
				/// Hong 04/05/07 v.8.0596e MOVE_TO_USER_PARAMETERS
				//colCC.SetParameter(trCN.SignalDescr.strVal, 0);
				/// end MOVE_TO_USER_PARAMETERS
				/// END CHANGE_INFO_SETTING
				
				strNameTemp = trCN.TX.strVal;
				if ( !strNameTemp.IsEmpty() )
					colCC.SetComments(strNameTemp);	
					
				//nRet++; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE remove for no need
				/// Hong 12/24/06 QA80-8698 FIX_CHANNEL_GROUP_DATA_WITH_ID
				//-- now only support one channel group on data group, later should add code to support multi
				//byte* pbCN = pBuffer + trCN.NumberFirstBit.nVal / 8;
				//int nBitOffset = mod(trCN.NumberFirstBit.nVal,8);
				int nOffset = trDG.NumberRecordID.nVal;
				/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
				//if( nOffset > 0 && trDGSetting.GetNodeCount() > 1 ) /// Hong 12/25/06 ADD_ERROR_MESSAGE_FOR_MULTI_CHANNEL_GROUP
				/// Hong 0509/07/09 QA80-14278 MDF_SUPPORT_ASCET_FILE_WHICH_NO_OF_RECORD_IS_ONE
				//if( nOffset > 0 && trDG.GetNodeCount() > 1 )
				if( nOffset > 1 && trDG.GetNodeCount() > 1 )
				/// end MDF_SUPPORT_ASCET_FILE_WHICH_NO_OF_RECORD_IS_ONE
				/// end IMPORT_ALL_DATA_TO_ONE_SHEET
					return IMPERR_UNSUPPORT_VERSION;// should change to a better one
				byte* pbCN = pBuffer + trCN.NumberFirstBit.nVal / 8 + nOffset;
				int nBitOffset = mod(trCN.NumberFirstBit.nVal + nOffset,8);
				/// end FIX_CHANNEL_GROUP_DATA_WITH_ID
				///justin 07/11/2006 ADD_CODE_TO_DEAL_WITH_SEVERAL_BITS_DATA
				///// AW 07/10/06 SPEED_READ_MDF
				//if ( nBitOffset!= 0 )
				//{
					//out_str("Unfinished part, please contact with Justin or Andrew!");  // this is bit data, need file format
					//continue;
				//}
				///// END SPEED_READ_MDF
				///end ADD_CODE_TO_DEAL_WITH_SEVERAL_BITS_DATA
				
				TreeNode trCC = trCN.GetNode("CC");
				///---Sim 11-08-2006 HANDLE_CC_IS_INVALID
				/*
				TreeNode trVars = trCC.GetNode("Vars");
				colCC.SetUnits(trCC.Unit.strVal);
				vector<double> vdPara;
				if ( trVars.IsValid() )
				{
					vdPara = trVars.dVals;
				}
				*/
				if ( trCC.IsValid() )
					colCC.SetUnits(trCC.Unit.strVal);
				///---END HANDLE_CC_IS_INVALID
				int nNumBits = trCN.NumberBits.nVal;
				//int iFormulaID = trCC.FormulaID.nVal; ///---Sim 11-08-2006 HANDLE_CC_IS_INVALID_MEAN_NO_FORMULA Remove
				//int nDataType = trCN.GetNode("DataType").nVal;
				int nDataType = trCN.SignalType.nVal;/// Hong 10/12/06 MORE_IMPORT_MDF_INTO_ORIGIN
				
				/// Hong 01/09/06 MORE_COLUMN_INFO
				// set user parameter
				StringArray vsNames, vsValues;
				vsNames.Add("Sample Rate");
				vsValues.Add(trCN.SampleRange.dVal);
				/// Hong 06/12/07 v8.0639 MORE_USEFUL_INFO_ASKED_BY_USER
				vsNames.Add("Bits Number");
				vsValues.Add(nNumBits);
				/// end MORE_USEFUL_INFO_ASKED_BY_USER
				/// Hong 04/05/07 v.8.0596e MOVE_TO_USER_PARAMETERS
				vsNames.Add("Signal Description");
				vsValues.Add(trCN.SignalDescr.strVal);
				/// end MOVE_TO_USER_PARAMETERS
				/// AW 06/08/07 ADD_SIGNAL_DISPLAY_INFO
				vsNames.Add("Display Identifier");
				vsValues.Add(trCN.Signal.strVal);
				/// END AW 06/08/07 ADD_SIGNAL_DISPLAY_INFO
				set_user_parameters(colCC, vsNames, vsValues);
				// set user info
				Tree trUserInfo;
				trUserInfo.AddTextNode(lpcszFileName, "ImportFile");
				if( trCN.ValidRange.nVal )
				{
					TreeNode trNode1 = trUserInfo.AddNumericNode(trCN.MinRange.dVal, "MinRange");
					trNode1.SetAttribute(STR_LABEL_ATTRIB, "Implementation Min");
					trUserInfo.AddNumericNode(trCN.MaxRange.dVal, "MaxRange");
				}
				if( trCC.IsValid() && trCC.ValidRange.nVal )
				{
					trUserInfo.AddNumericNode(trCC.PhysMin.dVal, "PhysMin");
					trUserInfo.AddNumericNode(trCC.PhysMax.dVal, "PhysMax");
				}
				string strFormulaName = "";
				if( trCC.IsValid() && trCC.FormulaID )
				{
					switch( trCC.FormulaID.nVal )
					{
						case 0: // parametric, linear
							strFormulaName = "parametric, linear";
							break;
						case 1: // tabular with interpolation
							strFormulaName = "tabular with interpolation";
							break;
						case 2: // tabular
							strFormulaName = "tabular";
							break;
						case 6: // polynomial function
							strFormulaName = "polynomial function";
							break;
						case 7: // exponential function
							strFormulaName = "exponential function";
							break;
						case 8: // logarithmic function
							strFormulaName = "logarithmic function";
							break;
						case 9: // ASAP2 Rational conversion formula
							strFormulaName = "ASAP2 Rational conversion formula";
							break;
						case 10:
							break;
						case 11: // ASAM-MCD2 Text Table
							strFormulaName = "ASAM-MCD2 Text Table";
						case 12: // ASAM-MCD2 Text Range Table 
							strFormulaName = "ASAM-MCD2 Text Range Table";
							break;
						case 132: // Date
							strFormulaName = "Date";
							break;
						case 133: // time
							strFormulaName = "time";
							break;
						case 65535: // 1:1 conversion formula
							strFormulaName = "1:1 conversion formula";
							break;
						default:
							break;
					}
					trUserInfo.AddTextNode(strFormulaName, "Formula");
				}
				trUserInfo.Enable = ENABLE_READ_ONLY;
				trUserInfo.SetAttribute(STR_ATTRIB_BRANCH, GETNBRANCH_OPEN);
				string strTemp("ColumnInfo");
				///---Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
				//trUserInfo.Show = 0; ///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
				//set_user_info(colCC, strTemp, trUserInfo);
				fu_set_import_file_info(colCC, trUserInfo, strTemp, IMPORT_INFO_TO_USER_TREE);
				///---END QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
				///---Sim 02-04-2010 QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
				///---Sim 02-05-2010 QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
				// roll back move column info out of user tree, as CP said
				//fu_set_import_file_name_info(colCC, lpcszFileName);
			//
				//trUserInfo.RemoveChild("ImportFile");
				//trUserInfo.Show = 1;
				//set_import_file_info(colCC, trUserInfo, "MDF");
				///---END QA81-15063 ROLL_BACK_MOVE_COL_INFO_OUT_OF_USER_TREE
				///---END QA81-15063 MOVE_IMP_FILE_INFO_OUT_FROM_COL_USER_INFO_TREE
				//if( trCC.IsValid() && trCC.ValidRange.nVal )
				//{
					//vsNames.Add("Implementation Min");
					//vsValues.Add(trCN.MinRange.dVal);					
					//vsNames.Add("Implementation Max");
					//vsValues.Add(trCN.MaxRange.dVal);							
				//}
				//vsNames.Add("Sample Rate");
				//vsValues.Add(trCN.SampleRange.dVal);	
				//if( trCC.IsValid() && trCC.ValidRange.nVal )
				//{
					//vsNames.Add("PhysMin");
					//vsValues.Add(trCC.PhysMin.dVal);					
					//vsNames.Add("PhysMax");
					//vsValues.Add(trCC.PhysMax.dVal);										
				//}
				/// end MORE_COLUMN_INFO
				///--- Justin 7/13/2006 FASTER_IMPORT_DATA
				//if (7 == trCN.SignalType.nVal )  // text column
				//{
					///// AW 07/10/06 SPEED_READ_MDF
					////colCC.SetInternalDataType(FSI_TEXT, 0);    // must comment this, need ask CP
					//Dataset dsTemp(colCC);
					//dsTemp.SetSize(nNumRecords);
					//
					//for( int ii = 0; ii < nNumRecords; ii++) 
					//{
						//string strTemp(pbCN, nNumBits/8);//string strTemp(pbCN, nRecordSize);  ///justin 7/11/2006 REVISE_CN_TEXT_SIZE
						//dsTemp.SetText(ii, strTemp);
						//pbCN += nRecordSize;
					//}
					///// END SPEED_READ_MDF
				//}
		
				//else  // treat as double type column
				//{
					//colCC.SetInternalDataType(FSI_DOUBLE, 0); /// AW 07/10/06 SPEED_READ_MDF
					//colCC.SetNumRows(nNumRecords);  
					//int nElementSize;  
					//UINT nNumElements; 
					//double dResult; 
					//LPVOID lpData = colCC.GetInternalDataBuffer(&nElementSize, &nNumElements); 
					//double* pdCurrentDet =(double*)lpData; 
					//if( nElementSize != 8 && nNumElements < nNumRecords ) 
						//return -1; 
					//for( int ii = 0; ii < nNumRecords; ii++) 
					//{  
						//*pdCurrentDet = getCNValue( nDataType, pbCN, nBitOffset, iFormulaID, vdPara);
						//pbCN += nRecordSize; 
						//pdCurrentDet++; 
					//}
					//colCC.ReleaseBuffer();
								
					///*
					///// AW 07/10/06 SPEED_READ_MDF 
					//// the speed is not so good and there is problem in keep data after call GetInternalDataBuffer
					//{
						////Column coltemp(colCC);
						//colCC.SetNumRows(nNumRecords); 
						//colCC.SetInternalDataType(nDataType, 0);
						//int nElementSize;  
						//UINT nNumElements; 
						//double dResult; 
						//LPVOID lpData = colCC.GetInternalDataBuffer(&nElementSize, &nNumElements); 
						//if( nElementSize != nSize && nNumElements < nNumRecords ) 
							//return -1;
						//for( int ii = 0; ii < nNumRecords; ii++) 
						//{
							//double *pdd = (double *)pbCN;
							//memcpy(lpData, pbCN, nElementSize);
							//pbCN += nRecordSize; 
							//lpData+= nElementSize;
						//}
						//colCC.ReleaseBuffer(); 
					//}
					////wks.UpdateOrigin();
					////ApplyFormular(colCC, vdPara, iFormulaID); 
					///// END SPEED_READ_MDF
					//*/
				//}
				//---Sim 10-12-2006 ALREADY_CREATE_COLUMN
				//Dataset dsTemp(colCC);
				//dsTemp.SetSize(nNumRecords);
				//double dResult; ///---Sim 10-12-2006 NO_USE
				//dsTemp.Detach(); ///---Sim 10-12-2006 RELEASE_DATASET_FOR_LET_OTHER_OBJECT_USE
				//---END ALREADY_CREATE_COLUMN
				/// AW 07/13/06 MORE_ON_FASTER_IMPORT_DATA
				/*
				switch(nDataType)
				{
				case FSI_BYTE:
					switch( iFormulaID )
					{
					case 0:
						GET_NUMERIC_CN( FORMULA0(dResult,vdPara), dResult,nNumRecords,nRecordSize, pbCN, dsTemp, byte); 
						break;				 
					default:
						GET_NUMERIC_CN(FORMULA65535, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, byte) 
					}
					break;
				case FSI_USHORT:
					switch( iFormulaID )
					{
					case 0:
						GET_NUMERIC_CN(FORMULA0(dResult,vdPara), dResult,nNumRecords,nRecordSize, pbCN, dsTemp, USHORT) 
						break;				 
					default:
						GET_NUMERIC_CN(FORMULA65535, dResult, nNumRecords,nRecordSize, pbCN, dsTemp, USHORT) 
					}
					break;
				case FSI_ULONG:
					switch( iFormulaID )
					{
					case 0:
						GET_NUMERIC_CN( FORMULA0(dResult,vdPara), dResult,nNumRecords,nRecordSize, pbCN, dsTemp, UINT ); 
						break;				 
					default:
						GET_NUMERIC_CN(FORMULA65535, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, UINT) 
					}
					break;
				case FSI_CHAR:
					switch( iFormulaID )
					{
					case 0:
						GET_NUMERIC_CN( FORMULA0(dResult,vdPara), dResult,nNumRecords,nRecordSize, pbCN, dsTemp, char ); 
						break;				 
					default:
						GET_NUMERIC_CN(FORMULA65535, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, char) 
					}
					break;
				case FSI_SHORT:
					switch( iFormulaID )
					{
					case 0:
						GET_NUMERIC_CN( FORMULA0(dResult,vdPara), dResult,nNumRecords,nRecordSize, pbCN, dsTemp, short ); 
						break;				 
					default:
						GET_NUMERIC_CN(FORMULA65535, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, short) 
					}
					break;
				case FSI_LONG:
					switch( iFormulaID )
					{
					case 0:
						GET_NUMERIC_CN( FORMULA0(dResult,vdPara), dResult,nNumRecords,nRecordSize, pbCN, dsTemp, LONG ); 
						break;				 
					default:
						GET_NUMERIC_CN(FORMULA65535, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, LONG) 
					}
					break;
				case FSI_REAL:
					switch( iFormulaID )
					{
					case 0:
						GET_NUMERIC_CN( FORMULA0(dResult,vdPara), dResult,nNumRecords,nRecordSize, pbCN, dsTemp, float ); 
						break;				 
					default:
						GET_NUMERIC_CN(FORMULA65535, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, float) 
					}
					break;
				case FSI_DOUBLE:
					switch( iFormulaID )
					{
					case 0:
						GET_NUMERIC_CN(FORMULA0(dResult,vdPara), dResult,nNumRecords,nRecordSize, pbCN, dsTemp, double) 
						break;				 
					default:
						GET_NUMERIC_CN(FORMULA65535, dResult, nNumRecords, nRecordSize, pbCN, dsTemp, double) 
					}
					break;
				*/
				///Justin 09/22/2006 
				/*
				switch(nDataType)
				{
				case FSI_BYTE:
					GET_CN_DATA(vdPara, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, byte) 
				case FSI_USHORT:
					GET_CN_DATA(vdPara, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, USHORT) 
				case FSI_ULONG:
					GET_CN_DATA(vdPara, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, UINT)
				case FSI_CHAR:
					GET_CN_DATA(vdPara, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, char)
				case FSI_SHORT:
					GET_CN_DATA(vdPara, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, short)
				case FSI_LONG:
					GET_CN_DATA(vdPara, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, LONG)
				case FSI_REAL:
					GET_CN_DATA(vdPara, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, float)
				case FSI_DOUBLE:
					GET_CN_DATA(vdPara, dResult,nNumRecords,nRecordSize, pbCN, dsTemp, double)
				/// END MORE_ON_FASTER_IMPORT_DATA			
		
				case FSI_TEXT:
					GET_TEXT_CN( nNumRecords, nRecordSize, pbCN, dsTemp, nNumBits )
					break;		
				case -1:
				case -2:
				default:  out_str("Unfinished part, please contact with Justin or Andrew!");
				}
			
				///--- end FASTER_IMPORT_DATA
				*/
				//end 
				bool bAppliedFormular = false; ///---Sim 09-25-2006 SUPPORT_BYTE_ARRAY_DATA_TYPE
				/// Hong 10/10/06 IMPORT_MDF_INTO_ORIGIN
				string strRange;
				make_column_range_string(strRange, colCC);
				int nNumFirstBits = trCN.GetNode("NumberFirstBit").nVal;
				int nSkipNumBits;
				/// END IMPORT_MDF_INTO_ORIGIN
				bool bSupportedDataType = true; ///---Sim 10-12-2006 WARNING_BY_UNSUPPORT_DATA_TYPE
				/// Hong 10/12/06 MORE_IMPORT_MDF_INTO_ORIGIN
				/*
				switch(nDataType)
				{
				/// Hong 10/10/06 IMPORT_MDF_INTO_ORIGIN
				/*
				case FSI_BYTE:
				//	READ_NUMERIC_CN2(nNumRecords, nRecordSize, pbCN, dsTemp, byte)
					mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, sizeof(byte));
					break;
				case FSI_USHORT: 
					//READ_NUMERIC_CN2(nNumRecords, nRecordSize, pbCN, dsTemp, USHORT)
					mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, sizeof(USHORT));
					break;
				case FSI_ULONG:
					//READ_NUMERIC_CN2(nNumRecords, nRecordSize, pbCN, dsTemp, UINT)
					mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, sizeof(UINT));
					break;
				case FSI_CHAR:
					//READ_NUMERIC_CN2(nNumRecords, nRecordSize, pbCN, dsTemp, char)
					mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, sizeof(char));
					break;
				case FSI_SHORT:
					//READ_NUMERIC_CN2(nNumRecords, nRecordSize, pbCN, dsTemp, short)
					mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, sizeof(short));
					break;
				case FSI_LONG:
					//READ_NUMERIC_CN2(nNumRecords, nRecordSize, pbCN, dsTemp, LONG)
					mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, sizeof(LONG));
					break;
				case FSI_REAL:
					//READ_NUMERIC_CN2(nNumRecords, nRecordSize, pbCN, dsTemp, float)
					mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, sizeof(float));
					break;
				case FSI_DOUBLE:
					//READ_NUMERIC_CN2(nNumRecords, nRecordSize, pbCN, dsTemp, double)
					mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, sizeof(double));
					break;
					/
				case FSI_BYTE:
				case FSI_USHORT: 
				case FSI_ULONG:
				case FSI_CHAR:
				case FSI_SHORT:
				case FSI_LONG:
				case FSI_REAL:
				case FSI_DOUBLE:
					mdf_put_numberic_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, nDataType);
					break;
				case FSI_TEXT:
					mdf_put_text_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, nNumBits/8);
					break;		
				case FSI_BYTEARRAY:
					break;//need support later
				case -1: 
				case -2:
				case -3:
				case -4:
				case -5:
				case -6:
				case -7:
					nSkipNumBits = 	nNumFirstBits % 8;
					mdf_put_bits_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, nSkipNumBits, nNumBits);
					break;
				/// END IMPORT_MDF_INTO_ORIGIN
				default:
					///---Sim 10-12-2006 WARNING_BY_UNSUPPORT_DATA_TYPE
					//out_str("Unfinished part, please contact with Justin or Andrew!");
					string strMsg;
					strMsg.Format("Unsupport this data type: (%d), in Col(%s).", nDataType, colCC.GetName());
					warning_msg_box(strMsg, false);
					bool bSupportedDataType = false;
					///---END WARNING_BY_UNSUPPORT_DATA_TYPE
				}
				*/
				nSkipNumBits = 	nNumFirstBits % 8;
				if(!mdf_put_data_to_range(strRange, nNumRecords, nRecordSize, pbCN, nDataType, nSkipNumBits, nNumBits))
				{
					///---Sim 10-12-2006 WARNING_BY_UNSUPPORT_DATA_TYPE
					//out_str("Unfinished part, please contact with Justin or Andrew!");
					string strMsg;
					strMsg.Format("Unsupport this data type: (%d), in Col(%s).", nDataType, colCC.GetName());
					warning_msg_box(strMsg, false);
					bool bSupportedDataType = false;
					///---END WARNING_BY_UNSUPPORT_DATA_TYPE  
				}
				/// end MORE_IMPORT_MDF_INTO_ORIGIN
				if( 1 == trCN.ChannelType.nVal )
					colCC.SetType(OKDATAOBJ_DESIGNATION_X);
				else 
					colCC.SetType(OKDATAOBJ_DESIGNATION_Y);
				
				///---Sim 10-10-2006 SUPPORT_PROGRESS_SHOW
				///---Sim 04-18-2007 FIX_PROGRESS_CANCEL_ISSUE
				//m_bUserCancel = !(m_pProgress->Set(m_nDataCount++));
				if( 1 != trCN.ChannelType.nVal ) ///---Sim 09-08-2007 FIX_MORE_THAN_100_PERCENT_PROGRESS
					m_pProgress->Set(m_nDataCount++);
				m_bUserCancel = m_pProgress->IsAbort();
				///---END FIX_PROGRESS_CANCEL_ISSUE
				///---END SUPPORT_PROGRESS_SHOW
				
				///---Sim 10-12-2006 WARNING_BY_UNSUPPORT_DATA_TYPE
				// if unsupport this data type , couldn't apply formula and so on.
				if ( !bSupportedDataType )
					continue;
				///---END WARNING_BY_UNSUPPORT_DATA_TYPE
				
				///---Sim 09-25-2006 VARIABLE_PARAMETER
				//ApplyFormular(colCC, vdPara, iFormulaID); 
				if ( !bAppliedFormular )					
				{					
					/// Hong 07/09/07 v8.0655 IMPORT_RAW_DATA_FOR_MAY_FORMULA
					//ApplyFormular(colCC, trCN); 
					ApplyFormular(colCC, trCN, nC1, nC2); 
					/// end IMPORT_RAW_DATA_FOR_MAY_FORMULA
				}					
				///---END VARIABLE_PARAMETER
			///---Sim 09-29-2006 SUPPORT_DATA_SELECTION
			}
			/// Hong 06/08/07 QA80-9890 IMPORT_ALL_DATA_TO_ONE_SHEET
			//trCNSetting = trCNSetting.NextNode;
			trChannel = trChannel.NextNode;
			/// end IMPORT_ALL_DATA_TO_ONE_SHEET
			///---END SUPPORT_DATA_SELECTION
		}
	///---Sim 09-29-2006 ONLY_SUPPORT_ONE_CHANNEL_GROUP
	}
	///---END ONLY_SUPPORT_ONE_CHANNEL_GROUP

	free( pBuffer );
	return CER_NO_ERROR; ///---Sim 11-09-2006 HANDLE_ERROR_MESSAGE
}

int MDFFile::getDataTypeFromat(unsigned short numberOfBits, unsigned short SignalType )
{
	switch (SignalType)
	{
	case 0: // unsigned
        switch (numberOfBits)
        {
        case 8:
               	return FSI_BYTE; 
        case 16:
                return FSI_USHORT; 
        case 32:
                return FSI_ULONG; 
        /// justin 7/11/2006 ADD_MORE_RETURN_INFOMATION  
        //case 1:
                //// dataType='ubit1';   unknown handle
        //case 2:
                ////dataType='ubit2';   unknown handle
        //default:
                //return -1;
        case 1:
                return -1; // 1-bit unsigned data
        case 2:
                return -2; // 2-bit unsigned data
        default:
                return -8;  //indecate unkonwn data format
        //end ADD_MORE_RETURN_INFOMATION
        }
        
    case 1: //% signed int
        switch (numberOfBits)
        {
        case 8:
            return FSI_CHAR; //    
        case 16:
            return FSI_SHORT; //    
        case 32:
            return FSI_LONG; //    
        default:
            return -8 //return -1;  //    error('Unsupported number of bits for signed int'); /// justin 7/11/2006 ADD_MORE_RETURN_INFOMATION 
        }
        
    case 2:
    case 3: // % floating point
        switch (numberOfBits)
        {
        case 32:
                return FSI_REAL; 
        case 64:
                return FSI_DOUBLE; 
        default:
            return -8 //return -1;  //    error('Unsupported number of bits for signed int'); /// justin 7/11/2006 ADD_MORE_RETURN_INFOMATION 
        }
        
    case 7: //% NULL-terminated string
        return FSI_TEXT; 
    ///Justin 09/22/2006 QA70-8698 FULL_SUPPORT_MDF300    
    case 8: //% byte aray
    	return FSI_TEXT; 
    //end FULL_SUPPORT_MDF300    	
        
    default:
            return -8 //return -1;  //    error('Unsupported number of bits for signed int'); /// justin 7/11/2006 ADD_MORE_RETURN_INFOMATION 
    }
    return -8 //return -1;   /// justin 7/11/2006 ADD_MORE_RETURN_INFOMATION 
}
//justin 7/11/2006 ADD_CODE_TO_DEAL_WITH_SEVERAL_BITS_DATA 
//double MDFFile::getCNValue(int nDataType,  byte* pbOriginData,int iFormulaID, vector<double>& vdPara)
double MDFFile::getCNValue(int nDataType,  byte* pbOriginData, int nBitOffset, int iFormulaID, vector<double>& vdPara)
//end ADD_CODE_TO_DEAL_WITH_SEVERAL_BITS_DATA
{
	double dRet;
	switch(nDataType)
	{
	case FSI_BYTE:
		dRet = *pbOriginData;
		break;
	case FSI_USHORT:
		dRet = *(unsigned short*)pbOriginData;
		break;
	case FSI_ULONG:
		dRet = *(unsigned long*)pbOriginData;
		break;
	case FSI_CHAR:
		dRet = *(char *)pbOriginData;
		break;
	case FSI_SHORT:
		dRet = *(short*)pbOriginData;
		break;
	case FSI_LONG:
		dRet = *(int*) pbOriginData;
		break;
	case FSI_REAL:
		dRet = *(float*) pbOriginData;
		break;
	case FSI_DOUBLE:
		dRet = *(double*)pbOriginData;
		break;
	//justin 7/11/2006 ADD_CODE_TO_DEAL_WITH_SEVERAL_BITS_DATA 
	case -1:
		dRet = ((*pbOriginData) >>( 7 - nBitOffset)) & 1;
		break;
	case -2:
		dRet = ((*pbOriginData) >>( 6 - nBitOffset)) & 3;
		break;
	//end ADD_CODE_TO_DEAL_WITH_SEVERAL_BITS_DATA

	default: 
		dRet = NANUM;
	}
	
	switch(iFormulaID)
	{
	case 0:
		int nTemp = vdPara.GetSize();
		dRet = vdPara[0] + vdPara[1] * dRet;
		break;
	case 1:
	case 2:
		break;
	case 6:
		//if( 6 > vdPara.GetSize())
			//return NUNAM;
		double dTemp = dRet;
		dRet = vdPara[5];
		for(int ii = 5; ii >= 0; ii--)
		{
			dRet = dRet * dTemp + vdPara[ii];
		}
		break;
	case 10:
	case 11:		
	case 65535:
		break;
	}
	return dRet;
}
bool MDFFile::ConvertFileInfo(TreeNode& trFileInfo, TreeNode& trHdrStruct)
{
	///---Sim 10-10-2006 GET_HEADER_INFO
	trFileInfo.AddNode("HeaderInfo");
	trFileInfo.HeaderInfo.Replace(trHdrStruct);
	/*
	string strTmp;
	TreeNode trTemp = trHdrStruct.GetNode("MDF");
	strTmp = trTemp.BlockID.strVal;
	strTmp.Left(3);
	strTmp += trTemp.FormatID.strVal;
	trFileInfo.AddTextNode(strTmp, "Format version");
	strTmp = trTemp.ProgramID.strVal;
	trFileInfo.AddTextNode(strTmp, "Program");
	*/
	///---END GET_HEADER_INFO
	return true;
} 
///---Sim 10-10-2006 GET_SHOWING_FILE_INFO
BOOL MDFFile::GetUsefulFileInfo(TreeNode& trUsefulInfo, const TreeNode& trInfo, const TreeNode& trFileSetting)
{
	//get base info
	TreeNode trID = trInfo.GetNode("MDF");
	TreeNode trUsefulID = trUsefulInfo.AddNode("ID");
	trUsefulID.FileIdentifier.strVal = trID.BlockID.strVal; // should always contains "MDF"
	trUsefulID.FormatIdentifier.strVal = trID.FormatID.strVal; //Start with "2.00" or "3.00" , 
	trUsefulID.ProgramIdentifier.strVal = trID.ProgramID.strVal;
	
	TreeNode trHD = trInfo.GetNode("HD");
	TreeNode trUsefulHD = trUsefulInfo.AddNode("HD");
	trUsefulHD.NumberOfDataGroups.nVal = trHD.NumberDataGroups.nVal; //Number of DG  
	trUsefulHD.Date.strVal = trHD.date.strVal;
	trUsefulHD.Time.strVal = trHD.time.strVal;
	trUsefulHD.Author.strVal = trHD.Author.strVal;
	trUsefulHD.Department.strVal = trHD.department.strVal;
	trUsefulHD.Project.strVal = trHD.ProjName.strVal;
	trUsefulHD.MeasurementObject.strVal = trHD.MeasObj.strVal;
	
	//get data groups info
	/* no necessary get this information into worksheet layer
	TreeNode trDG0 = trInfo.GetNode("DG0");
	TreeNode trUsefulDG0 = trUsefulInfo.AddNode("DG0");
	
	TreeNode trDGSetting;
	if ( trFileSetting && trFileSetting.IsValid() )
		trDGSetting = trFileSetting.DataSelection.FirstNode;
	foreach (TreeNode trDG in trDG0.Children )
	{
		if ( !(trDGSetting && trDGSetting.IsValid()) || 1 == trDGSetting.Use )
		{
			TreeNode trUsefulDG = trUsefulDG0.AddNode(trDG.tagName);
			trUsefulDG.NumberOfChannelGroups.nVal = trDG.NumberChGroups.nVal; // The number of CG, should be 1. A DG has only one CG.
		}
		trDGSetting = trDGSetting.NextNode;
	}	
	*/

	return true;
}
///---END GET_SHOWING_FILE_INFO

/*
int TestMDF()   
{
	string strPath, strFileName;
	strPath = GetOpenBox();	
	strFileName = GetFileName(strPath);
	MDFFile MDFFile;
	int nRet;
//	if ( nRet = MDFFile.LoadAndVerify(strPath ) )
//		return nRet;
	
	if ( nRet = MDFFile.ReadFile(strPath ) )
		return nRet;

	MDFFile.GetResult();
	
	return 0;
}
*/
