#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	method_count,
	method_sum,
	method_mean,
	method_min,
	method_max,
};
enum{
	sort_total_no,
	sort_total_descend,
	sort_total_ascend,
};
enum{
	normalize_no,
	normalize_frac,
	normalize_perc,
};
//put additional include files here
#include <event_utils.h>		///------ Folger 06/29/09 BETTER_ERROR_CHECKING_FOR_PIVOT_TABLE
#include <ReportTree.h>			///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
///////////////////////////////////////////////////////////////////////////////
// Modification Log 
	/// CPY 11/15/08 QA70-12588-P2 RESULT_COL_HEADING_SHOULD_BE_SORTED
	/// CPY 11/16/08 CHANGE_COL_INDEX_TO_RANGE
	/// CPY 11/19/08 QA70-12588-P5 SORT_ROW_LABELS_ADD_COL_TOTAL
	/// Max 12/08/08 8.0983b USE_MORE_MEANINGFUL_ABBR
	/// CPY 4/28/09 QA70-13225-P7 COL_SUM_SHOULD_NOT_BE_SORTED
	/// Kyle 06/22/2009 QA80-13617 OUTPUT_MESSAGE_CODE_FROM_CrossTab
	/// Folger 06/29/09 BETTER_ERROR_CHECKING_FOR_PIVOT_TABLE
	/// Folger 07/14/09 QA80-13933 PIVOT_TABLE_FAILS_TO_COPY_SOURCE_COLUMN_FORMAT_TO_DEST
	/// Sim 08-18-2009 FIX_SHOW_HIDE_OPTION_AFTER_LOAD_THEME
	/// Kyle 08/19/2009 SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
	/// Kyle 08/19/2009 DISABLE_Show_Zeros_when_Empty_ON_COUNT_SELECTED
	/// Kyle 08/19/2009 CHECK_NUM_OF_ROWS_BEFORE_PUT_DATA_TO_THE_OUTPUT_WKS
	/// Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	/// Kyle 08/25/2009 QA80-14189-P4 ALWAYS_USE_THE_LONGER_INPUT_AS_DATA_COLUMN
	/// Kyle 09/25/2009 QA80-13617 ALLOW_USER_CANCEL_THE_OPERATION
	/// Kyle 10/10/2009 QA80-14187 REPORT_TREE_COPY_PROPERTY_FROM_SOURCE_COLUMN
	/// Folger 10/12/09 QA80-14449 REPORTDATA_SHOULD_NOT_UPDATE_SN_LN_WHEN_RECALCULATE
///////////////////////////////////////////////////////////////////////////////

///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT, clean the not used static functions
/*
static bool _put_wks_long_names(Worksheet& wks, const vector<string>& vs, int nC1)
{
	for(int ii = nC1, jj = 0; jj < vs.GetSize(); ii++, jj++)
	{
		Column cc = wks.Columns(ii);
		if(!cc)
			return error_report("col not found when setting LN at index = " + (string)(ii+1));
		
		cc.SetLongName(vs[jj]);
		cc.SetType(OKDATAOBJ_DESIGNATION_Y);
	}
	return true;
}

static bool _sum_wks_rows(Worksheet& wks, int c1, int c2, int nr)
{
	Dataset dy(wks, nr);
	
	for(int ii = c1, jj = 0; ii<=c2; ii++, jj++)
	{
		Dataset dd(wks, ii);
		if(jj == 0)
			dy = dd;
		else
			dy += dd;
	}
	return true;
}
*/
///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
		
static int _cvt_combo_to_ct(int nCombo)
{
	switch(nCombo)
	{
	case 1:
		return CT_SUM;
	case 2:
		return CT_MEAN;
	case 3:
		return CT_MIN;
	case 4:
		return CT_MAX;
	}
	return CT_COUNT;
}


