Examples of Calculation Formulas

Converting a Collected Value

The following code sample converts a temperature value from degrees Celsius to degrees Fahrenheit.
Result=CurrentValue("Temp F")*(9/5)+32

Calculations Inside Formulas

The following code sample contains a calculation within a formula. In this case, we are taking the average of values of the tag Simulation00001 over the previous hour. Typically, use a polled trigger to schedule the execution of the formula.
Result=Calculation("Simulation00001","Average","Now-1hour","Now",Quality)

Conditional Calculation

The following code sample stores the value of a tag only if it is 100.
IF CurrentQuality("Simulation00001")=100 THEN 
Result=CurrentValue("Simulation00001")
END IF

Combining Tag Values and Assigning a Trigger

The following code sample adds current values of multiple tags using two calculation triggers.
Result=CurrentValue("SERVER1.Simulation00003")+CurrentValue("SERVER1.Simulation00006")
The calculation triggers used in the sample are SERVER1.Simulation0003 and SERVER1.Simulation0006. The calculation is triggered if the value of either Server1.Simulation0003 or Server1.Simulation0006 changes.

Using CreateObject in a Formula

The following code sample reads data from another Historian Server using the Historian OLE DB provider, and stores it in a destination tag. When using this example, specify the username and password.
'connection and recordset variables
Dim Cnxn
Dim rsCurrentValueFromOtherServer
'open connection
Set Cnxn = CreateObject("ADODB.Connection")
'connect to default server using current username and password
'establish connection
Cnxn.Open "Provider=ihOLEDB.iHistorian.1;User Id=;Password="
'Create and open first Recordset using Connection execute
Set rsCurrentValueFromOtherServer = CreateObject("ADODB.Recordset")
'Get the value from the other server
Set rsCurrentValueFromOtherServer = Cnxn.Execute("select value from ihRawData 
where SamplingMode=CurrentValue and tagname = Simulation00001") 
'Set the result to the current value of other tag
Result=rsCurrentValueFromOtherServer("Value")
'Clean up
IF rsCurrentValueFromOtherServer.State = adStateOpen THEN
rsCurrentValueFromOtherServer.Close
END IF
IF Cnxn.State = adStateOpen THEN Cnxn.Close
END IF
Set rsCurrentValueFromOtherServer = Nothing
Set Cnxn = Nothing

Using a File

The following code sample shows how to read and write text files during a calculation. You may have data in a file to use as input to a calculation, or you may want to write debug values to a text file instead of using the LogMessage function.
Dim filesys, writefile, count,readfile
'need to create a file system object since there is no
'file I/O built into VBScript
Set filesys = CreateObject("Scripting.FileSystemObject")
'open the text file, or create it if it does not exist
set readfile = filesys.OpenTextFile("C:\somefile.txt", 1, true)
'try to read from the file
IF readfile.AtEndOfLine <> true THEN
count= readfile.ReadAll
END IF
'add one to the number stored in the count count = count+1
'close the file for reading 
readfile.Close
'open the same file but for writing
Set writefile= filesys.OpenTextFile("C:\somefile.txt", 2, true)
'write the updated count writefile.Write count
'close file for writing 
writefile.Close
Result = count

Converting a Number to a String

If your device and collector expose data as numeric codes, you can change to a string description. This examples also demonstrates that a calculation can output a string.
DIM X
x=CurrentValue ("tag1")
select case x
case 1
Result="one"
case 2
Result="two"
case else
Result="other"
End select

Detecting Recovery Mode Inside a Formula

The following code sample detects the recovery mode or recalculation inside a formula. If there are individual tags, you do not want to perform a recovery.
Dim MAXDIFF, TimeDiff
'Maximum difference in timestamps allowed (Must be > 2,
'units = seconds) MAXDIFF = 10
'Calculate time difference
TimeDiff = DateDiff("s", CurrentTime(), Now)
'Compare times, if difference is < MAXDIFF seconds perform calc
If TimeDiff < MAXDIFF Then
'Place calculation to be performed here:
Result = CurrentValue("DENALI.Simulation00001") Else
'Place what is to be done when no calc is performed here
Result = Null
End If

Looping Through Data Using the SDK

The following code sample uses the SDK to perform a query on a data set. It determines the minimum raw value over a one-hour time period.
on error resume next
Dim MyServer 'As Historian_SDK.Server
Dim I
Dim J
Dim K
Dim strComment
Dim lngInterval
Dim TagCount
Dim strDataQuality
Dim iDataRecordset
Dim iDataValue
Dim lEndTime, lStartTime, lNumSamples
Dim lNumSeconds, lNumSamplesPerSecond
Dim RawMin
'Instantiate The SDK
Set MyServer = CreateObject("iHistorian_SDK.Server")
'Attempt Connection
If Not MyServer.Connect("DENALI", "administrator","") Then
result = err.description
else
Set iDataRecordset = MyServer.Data.NewRecordset
'Find the number of samples.
'build query
With iDataRecordset
.Criteria.Tagmask = "EIGER.Simulation00001"
.Criteria.StartTime = DateAdd("h",-1,Now)
.Criteria.EndTime = Now
.Criteria.SamplingMode = 4 'RawByTime
.Criteria.Direction = 1 'forward
.Fields.AllFields
'do query
If Not .QueryRecordset Then
result = err.description
End If
'Some Large number so that real samples are less
RawMin = 1000000
For I = 1 To iDataRecordset.Tags.Count
For J = 1 To iDataRecordset.Item(I).Count
Set iDataValue = iDataRecordset.Item(I).Item(J)
' if the value is good data quality
if iDataValue.DataQuality = 1 then
if iDataValue.Value < RawMin then
rawMin = iDataValue.Value
end if
end if
lNumSamples = lNumSamples + 1
Next
Next
End With
End If
Result = RawMin
'Disconnect from server
MyServer.Disconnect

Using an ADO Query

The following code sample uses a query combining Historian data with ADO data. In the example, you convert a collected value, number of barrels per day (BarrelsUsedToday), to a dollar amount. The code then obtains the price per barrel (CostOfBarrel) from the SQL server, and finally stores the total dollars in an integer tag (TotalCostToday).

You can also do this with a linked server and the Historian OLE DB provider, but this example maintains a history of the results.

Dim CostOfBarrel, BarrelsUsedToday, TotalCostToday
'Calculate the total number of barrels used over
'the previous 24hours.
BarrelsUsedToday = Calculation("BarrelsUsedTag","Total","Now 1Day","Now",Quality)
'Retrieve cost per barrel used
Dim SQLExpression
Dim Cnxn
Dim rsCurrentValue
SQLExpression = "SELECT Barrel_Cost AS Value1 FROM RawMaterial_Costs WHERE Barrel_Type = CrudeOil and
samplingmode = CurrentValue"
'open connection
Set Cnxn = CreateObject("ADODB.Connection")
'connect to default server using current username and password
'establish connection
Cnxn.Open "Provider=SQLOLEDB.1;User ID=sa; Password=;Initial Catalog=Northwind"
'Create and open first Recordset using Connection execute
Set rsCurrentValue = CreateObject("ADODB.Recordset")
'Get the value from the other server
Set rsCurrentValue= Cnxn.Execute(SQLExpression)
'Set the result to the current value of other tag
CostOfBarrel = rsCurrentValue("Value1")
'Clean up
If rsCurrentValue.State = adStateOpen then 
rsCurrentValue.Close
End If
If Cnxn.State = adStateOpen then
Cnxn.Close
End If
Set rsCurrentValue = Nothing
Set Cnxn = Nothing
'Retrieve number of barrels used
BarrelsUsedToday = Calculation("BarrelsUsed","Count","Now 1Day","Now",Quality)
'Calculate total cost of barrels today
TotalCostToday = CostOfBarrel * BarrelsUsedToday

Windows Performance Statistics Physical Memory Usage

The following code sample creates a formula that collects data reflecting private byte usage.
`Get a reference to the local data archiver process object
Set RawProc = GetObject("winmgmts:Win32_PerfRawdata_Perfproc_process.name='ihDataArchiver.'")
`Scale the virtual bytes number to a value within
`the tag's EGU range
result =RawProc.PrivateBytes *.001

Windows Performance Statistics Virtual Memory Usage

The following code sample creates a formula that collects data reflecting virtual byte usage.
`Get a reference to the local data archiver process object
                Set RawProc = GetObject("winmgmts:Win32_PerfRawdata_Perfproc_process.name='ihDataArchiver.'")
`Scale the virtual bytes number to a value within the
`tag's EGU range
result =RawProc.VirtualBytes *.0001

Determining Collector Downtime

The following code sample determines the amount of downtime, in seconds, that the Calculation collector has experienced over the last day. Downtime occurs when there are two consecutive bad quality data points for the pulse tag. If the last known data point for the pulse tag is bad quality, all the time between its timestamp and the current time is regarded as downtime. In the following sample, the pulse tag is configured to be polled, with a collection interval of one day.
Dim pulseTag, totalDownTime, startTime, endTime
Dim prevTime, prevQuality, lastPrevTime, lastPrevQuality 
pulseTag = "calcPulseTag"
totalDownTime = 0 
endTime = CurrentTime()
startTime = DateAdd("d", -1, endTime)
lastPrevTime = curTime lastPrevQuality = 0
Do
  'get the timestamp and quality of the tag value previous to the last one we checked
  On Error Resume Next
  prevTime = PreviousTime(pulseTag, lastPrevTime) 
  If Err.Number <> 0 Then
    'no more values for this tag exit gracefully
    Exit Do
End If
prevQuality = PreviousQuality(pulseTag, lastPrevTime)
'if we have two consecutive bad data points, add to the downtime
If prevQuality = 0 And lastPrevQuality = 0 Then
  If prevTime > startTime Then
    totalDownTime = totalDownTime + DateDiff("s", prevTime, lastPrevTime) 
Else
    totalDownTime = totalDownTime + DateDiff("s", startTime, lastPrevTime) 
End If
End If
  'store the timestamp and quality for comparison with the next values 
lastPrevQuality = prevQuality
  lastPrevTime = prevTime
Loop While lastPrevTime > startTime
Result = totalDownTime

Analyzing the Collected Data

The following code sample analyzes the collected data to determine the amount of time that a condition was true and had good quality in the last day.
Dim tagName, startTime, endTime
tagName = "testTag"
startTime = "Now 1Day" 
endTime = "Now"
Result = CalculationFilter(tagName, "TotalTimeGood", startTime, endTime, 100, tagName, "AfterTime", "Equal", 1)

Simulating Demand Polling

To simulate demand polling, create the following tags.
Tag Description
Polled Tag A polled tag with a collection interval of the longest period you want between raw samples. Do not enable collector or archive compression. This tag should point to the same source address as the unsolicited tag.
Unsolicited Tag An unsolicited tag with a 0 or 1 second collection interval. This tag ensures you will be notified whenever changes occur. This tag should point to the same source address as the polled tag.
Combined Tag An unsolicited calculation tag that is triggered by either the polled tag or the unsolicited tag, and combines the raw samples of both into a single tag. Use a 0 or 1 second collection interval and use the following formula:
dim timetag1 
dim timetag2 
dim tag1
dim tag2
Dim x
tag1 = "T20.di-1.F_CV"
tag2 = "t20.T20.DI-1.F_CV"
x = DateAdd("s", 1,CurrentTime) ' add 1 second to calc time
' Get the timestamp of the newest raw sample for tag1:
timetag1 = previousTime(tag1, x)
' Get the timestamp of the newest raw sample for tag2:
timetag2 = previousTime(tag2, x)
if timetag1 > timetag2 then
' If tag1 triggered me, then:
result = PreviousValue(tag1,CurrentTime)
else
' If tag2 triggered me, then:
result = PreviousValue(Tag1, CurrentTime)
end if