Using the MS Scripting Control as a Function/Expression Evaluator
Michael Edey - edey@hotmail.com
It just so happened that I saw your note about articles as I happened upon an interesting technique. I did a quick search and did not find (though I might have, if I looked harder :) an article on using the MS Scripting Control as a function/expression evaluator.
There were several reasons why I thought that this control would be appropriate:
1) it's free, and most systems prob. already have it installed
2) it's
flexible, scripts can be written in what ever languages there are installed
3) it's easy to setup & call, if you don't need automation objects.
I've attached a (really) simple project that demonstrates how easy it can be to use this control for this particular purpose.
unit Unit1;Using this project is easy, type in an expression in Edit1, hit the button, and get the result in Edit2. The expression can be any valid expression in the currently selected language, so you could try any of these:interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, comObj,
StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
script : variant; //the refrence to our instance of the scripting engineimplementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
script := createOLEObject('ScriptControl');
script.language := 'JScript'; //this can be set, even at runtime, to any available language
end;procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2.Text := script.eval(Edit1.Text);
end;end.
3+4Perhaps you'd rather not have to deal with the math object directly? Well, you can add functions to the scripting control's name space rather easily:
123*321
Math.sin(Math.PI/4)*Math.sqrt(2)
script.addCode('funtion sin(num){return math.sin(num);};');Now instead of haveing to call Math.sin, you can just can call sin(). You can even introduce entirly new function, complete with loops and such, as evidenced by this factorial function:
script.addCode('function factorial(num){result=1;for(ix=1;ix<=num;ix++){result = result*ix;};return result;};');The expression to be evaluated can even be a script. Want to know what the sum of all the factorials from 1! to 20! is? try putting this in the edit box:
r=0;for(iy=1;iy<=20;iy++){r = r+factorial(iy);};Voila my little app returns 2.56132749411182E+18 immediatley. this function required, what,95 mul's & 19 adds plus the overhead of the loops (96 of them) and the scripted function call & the conversion of the input from a string to a float (prob.) and back to a string again - Yet it all happened immediately. I'm sure it's fast enough :)
The control also has (among others) a run method, for executing functions that have been added like the sin & factorial functions here. So if you know a said function is available you could try something like this:
procedure TForm1.Button1Click(Sender: TObject);So, while it may take some extra work to get the scripting control to access VCL's (that don't implement access through an IDispatch interface) it's a snap to integrate it for most other purposes.
begin
Edit2.Text := script.Run('factorial',edit1.text);
end;
--Mike