我正在尝试运行由Private Sub Worksheet_Change(ByVal target As Range)
事件驱动的代码。我希望我的代码能够实时分析数据,而不是每15-20分钟输入一大块数据来分析新数据。
我尝试运行的数据是通过API从数据服务输入的,并直播到我的Excel工作表中。我使用一个名为CMED.MA
的函数,它有两个不同的参数(在当前时刻无关紧要)。它提供了向下滚动的行,因此您有一行,然后新数据将在下一行等中提供,等等。有时它相当快(每隔几秒)......其他时间它非常停滞(每隔几分钟左右)。 注意:数据一次只能以单行提供。
我创建了一堆函数并将它们存储在一个单独的模块中(所有Public Functions
),以保持工作表模块的清洁和简短。
问题
在写了一小部分内容以涵盖实时数据的分析后,我想测试它(谢天谢地决定测试它),现在当我试图让代码在工作表模块中生效时,它完全崩溃了。我必须关闭源数据源,以便我可以禁用工作表模块中的代码。我的代码有任何想法或明显的问题吗?这是我第一次尝试使用Worksheet_Change
事件
工作表模块代码
Option Explicit
Private Sub Worksheet_Change(ByVal target As Range)
Dim initialTradeStructure As String, finalTradeStructure As String, rawStructure As String
'RFQs
If target.Item(1, 3) = "RequestForQuote" Then
'Do Nothing....no analysis of RFQs is necessary....will be filtered later
'Screen Trades
ElseIf target.Item(1, 3) = "GlobexTrades" Then
rawStructure = target.Item(1, 2)
initialTradeStructure = Right(rawStructure, Len(rawStructure) - 4)
'Bulk of analaysis conducted in analsyis engine to keep worksheet code clean/short
finalTradeStructure = OptionStructureAnalysisEngine(initialTradeStructure, target)
'Block screen represented as Multileg in datafeed structure
ElseIf target.Item(1, 3) = "Block" Then
If target.Item(1, 17) = "TRUE" Then
rawStructure = target.Item(1, 2)
initialTradeStructure = Right(rawStructure, Len(rawStructure) - 4)
'Bulk of analysis conducted in analysis engine to keep worksheet code clean/short
finalTradeStructure = OptionStructureAnalysisEngine(initialTradeStructure, target)
ElseIf target.Item(1, 17) = "FALSE" And target.Item(1, 16) = "FALSE" Then
'Live block trade
Else
'Do Nothing....No analysis of single block legs is necessary
End If
End If
If Not finalTradeStructure = "Nothing" Then
target.Item(1, 1) = finalTradeStructure
End If
End Sub
功能模块
Public Function OptionStructureAnalysisEngine(tradeStructure As String, tradeDataRange As Range) As String
'analyzes and translates tradeStructure and dataRange
'Driver
Dim structureAssemblyString As String, optionType As String
'Tests for / in tradeStructure to determine if it's a LIVE option trade or if it's a multi leg structure
If InStr(1, tradeStructure, "/") < 1 Then
'Declares LIVE and option Type
structureAssemblyString = "LIVE " & GetOptionCodes(Mid(tradeStructure, 8, 2)) & " " & TranslateExpirationDate(Mid(tradeStructure, 11, 6)) _
& " " & GetCallOrPut(Mid(tradeStructure, 18, 1))
Else
'Place holder for multileg structures
structureAssemblyString = "Nothing"
End If
OptionStructureAnalysisEngine = structureAssemblyString
End Function
Public Function GetOptionCodes(optionType As String) As String
Select Case optionType
Case "LO"
GetOptionCodes = "WTI American"
Case "OH"
GetOptionCodes = "HO American"
Case "OB"
GetOptionCodes = "RB American"
Case "LN"
GetOptionCodes = "NG European"
End Select
End Function
Public Function TranslateExpirationDate(expirationDate As Double) As String
Select Case Right(expirationDate, 2)
Case 1
TranslateExpirationDate = "F" & Mid(expirationDate, 3, 2)
Case 2
TranslateExpirationDate = "G" & Mid(expirationDate, 3, 2)
Case 3
TranslateExpirationDate = "H" & Mid(expirationDate, 3, 2)
Case 4
TranslateExpirationDate = "J" & Mid(expirationDate, 3, 2)
Case 5
TranslateExpirationDate = "K" & Mid(expirationDate, 3, 2)
Case 6
TranslateExpirationDate = "M" & Mid(expirationDate, 3, 2)
Case 7
TranslateExpirationDate = "N" & Mid(expirationDate, 3, 2)
Case 8
TranslateExpirationDate = "Q" & Mid(expirationDate, 3, 2)
Case 9
TranslateExpirationDate = "U" & Mid(expirationDate, 3, 2)
Case 10
TranslateExpirationDate = "V" & Mid(expirationDate, 3, 2)
Case 11
TranslateExpirationDate = "X" & Mid(expirationDate, 3, 2)
Case 12
TranslateExpirationDate = "Z" & Mid(expirationDate, 3, 2)
End Select
End Function
Public Function GetCallOrPut(legOption As String) As String
'Translates C to Call and P to Put in option Structure
If legOption = "C" Then
GetCallOrPut = "Call"
ElseIf legOption = "P" Then
GetCallOrPut = "Put"
End If
End Function
答案 0 :(得分:1)
我看不到你的数据,也看不到这些子和函数如何与它们相互作用,但这是我对你的问题的盲目重写。我还重写了你的一个函数,使它更具可读性(对我而言)。
Sheet1 - 代码表
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Rows(1).Cells.Count = 18 Then
'set a custom error procedure; essentially revert to as normal as ppossible
On Error GoTo bm_Safe_Exit
'turn off event handling so if anything is changed, the sub procedure does not try to walk on top of itself
Application.EnableEvents = False
'only dim things now that you know that something is actually going to happen
Dim iTS As String, fTS As String, rS As String
'always determine text comparisons as case-insensitive
Select Case LCase(Target.Cells(1, 3).Value2)
caae "requestforquote"
'do nothing
caae "globextrades"
rS = Target.Cells(1, 2).Value2
initialTritsadeStructure = Right(rS, Len(rS) - 4)
'Bulk of analaysis conducted in analsyis engine to keep worksheet code clean/short
fTS = OptionStructureAnalysisEngine(iTS, Target)
'Block screen represented as Multileg in datafeed structure
caae "block"
'Is this actually TRUE/FALSE or text...????!!!?????
Select Case UCase(Target.Item(1, 17).Text)
Case "TRUE"
rS = Target.Item(1, 2).Value2
iTS = Right(rS, Len(rS) - 4)
Case "FALSE"
'Bulk of analysis conducted in analysis engine to keep worksheet code clean/short
fTS = OptionStructureAnalysisEngine(iTS, Target.Cells(1, 1)) '<~~ need to know which of a typical target's 18 cells to throw into this
Case Else
'do nothing
End Select
Case Else
'do nothing
End Select
End If
If Not fTS = "Nothing" And CBool(Len(fTS)) Then
Target.Item(1, 1) = fTS
End If
bm_Safe_Exit:
Application.EnableEvents = True
End Sub
Module1代码表
Option Explicit
Public Function OptionStructureAnalysisEngine(tradeStructure As String, tradeDataRange As Range) As String
'analyzes and translates tradeStructure and dataRange
'Driver
Dim structureAssemblyString As String, optionType As String
'Tests for / in tradeStructure to determine if it's a LIVE option trade or if it's a multi leg structure
If InStr(1, tradeStructure, "/") < 1 Then
'Declares LIVE and option Type
structureAssemblyString = "LIVE " & GetOptionCodes(Mid(tradeStructure, 8, 2)) & " " & TranslateExpirationDate(Mid(tradeStructure, 11, 6)) _
& " " & GetCallOrPut(Mid(tradeStructure, 18, 1))
Else
'Place holder for multileg structures
structureAssemblyString = "Nothing"
End If
OptionStructureAnalysisEngine = structureAssemblyString
End Function
Public Function GetOptionCodes(optionType As String) As String
Select Case UCase(optionType)
Case "LO"
GetOptionCodes = "WTI American"
Case "OH"
GetOptionCodes = "HO American"
Case "OB"
GetOptionCodes = "RB American"
Case "LN"
GetOptionCodes = "NG European"
Case Else
'do nothing
End Select
End Function
Public Function TranslateExpirationDate(expirationDate As Long) As String
Dim c As Integer, str As String
c = CInt(Right(expirationDate, 2))
str = Mid(expirationDate, 3, 2)
Select Case c
Case 1, 2, 3
TranslateExpirationDate = Chr(c + 69) & str
Case 4, 5
TranslateExpirationDate = Chr(c + 70) & str
Case 6, 7
TranslateExpirationDate = Chr(c + 71) & str
Case 8
TranslateExpirationDate = Chr(c + 72) & str
Case 9, 10
TranslateExpirationDate = Chr(c + 76) & str
Case 11
TranslateExpirationDate = Chr(c + 77) & str
Case 12
TranslateExpirationDate = Chr(c + 78) & str
Case Else
'do nothing
End Select
End Function
Public Function GetCallOrPut(legOption As String) As String
Select Case UCase(legOption)
Case "C"
GetCallOrPut = "Call"
Case "P"
GetCallOrPut = "Put"
Case Else
'do nothing
End Select
End Function
如前所述,我是盲目的。如果您无法使用或根据自己的目的进行修改,请修改原始问题以包含Minimal, Complete, and Verifiable example(根据需要编辑示例数据)。
答案 1 :(得分:0)
该行说
target.Item(1, 1) = finalTradeStructure
可能会导致无限循环,因为如果它被执行,它将触发一个新的Change事件。
我建议您只看一个列(不是您可能修改的列),例如:
Option Explicit
Private Sub Worksheet_Change(ByVal target As Range)
Dim initialTradeStructure As String, finalTradeStructure As String, rawStructure As String
'See if the change affects something in column 3 and only process if it does
If Not Intersect(Target, Columns(3)) Is Nothing Then
With Target.Rows(1)
'RFQs
If .Cells(1, "D") = "RequestForQuote" Then
'Do Nothing....no analysis of RFQs is necessary....will be filtered later
'Screen Trades
ElseIf .Cells(1, "D") = "GlobexTrades" Then
rawStructure = .Cells(1, "C")
initialTradeStructure = Right(rawStructure, Len(rawStructure) - 4)
'Bulk of analaysis conducted in analsyis engine to keep worksheet code clean/short
finalTradeStructure = OptionStructureAnalysisEngine(initialTradeStructure, target)
'Block screen represented as Multileg in datafeed structure
ElseIf .Cells(1, "D") = "Block" Then
If .Cells(1, "R") = "TRUE" Then
rawStructure = .Cells(1, "C")
initialTradeStructure = Right(rawStructure, Len(rawStructure) - 4)
'Bulk of analysis conducted in analysis engine to keep worksheet code clean/short
finalTradeStructure = OptionStructureAnalysisEngine(initialTradeStructure, target)
ElseIf .Cells(1, "R") = "FALSE" And .Cells(1, "Q") = "FALSE" Then
'Live block trade
Else
'Do Nothing....No analysis of single block legs is necessary
End If
End If
If Not finalTradeStructure = "Nothing" Then
.Cells(1, "B") = finalTradeStructure
End If
End With
End If
End Sub
注意:我已将您的Target.Items(1,x)
格式更改为Target.Rows(1).Cells(1,x+1)
格式(将x + 1编码为实际的字母列名称),因为我认为这样可以更轻松地查看哪些列被提及。