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

时间:2014-04-02 16:55:48

标签: c# excel c#-2.0 office-interop excel-udf

我正在创建一个实现IDTExtensibility2的Excel加载项,并且有一个函数使用Excel PublishObjects

从工作表中发布范围

我正在使用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
}

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

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

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

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

问题:有没有办法避免此计算模式重置?

我自己调用的函数不是问题,我总是可以在那里添加一些布尔标志,但是工作表会有其他函数,我不能调用它。

BTW,当从主线程调用DoWork时问题不存在,这特定于运行后台线程。

1 个答案:

答案 0 :(得分:0)

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

这是一个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