I found a solution to setup Excel instance in WPF by using the SetParent() function of Windows.
Problem is, that mouse and keyboard is not reacting to the sheet but to the Workbook it does.
Full sample Project Download here
I also tried with WindowsFormsHost but it has the same effect.
XAML
<Window x:Class="ExcelEditor.SimpleWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ExcelEditor"
mc:Ignorable="d" Loaded="Window_Loaded" Closing="Window_Closing"
Title="SimpleWindow" Height="450" Width="800">
<Grid x:Name="LayoutRoot">
</Grid>
C# code
using System;
using System.Windows;
namespace ExcelEditor
{
/// <summary>
/// Interaktionslogik für SimpleWindow.xaml
/// </summary>
public partial class SimpleWindow : Window
{
private Microsoft.Office.Interop.Excel.Application ExcelApplication;
public SimpleWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Forms.Integration.ElementHost.EnableModelessKeyboardInterop(this); // <- testing only (no success)
ExcelApplication = new Microsoft.Office.Interop.Excel.Application();
ExcelApplication.DisplayAlerts = false;
System.Windows.Interop.HwndSource hwnd = (System.Windows.Interop.HwndSource)System.Windows.Interop.HwndSource.FromVisual(this.LayoutRoot);
var excelWnd = Microsoft.Win32.Interop.FindWindow("XLMAIN", null);
GenerateTestData(ExcelApplication);
var successOfParentSetup = Microsoft.Win32.Interop.SetParent(excelWnd, hwnd.Handle);
var isMovedToLeftTop = Microsoft.Win32.Interop.MoveWindow(excelWnd, 10, 10, 800, 600, true);
ExcelApplication.Visible = true;
}
private void GenerateTestData(Microsoft.Office.Interop.Excel.Application excelApplication)
{
var excelWorkbook = excelApplication.Workbooks.Add();
var excelWorksheet = excelWorkbook.Worksheets[1] as Microsoft.Office.Interop.Excel.Worksheet;
excelWorksheet.Cells[1, 1] = "Today";
excelWorksheet.Cells[2, 1] = DateTime.Now.ToString();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (ExcelApplication != null)
{
ExcelApplication.ActiveWorkbook.Close();
ExcelApplication.Visible = false;
ExcelApplication.Quit();
ExcelApplication = null;
}
}
}
}
Api calls
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern bool SetWindowPos(
IntPtr hWnd, // handle to window
IntPtr hWndInsertAfter, // placement-order handle
int X, // horizontal position
int Y, // vertical position
int cx, // width
int cy, // height
uint uFlags // window-positioning options
);
[DllImport("user32.dll", EntryPoint = "MoveWindow")]
public static extern bool MoveWindow(
IntPtr hWnd,
int X,
int Y,
int nWidth,
int nHeight,
bool bRepaint
);
[DllImport("USER32.DLL", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
//Sets a window to be a child window of another window
[DllImport("USER32.DLL", SetLastError = true)]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
Question is, how to enable the mouse and keyboard handling in Excel to allow editing the worksheet?
*Tested at: Windows 10 x64, Single screen (optional dual screen) Excel 2016 MSO 32-Bit (16.0.10325.20082) out of Office 365
This issue is also reported on Microsoft Forum to check if there is a solution.
In the following video you see how the click sometimes will select cells and sometimes it will not recognize the mouse.
You need to make sure Excel has been shown once before you can call SetParent
. Of course, it looks ugly, so you also need to hide Excel UI somehow from the end-user. For example:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
...
// get excel window
var excelWnd = Microsoft.Win32.Interop.FindWindow("XLMAIN", null);
// move excel somewhere outside the screen (of course you should compute it, not hardcode it)
Microsoft.Win32.Interop.MoveWindow(excelWnd, -10000, -10000, 800, 600, true);
// show it so it's initialized properly
ExcelApplication.Visible = true;
GenerateTestData(ExcelApplication);
// now call SetParent
Microsoft.Win32.Interop.SetParent(excelWnd, hwnd.Handle);
// move it to parent
Microsoft.Win32.Interop.MoveWindow(excelWnd, 10, 10, 800, 600, true);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With