├── .gitignore
├── ExcelFormulaParser Solution.sln
├── Images
├── Excel.icns
├── Excel.ico
├── Excel.png
├── Excel_64x64.ico
├── Excel_64x64.png
└── readme.txt
├── LICENSE
├── README.md
├── appveyor.yml
├── codecov-local.cmd
├── examples
├── ExcelFormulaParser.Expressions.Console
│ ├── Book.xlsx
│ ├── ExcelFormulaParser.Expressions.Console.csproj
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── log4net.config
└── ExcelFormulaParserSample
│ ├── ExcelFormulaParserSample.csproj
│ ├── Program.cs
│ ├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
│ ├── SampleForm.Designer.cs
│ ├── SampleForm.cs
│ └── SampleForm.resx
├── original
└── ExcelFormulaParser.v1.1.zip
├── src
├── ExcelFormulaExpressionParser
│ ├── Compatibility
│ │ └── TypeExtensions.cs
│ ├── Constants
│ │ ├── Errors.cs
│ │ └── MathConstants.cs
│ ├── ExcelFormulaContext.cs
│ ├── ExcelFormulaExpressionParser.csproj
│ ├── ExpressionParser.cs
│ ├── Expressions
│ │ ├── XArgExpression.cs
│ │ └── XRangeExpression.cs
│ ├── Extensions
│ │ └── ExpressionExtensions.cs
│ ├── Functions
│ │ ├── DateFunctions.cs
│ │ ├── LogicalFunctions.cs
│ │ ├── LookupAndReferenceFunctions.cs
│ │ └── MathFunctions.cs
│ ├── Helpers
│ │ └── DateTimeHelpers.cs
│ ├── ICellFinder.cs
│ ├── Models
│ │ ├── CellAddress.cs
│ │ ├── XArg.cs
│ │ ├── XCell.cs
│ │ ├── XNamedRange.cs
│ │ ├── XRange.cs
│ │ ├── XRow.cs
│ │ ├── XSheet.cs
│ │ └── XWorkbook.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── Utils
│ │ ├── CellFinder.cs
│ │ └── ExcelUtils.cs
└── ExcelFormulaParser
│ ├── Copyright.txt
│ ├── ExcelFormula.cs
│ ├── ExcelFormulaParser.csproj
│ ├── ExcelFormulaStack.cs
│ ├── ExcelFormulaToken.cs
│ ├── ExcelFormulaTokenSubtype.cs
│ ├── ExcelFormulaTokenType.cs
│ ├── ExcelFormulaTokens.cs
│ ├── IExcelFormulaContext.cs
│ └── Properties
│ └── AssemblyInfo.cs
└── tests
├── ExcelFormulaExpressionParser.Tests
├── DateFunctionsTests.cs
├── ExcelFormulaExpressionParser.Tests.csproj
├── LookupAndReferenceFunctionsTests.cs
├── OperandFunctionTests.Date.cs
├── OperandFunctionTests.Logical.cs
├── OperandFunctionTests.Math.cs
├── OperandFunctionTests.Nested.cs
├── OperandFunctionTests.VLookup.cs
└── OperatorPrefixLogicalTests.cs
└── ExcelFormulaParser.Tests
├── ExcelFormulaParser.Tests.csproj
├── ExcelFormulaTests.cs
└── OperatorMathTests.cs
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/ExcelFormulaParser Solution.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26430.12
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BCA71646-7799-4A23-9279-18C87E785645}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{26813EB3-A699-43E2-BA62-602FC8F0E9B2}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExcelFormulaParser", "src\ExcelFormulaParser\ExcelFormulaParser.csproj", "{53490EAA-4A87-43E6-9A3F-A6E8891CE152}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelFormulaParserSample", "examples\ExcelFormulaParserSample\ExcelFormulaParserSample.csproj", "{D05ECA40-6315-4339-BC32-8E922981218D}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Solution", "_Solution", "{95BDEA56-0346-4DC0-B2E2-E39E55D9CEFB}"
15 | ProjectSection(SolutionItems) = preProject
16 | appveyor.yml = appveyor.yml
17 | README.md = README.md
18 | EndProjectSection
19 | EndProject
20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{08EB3110-9DD0-42AF-87FC-6AB911DBC9F4}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExcelFormulaParser.Tests", "tests\ExcelFormulaParser.Tests\ExcelFormulaParser.Tests.csproj", "{DBC87F72-9E61-47DE-BB8C-35018DD9E9CA}"
23 | EndProject
24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelFormulaParser.Expressions.Console", "examples\ExcelFormulaParser.Expressions.Console\ExcelFormulaParser.Expressions.Console.csproj", "{4B2CC684-5281-43E2-A29C-04252381531B}"
25 | EndProject
26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelFormulaExpressionParser", "src\ExcelFormulaExpressionParser\ExcelFormulaExpressionParser.csproj", "{935AF390-A30A-495A-BD54-730A0F012358}"
27 | EndProject
28 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelFormulaExpressionParser.Tests", "tests\ExcelFormulaExpressionParser.Tests\ExcelFormulaExpressionParser.Tests.csproj", "{DAF7A07A-C12F-4A33-83CF-F27703987C8A}"
29 | EndProject
30 | Global
31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
32 | Debug|Any CPU = Debug|Any CPU
33 | Release|Any CPU = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
36 | {53490EAA-4A87-43E6-9A3F-A6E8891CE152}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {53490EAA-4A87-43E6-9A3F-A6E8891CE152}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {53490EAA-4A87-43E6-9A3F-A6E8891CE152}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {53490EAA-4A87-43E6-9A3F-A6E8891CE152}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {D05ECA40-6315-4339-BC32-8E922981218D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {D05ECA40-6315-4339-BC32-8E922981218D}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {D05ECA40-6315-4339-BC32-8E922981218D}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {D05ECA40-6315-4339-BC32-8E922981218D}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {DBC87F72-9E61-47DE-BB8C-35018DD9E9CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {DBC87F72-9E61-47DE-BB8C-35018DD9E9CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {DBC87F72-9E61-47DE-BB8C-35018DD9E9CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {DBC87F72-9E61-47DE-BB8C-35018DD9E9CA}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {4B2CC684-5281-43E2-A29C-04252381531B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {4B2CC684-5281-43E2-A29C-04252381531B}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {4B2CC684-5281-43E2-A29C-04252381531B}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {4B2CC684-5281-43E2-A29C-04252381531B}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {935AF390-A30A-495A-BD54-730A0F012358}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {935AF390-A30A-495A-BD54-730A0F012358}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {935AF390-A30A-495A-BD54-730A0F012358}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {935AF390-A30A-495A-BD54-730A0F012358}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {DAF7A07A-C12F-4A33-83CF-F27703987C8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57 | {DAF7A07A-C12F-4A33-83CF-F27703987C8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
58 | {DAF7A07A-C12F-4A33-83CF-F27703987C8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
59 | {DAF7A07A-C12F-4A33-83CF-F27703987C8A}.Release|Any CPU.Build.0 = Release|Any CPU
60 | EndGlobalSection
61 | GlobalSection(SolutionProperties) = preSolution
62 | HideSolutionNode = FALSE
63 | EndGlobalSection
64 | GlobalSection(NestedProjects) = preSolution
65 | {53490EAA-4A87-43E6-9A3F-A6E8891CE152} = {BCA71646-7799-4A23-9279-18C87E785645}
66 | {D05ECA40-6315-4339-BC32-8E922981218D} = {26813EB3-A699-43E2-BA62-602FC8F0E9B2}
67 | {DBC87F72-9E61-47DE-BB8C-35018DD9E9CA} = {08EB3110-9DD0-42AF-87FC-6AB911DBC9F4}
68 | {4B2CC684-5281-43E2-A29C-04252381531B} = {26813EB3-A699-43E2-BA62-602FC8F0E9B2}
69 | {935AF390-A30A-495A-BD54-730A0F012358} = {BCA71646-7799-4A23-9279-18C87E785645}
70 | {DAF7A07A-C12F-4A33-83CF-F27703987C8A} = {08EB3110-9DD0-42AF-87FC-6AB911DBC9F4}
71 | EndGlobalSection
72 | EndGlobal
73 |
--------------------------------------------------------------------------------
/Images/Excel.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StefH/ExcelFormulaParser/9e9d624c3232837ce32f9d64e1cb95dccd0eba72/Images/Excel.icns
--------------------------------------------------------------------------------
/Images/Excel.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StefH/ExcelFormulaParser/9e9d624c3232837ce32f9d64e1cb95dccd0eba72/Images/Excel.ico
--------------------------------------------------------------------------------
/Images/Excel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StefH/ExcelFormulaParser/9e9d624c3232837ce32f9d64e1cb95dccd0eba72/Images/Excel.png
--------------------------------------------------------------------------------
/Images/Excel_64x64.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StefH/ExcelFormulaParser/9e9d624c3232837ce32f9d64e1cb95dccd0eba72/Images/Excel_64x64.ico
--------------------------------------------------------------------------------
/Images/Excel_64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StefH/ExcelFormulaParser/9e9d624c3232837ce32f9d64e1cb95dccd0eba72/Images/Excel_64x64.png
--------------------------------------------------------------------------------
/Images/readme.txt:
--------------------------------------------------------------------------------
1 | Images are from Dakirby309-Simply-Styled-Microsoft-Excel-2013
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Stef Heyenrath
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Build and Code Coverage
2 | [](https://ci.appveyor.com/project/StefH/excelformulaparser)
3 | [](https://codecov.io/gh/StefH/ExcelFormulaParser)
4 |
5 | # ExcelFormulaParser
6 | An Excel Formula Parser, based on http://ewbi.blogs.com/develops/2007/03/excel_formula_p.html.
7 |
8 | [](https://www.nuget.org/packages/ExcelFormulaParser)
9 |
10 |
11 | Supported frameworks:
12 | - net 2.0
13 | - netstandard 1.0
14 |
15 | # ExcelFormulaExpressionParser
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | os: Visual Studio 2017
2 |
3 | version: 1.0.0.{build}
4 |
5 | configuration:
6 | - Debug
7 |
8 | init:
9 | - ps: $Env:LABEL = "CI" + $Env:APPVEYOR_BUILD_NUMBER.PadLeft(5, "0")
10 |
11 | install:
12 | - ps: Start-FileDownload 'https://download.microsoft.com/download/8/F/9/8F9659B9-E628-4D1A-B6BF-C3004C8C954B/dotnet-1.1.1-sdk-win-x64.exe'
13 | - cmd: dotnet-1.1.1-sdk-win-x64.exe /quiet
14 | - ps: $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = "true"
15 |
16 | environment:
17 | PATH: $(PATH);$(PROGRAMFILES)\dotnet\
18 | COVERALLS_REPO_TOKEN:
19 | secure: Eq/3VV5DVAeQAlQhe6hvy21IYPo5uY4fWKxvC4pxdq3giJzcwFp1QxBvRpXJ8Wkw
20 |
21 | before_build:
22 | # restore src and examples
23 | - dotnet restore .\src\ExcelFormulaParser\ExcelFormulaParser.csproj
24 | - dotnet restore .\src\ExcelFormulaExpressionParser\ExcelFormulaExpressionParser.csproj
25 | - nuget restore .\examples\ExcelFormulaParserSample\ExcelFormulaParserSample.csproj -PackagesDirectory packages
26 |
27 | build_script:
28 | # build ExcelFormulaParser
29 | - dotnet build .\src\ExcelFormulaParser\ExcelFormulaParser.csproj -c %CONFIGURATION% --framework net452
30 |
31 | # build ExcelFormulaExpressionParser
32 | - dotnet build .\src\ExcelFormulaExpressionParser\ExcelFormulaExpressionParser.csproj -c %CONFIGURATION% --framework net452
33 |
34 | # build ExcelFormulaParserSample
35 | # - cmd: msbuild .\examples\ExcelFormulaParserSample\ExcelFormulaParserSample.csproj /p:Configuration=%CONFIGURATION%
36 |
37 | # restore and build Tests
38 | - dotnet restore .\tests\ExcelFormulaParser.Tests\ExcelFormulaParser.Tests.csproj
39 | - dotnet build .\tests\ExcelFormulaParser.Tests\ExcelFormulaParser.Tests.csproj -c %CONFIGURATION%
40 | - dotnet restore .\tests\ExcelFormulaExpressionParser.Tests\ExcelFormulaExpressionParser.Tests.csproj
41 | - dotnet build .\tests\ExcelFormulaExpressionParser.Tests\ExcelFormulaExpressionParser.Tests.csproj -c %CONFIGURATION%
42 |
43 | test_script:
44 | - nuget.exe install OpenCover -ExcludeVersion
45 | - nuget.exe install coveralls.net -ExcludeVersion
46 | - pip install codecov
47 |
48 | - cmd: '"OpenCover\tools\OpenCover.Console.exe" -register:user -target:dotnet.exe -targetargs:"test tests\ExcelFormulaParser.Tests\ExcelFormulaParser.Tests.csproj --no-build" -returntargetcode -filter:"+[ExcelFormulaParser]* -[ExcelFormulaParser.Tests*]*" -mergeoutput -output:coverage.xml -oldstyle -searchdirs:".\tests\ExcelFormulaParser.Tests\bin\%CONFIGURATION%\net452"'
49 | - cmd: '"OpenCover\tools\OpenCover.Console.exe" -register:user -target:dotnet.exe -targetargs:"test tests\ExcelFormulaExpressionParser.Tests\ExcelFormulaExpressionParser.Tests.csproj --no-build" -returntargetcode -filter:"+[ExcelFormulaExpressionParser]* -[ExcelFormulaExpressionParser.Tests*]*" -mergeoutput -output:coverage.xml -oldstyle -searchdirs:".\tests\ExcelFormulaExpressionParser.Tests\bin\%CONFIGURATION%\net452"'
50 | - codecov -f "coverage.xml"
51 | - coveralls.net\tools\csmacnz.Coveralls.exe --opencover -i .\coverage.xml
--------------------------------------------------------------------------------
/codecov-local.cmd:
--------------------------------------------------------------------------------
1 | rem https://www.appveyor.com/blog/2017/03/17/codecov/
2 |
3 | %USERPROFILE%\.nuget\packages\opencover\4.6.519\tools\OpenCover.Console.exe -target:dotnet.exe -targetargs:"test tests\ExcelFormulaParser.Tests\ExcelFormulaParser.Tests.csproj --no-build" -filter:"+[ExcelFormulaParser]* -[ExcelFormulaParser.Tests*]*" -output:coverage.xml -register:user -oldStyle -searchdirs:"tests\ExcelFormulaParser.Tests\bin\debug\net452"
4 |
5 | %USERPROFILE%\.nuget\packages\ReportGenerator\2.5.6\tools\ReportGenerator.exe -reports:"coverage.xml" -targetdir:"report"
6 |
7 | start report\index.htm
--------------------------------------------------------------------------------
/examples/ExcelFormulaParser.Expressions.Console/Book.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StefH/ExcelFormulaParser/9e9d624c3232837ce32f9d64e1cb95dccd0eba72/examples/ExcelFormulaParser.Expressions.Console/Book.xlsx
--------------------------------------------------------------------------------
/examples/ExcelFormulaParser.Expressions.Console/ExcelFormulaParser.Expressions.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp1.0
6 | 1.0.1
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | PreserveNewest
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | 4.3.0
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParser.Expressions.Console/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using ExcelFormulaExpressionParser;
6 | using ExcelFormulaExpressionParser.Extensions;
7 | using ExcelFormulaExpressionParser.Helpers;
8 | using ExcelFormulaExpressionParser.Models;
9 | using OfficeOpenXml;
10 | using OfficeOpenXml.FormulaParsing.Utilities;
11 | using System.Globalization;
12 | using System.Reflection;
13 | using log4net;
14 | using log4net.Config;
15 |
16 | namespace ExcelFormulaParser.Expressions.Console
17 | {
18 | class Program
19 | {
20 | private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
21 |
22 | static void Main(string[] args)
23 | {
24 | var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
25 | XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
26 |
27 | Log.Info("Entering application.");
28 | Test();
29 | //CalcTest();
30 | //ExcelTest();
31 | }
32 |
33 | private static void Test()
34 | {
35 | using (var package = new ExcelPackage(new FileInfo("c:\\temp\\test.xlsx")))
36 | {
37 | var wb = new XWorkbook();
38 |
39 | foreach (var worksheet in package.Workbook.Worksheets)
40 | {
41 | var sheet = new XSheet(worksheet.Name);
42 |
43 | // Obtain the worksheet size
44 | ExcelCellAddress endCell = worksheet.Dimension.End;
45 |
46 | for (int r = 1; r <= endCell.Row; r++)
47 | {
48 | var xrow = new XRow(sheet, r);
49 | for (int c = 1; c <= endCell.Column; c++)
50 | {
51 | xrow.Cells.Add(ToXCell(sheet, xrow, worksheet.Cells[r, c]));
52 | }
53 |
54 | sheet.Rows.Add(xrow);
55 | }
56 |
57 | wb.Sheets.Add(sheet);
58 | }
59 |
60 | var names = package.Workbook.Names;
61 | foreach (var name in names)
62 | {
63 | wb.Names.Add(name.Name, name.Address);
64 | }
65 |
66 | var calcCell = wb.Sheets[2].Rows[16].Cells[2];
67 | var parser = new ExpressionParser(calcCell.ExcelFormula, 0, (ExcelFormulaContext)calcCell.ExcelFormula.Context, wb);
68 |
69 | Expression x = parser.Parse();
70 | System.Console.WriteLine($"Expression = `{x}`");
71 |
72 | var o = x.Optimize();
73 |
74 | System.Console.WriteLine($"Expression Optimize = `{o}`");
75 |
76 | var result = o.LambdaInvoke();
77 |
78 | System.Console.WriteLine($"result = `{result}`");
79 | }
80 | }
81 |
82 | private static void ExcelTest()
83 | {
84 | using (var package = new ExcelPackage(new FileInfo("Book.xlsx")))
85 | {
86 | var wb = new XWorkbook();
87 |
88 | package.Workbook.Worksheets[1].Cells["B1"].Value = 77;
89 |
90 | foreach (var worksheet in package.Workbook.Worksheets)
91 | {
92 | var sheet = new XSheet(worksheet.Name);
93 |
94 | // Obtain the worksheet size
95 | ExcelCellAddress endCell = worksheet.Dimension.End;
96 |
97 | for (int r = 1; r <= endCell.Row; r++)
98 | {
99 | var xrow = new XRow(sheet, r);
100 | for (int c = 1; c <= endCell.Column; c++)
101 | {
102 | xrow.Cells.Add(ToXCell(sheet, xrow, worksheet.Cells[r, c]));
103 | }
104 |
105 | sheet.Rows.Add(xrow);
106 | }
107 |
108 | wb.Sheets.Add(sheet);
109 | }
110 |
111 | var names = package.Workbook.Names;
112 | foreach (var name in names)
113 | {
114 | wb.Names.Add(name.Name, name.Address);
115 | }
116 |
117 | var calcCell = wb.Sheets[0].Rows[3].Cells[1];
118 | var parser = new ExpressionParser(calcCell.ExcelFormula, (ExcelFormulaContext)calcCell.ExcelFormula.Context, wb);
119 |
120 | Expression x = parser.Parse();
121 | System.Console.WriteLine($"Expression = `{x}`");
122 |
123 | var o = x.Optimize();
124 |
125 | System.Console.WriteLine($"Expression Optimize = `{o}`");
126 |
127 | LambdaExpression le = Expression.Lambda(o);
128 |
129 | var result = le.Compile().DynamicInvoke();
130 |
131 | System.Console.WriteLine($"result = `{result}`");
132 |
133 | var bool2 = wb.Sheets[0].Rows[4].Cells[1];
134 | var boolParser = new ExpressionParser(bool2.ExcelFormula, (ExcelFormulaContext)bool2.ExcelFormula.Context, wb);
135 |
136 | Expression bx = boolParser.Parse();
137 | System.Console.WriteLine($"Expression = `{bx}`");
138 |
139 | var o2 = bx.Optimize();
140 |
141 | System.Console.WriteLine($"Expression Optimize = `{o2}`");
142 |
143 | var bresult = Expression.Lambda(o2).Compile().DynamicInvoke();
144 | System.Console.WriteLine($"bresult = `{bresult}`");
145 |
146 |
147 | var sum = wb.Sheets[0].Rows[6].Cells[1];
148 | var sumParser = new ExpressionParser(sum.ExcelFormula, (ExcelFormulaContext)sum.ExcelFormula.Context, wb);
149 |
150 | Expression sumE = sumParser.Parse();
151 | System.Console.WriteLine($"Expression = `{sumE}`");
152 |
153 | var sumEOpt = sumE.Optimize();
154 |
155 | System.Console.WriteLine($"Expression Optimize = `{sumEOpt}`");
156 |
157 | var sumresult = Expression.Lambda(sumEOpt).Compile().DynamicInvoke();
158 | System.Console.WriteLine($"sumresult = `{sumresult}`");
159 |
160 |
161 | var sumSqrt = wb.Sheets[3].Rows[0].Cells[1];
162 | var sumSqrtParser = new ExpressionParser(sumSqrt.ExcelFormula, (ExcelFormulaContext)sumSqrt.ExcelFormula.Context, wb);
163 |
164 | Expression sumSqrtE = sumSqrtParser.Parse();
165 | //System.Console.WriteLine($"Expression = `{sumSqrtE}`");
166 |
167 | var sumSqrtEOpt = sumSqrtE.Optimize();
168 |
169 | //System.Console.WriteLine($"Expression Optimize = `{sumSqrtEOpt}`");
170 |
171 | var sumSqrtresult = Expression.Lambda(sumSqrtEOpt).Compile().DynamicInvoke();
172 | System.Console.WriteLine($"sumresult = `{sumSqrtresult}`");
173 |
174 |
175 | var dateyear = wb.Sheets[0].Rows[7].Cells[2];
176 | var dateyearParser = new ExpressionParser(dateyear.ExcelFormula, (ExcelFormulaContext)dateyear.ExcelFormula.Context, wb);
177 |
178 | Expression dateyearE = dateyearParser.Parse();
179 | //System.Console.WriteLine($"Expression = `{sumSqrtE}`");
180 |
181 | var dateyearO = dateyearE.Optimize();
182 |
183 | //System.Console.WriteLine($"Expression Optimize = `{sumSqrtEOpt}`");
184 |
185 | var dateyearResult = Expression.Lambda(dateyearO).Compile().DynamicInvoke();
186 | System.Console.WriteLine($"dateyearResult = `{dateyearResult}`");
187 |
188 | var dateyearnow = wb.Sheets[0].Rows[8].Cells[2];
189 | var dateyearnowParser = new ExpressionParser(dateyearnow.ExcelFormula, (ExcelFormulaContext)dateyearnow.ExcelFormula.Context, wb);
190 |
191 | var dateyearnowResult = dateyearnowParser.Parse().LambdaInvoke();
192 | System.Console.WriteLine($"dateyearnowResult = `{dateyearnowResult}`");
193 |
194 | var named1 = wb.Sheets[0].Rows[9].Cells[1];
195 | var namedParser1 = new ExpressionParser(named1.ExcelFormula, (ExcelFormulaContext)named1.ExcelFormula.Context, wb);
196 |
197 | var namedResult1 = namedParser1.Parse().LambdaInvoke();
198 | System.Console.WriteLine($"namedResult1 = `{namedResult1}`");
199 |
200 | var named2 = wb.Sheets[0].Rows[10].Cells[1];
201 | var namedParser2 = new ExpressionParser(named2.ExcelFormula, (ExcelFormulaContext)named2.ExcelFormula.Context, wb);
202 |
203 | var namedResult2 = namedParser2.Parse().LambdaInvoke();
204 | System.Console.WriteLine($"namedResult2 = `{namedResult2}`");
205 |
206 |
207 | var vlookup = wb.Sheets[3].Rows[0].Cells[4];
208 | var vlookupParser = new ExpressionParser(vlookup.ExcelFormula, (ExcelFormulaContext)vlookup.ExcelFormula.Context, wb);
209 | var vlookupResult = vlookupParser.Parse().LambdaInvoke();
210 | System.Console.WriteLine($"vlookupResult = `{vlookupResult}`");
211 |
212 | var vlookup2 = wb.Sheets[3].Rows[1].Cells[4];
213 | var vlookupParser2 = new ExpressionParser(vlookup2.ExcelFormula, (ExcelFormulaContext)vlookup2.ExcelFormula.Context, wb);
214 | var vlookupResult2 = vlookupParser2.Parse().LambdaInvoke();
215 | System.Console.WriteLine($"vlookupResult2 = `{vlookupResult2}`");
216 |
217 | int u = 0;
218 | }
219 | }
220 |
221 | private static XCell ToXCell(XSheet sheet, XRow row, ExcelRange range)
222 | {
223 | var cell = new XCell(row, range.Address)
224 | {
225 | FullAddress = $"{range.Worksheet.Name}!{range.Address}"
226 | };
227 |
228 | var context = new ExcelFormulaContext
229 | {
230 | Sheet = sheet
231 | };
232 |
233 | if (!string.IsNullOrEmpty(range.Formula))
234 | {
235 | cell.Formula = "=" + range.Formula;
236 | cell.ExcelFormula = new ExcelFormula(cell.Formula, context);
237 | }
238 | else
239 | {
240 | cell.Value = range.Value;
241 |
242 | if (range.Value == null)
243 | {
244 | return cell;
245 | }
246 |
247 | if (range.Value is bool)
248 | {
249 | cell.ExcelFormula = new ExcelFormula((bool)range.Value ? "=TRUE" : "=FALSE", context);
250 | }
251 | else if (range.Value is DateTime)
252 | {
253 | double value = DateTimeHelpers.ToOADate((DateTime)range.Value);
254 | cell.ExcelFormula = new ExcelFormula("=" + value.ToString(CultureInfo.InvariantCulture), context);
255 | }
256 | else if (range.Value.IsNumeric())
257 | {
258 | double value = Convert.ToDouble(range.Value);
259 | cell.ExcelFormula = new ExcelFormula("=" + value.ToString(CultureInfo.InvariantCulture), context);
260 | }
261 | else
262 | {
263 | cell.ExcelFormula = new ExcelFormula(string.Format("=\"{0}\"", range.Text), context);
264 | }
265 | }
266 |
267 | return cell;
268 | }
269 |
270 | private static void CalcTest()
271 | {
272 | // haakjes, machtsverheffen, vermenigvuldigen, delen, worteltrekken, optellen, aftrekken
273 | //var excelFormula = new ExcelFormula("=2^3 - -(1+1+1) * ROUND(4/2.7,2) + POWER(1+1,4) + 500 + SIN(3.1415926) + COS(3.1415926/2) + ABS(-1)");
274 | //var parser = new ExpressionParser(excelFormula);
275 |
276 | //Expression x = parser.Parse();
277 | //System.Console.WriteLine($"Expression = `{x}`");
278 |
279 | //var o = x.Optimize();
280 |
281 | //System.Console.WriteLine($"Expression = `{o}`");
282 |
283 | //LambdaExpression le = Expression.Lambda(o);
284 |
285 | //var result = le.Compile().DynamicInvoke();
286 |
287 | //System.Console.WriteLine($"result = `{result}`");
288 |
289 | //var trunc2 = new ExcelFormula("=TRUNC(91.789, 2)");
290 | //System.Console.WriteLine("trunc2 = `{0}`", Expression.Lambda(new ExpressionParser(trunc2).Parse()).Compile().DynamicInvoke());
291 |
292 | //var trunc0 = new ExcelFormula("=TRUNC(91.789)");
293 | //System.Console.WriteLine("trunc0 = `{0}`", Expression.Lambda(new ExpressionParser(trunc0).Parse()).Compile().DynamicInvoke());
294 |
295 | //var gt = new ExcelFormula("=1>2");
296 | //System.Console.WriteLine("gt = `{0}`", Expression.Lambda(new ExpressionParser(gt).Parse()).Compile().DynamicInvoke());
297 |
298 | //var sum = new ExcelFormula("=SUM(1,2,3)");
299 | //System.Console.WriteLine("sum = `{0}`", Expression.Lambda(new ExpressionParser(sum).Parse()).Compile().DynamicInvoke());
300 |
301 | var now = new ExcelFormula("=NOW()");
302 | System.Console.WriteLine("{0} : `{1}`", now.Formula, Expression.Lambda(new ExpressionParser(now).Parse()).Compile().DynamicInvoke());
303 | }
304 | }
305 | }
--------------------------------------------------------------------------------
/examples/ExcelFormulaParser.Expressions.Console/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly: log4net.Config.XmlConfigurator(Watch = true)]
--------------------------------------------------------------------------------
/examples/ExcelFormulaParser.Expressions.Console/log4net.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/ExcelFormulaParserSample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | AnyCPU
5 | 8.0.50727
6 | 2.0
7 | {D05ECA40-6315-4339-BC32-8E922981218D}
8 | WinExe
9 | Properties
10 | ExcelFormulaParserSample
11 | ExcelFormulaParserSample
12 | v2.0
13 |
14 |
15 |
16 |
17 | 2.0
18 | publish\
19 | true
20 | Disk
21 | false
22 | Foreground
23 | 7
24 | Days
25 | false
26 | false
27 | true
28 | 0
29 | 1.0.0.%2a
30 | false
31 | false
32 | true
33 |
34 |
35 | true
36 | full
37 | false
38 | bin\Debug\
39 | DEBUG;TRACE
40 | prompt
41 | 4
42 |
43 |
44 | pdbonly
45 | true
46 | bin\Release\
47 | TRACE
48 | prompt
49 | 4
50 |
51 |
52 | ../../Images/Excel_64x64.ico
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | Form
62 |
63 |
64 | SampleForm.cs
65 |
66 |
67 |
68 |
69 | Designer
70 | SampleForm.cs
71 |
72 |
73 | ResXFileCodeGenerator
74 | Resources.Designer.cs
75 | Designer
76 |
77 |
78 | True
79 | Resources.resx
80 | True
81 |
82 |
83 | SettingsSingleFileGenerator
84 | Settings.Designer.cs
85 |
86 |
87 | True
88 | Settings.settings
89 | True
90 |
91 |
92 |
93 |
94 | False
95 | .NET Framework 3.5 SP1
96 | true
97 |
98 |
99 |
100 |
101 | {53490eaa-4a87-43e6-9a3f-a6e8891ce152}
102 | ExcelFormulaParser
103 |
104 |
105 |
106 |
113 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Windows.Forms;
4 |
5 | namespace ExcelFormulaParserSample
6 | {
7 | static class Program
8 | {
9 | ///
10 | /// The main entry point for the application.
11 | ///
12 | [STAThread]
13 | static void Main()
14 | {
15 | Application.EnableVisualStyles();
16 | Application.SetCompatibleTextRenderingDefault(false);
17 | Application.Run(new SampleForm());
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ExcelFormulaParserSample")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("ewbi.com")]
12 | [assembly: AssemblyProduct("ExcelFormulaParserSample")]
13 | [assembly: AssemblyCopyright("Copyright © 2007 E. W. Bachtal, Inc.")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("b7a4d8b2-c955-426a-8184-ca941465f2fb")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | [assembly: AssemblyVersion("1.0.0.0")]
33 | [assembly: AssemblyFileVersion("1.0.0.0")]
34 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ExcelFormulaParserSample.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExcelFormulaParserSample.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ExcelFormulaParserSample.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/SampleForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ExcelFormulaParserSample
2 | {
3 | partial class SampleForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
32 | System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
33 | System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
34 | System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
35 | this.ExcelFormulaTextBox = new System.Windows.Forms.TextBox();
36 | this.label1 = new System.Windows.Forms.Label();
37 | this.ParseButton = new System.Windows.Forms.Button();
38 | this.panel1 = new System.Windows.Forms.Panel();
39 | this.ExcelFormulaTokensGridView = new System.Windows.Forms.DataGridView();
40 | this.index = new System.Windows.Forms.DataGridViewTextBoxColumn();
41 | this.type = new System.Windows.Forms.DataGridViewTextBoxColumn();
42 | this.subtype = new System.Windows.Forms.DataGridViewTextBoxColumn();
43 | this.token = new System.Windows.Forms.DataGridViewTextBoxColumn();
44 | this.tokentree = new System.Windows.Forms.DataGridViewTextBoxColumn();
45 | this.panel1.SuspendLayout();
46 | ((System.ComponentModel.ISupportInitialize) (this.ExcelFormulaTokensGridView)).BeginInit();
47 | this.SuspendLayout();
48 | //
49 | // ExcelFormulaTextBox
50 | //
51 | this.ExcelFormulaTextBox.Location = new System.Drawing.Point(11, 33);
52 | this.ExcelFormulaTextBox.Name = "ExcelFormulaTextBox";
53 | this.ExcelFormulaTextBox.Size = new System.Drawing.Size(658, 21);
54 | this.ExcelFormulaTextBox.TabIndex = 0;
55 | this.ExcelFormulaTextBox.Enter += new System.EventHandler(this.ExcelFormulaTextBox_Enter);
56 | //
57 | // label1
58 | //
59 | this.label1.AutoSize = true;
60 | this.label1.Location = new System.Drawing.Point(11, 16);
61 | this.label1.Margin = new System.Windows.Forms.Padding(0);
62 | this.label1.Name = "label1";
63 | this.label1.Size = new System.Drawing.Size(75, 13);
64 | this.label1.TabIndex = 1;
65 | this.label1.Text = "Excel formula:";
66 | //
67 | // ParseButton
68 | //
69 | this.ParseButton.Location = new System.Drawing.Point(675, 31);
70 | this.ParseButton.Name = "ParseButton";
71 | this.ParseButton.Size = new System.Drawing.Size(65, 24);
72 | this.ParseButton.TabIndex = 2;
73 | this.ParseButton.Text = "Parse";
74 | this.ParseButton.UseVisualStyleBackColor = true;
75 | this.ParseButton.Click += new System.EventHandler(this.ParseButton_Click);
76 | //
77 | // panel1
78 | //
79 | this.panel1.AutoSize = true;
80 | this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
81 | this.panel1.Controls.Add(this.ExcelFormulaTokensGridView);
82 | this.panel1.Location = new System.Drawing.Point(11, 64);
83 | this.panel1.Name = "panel1";
84 | this.panel1.Size = new System.Drawing.Size(729, 580);
85 | this.panel1.TabIndex = 4;
86 | //
87 | // ExcelFormulaTokensGridView
88 | //
89 | this.ExcelFormulaTokensGridView.AllowUserToAddRows = false;
90 | this.ExcelFormulaTokensGridView.AllowUserToDeleteRows = false;
91 | this.ExcelFormulaTokensGridView.AllowUserToResizeRows = false;
92 | this.ExcelFormulaTokensGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders;
93 | this.ExcelFormulaTokensGridView.BorderStyle = System.Windows.Forms.BorderStyle.None;
94 | this.ExcelFormulaTokensGridView.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleHorizontal;
95 | this.ExcelFormulaTokensGridView.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.None;
96 | dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
97 | dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control;
98 | dataGridViewCellStyle1.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
99 | dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
100 | dataGridViewCellStyle1.Padding = new System.Windows.Forms.Padding(0, 2, 0, 2);
101 | dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
102 | dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
103 | dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
104 | this.ExcelFormulaTokensGridView.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
105 | this.ExcelFormulaTokensGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
106 | this.ExcelFormulaTokensGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
107 | this.index,
108 | this.type,
109 | this.subtype,
110 | this.token,
111 | this.tokentree});
112 | dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
113 | dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window;
114 | dataGridViewCellStyle2.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
115 | dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText;
116 | dataGridViewCellStyle2.Padding = new System.Windows.Forms.Padding(1, 0, 0, 0);
117 | dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Window;
118 | dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.ControlText;
119 | dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
120 | this.ExcelFormulaTokensGridView.DefaultCellStyle = dataGridViewCellStyle2;
121 | this.ExcelFormulaTokensGridView.Dock = System.Windows.Forms.DockStyle.Fill;
122 | this.ExcelFormulaTokensGridView.Location = new System.Drawing.Point(0, 0);
123 | this.ExcelFormulaTokensGridView.Name = "ExcelFormulaTokensGridView";
124 | this.ExcelFormulaTokensGridView.ReadOnly = true;
125 | dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
126 | dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Control;
127 | dataGridViewCellStyle3.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
128 | dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.WindowText;
129 | dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight;
130 | dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
131 | dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
132 | this.ExcelFormulaTokensGridView.RowHeadersDefaultCellStyle = dataGridViewCellStyle3;
133 | this.ExcelFormulaTokensGridView.RowHeadersVisible = false;
134 | dataGridViewCellStyle4.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
135 | this.ExcelFormulaTokensGridView.RowsDefaultCellStyle = dataGridViewCellStyle4;
136 | this.ExcelFormulaTokensGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
137 | this.ExcelFormulaTokensGridView.ShowCellErrors = false;
138 | this.ExcelFormulaTokensGridView.ShowCellToolTips = false;
139 | this.ExcelFormulaTokensGridView.ShowEditingIcon = false;
140 | this.ExcelFormulaTokensGridView.ShowRowErrors = false;
141 | this.ExcelFormulaTokensGridView.Size = new System.Drawing.Size(725, 576);
142 | this.ExcelFormulaTokensGridView.StandardTab = true;
143 | this.ExcelFormulaTokensGridView.TabIndex = 4;
144 | //
145 | // index
146 | //
147 | this.index.HeaderText = "index";
148 | this.index.Name = "index";
149 | this.index.ReadOnly = true;
150 | this.index.Width = 50;
151 | //
152 | // type
153 | //
154 | this.type.DataPropertyName = "Type";
155 | this.type.HeaderText = "type";
156 | this.type.Name = "type";
157 | this.type.ReadOnly = true;
158 | this.type.Width = 130;
159 | //
160 | // subtype
161 | //
162 | this.subtype.DataPropertyName = "Subtype";
163 | this.subtype.HeaderText = "subtype";
164 | this.subtype.Name = "subtype";
165 | this.subtype.ReadOnly = true;
166 | this.subtype.Width = 120;
167 | //
168 | // token
169 | //
170 | this.token.DataPropertyName = "Value";
171 | this.token.HeaderText = "token";
172 | this.token.Name = "token";
173 | this.token.ReadOnly = true;
174 | this.token.Width = 200;
175 | //
176 | // tokentree
177 | //
178 | this.tokentree.HeaderText = "tokentree";
179 | this.tokentree.Name = "tokentree";
180 | this.tokentree.ReadOnly = true;
181 | this.tokentree.Width = 225;
182 | //
183 | // SampleForm
184 | //
185 | this.AcceptButton = this.ParseButton;
186 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
187 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
188 | this.ClientSize = new System.Drawing.Size(750, 656);
189 | this.Controls.Add(this.panel1);
190 | this.Controls.Add(this.ParseButton);
191 | this.Controls.Add(this.label1);
192 | this.Controls.Add(this.ExcelFormulaTextBox);
193 | this.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
194 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
195 | this.MaximizeBox = false;
196 | this.Name = "SampleForm";
197 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
198 | this.Text = "ExcelFormulaParserSample";
199 | this.panel1.ResumeLayout(false);
200 | ((System.ComponentModel.ISupportInitialize) (this.ExcelFormulaTokensGridView)).EndInit();
201 | this.ResumeLayout(false);
202 | this.PerformLayout();
203 |
204 | }
205 |
206 | #endregion
207 |
208 | private System.Windows.Forms.TextBox ExcelFormulaTextBox;
209 | private System.Windows.Forms.Label label1;
210 | private System.Windows.Forms.Button ParseButton;
211 | private System.Windows.Forms.Panel panel1;
212 | private System.Windows.Forms.DataGridView ExcelFormulaTokensGridView;
213 | private System.Windows.Forms.DataGridViewTextBoxColumn index;
214 | private System.Windows.Forms.DataGridViewTextBoxColumn type;
215 | private System.Windows.Forms.DataGridViewTextBoxColumn subtype;
216 | private System.Windows.Forms.DataGridViewTextBoxColumn token;
217 | private System.Windows.Forms.DataGridViewTextBoxColumn tokentree;
218 | }
219 | }
220 |
221 |
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/SampleForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Text;
4 | using System.Windows.Forms;
5 | using ExcelFormulaParser;
6 |
7 | namespace ExcelFormulaParserSample
8 | {
9 | public partial class SampleForm : Form
10 | {
11 | public SampleForm()
12 | {
13 | InitializeComponent();
14 | }
15 |
16 | private void ParseButton_Click(object sender, EventArgs e)
17 | {
18 | ExcelFormula excelFormula = new ExcelFormula(ExcelFormulaTextBox.Text);
19 |
20 | ExcelFormulaTokensGridView.DataSource = new BindingList(excelFormula);
21 |
22 | int indentCount = 0;
23 | for (int i = 0; i < excelFormula.Count; i++)
24 | {
25 | ExcelFormulaTokensGridView.Rows[i].Cells["index"].Value = i + 1;
26 | ExcelFormulaToken token = excelFormula[i];
27 | if (token.Subtype == ExcelFormulaTokenSubtype.Stop)
28 | {
29 | indentCount -= indentCount > 0 ? 1 : 0;
30 | }
31 |
32 | StringBuilder indent = new StringBuilder();
33 | indent.Append("|");
34 | for (int ind = 0; ind < indentCount; ind++)
35 | {
36 | indent.Append(" |");
37 | }
38 | indent.Append(token.Value);
39 |
40 | ExcelFormulaTokensGridView.Rows[i].Cells["tokentree"].Value = indent.ToString();
41 | if (token.Subtype == ExcelFormulaTokenSubtype.Start)
42 | {
43 | indentCount += 1;
44 | }
45 | }
46 | }
47 |
48 | private void ExcelFormulaTextBox_Enter(object sender, EventArgs e)
49 | {
50 | ExcelFormulaTextBox.SelectAll();
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/examples/ExcelFormulaParserSample/SampleForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | True
122 |
123 |
124 | True
125 |
126 |
127 | True
128 |
129 |
130 | True
131 |
132 |
133 | True
134 |
135 |
--------------------------------------------------------------------------------
/original/ExcelFormulaParser.v1.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/StefH/ExcelFormulaParser/9e9d624c3232837ce32f9d64e1cb95dccd0eba72/original/ExcelFormulaParser.v1.1.zip
--------------------------------------------------------------------------------
/src/ExcelFormulaExpressionParser/Compatibility/TypeExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Reflection;
4 |
5 | namespace ExcelFormulaExpressionParser.Compatibility
6 | {
7 | public static class TypeExtensions
8 | {
9 | public static MethodInfo FindMethod(this Type type, string name, Type[] types)
10 | {
11 | #if NETSTANDARD
12 | return type.GetTypeInfo().GetDeclaredMethods(name).Single(mi => mi.GetParameters().Select(p => p.ParameterType).SequenceEqual(types));
13 | #else
14 | return type.GetMethod(name, types);
15 | #endif
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/ExcelFormulaExpressionParser/Constants/Errors.cs:
--------------------------------------------------------------------------------
1 | using System.Linq.Expressions;
2 |
3 | namespace ExcelFormulaExpressionParser.Constants
4 | {
5 | internal static class Errors
6 | {
7 | public static readonly Expression Div0 = Expression.Constant("#DIV/0!");
8 | public static readonly Expression NA = Expression.Constant("#N/A");
9 | public static readonly Expression Name = Expression.Constant("#NAME?");
10 | public static readonly Expression Null = Expression.Constant("#NULL!");
11 | public static readonly Expression Num = Expression.Constant("#NUM!");
12 | public static readonly Expression Ref = Expression.Constant("#REF!");
13 | public static readonly Expression Value = Expression.Constant("#VALUE!");
14 | }
15 | }
--------------------------------------------------------------------------------
/src/ExcelFormulaExpressionParser/Constants/MathConstants.cs:
--------------------------------------------------------------------------------
1 | using System.Linq.Expressions;
2 |
3 | namespace ExcelFormulaExpressionParser.Constants
4 | {
5 | internal static class MathConstants
6 | {
7 | public static readonly Expression Constant0 = Expression.Constant(0d);
8 | public static readonly Expression Constant10 = Expression.Constant(10d);
9 | }
10 | }
--------------------------------------------------------------------------------
/src/ExcelFormulaExpressionParser/ExcelFormulaContext.cs:
--------------------------------------------------------------------------------
1 | using ExcelFormulaExpressionParser.Models;
2 | using ExcelFormulaParser;
3 |
4 | namespace ExcelFormulaExpressionParser
5 | {
6 | public class ExcelFormulaContext : IExcelFormulaContext
7 | {
8 | public XSheet Sheet { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/ExcelFormulaExpressionParser/ExcelFormulaExpressionParser.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net40;net452;netstandard1.3
5 | 1.0.0.0
6 | Stef Heyenrath
7 | Stef Heyenrath
8 | ../../Images/Excel.ico
9 | ewbi.com
10 | A library to parse Excel formulas to System.Linq.Expressions
11 | https://github.com/StefH/ExcelFormulaParser
12 | git
13 | excel;formula;parser
14 |
15 | https://github.com/StefH/ExcelFormulaParser
16 | https://raw.githubusercontent.com/StefH/ExcelFormulaParser/master/LICENSE
17 | https://raw.githubusercontent.com/StefH/ExcelFormulaParser/master/Images/Excel_64x64.png
18 | True
19 | full
20 |
21 |
22 |
23 | NETSTANDARD
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/ExcelFormulaExpressionParser/ExpressionParser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Linq.Expressions;
6 | using ExcelFormulaExpressionParser.Functions;
7 | using ExcelFormulaExpressionParser.Models;
8 | using ExcelFormulaExpressionParser.Utils;
9 | using ExcelFormulaParser;
10 | using JetBrains.Annotations;
11 | using TokenType = ExcelFormulaParser.ExcelFormulaTokenType;
12 | using TokenSubtype = ExcelFormulaParser.ExcelFormulaTokenSubtype;
13 | using ExcelFormulaExpressionParser.Expressions;
14 | using log4net;
15 |
16 | namespace ExcelFormulaExpressionParser
17 | {
18 | public class ExpressionParser
19 | {
20 | private static readonly ILog Log = LogManager.GetLogger(typeof(ExpressionParser));
21 |
22 | private int _index;
23 | private int _level;
24 |
25 | private ExcelFormulaToken CT => _list[_index];
26 |
27 | private readonly IList _list;
28 | private readonly ExcelFormulaContext _context;
29 | private readonly ICellFinder _finder;
30 |
31 | ///
32 | /// ExpressionParser
33 | ///
34 | /// The ExcelFormula or a list from ExcelFormulaTokens.
35 | public ExpressionParser([NotNull] IList tokens) :
36 | this(tokens, 0, null, (XWorkbook)null)
37 | {
38 | }
39 |
40 | ///
41 | /// ExpressionParser
42 | ///
43 | /// The ExcelFormula or a list from ExcelFormulaTokens.
44 | /// The level (default 0).
45 | /// The ExcelFormulaContext. (Optional if no real Excel Workbook is parsed.)
46 | /// The Excel Workbook. (Optional if no real Excel Workbook is parsed.)
47 | public ExpressionParser([NotNull] IList tokens, int level, [CanBeNull] ExcelFormulaContext context = null, [CanBeNull] XWorkbook workbook = null) :
48 | this(tokens, level, context, workbook != null ? new CellFinder(workbook) : null)
49 | {
50 | }
51 |
52 | ///
53 | /// ExpressionParser
54 | ///
55 | /// The ExcelFormula or a list from ExcelFormulaTokens.
56 | /// The ExcelFormulaContext. (Optional if no real Excel Workbook is parsed.)
57 | /// The Excel Workbook. (Optional if no real Excel Workbook is parsed.)
58 | public ExpressionParser([NotNull] IList tokens, [CanBeNull] ExcelFormulaContext context = null, [CanBeNull] XWorkbook workbook = null) :
59 | this(tokens, 0, context, workbook != null ? new CellFinder(workbook) : null)
60 | {
61 | }
62 |
63 | ///
64 | /// ExpressionParser
65 | ///
66 | /// The ExcelFormula or a list from ExcelFormulaTokens.
67 | /// The level (default 0).
68 | /// The ExcelFormulaContext. (Optional if no real Excel Workbook is parsed.)
69 | /// The cellfinder to finds cells in a workbook. (Optional if no real Excel Workbook is parsed.)
70 | public ExpressionParser([NotNull] IList tokens, int level = 0, [CanBeNull] ExcelFormulaContext context = null, [CanBeNull] ICellFinder finder = null)
71 | {
72 | _list = tokens;
73 | _level = level;
74 | _context = context;
75 | _finder = finder;
76 |
77 | // Log.InfoFormat("Formula : '{0}', Sheet : '{1}'", GetFormula(), context != null ? context.Sheet.Name : "");
78 | }
79 |
80 | public Expression Parse()
81 | {
82 | _index = 0;
83 |
84 | return ParseArgs();
85 | }
86 |
87 | private string GetFormula()
88 | {
89 | string formula = new string(' ', _level);
90 | foreach (var token in _list)
91 | {
92 | if (token.Type == TokenType.Subexpression && token.Subtype == TokenSubtype.Start)
93 | {
94 | formula += "(";
95 | }
96 | else if (token.Type == TokenType.Function && token.Subtype == TokenSubtype.Start)
97 | {
98 | formula += token.Value + "(";
99 | }
100 | else if (token.Subtype == TokenSubtype.Stop)
101 | {
102 | formula += ")";
103 | }
104 | else
105 | {
106 | formula += token.Value;
107 | }
108 | }
109 |
110 | return formula;
111 | }
112 |
113 | private void Next()
114 | {
115 | if (_index + 1 < _list.Count)
116 | {
117 | _index++;
118 | }
119 | }
120 |
121 | private Expression ParseArgs()
122 | {
123 | Expression left = ParseAdditive();
124 |
125 | while (CT.Type == TokenType.Argument)
126 | {
127 | Next();
128 | Expression right = ParseAdditive();
129 |
130 | var argExpression = left as XArgExpression;
131 | if (argExpression != null)
132 | {
133 | left = argExpression.Add(right);
134 | }
135 | else
136 | {
137 | argExpression = XArgExpression.Create(left);
138 | left = argExpression.Add(right);
139 | }
140 | }
141 |
142 | return left;
143 | }
144 |
145 | // +, -
146 | private Expression ParseAdditive()
147 | {
148 | Expression left = ParseMultiplication();
149 |
150 | while (CT.Type == TokenType.OperatorInfix && CT.Subtype == TokenSubtype.Math && (CT.Value == "+" || CT.Value == "-"))
151 | {
152 | var op = CT;
153 | Next();
154 | Expression right = Expression.Convert(ParseMultiplication(), typeof(double));
155 |
156 | switch (op.Value)
157 | {
158 | case "+":
159 | left = Expression.Add(left, right);
160 | break;
161 | case "-":
162 | left = Expression.Subtract(left, right);
163 | break;
164 | }
165 | }
166 |
167 | return left;
168 | }
169 |
170 | // *, /, ^
171 | private Expression ParseMultiplication()
172 | {
173 | Expression left = ParseLogical();
174 |
175 | while (CT.Type == TokenType.OperatorInfix && CT.Subtype == TokenSubtype.Math && (CT.Value == "^" || CT.Value == "*" || CT.Value == "/"))
176 | {
177 | var op = CT;
178 | Next();
179 | Expression right = ParseLogical();
180 |
181 | switch (op.Value)
182 | {
183 | case "^":
184 | left = MathFunctions.Power(left, right);
185 | break;
186 | case "*":
187 | left = Expression.Multiply(left, right);
188 | break;
189 | case "/":
190 | left = Expression.Divide(left, right);
191 | break;
192 | default:
193 | throw new NotSupportedException(op.Value);
194 | }
195 | }
196 |
197 | return left;
198 | }
199 |
200 | // >, >=, <, <=, <>, =
201 | private Expression ParseLogical()
202 | {
203 | Expression left = ParseFunction();
204 |
205 | while (CT.Type == TokenType.OperatorInfix && CT.Subtype == TokenSubtype.Logical)
206 | {
207 | var op = CT;
208 | Next();
209 | Expression right = ParseFunction();
210 |
211 | switch (op.Value)
212 | {
213 | case ">":
214 | left = Expression.GreaterThan(left, right);
215 | break;
216 | case ">=":
217 | left = Expression.GreaterThanOrEqual(left, right);
218 | break;
219 | case "<":
220 | left = Expression.LessThan(left, right);
221 | break;
222 | case "<=":
223 | left = Expression.LessThanOrEqual(left, right);
224 | break;
225 | case "<>":
226 | left = Expression.NotEqual(left, right);
227 | break;
228 | case "=":
229 | left = Expression.Equal(left, right);
230 | break;
231 | default:
232 | throw new NotSupportedException(op.Value);
233 | }
234 | }
235 |
236 | return left;
237 | }
238 |
239 | // =ROUND(-3 * ROUND(1.001 * 2, 1) + 7.001, 1) + 11
240 | private Expression ParseFunction()
241 | {
242 | Expression left = ParseOperatorPrefix();
243 |
244 | while (CT.Type == TokenType.Function || CT.Type == TokenType.Subexpression)
245 | {
246 | var op = CT;
247 | Next();
248 |
249 | int indent = 0;
250 | var tokens = new List();
251 | while (!(CT.Subtype == TokenSubtype.Stop && indent == 0))
252 | {
253 | if (CT.Subtype == TokenSubtype.Start)
254 | {
255 | indent++;
256 | }
257 |
258 | if (CT.Subtype == TokenSubtype.Stop)
259 | {
260 | indent--;
261 | }
262 |
263 | tokens.Add(CT);
264 |
265 | Next();
266 | }
267 |
268 | Next();
269 | var right = ParseOperatorPrefix();
270 |
271 | // If there is more to be done (right != null), return right, else return the value from this function.
272 | return right ?? ParseFunctionWithArgs(op.Value, tokens, _context);
273 | }
274 |
275 | return left;
276 | }
277 |
278 | private Expression ParseFunctionWithArgs(string functionName, IList tokens, ExcelFormulaContext context)
279 | {
280 | void AddToArgumentsList(ICollection