解析print语句以提取文本和变量

时间:2018-02-21 17:12:28

标签: parsing word-vba

我有2500个左右的打印语句需要重新格式化。典型的声明(在Tradestation EasyLanguage中)如下所示:

If Step15 then print(Datetime.CurrentTime.Format(HH_MM_SS), " STEP 15: AddPositionToGrid: Calling CreateStockPSP with REF values: ", uSymbol, " | ", RefSerPer, " | ", RefSerVal, " | ", PSPRefRange, " | ", "Reference");

所有开头都是"如果步骤"并以分号结束";"

文字值在引号内,如" STEP 15: AddPositionToGrid: Calling CreateStockPSP with REF values: "

变量名不在引号中。

我需要保留序列,然后创建一个新语句,以(以不同的格式)写入日志文件,如下所示:

Logstring = "";
LogString = LogString.concat(LogString, "Calling CreateStockPSP with TRADING values: ", uSymbol, " | ", TrdgSerPer, " | ", TrdgSerVal, " | ", PSPTrdgRange, " | ", "Trading");
WriteSysLog(LogString, "STEP 15", IndValue, "AddPositionToGrid");

我有一本手册(史蒂文罗马 - 写字词宏)列出了所有(我假设)可用于操作文本的命令。我无法评估每一个VBA命令以确定它是否有用,所以我希望之前做过类似事情的人可以指出我正确的方向。

我不是在寻找一个编码解决方案 - 只是我可以使用的适当VBA命令的一些建议。

我在想我可以使用Find命令和move(range)命令来逐步执行每个Text值 - 或以某种方式使用Split(尽管有多个文本实例用引号括起来或用逗号括起来的变量)。我不想依赖Word行结尾 - 但我不确定如何或者是否可以创建一个以" IF Step"文本并以分号结束,以便将整行代码放入范围变量中,或者即使这是有用的事情......

1 个答案:

答案 0 :(得分:0)

此项目现已完成。我花了一些时间来解析我创建的每个VBA应用程序,希望这些代码可能对面临类似任务的任何人都有用。

本质上,我将Range和Selection功能与​​VBA的字符串处理结合使用,并且在Tradestation的开发环境中需要进行一些简单的搜索/替换。

该代码包含大约35,000行使用Tradestation的EasyLanguage编写的代码。我将此代码复制到word文档(docm)中,并创建了这些VBA程序来操作现有代码。

