Hello all,
I am in the process of trying to create a macro that will, through a combination of code and Regular Expressions, clean-up and apply consistant formatting to our library of SQL Scripts.
My macro consists of 2 parts. The first section loops through a collection of SQL key words (select, from, where, etc..) and uses the Find object to perform a Find / Replace All and convert all keywords to UPPERCASE.
Ex:
//Create list of literal string changes
Dim literals As New Dictionary(Of String, String)
With literals
.Add("and", "AND")
.Add("as", "AS")
.Add("begin", "BEGIN")
.Add("between", "BETWEEN")
//
//other keywords go here...
//
.Add("select", "SELECT")
.Add("set", "SET")
.Add("where", "WHERE")
.Add("with", "WITH")
End With
Dim f As Find = DTE.Find
With f
.Action = vsFindAction.vsFindActionReplaceAll
.Target = vsFindTarget.vsFindTargetCurrentDocument
.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
.MatchCase = False
.MatchWholeWord = True
.Backwards = False
.MatchInHiddenText = False
End With
For Each entry As KeyValuePair(Of String, String) In literals
f.FindWhat = entry.Key
f.ReplaceWith = entry.Value
f.Execute()
Next
Once this is finished, I loop through a second collection containing FindWhat and ReplaceWith regular expressions for anything more complex (such as ensuring that the body of all IF statements are wrapped in BEGIN / END blocks
Ex:
Dim expressions As New Dictionary(Of String, String)()
With expressions
//Find any spaces or tabs preceding a comma and zero or more spaces at the end of a line
//Strip all spaces / tabs, leaving just the comma
.Add(":b+,:b*$", ",")
//Find any comma that follows the beginning of a new line preceded by 0 or more spaces/ tabs
//Move the comma before the new-line, keep the same number of spaces / tabs after the new-line
.Add("\n{:b*},", ",\n\1")
//Find any instance of an IF statement not followed by a BEGIN / END block
//Wraps the line following the IF statement in a BEGIN / END block
.Add("^{:b*IF(.*)\n}{:b*}<~(BEGIN){(.*)}\n", "\1\2BEGIN\n\2\t\3\n\2END")
//Find any INSERT statement (INTO clause optional) that has following text on the same line
//Move the text following the INSERT statement down a line and indent it
.Add("^{:b*}INSERT:b*(INTO)*:b*{(.*)}\n", "\1INSERT INTO\n\1\t\2\n")
//Find any SELECT statement (DISTINCT clause optional) that has following text on the same line
//Move the text following the SELECT statement down a line and indent it
.Add("^{:b*}{SELECT (DISTINCT)*}:b*{(.+)}\n", "\1\2\n\1\t\3\n")
//Finds any instance of a JOIN clause split onto seperate lines
//puts the JOIN clause on a single line
.Add("{(INNER|LEFT|OUTER|RIGHT)}:b*(\n:b*)+JOIN", "\1 JOIN")
//Finds any instance of any default JOIN clause missing its INNER prefix
//adds the INNER prefix
.Add("~(INNER|LEFT|OUTER|RIGHT){:b+}JOIN", "\1INNER JOIN")
//more regular expressions go here...
End With
With f
.Action = vsFindAction.vsFindActionReplaceAll
.Target = vsFindTarget.vsFindTargetCurrentDocument
.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxRegExpr
.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
.MatchCase = False
.MatchWholeWord = False
.Backwards = False
.MatchInHiddenText = False
End With
For Each entry As KeyValuePair(Of String, String) In expressions
f.FindWhat = entry.Key
f.ReplaceWith = entry.Value
f.Execute()
Next
This is my first foray into programming macros for use in Visual Studio, so any feedback / comments / suggestions on my approach would be greatly appreciated...