Issue Encountered in Excel Add-In Distribution

57 views
Skip to first unread message

Sham Khole

unread,
May 3, 2024, 1:17:31 AMMay 3
to Excel-DNA

I am reaching out to discuss an issue we've encountered while testing the distribution version of our Excel add-in.

Upon running the packaged XLL file, we encountered the following error message:

"An exception occurred while calling function GetDynamicStatus. The exception message is: Parameter is not valid."

This error seems to be related to the GetDynamicStatus function within the add-in. It appears to be encountering an invalid parameter during its execution.

We're currently investigating this discrepancy, as the error doesn't occur when running the project directly but arises specifically when using the packaged file intended for distribution.

Below is code for reference :-
using ExcelDna.Integration.CustomUI;
using ExcelDna.Integration;
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Timers;

namespace BanorCapital
{
    [ComVisible(true)]
    public partial class RibbonController : ExcelRibbon, IDisposable
    {
        private Microsoft.Office.Core.IRibbonUI _ribbonUi;
        private static RibbonController instance;
        private string selectedDataSource = "Influx";
        private bool isFlagEnabled = false;
        private System.Timers.Timer timer;
        string timezone = TimeZoneInfo.Local.Id;
       
        public static RibbonController Instance
        {
            get { return instance; }
        }
        public RibbonController()
        {
            // Initialize timer with 10 seconds interval
            timer = new System.Timers.Timer(10000);
            timer.Elapsed += Timer_Elapsed;
            timer.Start();

            // Get the timezone identifier in "Continent/City" format
            timezone = GetTimeZoneId();
        }
        private string GetTimeZoneId()
        {
            TimeZoneInfo localTimeZone = TimeZoneInfo.Local;
            return localTimeZone.DisplayName;
        }
        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            // Call GetButtonImage to update the button image
            _ribbonUi.InvalidateControl("status_button");
        }
        public string SelectedDataSource
        {
            get { return selectedDataSource; }
            set { selectedDataSource = value; }
        }

        /// <summary>
        /// Gets the Excel application instance.
        /// </summary>
        private Microsoft.Office.Interop.Excel.Application App
        {
            get => (Microsoft.Office.Interop.Excel.Application)ExcelDnaUtil.Application;
        }
       
        /// <summary>
        /// Handles the Ribbon load event.
        /// Initializes the IRibbonUI interface.
        /// </summary>
        public void OnLoad(Microsoft.Office.Core.IRibbonUI ribbonUI)
        {
            _ribbonUi = ribbonUI;
            instance = this; // Assign the current instance to the static property
        }
       