使用此代码完成首次通行证:

    Option Explicit

    Sub ReformatPrintLines()

    Dim CurrentSelection As Selection
    Dim CurrentRange As Range
    Dim NewRange As Range
    Dim InsertionRange As Range

    Dim StatementLength As Integer
    Dim CharLocation As Integer
    Dim LeftChars As Integer
    Dim RightChars As Integer
    Dim StringStart As Integer
    Dim StringEnd As Integer
    Dim StringLength As Integer
    Dim PrintIndicator As String
    Dim ElementStart As Integer
    Dim LogString1 As String
    Dim LogString2 As String


    Dim PrintStatement As String
    Dim SavedPrintStatement As String
    Dim FoundStmtCount As Integer            'count of print statements processed

    Dim DocEnd As Boolean
    Dim LineEnd As Boolean

    Dim TextToInsert As String
    Dim MaxLinesPerPrompt As Integer


    '========= end of Dim section ==============

    '========= Initial Setup ===================
    DocEnd = False
    MaxLinesPerPrompt = 0

    'Set CurrentRange to the full document
    Set CurrentRange = ActiveDocument.Content

    'Set NewRange to the full document also
    Set NewRange = CurrentRange.Duplicate


    '========= Loop to Find Print Statements ===
    Do
    With NewRange.Find
        .ClearFormatting
        .Text = "If Step*then print"
        .Forward = True
        .Wrap = wdFindStop
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = True
        .MatchSoundsLike = False
        End With
        NewRange.Find.Execute

        If Not NewRange.Find.Found Then Exit Do

        If NewRange.Find.Found Then
            FoundStmtCount = FoundStmtCount + 1
            Debug.Print "-", "PrintStmt found - Count is ", FoundStmtCount
            Debug.Print "A", FoundStmtCount
            NewRange.Select
            Debug.Print "B", NewRange.Text

            'Process the new PrintStatement

            '========== Replace If Step with "// If Step" at the start of the line
            With NewRange.Find
                .ClearFormatting
                .Replacement.ClearFormatting
                .Text = "If Step"
                .Replacement.Text = "// If xStep"
                .Forward = True
                .Wrap = wdFindStop
                .Format = False
                .MatchCase = False
                .MatchWholeWord = False
                .MatchWildcards = False
                .MatchSoundsLike = False
            End With
            NewRange.Find.Execute Replace:=wdReplaceAll
            Debug.Print "C", NewRange.Text

            ' Expand the selection to include the entire print statement
            Set CurrentSelection = Selection
            CurrentSelection.Extend ";"
            Debug.Print "D Expanded", CurrentSelection.Text
            PrintStatement = CurrentSelection.Text
            StatementLength = Len(PrintStatement)
            Debug.Print "E", PrintStatement

            '========== Get the Print Indicator Variable Name ===
            With CurrentSelection.Find
                .ClearFormatting
                .Text = "Step* "
                .Forward = True
                .Wrap = wdFindStop
                .Format = False
                .MatchCase = False
                .MatchWholeWord = False
                .MatchWildcards = True
                .MatchSoundsLike = False
            End With
            CurrentSelection.Find.Execute
            PrintIndicator = CurrentSelection.Text
            Debug.Print "F", PrintIndicator

            '========== Move start of the NewRange to next line
            NewRange.MoveStart wdWord
            NewRange.End = CurrentRange.End

            '========== Remove the printed Print Indicator from the PrintStatement
            CharLocation = InStr(1, PrintStatement, ":")
            Debug.Print "G1", StatementLength, CharLocation
            RightChars = StatementLength - (CharLocation + 1)
            Debug.Print "G2", " RightChars - ", RightChars
            PrintStatement = Right(PrintStatement, RightChars)
            Debug.Print "G3", PrintStatement
            StatementLength = RightChars
            Debug.Print "G4 - New StatementLength = ", StatementLength

            '========== Add back the opening quote ==
            PrintStatement = """" & PrintStatement
            StatementLength = StatementLength + 1
            Debug.Print "H1 - New StatementLength = ", StatementLength
            Debug.Print "H2 ", PrintStatement
            TextToInsert = PrintStatement
            Debug.Print "H3 TextToInsert = ", TextToInsert

            ' Expand the selection to include the entire print statement
            Set CurrentSelection = Selection
            CurrentSelection.Extend ";"
            Debug.Print "H4 Expanded", CurrentSelection.Text

            Selection.InsertParagraphAfter
            Debug.Print "J1", "New Paragraph Inserted"
            LogString1 = vbTab & vbTab & vbTab & "LogString = """""
            Selection.InsertAfter (LogString1)
            Selection.InsertParagraphAfter
            Debug.Print "J2", "LogString1 and new Para Inserted"

            'Assemble Logstring2
            LogString2 = vbTab & vbTab & vbTab & "LogString = LogString.concat(LogString, " & TextToInsert
            Debug.Print "K1", "LogString2 = ", LogString2
            Selection.InsertAfter (LogString2)
            Selection.InsertParagraphAfter
            Debug.Print "K2", "Concat Statement & Para inserted"

            ' WriteSysLog(LogString, "STEP 02", IndValue);
            TextToInsert = vbTab & vbTab & vbTab & "IndValue = False;"
            Selection.InsertAfter (TextToInsert)
            Selection.InsertParagraphAfter
            Debug.Print "K3", "Command to clear PrintIndicator inserted"

            TextToInsert = vbTab & vbTab & vbTab & "If " & PrintIndicator & " then IndValue = True;"
            Selection.InsertAfter (TextToInsert)
            Selection.InsertParagraphAfter
            Debug.Print "K4", "Command to set PrintIndicator inserted"

            TextToInsert = vbTab & vbTab & vbTab & "WriteSysLog(LogString, " & PrintIndicator & ", IndValue);"
            Selection.InsertAfter (TextToInsert)
            Selection.InsertParagraphAfter
            Debug.Print "L1", "Closing chars and New Paragraph Inserted"

            '========== Move start of the NewRange to next line
            NewRange.Start = Selection.End
            NewRange.End = CurrentRange.End

