有没有办法在Excel工作簿对象上设置临时标志?

时间:2011-03-07 16:11:58

标签: c# excel vba interop

我有一个C#帮助程序类(ExcelMacroHelper),可以帮助将VBA宏代码注入打开的Excel工作簿并运行生成的宏。我刚刚意识到以下步骤会破坏我的代码:

  1. C#应用程序将宏代码注入活动工作簿,这会导致ExcelMacroHelper将其状态标记为准备运行宏

  2. 用户在Excel中切换到另一个工作簿。

  3. C#应用程序尝试运行宏。 ExcelMacroHelper会认为它已准备好运行宏,但是VBA代码被注入到不同的工作簿中,因此调用将失败。

  4. 要解决这个问题,我想我需要一些方法在Workbook对象上设置一个临时属性,表明我的宏代码已经注入其中,或者至少是一种维护{{1已被处理的s。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

您可以使用名称来保存值(以及范围引用等)

在伪代码中

if not (name already exists) then
    Set nm = workbook.Names.add("Injected")
    nm.Value = False
    nm.Visable = False
end if

if nm.value = False
    //Inject Code
    nm.value = true
endif

注意:测试名称是否存在的最简单方法是尝试访问它并处理错误(如果不存在)

答案 1 :(得分:0)

您可以使用TagWorkbook属性。

当您注入代码时,您可以执行以下操作:

public class ExcelMacroHelper
{
   public static void Inject(Workbook workbook)
   {
       if ((workbook.Tag as String != "Injected"))
       {
          //Inject the code

           workbook.Tag = "Injected";
       }
   }
}

答案 2 :(得分:0)

我最终使用了自定义文档属性。像这样:

private bool needToInjectMacroCode() {
    // Get custom document property with name tagPropertyName

    object properties, property, propertyValue;

    properties = excel.ActiveWorkbook.GetType().InvokeMember(
        "CustomDocumentProperties",
        BindingFlags.Default | BindingFlags.GetProperty,
        null, excel.ActiveWorkbook, null);

    try {
        property = properties.GetType().InvokeMember(
            "Item",
            BindingFlags.Default | BindingFlags.GetProperty,
            null, properties, new object[] { tagPropertyName });
    } catch (TargetInvocationException) {
        return true;
    }

    propertyValue = property.GetType().InvokeMember(
        "Value",
        BindingFlags.Default | BindingFlags.GetProperty,
        null, property, null);

    return (tagString != (propertyValue as string));
}

// ...

private void setMacroCodeInjected() {
    // Set custom property with name tagPropertyName to value tagString

    object properties = excel.ActiveWorkbook.GetType().InvokeMember(
        "CustomDocumentProperties",
        BindingFlags.Default | BindingFlags.GetProperty,
        null, excel.ActiveWorkbook, null);

    try {
        properties.GetType().InvokeMember(
            "Add",
            BindingFlags.Default | BindingFlags.InvokeMethod,
            null, properties, new object[] {
                tagPropertyName, false,
                Office.MsoDocProperties.msoPropertyTypeString,
                tagString
            });
    } catch (TargetInvocationException) {
        object property = properties.GetType().InvokeMember(
            "Item",
            BindingFlags.Default | BindingFlags.GetProperty,
            null, properties, new object[] { tagPropertyName });

        property.GetType().InvokeMember(
            "Value",
            BindingFlags.Default | BindingFlags.SetProperty,
            null, property, new object[] { tagString });
    }
}