views:

12

answers:

0

Hi,

This one is pretty weird ... I have a VSTO Excel 2007 project for C# where I create a bunch of worksheet functions that return object[,]. They all work fine but I wanted to return exception messages/stack traces when the function fails. When I tried this I got #VALUE!'s everywhere. So during troubleshooting the issue I created a simple worksheet function, public object[,] fillcells(int height, int width) { ... } (which just returns i*j to the ij'th cell -- see the implementation below),

as well but it worked fine on function failure and returned the error messages as expected. So I thought maybe it had something to do with the arugment list since some of my functions had more complex arguments. After a lot of trial and error with adding dummy string arguments (which only appear in the argument list and are never referenced within the function itself) I found out that

public object[,] fillcells(int height, int width,string a,string b,string c,string d) { ... }

does return error messages when an exception is thrown and so does

public object[,] fillcells(int height, int width,string aaaaaa,string bbbbbb,string cccccc,string dddddd) { ... }

but

public object[,] fillcells(int height, int width,string aaaaaaa,string bbbbbb,string cccccc,string dddddd) { ... }

does NOT!!! In general as long as the four string argument lengths add up to 24 or less then it works, but for 25 or greater it doesn't.

ie. the following collections of argument names

height,weight,aaaaaaa,bbbbb,cccccc,dddddd height,weight,aaaaaaaaaaaaaaaaaaaaa,b,c,d height,weight,aaaaaa,bbbbbbbb,ccccc,dddd etc. etc. work

but

height,weight,aaaaaaa,bbbbb,ccccccc,dddddd height,weight,aaaaaaaaaaaaaaaaaaaaaa,b,c,d height,weight,aaaaaa,bbbbbbbb,ccccccc,dddd etc. etc. do NOT work

But remember ALL the above combinations work fine when no exception is thrown and return the proper values. The only problem arises when an exception is thrown and an object[,] (which includes the exception message or stack trace, but can be anything) is returned from the catch{} block.

i.e. fillcells(3,4,"a","b","c","d") returns:
0 0 0 0
0 1 2 3
0 2 4 6

for any of the function signatures above, but

fillcells("three",4,"a","b","c","d") returns:

"System.OverflowException: Arithmetic operation resulted in an overflow. at RATAddIn.RATAddIn.fillcells(Int32 height, Int32 width, String a, String b, String c, String d) in C:\Temp\AutomationTest\AutomationTest\RATAddIn\RATAddIn.cs:line 134" 0 0 0
0 0 0 0
0 0 0 0

for signature:
public object[,] fillcells(int height, int width,string a,string b,string c,string d)
(as expected since I am passing a string for height to the expression 'i < height' where an int is required),

while

fillcells("three",4,"a","b","c","d") returns:

#VALUE! #VALUE! #VALUE! #VALUE!
#VALUE! #VALUE! #VALUE! #VALUE!
#VALUE! #VALUE! #VALUE! #VALUE!

for signature: public object[,] fillcells(int height, int width,string aaaaaaa,string bbbbbb,string cccccc,string dddddd).

I am at a complete loss as to what could possibly be going on here. Any suggestions would be appreciated.

Here is the acutal function:


using System;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Remoting;
using Extensibility;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
using Microsoft.Win32;

[GuidAttribute("85C88C21-EFD5-443E-8FB8-8B8522487FBC"), ProgId("RATAddIn.RATAddIn")] [ClassInterface(ClassInterfaceType.AutoDual),ComVisible(true)]
public class RATAddIn : Object,Extensibility.IDTExtensibility2
{

...

public object[,] fillcells(int height, int width, string a,
    string b,
    string c,
    string d)
{
    Range range = null;

    try
    {

    Application application = (Application)applicationObject;
    range = (Range)application.get_Caller(System.Type.Missing);

    object[,] resultObj = new object[height, width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
        resultObj[i, j] = i * j;
        }

    }

    return resultObj;
    }
    catch (Exception e)
    {
    try
    {
        object[,] error = new object[range.Rows.Count, range.Columns.Count];
        error[0, 0] = e.ToString();
        return error;
    }
    catch (Exception ex)
    {
        return new object[,] { { e.Message } };
    }

}

...

}

Thanks,

Jeff.