XLL插件开发 – Excel SDKfunction问题

目前,我正在开发Excel 2010 2010的Excel加载项。不幸的是,微软的文档很less(或者我目前还没有看到)。 我达到了我的加载项被加载到Excel的内部,我可以从加载项的菜单中调用一个函数。 在里面,我尝试收集所有的表名,但每次调用函数都会得到不同的结果。 正确的名称总是返回,但它们被改变“奇怪”的字符包围。

相应的代码:

LPXLOPER12 GetWorkbook(void){ LPXLOPER12 workbooksheets=new XLOPER12,xworkbookname = new XLOPER12; memset(xworkbookname,0,sizeof(XLOPER12)); memset(workbooksheets,0,sizeof(XLOPER12)); Excel12f(xlfGetDocument,xworkbookname,1,TempInt12(88)); Excel12f(xlfGetWorkbook,workbooksheets,2,TempInt12(1),xworkbookname); return 0; 

}

你还没有在这里提供很多信息,但我会猜测。

由于计算机使用数字,所以必须有关于文本如何表示的约定。 C编程语言使用的一个惯例是说“文本的第一个字符在第一个存储位置,并且文本一直持续到你敲击一个值为0的字节/字”。 既然你用C语言写作,我想这就是你的期望。

但是微软最初并没有用C语言开发Excel,他们是在Pascal开发的。 Pascal使用的惯例是“第一个内存位置包含文本的长度,而实际文本从第二个内存位置开始,进入与长度所指定的内存位置一样多的位置,没有终止0.”

实际上MSDN网站上有很多可用的文档,例如http://msdn.microsoft.com/en-us/library/aa730920%28v=office.12%29.aspx

特别是,他们有一个graphics(和示例代码),显示您需要使用哪些例程在Pascalstring和Cstring之间进行转换。

尝试http://xll.codeplex.com 。 它会让你的生活更轻松。

正如AnotherParker所暗示的那样,xlfGetWorkbook将Sheet名称作为Length前缀string返回,所以要在函数中使用它,需要将其转换为空分隔string。

此外,xlfGetWorkbook在[]括号中将工作簿名称作为工作表名称的前缀,因此您需要将其删除以获取实际的工作表名称。

下面是C中的一个完整的工作示例,没有使用任何flavor的框架,它在Activesheet的第一列中输出Sheet名称。

 int __stdcall ListSheetsD (void) { static XLOPER12 xWorkbook; XLOPER12 xRef, xNumParm, xAutoFit, xFalse, xlCell[10], xlArray; int rc, i, iSheets; size_t fullnamelen, sheetnamelen; wchar_t *fullname, *sheetname; XCHAR *ptr; OLECHAR buffer[100]; OLECHAR *function = L"ListSheetsD"; xNumParm.xltype = xltypeNum; xNumParm.val.num = 1; rc = Excel12 ( xlfGetWorkbook, (LPXLOPER12)&xWorkbook, 1, (LPXLOPER12)&xNumParm); if ( rc != xlretSuccess ) { swprintf ( buffer, 100, L"xlfGetWorkbook. rc=%d", rc ); MessageBox (NULL, buffer, function, MB_OK | MB_SETFOREGROUND ); } //Get Number of Sheets iSheets = xWorkbook.val.array.columns; for ( i = 0; i < iSheets; i++ ) { if ( i < 10 ) { //Pickup Sheet Name (format: [Book.xls]Sheet1) & set it up as a Null Delimited String fullnamelen = xWorkbook.val.array.lparray[i].val.str[0]; fullname = (wchar_t *) malloc ( (fullnamelen + 2) * sizeof (wchar_t) ); memcpy (fullname, (xWorkbook.val.array.lparray[i].val.str + 1), (fullnamelen) * sizeof(wchar_t)); fullname[fullnamelen] = L'\0'; //Extract Sheet Name (format: Sheet1) & set it up as a Length Prefixed String sheetname = (wchar_t *) malloc ( (fullnamelen + 2) * sizeof (wchar_t) ); ptr = wcschr (fullname, L']'); sheetnamelen = wcslen (ptr); wcscpy ( sheetname, ptr ); sheetname[0] = sheetnamelen; //Setup Output Row xlCell[i].xltype = xltypeStr; xlCell[i].val.str = sheetname; free (fullname); } } if ( i > 10 ) i = 10; xlArray.xltype = xltypeMulti; xlArray.val.array.rows = i; xlArray.val.array.columns = 1; xlArray.val.array.lparray = &xlCell[0]; xRef.xltype = xltypeSRef; xRef.val.sref.count = 1; xRef.val.sref.ref.rwFirst = 0; xRef.val.sref.ref.rwLast = i - 1; xRef.val.sref.ref.colFirst = 0; xRef.val.sref.ref.colLast = 0; rc = Excel12 ( xlSet, 0, 2, (LPXLOPER12)&xRef, (LPXLOPER12)&xlArray ); if ( rc != xlretSuccess ) { swprintf ( buffer, 100, L"xlSet. Error=%d", rc ); MessageBox (NULL, buffer, function, MB_OK | MB_SETFOREGROUND ); } rc = Excel12 (xlFree, NULL, 2, &xWorkbook, &xlArray ); if ( rc != xlretSuccess ) { swprintf ( buffer, 100, L"xlFree. rc=%d", rc ); MessageBox (NULL, buffer, function, MB_OK | MB_SETFOREGROUND ); } rc = Excel12 ( xlcSelect, 0, 1, (LPXLOPER12)&xRef ); if ( rc != xlretSuccess ) { swprintf ( buffer, 100, L"xlcSelect. rc=%d", rc ); MessageBox (NULL, buffer, function, MB_OK | MB_SETFOREGROUND ); } xAutoFit.xltype = xltypeNum; xAutoFit.val.num = 3; xFalse.xltype = xltypeBool; xFalse.val.xbool = 0; rc = Excel12 ( xlcColumnWidth, 0, 4, &xNumParm, (LPXLOPER12)&xRef, &xFalse, &xAutoFit ); if ( rc != xlretSuccess ) { swprintf ( buffer, 100, L"xlcColumnWidth. rc=%d", rc ); MessageBox (NULL, buffer, function, MB_OK | MB_SETFOREGROUND ); } return 1; }