'            MaxLinesPerPrompt = MaxLinesPerPrompt + 1
'            If MaxLinesPerPrompt = 1 Then
'
'                MsgBox "Proceed to next nn Stmts?", vbOKCancel
'                If MsgBox("Proceed to next nn Stmts?", 1) <> 1 Then
'                    Exit Sub
'                End If 'If Msbox
'            MaxLinesPerPrompt = 0
'            End If 'MaxLinesPerPrompt
        End If 'NewRange.Find.Found
    Loop While DocEnd = False   'Do With NewRange.Find

    MsgBox "End of Document Reached"

    DocEnd = True

End Sub

评论部分允许我以nn间隔单步执行代码。

第二次通过 此代码设置MethodName变量

Option Explicit

' This VBA program extracts the MethodName and stored it in a local variable called MethodName

Sub AddMethodName()

    Dim MethodStatement As String
    Dim MethodName As String
    Dim CurrentSelection As Selection
    Dim CurrentRange As Range
    Dim NewRange As Range
    Dim InsertionRange As Range

    Dim MethodStartText As String

    Dim StatementLength As Integer
    Dim CharLocation As Integer
    Dim LeftChars As Integer
    Dim RightChars As Integer
    Dim StringStart As Integer
    Dim StringEnd As Integer
    Dim StringLength As Integer
    Dim FoundMethodCount As Integer
    Dim MaxLinesPerPrompt As Integer
    Dim DocEnd As Boolean
    Dim TextToAdd As String



    '========= Initial Setup ===================
    DocEnd = False
    MaxLinesPerPrompt = 0

    'Set CurrentRange to the full document
    Set CurrentRange = ActiveDocument.Content

    'Set NewRange to the full document also
    Set NewRange = CurrentRange.Duplicate


    '========= Loop to Find Method Statements ===
    Do
    With NewRange.Find
        .ClearFormatting
        .Text = "Method void *\("
        .Forward = True
        .Wrap = wdFindStop
        .Format = False
        .MatchCase = True
        .MatchWholeWord = False
        .MatchWildcards = True
        .MatchSoundsLike = False
        End With
        NewRange.Find.Execute

        If Not NewRange.Find.Found Then Exit Do

        If NewRange.Find.Found Then
            MethodStartText = NewRange.Text
            FoundMethodCount = FoundMethodCount + 1
            Debug.Print "-", "Method Found - Count is ", FoundMethodCount
            Debug.Print "A1", FoundMethodCount
            NewRange.Select
 '           Debug.Print "A2", NewRange.Text

            'Process the new Method Statement
            MethodStatement = NewRange.Text

            '========== Extract The Method Name
            StatementLength = Len(MethodStatement)
 '           Debug.Print "B1"; StatementLength

            RightChars = StatementLength - 12
 '           Debug.Print "B2", " RightChars - ", RightChars
            MethodName = Right(MethodStatement, RightChars)
            StatementLength = Len(MethodName)
            MethodName = Left(MethodName, StatementLength - 1)
            Debug.Print "B3", MethodName

            ' Expand the selection to include the entire print statement
            Set CurrentSelection = Selection
            CurrentSelection.Extend "\)"
'            Debug.Print "B4 Expanded", CurrentSelection.Text

            NewRange.MoveStart wdWord
            NewRange.End = CurrentRange.End

            'Find the Begin Statement and add the Method Name variable and value
            With NewRange.Find
                .ClearFormatting
                .Text = "begin"
                .Forward = True
                .Wrap = wdFindStop
                .Format = False
                .MatchCase = False
                .MatchWholeWord = False
                .MatchWildcards = False
                .MatchSoundsLike = False
            End With
                NewRange.Find.Execute

        If Not NewRange.Find.Found Then
            Debug.Print "C1 Could not find Search text ", NewRange.Find.Text
            Exit Do
        Else
            NewRange.Select
            Debug.Print "C2 Found Search text ", NewRange.Find.Text
            Set CurrentSelection = Selection
 '           Debug.Print "C3 CurrentSelection = ", CurrentSelection.Text


        End If

        ' Move the selection to the next word and insert a Return and the new Method value statement
            '========== Move start of the NewRange to next line
            NewRange.MoveStart wdWord
