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?

È stato utile?

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top