BOOL StartAddinClrHost() { TCHAR buffer[256] = { 0 }; ::GetModuleFileName(Constants::Dll, buffer, sizeof(buffer) / sizeof(WCHAR)); // trim off file name int pos = wcslen(buffer); while (--pos >= 0 && buffer[pos] != '\\'); buffer[pos] = 0; #if CLR2 static LPCTSTR clrVersion = L"v2.0.50727"; #elif CLR4 static LPCTSTR clrVersion = L"v4.0.30319"; #endif ClrRuntimeHost::Start(clrVersion, L"ExcelMvc", buffer); BOOL result = ClrRuntimeHost::TestAndDisplayError(); if (result) { // create and remove a book just to get Excel registered with the ROT Excel12f(xlcEcho, 0, 1, (LPXLOPER12) TempBool12(false)); Excel12f(xlcNew, 0, 1, (LPXLOPER12) TempInt12(5)); Excel12f(xlcWorkbookInsert, 0, 1, (LPXLOPER12) TempInt12(6)); Excel12f(xlcFileClose, 0, 1, (LPXLOPER12) TempBool12(false)); Excel12f(xlcEcho, 0, 1, (LPXLOPER12) TempBool12(true)); // attach to ExcelMVC ClrRuntimeHost::CallStaticMethod(L"ExcelMvc.Runtime.Interface", L"Attach"); result = ClrRuntimeHost::TestAndDisplayError(); } return result; }
// Called by Microsoft Office Excel whenever the user activates the XLL during // an Excel session by using the Add-In Manager. This function is not called // when Excel starts up and loads a pre-installed add-in. __declspec(dllexport) int WINAPI xlAutoAdd(void) { const size_t bufsize = 255; const size_t dllsize = 100; LPWSTR szBuf = (LPWSTR)malloc(bufsize * sizeof(WCHAR)); LPWSTR szDLL = (LPWSTR)malloc(dllsize * sizeof(WCHAR)); XLOPER12 xDLL; // Get the name of the XLL Excel12f(xlGetName, &xDLL, 0); wcsncpy_s(szDLL, dllsize, xDLL.val.str + 1, xDLL.val.str[0]); szDLL[xDLL.val.str[0]] = (WCHAR)NULL; // Display dialog swprintf_s((LPWSTR)szBuf, 255, L"Adding %s\nBuild %hs - %hs", szDLL, __DATE__, __TIME__); Excel12f(xlcAlert, 0, 2, TempStr12(szBuf), TempInt12(2)); // Free the XLL filename Excel12f(xlFree, 0, 1, (LPXLOPER12)&xDLL); free(szBuf); free(szDLL); return 1; }
// getNumberOfRows // Helper function to get the number of rows in an XLOPER12. int getNumberOfRows(LPXLOPER12 px) { int n = -1; XLOPER12 xMulti; switch (px->xltype) { case xltypeNum: n = 1; break; case xltypeRef: case xltypeSRef: case xltypeMulti: // Multi value, coerce it into a readable form if (Excel12f(xlCoerce, &xMulti, 2, px, TempInt12(xltypeMulti)) != xlretUncalced) { n = xMulti.val.array.rows; } Excel12f(xlFree, 0, 1, (LPXLOPER12)&xMulti); break; } return n; }
// Called by Microsoft Office Excel when the Add-in Manager is invoked for the // first time in an Excel session. This function is used to provide the Add-In // Manager with information about your add-in. _declspec(dllexport) LPXLOPER12 WINAPI xlAddInManagerInfo12(LPXLOPER12 xAction) { LPXLOPER12 pxInfo; XLOPER12 xIntAction; pxInfo = (LPXLOPER12)malloc(sizeof(XLOPER12)); Excel12f(xlCoerce, &xIntAction, 2, xAction, TempInt12(xltypeInt)); if (xIntAction.val.w == 1) { LPWSTR szDesc = (LPWSTR)malloc(50 * sizeof(WCHAR)); swprintf_s(szDesc, 50, L"%s", L"\020Example CUDA XLL"); pxInfo->xltype = xltypeStr; pxInfo->val.str = szDesc; } else { pxInfo->xltype = xltypeErr; pxInfo->val.err = xlerrValue; } pxInfo->xltype |= xlbitDLLFree; return pxInfo; }
int check_excel_array(const LPXLOPER12 excelArray, LPXLOPER12 coerced, const T&... args) { switch (excelArray->xltype) { case xltypeRef: case xltypeSRef: case xltypeMulti: break; default: Excel12f(xlcAlert, 0, 1, TempStr12(L"Expected a N-columns excel range")); return xlretInvXloper; } if (xlretUncalced == Excel12f(xlCoerce, coerced , 2, excelArray, TempInt12(xltypeMulti) ) ) return xlretUncalced; if (coerced->val.array.columns != sizeof...(args)) { //throw std::runtime_error("Wrong number of dimensions, expected:" + std::to_string(sizeof...(args))); Excel12f(xlcAlert, 0, 1, TempStr12(L"Wrong number of dimensions")); return xlretInvXloper; } return 0; }
// The Excel Add-in Manager calls xlAddInManagerInfo12 function // to find the long name of the add-in. __declspec(dllexport) LPXLOPER12 WINAPI xlAddInManagerInfo12(LPXLOPER12 xAction) { static XLOPER12 xInfo, xIntAction; // This code coerces the passed-in value to an integer. Excel12f(xlCoerce, &xIntAction, 2, xAction, TempInt12(xltypeInt)); if (xIntAction.val.w == 1) { // Note that the string is length-prefixed in octal. xInfo.xltype = xltypeStr; xInfo.val.str = L"SimpleXll2007"; } else { xInfo.xltype = xltypeErr; xInfo.val.err = xlerrValue; } // Word of caution: returning static XLOPERs/XLOPER12s is // not thread-safe. For UDFs declared as thread-safe, use // alternate memory allocation mechanisms. return(LPXLOPER12) &xInfo; }
BOOL __stdcall xlAutoOpen(void) { if (++AutoOpenCount > 1) { //MessageBox(0, L"Test", L"Test", MB_OK); return TRUE; } static XLOPER12 xDLL; Excel12f(xlGetName, &xDLL, 0); int count = sizeof(rgFuncs) / (sizeof(rgFuncs[0][0]) * NumberOfParameters); for (int idx = 0; idx < count; idx++) { int macroType = wcscmp(rgFuncs[idx][4], L"0") == 0 ? 0 : 1; Excel12f ( xlfRegister, 0, 12, (LPXLOPER12) &xDLL, (LPXLOPER12) TempStr12(rgFuncs[idx][0]), (LPXLOPER12) TempStr12(rgFuncs[idx][1]), (LPXLOPER12) TempStr12(rgFuncs[idx][2]), (LPXLOPER12) TempStr12(rgFuncs[idx][3]), (LPXLOPER12) TempInt12(macroType), (LPXLOPER12) TempStr12(rgFuncs[idx][5]), (LPXLOPER12) TempStr12(rgFuncs[idx][6]), (LPXLOPER12) TempStr12(rgFuncs[idx][7]), (LPXLOPER12) TempStr12(rgFuncs[idx][8]), (LPXLOPER12) TempStr12(rgFuncs[idx][9]), (LPXLOPER12) TempStr12(rgFuncs[idx][10]) ); } Excel12f(xlFree, 0, 1, (LPXLOPER12) &xDLL); return StartAddinClrHost(); }
// extractData // Helper function for to extract the data from an XLOPER12 into an // array of n floats. If the XLOPER12 contains a single value then it // is replicated into all n elements of the array. Otherwise the // XLOPER12 must contain exactly n rows and one column and the data // is copied directly into the array. int extractData(LPXLOPER12 px, int n, float *pdst, int *error) { int ok = 1; int i; XLOPER12 xMulti; switch (px->xltype) { case xltypeNum: // If there is only one value, copy it into each element of // the array. for (i = 0 ; i < n ; i++) { pdst[i] = (float)px->val.num; } break; case xltypeRef: case xltypeSRef: case xltypeMulti: // Multi value, coerce it into a readable form if (Excel12f(xlCoerce, &xMulti, 2, px, TempInt12(xltypeMulti)) != xlretUncalced) { // Check number of columns if (xMulti.val.array.columns != 1) ok = 0; if (ok) { // Check number of rows if (xMulti.val.array.rows == 1) { for (i = 0 ; i < n ; i++) { pdst[i] = (float)xMulti.val.array.lparray[0].val.num; } } else if (xMulti.val.array.rows == n) { // Extract data into the array for (i = 0 ; ok && i < n ; i++) { switch (xMulti.val.array.lparray[i].xltype) { case xltypeNum: pdst[i] = (float)xMulti.val.array.lparray[i].val.num; break; case xltypeErr: *error = xMulti.val.array.lparray[i].val.err; ok = 0; break; case xltypeMissing: *error = xlerrNum; ok = 0; break; default: *error = xlerrRef; ok = 0; } } } else ok = 0; } } else ok = 0; Excel12f(xlFree, 0, 1, (LPXLOPER12)&xMulti); break; default: ok = 0; } return ok; }