⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exceldriver.hpp

📁 financal instrument pricing using c
💻 HPP
字号:
// Excel driver class.
//
// Datasim Education BV (c) 2003
// 
// Modification dates:
// 23 July 2003 - MB - Started.
// 29 July 2003 - MB - Added support for PropertySets.
//					 - Writing chart data in vertical direction.
//					 - Added Instance() method which returns an ExcelDriver singleton.

// Office 2000 - local typelibraries.
#import "mso9.dll" no_namespace rename("DocumentProperties", "DocumentPropertiesXL") 
#import "vbe6ext.olb" no_namespace rename("Property", "PropertyVB") 
#import "Excel9.olb" rename("DialogBox", "DialogBoxXL") rename("RGB", "RBGXL") rename("DocumentProperties", "DocumentPropertiesXL")  no_dual_interfaces

// STL list class.
#include <list>
using namespace std;

// Datasim container classes.
#include "Vector.cpp"
#include "NumericMatrix.cpp"
#include "SimplePropertySet.cpp"

// Excel driver class definition.
// Contains functionality to add charts and matrices.
// Hides all COM details. COM exceptions are re-thrown
// as STL strings.
class ExcelDriver
{
private:
	// Private member data.
	Excel::_ApplicationPtr xl;		// Pointer to Excel.
	long curDataColumn;				// Current column of 'Chart Data'

	// Writes label and vector to cells in horizontal direction.
	void ToSheetHorizontal( Excel::_WorksheetPtr sheet,
					long sheetRow, long sheetColumn,
					string label,
					const Vector<double, int> & values )
	{
		// Get cells.
		Excel::RangePtr pRange=sheet->Cells;
	
		// First cell contains the label.
		Excel::RangePtr item = pRange->Item[sheetRow][sheetColumn];
		item->Value = label.c_str();
		sheetColumn++;

		// Next cells contain the values.
		for(int i=values.MinIndex(); i <= values.MaxIndex(); i++)
		{
			Excel::RangePtr item = pRange->Item[sheetRow][sheetColumn];
			item->Value = values[i];			
			sheetColumn++;
		}
	}

	// Writes label and vector to cells in vertical direction.
	void ToSheetVertical( Excel::_WorksheetPtr sheet,
					long sheetRow, long sheetColumn,
					string label,
					const Vector<double, int> & values )
	{
		// Get cells.
		Excel::RangePtr pRange=sheet->Cells;
	
		// First cell contains the label.
		Excel::RangePtr item = pRange->Item[sheetRow][sheetColumn];
		item->Value = label.c_str();
		sheetRow++;

		// Next cells contain the values.
		for(int i=values.MinIndex(); i <= values.MaxIndex(); i++)
		{
			Excel::RangePtr item = pRange->Item[sheetRow][sheetColumn];
			item->Value = values[i];			
			sheetRow++;
		}
	}

	// Throw COM error as string.
	void ExcelDriver::ThrowAsString( _com_error & error )
	{
		bstr_t description = error.Description();
		if( !description )
		{
			description = error.ErrorMessage();
		}
		throw string(description);
	}

	// Returns row from matrix as vector.
	Vector <double, int> createVector(const Matrix<double,int>& mat, int row)
	{
		int nCols = mat.Columns();

		Vector<double, int> result (nCols, mat.MinColumnIndex());
		for (int i = mat.MinColumnIndex(); i <= mat.MaxColumnIndex(); i++)
		{
			result[i] = mat(row, i);
		}

		return result;
	}

public:
	// Constructor. Starts Excel in invisible mode.
	ExcelDriver()
		: curDataColumn(1)
	{
		try
		{
			// Initialize COM Runtime Libraries.
			CoInitialize(NULL);

			// Start excel application.
			xl.CreateInstance(L"Excel.Application");
			xl->Workbooks->Add((long) Excel::xlWorksheet);

			// Rename "Sheet1" to "Chart Data".
			Excel::_WorkbookPtr pWorkbook = xl->ActiveWorkbook;
			Excel::_WorksheetPtr pSheet = pWorkbook->Worksheets->GetItem("Sheet1");
			pSheet->Name = "Chart Data";
		}
		catch( _com_error & error )
		{
			ThrowAsString(error);
		}
	}

