How to Update Ribbon Icon via Excel DNA

44 views
Skip to first unread message

Sham Khole

unread,
Apr 29, 2024, 2:13:53 AMApr 29
to Excel-DNA
Description: We aim to modify our existing C# code to periodically check the user's login status by sending requests to a external Java application (As it is a external applicatrion ).Based on the response received, we intend to dynamically update the icon or indicator displayed in the Excel Ribbon accordingly.
Given our project requirements and technology stack, we are considering leveraging .NET Framework C# along with Excel DNA for this implementation.
Can you confirm if this functionality is achievable with these technologies?  

Best regards,
Sham

Terry Aney

unread,
May 18, 2024, 9:07:17 AMMay 18
to Excel-DNA
Part of a larger discussion, but yes this is possible.  Here is sample from larger discussion from Govert.

My current implementation is something like this:

1. When new workbook is activated, async call into web api to get some status (UpdateCalcEngineInfoAsync)
2. When async call completes, start QueueAsMacro so I'm on the 'primary thread' and call ribbon.Invalidate.
3. Then the various ribbon handlers will trigger and you can update what you need, in my case I'm loading an image of a 'log' and putting a badge count on it on how many error (our errors) are found in the file.

    private void Application_WorkbookActivate( MSExcel.Workbook wb )
    {
        RunRibbonTask( async () =>
        {
            var validations = await WorkbookState.UpdateCalcEngineInfoAsync( wbName );
            ExcelAsyncUtil.QueueAsMacro( () =>
            {
                ribbon.Invalidate();
                if ( validations != null )
                {
                    ShowValidations( validations );
                }
            } );
        } );
    }
    private void RunRibbonTask( Func<Task> action, [CallerMemberName] string actionName = "" )
    {
        Task.Run( async () =>
        {
            try
            {
                await action();
            }
            catch ( Exception ex )
            {
                ShowException( ex, actionName );
            }
            finally
            {
                ExcelAsyncUtil.QueueAsMacro( () => application.Cursor = MSExcel.XlMousePointer.xlDefault );
            }
        } );
    }
    public Bitmap Ribbon_GetImage( IRibbonControl control )
    {
        try
        {
            switch ( control.Id )
            {
                case "katShowDiagnosticLog":
                {
                    using var ms = new MemoryStream( auditShowLogImage );

                    var img = Image.FromStream( ms );

                    if ( auditShowLogBadgeCount > 0 )
                    {
                        var flagGraphics = Graphics.FromImage( img );
                        flagGraphics.FillEllipse(
                            new SolidBrush( Color.FromArgb( 242, 60, 42 ) ),
                            new Rectangle( 11, 0, 19, 19 )
                        );
                        flagGraphics.DrawString(
                            auditShowLogBadgeCount.ToString(),
                            new Font( FontFamily.GenericSansSerif, 6, FontStyle.Bold ),
                            Brushes.White,
                            x: auditShowLogBadgeCount < 10 ? 16 : 13,
                            y: 3
                        );
                    }

                    return (Bitmap)img;
                }

                default: throw new ArgumentOutOfRangeException( nameof( control ), $"The id {control.Id} does not support custom image generation." );
            }
        }
        catch ( Exception ex )
        {
            ShowException( ex, $"Ribbon_GetImage {control.Tag}" );
            return null!;
        }
    }

Reply all
Reply to author
Forward
0 new messages