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

问题描述 投票:0回答:6

我有一个带有功能区的 Excel 2007 加载项。功能区中的一个按钮会触发对当前工作表的大量操作,出于速度和用户体验的原因,我在操作过程中设置了各种

Excel.Application
属性,例如
Interactive
EnableEvents
false

我的问题是功能区不会窃取焦点,因此如果用户在单击功能区按钮时正在编辑单元格,则设置

Application.Interactive = false
时会引发异常,因为 Excel 认为用户仍在编辑单元格。

有没有办法通过保存或放弃对单元格所做的更改来停止编辑?

看起来

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

编辑:似乎

Range.DiscardChanges()
适用于基于 OLAP 数据源的范围,因此无论如何它都无法解决我的问题。

编辑:我尝试在另一个手机上拨打

Range.Activate()
。虽然我确实看到 GUI 中单元格焦点发生变化,但无论如何都会抛出异常。
Range.Select()
没有做任何事情。

c# .net excel-interop
6个回答
5
投票

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

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/


4
投票

因此,在查了几天并在 MSDN 上询问后,最终的答案是 API 中根本没有任何相关内容,并且如果不使用 hacky 解决方案,这是不可能的1

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

1:Hacky,因为使用

SendKeys
等技术需要返回 GUI 以确保操作已处理,然后调用要求单元格不处于编辑状态的方法。这在一个地方没问题,但对 Excel Interop 的每个方法调用都这样做是疯狂的。


1
投票

现在回答可能为时已晚。但认为有人在寻找解决方案时会使用这个技巧。

由于某种原因,sendkeys 和 Cells/Range activate 命令无法执行。

解决此问题的唯一解决方法是将焦点更改到另一个工作表,然后返回到当前工作表以欺骗 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();
    }

希望这有帮助。

拉姆


0
投票

其他建议的解决方案都不适合我,然后我了解到我们可以在 VB.NET 应用程序中使用 Excel 事件,并使用“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

'Wb = handle to your workbook in Excel'
Public Sub Exit_cell_edit_mode(Wb as Workbook)
    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'
    Wb.Close()  'This command will trigger the WorkbookBeforeClose 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

-1
投票

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

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


-1
投票

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

函数 ExcelIsEditing() 作为布尔值 Excel 正在编辑 = False

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

结束功能

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

© www.soinside.com 2019 - 2024. All rights reserved.