'            Debug.Print "D1 Moved NewRange Start 1 word "
            NewRange.End = CurrentRange.End
'           Debug.Print "D2 NewRange End = CurrentRange End "
            Selection.InsertParagraphAfter
'            Debug.Print "D3", "New Paragraph Inserted"
            TextToAdd = vbTab & "MethodName = " & """" & MethodName & """"
            Selection.InsertAfter (TextToAdd)
            Selection.InsertParagraphAfter
            Debug.Print "D4", "TextToAdd and new Para Inserted"
'
'            ' Expand the selection to include the entire print statement
'            Set CurrentSelection = Selection
'            CurrentSelection.Extend ";"
'            Debug.Print "D Expanded", CurrentSelection.Text
'            PrintStatement = CurrentSelection.Text
'            StatementLength = Len(PrintStatement)
'            Debug.Print "E", PrintStatement
'
'            '========== Get the Print Indicator Variable Name ===
'            With CurrentSelection.Find
'                .ClearFormatting
'                .Text = "Step* "
'                .Forward = True
'                .Wrap = wdFindStop
'                .Format = False
'                .MatchCase = False
'                .MatchWholeWord = False
'                .MatchWildcards = True
'                .MatchSoundsLike = False
'            End With
'            CurrentSelection.Find.Execute
'            PrintIndicator = CurrentSelection.Text
'            Debug.Print "F", PrintIndicator
'
'            '========== Move start of the NewRange to next line
'            NewRange.MoveStart wdWord
'            NewRange.End = CurrentRange.End

            '========== MsgBox for Operator Loop Control
            MaxLinesPerPrompt = MaxLinesPerPrompt + 1
            If MaxLinesPerPrompt = 1 Then

                MsgBox "Proceed to next 1 Stmts?", vbOKCancel
                If MsgBox("Proceed to next 1 Stmts?", 1) <> 1 Then
                    Exit Sub
                End If 'If Msbox
            MaxLinesPerPrompt = 0
            End If 'MaxLinesPerPrompt

        End If 'NewRange.Find.Found
    Loop While DocEnd = False   'Do With NewRange.Find

End Sub

第三次通过 第三遍将MethodName变量添加到已定义变量的方法中。手动添加了一个新的变量语句(复制和粘贴),之前没有定义任何变量。

Option Explicit

' This VBA program adds the MethodName variable to the vars: list

Sub AddMethodLocalVariables()

    Dim MethodStatement As String
    Dim MethodName As String
    Dim CurrentSelection As Selection
    Dim CurrentRange As Range
    Dim NewRange As Range
    Dim InsertionRange As Range

    Dim MethodStartText As String

    Dim StatementLength As Integer
    Dim CharLocation As Integer
    Dim LeftChars As Integer
    Dim RightChars As Integer
    Dim StringStart As Integer
    Dim StringEnd As Integer
    Dim StringLength As Integer
    Dim FoundMethodCount As Integer
    Dim MaxLinesPerPrompt As Integer
    Dim DocEnd As Boolean
    Dim TextToAdd As String



    '========= Initial Setup ===================
    DocEnd = False
    MaxLinesPerPrompt = 0

    'Set CurrentRange to the full document
    Set CurrentRange = ActiveDocument.Content

    'Set NewRange to the full document also
    Set NewRange = CurrentRange.Duplicate

    '========== Replace Vars: Statement
            With NewRange.Find
                .ClearFormatting
                .Replacement.ClearFormatting
                .Text = "vars:"
                .Replacement.Text = "vars:" & vbTab & "String" & vbTab & "MethodName" & ","
                .Forward = True
                .Wrap = wdFindStop
                .Format = False
                .MatchCase = False
                .MatchWholeWord = False
                .MatchWildcards = False
                .MatchSoundsLike = False
            End With
            NewRange.Find.Execute Replace:=wdReplaceAll

End Sub

