如何在Excel互操作中强制单元格停止编辑?

本文关键字:单元格 编辑 Excel 互操作 | 更新日期: 2023-09-27 17:50:57

我有一个带ribbon的Excel 2007插件。功能区中的一个按钮触发了对当前工作表的大量操作,出于速度和用户体验的原因,我在操作期间设置了各种Excel.Application属性,如InteractiveEnableEventsfalse

我的问题是,功能区不会偷焦点,所以如果用户在编辑单元格时,他点击我的功能区按钮,设置Application.Interactive = false时抛出异常,因为Excel认为用户仍在编辑单元格。

是否有一种方法可以通过保存或丢弃对单元格所做的更改来停止版本?

看来Range.DiscardChanges()可能会解决我的问题,但它在2007年的API中不可用。

编辑:似乎Range.DiscardChanges()是基于OLAP数据源的范围,所以它不会解决我的问题。

编辑:我试过在另一个细胞上呼叫Range.Activate()。虽然我确实看到GUI中的单元格焦点发生了变化,但无论如何都会抛出异常。Range.Select()不做任何事情

如何在Excel互操作中强制单元格停止编辑?

您不能停止编辑,但您可以检查编辑是否启用,然后告诉用户停止编辑:

private bool IsEditing(Microsoft.Office.Interop.Excel.Application excelApp)
{
    if (excelApp.Interactive)
    {
        try
        {
            excelApp.Interactive = false;
            excelApp.Interactive = true;
        }
        catch (Exception)
        {
            MessageBox.Show("Please stop cell editing before you continue.");
            return true;
        }
    }
    return false;
}

我在本页找到了答案,并将其从VBA更改为c#:https://www.add-in-express.com/creating-addins-blog/2011/03/23/excel-check-user-edit-cell/

因此,在寻找了几天并在MSDN上询问之后,最终的答案是API中根本没有此功能,并且如果不使用黑客解决方案1,则不可能实现。

Excel本身处理这种事情的方式只是在用户编辑时将其菜单变灰,所以我这样做是为了与主机应用程序保持一致。

1: Hacky,因为像使用SendKeys这样的技术需要返回GUI以确保操作被处理,然后调用要求单元格不在版本中的方法。这在一个地方很好,但对每个调用Excel Interop的方法都这样做是疯狂的。

现在回答可能太晚了。但想想有人在寻找解决方案时会用这个技巧。

由于某种原因,sendkeys和单元格/范围激活命令没有运行。

解决这个问题的唯一方法是将焦点更改为另一个工作表,然后返回到当前工作表来欺骗excel。: -)

ExcelUtil.ActivateWorksheet("Sheet1");
currentWorksheet.Activate();
public static void ActivateWorksheet(string strWorksheetName)
    {
        bool found = false;
        foreach (Excel.Worksheet sheet in Globals.ThisAddIn.Application.Worksheets)
        {
            if (sheet.Name.ToLower() == strWorksheetName.ToLower())
            {
                found = true;
                break;
            }
        }
        if (!found)
            Globals.ThisAddIn.AddNewWorksheet(strWorksheetName);
        ((Excel.Worksheet)Globals.ThisAddIn.Application.Worksheets[strWorksheetName]).Activate();
    }

希望对你有帮助。

Ram

其他提出的解决方案都不适合我,然后我了解到我们可以在VB中使用excel Events。NET应用程序,并利用"BeforeClose"事件,强制Excel退出单元格编辑模式。

VB。NET代码:

'Declare Excel object'
Public WithEvents Excel As New Microsoft.Office.Interop.Excel.Application
public Fake_close as boolean
Public Function Is_in_edit_mode() As Boolean
    Try
        Excel.Interactive = Excel.Interactive
    Catch Ex As Exception
        Return True
    End Try
    Return False
End Function
Public Sub Exit_cell_edit_mode()
    If Not Is_in_edit_mode() Then Exit Sub
    'initiates closing the worksheet, which forces cancellation of cell edit mode.'
    Fake_close = True  'Signal that the closing event is fake'
    Excel.ActiveWorkbook.Close()  'This command will trigger the event below'
End Sub
'This event will be triggered in the VB.NET app before the workbook is closed on Excel'
Private Sub WorkbookBeforeClose(Wb As Workbook, ByRef Cancel As Boolean) Handles Excel.WorkbookBeforeClose
    If Fake_close Then 
        Cancel = True  'Cancel the closing of the workbook'
        Fake_close = False
    End if
End Sub

如果选择另一个单元格或所有单元格,错误会消失吗?

private void myFunction() { xlSheet.Cells.Select(); //the rest of the work }

我检测到问题并显示消息告诉用户:如果excelHelper.ExcelIsEditing(System.Media.SystemSounds.Beep.Play ()MsgBox("请完成编辑工作表!",vbCrLf,vbCrLf,"将光标移出当前单元格,然后重试按钮。")退出函数如果

函数ExcelIsEditing()作为BooleanExcelIsEditing = False

  If ExcelApp.Interactive = False Then Return False
  Try
     ExcelApp.Interactive = False
     ExcelApp.Interactive = True
  Catch
     Return True
  End Try

结束功能

这是我能想到的最好的:_(