获取带有描述的Excel宏名称

时间:2011-07-06 15:21:32

标签: c# excel vba excel-vba vsto

我找到了许多使用自动化(example)从Excel获取宏名称的方法。它们大多是相同的,也不能1)检索宏描述(每个记录的宏可以使用Excel UI进行描述)或2)过滤掉普通的VBA函数(有Excel记录的宏,你有一个函数/宏)写自己)。似乎Excel将描述保留为源代码中的注释,但也在某些私有地方。如果删除代码注释,则Excel仍然可以看到描述。

我需要达到至少2)并且如果可能的话1)。我很欣赏C#或VBA解决方案,但真的会做任何事情。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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;
    }