├── .gitattributes
├── .gitignore
├── CommonUtilities
├── CommonUtilities.csproj
├── Properties
│ └── AssemblyInfo.cs
└── XmlSerializationExtensions.cs
├── ExcelScript.sln
├── ExcelScript
├── AddinFunctions
│ ├── Create.cs
│ ├── Deserialize.cs
│ ├── DisplayCode.cs
│ ├── Evaluate.cs
│ ├── FormatCode.cs
│ ├── OptionsCreate.cs
│ ├── ParameterCreate.cs
│ ├── Parse.cs
│ ├── Register.cs
│ ├── Run.cs
│ └── Serialize.cs
├── ExcelScript-AddIn.dna
├── ExcelScript-AddIn.xll.config
├── ExcelScript.csproj
├── ExcelScriptAddin.cs
├── HandleNames.cs
├── Internal
│ ├── DirtyRangeFlagger.cs
│ ├── ManageDirtyFlagsAttribute.cs
│ ├── ParameterExtensions.cs
│ ├── ParameterValueFactory.cs
│ └── SerializationWrapper.cs
├── NinjectModules
│ └── ScriptingModule.cs
├── Properties
│ └── AssemblyInfo.cs
├── Registration
│ ├── FunctionLogging.cs
│ ├── RangeParameterConversion.cs
│ └── SuppressInDialog.cs
├── Todos and Bugs.txt
├── XlScriptOptions.cs
├── app.config
└── packages.config
├── ObjectStorage
├── ObjectStorage.csproj
├── ObjectStore.cs
├── Properties
│ └── AssemblyInfo.cs
├── StoredObject.cs
├── VersionProviders
│ ├── ConstantVersionProvider.cs
│ ├── HashVersionProvider.cs
│ ├── IVersionProvider.cs
│ ├── NotifyPropertyChangedVersionProvider.cs
│ └── NullObjectVersionProvider.cs
└── WeaklyStoredObject.cs
├── ObjectStorageAbstractions
├── IObjectStore.cs
├── IStoredObject.cs
├── ObjectStorageAbstractions.csproj
└── Properties
│ └── AssemblyInfo.cs
├── ObjectStorageTests
├── Generators
│ └── StoredTypeGenerator.cs
├── ObjectStorageTests.csproj
├── ObjectStoreTestBase.cs
├── ObjectStoreTests_Hashed.cs
├── ObjectStoreTests_Mixed.cs
├── ObjectStoreTests_NotifyPropertyChanged.cs
├── Properties
│ └── AssemblyInfo.cs
└── Types
│ ├── IStoredType.cs
│ ├── StoredTypeHashed.cs
│ ├── StoredTypeNotifyPropertyChanged.cs
│ └── StoredTypeUnsupported.cs
├── README.md
├── Resources
└── Examples.xlsm
├── RoslynScriptGlobals
├── Globals.cs
├── GlobalsFactory.cs
├── Properties
│ └── AssemblyInfo.cs
├── RoslynScriptGlobals-AddIn.dna
├── RoslynScriptGlobals.csproj
└── packages.config
├── RoslynScripting
├── Factory
│ ├── ParameterFactory.cs
│ └── ScriptFactory.cs
├── FormatColorScheme.cs
├── FormattedText.cs
├── HostedScriptRunner.cs
├── Internal
│ ├── DelegateDisposable.cs
│ ├── HashAttribute.cs
│ ├── HashEnumerable.cs
│ ├── HashHelper.cs
│ ├── HashValueAttribute.cs
│ ├── IScriptRunner.cs
│ └── Marshalling
│ │ ├── RemoteTask.cs
│ │ └── RemoteTaskCompletionSource.cs
├── Parameter.cs
├── ParameterValue.cs
├── ParseResult.cs
├── Properties
│ └── AssemblyInfo.cs
├── RoslynScripting.csproj
├── Script.cs
├── ScriptRunResult.cs
├── app.config
└── packages.config
├── RoslynScriptingTests
├── Generators
│ ├── ParameterGenerator.cs
│ └── ScriptGenerator.cs
├── Properties
│ └── AssemblyInfo.cs
├── RoslynScriptingTests.csproj
├── SerializationTests.cs
├── TestGlobals.cs
├── Types
│ └── SimpleSerializableType.cs
├── app.config
└── packages.config
└── ScriptingAbstractions
├── Factory
├── IParameterFactory.cs
├── IParameterValueFactory.cs
└── IScriptFactory.cs
├── IGlobalsFactory.cs
├── IHasDescription.cs
├── IParameter.cs
├── IParameterValue.cs
├── IScript.cs
├── IScriptGlobals.cs
├── IScriptRunResult.cs
├── Properties
└── AssemblyInfo.cs
├── ScriptingAbstractions.csproj
└── ScriptingOptions.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Windows Store app package directory
170 | AppPackages/
171 | BundleArtifacts/
172 |
173 | # Visual Studio cache files
174 | # files ending in .cache can be ignored
175 | *.[Cc]ache
176 | # but keep track of directories ending in .cache
177 | !*.[Cc]ache/
178 |
179 | # Others
180 | ClientBin/
181 | [Ss]tyle[Cc]op.*
182 | ~$*
183 | *~
184 | *.dbmdl
185 | *.dbproj.schemaview
186 | *.pfx
187 | *.publishsettings
188 | node_modules/
189 | orleans.codegen.cs
190 |
191 | # RIA/Silverlight projects
192 | Generated_Code/
193 |
194 | # Backup & report files from converting an old project file
195 | # to a newer Visual Studio version. Backup files are not needed,
196 | # because we have git ;-)
197 | _UpgradeReport_Files/
198 | Backup*/
199 | UpgradeLog*.XML
200 | UpgradeLog*.htm
201 |
202 | # SQL Server files
203 | *.mdf
204 | *.ldf
205 |
206 | # Business Intelligence projects
207 | *.rdl.data
208 | *.bim.layout
209 | *.bim_*.settings
210 |
211 | # Microsoft Fakes
212 | FakesAssemblies/
213 |
214 | # GhostDoc plugin setting file
215 | *.GhostDoc.xml
216 |
217 | # Node.js Tools for Visual Studio
218 | .ntvs_analysis.dat
219 |
220 | # Visual Studio 6 build log
221 | *.plg
222 |
223 | # Visual Studio 6 workspace options file
224 | *.opt
225 |
226 | # Visual Studio LightSwitch build output
227 | **/*.HTMLClient/GeneratedArtifacts
228 | **/*.DesktopClient/GeneratedArtifacts
229 | **/*.DesktopClient/ModelManifest.xml
230 | **/*.Server/GeneratedArtifacts
231 | **/*.Server/ModelManifest.xml
232 | _Pvt_Extensions
233 |
234 | # LightSwitch generated files
235 | GeneratedArtifacts/
236 | ModelManifest.xml
237 |
238 | # Paket dependency manager
239 | .paket/paket.exe
240 |
241 | # FAKE - F# Make
242 | .fake/
243 |
--------------------------------------------------------------------------------
/CommonUtilities/CommonUtilities.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {DC268D3E-5FB8-4BD0-93B6-588001FA8EAE}
8 | Library
9 | Properties
10 | ExcelScript.CommonUtilities
11 | CommonUtilities
12 | v4.6.1
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
54 |
--------------------------------------------------------------------------------
/CommonUtilities/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("CommonUtilities")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("CommonUtilities")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
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("dc268d3e-5fb8-4bd0-93b6-588001fa8eae")]
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 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ExcelScript.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelScript", "ExcelScript\ExcelScript.csproj", "{F489EDF9-1286-463B-8C76-3844169BC2D3}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectStorage", "ObjectStorage\ObjectStorage.csproj", "{8AB1CE36-E883-4A98-9713-9F6A849376ED}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectStorageTests", "ObjectStorageTests\ObjectStorageTests.csproj", "{3D4B72A2-1959-4429-8FC6-233CC7A81F8C}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectStorageAbstractions", "ObjectStorageAbstractions\ObjectStorageAbstractions.csproj", "{7013FBC4-3D9B-48DC-986E-31B39BCAD70B}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Object-Storage", "Object-Storage", "{F4288F4B-7251-4A48-A3D5-C2F0AC54C149}"
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripting", "Scripting", "{2FBA8A7A-07E1-4D62-BD9E-EF392C5AECE5}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptingAbstractions", "ScriptingAbstractions\ScriptingAbstractions.csproj", "{9C15D62F-889E-4C74-93D3-AAC38D27031F}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoslynScripting", "RoslynScripting\RoslynScripting.csproj", "{81C9CA40-28C5-490B-A32A-DEFFCA247613}"
21 | EndProject
22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoslynScriptGlobals", "RoslynScriptGlobals\RoslynScriptGlobals.csproj", "{EB8FEE81-6DE4-4BE3-A14C-22988D1F23B1}"
23 | EndProject
24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoslynScriptingTests", "RoslynScriptingTests\RoslynScriptingTests.csproj", "{0BE3325A-547C-4AC7-9AE5-EEB7BCBB4F22}"
25 | EndProject
26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommonUtilities", "CommonUtilities\CommonUtilities.csproj", "{DC268D3E-5FB8-4BD0-93B6-588001FA8EAE}"
27 | EndProject
28 | Global
29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
30 | Debug|Any CPU = Debug|Any CPU
31 | Release|Any CPU = Release|Any CPU
32 | EndGlobalSection
33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
34 | {F489EDF9-1286-463B-8C76-3844169BC2D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {F489EDF9-1286-463B-8C76-3844169BC2D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {F489EDF9-1286-463B-8C76-3844169BC2D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {F489EDF9-1286-463B-8C76-3844169BC2D3}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {8AB1CE36-E883-4A98-9713-9F6A849376ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {8AB1CE36-E883-4A98-9713-9F6A849376ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {8AB1CE36-E883-4A98-9713-9F6A849376ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {8AB1CE36-E883-4A98-9713-9F6A849376ED}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {3D4B72A2-1959-4429-8FC6-233CC7A81F8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {3D4B72A2-1959-4429-8FC6-233CC7A81F8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {3D4B72A2-1959-4429-8FC6-233CC7A81F8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {3D4B72A2-1959-4429-8FC6-233CC7A81F8C}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {7013FBC4-3D9B-48DC-986E-31B39BCAD70B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {7013FBC4-3D9B-48DC-986E-31B39BCAD70B}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {7013FBC4-3D9B-48DC-986E-31B39BCAD70B}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {7013FBC4-3D9B-48DC-986E-31B39BCAD70B}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {9C15D62F-889E-4C74-93D3-AAC38D27031F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {9C15D62F-889E-4C74-93D3-AAC38D27031F}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {9C15D62F-889E-4C74-93D3-AAC38D27031F}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {9C15D62F-889E-4C74-93D3-AAC38D27031F}.Release|Any CPU.Build.0 = Release|Any CPU
54 | {81C9CA40-28C5-490B-A32A-DEFFCA247613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {81C9CA40-28C5-490B-A32A-DEFFCA247613}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {81C9CA40-28C5-490B-A32A-DEFFCA247613}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {81C9CA40-28C5-490B-A32A-DEFFCA247613}.Release|Any CPU.Build.0 = Release|Any CPU
58 | {EB8FEE81-6DE4-4BE3-A14C-22988D1F23B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59 | {EB8FEE81-6DE4-4BE3-A14C-22988D1F23B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
60 | {EB8FEE81-6DE4-4BE3-A14C-22988D1F23B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
61 | {EB8FEE81-6DE4-4BE3-A14C-22988D1F23B1}.Release|Any CPU.Build.0 = Release|Any CPU
62 | {0BE3325A-547C-4AC7-9AE5-EEB7BCBB4F22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63 | {0BE3325A-547C-4AC7-9AE5-EEB7BCBB4F22}.Debug|Any CPU.Build.0 = Debug|Any CPU
64 | {0BE3325A-547C-4AC7-9AE5-EEB7BCBB4F22}.Release|Any CPU.ActiveCfg = Release|Any CPU
65 | {0BE3325A-547C-4AC7-9AE5-EEB7BCBB4F22}.Release|Any CPU.Build.0 = Release|Any CPU
66 | {DC268D3E-5FB8-4BD0-93B6-588001FA8EAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67 | {DC268D3E-5FB8-4BD0-93B6-588001FA8EAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
68 | {DC268D3E-5FB8-4BD0-93B6-588001FA8EAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
69 | {DC268D3E-5FB8-4BD0-93B6-588001FA8EAE}.Release|Any CPU.Build.0 = Release|Any CPU
70 | EndGlobalSection
71 | GlobalSection(SolutionProperties) = preSolution
72 | HideSolutionNode = FALSE
73 | EndGlobalSection
74 | GlobalSection(NestedProjects) = preSolution
75 | {8AB1CE36-E883-4A98-9713-9F6A849376ED} = {F4288F4B-7251-4A48-A3D5-C2F0AC54C149}
76 | {3D4B72A2-1959-4429-8FC6-233CC7A81F8C} = {F4288F4B-7251-4A48-A3D5-C2F0AC54C149}
77 | {7013FBC4-3D9B-48DC-986E-31B39BCAD70B} = {F4288F4B-7251-4A48-A3D5-C2F0AC54C149}
78 | {9C15D62F-889E-4C74-93D3-AAC38D27031F} = {2FBA8A7A-07E1-4D62-BD9E-EF392C5AECE5}
79 | {81C9CA40-28C5-490B-A32A-DEFFCA247613} = {2FBA8A7A-07E1-4D62-BD9E-EF392C5AECE5}
80 | {EB8FEE81-6DE4-4BE3-A14C-22988D1F23B1} = {2FBA8A7A-07E1-4D62-BD9E-EF392C5AECE5}
81 | {0BE3325A-547C-4AC7-9AE5-EEB7BCBB4F22} = {2FBA8A7A-07E1-4D62-BD9E-EF392C5AECE5}
82 | EndGlobalSection
83 | EndGlobal
84 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/Create.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelScript.Internal;
3 | using ExcelScript.Registration;
4 | using ObjectStorage.Abstractions;
5 | using RoslynScriptGlobals;
6 | using ScriptingAbstractions;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.ComponentModel;
10 | using System.Linq;
11 | using System.Reflection;
12 | using Excel = NetOffice.ExcelApi;
13 |
14 | namespace ExcelScript
15 | {
16 | public partial class ExcelScriptAddin
17 | {
18 | [ExcelFunction(Name = FunctionPrefix + nameof(Create), Description = "Creates a reusable script, and returns its Handle - which can then by invoked with the ExcelScript.Run method", IsVolatile = false)]
19 | [SuppressInDialog]
20 | [ManageDirtyFlags]
21 | public static object Create(
22 | [ExcelArgument("Name for a handle under which the script object will be stored in memory")] string HandleName,
23 | [ExcelArgument("The code for this script. Multiple lines are allowed.")] string[] code,
24 | [ExcelArgument("A handle to script option definitions as created by ExcelScript.Options.Create. Can be left blank to use defaults.")] string OptionsHandle = "",
25 | [ExcelArgument("An arbitrary number of handles to parameter definitions (as created by ExcelScript.Parameters.Create), which define input parameters for the script")] params string[] ParameterHandles)
26 | {
27 | if (code == null)
28 | throw new ArgumentNullException(nameof(code));
29 |
30 | string _code = String.Join(Environment.NewLine, code);
31 |
32 | // Get Options
33 | XlScriptOptions xlScriptOptions = (String.IsNullOrEmpty(OptionsHandle)) ? XlScriptOptions.Default : GetFromStoreOrThrow(OptionsHandle);
34 |
35 | // Create Script object
36 | var script = CreateScript(xlScriptOptions);
37 | script.Code = _code;
38 | script.ReturnType = xlScriptOptions.ReturnType;
39 |
40 | foreach (var parameterHandle in ParameterHandles)
41 | {
42 | var parameterHandleName = HandleNames.GetNameFrom(parameterHandle);
43 | IParameter storedParameter = GetFromStoreOrThrow(parameterHandleName);
44 | script.Parameters.Add(storedParameter);
45 | }
46 |
47 | IStoredObject storedScript;
48 | if (m_ObjectStore.GetByName(HandleName, out storedScript) && storedScript.Object.GetHashCode() == script.GetHashCode())
49 | {
50 | return HandleNames.ToHandle(storedScript);
51 | }
52 | else
53 | {
54 | return AddOrUpdateInStoreOrThrow(HandleName, script, () => TryDispose(script));
55 | }
56 | }
57 |
58 | private static IScript CreateScript(XlScriptOptions xlScriptOptions)
59 | {
60 | var options = CreateScriptingOptionsFrom(xlScriptOptions);
61 | var script = m_ScriptFactory.Create(m_GlobalsFactory, options);
62 | return script;
63 | }
64 |
65 | private static ScriptingOptions CreateScriptingOptionsFrom(XlScriptOptions xlScriptOptions)
66 | {
67 | var options = new ScriptingOptions();
68 |
69 | foreach (var reference in GetScriptDefaultReferences())
70 | options.References.Add(reference);
71 |
72 | foreach (var import in GetScriptDefaultImports())
73 | options.Imports.Add(import);
74 |
75 | options.HostingType = xlScriptOptions.HostingType;
76 |
77 | return options;
78 | }
79 |
80 | private static IEnumerable GetScriptDefaultReferences()
81 | {
82 | yield return typeof(string).Assembly; // mscorlib
83 | yield return typeof(IComponent).Assembly; // System
84 | yield return typeof(Enumerable).Assembly; // System.Core
85 | yield return typeof(Globals).Assembly; // script globals
86 | yield return typeof(Excel.Application).Assembly; // NetOffice
87 | }
88 |
89 |
90 | private static IEnumerable GetScriptDefaultImports()
91 | {
92 | yield return "System";
93 | yield return "System.Collections.Generic";
94 | yield return "System.Linq";
95 | yield return "NetOffice.ExcelApi";
96 | yield return "NetOffice";
97 | }
98 |
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/Deserialize.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelScript.Internal;
3 | using ExcelScript.Registration;
4 | using ObjectStorage.Abstractions;
5 | using RoslynScriptGlobals;
6 | using ScriptingAbstractions;
7 | using System;
8 | using System.IO;
9 | using System.IO.Compression;
10 | using System.Linq;
11 | using System.Text;
12 | using System.Xml.Linq;
13 | using System.Xml.Serialization;
14 |
15 | namespace ExcelScript
16 | {
17 | public partial class ExcelScriptAddin
18 | {
19 | [ExcelFunction(Name = FunctionPrefix + nameof(Deserialize), IsVolatile = false, Description = "Deserializes data that was previously serialized with ExcelScript.Serialzie()")]
20 | [SuppressInDialog]
21 | public static object Deserialize(
22 | [ExcelArgument("Data input. Can either be the raw data as it was generated by ExcelScript.Serialize(), or can be a filepath from which to load the data")] string input)
23 | {
24 | var obj = InternalDeserialize(input);
25 |
26 | IStoredObject storedObj = (IStoredObject)obj;
27 |
28 | // Re-inject dependencies into the object
29 | var underlyingObj = storedObj.Object;
30 | InjectDependencies(underlyingObj);
31 |
32 | Type objType = storedObj.GetType().GetGenericArguments().Single();
33 | IStoredObject reStoredObj;
34 |
35 | // todo: maybe reflect & call correct generic method?
36 | if (!m_ObjectStore.AddOrUpdate(storedObj.Name, underlyingObj, objType, out reStoredObj, () => TryDispose(underlyingObj)))
37 | throw new InvalidOperationException("Object could not be re-added to the data store");
38 |
39 | return HandleNames.ToHandle(reStoredObj);
40 | }
41 |
42 | private static object InternalDeserialize(string data)
43 | {
44 | if (IsValidFilePath(data) || IsValidFilePath(Environment.ExpandEnvironmentVariables(data)))
45 | {
46 | data = Environment.ExpandEnvironmentVariables(data);
47 |
48 | if (!File.Exists(data))
49 | throw new FileNotFoundException("The given file with serialized data was not found", data);
50 |
51 | data = File.ReadAllText(data);
52 | }
53 |
54 | XDocument doc;
55 | using (var sr = new StringReader(data))
56 | {
57 | doc = XDocument.Load(sr);
58 | }
59 |
60 | if (doc.Root.Name == "CompressedData")
61 | {
62 | string algorithm = doc.Root.Attribute("Algorithm").Value;
63 |
64 | switch (algorithm)
65 | {
66 | case "gzip":
67 | var compressedData = doc.Root.Value;
68 | Byte[] bytes = Convert.FromBase64String(compressedData);
69 | data = Unzip(bytes);
70 | break;
71 | default:
72 | throw new InvalidOperationException($"Cannot decompress data compressed with algorithm {algorithm}");
73 | }
74 | }
75 |
76 | var deserialized = XmlDeserialize(data);
77 | var obj = deserialized.ContainedObject;
78 |
79 | return obj;
80 | }
81 |
82 | private static void InjectDependencies(object DeserializedObject)
83 | {
84 | if (DeserializedObject is ScriptingAbstractions.IScript)
85 | InjectDependencies((RoslynScripting.Script)DeserializedObject);
86 | }
87 |
88 | private static void InjectDependencies(IScript Script)
89 | {
90 | m_ScriptFactory.Inject(Script, m_GlobalsFactory);
91 | }
92 |
93 | private static bool IsValidFilePath(string input)
94 | {
95 | try
96 | {
97 | string value = Path.GetFullPath(input);
98 | return !String.IsNullOrWhiteSpace(value);
99 | }
100 | catch (ArgumentException)
101 | {
102 | return false;
103 | }
104 | catch (NotSupportedException)
105 | {
106 | return false;
107 | }
108 | catch (PathTooLongException)
109 | {
110 | return false;
111 | }
112 | }
113 |
114 | // From http://stackoverflow.com/questions/7343465/compression-decompression-string-with-c-sharp
115 | private static string Unzip(byte[] bytes)
116 | {
117 | using (var msi = new MemoryStream(bytes))
118 | using (var mso = new MemoryStream())
119 | {
120 | using (var gs = new GZipStream(msi, CompressionMode.Decompress))
121 | {
122 | CopyTo(gs, mso);
123 | }
124 |
125 | return Encoding.UTF8.GetString(mso.ToArray());
126 | }
127 | }
128 |
129 | private static T XmlDeserialize(string xml)
130 | {
131 | XmlSerializer deserializer = new XmlSerializer(typeof(T));
132 | TextReader reader = new StringReader(xml);
133 | object obj = deserializer.Deserialize(reader);
134 | T result = (T)obj;
135 | reader.Close();
136 |
137 | return result;
138 | }
139 |
140 | private static void CopyTo(Stream src, Stream dest)
141 | {
142 | byte[] bytes = new byte[4096];
143 |
144 | int cnt;
145 |
146 | while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0)
147 | {
148 | dest.Write(bytes, 0, cnt);
149 | }
150 | }
151 |
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/DisplayCode.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ScriptingAbstractions;
3 | using System;
4 | using System.Linq;
5 |
6 | namespace ExcelScript
7 | {
8 | public partial class ExcelScriptAddin
9 | {
10 | [ExcelFunction(Name = FunctionPrefix + nameof(DisplayCode), Description = "Displays either the entire code, or specific lines from a script as given by the script handle. Can be useful for debugging.", IsVolatile = false)]
11 | public static object DisplayCode(
12 | [ExcelArgument(Name = "ScriptHandle", Description = "A stored handled to the script which shall be displayed")] string ScriptHandle,
13 | [ExcelArgument(Name = "DisplayLineNumbers", Description = "If true, prepends line numbers to each line of the code")] bool DisplayLineNumbers = false,
14 | [ExcelArgument(Name = "LineStart", Description = "Line number of the first line to be displayed (1-based). Optional.")] int LineStart = 0,
15 | [ExcelArgument(Name = "LineEnd", Description = "Line number of the last line to be displayed (1-based). Optional. If LineStart is given, but LineEnd is not, LineEnd will be = LineStart (i.e. will display exactly one line).")] int LineEnd = 0
16 | )
17 | {
18 | var script = GetFromStoreOrThrow(ScriptHandle);
19 |
20 | var scriptLines = script
21 | .Code
22 | .Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
23 |
24 | if (!scriptLines.Any())
25 | return "";
26 |
27 | int LineNumDigits = (int)Math.Floor(Math.Log10(scriptLines.Count()) + 1);
28 | string LineNumFormat = "D" + LineNumDigits;
29 |
30 | int _LineStart = (LineStart < 1) ? 1 : LineStart;
31 | int _LineEnd = Math.Min(scriptLines.Length, (LineEnd < 1) ? ((LineStart < 1) ? scriptLines.Length : (int)LineStart) : (int)LineEnd);
32 |
33 | var result1d = scriptLines
34 | .Select((x, i) => new { LineNumber = i + 1, CodeLine = x })
35 | .Where(x => x.LineNumber >= _LineStart && x.LineNumber <= _LineEnd)
36 | .Select(x => DisplayLineNumbers ? x.LineNumber.ToString(LineNumFormat) + ": " + x.CodeLine : x.CodeLine)
37 | .ToArray();
38 |
39 | string[,] result = new string[result1d.Length, 1];
40 | for (int i = 0; i < result1d.Length; i++)
41 | {
42 | result[i, 0] = result1d[i];
43 | }
44 |
45 |
46 | return result;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/Evaluate.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelScript.Registration;
3 | using ScriptingAbstractions;
4 | using System;
5 | using System.Diagnostics;
6 | using System.Linq;
7 |
8 | namespace ExcelScript
9 | {
10 | public partial class ExcelScriptAddin
11 | {
12 | [ExcelFunction(Name = FunctionPrefix + nameof(Evaluate), Description = "Evaluates the given expression and returns its result", IsVolatile = false)]
13 | [SuppressInDialog]
14 | public static object Evaluate(
15 | [ExcelArgument(Description = "The code that is to be evaluated")] string[] code
16 | )
17 | {
18 | if (code == null)
19 | throw new ArgumentNullException(nameof(code));
20 |
21 | string _code = String.Join(Environment.NewLine, code);
22 |
23 | var script = CreateScript(XlScriptOptions.Default);
24 |
25 | script.Code = _code;
26 | script.ReturnType = typeof(object);
27 | var result = script.Run(Enumerable.Empty());
28 |
29 | if (result.IsSuccess)
30 | {
31 | return result.ReturnValue;
32 | }
33 | else
34 | {
35 | throw new AggregateException("There were errors running the script", result.Errors);
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/FormatCode.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using RoslynScriptGlobals;
3 | using RoslynScripting;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Drawing;
7 | using System.Linq;
8 | using Excel = NetOffice.ExcelApi;
9 |
10 | namespace ExcelScript
11 | {
12 | public partial class ExcelScriptAddin
13 | {
14 | [ExcelFunction(Name = FunctionPrefix + nameof(FormatCode), IsMacroType = true, Description = "Formats the code in the input range, and replaces the input ranges' data with the formatted code")]
15 | public static object FormatCode(
16 | [ExcelArgument(AllowReference = true, Description = "A cell reference to the range containing C# code")] object excelRef)
17 | {
18 | Excel.Range cellRef = ToRange((ExcelReference)excelRef);
19 |
20 | if (cellRef == null)
21 | throw new ArgumentException("Input was not an excel reference", nameof(excelRef));
22 |
23 | if (cellRef.Columns.Count != 1)
24 | throw new ArgumentException("The range must have exactly one column", nameof(excelRef));
25 |
26 | IEnumerable codeLines = cellRef.Cells.Select(x => Convert.ToString(x.Value));
27 |
28 | // Remove all empty lines at the beginning and end
29 | codeLines = codeLines.SkipWhile(x => String.IsNullOrWhiteSpace(x))
30 | .Reverse()
31 | .SkipWhile(x => String.IsNullOrWhiteSpace(x))
32 | .Reverse();
33 |
34 | var code = String.Join(Environment.NewLine, codeLines);
35 |
36 | XlScriptOptions xlScriptOptions = XlScriptOptions.Default;
37 | var options = CreateScriptingOptionsFrom(xlScriptOptions);
38 |
39 | var formattedCode = Script.GetFormattedCodeAsync(code, options).Result;
40 |
41 | if (formattedCode.TextLines.Count > cellRef.Rows.Count)
42 | throw new ArgumentException($"The formatted result has {formattedCode.TextLines.Count} lines, but the input range has only {cellRef.Rows.Count}; please expant your input range.", nameof(excelRef));
43 |
44 | for (int i = 0; i < cellRef.Rows.Count; i++)
45 | {
46 | Excel.Range target = cellRef[i + 1, 1];
47 |
48 | if (i >= formattedCode.TextLines.Count)
49 | {
50 | // The target range is bigger than what we need; just clear out the unused cells
51 | target.ClearContents();
52 | }
53 | else
54 | {
55 | var line = formattedCode.TextLines.ElementAt(i);
56 | target.Value = line.Text;
57 |
58 | foreach (var linePart in line.Parts)
59 | {
60 | var characters = target.Characters(linePart.LineSpan.Start + 1, linePart.LineSpan.Length);
61 | var textColor = linePart.TextFormat.TextColor;
62 | var excelColor = Color.FromArgb(textColor.B, textColor.G, textColor.R); // excel uses BGR format, so we convert RGB to BGR here
63 | characters.Font.Color = excelColor.ToArgb();
64 | }
65 | }
66 | }
67 |
68 | return $"({DateTime.Now.ToShortTimeString()}) Formatted";
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/OptionsCreate.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelScript.Internal;
3 | using ExcelScript.Registration;
4 | using System;
5 |
6 | namespace ExcelScript
7 | {
8 | public partial class ExcelScriptAddin
9 | {
10 | [ExcelFunction(Name = FunctionPrefix + "Options.Create", Description = "Can be used to create/set options for user scripts. The result handle of this can be passed to the ExcelScript.Create() function's OptionsHandle parameter", IsVolatile = false)]
11 | [SuppressInDialog]
12 | [ManageDirtyFlags]
13 | public static object OptionsCreate(
14 | [ExcelArgument(Description = "Name of the object handle to be created")] string HandleName,
15 | [ExcelArgument(Description = "Return type of the script. Object by default.")] string ReturnType = "object",
16 | [ExcelArgument(Description = "Hosting type for script execution. Possible values: Shared = Same for all scripts (default). Individual = Seperate AppDomain for each script. Global = Same AppDomain as ExcelScript-Addin.")] string HostingType = "Shared"
17 | )
18 | {
19 | Type _ReturnType = ToType(ReturnType);
20 | ScriptingAbstractions.HostingType _HostingType = ToHostingType(HostingType);
21 |
22 | var options = new XlScriptOptions(_ReturnType, _HostingType);
23 | return AddOrUpdateInStoreOrThrow(HandleName, options, () => TryDispose(options));
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/ParameterCreate.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelScript.Internal;
3 | using ExcelScript.Registration;
4 | using ObjectStorage.Abstractions;
5 | using ScriptingAbstractions;
6 | using System;
7 |
8 | namespace ExcelScript
9 | {
10 | public partial class ExcelScriptAddin
11 | {
12 | [ExcelFunction(Name = FunctionPrefix + "Parameter.Create", Description = "Creates a definition for an input parameter for a user script. This can then be passed on to ExcelSCript.Create() ParameterHandles.", IsVolatile = false)]
13 | [SuppressInDialog]
14 | [ManageDirtyFlags]
15 | public static object Parameter_Create(
16 | [ExcelArgument(Description = "Name under which the parameter will be usable in scripts")] string ParameterName,
17 | [ExcelArgument(Description = "Type of the parameter")] string ParameterType,
18 | [ExcelArgument(Description = "If true, this parameter can be ommitted when calling the script, and will then default to its defaultValue (next parameter)")] bool isOptional = false,
19 | [ExcelArgument(Description = "Default value if the parameter is ommitted - only specify this when isOptional (previous parameter) = true")] object defaultValue = null,
20 | string Description = null,
21 | string HandleName = null)
22 | {
23 | if (String.IsNullOrWhiteSpace(ParameterName))
24 | throw new ArgumentException("Parameter name was empty", nameof(ParameterName));
25 |
26 | if (!Microsoft.CodeAnalysis.CSharp.SyntaxFacts.IsValidIdentifier(ParameterName))
27 | throw new ArgumentException("Parameter name was not in a valid format; must be in the format of a valid C# identifier", nameof(ParameterName));
28 |
29 | if (!isOptional && defaultValue != null)
30 | throw new ArgumentException("Please omit the default value when specifying the parameter as non-optional (isOptional = false).", nameof(defaultValue));
31 |
32 | if (HandleName == null)
33 | HandleName = ParameterName;
34 |
35 | var parameter = m_ParameterFactory.Create();
36 |
37 | parameter.Name = ParameterName;
38 | parameter.Type = ToType(ParameterType);
39 | parameter.IsOptional = isOptional;
40 | parameter.Description = Description;
41 |
42 | if (isOptional)
43 | parameter.DefaultValue = defaultValue;
44 |
45 | IStoredObject storedParameter;
46 | string result = AddOrUpdateInStoreOrThrow(HandleName, parameter, out storedParameter, () => TryDispose(parameter));
47 |
48 | return result;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/Parse.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelScript.Internal;
3 | using ExcelScript.Registration;
4 | using ObjectStorage.Abstractions;
5 | using RoslynScriptGlobals;
6 | using RoslynScripting;
7 | using ScriptingAbstractions;
8 | using System;
9 | using System.Linq;
10 | using System.Reflection;
11 |
12 | namespace ExcelScript
13 | {
14 | public partial class ExcelScriptAddin
15 | {
16 | [ExcelFunction(Name = FunctionPrefix + nameof(Parse), Description = "Creates a reusable script, and returns its Handle - which can then by invoked with the ExcelScript.Run method", IsVolatile = false)]
17 | [SuppressInDialog]
18 | [ManageDirtyFlags]
19 | public static object Parse(
20 | [ExcelArgument("The code for this script. Multiple lines are allowed.")] string[] code,
21 | [ExcelArgument("A handle to script option definitions as created by ExcelScript.Options.Create. Can be left blank to use defaults.")] string OptionsHandle = "",
22 | [ExcelArgument("Name for a handle under which the script object will be stored in memory, Can be ommitted, in which case the function name will be used.")] string HandleName = "")
23 | {
24 | if (code == null)
25 | throw new ArgumentNullException(nameof(code));
26 |
27 | string _code = String.Join(Environment.NewLine, code);
28 |
29 | // CAREFUL: This method may be run in a different AppDomain! Don't reference anything from outside of the delegate
30 | Func EntryMethodSelector = (methods) =>
31 | {
32 | MethodInfo result = null;
33 |
34 | // When only one method is available, we'll just return that one...
35 | if (methods.Count() == 1)
36 | {
37 | result = methods.Single();
38 | }
39 | else
40 | {
41 | // Otherwise, we'll try to find a (one) function marked with an [ExcelFunction] attribute
42 | var markedMethods = methods
43 | .Where(x => x.GetCustomAttribute() != null);
44 |
45 | if (markedMethods.Count() == 0)
46 | throw new ArgumentException($"Your script defines {methods.Count()} methods; please mark one of them with the [ExcelFunction] attribute, to mark which function shall be used as an entry point to your script.");
47 |
48 | if (markedMethods.Count() > 1)
49 | throw new ArgumentException($"Please only mark one function with an [ExcelFunction] attribute; you have currently marked {markedMethods.Count()} functions: " + String.Join(", ", markedMethods.Select(x => x.Name)));
50 |
51 | result = markedMethods.Single();
52 | }
53 |
54 | return result;
55 | };
56 |
57 | // CAREFUL: This method may be run in a different AppDomain! Don't reference anything from outside of the delegate
58 | Func EntryMethodParameterFactory = (method =>
59 | {
60 | return method
61 | .GetParameters()
62 | .Select(x =>
63 | {
64 | var excelArgumentAttribute = x.GetCustomAttribute();
65 |
66 | return new Parameter
67 | {
68 | Name = (excelArgumentAttribute == null || String.IsNullOrWhiteSpace(excelArgumentAttribute.Name)) ? x.Name : excelArgumentAttribute.Name,
69 | Type = x.ParameterType,
70 | IsOptional = x.IsOptional,
71 | DefaultValue = x.DefaultValue,
72 | Description = (excelArgumentAttribute == null || String.IsNullOrWhiteSpace(excelArgumentAttribute.Description)) ? String.Empty : excelArgumentAttribute.Description
73 | };
74 | })
75 | .ToArray();
76 | });
77 |
78 | // Create Script object
79 | XlScriptOptions xlScriptOptions = (String.IsNullOrEmpty(OptionsHandle)) ? XlScriptOptions.Default : GetFromStoreOrThrow(OptionsHandle);
80 | var options = CreateScriptingOptionsFrom(xlScriptOptions);
81 | options.References.Add(typeof(ExcelFunctionAttribute).Assembly);
82 | options.Imports.Add(typeof(ExcelFunctionAttribute).Namespace);
83 |
84 | var parseResult = m_ScriptFactory.ParseFromAsync(m_GlobalsFactory, options, _code, EntryMethodSelector, EntryMethodParameterFactory).Result;
85 | var script = parseResult.Script;
86 | script.ReturnType = xlScriptOptions.ReturnType;
87 |
88 | if (String.IsNullOrWhiteSpace(HandleName))
89 | HandleName = parseResult.EntryMethodName;
90 |
91 | IStoredObject storedScript;
92 | if (m_ObjectStore.GetByName(HandleName, out storedScript) && storedScript.Object.GetHashCode() == script.GetHashCode())
93 | {
94 | return HandleNames.ToHandle(storedScript);
95 | }
96 | else
97 | {
98 | return AddOrUpdateInStoreOrThrow(HandleName, script, () => TryDispose(script));
99 | }
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/ExcelScript/AddinFunctions/Serialize.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelScript.Internal;
3 | using ExcelScript.Registration;
4 | using ObjectStorage.Abstractions;
5 | using System;
6 | using System.IO;
7 | using System.IO.Compression;
8 | using System.Text;
9 | using System.Xml.Linq;
10 | using System.Xml.Serialization;
11 |
12 | namespace ExcelScript
13 | {
14 | public partial class ExcelScriptAddin
15 | {
16 | [ExcelFunction(Name = FunctionPrefix + nameof(Serialize), IsVolatile = false, Description = "Serializes the object into a format which can later be re-loaded (with ExcelScript.Deserialize)")]
17 | [SuppressInDialog]
18 | public static object Serialize(
19 | [ExcelArgument(Description = "Handle to the object which shall be serialized")] string Handle,
20 | [ExcelArgument(Description = "If true, compressed the output. Signitifantly reduces the size of the output, but obfuscates it (makes it unreadable to humans)")] bool Compress = false,
21 | [ExcelArgument(Description = "Optional. If a file path is given, the deserialized data will be saved to a file to the given target destination")] string OutputFilePath = null)
22 | {
23 | return InternalSerialize(Handle, Compress, OutputFilePath);
24 | }
25 |
26 | private static object InternalSerialize(string HandleName, bool Compress = false, string OutputFilePath = null)
27 | {
28 | HandleName = HandleNames.GetNameFrom(HandleName);
29 | IStoredObject storedObj;
30 |
31 | if (!m_ObjectStore.GetByName(HandleName, out storedObj))
32 | throw new Exception($"No object named {HandleName} found");
33 |
34 | bool WriteToFile = !String.IsNullOrWhiteSpace(OutputFilePath);
35 |
36 | var obj = new SerializationWrapper { ContainedObject = storedObj };
37 | var result = XmlSerialize(obj);
38 |
39 | if (Compress)
40 | {
41 | var compressed = Zip(result);
42 | XDocument doc = new XDocument(new XElement("CompressedData", new XAttribute("Algorithm", "gzip"), Convert.ToBase64String(compressed)));
43 |
44 | if (WriteToFile)
45 | {
46 | OutputFilePath = Environment.ExpandEnvironmentVariables(OutputFilePath);
47 |
48 | using (var fileWriter = new FileStream(OutputFilePath, FileMode.Create))
49 | {
50 | doc.Save(fileWriter);
51 | }
52 | return $"Written to '{OutputFilePath}' in compressed format.";
53 | }
54 | else
55 | {
56 | using (var stringWriter = new StringWriter())
57 | {
58 | doc.Save(stringWriter);
59 | return stringWriter.ToString();
60 | }
61 | }
62 | }
63 | else
64 | {
65 | if (WriteToFile)
66 | {
67 | File.WriteAllLines(OutputFilePath, new string[] { result });
68 | return $"Written to '{OutputFilePath}' in uncompressed XML format.";
69 | }
70 | else
71 | {
72 | return result;
73 | }
74 | }
75 | }
76 |
77 | private static string XmlSerialize(T obj)
78 | {
79 | XmlSerializer serializer = new XmlSerializer(typeof(T));
80 | using (var writer = new StringWriter())
81 | {
82 | serializer.Serialize(writer, obj);
83 | return writer.ToString();
84 | }
85 | }
86 |
87 |
88 | // From http://stackoverflow.com/questions/7343465/compression-decompression-string-with-c-sharp
89 | private static byte[] Zip(string str)
90 | {
91 | var bytes = Encoding.UTF8.GetBytes(str);
92 |
93 | using (var msi = new MemoryStream(bytes))
94 | using (var mso = new MemoryStream())
95 | {
96 | using (var gs = new GZipStream(mso, CompressionMode.Compress))
97 | {
98 | CopyTo(msi, gs);
99 | }
100 |
101 | return mso.ToArray();
102 | }
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/ExcelScript/ExcelScript-AddIn.dna:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/ExcelScript/ExcelScript-AddIn.xll.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/ExcelScript/HandleNames.cs:
--------------------------------------------------------------------------------
1 | using ObjectStorage.Abstractions;
2 | using System;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace ExcelScript
6 | {
7 | public static class HandleNames
8 | {
9 | private static readonly Regex HandleRegex = new Regex("^(.*)(:[0-9]*)$");
10 | private static readonly Regex InvalidChars = new Regex("[^0-9a-zA-Z_]"); // only allow alphabetic characters, letters and underscores
11 |
12 | public static string ToHandle(IStoredObject storedObject)
13 | {
14 | return $"{storedObject.Name}:{storedObject.Version}";
15 | }
16 |
17 | ///
18 | /// Returns the Handle name from the given Handle
19 | /// e.g. Handle = Test:123, return value = Test
20 | /// Removes invalid characters.
21 | ///
22 | public static string GetNameFrom(string Text)
23 | {
24 | // Remove the :12345 at the end, if there is any
25 | var match = HandleRegex.Match(Text);
26 |
27 | if (match.Success)
28 | Text = match.Groups[1].Value;
29 |
30 | // Remove al invalid chars
31 | Text = InvalidChars.Replace(Text, String.Empty); // Remove invalid chars
32 |
33 | return Text;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ExcelScript/Internal/ManageDirtyFlagsAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace ExcelScript.Internal
8 | {
9 | [AttributeUsage(AttributeTargets.Method)]
10 | public class ManageDirtyFlagsAttribute : System.Attribute
11 | {
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ExcelScript/Internal/ParameterExtensions.cs:
--------------------------------------------------------------------------------
1 | using ExcelScript.Internal;
2 | using ScriptingAbstractions;
3 | using ScriptingAbstractions.Factory;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace ExcelScript
11 | {
12 | internal static class ParameterExtensions
13 | {
14 | private static readonly IParameterValueFactory m_ParameterValueFactory = new ParameterValueFactory();
15 |
16 | public static IParameterValue WithValue(this IParameter parameter, object Value)
17 | {
18 | return m_ParameterValueFactory.CreateFor(parameter, Value);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ExcelScript/Internal/ParameterValueFactory.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using RoslynScripting;
3 | using ScriptingAbstractions;
4 | using ScriptingAbstractions.Factory;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using Excel = NetOffice.ExcelApi;
11 |
12 | namespace ExcelScript.Internal
13 | {
14 | internal class ConverterInfo
15 | {
16 | public readonly TransferableValueToOriginalValueConverter transferableValueToOriginalValueConverter;
17 | public readonly OriginalValueToTransferableValueConverter originalValueToTransferableValueConverter;
18 | public readonly Type TransferableValueType;
19 |
20 | public ConverterInfo(TransferableValueToOriginalValueConverter transferableValueToOriginalValueConverter, OriginalValueToTransferableValueConverter originalValueToTransferableValueConverter, Type TransferableValueType)
21 | {
22 | this.transferableValueToOriginalValueConverter = transferableValueToOriginalValueConverter;
23 | this.originalValueToTransferableValueConverter = originalValueToTransferableValueConverter;
24 | this.TransferableValueType = TransferableValueType;
25 | }
26 |
27 | }
28 |
29 | public class ParameterValueFactory : IParameterValueFactory
30 | {
31 | private static readonly IDictionary Converters = CreateConverters();
32 |
33 | public IParameterValue CreateFor(IParameter Parameter, object WithValue)
34 | {
35 | var converter = GetMarshalConverterFor(Parameter);
36 | IParameterValue result;
37 |
38 | if(converter == null)
39 | {
40 | result = new ParameterValue(Parameter, WithValue);
41 | } else
42 | {
43 | result = new ParameterValue(Parameter, WithValue, converter.TransferableValueType, converter.originalValueToTransferableValueConverter, converter.transferableValueToOriginalValueConverter);
44 | }
45 |
46 | return result;
47 | }
48 |
49 |
50 |
51 | ///
52 | /// Gets the ConverterInfo needed to convert for marsalling the given parameter.
53 | /// If the type needs conversion but no appropriate converter is registered, throws an exception
54 | ///
55 | ///
56 | ///
57 | private static ConverterInfo GetMarshalConverterFor(IParameter Parameter)
58 | {
59 | if (!NeedsMarshalConverter(Parameter))
60 | return null;
61 |
62 | if (!Converters.ContainsKey(Parameter.Type))
63 | throw new InvalidOperationException($"Parameter value needs conversion, however did not find any converter to convert parameter type {Parameter.Type.Name} into a marshallable value");
64 |
65 | var result = Converters[Parameter.Type];
66 | return result;
67 | }
68 |
69 |
70 | private static bool NeedsMarshalConverter(IParameter Parameter)
71 | {
72 | if (Parameter.Type.IsValueType)
73 | return false; // marshals by value
74 |
75 | if (Parameter.Type == typeof(string))
76 | return false; // marshals by bleed
77 |
78 | if (typeof(MarshalByRefObject).IsAssignableFrom(Parameter.Type))
79 | return false; // marshals by ref
80 |
81 | if (Parameter.Type.IsSerializable)
82 | return false; // marshal by value - todo: double check this ALWAYS works with any .IsSerializable type
83 |
84 | return true;
85 | }
86 |
87 | private static IDictionary CreateConverters()
88 | {
89 | var result = new Dictionary();
90 |
91 | var rangeConverter = new ConverterInfo(TransferableValueToRange, RangeToTransferableValue, typeof(string));
92 | result.Add(typeof(Excel.Range), rangeConverter);
93 | return result;
94 | }
95 |
96 |
97 | #region Converter Functions
98 |
99 | // this will be executing on the host's appdomain
100 | private static Excel.Range TransferableValueToRange(object transferableValue)
101 | {
102 | string address = (string)transferableValue;
103 | var application = new Excel.Application(null, ExcelDnaUtil.Application);
104 | var range = application.Range(address);
105 |
106 | range.OnDispose += (args) =>
107 | {
108 | range.Application.Dispose();
109 | };
110 |
111 | return range;
112 | }
113 |
114 | private static string RangeToTransferableValue(object OriginalValue)
115 | {
116 | var range = (Excel.Range)OriginalValue;
117 | string result = range.Address(true, true, NetOffice.ExcelApi.Enums.XlReferenceStyle.xlA1, true);
118 | return result;
119 | }
120 |
121 | #endregion
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/ExcelScript/Internal/SerializationWrapper.cs:
--------------------------------------------------------------------------------
1 | using ExcelScript.CommonUtilities;
2 | using System.Xml;
3 | using System.Xml.Schema;
4 | using System.Xml.Serialization;
5 |
6 | namespace ExcelScript.Internal
7 | {
8 | public class SerializationWrapper : IXmlSerializable
9 | {
10 | public object ContainedObject { get; set; }
11 |
12 | #region IXmlSerializable
13 |
14 | public XmlSchema GetSchema()
15 | {
16 | return null;
17 | }
18 |
19 | public void WriteXml(XmlWriter writer)
20 | {
21 | writer.Write(nameof(ContainedObject), ContainedObject);
22 | }
23 |
24 | public void ReadXml(XmlReader reader)
25 | {
26 | reader.MoveToCustomStart();
27 |
28 | object _ContainedObject;
29 |
30 | reader.Read(nameof(ContainedObject), out _ContainedObject);
31 |
32 | this.ContainedObject = _ContainedObject;
33 |
34 | reader.ReadEndElement();
35 | }
36 |
37 | #endregion
38 |
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ExcelScript/NinjectModules/ScriptingModule.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelScript.Internal;
3 | using Ninject.Modules;
4 | using ObjectStorage;
5 | using ObjectStorage.Abstractions;
6 | using RoslynScriptGlobals;
7 | using RoslynScripting.Factory;
8 | using ScriptingAbstractions;
9 | using ScriptingAbstractions.Factory;
10 | using System;
11 | using Excel = NetOffice.ExcelApi;
12 |
13 | namespace ExcelScript.NinjectModules
14 | {
15 | public class ScriptingModule : NinjectModule
16 | {
17 | public override void Load()
18 | {
19 | Bind().To().InSingletonScope();
20 | Bind().To().InSingletonScope();
21 | Bind().To().InSingletonScope();
22 | Bind>().ToConstant>(GetApplication).WhenInjectedInto();
23 | Bind>().To().InSingletonScope();
24 | Bind().ToSelf().InSingletonScope();
25 | }
26 |
27 | private static Excel.Application GetApplication()
28 | {
29 | return new Excel.Application(null, ExcelDnaUtil.Application);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ExcelScript/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("ExcelScript")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ExcelScript")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
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("f489edf9-1286-463b-8c76-3844169bc2d3")]
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 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ExcelScript/Registration/FunctionLogging.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Registration;
2 | using System.Linq;
3 |
4 | namespace ExcelScript.Registration
5 | {
6 | public class FunctionLoggingHandler : FunctionExecutionHandler
7 | {
8 | int Index;
9 | public override void OnEntry(FunctionExecutionArgs args)
10 | {
11 | // FunctionExecutionArgs gives access to the function name and parameters,
12 | // and gives some options for flow redirection.
13 |
14 | // Tag will flow through the whole handler
15 | args.Tag = args.FunctionName + ":" + Index;
16 |
17 | ExcelScriptAddin.m_Log.Debug("{0} - OnEntry - Args: {1}", args.Tag, string.Join(",", args.Arguments.Select(arg => arg.ToString())));
18 | }
19 |
20 | public override void OnSuccess(FunctionExecutionArgs args)
21 | {
22 | ExcelScriptAddin.m_Log.Debug("{0} - OnSuccess - Result: {1}", args.Tag, args.ReturnValue);
23 | }
24 |
25 | public override void OnException(FunctionExecutionArgs args)
26 | {
27 | ExcelScriptAddin.m_Log.Error("{0} - OnException - Message: {1}", args.Tag, args.Exception);
28 | }
29 |
30 | public override void OnExit(FunctionExecutionArgs args)
31 | {
32 | ExcelScriptAddin.m_Log.Debug("{0} - OnExit", args.Tag);
33 | }
34 |
35 | // The configuration part - maybe move somewhere else.
36 | // (Add a registration index just to show we can attach arbitrary data to the captured handler instance which may be created for each function.)
37 | // If we return the same object for every function, the object needs to be re-entrancy safe is used by IsThreadSafe functions.
38 | static int _index = 0;
39 | internal static FunctionExecutionHandler LoggingHandlerSelector(ExcelFunctionRegistration functionRegistration)
40 | {
41 | return new FunctionLoggingHandler { Index = _index++ };
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ExcelScript/Registration/RangeParameterConversion.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelDna.Registration;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Linq.Expressions;
7 | using Excel = NetOffice.ExcelApi;
8 |
9 | namespace ExcelScript.Registration
10 | {
11 | // based on https://github.com/Excel-DNA/Registration/blob/master/Source/ExcelDna.Registration.VisualBasic/RangeParameterConversion.vb
12 | public static class RangeParameterConversion
13 | {
14 | public static IEnumerable UpdateRegistrationForRangeParameters(this IEnumerable reg)
15 | {
16 | return reg.Select(UpdateAttributesForRangeParameters);
17 | }
18 |
19 | public static Expression> ParameterConversion(Type paramType, ExcelParameterRegistration paramRegistration)
20 | {
21 | if (paramType == typeof(Excel.Range))
22 | return (Expression>)((object input) => ReferenceToRange(input));
23 | else
24 | return null;
25 | }
26 |
27 | private static ExcelFunctionRegistration UpdateAttributesForRangeParameters(ExcelFunctionRegistration reg)
28 | {
29 | var rangeParams = reg.FunctionLambda.Parameters.Select((x, i) => new { _Parameter = x, _Index = i })
30 | .Where(x => x._Parameter.Type == typeof(Excel.Range));
31 |
32 | bool hasRangeParam = false;
33 | foreach(var param in rangeParams)
34 | {
35 | reg.ParameterRegistrations[param._Index].ArgumentAttribute.AllowReference = true;
36 | hasRangeParam = true;
37 | }
38 |
39 | if (hasRangeParam)
40 | reg.FunctionAttribute.IsMacroType = true;
41 |
42 | return reg;
43 | }
44 |
45 | private static Excel.Range ReferenceToRange(object input)
46 | {
47 | ExcelReference xlRef = (ExcelReference)input;
48 | return ExcelScriptAddin.FromExcelReferenceToRange(xlRef);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/ExcelScript/Registration/SuppressInDialog.cs:
--------------------------------------------------------------------------------
1 | using ExcelDna.Integration;
2 | using ExcelDna.Registration;
3 | using System;
4 | using System.Linq;
5 |
6 | namespace ExcelScript.Registration
7 | {
8 | // Alternative pattern - make this an attribute directly
9 | // CONSIDER: In this case we never need the parameters. It would be nice never have to pull them into the FunctionExecutionArgs.
10 |
11 | // TODO: Only works for functions that return string or object. Automatically add a return value conversion otherwise?
12 |
13 | [AttributeUsage(AttributeTargets.Method)]
14 | public class SuppressInDialogAttribute : Attribute, IFunctionExecutionHandler
15 | {
16 | readonly string _dialogResult;
17 | public SuppressInDialogAttribute(string dialogMessage = "!!! NOT CALCULATED IN DIALOG !!!")
18 | {
19 | _dialogResult = dialogMessage;
20 | }
21 |
22 | public void OnEntry(FunctionExecutionArgs args)
23 | {
24 | if (ExcelDnaUtil.IsInFunctionWizard())
25 | {
26 | args.ReturnValue = _dialogResult;
27 | args.FlowBehavior = FlowBehavior.Return;
28 | }
29 | // Otherwise we do not interfere
30 | }
31 |
32 | // Implemented just to satisfy the interface
33 | public void OnSuccess(FunctionExecutionArgs args) { }
34 | public void OnException(FunctionExecutionArgs args) { }
35 | public void OnExit(FunctionExecutionArgs args) { }
36 | }
37 |
38 | public static class SuppressInDialogFunctionExecutionHandler
39 | {
40 | ///
41 | /// Currently only applied to functions that return object or string.
42 | ///
43 | ///
44 | ///
45 | public static IFunctionExecutionHandler SuppressInDialogSelector(ExcelFunctionRegistration functionRegistration)
46 | {
47 | // Eat the TimingAttributes, and return a timer handler if there were any
48 | if (functionRegistration.CustomAttributes.OfType().Any() &&
49 | (functionRegistration.FunctionLambda.ReturnType == typeof(object) ||
50 | functionRegistration.FunctionLambda.ReturnType == typeof(string)))
51 | {
52 | // Get the first cache attribute, and remove all of them
53 | var suppressAtt = functionRegistration.CustomAttributes.OfType().First();
54 | functionRegistration.CustomAttributes.RemoveAll(att => att is SuppressInDialogAttribute);
55 |
56 | return suppressAtt;
57 | }
58 | return null;
59 |
60 | }
61 |
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/ExcelScript/Todos and Bugs.txt:
--------------------------------------------------------------------------------
1 | 1. Do return-value conversion / cross domain boxing
2 | 2. Do conversion from Range to Array types2
3 | 3. Implement an RunAsync() excel function
4 | 4. Extend Unit Tests
--------------------------------------------------------------------------------
/ExcelScript/XlScriptOptions.cs:
--------------------------------------------------------------------------------
1 | using ScriptingAbstractions;
2 | using System;
3 |
4 | namespace ExcelScript
5 | {
6 | public class XlScriptOptions
7 | {
8 | public Type ReturnType { get; private set; }
9 | public HostingType HostingType { get; private set; }
10 |
11 |
12 | public XlScriptOptions()
13 | {
14 | this.ReturnType = typeof(Object);
15 | this.HostingType = HostingType.SharedSandboxAppDomain;
16 | }
17 |
18 | public XlScriptOptions(Type ReturnType, HostingType HostingType)
19 | {
20 | this.ReturnType = ReturnType;
21 | this.HostingType = HostingType;
22 | }
23 |
24 | public static XlScriptOptions Default
25 | {
26 | get
27 | {
28 | return new XlScriptOptions();
29 | }
30 | }
31 |
32 | public override int GetHashCode()
33 | {
34 | unchecked
35 | {
36 | int hash = (int)2166136261;
37 |
38 | hash = (hash * 16777619) ^ ReturnType.GetHashCode();
39 | hash = (hash * 16777619) ^ HostingType.GetHashCode();
40 |
41 | return hash;
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/ExcelScript/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/ExcelScript/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/ObjectStorage/ObjectStorage.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {8AB1CE36-E883-4A98-9713-9F6A849376ED}
8 | Library
9 | Properties
10 | ObjectStorage
11 | ObjectStorage
12 | v4.6.1
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | {dc268d3e-5fb8-4bd0-93b6-588001fa8eae}
56 | CommonUtilities
57 |
58 |
59 | {7013fbc4-3d9b-48dc-986e-31b39bcad70b}
60 | ObjectStorageAbstractions
61 |
62 |
63 |
64 |
71 |
--------------------------------------------------------------------------------
/ObjectStorage/ObjectStore.cs:
--------------------------------------------------------------------------------
1 | using ObjectStorage.Abstractions;
2 | using System;
3 | using System.Collections.Concurrent;
4 | using System.Linq;
5 | using System.Reflection;
6 |
7 | namespace ObjectStorage
8 | {
9 | public class ObjectStore : IObjectStore
10 | {
11 | private readonly ConcurrentDictionary _StoredObjects = new ConcurrentDictionary();
12 |
13 | public bool GetByName(string name, out IStoredObject result)
14 | {
15 | IStoredObject