//---- CPY 11/16/08 CHANGE_COL_INDEX_TO_RANGE
static BOOL _get_wks_col(const Range& rng, Worksheet& wks, int& nCol)
{
	int r1,r2,c1,c2;
	if(!rng.IsValid() || rng.GetNumRanges() < 1)
	{
		nCol = -1;
		return true;
	}
	Worksheet wks2;
	if(!rng.GetRange(0, r1, c1, r2, c2, wks2))
		return false;
	// check if same wks
	if(wks)
	{
		string strName1 = wks_get_book_sheet_name(wks);
		string strName2 = wks_get_book_sheet_name(wks2);
		if(strName2 != strName1)
			return false;
	}
	else
		wks = wks2;
	
	nCol = c1;
	return true;
}
//---- end CHANGE_COL_INDEX_TO_RANGE

///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT, clean the not used static functions
/*
//--------- CPY 11/19/08 QA70-12588-P5 SORT_ROW_LABELS_ADD_COL_TOTAL
static void _mat_col_wise_div(matrix& mm, vector& vv)
{
	ASSERT(mm.GetNumCols() == vv.GetSize());
	vector vdivider;
	vdivider = 1/vv;
	ASSERT(mm.GetNumCols() == vdivider.GetSize());
	matrix mdivider;
	mdivider.SetSize(vdivider.GetSize(), vdivider.GetSize());
	mdivider.SetDiagonal(vdivider);
	
	mm = mm * mdivider;
}
//---------
*/
///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT

///------ Folger 06/29/09 BETTER_ERROR_CHECKING_FOR_PIVOT_TABLE
static	int		_check_input_data(TreeNode& trGetN)
{
	int		nErrCode = 0;
	if ( 0 != (nErrCode = check_1_column(trGetN.row))
		|| 0 != (nErrCode = check_1_column(trGetN.col))
		|| (trGetN.method.nVal > 0 && 0 != (nErrCode = check_1_data(trGetN.data)))
		)
		;
	
	return nErrCode;
}
///------ End BETTER_ERROR_CHECKING_FOR_PIVOT_TABLE

///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT, clean the not used static functions
/*
///Kyle 08/19/2009 SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
void _mat_sum_skip_missing_values(matrix& mm, vector& vdSum, bool bSumCol)
{
	if(!bSumCol)
		mm.Transpose();
	mm.SumColumns(vdSum);

	for(int ii=vdSum.GetSize()-1; ii>=0; ii--)
	{
		if(is_missing_value(vdSum[ii]))
		{
			vector vCol;
			mm.GetColumn(vCol, ii);
			vCol.Trim();
			if(vCol.GetSize() > 0)
			{
				double dSum;
				vCol.Sum(dSum);
				vdSum[ii] = dSum;
			}

		}
	}
	if(!bSumCol)
		mm.Transpose();
}
///End SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
*/
///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT

///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT

#define PIVOT_TABLE_REPORT_ID			0x00000010
enum _PIVOT_TABLE_RES_ID
{
	_PIVOT_TABLE_ROW_VALUES_ID	= 0x00010010,
	_PIVOT_TABLE_RESULT_ID,
};

