How to easily create an Excel UDF with VSTO Add-in project

前端 未结 4 2119
日久生厌
日久生厌 2020-12-25 13:22

What I am trying to do is to create User Defined Functions (UDFs) for Excel using VSTO’s C# “Excel 2007 Add-in”-project type (since I just want to generate some general UDFs

4条回答
  •  没有蜡笔的小新
    2020-12-25 13:47

    As far as I know, you cannot directly create UDFs in VSTO.

    See Paul Stubbs' article How to create Excel UDFs in VSTO managed code where he uses a VBA add-in to expose VBA UDFs, which in turn call his Managed UDFs written in VSTO.

    You can use managed code to create UDFs, however, when not using VSTO. See Eric Carter's article Writing user defined functions for Excel in .NET on how to do this.

    As for VSTO's execution speed, I think you'll find it fine for virtually all tasks. Looping through cells, however, which is already Excel's weak-point, might be painfully slow, depending on what you are doing. Try to execute things in batch, as much as possible. For example, instead of looping through the cells one by one, return a two dimensional array of values from an area, process the array, and then pass it back to the range.

    To demonstrate, the following will return a two dimensional array of values from an area, process the values, and then pass the resulting array back to the original area in one shot:

    Excel.Range rng = myWorksheet.get_Range("A1:D4", Type.Missing);
    
    //Get a 2D Array of values from the range in one shot:
    object[,] myArray = (object[,])rng.get_Value(Type.Missing);
    
    // Process 'myArray' however you want here.
    // Note that the Array returned from Excel is base 1, not base 0.
    // To be safe, use GetLowerBound() and GetUpperBound:
    for (int row = myArray.GetLowerBound(0); row <= myArray.GetUpperBound(0); row++)
    {
        for (int column = myArray.GetLowerBound(1); column <= myArray.GetUpperBound(1); column++)
        {
            if (myArray[row, column] is double)
            {
                myArray[row, column] = (double)myArray[row, column] * 2;
            }
        }
    }
    
    // Pass back the results in one shot:
    rng.set_Value(Type.Missing, myArray);
    

    Hope this helps!

    Mike

提交回复
热议问题