Saturday, December 3, 2011

A Form Script Debugging System in MetaVision

Debugging vbscript that resides in forms in MetaVision is problematic. Runtime exceptions are often thrown without even the right message. I have, therefore, developped a debugging system that can be used in vbscripts in MetaVision to track function calls and provide information of scripting flow and runtime info.

The following script has to be added to a form:

Private Function Debug(strMsg)

If Not Scripts.CurrentUserType = "Beheerders" Then Exit Function

' Set environment variables
strFormName  = "MS Afspraken" ' Aanpassen per formulier
intPatientId = Scripts.CurrentPatientId
' Debug parameters aanpassen per database
intDebugLevelParamId = 12438 'Debug Level Debug parameter Id
intDebugFileParamId  = 12446 'Debug File Location Parameter to give optional file location
intDebugTagParamId   = 12445 'Debug Tag Parameter to add a tag to debug msg
' Debug levels
intLevelDebug   = 0
intLevelOff     = 1
intLevelSilent  = 2
intLevelMessage = 3
' Get Debug level
strSql = strSql & "Select TextId From TextSignals Where ParameterId = "
strSql = strSql & intDebugLevelParamId & " " 
If intPatientId > 0 Then strSql = strSql & "And PatientId = " & intPatientId & " "
strSql = strSql & "Order By ValidationTime Desc"
Set objRecordSet = Scripts.ExecuteStatement(strSql)
If Not objRecordSet.EOF Then intDebugLevel = objRecordSet.Fields("TextId").Value

If intDebugLevel > intLevelOff Then 
 strFileLocation = ""
 strDebugTag     = ""
 ' Get Debug file location
 If intDebugFileParamId > 0 Then
  strSql = "Select Value From FreeTextSignals "
  strSql = strSql & "Where ParameterId = " & intDebugFileParamId & " " 
  If intPatientId > 0 Then strSql = strSql & "And PatientId = " & intPatientId & " "
  strSql = strSql & "Order By ValidationTime Desc"
  Set objRecordSet = Scripts.ExecuteStatement(strSql)
  If Not objRecordSet.EOF Then strFileLocation = objRecordSet.Fields("Value").Value
 End IF
 ' Get Debug tag
 If intDebugTagParamId > 0 Then
  strSql = "Select Value From FreeTextSignals "
  strSql = strSql & "Where ParameterId = " & intDebugTagParamId & " " 
  If intPatientId > 0 Then strSql = strSql & "And PatientId = " & intPatientId & " "
  strSql = strSql & "Order By ValidationTime Desc"
  Set objRecordSet = Scripts.ExecuteStatement(strSql)
  If Not objRecordSet.EOF Then strDebugTag = objRecordSet.Fields("Value").Value
 End IF
  
 If intDebugLevel = intLevelMessage Then Scripts.MsgBox strMsg
 
 intForReading   = 1
 intForWriting   = 2
 intForAppending = 8 
 
 Set objFileSys = CreateObject("Scripting.FileSystemObject")
 If strFileLocation = "" Then strPath = "C:\mvlog.txt" Else strPath = strFileLocation
 
 If objFileSys.FileExists(strPath) Then
  If strDebugTag <> "" Then strLogText = strDebugTag & " "
  strLogText = strLogText & Now & ": " 
  strLogText = strLogText & strFormName & ", " 
  strLogText = strLogText & "Session: " & Scripts.CurrentSessionID & ", "
  strLogText = strLogText & Cstr(strMsg) & vbNewLine 

  Set objLogFile = objFileSys.OpenTextFile(strPath, intForAppending, True) 
  objLogFile.WriteLine(strLogText)
  objLogFile.Close
 End IF
End IF
End Function

First of all I have to apology for the length of the above function. This function is 65 lines! Normally, I try to keep function as simple as possible, let them do just one thing which typically results in function of about 10 lines max. But by putting everything an a single function it is easier to copy and paste (also ugly) this function in forms I need debugging.

The result is that at runtime I can start and/or change debugging for a particular patient in MetaVision. I can even debug the form in the formbuilder! This will look something like:

An Example of Debug level set to Message

In order to set the debug level for a particular patient there needs to be a 'Debug form' like:

The Debug Form

In my next blog entry I will go into more detail of how the debug function works

Scripting in MetaVision

In our hospital we use MetaVision as a PDMS (Patient Data Management System). It is a very flexible product, which is it's strength and also it's weakness. Part of the flexibility comes from the possibility to use vbscript as a scripting language to automate tasks, processes, data analyses and/or create user forms.

I will publish my experiences with using scripting in MetaVision.

The first challenge of using vbscript in MetaVision, specifically in forms, is debugging. Debugging script in MetaVision forms is difficult. Moreover, vbscript exceptions thrown at runtime tend to be misleading! This can be a very frustrating trap, in which I have fallen many times. Therefore, the first thing you should do when using vbscript is setup a debugging system.

The most obvious and simple way to debug vbscripts is using message boxes. The following vbscript can be used as a simple helper function that can act to test pre- and postconditions of functions:

Private Function AssertIsTrue(blnIsTrue, strMsg)

 If Not blnIsTrue Then Scripts.MsgBox strMsg

End Function

A precondition is the condition that has to be met for the function to work, and the post condition must be met by the result of the function.

The function can then be used as follows:

Private Function ClearComboBox(cboBox)

 '' Clears a multi select combobox
 AssertIsTrue cboBox.Name = "cboTextComboMulti", "cboBox is not valid"
 
 intUpper = cboBox.Count - 1
 For intIndex = 0 To intUpper
  If cboBox.Selected(Clng(intIndex)) Then _
   cboBox.Selected(Clng(intIndex)) = False
 Next

End Function

In this function I make sure nothing is selected in a combobox. The combobox is passed in, but because there is no type checking in vbscript, I cannot be sure that the parameter cboBox really references a combobox control. Hence the assertion.

In the next blog I will discuss a more advanced debugging solution.

Wednesday, June 29, 2011

A Generic Prescription Outcome Model

In medical science progress is measured in outcome. Epidemiology studies the occurrence relation between exposure and outcome. Patients can be exposed to a variety of factors, patient related, disease related and or treatment related. Also, treatment can be defined in the broadest sense in that any intervention in patient care can be regarded as an exposure that can influence outcome.

Computerized prescriber order entry systems (CPOE systems) fit can have an influence on patient outcome just as the treatment that is described using (or not using) these systems. Therefore, CPOE systems have to be studied and the occurence relation between the use of CPOE as an exposure and outcome is just as relevant as any other medical intervention research.

Defining outcome that can be measured is a challenge. Specifically, strict definitions have to be developed to facilitate comparable research results. This BLOG attempts to describe an outcome model that can be applied to research on CPOE systems.

A definition of outcome has to take into account the process of drug treatment in patients, because CPOE systems can affect every aspect of a conceptual treatment cycle:





1. Defining the treatment indication
2. Generating the drug prescription
3. Validate the drug prescription
4. Schedule the drug
5. Prepare the drug
6. Administer the drug
7. Evaluate the effects of the prescription


The effect of a CPOE can be measured at all of these 7 levels. Most of the time the of CPOE systems and the process of drug prescription is measured in terms of error. As each level in the medication cycle involves a process, things can go wrong in the process. The potential benefits of interventions in the process of drug prescription can be expressed in efficiency, both in time as in finance.