	// Destructor.
	virtual ~ExcelDriver()
	{
		// Undo initialization of COM Runtime Libraries.
		CoUninitialize();
	}

	// Access to single, shared instance of ExcelDriver (singleton).
	static ExcelDriver & Instance()
	{
		static ExcelDriver singleton;
		return singleton;
	}

	// Create chart with a number of functions. The arguments are:
	//  x:			vector with input values
	//  labels:		labels for output values
	//  vectorList: list of vectors with output values.
	//  chartTitle:	title of chart
	//  xTitle:		label of x axis
	//  yTitle:		label of y axis
	void CreateChart(const Vector<double, int> & x, const list<string> & labels, const list<Vector<double, int> > & vectorList, 
					const std::string& chartTitle, const std::string& xTitle = "X", const std::string& yTitle = "Y")
	{
		try
		{
			// Check # labels vs. # vectors.
			if( labels.size() != vectorList.size() )
			{
				throw "Number of labels must equal number of vectors.";
			}

			// Activate sheet with numbers.
			Excel::_WorkbookPtr pWorkbook = xl->ActiveWorkbook;
			Excel::_WorksheetPtr pSheet = pWorkbook->Worksheets->GetItem("Chart Data");
			
			// Calculate range with source data.
			// The first row contains the labels shown in the chart's legend.
			long beginRow = 1;
			long beginColumn = curDataColumn;
			long endRow = x.Size() + 1;								// +1 to include labels.
			long endColumn = beginColumn + vectorList.size();		// 1st is input, rest is output.

			// Write label + input values to cells in vertical direction.
			ToSheetVertical(pSheet, 1, curDataColumn, xTitle, x);		// X values.
			curDataColumn++;

			// Write label + output values to cells in vertical direction.
			list<Vector<double, int> >::const_iterator vectorIt;
			list<string>::const_iterator labelIt = labels.begin();
			for( vectorIt = vectorList.begin(); vectorIt != vectorList.end(); vectorIt++ )
			{
				// Get label and row index.
				string label = *labelIt;
				
				// Add label + output values to Excel.
				ToSheetVertical(pSheet, 1, curDataColumn, label, *vectorIt);

				// Advance row and label.
				curDataColumn++;
				labelIt++;
			}			
			
			// Create range objects for source data.
			Excel::RangePtr pBeginRange = pSheet->Cells->Item[beginRow][beginColumn];
			Excel::RangePtr pEndRange = pSheet->Cells->Item[endRow][endColumn];
			Excel::RangePtr pTotalRange = pSheet->Range[(Excel::Range*)pBeginRange][(Excel::Range*)pEndRange];
			
			// Create the chart and sets its type
			Excel::_ChartPtr pChart=xl->ActiveWorkbook->Charts->Add();
			pChart->ChartWizard((Excel::Range*)pTotalRange, (long)Excel::xlXYScatter, 6L, (long)Excel::xlColumns, 1L, 1L, true, chartTitle.c_str(), xTitle.c_str(), yTitle.c_str());
			pChart->ApplyCustomType(Excel::xlXYScatterSmooth);
			pChart->Name = chartTitle.c_str();

			// Make all titles visible again. They were erased by the ApplyCustomType method.
			pChart->HasTitle=true;
			pChart->ChartTitle->Text=chartTitle.c_str();

			Excel::AxisPtr pAxis = pChart->Axes((long)Excel::xlValue, Excel::xlPrimary);
			pAxis->HasTitle = true;
			pAxis->AxisTitle->Text = yTitle.c_str();
			
			pAxis=pChart->Axes((long)Excel::xlCategory, Excel::xlPrimary);
			pAxis->HasTitle = true;
			pAxis->AxisTitle->Text = xTitle.c_str();

			// Add extra row space to make sheet more readable.
			curDataColumn++;
		}
		catch( _com_error & error )
		{
			ThrowAsString(error);
		}
	}