static void _update_output_report(ReportData& rd, const matrix& mm, const vector<string>& vsColVals, LPCSTR lpcszRowValuesLabel, const vector<string>& vsRowVals, int nSrcFmtColUID = 0)
{
	if(!rd || !mm)
		return;
	///------ Folger 10/12/09 QA80-14449 REPORTDATA_SHOULD_NOT_UPDATE_SN_LN_WHEN_RECALCULATE
	rd.SetAttribute(STR_REPORT_TREE_ALWAYS_UPDATE_COLUMN_LABELS_ATTRIB, 1);
	///------ End REPORTDATA_SHOULD_NOT_UPDATE_SN_LN_WHEN_RECALCULATE
	ReportTable rt = rd.CreateTable("PivotTable", "", PIVOT_TABLE_REPORT_ID);

	TreeNode trRowValues = rt.AddColumn(vsRowVals, "", _PIVOT_TABLE_ROW_VALUES_ID, lpcszRowValuesLabel, OKDATAOBJ_DESIGNATION_X);
	///Kyle 10/10/2009 QA80-14187 REPORT_TREE_COPY_PROPERTY_FROM_SOURCE_COLUMN
	//trRowValues.SetAttribute(STR_COL_FORMAT_SRC_COL_UID_ATTRIB, nSrcFmtColUID);
	DWORD dwCntrl = SRC_COL_PROPERTY_FORMAT;
	okutil_source_column_property(&trRowValues, &nSrcFmtColUID, &dwCntrl, false);
	///End REPORT_TREE_COPY_PROPERTY_FROM_SOURCE_COLUMN
	
	int nID = _PIVOT_TABLE_RESULT_ID;
	for(int nCol = 0; nCol < mm.GetNumCols(); nCol++)
	{
		vector vData;
		mm.GetColumn(vData, nCol);
		rt.AddColumn(vData, "", nID++, vsColVals[nCol]);
	}
}
///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	
//total = add new column to sum rows into a col(total)
//sum = add a new row to sum values in each column at the end


