Skip to content

Commit 06a408a

Browse files
author
Sébastien Geiser
committed
expression Evaluation in excel sheet filters
1 parent 923dbf7 commit 06a408a

File tree

2 files changed

+52
-16
lines changed

2 files changed

+52
-16
lines changed

RegexDialog/Model/ExcelSheetSelection.cs

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class ExcelSheetSelection : NotifyPropertyChangedBaseClass
1212
private readonly static Regex simpleColumnRegex = new Regex("^[A-Z]+$", RegexOptions.Compiled);
1313
private readonly static Regex simpleRowRegex = new Regex("^[1-9][0-9]*$", RegexOptions.Compiled);
1414
private readonly static Regex rangeRegex = new Regex("^[A-Z]+([1-9][0-9]*)?:[A-Z]+([1-9][0-9]*)?|[1-9][0-9]*:[1-9][0-9]*$", RegexOptions.Compiled);
15-
private readonly static Regex interpretedStuffRegex = new Regex(@"\[(?<var>FR|LR|FC|LC)\]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
15+
private readonly static Regex evaluatedExpressionRegex = new Regex(@"\{(?<expression>[^\}])\}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
1616

1717
public bool IsSelected { get; set; } = true;
1818
public string Name { get; set; } = string.Empty;
@@ -58,22 +58,52 @@ public IEnumerable<IXLCell> GetCells(IXLWorksheet sheet)
5858

5959
private string InterpretStuffInFilter(string filter, IXLWorksheet sheet)
6060
{
61-
return interpretedStuffRegex.Replace(filter, match =>
61+
ExpressionEvaluator evaluator = new ExpressionEvaluator(new Dictionary<string, object>()
6262
{
63-
switch(match.Groups["var"].Value)
63+
{ "FR", sheet.FirstRowUsed().RangeAddress.FirstAddress.RowNumber },
64+
{ "LR", sheet.LastRowUsed().RangeAddress.FirstAddress.RowNumber },
65+
{ "FC", sheet.FirstColumnUsed().RangeAddress.FirstAddress.ColumnLetter },
66+
{ "LC", sheet.LastColumnUsed().RangeAddress.FirstAddress.ColumnLetter },
67+
{ "FCN", sheet.FirstColumnUsed().RangeAddress.FirstAddress.ColumnNumber },
68+
{ "LCN", sheet.LastColumnUsed().RangeAddress.FirstAddress.ColumnNumber },
69+
{ "sheet", sheet },
70+
});
71+
72+
evaluator.EvaluateFunction += Evaluator_EvaluateFunction;
73+
74+
string result = evaluatedExpressionRegex.Replace(filter, match => evaluator.Evaluate(match.Groups["expression"].Value).ToString());
75+
76+
evaluator.EvaluateFunction -= Evaluator_EvaluateFunction;
77+
78+
return result;
79+
}
80+
81+
private void Evaluator_EvaluateFunction(object sender, FunctionEvaluationEventArg e)
82+
{
83+
IXLWorksheet sheet = e.Evaluator.Variables["sheet"] as IXLWorksheet;
84+
85+
if(e.Name.Equals("ToNumber"))
86+
{
87+
if(e.This != null)
6488
{
65-
case "FR":
66-
return sheet.FirstRowUsed().RangeAddress.FirstAddress.RowNumber.ToString();
67-
case "LR":
68-
return sheet.LastRowUsed().RangeAddress.FirstAddress.RowNumber.ToString();
69-
case "FC":
70-
return sheet.FirstColumnUsed().RangeAddress.FirstAddress.ColumnLetter;
71-
case "LC":
72-
return sheet.LastColumnUsed().RangeAddress.FirstAddress.ColumnLetter;
73-
default:
74-
return "";
89+
e.Value = sheet.Column((string)e.This).ColumnNumber();
7590
}
76-
});
91+
else
92+
{
93+
e.Value = sheet.Column(e.EvaluateArg<string>(0)).ColumnNumber();
94+
}
95+
}
96+
if(e.Name.Equals("ToLetter"))
97+
{
98+
if(e.This != null)
99+
{
100+
e.Value = sheet.Column((int)e.This).ColumnLetter();
101+
}
102+
else
103+
{
104+
e.Value = sheet.Column(e.EvaluateArg<int>(0)).ColumnLetter();
105+
}
106+
}
77107
}
78108
}
79109
}

RegexDialog/RegExToolDialog.xaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -904,12 +904,18 @@
904904
Margin="10,0,0,0">
905905
<TextBox.ToolTip>
906906
<StackPanel>
907-
<TextBlock>To filter cells to search in the sheet&#x0a;- Separate each range or cell by [;]</TextBlock>
907+
<TextBlock>To filter cells to search in the sheet</TextBlock>
908+
<TextBlock>- Separate each range or cell by ;</TextBlock>
908909
<TextBlock>- Individual cell can be specified with A1 format</TextBlock>
909910
<TextBlock>- Range can be specified with A1:ZZ99 format</TextBlock>
910911
<TextBlock>- Column can be specified by it's letters A;E;BD (range of columns are possible C:F)</TextBlock>
911912
<TextBlock>- Row can be specified by it's number 1;20;102 (range of rows are possible 3:6)</TextBlock>
912-
<TextBlock>- [FR],[LR],[FC],[LC] are replaced by respectively first row number, last row number, first column letter, last column letter</TextBlock>
913+
<TextBlock>- expressions between { and } are evaluate as math expression.<LineBreak/><Run Text=" "/>
914+
FR, LR are variables for respectively First Row number and Last Row number.<LineBreak/><Run Text=" "/>
915+
FC, LC are variables for respectively First Column letter(s) and Last Column letter(s).<LineBreak/><Run Text=" "/>
916+
FCN, LCN are variables for respectively First Column number and Last Column number.<LineBreak/><Run Text=" "/>
917+
columnLetter.ToNumber() or ToNumber(columnLetter) Convert a column letter to its corresponding number<LineBreak/><Run Text=" "/>
918+
columnNumber.ToLetter() or ToLetter(columnNumber) Convert a column number to its corresponding letter(</TextBlock>
913919
</StackPanel>
914920
</TextBox.ToolTip>
915921
</TextBox>

0 commit comments

Comments
 (0)