    // Create chart with a number of functions. The arguments are:
	//  x:			vector with input values
	//  y:			vector with output values.
	//  chartTitle:	title of chart
	//  xTitle:		label of x axis
	//  yTitle:		label of y axis
	void CreateChart(const Vector<double, int> & x, const Vector<double, int> & y, const std::string& chartTitle, const std::string& xTitle = "X", const std::string& yTitle = "Y")
	{ 
		// Create list with single function and single label.
		list<Vector<double, int> > functions;
		list<string> labels;
		functions.push_back(y);
		labels.push_back(chartTitle);
		CreateChart(x, labels, functions, chartTitle, xTitle, yTitle);
	}

	// Add Matrix to the spreadsheet with row and column labels.
	void AddMatrix(string name, const NumericMatrix<double, int> & matrix, const list<string> & rowLabels, const list<string> & columnLabels)
	{
		// Check label count vs. matrix.
		if( matrix.Columns() != columnLabels.size() )
		{
			throw "Count mismatch between # matrix columns and # column labels";
		}
		if( matrix.Rows() != rowLabels.size() )
		{
			throw "Count mismatch between # matrix rows and # row labels";
		}

		// Add sheet.
		Excel::_WorkbookPtr pWorkbook = xl->ActiveWorkbook;
		Excel::_WorksheetPtr pSheet = pWorkbook->Worksheets->Add();
		pSheet->Name = name.c_str();

		// Current indeces in spreadsheet.
		long sheetRow = 1;
		long sheetColumn = 1;
				
		// Add column labels starting at column 2.
		sheetColumn = 2;
		Excel::RangePtr pRange=pSheet->Cells;
		list<string>::const_iterator columnLabelIt;
		for(columnLabelIt = columnLabels.begin(); columnLabelIt != columnLabels.end(); columnLabelIt++)
		{
			Excel::RangePtr item = pRange->Item[sheetRow][sheetColumn];
			item->Value = columnLabelIt->c_str();
			sheetColumn++;
		}

		// Add row labels + values.
		sheetColumn = 1;
		sheetRow = 2;
		list<string>::const_iterator rowLabelIt = rowLabels.begin();
		for( int r = matrix.MinRowIndex(); r <= matrix.MaxRowIndex(); r++ )
		{
			Vector<double, int>	row = createVector(matrix, r);
			ToSheetHorizontal(pSheet, sheetRow, sheetColumn, *rowLabelIt, row);
			rowLabelIt++;
			sheetRow++;
		}
	}

	// Add PropertySet.
	void AddPropertySet(const SimplePropertySet<string, double> & pset)
	{
		// Add sheet.
		Excel::_WorkbookPtr pWorkbook = xl->ActiveWorkbook;
		Excel::_WorksheetPtr pSheet = pWorkbook->Worksheets->Add();
		pSheet->Name = L"Input";

		// Add properties to cells.
		Excel::RangePtr pRange = pSheet->Cells;
		long row = 1;
		for(SimplePropertySet<string, double>::const_iterator it = pset.Begin(); it != pset.End(); ++it, ++row)
		{
			// Set name and value.
			pRange->Item[row][(long)1] = it->name().c_str();
			pRange->Item[row][(long)2] = (*it) ();
		}
	}

	// Get PropertySet. Reads all properties from top to bottom.
	// The properties must be present in the given property set.
	void GetPropertySet(SimplePropertySet<string, double> & pset)
	{
		// Get input sheet.
		Excel::_WorkbookPtr pWorkbook = xl->ActiveWorkbook;
		Excel::_WorksheetPtr pSheet = pWorkbook->Worksheets->GetItem("Input");
		
		// Get values from cells.
		Excel::RangePtr pRange = pSheet->Cells;
		long row = 1;
		while(true)
		{
			// Get name from first column.
			long myCol = 1;
			_bstr_t bstrName = pRange->Item[row][myCol];
			string name = bstrName;
			if( name != string("") )
			{
				// Get value from second column.
				myCol = 2;
				double value = (double)pRange->Item[row][myCol];
				pset.set(name, value);
			}
			else
			{
				break;
			}
			++row;
		}
	}

	// Make Excel window visible.
	void MakeVisible( bool b = true )
	{
		// Make excel visible.
		xl->Visible = b ? VARIANT_TRUE : VARIANT_FALSE;
	}
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -