Native AOT feedback and sample repository

127 views
Skip to first unread message

Luigi Serio

unread,
Jun 19, 2026, 8:51:16 AMJun 19
to Excel-DNA

Hello,

I would like to share my recent experience migrating an Excel-DNA project from classic JIT compilation to Native AOT.

While it wasn't entirely straightforward due to the inherent nature of AOT, I managed to build a working add-in. Hoping this feedback can be helpful to someone, I'd like to highlight some difficulties I've encountered (mostly regarding the Ribbon) and share an simplified example repository.

difficulties encountered:

  • Conflict with ExcelDna.IntelliSense: To properly access core interfaces and classes such as IExcelRibbon, RibbonControl, and IDynamic, I noticed that the ExcelDna.IntelliSense package must not be included in the project. It took me quite a while to figure this out; I would recommend highlighting this more clearly in the documentation.

  • Ribbon Event Limitations (onLoad, getVisible, getLabel): Under AOT, these and similar events do not seem to function correctly. Specifically for onLoad, the received argument is cast to ExcelDna.Integration.CustomUI.RibbonControl, but the instance ends up empty. This prevents retrieving the proper interface needed to call .Invalidate() on the Ribbon—a feature I rely on for dynamic UI updates.

  • loadImage='LoadImage' Attribute: To load icons using the official examples, you must explicitly add loadImage='LoadImage' inside the <customUI> element. I assume LoadImage is an internal callback method within Excel-DNA that isn't publicly exposed. Much like the IntelliSense issue, adding a note about this in the documentation would be very helpful.

  • 32-bit AOT Publishing Anomaly (win-x86): Since I run a 64-bit version of Excel, I haven't been able to physically test the 32-bit add-in, but I believe there might be an issue in the publishing workflow. Although the project DLL compiles correctly for x86, Excel-DNA targets copy the 64-bit loader into the publish folder (deduced both from the ExcelDNAtest-AddIn64.xll file name and by inspecting the header via dumpbin /headers). It might be an error on my end, but I haven't been able to fully trace the underlying workflow.

GitHub Repository

I have set up a public repository containing a working setup that addresses these scenarios: https://github.com/luigicondimax/ExcelDNAtest

I implemented and tested several solutions in this project that might be useful to others:

  • Parallel Development Path: Handling both classic JIT mode and Native AOT within the same project file, with both configured for 32-bit and 64-bit publishing.

  • Inno Setup Installer: I've seen several deployment-related requests on the forum in the past, so I included a complete Inno Setup script that automatically handles add-in installation for different scenarios (requires Inno Setup installed to compile).

  • Avalonia UI: Instead of traditional Windows Forms or WPF, I integrated Avalonia UI (which is fully AOT-compliant) to handle dialog windows, custom forms, and message boxes.

  • Localization: I have adapted to the AOT compilation a Ribbon and function translation system that uses dynamic registration and the interface invalidation mechanism.

I translated and adapted this text with gemini so there might be some errors.

Can you confirm me the problem with the ribbon and the 32 bit compilation?

Thanks

Govert van Drimmelen

unread,
Jun 19, 2026, 7:30:39 PMJun 19
to exce...@googlegroups.com

Hi Luigi,

 

Thank you very much for writing this up and the detailed feedback.

 

I’ll go through and see how we can best address the issues you raise.

 

Regards,

Govert

--
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 visit https://groups.google.com/d/msgid/exceldna/9d5f0237-cb1f-4127-a61f-8b5b8615416cn%40googlegroups.com.

Govert van Drimmelen

unread,
Jun 29, 2026, 5:55:44 PMJun 29
to Excel-DNA
Hi Luigi,

I have not forgotten about this.
I have reproduced and fixed the issues you report and just need to get a release together.

-Govert

Luigi Serio

unread,
Jul 1, 2026, 5:54:53 AMJul 1
to Excel-DNA
Hi Govert,

thanks for the update and your job.
I will wait for the release

Luigi

Govert van Drimmelen

unread,
Jul 6, 2026, 6:30:45 PMJul 6
to Excel-DNA
Hi Luigi,

I pushed to NuGet an update to v1.10.0-preview5 which should address your issues:
* Ribbon events should now work right in NativeAOT
* 32-bit NativeAOT is published correctly
* IntelliSense is warned about - for now no NativeAOT version that you include inthe single-file add-in, but you can use the standalone ExcelDna.IntelliSense(64).xll  add-in  (from the Releases page on that repo) and your NativeAOT add-in should light up with no other changes.

I've not tested the final packages yet, so please let me know if you see anything funny, or your issues are not yet resolved.

Thanks again for writing this up and reporting so clearly.

Regards,
Govert

Luigi Serio

unread,
Jul 7, 2026, 6:00:05 AMJul 7
to Excel-DNA
Hi Govert,
I checked your update:
  • the ribbon works well.
  • The 32-bit publishing seems correct, but when I tried it on another PC, Excel crashed.
    It's not my PC, so I couldn't debug it. I'll look into it in the next few days.
    Have you tried the 32 bit version just to be sure it's my problem?
  • I didn't know you could use Intellisense this way on AOT. I tried it and it works very well