void wpivot(const Range& row, const Range& col, const Range& data, const int& method, const int& total, const int& sort_total, const int& sum, const int& normalize, const int& zero, ReportData& rd)
{
	///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	/*
	if(!row.IsValid() || !orng.IsValid() || !col.IsValid())
		XF_THROW(CER_NO_WORKSHEET);
	
	Worksheet 		wout;
	int				r1,r2,c1,c2;
	
	if(!orng.GetRange(0, r1, c1, r2, c2, wout))
		XF_THROW(CER_NO_WORKSHEET);
	
	Column			crRow = wout.Columns(c1);// the row label col for the result table(matrix)
	if(!crRow)
		XF_THROW(CER_NO_WORKSHEET);
	crRow.SetType(OKDATAOBJ_DESIGNATION_X);
	*/
	if(!row.IsValid() || !rd.IsValid() || !col.IsValid())
		XF_THROW(CER_NO_WORKSHEET);
	///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	///Kyle 09/14/2009 CHECK_INPUT_DATA_BEFORE_CALCULATION
	int nErrCode = 0;
	if( 0 != (nErrCode = check_1_column(row)) ||
		0 != (nErrCode = check_1_column(col)) ||
		(method != method_count && 0 != (nErrCode = check_1_data(data)) )
		)
		XF_THROW(nErrCode);
	///End CHECK_INPUT_DATA_BEFORE_CALCULATION
	int				nStatsType = _cvt_combo_to_ct(method);
	//---- CPY 11/16/08 CHANGE_COL_INDEX_TO_RANGE
	//int				nvRow = row - 1;//LT index to OC index
	//int				nvCol = col - 1;
	//int				nData = data - 1;
	int nvRow, nvCol, nData;
	Worksheet iw;
	if(!_get_wks_col(row, iw, nvRow)) XF_THROW(XFERR_INVALID_COL_RANGE);
	if(!_get_wks_col(col, iw, nvCol)) XF_THROW(XFERR_INVALID_COL_RANGE);
	if(!_get_wks_col(data, iw, nData)) XF_THROW(XFERR_INVALID_COL_RANGE);
	//----
		
	int				nTotalColsInWks = iw.GetNumCols();
	if ( nvRow < 0 || nvCol < 0 || nTotalColsInWks <= nvRow || nTotalColsInWks <= nvCol || nTotalColsInWks <= nData )
		XF_THROW(XFERR_INVALID_COL_RANGE);
	
	if(nStatsType == CT_COUNT )
	{
		///Kyle 08/25/2009 QA80-14189-P4 ALWAYS_USE_THE_LONGER_INPUT_AS_DATA_COLUMN
		//nData = nvRow;// force to use vRow col to make things simple as recalculate will assign data to this anyway if started out empty
		Column cRow = iw.Columns(nvRow);
		Column cCol = iw.Columns(nvCol);
		if(cCol.GetUpperBound() - cCol.GetLowerBound() > cRow.GetUpperBound() - cRow.GetLowerBound())
			nData = nvCol;
		else
			nData = nvRow;
		///End ALWAYS_USE_THE_LONGER_INPUT_AS_DATA_COLUMN
	}
	else if(nData < 0)
			XF_THROW(XFERR_INVALID_COL_RANGE);
	
	matrix			mm;
	vector<string>	vsRowVals, vsColVals;
	///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	//int				nRet = iw.CrossTab(nvRow, nvCol, nData, mm, &vsRowVals, &vsColVals, nStatsType);
	DWORD dwCntrl = 0;
	if(sum)
		dwCntrl |= CROSS_TAB_COL_TOTAL;
	if(total)
		dwCntrl |= CROSS_TAB_ROW_TOTAL;
	if(normalize)
	{
		dwCntrl |= CROSS_TAB_NORMALIZE_BY_COLUMN_TOTAL;
		if(normalize == normalize_perc)
			dwCntrl |= CROSS_TAB_NORMALIZE_PERCENT;
	}
	int				nRet = iw.CrossTab(nvRow, nvCol, nData, mm, &vsRowVals, &vsColVals, nStatsType, dwCntrl);
	///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	///Kyle 06/22/2009 QA80-13617 OUTPUT_MESSAGE_CODE_FROM_CrossTab
	if(nRet)
	{
		if(nRet == CTERROR_OUT_OF_MEMORY)
		{
			XF_THROW(XF_ERR_NOT_ENOUGH_MEM);
		}
		///Kyle 09/25/2009 QA80-13617 ALLOW_USER_CANCEL_THE_OPERATION
		else if(nRet == CTERROR_CANCELED_BY_USER)
		{
			XF_THROW(XFERR_UI_USER_CANCEL);
		}
		///End ALLOW_USER_CANCEL_THE_OPERATION
		else
		{
			XF_THROW(nRet);
		}
	}
	///End OUTPUT_MESSAGE_CODE_FROM_CrossTab
	if(vsRowVals.GetSize() == 0 || vsColVals.GetSize() == 0)
		return;// nothing found
	///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	/*
	int				nrC1 = c1 + 1;//matrix 1st col
	int				nrC2 = nrC1 + vsColVals.GetSize() - 1;//matrix last col
	int				nrCols = nrC2 + 1 + (total?1:0);// number of result table cols
	if(wout.GetNumCols() < nrCols)
		wout.SetSize(-1, nrCols);
	///Kyle 08/19/2009 CHECK_NUM_OF_ROWS_BEFORE_PUT_DATA_TO_THE_OUTPUT_WKS
	int 	nUpperBound = mm.GetNumRows() + (sum? 1 : 0) - 1;
	foreach(Column cc in wout.Columns)
	{
		cc.SetUpperBound(nUpperBound);
	}
	///End CHECK_NUM_OF_ROWS_BEFORE_PUT_DATA_TO_THE_OUTPUT_WKS
	
	/// YuI 11/24/08 QA70-12637 PIVOT_XFUNCTION_SHOULD_PRODUCE_PROPER_OUTPUT
	orng.SetRange(0, wout, 0, c1, -1, nrCols - 1);
	/// end PIVOT_XFUNCTION_SHOULD_PRODUCE_PROPER_OUTPUT
	//result table row labels
	Column cvRow = iw.Columns(nvRow);
	crRow.SetLongName(cvRow.GetLongName());
	///------ Folger 07/14/09 QA80-13933 PIVOT_TABLE_FAILS_TO_COPY_SOURCE_COLUMN_FORMAT_TO_DEST
	crRow.CopyDataFormat(cvRow);
	///------ End PIVOT_TABLE_FAILS_TO_COPY_SOURCE_COLUMN_FORMAT_TO_DEST
	*/
	///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	//--- CPY 11/15/08 QA70-12588-P2 RESULT_COL_HEADING_SHOULD_BE_SORTED
	vector<uint> vn;
	vsColVals.Sort(SORT_ASCENDING, true, vn);
	///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	if(total)
	{
		vn.Add(vn.GetSize());
		vsColVals.Add(_L("Total"));
	}
	///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	mm.Transpose();
	mm.ReorderRowWise(vn);
	mm.Transpose();
	///Kyle 08/21/2009 QA80-14189 CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
	////--------- CPY 11/19/08 QA70-12588-P5 SORT_ROW_LABELS_ADD_COL_TOTAL
	//if(!total || sort_total_no == sort_total)// sort = sort total col, so if total not sorted, we should sort the row label col
	//{
		//vsRowVals.Sort(SORT_ASCENDING, true, vn);
		//mm.ReorderRowWise(vn);		
	//}
	////---- CPY 4/28/09 QA70-13225-P7 COL_SUM_SHOULD_NOT_BE_SORTED
	//// need to move to later
	////if(sum) // col total row
	////	vsRowVals.Add(_L("Total"));
	////---- end COL_SUM_SHOULD_NOT_BE_SORTED
	////--------- end SORT_ROW_LABELS_ADD_COL_TOTAL
	//crRow.PutStringArray(vsRowVals);
	////--- end RESULT_COL_HEADING_SHOULD_BE_SORTED
	//
	//_put_wks_long_names(wout, vsColVals, nrC1);
	//
	//if(zero)
		//mm.Replace(NANUM, 0, MATREPL_TEST_EQUAL);
	//
	////--------- CPY 11/19/08 QA70-12588-P5 SORT_ROW_LABELS_ADD_COL_TOTAL
	//vector colsum;
	//if(sum || normalize)
		/////Kyle 08/19/2009 SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
		////mm.SumColumns(colsum);
		//_mat_sum_skip_missing_values(mm, colsum, true);
		/////End SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
	//if(normalize)
	//{
		//_mat_col_wise_div(mm, colsum);
		//if(normalize_perc == normalize)
			//mm *= 100.0;
	//}
	////---- CPY 4/28/09 QA70-13225-P7 COL_SUM_SHOULD_NOT_BE_SORTED
	//// need to move to later 
	///*
	//if(sum)
	//{
		//int nOldRows = mm.GetNumRows();
		//mm.SetSize(nOldRows + 1, mm.GetNumCols(), true);
		//mm.SetRow(colsum, nOldRows);
	//}
	//*/
	////---- end COL_SUM_SHOULD_NOT_BE_SORTED
	////--------- end SORT_ROW_LABELS_ADD_COL_TOTAL
	//
	//mm.CopyTo(wout, 0, 0, -1, -1, 0, nrC1, false, false);
	//if(total)
	//{
		//Column cTot = wout.Columns(nrC2 + 1);
		//cTot.SetLongName("Total");
		/////Kyle 08/19/2009 SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
		////_sum_wks_rows(wout, nrC1, nrC2, nrC2+1);
		//vector rowsum;
		//_mat_sum_skip_missing_values(mm, rowsum, false);
		//Dataset dy(wout, nrC2+1);
		//dy = rowsum;
		/////End SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
		//if(sort_total)// nrC1+1 = Total col
			////wout.Sort(nrC2+1, sort_total==sort_total_a?SORT_ASCENDING : SORT_DESCENDING, TRUE, 0, c1,-1, nrC2+1);
			//wout.Sort(nrC2+1, sort_total==sort_total_ascend?SORT_ASCENDING : SORT_DESCENDING, TRUE, 0, c1,-1, nrC2+1);	/// Max 12/08/08 8.0983b USE_MORE_MEANINGFUL_ABBR
	//}
	//
	////---- CPY 4/28/09 QA70-13225-P7 COL_SUM_SHOULD_NOT_BE_SORTED
	//if(sum) // col total row
	//{
		//int 	nRowTotalRow = mm.GetNumRows();
		//int		nCols = colsum.GetSize();
		//if(total) 
		//{
			//double dsum = -1;
			//colsum.Sum(dsum);
			/////Kyle 08/19/2009 SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
			//if(is_missing_value(dsum))
			//{
				//vector vd;
				//vd = colsum;
				//vd.Trim();
				//if(vd.GetSize() > 0)
					//vd.Sum(dsum);
			//}
			/////End SKIP_MISSING_VALUES_WHEN_GET_SUM_OF_COLUMNS_OR_ROWS
			//nCols++;
			//colsum.SetSize(nCols);
			//colsum[nCols-1] = dsum; 
		//}
		//wout.SetCell(nRowTotalRow, nrC1-1, "Total");
		//mm.SetSize(1, nCols);// convert to 1xm to receive col sum data to be put into wks total row
		//mm.SetByVector(colsum);
		//mm.CopyTo(wout, 0, 0, -1, -1, nRowTotalRow, nrC1, false, false);
	//}
	////---- end COL_SUM_SHOULD_NOT_BE_SORTED
	if(zero)
		mm.Replace(NANUM, 0, MATREPL_TEST_EQUAL);
	if(total && sort_total)
	{
		vector vRowTotal;
		mm.GetColumn(vRowTotal, mm.GetNumCols()-1);
		if(sum)
			vRowTotal.SetSize(vRowTotal.GetSize()-1);			// remove the total
		vRowTotal.Sort(sort_total==sort_total_ascend?SORT_ASCENDING : SORT_DESCENDING, true, vn);
		ASSERT(vn.GetSize() == vsRowVals.GetSize());
		vsRowVals.Reorder(vn);
	}
	else
		vsRowVals.Sort(SORT_ASCENDING, true, vn);
	if(sum)										// add back the total
	{
		vn.Add(vsRowVals.GetSize());
		vsRowVals.Add(_L("Total"));
	}
	mm.ReorderRowWise(vn);
	
	Column cvRow = iw.Columns(nvRow);
	_update_output_report(rd, mm, vsColVals, cvRow.GetLongName(), vsRowVals, cvRow.GetUID(true));
	///End CrossTab_CALCULATE_ROW_TOTAL_AND_COLUMN_TOTAL_AND_USE_ReportData_AS_OUTPUT
		
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int wpivot_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return wpivot_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	trGetN.data.Show = trGetN.method.nVal > 0;
	trGetN.sort_total.Show = trGetN.total.nVal;
	trGetN.zero.Show = trGetN.method.nVal!=0;			///Kyle 08/19/2009 DISABLE_Show_Zeros_when_Empty_ON_COUNT_SELECTED
	
	///------ Folger 06/29/09 BETTER_ERROR_CHECKING_FOR_PIVOT_TABLE
	int		nErr = 0;
	if ( 0 != (nErr = _check_input_data(trGetN)) )
	{
		strErrMsg = nErr;
		bOKEnable = false;
	}
	///------ End BETTER_ERROR_CHECKING_FOR_PIVOT_TABLE
	return true;	

}

int wpivot_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return -1;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void wpivot_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	///------ Folger 06/29/09 BETTER_ERROR_CHECKING_FOR_PIVOT_TABLE
	if ( is_xf_startup(nGetNDialog, dwCntrl) && 0 == nGetNDialog )
	{
		if ( 0 != _check_input_data(trGetN) )
		{
			nRet = XFEVT_PROCEED_WITH_DLG;
			return;
		}
	}
	///------ End BETTER_ERROR_CHECKING_FOR_PIVOT_TABLE
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int wpivot_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
