# Configuration

Source: https://docs.interop.io/adapters/ms-office/excel/configuration/index.html

## Overview

The Excel Adapter can be configured via the following files:

| File | Description |
|------|-------------|
| `GlueXl-AddIn64.xll.config` | Located in the Excel Adapter installation folder. Specifies the location of the main configuration file (`ioxl2_config.json`) and contains the [logging](#logging) settings. For the 32-bit version of the Excel Adapter, the file is called `GlueXl-AddIn.xll.config`. |
| `ioxl2_config.json` | Main configuration file containing the [Excel Adapter settings](#excel_adapter_settings). |
| `xl-service-configuration.json` | Optional file for defining [custom UDFs, keyboard shortcuts, menus, and custom task panes](#excel_service_configuration) which the Excel Adapter will create when Excel starts. |
| `custom-ioxl-ribbon.json` | Optional file for defining [custom Excel ribbon tabs](#ribbon-custom_tabs). |
| `ribbon-attributes-overrides.json` | Optional file for [overriding the attributes](#ribbon-attribute_overrides) of the Excel ribbon controls. |

By default, all JSON configuration files are located in the `%LocalAppData%/interop.io/io.Connect Desktop/UserData/<ENV>-<REGION>` folder, where `<ENV>-<REG>` represents the environment and region of **io.Connect Desktop** (e.g., `DEMO-INTEROP.IO`).

The paths to the configuration files can be absolute paths, can contain environment variables (e.g., `%LocalAppData%`), or can be URLs. If a file isn't found at the specified location, the Excel Adapter will search for a file with the same name in its installation folder.

## Excel Adapter Settings

To specify the location of the `ioxl2_config.json` file, use the `addinConfigPath` key in the `<appSettings>` section of the `GlueXl-AddIn64.xll.config` file:

```xml
<appSettings>
    <add key="addinConfigPath" value="%localappdata%/interop.io/io.Connect Desktop/UserData/DEMO-INTEROP.IO/ioxl2_config.json" />
</appSettings>
```

The `ioxl2_config.json` file has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"auto-init-glue"` | `string` | If this property is present (regardless of its value), the Excel Adapter will connect to io.Connect automatically when Excel starts. |
| `"custom-ribbon"` | `object[]` | Array of objects describing [custom Excel ribbon tabs](#ribbon-custom_tabs). Used only if `"custom-ribbon-path"` isn't specified. |
| `"custom-ribbon-path"` | `string` | Path or URL to a file containing [custom Excel ribbon tabs](#ribbon-custom_tabs). |
| `"disable-Feedback"` | `string` | If this property is present (regardless of its value), the "Feedback" button in the `interop.io` ribbon tab will be hidden. |
| `"disable-IOGlueXlTabId"` | `string` | If this property is present (regardless of its value), the `interop.io` ribbon tab will be hidden. Note that in this case, the [custom ribbon tabs](#ribbon-custom_tabs) won't be created either. |
| `"disable-ribbon"` | `string` | If this property is present (regardless of its value), the Excel Adapter won't add any tabs to the Excel ribbon. |
| `"excel-service-configuration"` | `string` | Path or URL to the [Excel service configuration](#excel_service_configuration) file. |
| `"excel-service-preference-app"` | `string` | Name of an interop-enabled app whose [app preferences](https://docs.interop.io/desktop/capabilities/app-preferences/overview/index.md) contain the [Excel service configuration](#excel_service_configuration). Used only if `"excel-service-configuration"` isn't specified. |
| `"IGlueExcelService-ns"` | `string` | Prefix for the names of the Interop methods registered by the Excel Adapter. Must match the prefix used by the [Excel API](https://docs.interop.io/adapters/ms-office/excel/excel-api/index.md#excel_service_operations-initialization). Defaults to `"T42.XL."`. The default `ioxl2_config.json` file sets this to `"IO.XL."`. |
| `"IGlueExcelService.InvocationTimeout"` | `number` | Timeout in milliseconds for executing Excel API operations. Defaults to `20000`. |
| `"IOGlueXlTabId-label"` | `string` | Label for the `interop.io` ribbon tab. Defaults to `"interop.io"`. |
| `"ioxl_invoke_target_await"` | `number` | Interval in milliseconds during which the [`IOXL_Invoke()`](https://docs.interop.io/adapters/ms-office/excel/udfs/index.md#sending_data-ioxl_invoke) and [`IOXL_SendData()`](https://docs.interop.io/adapters/ms-office/excel/udfs/index.md#sending_data-ioxl_senddata) UDFs will wait for the target Interop method to become available. Defaults to `5000`. |
| `"ribbon-attributes-overrides-path"` | `string` | Path or URL to a file containing [ribbon attribute overrides](#ribbon-attribute_overrides). |
| `"ribbon-preference-app"` | `string` | Name of an interop-enabled app whose [app preferences](https://docs.interop.io/desktop/capabilities/app-preferences/overview/index.md) contain ribbon settings. The settings stored in the app preferences override the respective settings in the `ioxl2_config.json` file. Used only if `"ribbon-wait-glue-init"` is specified. |
| `"ribbon-wait-glue-init"` | `number` | Interval in milliseconds to wait for the connection to io.Connect before loading the ribbon settings from the app specified in `"ribbon-preference-app"`. |
| `"volatile-udfs"` | `string[]` | Names of io.Connect UDFs for which to register [volatile versions](https://docs.interop.io/adapters/ms-office/excel/udfs/index.md#overview-volatile_udfs). |

Example `ioxl2_config.json` file:

```json
{
    "auto-init-glue": "",
    "IGlueExcelService-ns": "IO.XL.",
    "volatile-udfs": ["IOXL_Invoke", "IOXL_SendData", "IOXL_RaiseNotification"],
    "custom-ribbon-path": "%localappdata%/interop.io/io.Connect Desktop/UserData/DEMO-INTEROP.IO/custom-ioxl-ribbon.json",
    "excel-service-configuration": "%localappdata%/interop.io/io.Connect Desktop/UserData/DEMO-INTEROP.IO/xl-service-configuration.json"
}
```

## Excel Service Configuration

The Excel service configuration file allows you to define custom UDFs, keyboard shortcuts, context menus, ribbon menus, and [custom task panes](#custom_task_panes) which the Excel Adapter will create when Excel starts. You can achieve the same at runtime by using the [Excel API](https://docs.interop.io/adapters/ms-office/excel/excel-api/index.md).

To specify the location of the file, use the `"excel-service-configuration"` property of the [Excel Adapter settings](#excel_adapter_settings). Alternatively, you can store the Excel service configuration in the [app preferences](https://docs.interop.io/desktop/capabilities/app-preferences/overview/index.md) of an interop-enabled app and specify the name of the app in the `"excel-service-preference-app"` property.

The Excel service configuration file has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"CreateContextMenu"` | `object[]` | Array of objects describing [context menus](#excel_service_configuration-context_menus). |
| `"CreateCTP"` | `object[]` | Array of objects describing [custom task panes](#custom_task_panes). |
| `"CreateDynamicRibbonMenu"` | `object[]` | Array of objects describing [ribbon menus](#excel_service_configuration-ribbon_menus). |
| `"RegisterCallbackShortcut"` | `object[]` | Array of objects describing [keyboard shortcuts](#excel_service_configuration-keyboard_shortcuts). |
| `"RegisterUDF"` | `object[]` | Array of objects describing [custom UDFs](#excel_service_configuration-custom_udfs). |

### Custom UDFs

To define custom UDFs, use the `"RegisterUDF"` property. The code of the UDF must be written in C#. Use the `Args` array to access the arguments passed to the UDF (e.g., `Args[0]`) and a `return` statement to return the result to Excel:

```json
{
    "RegisterUDF": [
        {
            "UdfName": "IO_XL_DiscountedValue",
            "Imports": ["System.Math"],
            "Helpers": "double DiscountFactor(double rate, double periods) => Pow(1 + rate, -periods);",
            "Script": "return (double)Args[0] * DiscountFactor((double)Args[1] / 100.0, (double)Args[2]);",
            "Parameters": [
                { "Name": "futureValue", "Description": "Future cash flow amount." },
                { "Name": "ratePercent", "Description": "Annual discount rate (%)." },
                { "Name": "periods", "Description": "Number of periods." }
            ]
        }
    ]
}
```

The UDF can then be used in Excel like any other function:

```
=IO_XL_DiscountedValue(1000, 5, 3)
```

Each object in the `"RegisterUDF"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"Deps"` | `string[]` | Names of .NET assemblies required by the UDF code. |
| `"Helpers"` | `string` | C# code for helper methods that can be used in the UDF code. |
| `"HelpersPath"` | `boolean` | If `true`, the value of `"Helpers"` will be treated as a path or a URL to a file containing the helper code. Defaults to `false`. |
| `"Imports"` | `string[]` | Namespaces to import for the UDF code. |
| `"Parameters"` | `object[]` | Array of objects, each with a `"Name"` and a `"Description"` property, describing the UDF parameters. The parameter names and descriptions are displayed in the Excel Insert Function dialog. |
| `"Script"` | `string` | **Required.** C# code of the UDF. |
| `"ScriptPath"` | `boolean` | If `true`, the value of `"Script"` will be treated as a path or a URL to a file containing the UDF code. Defaults to `false`. |
| `"UdfName"` | `string` | **Required.** Name for the UDF. Must be unique. |

> ⚠️ *Note that custom UDFs can't be modified or removed while Excel is running.*

### Keyboard Shortcuts

To define keyboard shortcuts which will invoke an Interop method with the values of a specified range, use the `"RegisterCallbackShortcut"` property:

```json
{
    "RegisterCallbackShortcut": [
        {
            "range": { "range": "A1:B2" },
            "shortcut": "^+k",
            "subscriptionInfo": {
                "callbackEndpoint": "MyShortcutHandler",
                "callbackId": "shortcut1"
            }
        }
    ]
}
```

Each object in the `"RegisterCallbackShortcut"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"range"` | `object` | [Range](#excel_service_configuration-range_settings) whose values will be sent to the Interop method. |
| `"shortcut"` | `string` | **Required.** Keyboard shortcut in the format used by the Excel [`Application.OnKey`](https://learn.microsoft.com/en-us/office/vba/api/excel.application.onkey) method. For instance, `"^+k"` is `CTRL + SHIFT + K`. |
| `"subscriptionInfo"` | `object` | **Required.** [Callback settings](#excel_service_configuration-callbacks) for the Interop method to invoke when the shortcut is pressed. |

Besides the [common callback properties](#excel_service_configuration-callbacks), the Interop method will receive an `rng` property containing the values of the specified range.

> ⚠️ *Note that you can register up to 20 keyboard shortcuts.*

### Context Menus

To add custom items to the Excel cell context menu, use the `"CreateContextMenu"` property. When the user clicks the menu item, the specified Interop method will be invoked:

```json
{
    "CreateContextMenu": [
        {
            "caption": "Send to CRM",
            "toolTip": "Send the selected client to the CRM app",
            "menuPath": ["interop.io", "Actions"],
            "range": { "worksheet": "Clients", "range": "A2:A100" },
            "subscriptionInfo": {
                "callbackEndpoint": "SendToCRM",
                "selectionLimit": 10
            }
        }
    ]
}
```

Each object in the `"CreateContextMenu"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"caption"` | `string` | **Required.** Caption for the menu item. |
| `"menuPath"` | `string[]` | Captions of the parent submenus in which to place the menu item. If not specified, the menu item will be added to the top level of the context menu. |
| `"range"` | `object` | [Range](#excel_service_configuration-range_settings) in which the menu item will be available. If not specified, the menu item will be available in all cells of all workbooks. |
| `"subscriptionInfo"` | `object` | **Required.** [Callback settings](#excel_service_configuration-callbacks) for the Interop method to invoke when the menu item is clicked. |
| `"toolTip"` | `string` | Tooltip for the menu item. |

### Ribbon Menus

To add custom items to the "Dynamics" dropdown in the `interop.io` ribbon tab, use the `"CreateDynamicRibbonMenu"` property. When the user selects the item and clicks the "Execute Dynamic" button, the specified Interop method will be invoked:

```json
{
    "CreateDynamicRibbonMenu": [
        {
            "caption": "Refresh Prices",
            "toolTip": "Request the latest prices",
            "subscriptionInfo": {
                "callbackEndpoint": "RefreshPrices"
            }
        }
    ]
}
```

Each object in the `"CreateDynamicRibbonMenu"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"caption"` | `string` | **Required.** Caption for the menu item. |
| `"range"` | `object` | [Range](#excel_service_configuration-range_settings) in which the menu item will be enabled. Only the `"workbook"` and `"worksheet"` properties are taken into account. If not specified, the menu item will be enabled in all workbooks. |
| `"subscriptionInfo"` | `object` | **Required.** [Callback settings](#excel_service_configuration-callbacks) for the Interop method to invoke when the menu item is executed. |
| `"toolTip"` | `string` | Tooltip for the menu item. |

### Range Settings

The `"range"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"range"` | `string` | Excel range (e.g., `"A1:C10"`). |
| `"workbook"` | `string` | Name of an Excel workbook. |
| `"worksheet"` | `string` | Name of an Excel worksheet. |

### Callbacks

The `"subscriptionInfo"` object describes the Interop method to invoke when the user interacts with an Excel element created by the Excel Adapter. It has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"callbackApp"` | `string` | Name of an app (as specified in its definition) to target when invoking the Interop method. |
| `"callbackEndpoint"` | `string` | **Required.** Name of the [Interop method](https://docs.interop.io/desktop/capabilities/data-sharing/interop/overview/index.md) to invoke. |
| `"callbackId"` | `string` | Custom ID that will be passed to the Interop method. Use it to identify the Excel element that has invoked the Interop method. |
| `"callbackInstance"` | `string` | ID of an app instance to target when invoking the Interop method. |
| `"selectionLimit"` | `number` | Maximum number of selected cells whose values will be sent to the Interop method. If the user has selected more cells, no values will be sent. Defaults to `1`. |
| `"targetType"` | `"All"` \| `"Any"` | Set to `"All"` to invoke the Interop method on all servers that have registered it. Set to `"Any"` to invoke it only on the first available server. Defaults to `"All"`. |

The Interop method will receive an object with the following common properties:

| Property | Type | Description |
|----------|------|-------------|
| `activeCell` | `any` | Value of the active cell. |
| `activeCellAddress` | `string` | Address of the active cell (e.g., `"$A$2"`). |
| `callbackId` | `string` | The value of the `"callbackId"` property. |
| `origin` | `any` | Excel element that has invoked the Interop method. |
| `selection` | `any[]` | Values of the selected cells. Empty if the number of selected cells exceeds the value of `"selectionLimit"`. |
| `selectionAddress` | `string` | Address of the selection (e.g., `"$B$2:$B$3"`). |
| `selectionColumnCount` | `number` | Number of columns in the selection. |
| `selectionCount` | `number` | Number of selected cells. |
| `selectionRowCount` | `number` | Number of rows in the selection. |
| `subscriptionId` | `string` | ID of the Excel element (e.g., menu ID) that has invoked the Interop method. |
| `workbook` | `string` | Name of the active workbook. |
| `workbookPath` | `string` | Full path to the active workbook. |
| `worksheet` | `string` | Name of the active worksheet. |

## Ribbon

The Excel Adapter adds an `interop.io` tab to the Excel ribbon. You can add your own tabs to the Excel ribbon and modify the attributes of the existing ribbon controls.

### Custom Tabs

To define custom ribbon tabs, create a JSON file containing an array of tab objects and specify its location in the `"custom-ribbon-path"` property of the [Excel Adapter settings](#excel_adapter_settings). Alternatively, use the `"custom-ribbon"` property to define the tabs directly in the `ioxl2_config.json` file.

Each tab contains groups, and each group contains controls (buttons, boxes, button groups, and separators). When the user clicks a button, the Interop method specified in its `"callback"` property will be invoked:

```json
[
    {
        "type": "tab",
        "label": "My Tab",
        "controls": [
            {
                "type": "group",
                "label": "Actions",
                "controls": [
                    {
                        "type": "button",
                        "label": "Send Data",
                        "size": "large",
                        "imageMso": "HappyFace",
                        "callback": {
                            "callbackEndpoint": "SendData",
                            "callbackId": "send-data"
                        }
                    },
                    {
                        "type": "separator"
                    },
                    {
                        "type": "box",
                        "horizontal": false,
                        "controls": [
                            {
                                "type": "button",
                                "label": "Buy",
                                "callback": { "callbackEndpoint": "Buy" }
                            },
                            {
                                "type": "button",
                                "label": "Sell",
                                "callback": { "callbackEndpoint": "Sell" }
                            }
                        ]
                    }
                ]
            }
        ]
    }
]
```

Each ribbon object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"callback"` | `object` | [Callback settings](#excel_service_configuration-callbacks) for the Interop method to invoke when a button is clicked. Valid only for buttons. |
| `"controls"` | `object[]` | Child ribbon objects. Valid for tabs, groups, boxes, and button groups. |
| `"horizontal"` | `boolean` | If `true`, the controls in a box will be arranged horizontally. Valid only for boxes. Defaults to `true`. |
| `"id"` | `string` | ID for the ribbon object. If not specified, an ID will be generated automatically. |
| `"imageMso"` | `string` | Name of a built-in Office icon to display on a button (e.g., `"HappyFace"`). |
| `"label"` | `string` | Label for the ribbon object. |
| `"screenTip"` | `string` | Tooltip title for a button. |
| `"size"` | `"normal"` \| `"large"` | Size of a button. |
| `"superTip"` | `string` | Tooltip description for a button. |
| `"tag"` | `string` | Custom data for a button. |
| `"type"` | `string` | **Required.** Type of the ribbon object. Can be `"tab"`, `"group"`, `"box"`, `"buttonGroup"`, `"button"`, or `"separator"`. Tabs can contain only groups. Button groups can contain only buttons. |

### Attribute Overrides

To override the attributes of the ribbon controls (including the controls of the `interop.io` tab), create a JSON file and specify its location in the `"ribbon-attributes-overrides-path"` property of the [Excel Adapter settings](#excel_adapter_settings).

The keys of the JSON object are control IDs. Their values are objects whose keys are names of Office ribbon XML attributes (e.g., `"label"`, `"visible"`, `"screentip"`). To remove a control from the ribbon, set its value to `null`:

```json
{
    "IOGlueXlTabId": {
        "label": "My Company"
    },
    "IOFeedbackBtn": null
}
```

To set the label, visibility, or enabled state of a control dynamically, use the `"OnGetLabel"`, `"OnGetVisible"`, or `"OnGetEnabled"` keys and provide the name of an Interop method as a value. The Interop method will receive the control ID in the `ribbonObject` property and the key name in the `onGet` property. It must return an object with a property with the same name as the key (e.g., `{ OnGetVisible: false }`) within 800 milliseconds:

```json
{
    "IOStatusBtn": {
        "OnGetVisible": "MyRibbonVisibilityHandler"
    }
}
```

The following table lists the IDs of the controls in the `interop.io` tab:

| Control ID | Description |
|------------|-------------|
| `"IOGlueXlTabId"` | The `interop.io` tab. |
| `"IOGlueXlSystemGroupId"` | The "io.Connect" group. |
| `"ioXL2Instances"` | The "IO Instances" dropdown. |
| `"ioXL2SwitchInstance"` | The "Switch Instance" button. |
| `"IOStatusBtn"` | The "Status" button. |
| `"IOCTPBtn"` | The "CTPs" button. |
| `"IOLogBtn"` | The "Logs" button. |
| `"IOFeedbackBtn"` | The "Feedback" button. |
| `"IO_XL_Dynamics_Group"` | The "Dynamics" group. |
| `"ioXL2DynamicDropDown"` | The "Dynamics" dropdown containing the [ribbon menus](#excel_service_configuration-ribbon_menus). |
| `"IOXL_DynamicsBtn"` | The "Execute Dynamic" button. |

## Custom Task Panes

To create custom task panes in Excel when Excel starts, use the `"CreateCTP"` property of the [Excel service configuration](#excel_service_configuration). To create custom task panes at runtime, use the [Excel API](https://docs.interop.io/adapters/ms-office/excel/excel-api/index.md#excel_service_operations-custom_task_panes).

A custom task pane contains UI elements described by the `"ui"` property. When the user clicks a button in the task pane, the Interop method specified in the button's `"callback"` property will be invoked. If the button doesn't have a callback, the Interop method specified in the `"subscriptionInfo"` property of the task pane will be invoked:

```json
{
    "CreateCTP": [
        {
            "subscriptionInfo": {
                "callbackEndpoint": "PricingPanelHandler"
            },
            "ctpDescriptor": {
                "id": "pricingPanel",
                "title": "Pricing",
                "dockPosition": "msoCTPDockPositionLeft",
                "ui": {
                    "type": "Panel",
                    "margin": { "top": 10, "left": 10, "bottom": 10, "right": 10 },
                    "children": [
                        {
                            "type": "Label",
                            "text": "Select a pricing source:"
                        },
                        {
                            "type": "Button",
                            "id": "btnBloomberg",
                            "text": "Bloomberg Pricing",
                            "callback": { "callbackEndpoint": "PricingBloomberg" }
                        },
                        {
                            "type": "Border"
                        },
                        {
                            "type": "Button",
                            "id": "btnFidessa",
                            "text": "Fidessa Pricing",
                            "backColor": "#E0FFE0"
                        }
                    ]
                }
            }
        }
    ]
}
```

Each object in the `"CreateCTP"` array has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"ctpDescriptor"` | `object` | **Required.** Object describing the custom task pane. |
| `"subscriptionInfo"` | `object` | [Callback settings](#excel_service_configuration-callbacks) for the Interop method to invoke when a button without its own callback is clicked. |

The `"ctpDescriptor"` object has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"dockPosition"` | `string` | Position of the task pane. Can be `"msoCTPDockPositionLeft"`, `"msoCTPDockPositionTop"`, `"msoCTPDockPositionRight"`, `"msoCTPDockPositionBottom"`, or `"msoCTPDockPositionFloating"`. Defaults to `"msoCTPDockPositionFloating"`. |
| `"dockPositionRestrict"` | `string` | Restricts the positions to which the user can move the task pane. Can be `"msoCTPDockPositionRestrictNone"`, `"msoCTPDockPositionRestrictNoChange"`, `"msoCTPDockPositionRestrictNoHorizontal"`, or `"msoCTPDockPositionRestrictNoVertical"`. Defaults to `"msoCTPDockPositionRestrictNone"`. |
| `"id"` | `string` | ID for the task pane. |
| `"title"` | `string` | Title for the task pane. |
| `"ui"` | `object` | **Required.** Object describing the root UI element of the task pane. |
| `"visible"` | `boolean` | If `true`, the task pane will be visible. Defaults to `true`. |

The following UI elements are available:

| Type | Description |
|------|-------------|
| `"Border"` | Horizontal separator line. |
| `"Button"` | Button that invokes an Interop method when clicked. |
| `"Label"` | Text label. |
| `"Panel"` | Container that arranges its child elements vertically. |
| `"ScrollBox"` | Container with a scrollbar that arranges its child elements vertically. |
| `"TextBox"` | Text input field. |
| `"WebView"` | Embedded web page. Use the `"text"` property to specify the URL of the page. |

Each UI element has the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `"backColor"` | `string` | Background color (e.g., `"#FFE0E0"` or `"LightBlue"`). |
| `"callback"` | `object` | [Callback settings](#excel_service_configuration-callbacks) for the Interop method to invoke when a button is clicked. Valid only for buttons. |
| `"children"` | `object[]` | Child UI elements. Valid only for panels and scroll boxes. |
| `"foreColor"` | `string` | Text color (e.g., `"#000000"` or `"Black"`). |
| `"horizontalAlignment"` | `string` | Horizontal alignment of the element. Can be `"Left"`, `"Center"`, `"Right"`, or `"Stretch"`. |
| `"id"` | `string` | ID for the element. Sent to the Interop method in the `descriptor` property when a button is clicked. |
| `"isReadOnly"` | `boolean` | If `true`, the user won't be able to edit the text. Valid only for text boxes. Defaults to `false`. |
| `"margin"` | `object` | Margin around the element. Accepts an object with `"left"`, `"top"`, `"right"`, and `"bottom"` properties in pixels. |
| `"minHeight"` | `number` | Minimum height of the element in pixels. |
| `"minWidth"` | `number` | Minimum width of the element in pixels. |
| `"text"` | `string` | Text of the element. For web views, the URL of the page. |
| `"toolTip"` | `string` | Tooltip for a button. Valid only for buttons. |
| `"type"` | `string` | **Required.** Type of the UI element. |
| `"verticalAlignment"` | `string` | Vertical alignment of the element. Can be `"Top"`, `"Center"`, `"Bottom"`, or `"Stretch"`. |

Besides the [common callback properties](#excel_service_configuration-callbacks), the Interop method will receive a `descriptor` property containing the ID of the clicked button.

## Logging

The Excel Adapter writes its log to the `%LocalAppData%/interop.io/io.Connect Desktop/UserData/ApplicationAdapters/Excel/GlueXLv2.log` file. To view the latest log entries in Excel, click the "Logs" button in the `interop.io` ribbon tab.

To change the log level or the log file location, edit the `<log4net>` section of the `GlueXl-AddIn64.xll.config` file:

```xml
<log4net>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
        <file type="log4net.Util.PatternString" value="%env{localappdata}\interop.io\io.Connect Desktop\UserData\ApplicationAdapters\Excel\GlueXLv2.log" />
        
    </appender>
    <root>
        
        <level value="INFO" />
        <appender-ref ref="RollingFileAppender" />
    </root>
</log4net>
```
