我有一个用VB.NET编写的应用程序,它通过互操作与Excel交互。 我最终遇到了已知的细胞编辑模式问题(有关背景,请参阅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对象,并重新添加引用,但无法弄清楚是什么问题。有任何想法吗?
答案 0 :(得分:3)
作为一个快速而肮脏的修复,我使用以下代码作为替代
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
当Excel处于单元格编辑模式时,.GoTo功能(和相应的菜单项)不可用。 如果用户在代码运行时在单元格中工作,则为.GoTo函数提供虚拟目标将不会执行任何操作。
额外增加的是不需要引用Microsoft Office对象(Microsoft.Office.Core)库。
答案 1 :(得分:1)
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
答案 2 :(得分:1)
我们以前使用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;
}
答案 3 :(得分:0)
以下代码将检测excel是否处于编辑模式并退出:
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);
答案 4 :(得分:0)
较老的帖子,但不是老问题。上面检测和退出的解决方案很好,但是我找到了另一个使Excel退出编辑模式的解决方案,不需要使用API查找窗口或使用Sendkeys单击单元格,我的解决方案使用事件。 Excel甚至可以处于编辑模式并最小化,此解决方案仍然可以使用。如果您正在阅读本文,则可能不需要确切的代码,但如果需要,请告诉我。 首先使用类似于先前解决方案的try catch检测Excel编辑模式,如果Excel处于编辑模式,则将全局标志设置为True。 然后告诉Excel关闭。即使在编辑模式下,此操作也将可用。 在Excel OnClosing事件中,检查是否设置了全局标志,如果已设置,则将“关闭时”事件“ e.Cancel”设置为True,这将停止Excel关闭。 将您的Global标志重新设置为False,当Excel返回时,它将退出编辑模式,并且写入到已编辑单元格中的所有内容仍然存在。