Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有办法在Excel工作簿对象上设置临时标志?_C#_Excel_Vba_Interop - Fatal编程技术网

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

C# 有没有办法在Excel工作簿对象上设置临时标志?,c#,excel,vba,interop,C#,Excel,Vba,Interop,我有一个C#helper类(ExcelMacroHelper),它帮助将VBA宏代码注入打开的Excel工作簿并运行生成的宏。我刚刚意识到以下步骤会破坏我的代码: C#应用程序将宏代码注入活动工作簿,这会导致ExcelMacroHelper将其状态标记为准备运行宏 用户切换到Excel中的其他工作簿 C#应用程序尝试运行宏。ExcelMacroHelper将认为它已准备好运行宏,但VBA代码已插入到其他工作簿中,因此调用将失败 为了解决这个问题,我想我需要在工作簿对象上设置一个临时属性,表明我的

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

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

  • 用户切换到Excel中的其他工作簿

  • C#应用程序尝试运行宏。
    ExcelMacroHelper
    将认为它已准备好运行宏,但VBA代码已插入到其他工作簿中,因此调用将失败

  • 为了解决这个问题,我想我需要在
    工作簿
    对象上设置一个临时属性,表明我的宏代码已被注入该对象,或者至少需要一种方法来维护已处理的
    工作簿
    列表。有什么想法吗?

    您可以使用的属性

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

    public class ExcelMacroHelper
    {
       public static void Inject(Workbook workbook)
       {
           if ((workbook.Tag as String != "Injected"))
           {
              //Inject the code
    
               workbook.Tag = "Injected";
           }
       }
    }
    
    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 });
        }
    }
    

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

    伪码

    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
    

    注意:测试名称是否存在的最简单方法是尝试访问该名称,如果名称不存在,则处理错误。大概是这样的:

    public class ExcelMacroHelper
    {
       public static void Inject(Workbook workbook)
       {
           if ((workbook.Tag as String != "Injected"))
           {
              //Inject the code
    
               workbook.Tag = "Injected";
           }
       }
    }
    
    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 });
        }
    }
    

    这似乎正是我想要的,除了
    工作簿
    对象没有
    标记
    属性(使用Office 2007)。@jnylen-这很奇怪。。。我刚刚启动了一个Office 2007工作簿项目(Visual Studio 2008),它有一个标记属性。我正在使用Microsoft.Office.Interop.Excel库和命名空间。似乎您正在使用VSTO Excel库。