Временное решение, чтобы увидеть, если Excel находится в режиме редактирования ячейки-в .NET

У меня есть приложение, написанное в VB.NET, который взаимодействует с Excel через Interop. В конце концов я столкнулся с известной проблемой режима редактирования клеток (см. msdn и Stackoverflow для какой-то фон).

Я пытался преобразовать предложенный код в VB.NET, но продолжайте получать следующую ошибку:

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

Оригинальный код C # (от предыдущих упомянутых статей) выглядит следующим образом

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;
}

Мой преобразованный код VB.NET выглядит следующим образом

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

Я добавил (COM) ссылку на библиотеку объекта Microsoft Office

Imports Office = Microsoft.Office.Core
Imports Microsoft.Office.Interop

Я вроде застрял. Я уже пробовал косвенно ссылаться на объект CommandBar, и повторно добавляя обложки, но не может выяснить, в чем проблема. Любые идеи?


person barry    schedule 21.01.2009    source источник
comment
должны быть Импорт Офис = Microsoft.Office.Core Импорт Microsoft.Office.Interop.Excel не Импорт Офис = Microsoft.Office.Core Импорт Microsoft.Office.Interop   -  person Anonymous Type    schedule 25.02.2010


Ответы (4)


В качестве быстрого и грязного исправления я использовал следующий код в качестве альтернативы

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

Функция .goto (и соответствующий пункт меню) недоступен, когда Excel находится в режиме редактирования клеток. Давая функцию .goto Пустота назначения пустышки ничего не сделает и не повлияет на что-то повлияло, если пользователь работает в ячейке при запуске кода.

Дополнительным преимуществом является то, что не требуется ссылка на библиотеку объектов Microsoft Office (Microsoft.Office.Core).

person barry    schedule 21.01.2009
comment
Выше теперь работал отлично на некоторое время на несколько различных установок. - person barry; 31.01.2009

Ранее мы использовали метод Application.CommandBars["Worksheet Menu Bar"], но столкнулись с недостатком. При выходе из Excel во время режима редактирования режим редактирования отменяется, но функция все еще возвращает true, поскольку элементы меню были отключены как часть отключения.

Вместо этого мы использовали следующее решение:

public static bool ApplicationIsInEditMode(Application application)
{
    try
    {
        application.ReferenceStyle = application.ReferenceStyle;
    }
    catch (COMException e)
    {
        return true;
    }
    return false;
}
person Chris C    schedule 25.04.2013

Старше пост, но не старая проблема. Приведенное выше решение для обнаружения и выхода прекрасно, но я нашел другое решение для вывода Excel из режима редактирования, в котором не нужно использовать API для поиска окна или использовать клавиши Send для щелчка по ячейке, мое решение использует события. Excel может быть даже в режиме редактирования и свести к минимуму, и это решение будет работать. Если вы читаете это, вы, вероятно, не будет нужен точный код, но если вы, пожалуйста, дайте мне знать. Во-первых обнаружение режима редактирования Excel с попыткой поймать похож на предыдущие решения и установить глобальный флаг Правда, если Excel находится в режиме редактирования. Тогда скажите Excel, чтобы закрыть. Это действие будет доступно даже в режиме редактирования. При проверке событий Excel OnClosing если ваш Глобальный флаг установлен, и если да, установить на закрытии мероприятия «e.Cancel» в True, который остановит закрытие Excel. Установите Глобальный обратно флаг в Ложный и когда Excel возвращается он выйдет из режима редактирования и все, что было написано в редактируемые ячейки все еще будет там.

person Rodent    schedule 06.12.2019

После кода обнаружит ли первенствует находится в режиме редактирования и выхода из него:

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);
person Atish    schedule 07.08.2014