using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using System.Collections.Generic;
using System.Threading.Tasks;
public class MainWindow : Window
private Label StatusLabel;
private Button SomeButton;
private MemoryStream parentMemStream;
private XLWorkbook user_wb;
private volatile bool isTaskCompleted = false;
public MainWindow(MemoryStream parentMemStream, XLWorkbook user_wb) : this()
this.parentMemStream = parentMemStream;
// Start the background operation when the window is initialized
StartBackgroundOperation();
private void InitializeComponent()
AvaloniaXamlLoader.Load(this);
StatusLabel = this.FindControl<Label>("StatusLabel");
SomeButton = this.FindControl<Button>("SomeButton");
SomeButton.Click += OnSomeButtonClick;
private async void OnSomeButtonClick(object sender, Avalonia.Interactivity.RoutedEventArgs e)
// Handle some button click event
await Dispatcher.UIThread.InvokeAsync(() => StatusLabel.Content = "Button Clicked!");
// Start waiting for task completion and then open folder picker
await WaitForTaskCompletionAndOpenFolderPicker();
private void StartBackgroundOperation()
var progress = new Progress<string>(message =>
// Update the label with the progress message
StatusLabel.Content = message;
// Perform the long-running operation in the background
Task.Run(() => ProcessExcelFileAsync(progress)).ContinueWith(task =>
// Code to run after the task is finished
}, TaskScheduler.FromCurrentSynchronizationContext()); // Ensure continuation runs on the UI thread
private async Task ProcessExcelFileAsync(IProgress<string> progress)
// Simulate a long-loading operation with progress updates
progress.Report("Loading started...");
// Create XLWorkbook Object in Memory from Master file
var FinalWorkbook = new XLWorkbook(parentMemStream);
// Simulate loading progress
progress.Report("Step 1 completed...");
var winWs = FinalWorkbook.Worksheet("Hello_Win");
var macWs = FinalWorkbook.Worksheet("Hello_Mac");
// Simulate loading progress
progress.Report("Fetched homepages...");
// Holder for sheet names added
var sheetNames = new List<string>();
// Handling of User supplied workbook
// Get all the Sheets of the User Workbook
var existingSheets = user_wb.Worksheets.Select(s => s.Name).ToArray();
// Parsing the user workbook sheets for unwanted elements
foreach (var s in user_wb.Worksheets)
// FIX NAMED RANGES PROBLEMS
foreach (var dn in s.DefinedNames)
if (!dn.IsValid || !existingSheets.Contains(dn.RefersTo.Split("!")[0]))
progress.Report($"Processed named ranges for sheet {s.Name}");
var incomingImageNames = new Dictionary<string, string>();
var incomingImageNamesCounter = new Dictionary<string, int>();
foreach (var pic in s.Pictures)
var originalName = pic.Name;
if (!incomingImageNames.TryAdd(originalName, originalName))
incomingImageNamesCounter[originalName]++;
var uniqueName = $"{originalName}_{incomingImageNamesCounter[originalName]}";
incomingImageNamesCounter[originalName] = 1;
catch (Exception exception)
Console.WriteLine(exception);
progress.Report($"Processed images for sheet {s.Name}");
// Add the User Sheet to the Master
FinalWorkbook.AddWorksheet(s);
// Keep track of its name
FinalWorkbook.Worksheet(s.Name).Position = cnt;
FinalWorkbook.Worksheet(s.Name).RecalculateAllFormulas();
progress.Report($"Added and recalculated sheet {s.Name}");
progress.Report("Loading completed...");
private void OnTaskCompleted(Task task)
var exception = task.Exception.Flatten().InnerExceptions.FirstOrDefault();
Dispatcher.UIThread.InvokeAsync(() => StatusLabel.Content = $"Error: {exception.Message}");
// Update the label to indicate the completion of the operation
Dispatcher.UIThread.InvokeAsync(() => StatusLabel.Content = "Operation Completed!");
// Set the flag to indicate the task is completed
private async Task WaitForTaskCompletionAndOpenFolderPicker()
// Wait until the flag is set
await Task.Delay(100); // Check every 100 milliseconds
// Open the folder picker
var folderDialog = new OpenFolderDialog();
var result = await folderDialog.ShowAsync(this);
await Dispatcher.UIThread.InvokeAsync(() => StatusLabel.Content = $"Selected folder: {result}");
await Dispatcher.UIThread.InvokeAsync(() => StatusLabel.Content = "No folder selected");