For types without built-in FCell converter you can create your own conversion function.

If you have access to the source code which defines the type you can specify your conversion functions as explicit casts.

If you do not have access to the source code you will need to create static conversion methods marked with [XlConverter] attribute.

Explicit cast converters

Create explicit cast methods to convert your type from/to XlData or XlValue

Note

If converter to/from XlValue exists, you can automatically use aggregate types, e.g. arrays, based on your type. See previous chapter.

F# Copy imageCopy
namespace Test
module Udfs =
    open FCell.ManagedXll
    open System

    type MyVector(data : float[]) =
        let _data = data
        member this.Data = _data
        static member op_Explicit(v : MyVector) : XlData = XlData.op_Explicit v.Data
        static member op_Explicit(v : MyVector) : XlValue =
            if v.Data.Length = 1 then
                XlValue.op_Explicit(v.Data.[0])
            else raise (new ArgumentException())

    //you can now use this function in Excel array formula
    let createVector n v = new MyVector(Array.create n v)
C# Copy imageCopy
using FCell.ManagedXll;
using System;
using System.Linq;
namespace Test
{
    public class MyVector
    {
        private double[] _data;

        public MyVector(double[] data)
        {
            _data = data;
        }

        public double[] Data
        {
            get
            {
                return _data;
            }
        }

        public static explicit operator XlData(MyVector v)
        {
            return (XlData)v.Data;
        }

        public static explicit operator XlValue(MyVector v)
        {
            if (v.Data.Length == 1)
            {
                return (XlValue)v.Data[0];
            }
            throw new ArgumentException("");
        }
    }

    public class CSharpUdfs
    {
        //you can now use this function in Excel array formula
        public static MyVector CreateVector(int n, double v)
        {
            var res = Enumerable.Range(0, n).Select(x => v).ToArray();
            return new MyVector(res);
        }
    }
}
Visual Basic Copy imageCopy
Imports System
Imports System.Linq
Imports FCell.ManagedXll

Namespace Test
    Public Class MyVector
        Private _data() As Double

        Public Sub New(ByVal data() As Double)
            _data = data
        End Sub

        ReadOnly Property Data() As Double()
            Get
                Return _data
            End Get
        End Property

        Public Shared Narrowing Operator CType(ByVal v As MyVector) As XlData
            Return CType(v.Data, XlData)
        End Operator

        Public Shared Narrowing Operator CType(ByVal v As MyVector) As XlValue
            If v.Data.Length = 1 Then
                Return CType(v.Data(0), XlValue)
            Else
                Throw New ArgumentException("")
            End If
        End Operator
    End Class

    Public Class VBUdfs
        'you can now use this function in Excel array formula
        Public Shared Function CreateVector(ByVal n As Integer, ByVal v As Double) As MyVector
            Dim res = Enumerable.Range(0, n).Select(Function(x) v).ToArray()
            Return New MyVector(res)
        End Function
    End Class
 End Namespace

[XlConverter] based converters

Create methods marked with [XlConverter] to convert your type from/to XlData or XlValue

Note

[XlConverter] based converters only apply to UDFs defined in the same assembly.

Note

If converter to/from XlValue exists, you can automatically use aggregate types, e.g. arrays, based on your type. See previous chapter.

In the code example below we assume that MyVector (see code above) is defined in another assembly:

F# Copy imageCopy
namespace Test
module Udfs =
    open FCell.ManagedXll
    open System
    open MyVectorNamespace

    [<XlConverter>]
    let convertMyVectorToXlData (v : MyVector) : XlData = XlData.op_Explicit v.Data

    [<XlConverter>]
    let convertMyVectorToXlValue (v : MyVector) : XlValue =
        if v.Data.Length = 1 then
            XlValue.op_Explicit(v.Data.[0])
        else raise (new ArgumentException())

    //you can now use this function in Excel array formula
    let createVector n v = new MyVector(Array.create n v)
C# Copy imageCopy
using FCell.ManagedXll;
using System;
using System.Linq;
using MyVectorNamespace;
namespace Test
{
    public class CSharpUdfs
    {
        public static XlData ConvertMyVectorToXlData(MyVector v)
        {
            return (XlData)v.Data;
        }

        public static XlValue ConvertMyVectorToXlValue(MyVector v)
        {
            if (v.Data.Length == 1)
            {
                return (XlValue)v.Data[0];
            }
            throw new ArgumentException("");
        }


        //you can now use this function in Excel array formula
        public static MyVector CreateVector(int n, double v)
        {
            var res = Enumerable.Range(0, n).Select(x => v).ToArray();
            return new MyVector(res);
        }
    }
}
Visual Basic Copy imageCopy
Imports System
Imports System.Linq
Imports FCell.ManagedXll
Imports MyVectorNamespace

Namespace Test
    Public Class VBUdfs
        Public Shared Function ConvertMyVectorToXlData(ByVal v As MyVector) As XlData
            Return CType(v.Data, XlData)
        End Function

        Public Shared Function ConvertMyVectorToXlValue(ByVal v As MyVector) As XlValue
            If v.Data.Length = 1 Then
                Return CType(v.Data(0), XlValue)
            Else
                Throw New ArgumentException("")
            End If
        End Function

        'you can now use this function in Excel array formula
        Public Shared Function CreateVector(ByVal n As Integer, ByVal v As Double) As MyVector
            Dim res = Enumerable.Range(0, n).Select(Function(x) v).ToArray()
            Return New MyVector(res)
        End Function
    End Class
 End Namespace