Skip to content

Commit 6b39886

Browse files
committed
Create README.md
1 parent cb98fc3 commit 6b39886

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

README.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# ![VBA Expressions](/docs/assets/img/VBA%20Expressions.png)
2+
[![GitHub](https://img.shields.io/github/license/ws-garcia/VBA-Expressions?style=plastic)](https://github.com/ws-garcia/VBA-Expressions/blob/master/LICENSE) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/ws-garcia/VBA-Expressions?style=plastic)](https://github.com/ws-garcia/VBA-Expressions/releases/latest)
3+
4+
## Introductory words
5+
VBA Expressions is a powerful mathematical expressions evaluator for VBA strings. The `VBAexpressions.cls` class serves as an intermediary between user interfaces and the main VBA/custom functions exposed through it. The main development goal of the class is to integrate it with [CSV Interface](https://github.com/ws-garcia/VBA-CSV-interface), with as minimal programming effort as possible, and to allow users to perform complex queries from CSV files using built-in and custom functions.
6+
7+
## Advantages
8+
* __Easy to use and integrate__.
9+
* __Basic math operators__: `+` `-` `*` `/` `\` `^` `!`
10+
* __Logical expressions__: `& (AND)` `| (OR)` `|| (XOR)`
11+
* __Binary relations__: `< <= <> >= = >`
12+
* __More than 20 built-in functions__: `Max`, `Min`, `Avg`, `Sin`, `Ceil`, `Floor`...
13+
* __Very flexible__: variables, constants and user-defined functions (UDFs) support.
14+
* __Implied multiplication for variables, constants and functions__: `5avg(2;abs(-3-7tan(5));9)-12pi-e+(7/sin(30)-4!)*min(cos(30);cos(150))` is valid expression; `5(2)` is not.
15+
* __Evaluation of arrays of expressions given as text strings, as in Java__: curly brackets are used to define arrays`{{...};{...}}`
16+
* __Floating point notation input support__: `-5E-5`, `(1.434E3+1000)*2/3.235E-5` are valid inputs.
17+
* __Free of external VBA dependencies__: does not use dll.
18+
19+
## Supported expressions
20+
21+
The evaluation approach used is similar to the one we humans use: divide the function into sub-expressions, create a symbolic string to build an expression evaluation flow, split the sub-expressions into chunks of operations (tokens) by tokenization, evaluate all the tokens.
22+
23+
The module can evaluate mathematical expressions such as:
24+
25+
+ `5*avg(2;abs(-3-7*tan(5));9)-12*pi-e+(7/sin(30)-4!)*min(cos(30);cos(150))`
26+
+ `min(cos(sin(30))+2^2;1)`
27+
+ \* `GCD(1280;240;100;30*cos(0);10*DET({{sin(atn(1)*2); 0; 0}; {0; 2; 0}; {0; 0; 3}}))`
28+
29+
\*`GCD` and `DET` are user-defined functions (UDF).
30+
31+
Allowed expressions must follow the following grammar:
32+
33+
```
34+
Expression = ([{"("}] SubExpr [{Operator [{"("}] SubExpr [{")"}]}] [{")"}] | {["("] ["{"] List [{";" List}] ["}"] [")"]}
35+
SubExpr = Token [{Operator Token}]
36+
Token = [{Unary}] Argument [(Operator | Function) ["("] [{Unary}] Argument [")"]]
37+
Argument = (List | Variable | Operand)
38+
List = ["{"] SubExpr [{";" SubExpr}] ["}"]
39+
Unary = "-" | "+" | ~
40+
Operand = ({Digit} ["."] [{Digit}] ["E"("-" | "+"){Digit}] | (True | False))
41+
Variable = Alphabet [{Decimal}] [{(Digit | Alphabet)}]
42+
Alphabet = "A-Z" | "a-z"
43+
Decimal = "."
44+
Digit = "0-9"
45+
Operator = "+" | "-" | "\*" | "/" | "\" | "^" | "%" | "<" | "<=" | "<>" | ">" | ">=" | "=" | "&" | "|" | "||"
46+
Function = "abs" | "sin" | "cos" | "min" |...|[UDF]
47+
```
48+
49+
## Operators precedence
50+
VBA expressions uses the following precedence rules to evaluate mathematical expressions:
51+
52+
1. `()` Grouping: evaluates functions arguments as well.
53+
2. `! - +` Unary operators: exponentiation is the only operation that violates this. Ex.: `-2 ^ 2 = -4 | (-2) ^ 2 = 4`.
54+
3. `^` Exponentiation: Although Excel and Matlab evaluate nested exponentiations from left to right, Google, mathematicians and several modern programming languages, such as Perl, Python and Ruby, evaluate this operation from right to left. VBA expressions also evals in Python way: a^b^c = a^(b^c).
55+
4. `\* / % ` Multiplication, division, modulo: from left to right.
56+
5. `+ -` Addition and subtraction: from left to right.
57+
6. `< <= <> >= = >` Binary relations.
58+
7. `~` Logical negation.
59+
8. `&` Logical AND.
60+
9. `||` Logical XOR.
61+
10. `|` Logical OR.
62+
63+
## Variables
64+
Users can enter variables and set/assign their values for the calculations. Variable names must meet the following requirements:
65+
1. Start with a letter.
66+
2. End in a letter or number. `"x.1"`, `"number1"`, `"value.a"` are valid variable names.
67+
3. A variable named `"A"` is distinct from another variable named `"a"`, since variables are case-sensitive. This rule is broken by the constant `PI`, since `PI=Pi=pi=pI`.
68+
4. The token `"E"` cannot be used as variable due this token is reserved for floating point computation. For example, the expression `"2.5pi+3.5e"` will be evaluated to `~17.3679680`, but a expression like `"2.5pi+3.5E"` will return an error.
69+
70+
## User-defined functions (UDF)
71+
Users can register custom modules to expose and use their functions through the VBAcallBack.cls module. All UDFs must have a single Variant argument that will receive an one-dimensional array of strings (one element for each function argument).
72+
73+
## Working with arrays
74+
VBA expressions can evaluate matrix functions whose arguments are given as arrays/vectors, using a syntax like [Java](https://www.w3schools.com/java/java_arrays.asp). The following expression will calculate the determinant (`DET`) of a matrix composed of 3 vectors with 3 elements each:
75+
76+
`DET({{sin(atn(1)\*2); 0; 0}; {0; 2; 0}; {0; 0; 3}})`
77+
78+
If the user needs to evaluate a function that accepts more than one argument, including more than one array, all arrays arguments must be passed surrounded by parentheses "({...})". For example, a function call that emulates the SQL IN statement using an array argument and a reference value can be written as follows.
79+
80+
`IN_(({{sin(atn(1)\*2); 2; 3; 4; 5}});1)`
81+
82+
The above will pass this array of strings to the `IN_` function:
83+
84+
`\[{{1;2;3;4;5}}\] \[1\]`
85+
86+
However, matrix functions need to take care of creating arrays from a string, the ArrayFromString method can be used for this purpose.
87+
88+
As an illustration, the `UDFunctions.cls` module has an implementation of the `DET` function with an example of using the array handle function. In addition, the `GCD` function is implemented as a demo.
89+
90+
## Licence
91+
92+
Copyright (C) 2022 [W. García](https://github.com/ws-garcia/).
93+
94+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
95+
96+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
97+
98+
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
99+

0 commit comments

Comments
 (0)