2011-07-06 133 views
1

我發現了許多使用自動化從Excel獲取宏名稱的方法(example)。他們大多是相同的,都不能1)檢索宏描述(每個錄製的宏可以使用Excel UI的描述裝飾)或2)過濾掉普通的VBA功能(有Excel錄製的宏,並有funcs /宏,你是寫下你自己)。看起來好像Excel將源代碼中的註釋保留爲註釋,但也在某些私人位置。如果刪除代碼註釋,說明仍然對Excel可見。獲取帶描述的Excel宏名稱

我需要達到至少2),如果可能的話1)也是。我很感激C#或VBA解決方案,但真的有什麼可以做。

+1

你是什麼意思的「宏描述?」和「過濾出普通的VBA功能?」 –

+0

當您錄製宏時,您可以爲其分配描述。至於普通功能,我指的是任何手工製作的VBA功能。我需要區分這些和錄製的宏。 – wpfwannabe

+0

@Jean:謝謝你的反對。如果你甚至遠程熟悉這個主題,你會發現用編程方式使用Excel宏是遠遠不夠的。如果你知道Excel,那麼你也知道宏有描述。我應該花多少精力去問「如何獲得宏觀描述」?我無法彌補事實只是爲了彌補太少的話。你讓我看起來不好,但那是你的權利。 – wpfwannabe

回答

2

如果你在excel中記錄一個宏,將另一個「手寫」的文件添加到同一個模塊,然後將該模塊導出到一個文件中,你會看到錄製的宏有額外的屬性,這些屬性在手動輸入一個。

Sub RecordedMacro() 
Attribute RecordedMacro.VB_Description = "some description here" 
Attribute RecordedMacro.VB_ProcData.VB_Invoke_Func = "g\n14" 
' 
' RecordedMacro Macro 
' some description here 
' 
' Keyboard Shortcut: Ctrl+g 
' 
    Range("C8").Select 
    ActiveCell.FormulaR1C1 = "sfhsf" 

End Sub 

您可以使用代碼導出模塊,因此您可以解析導出的文件以查找這些屬性。

這對於使用VBA訪問/操縱VBE的內容一個很好的資源: http://www.cpearson.com/excel/vbe.aspx

2

我遇到同樣的問題,並通過一個網站的幫助下解決了它在那裏你可以read Excel VBA macros and functions through csharp。我做了一些改變,並提出了下面的解決方案。我收到一份包含可用宏的列表以及他們第一次創建時的描述。我使用正則表達式來解析描述。可能是一些更好的解決方案,但至少它適用於我的目的。

public List<Tuple<string,string>> GetAllMacrosInExcelFile(string fileName) { 

     List<Tuple<string,string>> listOfMacros = new List<Tuple<string,string>>(); 

     var excel = new Excel.Application(); 
     var workbook = excel.Workbooks.Open(fileName, false, true, Type.Missing, Type.Missing, Type.Missing, true, Type.Missing, Type.Missing, false, false, Type.Missing, false, true, Type.Missing); 

     var project = workbook.VBProject; 
     var projectName = project.Name; 
     var procedureType = Microsoft.Vbe.Interop.vbext_ProcKind.vbext_pk_Proc; 

     foreach (var component in project.VBComponents) { 
      VBA.VBComponent vbComponent = component as VBA.VBComponent; 
      if (vbComponent != null) { 
       string componentName = vbComponent.Name; 
       var componentCode = vbComponent.CodeModule; 
       int componentCodeLines = componentCode.CountOfLines; 

       int line = 1; 
       while (line < componentCodeLines) { 
        string procedureName = componentCode.get_ProcOfLine(line, out procedureType); 
        if (procedureName != string.Empty) { 
         int procedureLines = componentCode.get_ProcCountLines(procedureName, procedureType); 
         int procedureStartLine = componentCode.get_ProcStartLine(procedureName, procedureType); 
         var allCodeLines = componentCode.get_Lines(procedureStartLine, procedureLines); 

         Regex regex = new Regex("Macro\r\n' (.*?)\r\n'\r\n\r\n'"); 
         var v = regex.Match(allCodeLines); 
         string comments = v.Groups[1].ToString(); 

         if (comments.IsEmpty()) { comments = "No comment is written for this Macro"; } 

         line += procedureLines - 1; 
         listOfMacros.Add(procedureName.Tuple(comments)); 
        } 
        line++; 
       } 
      } 
     } 
     excel.Quit(); 
     return listOfMacros; 
    }