最后的步骤 最后一步是在IndicatorName周围添加引号,这是我在WriteSysLog语句中遗漏的。左引号很容易被一个简单的搜索/替换操作所取代,但右手一个需要一些编码。

有趣的是,#通配符没有找到IndicatorName的最后一位数字,而是用一个有效的charlist [0123456789]替换它。

有一些指标名称带有另一个数字(abcd ......等),我手动替换它们。

在下面的代码中,我首先运行了第一个搜索/替换,然后将其注释掉并运行第二个代码块。

一个轻微的皱纹是Word用正斜率的引号字符代替普通引号字符 - 这些字符未被Tradestation开发环境认可。这是Tradestation DE中的一个简单修复,具有两个查找/替换操作。

Sub FixIndicatorNameWriteSysLog()

    Dim CurrentSelection As Selection
    Dim CurrentRange As Range
    Dim NewRange As Range
    Dim InsertionRange As Range
    Dim DocEnd As Boolean


    ' existing statement:   WriteSysLog(LogString, Step109 , IndValue, MethodName);
    ' should be:            WriteSysLog(LogString, "Step109" , IndValue, MethodName);

    'Find and Replace All instances of: WriteSysLog(LogString, S
    '                           with:   WriteSysLog(LogString, "S

    '========= Initial Setup ===================
    DocEnd = False

    'Set CurrentRange to the full document
    Set CurrentRange = ActiveDocument.Content

    'Set NewRange to the full document also
    Set NewRange = CurrentRange.Duplicate

    '========== Replace First Part of statement
'            With NewRange.Find
'                .ClearFormatting
'                .Replacement.ClearFormatting
'                .Text = "WriteSysLog(LogString, S"
'                .Replacement.Text = "WriteSysLog(LogString, ""S"
'                .Forward = True
'                .Wrap = wdFindStop
'                .Format = False
'                .MatchCase = False
'                .MatchWholeWord = False
'                .MatchWildcards = False
'                .MatchSoundsLike = False
'            End With
'            NewRange.Find.Execute Replace:=wdReplaceAll

    '========== Replace Second Part of statement
        Do
            '== Find the last character of the Indicator Name
            With NewRange.Find
                .ClearFormatting
                .Text = "[0123456789] , IndValue, MethodName"
                .Forward = True
                .Wrap = wdFindStop
                .Format = False
                .MatchCase = False
                .MatchWholeWord = False
                .MatchWildcards = True
                .MatchSoundsLike = False
            End With
            NewRange.Find.Execute

            If NewRange.Find.Found Then
                NewRange.Select
                Debug.Print "C Found an instance"

                Set CurrentSelection = Selection
                Debug.Print "D Found Next Instance", CurrentSelection.Text
             End If


            '========= Insert a quote symbol after the last digit of the indicator name ===
            Set CurrentSelection = Selection
            Debug.Print "E", CurrentSelection.Text

            '== Find the last character of the Indicator Name
            With Selection.Find
              .ClearFormatting
                .Replacement.ClearFormatting
                .Text = " , Ind"
                .Replacement.Text = """, Ind"
                .Forward = True
                .Wrap = wdFindStop
                .Format = False
                .MatchCase = False
                .MatchWholeWord = False
                .MatchWildcards = False
                .MatchSoundsLike = False
            End With
            Selection.Find.Execute Replace:=wdReplaceAll
            Set CurrentSelection = Selection
            Debug.Print "F ReplacementMade", CurrentSelection.Text

            '========== Move start of the NewRange to next line
            NewRange.Start = Selection.End
            NewRange.End = CurrentRange.End
            Debug.Print "G Set the Search Start to the Next Line "

       Loop While DocEnd = False

End Sub

内容 这是我第一次涉足VBA for Word。我首先从亚马逊购买了一本书(由Steven Roman编写Word Macros),这本书很有用,但与大多数手册一样,在有用的例子上有点薄。

我曾希望其他StackOverflow用户之前可能已经做过这样的事情,并且能够节省我很多时间来探索手册并摆弄不同的方法来完成这项任务。但事实并非如此。尽管如此,手动更改这些打印语句大约需要5分钟。大约有2,700个陈述,所以大约225个小时的工作 - 将近30天。我在一个多星期内完成了它。