PRB: The last arguments' descriptions are the same as the description of an earlier argument
Reference: Q0008
Article last modified on 06-Jul-2002
The information in this article applies to:
- XLL+ for Visual Studio .NET - 3, 4.1, 4.2, 4.3.1
- XLL+ for Visual Studio 6 - 3, 4.1, 4.2, 4.3.1
- Excel - all versions
Problem
If a function description is long, then the last N arguments' descriptions are lost, and the description for the (N+1) from last argument is used instead.
Summary
- There is a limit (imposed by Excel, not by XLL+) to the total number of characters and words of description that can be associated with one function.
- The table below describes the limits.
- A checking function XlCheckFnStrings() is provided below, which can be used to check whether the strings provided are too long. This function can be called during initialisation to print warnings to the console.
String size limits
Arguments | Maximum characters in function description + argument list |
---|---|
8 | 452 |
9 | 429 |
10 | 238 |
11 | 238 |
12 | 216 |
13 | 180 |
14 | 163 |
15 | 156 |
16 | 142 |
16 | 123 |
18 | 111 |
19 | 99 |
Resolution
Size checking functions
Add the functions below to your code, before the InitInstance() event handler.
BOOL XlCheckFnStrings(CXllFn* pfn) { static int anLimits[] = { 8, 452, 9, 429, 10, 238, 11, 238, 12, 216, 13, 180, 14, 163, 15, 156, 16, 142, 17, 123, 18, 111, 19, 99, 0, 0 }; int i; int cChars = pfn->m_stArgNames.GetLength() + pfn->m_stHelpText.GetLength(); for (i = 0; anLimits[i]; i += 2) { if (pfn->m_astArgHelpText.GetSize() < anLimits[i]) return TRUE; if (pfn->m_astArgHelpText.GetSize() == anLimits[i]) { if (cChars <= anLimits[i+1]) return TRUE; else break; } } if (anLimits[i]) { TRACE("!!WARNING\n" " Function '%s': m_stArgNames.GetLength()=%d; m_stHelpText.GetLength()=%d\n" " Total = %d; limit for combined length = %d\n\n", (LPCSTR)pfn->m_stName, pfn->m_stArgNames.GetLength(), pfn->m_stHelpText.GetLength(), pfn->m_stArgNames.GetLength()+pfn->m_stHelpText.GetLength(), anLimits[i+1]); } else { TRACE("!!WARNING\n" " Function '%s': argument count > 19\n" " %d argument(s) will have no descriptions\n\n", (LPCSTR)pfn->m_stName, pfn->m_astArgHelpText.GetSize() - 19); } return FALSE; } BOOL XlCheckFnStrings(CXllApp* app, const char* pszExportedName) { CXllFn* pfn = app->FindFn(pszExportedName); if (pfn == 0) { TRACE("Function '%s' not found\n", pszExportedName); return FALSE; } return XlCheckFnStrings(pfn); } BOOL XlCheckFnStrings(CXllApp* app) { CXllApp::POSITION pos = app->GetStartFnPosition(); CXllFn* pfn; CString fnName; BOOL bAnyBad = FALSE; while (pos != NULL) { app->GetNextFnAssoc(pos, fnName, pfn); if (!XlCheckFnStrings(pfn)) bAnyBad = TRUE; } return !bAnyBad; }
Call the string size checker in your InitInstance() function
Add a call to XlCheckFnStrings(app) in your InitInstance() function, as in the example below:
BOOL CCarefulApp::InitInstance() { // Call the base class if ( !CXllApp::InitInstance() ) return FALSE; // Set the name of the library to the default value m_stName = m_pszDefName; // Add the statically defined function specifications AddStaticFns(); // TODO: Add your specialized code here #ifdef _DEBUG if (!XlCheckFnStrings(this)) { MessageBox(NULL, "At least one function will lose its argument descriptions.\n" "See the console Debug window for more information", "XLL+", MB_OK+MB_ICONEXCLAMATION); } #endif return TRUE; }