J'ai trouvé une solution pour installer l'instance Excel dans WPF en utilisant la fonction SetParent () de Windows.
Le problème est que la souris et le clavier ne réagissent pas à la feuille mais au classeur.
Exemple complet Télécharger le projet ici
J'ai aussi essayé avec WindowsFormsHost mais cela a le même effet.
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>
Code C #
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;
}
}
}
}
Appels Api
[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);
La question est de savoir comment activer la manipulation de la souris et du clavier dans Excel pour permettre la modification de la feuille de calcul.
* Testé à: Windows 10 x64, Écran unique (double écran en option) Excel 2016 MSO 32 bits (16.0.10325.20082) sur Office 365
Ce problème est également signalé sur Microsoft Forum pour vérifier s’il existe une solution.
Dans la vidéo suivante, vous voyez comment le clic sélectionne parfois des cellules et parfois, il ne reconnaît pas la souris.
Vous devez vous assurer que Excel a été affiché une fois avant de pouvoir appeler SetParent
. Bien sûr, cela a l'air moche, vous devez donc également cacher l'interface utilisateur Excel à l'utilisateur final. Par exemple:
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);
}