In the next weeks i will try to migrate some major code on AOT and i will report you if i encounter some AOT related problem but i don't think

Thanks again for your job

Have a nice day
Luigi

Govert van Drimmelen

unread,
Jul 7, 2026, 8:00:24 AMJul 7
to exce...@googlegroups.com

Hi Luigi,

 

Thank you for checking and for the feedback.

 

I have not tested the NativeAOT on 32-bit Excel at all.

I’ll see if I can get a way to test it and see what the actual status is there.

 

Please keep posting anything else you find.

Luigi Serio

unread,
Jul 17, 2026, 2:35:26 AM (12 days ago) Jul 17
to Excel-DNA
Hi,

I probably found a small problem in AOT:
Apparently, in AOT, it's not possible to disable automatic function registration because the <ExcelAddInExplicitRegistration> parameter is ignored.

Luigi Serio

unread,
Jul 23, 2026, 3:08:54 AM (6 days ago) Jul 23
to Excel-DNA
Hi,

In addition to the inability to disable automatic function registration, I found a second problem visible in the following example:

[ExcelFunction(IsMacroType = true)]
public static string? LanguageTest(object _true, object _sum)
{
// italian function =LanguageTest(VERO;SOMMA(1;2))
// VERO = TRUE
// SOMMA = SUM
// format cell #.##0,00

// C-API
var caller = (ExcelReference)XlCall.Excel(XlCall.xlfCaller);
Debug.Print($"C-API Local formula: {XlCall.Excel(XlCall.xlfGetCell, 6, caller)}");
Debug.Print($"C-API Global formula: {XlCall.Excel(XlCall.xlfGetCell, 41, caller)}");
Debug.Print($"C-API Format: {XlCall.Excel(XlCall.xlfGetCell, 7, caller)}");

// COM
var range = ToRange(caller)!;
var formula = range.Get("Formula") as string;
Debug.Print($"COM Formula: {formula}");
Debug.Print($"COM Formula: {range.Get("FormulaLocal")}");
Debug.Print($"COM Format: {range.Get("NumberFormat")}");

return formula;
}

below are the results:

// JIT result
//Information: 0 : C - API Local formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : C - API Global formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : C - API Format: #.##0,00
//Information: 0 : COM Formula: = LanguageTest(TRUE, SUM(1, 2))
//Information: 0 : COM Formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : COM Format: #,##0.00
//Information: 0 : COM LCID Formula: = LanguageTest(TRUE, SUM(1, 2))
//Information: 0 : COM LCID Formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : COM LCID Format: #,##0.00

// AOT

//Information: 0 : C - API Local formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : C - API Global formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : C - API Format:
 #.##0,00
//Information: 0 : COM Formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : COM Formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : COM 
Format: #.##0,00
//Information: 0 : COM LCID Formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : COM LCID Formula: = LanguageTest(VERO; SOMMA(1; 2))
//Information: 0 : COM LCID
 Format: #.##0,00

You can found the full source code in the repository but this is a problem related to excel language

C-API notoriously returns in the local language.
COM, on the other hand, should return in American notation.

This is true in JIT but not in AOT, as you can see in the example code.

I tried changing the thread language and similar without success.
The only solution was to change the Excel language, but that doesn't seem like an optimal solution.

Looking at the source code, I found that the problem is due to DispatchObject.cs under
\ExcelDna.Integration\ComInterop\Generator\Interfaces\DispatchObject.cs
The code currently includes
"private const int LOCALE_USER_DEFAULT = 0x0400;" which is essentially the system language.
Changing it to 0x0409 solved the problem.

I think the AOT code should behave like JIT, and in general, using the american language makes the code more universal.
I would at least recommend the possibility of changing this variable.

What do you think?

Govert van Drimmelen

unread,
Jul 23, 2026, 2:28:24 PM (5 days ago) Jul 23
to exce...@googlegroups.com

Hi Luigi,

 

Thank you for the ongoing feedback.

Making the NativeAOT COM language work the same as non-NativeAOT should indeed be a goal.

 

I’ll also have a look at the ‘ExplicitRegistration’ story, though there might be some snags – we might not compile in all the right stub types for runtime registration with NativeAOT.
How do you use this feature? To change the registration details, or to generate functions at runtime?

-Govert

Luigi Serio

unread,
Jul 24, 2026, 3:20:59 AM (5 days ago) Jul 24
to Excel-DNA
Hi,

I use runtime registration both to choose whether or not to register a function and to localize it.
If you use Excel in Italian and then reopen it in English, it automatically converts the functions ("Somma" <--> "Sum"). Since I can't replicate this system, at least as far as I know, I typically register the function in the user's language and then in the other languages, but as hidden.
Basically I register the various functions "SommaSpeciale", "SumSpecial", ... with the descriptions, category, names of the parameters and similary localized in the user's language but keeping visible only the function with the name localized in his language.
I should probably rethink this system but actually I don't see any other approaches.

The DynamicRegistration.cs class in the repository demonstrates this method. It's a simplified version of the function and resource identification part, but the registration mechanism I use is exactly the same.

Luigi
Reply all
Reply to author
Forward
0 new messages