├── .gitignore
├── docs
└── addin-ribbon.png
├── JuliaInXL
├── juliaicon.png
├── juliafileopen.png
├── juliafileinclude.png
├── JuliaComputing_Icon.ico
├── juliafileselection.png
├── resources
│ ├── Examples.xlsx
│ ├── sim.jl
│ └── License.rtf
├── JuliaInExcel_TemporaryKey.pfx
├── setassemblyversion.bat
├── app.config
├── JuliaInXL.csproj.user
├── packages.config
├── Properties
│ ├── AssemblyInfo.noversion
│ └── AssemblyInfo.cs
├── JuliaInXL-AddIn.dna
├── julia.svg
├── JuliaInXL.csproj
└── AddInUtilities.cs
├── .gitattributes
├── LICENSE
├── JuliaInXL.sln
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs
2 | bin
3 | obj
4 | Setup/JuliaInXLSetup
5 | packages/*
6 | ~*
--------------------------------------------------------------------------------
/docs/addin-ribbon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuliaComputing/JuliaInXL/HEAD/docs/addin-ribbon.png
--------------------------------------------------------------------------------
/JuliaInXL/juliaicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuliaComputing/JuliaInXL/HEAD/JuliaInXL/juliaicon.png
--------------------------------------------------------------------------------
/JuliaInXL/juliafileopen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuliaComputing/JuliaInXL/HEAD/JuliaInXL/juliafileopen.png
--------------------------------------------------------------------------------
/JuliaInXL/juliafileinclude.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuliaComputing/JuliaInXL/HEAD/JuliaInXL/juliafileinclude.png
--------------------------------------------------------------------------------
/JuliaInXL/JuliaComputing_Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuliaComputing/JuliaInXL/HEAD/JuliaInXL/JuliaComputing_Icon.ico
--------------------------------------------------------------------------------
/JuliaInXL/juliafileselection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuliaComputing/JuliaInXL/HEAD/JuliaInXL/juliafileselection.png
--------------------------------------------------------------------------------
/JuliaInXL/resources/Examples.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuliaComputing/JuliaInXL/HEAD/JuliaInXL/resources/Examples.xlsx
--------------------------------------------------------------------------------
/JuliaInXL/JuliaInExcel_TemporaryKey.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JuliaComputing/JuliaInXL/HEAD/JuliaInXL/JuliaInExcel_TemporaryKey.pfx
--------------------------------------------------------------------------------
/JuliaInXL/setassemblyversion.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | @echo //>> AssemblyInfo.cs
3 | @echo [assembly: AssemblyVersion("%JuliaPro_Version%")] >> AssemblyInfo.cs
4 | @echo [assembly: AssemblyFileVersion("%JuliaPro_Version%")] >> AssemblyInfo.cs
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/JuliaInXL/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/JuliaInXL/JuliaInXL.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Program
5 | C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE
6 | JuliaInXL-32bit.xll
7 | C:\Users\andy\Documents\GitHub\JuliaInXL\JuliaInXL\bin\Debug\
8 |
9 |
--------------------------------------------------------------------------------
/JuliaInXL/resources/sim.jl:
--------------------------------------------------------------------------------
1 | using Distributions
2 | using JuliaWebAPI
3 | using Logging
4 | Logging.configure(level=DEBUG)
5 |
6 | f(u) = exp(-u^2/2)/√(2pi)
7 |
8 | const u1=Uniform(-5.0,+5.0)
9 | const u2=Uniform(0.0, 0.5)
10 |
11 | function simulate_pt()
12 | x=rand(u1)
13 | y=rand(u2)
14 | y
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Julia Computing, Inc.
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 |
--------------------------------------------------------------------------------
/JuliaInXL/Properties/AssemblyInfo.noversion:
--------------------------------------------------------------------------------
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("JuliaInXL")]
9 | [assembly: AssemblyDescription("Julia in Excel")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Julia Computing Inc")]
12 | [assembly: AssemblyProduct("JuliaInXL")]
13 | [assembly: AssemblyCopyright("Copyright © 2016 Julia Computing 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("a1829377-7fc9-42ea-b92b-26b2b2f83500")]
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.*")]
--------------------------------------------------------------------------------
/JuliaInXL/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("JuliaInXL")]
9 | [assembly: AssemblyDescription("Julia in Excel")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Julia Computing Inc")]
12 | [assembly: AssemblyProduct("JuliaInXL")]
13 | [assembly: AssemblyCopyright("Copyright © 2016 Julia Computing 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("a1829377-7fc9-42ea-b92b-26b2b2f83500")]
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("0.5.0.4")]
36 | [assembly: AssemblyFileVersion("0.5.0.4")]
37 |
38 |
--------------------------------------------------------------------------------
/JuliaInXL.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.24720.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JuliaInXL", "JuliaInXL\JuliaInXL.csproj", "{A1829377-7FC9-42EA-B92B-26B2B2F83500}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | CD_ROM|Any CPU = CD_ROM|Any CPU
11 | Debug|Any CPU = Debug|Any CPU
12 | DVD-5|Any CPU = DVD-5|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | SingleImage|Any CPU = SingleImage|Any CPU
15 | EndGlobalSection
16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
17 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU
18 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.CD_ROM|Any CPU.Build.0 = Release|Any CPU
19 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
20 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.Debug|Any CPU.Build.0 = Debug|Any CPU
21 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU
22 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.DVD-5|Any CPU.Build.0 = Debug|Any CPU
23 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU
26 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}.SingleImage|Any CPU.Build.0 = Release|Any CPU
27 | EndGlobalSection
28 | GlobalSection(SolutionProperties) = preSolution
29 | HideSolutionNode = FALSE
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/JuliaInXL/resources/License.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fmodern\fprq1\fcharset0 Courier New;}{\f1\fnil\fcharset0 Calibri;}}
2 | {\colortbl ;\red0\green0\blue0;}
3 | {\*\generator Riched20 10.0.22000}\viewkind4\uc1
4 | \pard\widctlpar\qc\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf1\b\f0\fs20\lang2057 MIT License\par
5 |
6 | \pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\b0\par
7 | Copyright (c) 2015-2022 Julia Computing, Inc.\par
8 | \par
9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\par
10 | \par
11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\par
12 | \par
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\par
14 |
15 | \pard\sa200\sl276\slmult1\cf0\f1\fs22\lang9\par
16 | }
17 |
--------------------------------------------------------------------------------
/JuliaInXL/JuliaInXL-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 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/JuliaInXL/julia.svg:
--------------------------------------------------------------------------------
1 |
2 |
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Call Julia functions from Microsoft Excel
2 |
3 | ### Installation
4 |
5 | The JuliaInXL system is composed of two parts, a Julia package and an Excel Plugin. The Excel plugin itself consists of an XLL add-in.
6 |
7 | The Excel plugin is distributed as an installable exe: JuliaProfessional_JuliaInXL_Addin_vW.X.Y.Z.exe, where vW.X.Y.Z is the associated version number of Julia Professional. Running this installer will install the XLL into `\[APPDATA]\Roaming\Microsoft\AddIns\`. Use of the JuliaInXL plug-in depends on .NET v4.0 or later being available on the system. After installation, the add-in needs to be enabled via either [File -> Options -> Add-ins](https://support.office.com/en-us/article/View-manage-and-install-add-ins-in-Office-programs-16278816-1948-4028-91E5-76DCA5380F8D) menu entry or the [Developer/Add-In](https://msdn.microsoft.com/en-us/library/bb608625.aspx) ribbon button.
8 |
9 | The Julia language package can be installed by doing (on the Julia REPL) `Pkg.add("JuliaInXL")`, if you have the rights to that repository. However, you will most likely be provided this package as part of your Julia Professional Bundle. This package depends on two public packages, `JuliaWebAPI` and `Reexport`.
10 |
11 | ### Usage Workflow
12 |
13 | #### Getting Started
14 | The primary supported workflow is for interactive development of Julia programs alongside Excel. Once the packages are installed, start Excel, and a Julia REPL. On the Julia repl, type `using JuliaInXL` to make the environment ready for calling via Excel. After that, define your functions as normal on the REPL. To try an an example, use a demo file included with the package: `include("C:\\Users\\\\AppData\\Local\\JuliaPro-W.X.Y.Z\\Julia-W.X.Y\\share\\julia\\site\\vW.X\\JuliaInXL\\test\\sim.jl")` where `` is your current Windows username and W.X.Y.Z are integers representing the current release of Julia Professional. (When using theses examples, you will need the `Distributions.jl` package installed. Please run `Pkg.add("Distributions")` on the Julia REPL if you do not have this already installed.)
15 |
16 | Once you have the functions that you need to call from Excel, expose them via the `process_async` call. This will start the server listening to requests from Excel in the background, and return a connection object that can be used for exposing more functions later. The primary arguments to this function is an array of functions to be exposed, and the endpoint on which to listen to messages. The `bind=true` parameter tells the function to start listening at the endpoint and wait for client connections.
17 |
18 | ```julia
19 | conn = process_async([simulate, simulateTime], "tcp://127.0.0.1:9999", bind=true)
20 | ```
21 |
22 | There is a corresponding `process` function with exactly the same API which listens synchronously, and thus doesn't return. This function should be used if the process is started from a command line, rather than via an iteractive REPL.
23 |
24 | #### Calling functions from Excel
25 |
26 | Once the server is started, julia functions can be called from Excel using the `jlcall` worksheet function. The first argument to jlcall is a string, which is the name of the function to be called. Subsequent arguments to the `jlcall` function are passed as parameters to the Julia function being called. These can be constant literals, or cell references. Arrays can be passed via cell ranges.
27 |
28 | If the Julia function returns an array (1d or 2d), then use `jlcall` as an Excel Array function by selecting a range before entering the function, and pressing `Shift-Ctrl-Enter` to finish.
29 |
30 | Functions exposed to Excel should take floats or strings, or their arrays as arguments. In general, it is a good idea to keep the function arguments as loosely typed as possible. Therefore functions should return integers, floats, or strings; or their arrays. However, arrays of dimensions greater than two are not supported.
31 |
32 | Note that [Excel stores all numbers as 64 bit IEEE floats](https://support.microsoft.com/en-us/kb/78113). Therefore, be aware of the possibility of truncation if returning large, or high precision, numbers.
33 |
34 | Dates are passed in from excel as floating point numbers in its internal encoding (fractional days since 1/1/1900 or 1/1/1904). Thus, they are recieved in Julia functions as floats. They can be converted to Julia DateTime values using the `xldate` function.
35 |
36 | #### Making changes
37 |
38 | Remember that we started the Julia server in async mode. This means that the REPL is available for interactive use when working with Excel. Creating new definitions of functions that are already exposed will replace them, and the new versions will get called when the sheet is next recalculated.
39 |
40 | New functions can be added to the listener interface using the connection object saved from the original `process_async` call, via the `register` function. The arguments to `register` are the connection object returned from `process_async`, and the function name to expose.
41 |
42 | ```julia
43 | register(conn, simulateArray)
44 | ```
45 | #### Controlling Julia from within Excel
46 | 
47 |
48 | ----
49 | _Microsoft and Excel are registered trademarks of Microsoft Corporation_
50 |
--------------------------------------------------------------------------------
/JuliaInXL/JuliaInXL.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {A1829377-7FC9-42EA-B92B-26B2B2F83500}
8 | Library
9 | Properties
10 | JuliaInXL
11 | JuliaInXL
12 | v4.0
13 | 512
14 | Client
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | none
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 0
32 |
33 |
34 | false
35 |
36 |
37 |
38 | ..\packages\AsyncIO.0.1.18.0\lib\net40\AsyncIO.dll
39 | True
40 |
41 |
42 | ..\packages\ExcelDna.Integration.0.33.9\lib\ExcelDna.Integration.dll
43 | False
44 |
45 |
46 | ..\packages\ExcelDna.Registration.0.33.9\lib\net40\ExcelDna.Registration.dll
47 | True
48 |
49 |
50 | ..\packages\NetMQ.3.3.3.1\lib\net40\NetMQ.dll
51 | True
52 |
53 |
54 | ..\packages\Newtonsoft.Json.8.0.3\lib\net40\Newtonsoft.Json.dll
55 | True
56 |
57 |
58 |
59 |
60 | ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll
61 | True
62 |
63 |
64 | ..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.dll
65 | True
66 |
67 |
68 | ..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.Extensions.dll
69 | True
70 |
71 |
72 | ..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.Primitives.dll
73 | True
74 |
75 |
76 | ..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.WebRequest.dll
77 | True
78 |
79 |
80 | ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll
81 | True
82 |
83 |
84 | ..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll
85 | True
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | Always
102 |
103 |
104 | Always
105 |
106 |
107 | Always
108 |
109 |
110 | Always
111 |
112 |
113 | PreserveNewest
114 | Designer
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | xcopy "$(SolutionDir)packages\ExcelDna.AddIn.0.33.9\tools\ExcelDna.Integration.dll" "$(TargetDir)ExcelDna.Integration.dll*" /C /Y
123 | xcopy "$(SolutionDir)packages\ExcelDna.AddIn.0.33.9\tools\ExcelDna.xll" "$(TargetDir)JuliaInXL-AddIn.xll*" /C /Y
124 | xcopy "$(ProjectDir)JuliaInXL-AddIn.dna" "$(TargetDir)JuliaInXL-AddIn.dna*" /C /Y
125 | xcopy "$(TargetDir)JuliaInXL-AddIn.dna" "$(TargetDir)JuliaInXL-AddIn64.dna*" /C /Y
126 | xcopy "$(SolutionDir)packages\ExcelDna.AddIn.0.33.9\tools\ExcelDna64.xll" "$(TargetDir)JuliaInXL-AddIn64.xll*" /C /Y
127 | "$(SolutionDir)packages\ExcelDna.AddIn.0.33.9\tools\ExcelDnaPack.exe" "$(TargetDir)JuliaInXL-AddIn.dna" /Y
128 | "$(SolutionDir)packages\ExcelDna.AddIn.0.33.9\tools\ExcelDnaPack.exe" "$(TargetDir)JuliaInXL-AddIn64.dna" /Y
129 | del /Q "$(TargetDir)ExcelDna.Integration.dll"
130 | del /Q "$(TargetDir)ExcelDna.Registration.dll"
131 | del /Q "$(TargetDir)AsyncIO.dll"
132 | del /Q "$(TargetDir)JuliaInXL.dll"
133 | del /Q "$(TargetDir)JuliaInXL.dll.config"
134 | del /Q "$(TargetDir)NetMQ.dll"
135 | del /Q "$(TargetDir)NetMQ.xml"
136 | del /Q "$(TargetDir)Newtonsoft.Json.dll"
137 | del /Q "$(TargetDir)Newtonsoft.Json.xml"
138 | del /Q "$(TargetDir)JuliaInXL-AddIn.dna"
139 | del /Q "$(TargetDir)JuliaInXL-AddIn64.dna"
140 | del /Q "$(TargetDir)System.IO.dll"
141 | del /Q "$(TargetDir)System.IO.xml"
142 | del /Q "$(TargetDir)System.Net.Http.dll"
143 | del /Q "$(TargetDir)System.Net.Http.xml"
144 | del /Q "$(TargetDir)System.Net.Http.Extensions.dll"
145 | del /Q "$(TargetDir)System.Net.Http.Extensions.xml"
146 | del /Q "$(TargetDir)System.Net.Http.Primitives.dll"
147 | del /Q "$(TargetDir)System.Net.Http.Primitives.xml"
148 | del /Q "$(TargetDir)System.Net.Http.WebRequest.dll"
149 | del /Q "$(TargetDir)System.Net.Http.WebRequest.xml"
150 | del /Q "$(TargetDir)System.Runtime.dll"
151 | del /Q "$(TargetDir)System.Runtime.xml"
152 | del /Q "$(TargetDir)System.Threading.Tasks.dll"
153 | del /Q "$(TargetDir)System.Threading.Tasks.xml"
154 | del /Q "$(TargetDir)JuliaInXL-AddIn.xll"
155 | del /Q "$(TargetDir)JuliaInXL-AddIn64.xll"
156 | del /Q "$(TargetDir)juliaicon.png"
157 | del /Q "$(TargetDir)juliafileopen.png"
158 | del /Q "$(TargetDir)juliafileinclude.png"
159 | del /Q "$(TargetDir)juliafileselection.png"
160 | rename "$(TargetDir)JuliaInXL-AddIn-packed.xll" "JuliaInXL-32bit.xll"
161 | rename "$(TargetDir)JuliaInXL-AddIn64-packed.xll" "JuliaInXL-64bit.xll"
162 |
163 |
164 | del /Q "$(TargetDir)JuliaInXL-32bit.xll"
165 | del /Q "$(TargetDir)JuliaInXL-64bit.xll"
166 | xcopy /y "$(ProjectDir)Properties\AssemblyInfo.noversion" "$(ProjectDir)\Properties\AssemblyInfo.cs"
167 | cd "$(ProjectDir)Properties"
168 | CALL "$(ProjectDir)setassemblyversion.bat"
169 |
170 |
171 |
172 |
173 |
174 |
175 |
182 |
--------------------------------------------------------------------------------
/JuliaInXL/AddInUtilities.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Text.RegularExpressions;
8 | using System.Threading;
9 | using System.Windows.Forms;
10 | using ExcelDna.Integration;
11 | using ExcelDna.Integration.Extensibility;
12 | using ExcelDna.ComInterop;
13 | using ExcelDna.Integration.CustomUI;
14 | using ExcelDna.Registration;
15 | using ExcelDna.Logging;
16 |
17 | using NetMQ;
18 | using Newtonsoft.Json.Linq;
19 | using NetMQ.Sockets;
20 | using Microsoft.Win32;
21 | using System.Collections.Generic;
22 |
23 | namespace JuliaInXL
24 | {
25 |
26 | [Serializable()]
27 | public class JuliaException : System.Exception
28 | {
29 | public JuliaException() : base() { }
30 | public JuliaException(string message) : base(message) { }
31 | public JuliaException(string message, System.Exception inner) : base(message, inner) { }
32 |
33 | // A constructor is needed for serialization when an
34 | // exception propagates from a remoting server to the client.
35 | protected JuliaException(System.Runtime.Serialization.SerializationInfo info,
36 | System.Runtime.Serialization.StreamingContext context)
37 | { }
38 | }
39 |
40 | [ComVisible(true)]
41 | public interface IAddInUtilities
42 | {
43 | object CallJulia(string fn, object[] arguments,int JuliaInXL_timeout=30);
44 | void Terminate();
45 | void Reconnect();
46 | Process LaunchLocalJulia();
47 | void ShutdownJulia(Process p);
48 | }
49 |
50 | [ComVisible(true)]
51 | [ClassInterface(ClassInterfaceType.AutoDual)]
52 | public class AddInUtilities : IAddInUtilities
53 | {
54 | private RequestSocket client;
55 | private NetMQContext context;
56 | private Process juliaprocess = new Process();
57 | private string juliaversion;
58 | private string juliaproversion;
59 | private string endpoint = "tcp://localhost:9999";
60 | private string juliafile = "";
61 | private bool connected = false;
62 |
63 | public string Endpoint
64 | {
65 | get
66 | {
67 | return endpoint;
68 | }
69 |
70 | set
71 | {
72 | endpoint = value;
73 | }
74 | }
75 |
76 | public Process JuliaProcess
77 | {
78 | get
79 | {
80 | return juliaprocess;
81 | }
82 |
83 | set
84 | {
85 | juliaprocess = value;
86 | }
87 | }
88 |
89 | public string JuliaProVersion
90 | {
91 | get
92 | {
93 | return juliaproversion;
94 | }
95 |
96 | set
97 | {
98 | juliaproversion = value;
99 | }
100 | }
101 |
102 | public string JuliaVersion
103 | {
104 | get
105 | {
106 | return juliaversion;
107 | }
108 |
109 | set
110 | {
111 | juliaversion = value;
112 | }
113 | }
114 |
115 | public string JuliaFile
116 | {
117 | get
118 | {
119 | return juliafile;
120 | }
121 | set
122 | {
123 | juliafile = value;
124 | }
125 | }
126 |
127 | public bool Connected
128 | {
129 | get
130 | {
131 | return connected;
132 | }
133 | set
134 | {
135 | connected = value;
136 | }
137 | }
138 |
139 | public static bool registryValueExists(string hive_HKLM_or_HKCU, string registryRoot, string valueName)
140 | {
141 | RegistryKey root;
142 |
143 | switch (hive_HKLM_or_HKCU.ToUpper())
144 | {
145 | case "HKLM":
146 | RegistryKey localMachineRegistry
147 | = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
148 | Environment.Is64BitOperatingSystem
149 | ? RegistryView.Registry64
150 | : RegistryView.Registry32);
151 |
152 | root = localMachineRegistry.OpenSubKey(registryRoot);
153 |
154 | break;
155 | case "HKCU":
156 |
157 | root = Registry.CurrentUser.OpenSubKey(registryRoot);
158 |
159 | break;
160 | default:
161 | throw new System.InvalidOperationException("parameter registryRoot must be either \"HKLM\" or \"HKCU\"");
162 | }
163 |
164 | bool test = (root != null) && (root.GetValue(valueName) != null);
165 |
166 | return test;
167 | }
168 |
169 | public AddInUtilities()
170 | {
171 |
172 | Version version = Assembly.GetExecutingAssembly().GetName().Version;
173 | JuliaVersion = version.Major + "." + version.Minor + "." + version.Build;
174 | JuliaProVersion = JuliaVersion + "." + version.Revision;
175 |
176 | // Check for either JuliaInXL or JuliaPro contained within the registry path to the JuliaPro installation.
177 | if (registryValueExists("HKCU", "Software\\JuliaPro\\JuliaInXL", "JuliaInXL_Default_Endpoint") == true)
178 | {
179 | endpoint = (string)Registry.GetValue(@"HKEY_CURRENT_USER\Software\JuliaPro\JuliaInXL", "JuliaInXL_Default_Endpoint", "");
180 | }
181 | else if (registryValueExists("HKCU", "Software\\JuliaPro\\" + JuliaProVersion, "JuliaInXL_Default_Endpoint") == true)
182 | {
183 | endpoint = (string)Registry.GetValue(@"HKEY_CURRENT_USER\Software\JuliaPro\" + JuliaProVersion, "JuliaInXL_Default_Endpoint", "");
184 | }
185 | else if (registryValueExists("HKLM", "Software\\JuliaPro\\JuliaInXL", "JuliaInXL_Default_Endpoint") == true)
186 | {
187 | RegistryKey localMachineRegistry
188 | = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
189 | Environment.Is64BitOperatingSystem
190 | ? RegistryView.Registry64
191 | : RegistryView.Registry32);
192 |
193 | RegistryKey key = localMachineRegistry.OpenSubKey("Software\\JuliaPro\\JuliaInXL");
194 |
195 | endpoint = (string)key.GetValue("JuliaInXL_Default_Endpoint");
196 | }
197 | else if (registryValueExists("HKLM", "Software\\JuliaPro\\" + JuliaProVersion, "JuliaInXL_Default_Endpoint") == true)
198 | {
199 | RegistryKey localMachineRegistry
200 | = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
201 | Environment.Is64BitOperatingSystem
202 | ? RegistryView.Registry64
203 | : RegistryView.Registry32);
204 |
205 | RegistryKey key = localMachineRegistry.OpenSubKey("Software\\JuliaPro\\" + JuliaProVersion);
206 |
207 | endpoint = (string)key.GetValue("JuliaInXL_Default_Endpoint");
208 | }
209 | else if (Environment.GetEnvironmentVariable("JULIAINXL_DEFAULT_ENDPOINT") != null)
210 | {
211 | endpoint = Environment.GetEnvironmentVariable("JULIAINXL_DEFAULT_ENDPOINT");
212 | }
213 | else
214 | {
215 | endpoint = "tcp://localhost:9999";
216 | }
217 |
218 | context = NetMQ.NetMQContext.Create();
219 | client = context.CreateRequestSocket();
220 | client.Connect(endpoint);
221 | Connected = true;
222 | }
223 |
224 | public Process LaunchLocalJulia()
225 | {
226 | string julia_exe;
227 | Version version = Assembly.GetExecutingAssembly().GetName().Version;
228 | JuliaVersion = version.Major + "." + version.Minor + "." + version.Build;
229 | JuliaProVersion = JuliaVersion + "." + version.Revision;
230 |
231 | // Check for either JuliaInXL or JuliaPro contained within the registry path to the JuliaPro installation.
232 | if (registryValueExists("HKCU", "Software\\JuliaPro\\JuliaInXL\\", "Install_Dir") == true)
233 | {
234 | string juliaBaseDir = (string)Registry.GetValue(@"HKEY_CURRENT_USER\Software\JuliaPro\JuliaInXL\", "Install_Dir", "");
235 | julia_exe = juliaBaseDir + "\\julia.exe";
236 | }
237 | else if (registryValueExists("HKCU", "Software\\JuliaPro\\" + JuliaProVersion, "Install_Dir") == true)
238 | {
239 | string juliaBaseDir = (string)Registry.GetValue(@"HKEY_CURRENT_USER\Software\JuliaPro\" + JuliaProVersion, "Install_Dir", "");
240 | julia_exe = juliaBaseDir + "\\Julia-" + JuliaVersion + "\\bin\\julia.exe";
241 | }
242 | else if (registryValueExists("HKLM", "Software\\JuliaInXL\\" + JuliaProVersion, "Install_Dir") == true)
243 | {
244 | RegistryKey localMachineRegistry
245 | = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
246 | Environment.Is64BitOperatingSystem
247 | ? RegistryView.Registry64
248 | : RegistryView.Registry32);
249 | RegistryKey key = localMachineRegistry.OpenSubKey("Software\\JuliaPro\\JuliaInXL");
250 | string juliaBaseDir = (string) key.GetValue("Install_Dir");
251 | julia_exe = juliaBaseDir + "\\julia.exe";
252 | }
253 | else if (registryValueExists("HKLM", "Software\\JuliaPro\\" + JuliaProVersion, "Install_Dir") == true)
254 | {
255 | RegistryKey localMachineRegistry
256 | = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
257 | Environment.Is64BitOperatingSystem
258 | ? RegistryView.Registry64
259 | : RegistryView.Registry32);
260 | RegistryKey key = localMachineRegistry.OpenSubKey("Software\\JuliaPro\\" + JuliaProVersion);
261 | string juliaBaseDir = (string)key.GetValue("Install_Dir");
262 | julia_exe = juliaBaseDir + "\\Julia-" + JuliaVersion + "\\bin\\julia.exe";
263 | }
264 | else
265 | {
266 | julia_exe = "julia.exe";
267 | }
268 |
269 | Process p = new Process();
270 |
271 | try
272 | {
273 | string endpoint = Endpoint;
274 | char[] delimiter = { ':' };
275 | string[] words = endpoint.Split(delimiter);
276 | string port = words[words.Length - 1];
277 | string host = words[words.Length - 2];
278 |
279 | string address;
280 | if (host.Equals("//localhost"))
281 | {
282 | address = "//127.0.0.1";
283 | }
284 | else
285 | {
286 | address = host;
287 | }
288 |
289 | string commandlineargs = String.Join("", "-i -e \"using JuliaInXL; JuliaInXL.start_async_server(", port, ")\"");
290 |
291 | p.StartInfo.FileName = julia_exe;
292 | p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized; // ProcessWindowStyle.Hidden;
293 | p.StartInfo.Arguments = commandlineargs;
294 |
295 | p.Start();
296 |
297 | Thread.Sleep(1000);
298 | Process.GetProcessById(p.Id);
299 | Connected = true;
300 | }
301 | catch (Exception e)
302 | {
303 | MessageBox.Show("Exception = " + e.ToString());
304 | p = null;
305 | }
306 |
307 | return p;
308 |
309 | }
310 |
311 | public void ShutdownJulia(Process p)
312 | {
313 | p.Kill();
314 | }
315 |
316 |
317 | public object CallJulia(string fn, object[] arguments, int JuliaInXL_timeout=30)
318 | {
319 |
320 | try
321 | {
322 | Version version = Assembly.GetExecutingAssembly().GetName().Version;
323 | JuliaVersion = version.Major + "." + version.Minor + "." + version.Build;
324 | JuliaProVersion = JuliaVersion + "." + version.Revision;
325 | RegistryKey localMachineRegistry
326 | = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
327 | Environment.Is64BitOperatingSystem
328 | ? RegistryView.Registry64
329 | : RegistryView.Registry32);
330 | RegistryKey key = localMachineRegistry.OpenSubKey("Software\\JuliaPro\\" + JuliaProVersion + "\\JuliaInXL");
331 |
332 | if ((registryValueExists("HKCU", "Software\\JuliaPro\\" + JuliaProVersion + "\\JuliaInXL", "Timeout") == true) && (int.TryParse((string)Registry.GetValue(@"HKEY_CURRENT_USER\Software\JuliaPro\" + JuliaProVersion + "\\JuliaInXL", "Timeout", ""), out JuliaInXL_timeout)) && (JuliaInXL_timeout > 0)) {}
333 | else if ((registryValueExists("HKLM", "Software\\JuliaPro\\" + JuliaProVersion + "\\JuliaInXL", "Timeout") == true) && (int.TryParse((string)key.GetValue("Timeout"), out JuliaInXL_timeout)) && (JuliaInXL_timeout > 0)) {}
334 | else if (Environment.GetEnvironmentVariable("JuliaInXL_timeout") != null && (int.TryParse(Environment.GetEnvironmentVariable("JuliaInXL_timeout"), out JuliaInXL_timeout)) && (JuliaInXL_timeout > 0)) {}
335 | else
336 | {
337 | JuliaInXL_timeout = 30;
338 | }
339 | JObject o = new JObject();
340 | o["cmd"] = fn;
341 | if (arguments.Length > 1 || arguments[0] != null)
342 | {
343 | JArray args = new JArray();
344 | for (int i = 0; i < arguments.Length; i++)
345 | {
346 |
347 | if (arguments[i] is object[])
348 | {
349 |
350 | object[] arg = (object[])arguments[i];
351 |
352 | JArray jarg = new JArray();
353 | for (int k = 0; k < arg.Length; k++)
354 | {
355 | jarg.Add(arg[k]);
356 | }
357 |
358 | args.Add(jarg);
359 |
360 | }
361 | else if (arguments[i] is object[,])
362 | {
363 | object[,] arg = (object[,])arguments[i];
364 |
365 | int cols = arg.GetUpperBound(1) + 1;
366 | int rows = arg.GetUpperBound(0) + 1;
367 |
368 | JArray jarg_cols = new JArray();
369 | for (int n = 0; n < cols; n++)
370 | {
371 | object[] arg_col = new object[rows];
372 | for (int m = 0; m < rows; m++)
373 | {
374 | arg_col[m] = arg[m, n];
375 | }
376 | jarg_cols.Add(new JArray(arg_col));
377 | }
378 |
379 | args.Add(jarg_cols);
380 |
381 | }
382 | else if (arguments[i] is Array)
383 | {
384 | //It seems JArray flattens its arguments by default
385 | //wrapping it in another JArray prevents flattening
386 | args.Add(new JArray(arguments[i]));
387 | }
388 | else
389 | {
390 | args.Add(arguments[i]);
391 | }
392 | }
393 | o["args"] = args;
394 | }
395 | client.SendFrame(o.ToString());
396 |
397 | // Receive the response from the client socket
398 | string m2="";
399 | if (Connected==true)
400 | {
401 | client.TryReceiveFrameString(TimeSpan.FromSeconds(JuliaInXL_timeout), out m2);
402 | }
403 | object retval = ProcessResult(m2);
404 | return retval;
405 | }
406 | catch
407 | {
408 | this.Reconnect();
409 | return "#ERR";
410 | }
411 | }
412 |
413 | /**
414 | * Convert the JSON string into native objects that can be returned to Excel
415 | * Arrays are supported only upto dimension 2
416 | **/
417 | private dynamic ProcessResult(string m2)
418 | {
419 | dynamic retval = "";
420 | if (m2 == null)
421 | {
422 | client.Close();
423 | client = context.CreateRequestSocket();
424 | client.Connect(endpoint);
425 | Connected = false;
426 | retval = "#ERR";
427 | }
428 | else
429 | {
430 | JObject result = JObject.Parse(m2);
431 | retval = result["data"];
432 |
433 | if (retval is JArray)
434 | {
435 | Object[] t = ((JArray)retval).ToObject