Soluzione alternativa per verificare se Excel è in modalità di modifica delle celle in .NET
-
19-08-2019 - |
Domanda
Ho un'applicazione scritta in VB.NET che interagisce con Excel tramite interop. Alla fine ho riscontrato il problema noto della modalità di modifica delle celle (vedere MSDN e stackoverflow per qualche sfondo).
Ho provato a convertire il codice suggerito in VB.NET ma continuo a ricevere il seguente errore:
Reference required to assembly 'office, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' containing the type 'Microsoft.Office.Core.CommandBars'. Add one to your project. (BC30652) - E:\ ... .vb:3471
Il codice C # originale (dagli articoli citati in precedenza) è il seguente
private bool IsEditMode()
{
object m = Type.Missing;
const int MENU_ITEM_TYPE = 1;
const int NEW_MENU = 18;
// Get the "New" menu item.
CommandBarControl oNewMenu = Application.CommandBars["Worksheet Menu Bar"].FindControl(MENU_ITEM_TYPE, NEW_MENU, m, m, true );
if ( oNewMenu != null )
{
// Check if "New" menu item is enabled or not.
if ( !oNewMenu.Enabled )
{
return true;
}
}
return false;
}
Il mio codice VB.NET convertito è il seguente
Private Function isEditMode() As Boolean
isEditMode = False
Dim m As Object = Type.Missing
Const MENU_ITEM_TYPE As Integer = 1
Const NEW_MENU As Integer = 18
Dim oNewMenu As Office.CommandBarControl
' oExcel is the Excel Application object
' the error is related to the below line
oNewMenu = oExcel.CommandBars("Worksheet Menu Bar").FindControl(MENU_ITEM_TYPE, NEW_MENU, m, m, True)
If oNewMenu IsNot Nothing Then
If Not oNewMenu.Enabled Then
isEditMode = True
End If
End If
End Function
Ho aggiunto un riferimento (COM) alla Libreria oggetti di Microsoft Office
Imports Office = Microsoft.Office.Core
Imports Microsoft.Office.Interop
Sono un po 'bloccato. Ho già provato a fare riferimento indirettamente all'oggetto CommandBar e ad aggiungere nuovamente riferimenti ma non riesco a capire quale sia il problema. qualche idea?
Soluzione
Come soluzione rapida e sporca ho usato il seguente codice come alternativa
Private Function isEditMode() As Boolean
isEditMode = False
Try
oExcel.GoTo("###")
Catch Ex As Exception
' Either returns "Reference is not valid."
' or "Exception from HRESULT: 0x800A03EC"
If ex.Message.StartsWith("Exception") then isEditMode = True
End Try
End Function
La funzione .GoTo (e la corrispondente voce di menu) non è disponibile quando Excel è in modalità Modifica cella. Dare alla funzione .GoTo una destinazione fittizia non farà nulla e non influenzerà nulla se l'utente sta lavorando nella cella quando il codice viene eseguito.
Un ulteriore vantaggio è che non è necessario alcun riferimento alla libreria Microsoft Office Object (Microsoft.Office.Core).
Altri suggerimenti
Function ExcelIsBusy()
ExcelIsBusy = Not Application.Ready
Dim m
m = Empty
Const MENU_ITEM_TYPE = 1
Const NEW_MENU = 18
Dim oNewMenu
Set oNewMenu = Application.CommandBars("Worksheet Menu Bar").FindControl(MENU_ITEM_TYPE, NEW_MENU, m, m, True)
If Not (oNewMenu Is Nothing) Then
If Not oNewMenu.Enabled Then
ExcelIsBusy = True
'throw new Exception("Excel is in Edit Mode")
End If
End If
End Function
In precedenza avevamo usato il metodo Application.CommandBars [" Barra dei menu del foglio di lavoro "]
ma abbiamo riscontrato un difetto. Quando si esce da Excel mentre si è in modalità di modifica, la modalità di modifica si annulla, ma la funzione torna comunque vera perché le voci di menu sono state disabilitate come parte dell'arresto.
Abbiamo usato invece la seguente soluzione:
public static bool ApplicationIsInEditMode(Application application)
{
try
{
application.ReferenceStyle = application.ReferenceStyle;
}
catch (COMException e)
{
return true;
}
return false;
}
Il seguente codice rileverà se Excel è in modalità Modifica e ne uscirà:
private void exitEditMode()
{
if (!isExcelInteractive())
{
// get the current range
Excel.Range r = Globals.ThisAddIn.Application.ActiveCell;
// bring Excel to the foreground, with focus
// and issue keys to exit the cell
xlBringToFront();
Globals.ThisAddIn.Application.ActiveWindow.Activate();
SendKeys.Flush();
SendKeys.SendWait("{ENTER}");
// now make sure the original cell is
// selected…
r.Select();
}
}
private bool isExcelInteractive()
{
try
{
// this line does nothing if Excel is not
// in edit mode. However, trying to set
// this property while Excel is in edit
// cell mdoe will cause an exception
Globals.ThisAddIn.Application.Interactive = Globals.ThisAddIn.Application.Interactive;
return true; // no exception, ecel is
// interactive
}
catch
{
return false; // in edit mode
}
}
private void xlBringToFront()
{
SetForegroundWindow(Globals.ThisAddIn.Application.Hwnd);
}
[DllImport("User32.dll")]
public static extern Int32 SetForegroundWindow(int hWnd);