2011-03-07 59 views
0

我有一個C#幫助類(ExcelMacroHelper),它有助於將VBA宏代碼注入到打開的Excel工作簿中並運行生成的宏。我剛剛意識到,下面的步驟將打破我的代碼:有沒有辦法在Excel工作簿對象上設置臨時標誌?

  1. C#應用程序注入宏代碼到活動工作簿,這將導致ExcelMacroHelper,以紀念其狀態爲準備好運行宏

  2. 用戶交換機到Excel中的其他工作簿。

  3. C#應用程序試圖運行一個宏。 ExcelMacroHelper會認爲它已準備好運行宏,但VBA代碼被注入到不同的工作簿中,因此調用將失敗。

爲了解決這個問題,我想我需要設置表明我的宏代碼已注入,或至少維持Workbook個列表的方式Workbook對象上的一個臨時性質的某種方式,已經處理完畢。有任何想法嗎?

回答

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 }); 
    } 
} 
0

您可以使用WorkbookTag屬性。

當你注入的代碼,你可以做這樣的事情:

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

      workbook.Tag = "Injected"; 
     } 
    } 
} 
+0

這似乎正是我想要的,除了'工作簿'對象沒有'標記'屬性對我來說(使用Office 2007)。 – jnylen 2011-03-07 18:55:54

+0

@jnylen - 這很奇怪......我剛創建了一個Office 2007工作簿項目(Visual Studio 2008),它有一個標籤屬性。 – RQDQ 2011-03-07 19:59:19

+0

我正在使用Microsoft.Office.Interop.Excel庫和命名空間。您似乎可能會使用VSTO Excel庫。 – jnylen 2011-03-07 22:52:54

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 

注意:測試名稱是否存在的最簡單方法是嘗試訪問它並處理錯誤(如果不存在)

相關問題