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

q35jwt9p  于 2023-05-08  发布在  .NET
关注(0)|答案(6)|浏览(177)

我有一个带功能区的Excel 2007加载项。功能区中的一个按钮会触发对当前工作表的大量操作,出于速度和用户体验的原因,我在操作过程中设置了各种Excel.Application属性,如InteractiveEnableEventsfalse
我的问题是功能区不会窃取焦点,因此如果用户在单击功能区按钮时正在编辑单元格,则在设置Application.Interactive = false时会引发异常,因为Excel认为用户仍在编辑单元格。
是否有一种方法可以通过保存或放弃对单元格所做的更改来停止编辑?
看起来Range.DiscardChanges()可能会解决我的问题,但它在2007年的API中不可用。
编辑:似乎Range.DiscardChanges()是基于OLAP数据源的范围,所以它无论如何都不能解决我的问题。
编辑:我试过在另一个手机上打电话给Range.Activate()。虽然我确实看到GUI中的单元格焦点发生了变化,但还是抛出了异常。Range.Select()不做任何事情。

kx7yvsdv

kx7yvsdv1#

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

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/

ckx4rj1h

ckx4rj1h2#

因此,在四处寻找了几天并在MSDN上询问之后,最终的答案是API中根本没有任何内容,如果不使用黑客解决方案1,这是不可能的。
Excel本身处理这类事情的方式只是在用户编辑时使其菜单变灰,所以我这样做是为了与主机应用程序保持一致。
1:Hacky,因为像使用SendKeys这样的技术需要返回到GUI以确保操作被处理,然后调用要求单元格不在编辑中的方法。在一个地方这样做很好,但是对Excel Interop的每个方法调用都这样做是疯狂的。

ujv3wf0j

ujv3wf0j3#

现在回答可能为时已晚。但是想想有人在寻找解决方案的时候会用这个技巧。
由于某种原因,sendkeys和Cells/Range激活命令没有运行。
解决这个问题的唯一方法是将焦点更改为另一个工作表,然后返回到当前工作表以欺骗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();
    }

希望这能帮上忙。
公羊

xggvc2p6

xggvc2p64#

其他建议的解决方案都不适合我,然后我发现我们可以在互操作中使用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

Public Sub Exit_cell_edit_mode()
    If Not Is_in_edit_mode() Then Exit Sub

    'initiates closing the worksheet, which forces exit 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'
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
smdnsysy

smdnsysy5#

如果选择另一个单元格或所有单元格,错误是否消失?
private void myFunction() { xlSheet.Cells.Select(); //the rest of the work }

wz3gfoph

wz3gfoph6#

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

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

结束函数
这是我能想到的最好的:_(

相关问题