Opto22‘s PAC Control can import IO variables from tag databases – which are simply CSV files, but there is no built in way to import strategy variables from a list/spreadsheet. To get around this limitation I created an AutoHotkey script that will take a CSV file and create PAC Control variables.
The AHK script expects a CSV file with a specific layout. It requires several columns in the following order:
Name – The name of your variable
Description – An optional description
Type – The Opto22 data type – type exactly as they are listed in PAC Control
Initialization – How you want the variable initialized: on download, on run or persistent
Initial Value – What you want the variable initialized to.
Length – The length of tables
Width – The size of strings
Points to Type – The data type a pointer variable points to – exactly as listed in PAC Control
The first row of the CSV file should contain the header row and will be ignored by the script. Also, any pointers that reference another variable in the csv file need to come after the referenced variable (Not immediately after, just some time after).
Here is a sample of CSV data.
Name,Description,Type,Initialization,Initial Value,Length,Width,Points to Type Int32,"Integer 32",Integer 32,download,1,,, Int64,Integer 64,Integer 64,run,-5,,, AnotherInt32,,Integer 32,persistent,,,, MyDownTimer,,Down Timer,,,,, MyUpTimer,,Up Timer,,,,, MyFloat,,Float,,,,, MyString,Test String,String,,,,10, ptrEB1,Pointers should be last if they initialize,Pointer,,Int64,,,Integer 64 Variable MyComm,,Communication Handle,tcp:my_server:255,,,, ntInt32,,Integer 32 Table,,,100,, ntInt64,,Integer 64 Table,,,100,, ftFloat,,Float Table,persistent,,100,, stString,,String Table,download,YoYo,50,4, ptPointers,Need some Pointers?,Pointer Table,download,,10,,
You can copy this into a text file and save it with a csv extension. You can use Excel or another spreadsheet program to edit this file or to build your list of variables, just be sure to save as a CSV file. Also, avoid the use of commas in your variable descriptions to avoid csv parsing issues.
The AHK script has some variables of it’s own that can be configure for your situation. The CSVPath will need to be set to where your CSV file is located. Edit: The script now prompts for the CSV location. There is a StopOnErrors flag that if set will stop the script as soon as a PAC Project variable cannot successfully be added, otherwise it will continue on and give you a list in notepad of the variables it could not create. There is also a DialogWait variable that may need to be increased if your particular system takes longer for the Add Variable dialog to close.
To run the script, make sure your PAC Control strategy is open and that no dialog boxes are currently open. Then you should be able to double-click on the AutoHotkey script and it will process your CSV file. Don’t press any keys or click anywhere while the script runs.
Below is the AHK script that does all the heavy lifting. Save this to a text file with a “ahk” extension for AutoHotkey to process it.
Edit: 12/28/2016 – The script now prompts for the CSV file location, and I made some improvements to make sure the script is sending keys to the correct location.
Edit: 2/14/2017 – Fixed a bug where the script would not detect variables that were already created in newer versions of PAC Control.
;Make sure you have a backup of your project file in case something goes wrong. ;Make this nonzero to stop when a variable cannot be created ;Otherwise the script will open notepad with a list of variables that could ;not be created. StopOnErrors=0 ;This is how long the script waits for the create variable dialog to close in seconds ;If the script starts typing in the wrong spot and causing all sorts of mischief, then ;increase this value. DialogWait=0.5 SetWorkingDir %A_ScriptDir% ;Open file dialog for user to select csv file FileSelectFile, CSVPath, 3,,, Comma-separated Values (*.csv) if !CSVPath Exit #NoEnv SendMode Input ErrorList := "" WinActivate, PAC Control WinWaitActive, PAC Control,,2 IfWinNotActive, PAC Control { MsgBox Could not activate PAC Control. Exit } ;Get to configure Variables WinMenuSelectItem, PAC Control,,Configure,Variables... WinWaitActive ,Configure Variables ahk_class #32770,,2 if ErrorLevel { MsgBox Could not open Configure Variables. Exit } Loop, Read, %CSVPath% { if A_Index > 1 ;Skip the heading { Loop, Parse, A_LoopReadLine, CSV { if A_Index = 1 Name=%A_Loopfield% else if A_Index = 2 Description=%A_Loopfield% else if A_Index = 3 DataType=%A_Loopfield% else if A_Index = 4 Initialization=%A_Loopfield% else if A_Index = 5 InitValue=%A_Loopfield% else if A_Index = 6 Length=%A_Loopfield% else if A_Index = 7 Width=%A_Loopfield% else if A_Index = 8 PointerType=%A_Loopfield% } WinWaitActive ,Configure Variables ahk_class #32770,,2 if ErrorLevel { MsgBox Expected Configure Variables to be the active window. Consider increasing the value in DialogWait. Exit } ;!t moves to type dropdown then C get to known position in list before going where we want SendInput !tc if DataType In Integer 32,Integer 64,Float { SendInput nn ;nn gets to Numeric Variables SendInput !a ;Wait for dialog to open WinWaitActive ,Add Variable ahk_class #32770,,%DialogWait% SendInput !n%Name%{TAB}%Description%{TAB} if DataType = Integer 64 SendInput i else if DataType = Float SendInput f SendInput {TAB} if Initialization = download SendInput {Down} else if Initialization = persistent SendInput {Down 2} SendInput {TAB}%InitValue%{Enter} } else if DataType In Up Timer,Down Timer { SendInput nn ;nn gets to Numeric Variables SendInput !a ;Wait for dialog to open WinWaitActive ,Add Variable ahk_class #32770,,%DialogWait% SendInput !n%Name%{TAB}%Description%{TAB} if DataType = Up Timer SendInput u else if DataType = Down Timer SendInput d SendInput {ENTER} } else if DataType In Integer 32 Table,Integer 64 Table,Float Table { SendInput n ;n gets to Numeric Tables SendInput !a ;Wait for dialog to open WinWaitActive ,Add Variable ahk_class #32770,,%DialogWait% SendInput !n%Name%{TAB}%Description%{TAB} if DataType = Integer 64 Table SendInput i else if DataType = Float Table SendInput f SendInput {TAB}%Length%{TAB} if Initialization = download SendInput {Down} else if Initialization = persistent SendInput {Down 2} SendInput {TAB}%InitValue%{Enter} } else if DataType = String { SendInput ss SendInput !a ;Wait for dialog to open WinWaitActive ,Add Variable ahk_class #32770,,%DialogWait% SendInput !n%Name%{TAB}%Description%{TAB} SendInput {TAB}%Width%{TAB} if Initialization = download SendInput {Down} else if Initialization = persistent SendInput {Down 2} SendInput {TAB}%InitValue%{Enter} } else if DataType = String Table { SendInput s SendInput !a ;Wait for dialog to open WinWaitActive ,Add Variable ahk_class #32770,,%DialogWait% SendInput !n%Name%{TAB}%Description%{TAB} SendInput {TAB}%Length%{TAB}%Width%{TAB} if Initialization = download SendInput {Down} else if Initialization = persistent SendInput {Down 2} SendInput {TAB}%InitValue%{Enter} } else if DataType = Pointer { SendInput pp SendInput !a ;Wait for dialog to open WinWaitActive ,Add Variable ahk_class #32770,,%DialogWait% SendInput !n%Name%{TAB}%Description%{TAB} SendInput {TAB}%PointerType%{TAB} if Initialization = download SendInput {Down} SendInput {TAB}%InitValue%{Enter} } else if DataType = Pointer Table { SendInput p SendInput !a ;Wait for dialog to open WinWaitActive ,Add Variable ahk_class #32770,,%DialogWait% SendInput !n%Name%{TAB}%Description%{TAB} SendInput {TAB}%Length%{TAB} if Initialization = download SendInput {Down} SendInput {Enter} } else if DataType = Communication Handle { SendInput c SendInput !a ;Wait for dialog to open WinWaitActive ,Add Variable ahk_class #32770,,%DialogWait% SendInput !n%Name%{TAB}%Description%{TAB 2} if Initialization = download SendInput {Down} else if Initialization = persistent SendInput {Down 2} SendInput {TAB}%InitValue%{Enter} } ;Make sure Add Variable Window closed WinWaitClose ,Add Variable ahk_class #32770,,%DialogWait% if ErrorLevel { if StopOnErrors { MsgBox Error adding variable. Exit } else { ErrorList := ErrorList . Name . "`n" SendInput {ESC} IfWinActive ,Add Variable ahk_class #32770 { WinWaitClose ,Add Variable ahk_class #32770,,%DialogWait% if ErrorLevel { SendInput {ESC} } } } } } } SendInput {ESC} if ErrorList { run, Notepad.exe,,,notePadPID WinWait, ahk_pid %notepadPID% WinActivate, ahk_pid %notepadPID% WinWaitActive, ahk_pid %notepadPID%,,2 IfWinActive, ahk_pid %notepadPID% SendInput % "The following variables were not able to be created:`n" . ErrorList }
Good luck!
Hi Philip,
I am a bit new to OPTO22 world, and am finding creating a huge number of almost identical variables pretty slow and time consuming using the normal method of doing them one by one. I can see that you had the same issue, but were smart enough to do something about it. However, I am a lesser person and even after reading your blog above, not sure how to go about implementing this. Where do you copy the script and how to you execute it. Can this be imported into PAC and run, or do I need to have AutoHotKey program i presume to run this script… Inputting this as a CSV file will allow for faster and better naming. It looks like just what I was looking for but not sure how to get started, any basic points on how to use your script and/or example would be helpful. Thanks in advance for 1) writing 2)sharing and possibly 3) getting me started on this. Cheers, Scott
LikeLike
Hi Scott,
Yes, you will need to have AutoHotKey installed. You can copy the script anywhere you like on your computer that has PAC Control installed on it – your documents folder would be a good place. As long as the script ends with .ahk, double clicking the file will automatically launch AutoHotKey and it will ask you for the location of your formatted CSV file. I would start with the CSV file I created and edit it to have the variable you want. Add a couple variables to the CSV, make sure your PAC Control project is open, and run the script to test if it works. You can add more variables to the CSV file and run the script again at anytime.
Also, be aware that newer versions of PAC Control have command line options for adding variables. Also, be sure to check out the Opto22 Forums – good place to get answers to questions.
Good luck!
LikeLike