我有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"文本并以分号结束,以便将整行代码放入范围变量中,或者即使这是有用的事情......
答案 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天。我在一个多星期内完成了它。