        /// <summary>
        /// Handles the "Settings" button click on the Ribbon.
        /// Displays the login form if the user is not already authenticated.
        /// </summary>
        public void OnSettings(Microsoft.Office.Core.IRibbonControl control)
        {
            if (IsUserAuthenticated())
            {
                MessageBox.Show("You are already logged in.", "Already Logged In", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (!IsUserAuthenticated())
            {
                var loginForm = new LoginForm();
                DialogResult result = loginForm.ShowDialog();

                if (result != DialogResult.OK)
                {
                    return;
                }
            }

        }
       
        /// <summary>
        /// Checks if the user is authenticated.
        /// </summary>
        /// <returns>True if the user is authenticated, otherwise false.</returns>
        private bool IsUserAuthenticated()
        {
            return LoginForm.IsAuthenticated;
        }
       
        /// <summary>
        /// Handles the "All Funds" button click on the Ribbon.
        /// Displays a pop-up with information about all available funds.
        /// </summary>
        public void OnAllFunds(Microsoft.Office.Core.IRibbonControl control)
        {
            //As per client requirement need to disable authinticate functionality.

            //if (!LoginForm.IsAuthenticated)
            //{
            //    MessageBox.Show("You must be logged in to access this functionality.", "Access Denied", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            //    return; // Exit the method since the user is not authenticated
            //}
            ShowAllFundsPopup();
        }

        /// <summary>
        /// Handles the "Available Fields" button click on the Ribbon.
        /// Displays a pop-up with information about available fields.
        /// </summary>
        public void OnAvailableFields(Microsoft.Office.Core.IRibbonControl control)
        {
            //As per client requirement need to disable authinticate functionality.

            //if (!LoginForm.IsAuthenticated)
            //{
            //    MessageBox.Show("You must be logged in to access this functionality.", "Access Denied", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            //    return;
            //}
            var popup = new AvailableFieldsPopup();
            popup.ShowDialog();
        }

        /// <summary>
        /// Handles the "Show Version" button click on the Ribbon.
        /// Displays the add-in version information.
        /// </summary>
        public void OnShowVersion(Microsoft.Office.Core.IRibbonControl control)
        {
            const string projectVersion = "1.0.3";

            MessageBox.Show($"BanorCapital Add-In Version: {projectVersion}", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        /// <summary>
        /// Handles the "User Manual" button click on the Ribbon.
        /// Displays the user manual form.
        /// </summary>
        public void OnUserManual(Microsoft.Office.Core.IRibbonControl control)
        {
            var userManualForm = new UserManualForm();
            userManualForm.ShowDialog();
        }

       
        /// <summary>
        /// Retrieves the dynamic status image based on user authentication and flag status.
        /// </summary>
        /// <param name="control">The Ribbon control requesting the image.</param>
        /// <returns>A System.Drawing.Bitmap representing the dynamic status.</returns>
        public System.Drawing.Bitmap GetDynamicStatus(Microsoft.Office.Core.IRibbonControl control)
        {
            string username = LoginForm.AuthenticatedUsername;
            if (string.IsNullOrEmpty(username))
            {
                string defaultImagePath = "Images//LogoutUser.png";
                return new System.Drawing.Bitmap(defaultImagePath);
            }
            bool flagStatus = FetchFlagStatusFromEndpoint(username, timezone);

            string imagePath = flagStatus ? "Images//LoginUser.png" : "Images//LogoutUser.png";

            System.Drawing.Bitmap image = new System.Drawing.Bitmap(imagePath);

            return image;
        }

        /// <summary>
        /// Disposes of resources used by the RibbonController.
        /// </summary>
        public void Dispose()
        {

        }
    }
}
=======
<?xml version="1.0" encoding="utf-8"?>
<DnaLibrary Name="BanorCapital Add-In" RuntimeVersion="v4.0" xmlns="http://schemas.excel-dna.net/addin/2020/07/dnalibrary">
<ExternalLibrary Path="BanorCapital.dll" ExplicitExports="false" LoadFromBytes="true" Pack="true" IncludePdb="false" />

<CustomUI>
<customUI xmlns='http://schemas.microsoft.com/office/2009/07/customui' loadImage='LoadImage' onLoad='OnLoad'>
<ribbon>
<tabs>
<tab id='sample_tab' label='Banorcapital'>
<group id='sample_group' label='Operations'>
<button id='all_funds' label='Fund List' size='large' onAction='OnAllFunds' image='AllFunds'/>
<button id='fetch_data' label='Portfolio Data' size='large' onAction='OnFetchData' image='PortFolio'/>
<button id='available_fields' label='Available Fields' size='large' onAction='OnAvailableFields' image='CustomAvailableFields'/>
</group>
<group id='database_group' label='Data Sources'>
<checkBox id='checkbox_sql' label='SQL'
onAction='OnCheckBoxSql'
getPressed='GetCheckBoxSqlPressed'
screentip='Select SQL data source'
supertip='Select this option to fetch data from an SQL database'/>

<checkBox id='checkbox_influx' label='Influx'
onAction='OnCheckBoxInflux'
getPressed='GetCheckBoxInfluxPressed'
screentip='Select InfluxDB data source'
supertip='Select this option to fetch data from InfluxDB'/>

<checkBox id='checkbox_bpipe' label='B-Pipe'
onAction='OnCheckBoxBPipe'
getPressed='GetCheckBoxBPipePressed'
screentip='Select B Pipe data source'
supertip='Select this option to fetch data from B Pipe'/>
</group>
<group id='dynamic_group' label='B-Pipe App'>
<button id='status_button' label='Status' size='large' onAction ='OnBpipeStatus' getImage='GetDynamicStatus'/>
</group>
<group id='setting_group' label='Settings'>
<button id='settings_button' label='Settings' size='large' onAction='OnSettings' image='Settings'/>
</group>
<group id='info_group' label='Info'>
<button id='user_manual_button' label='Help' size='large' onAction='OnUserManual' image='UserManual'/>
<button id='version_button' label='Version' size='large' onAction='OnShowVersion' image='VersionIcon'/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
</CustomUI>

<Image Name='PortFolio' Path='Images\PortFolio.png' Pack='true' />
<Image Name='CustomAvailableFields' Path='Images\AvailableFields.png' Pack='true' />
<Image Name='AllFunds' Path='Images\AllFunds.png' Pack='true' />
<Image Name='Settings' Path='Images\Settings.png' Pack='true' />
<Image Name='VersionIcon' Path='Images\VersionIcon.png' Pack='true' />
<Image Name='UserManual' Path='Images\UserManual.png' Pack='true' />
<Image Name='SQLIcon' Path='Images\SQLIcon.png' Pack='true' />

</DnaLibrary>

Govert van Drimmelen

unread,
May 3, 2024, 8:58:52 AMMay 3
to Excel-DNA
I see you're packing the images into the .xll file (according to the <Image> tags in the .dna file).

Then you can use the base class implementation of ExcelRibbon.LoadImage to get the image from the packed .xll.
You pass in the Name attribute from the Iamge tag:
     var bitmap = base.LoadImage("CustomAvailableFields");

-Govert

Craig Crevola

unread,
May 3, 2024, 10:37:39 PMMay 3
to exce...@googlegroups.com
Hi Sham

Check your distribution for the login and logout images, perhaps they are not included. 

Thanks

Craig.

--
You received this message because you are subscribed to the Google Groups "Excel-DNA" group.
To unsubscribe from this group and stop receiving emails from it, send an email to exceldna+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/exceldna/ed56d462-3fff-424a-9dc9-bb160de3040cn%40googlegroups.com.

Terry Aney

unread,
May 18, 2024, 9:09:31 AMMay 18
to Excel-DNA
Another possibility...I simply just embed the images into the addin assembly and load the image directly from resource string.
Reply all
Reply to author
Forward
0 new messages