在后台线程中使用 PublishObject.Publish() 将重置工作簿的计算模式

本文关键字:工作簿 模式 计算 线程 后台 Publish PublishObject | 更新日期: 2023-09-27 17:56:26

我正在创建一个 Excel 加载项,该

加载项实现IDTExtensibility2并具有一个函数,该函数使用 Excel 的发布对象发布工作表中的范围

我正在使用Visual Studio 2008和Excel 2007,以下是我的代码:

public class AddIn : IDTExtensibility2
{
    private static Application s_Application;
    public string PublishRange(Range rng)
    {
        new Thread(() => DoWork(rng)).Start();
        return "OK";
    }
    private string DoWork(Range rng)
    {
        try
        {
            Worksheet sheet = rng.Parent as Worksheet;
            Workbook book = sheet.Parent as Workbook;
            string name = sheet.Name;
            string address = rng.get_Address(Type.Missing, 
                             Type.Missing, XlReferenceStyle.xlA1, 
                             Type.Missing, Type.Missing);
            book.PublishObjects.Add(
                             XlSourceType.xlSourceRange, @"c:'Temp'Output.htm",
                             name, address, XlHtmlType.xlHtmlStatic, "", "")
                         .Publish(true);
        }
        catch (Exception e)
        {
            return e.Message;
        }
    } 
    public void OnConnection(object application, ext_ConnectMode connectMode, 
                             object addInInst, ref Array custom)
    {
        s_Application = application as Application;
    }
    // implementation of other interface methods is omitted
}

上面的代码按预期工作,当我的工作簿处于自动公式计算模式时.htm我得到了输出。

但是,如果工作簿处于手动模式(并且在调试器中我看到s_Application.Calculation设置为 xlCalculationManual ),则第 Publish(true) 行将强制活动工作表上的所有 UDF 重新计算。

换句话说,在Publish(true)完成之前,我再次收到对我的PublishRange()方法的调用,但这次s_Application.Calculation设置为xlCalculationAutomatic

我还发现同一工作簿中其他工作表上的函数不受影响(不知道为什么)。

:有没有办法避免这种计算模式重置?

调用我自己的函数不是问题,我总是可以在其中添加一些布尔标志,但是工作表将具有其他函数,这些函数不得由我所做的任何事情调用。

顺便说一句,从主线程调用DoWork时不存在问题,这是特定于运行后台线程的。

在后台线程中使用 PublishObject.Publish() 将重置工作簿的计算模式

UDF 应始终将它们使用的所有单元格引用作为参数传入,否则 Excel 不知道何时在重新计算中调用它们(但也请注意,Excel 在确定最终计算序列的过程中可能会多次调用 UDF)。
也不确定您是否真的要使用活动表,因为这可能会改变。

这是一个在手动计算中不会调用两次的 VBA 版本。

Function zPublishRange(oRng As Range)
    Dim oPub As PublishObject
    On Error GoTo Fail
    Set oPub = oRng.Parent.Parent.PublishObjects.Add(xlSourceRange, "D:'Output.htm", oRng.Parent.Name, oRng.Address, xlHtmlStatic)
    oPub.Publish True
    zPublishRange = oRng.Parent.Parent.PublishObjects.Count
    Exit Function
Fail:
    zPublishRange = "Fail"
End Function