├── .gitattributes
├── .gitignore
├── AnalyzeInExcel.sln
├── AnalyzeInExcel
├── AnalyzeInExcel.csproj
├── AnalyzeInExcelAutoUpdater.xml
├── App.xaml
├── App.xaml.cs
├── ExcelHelper.cs
├── ExcelIconFromSvg.png
├── FodyWeavers.xml
├── FodyWeavers.xsd
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── ModelHelper.cs
├── OdcHelper.cs
├── Options.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── SQLBI MIT License.rtf
├── SplashLoading.xaml
├── SplashLoading.xaml.cs
├── TelemetryHelper.cs
├── analyzeinexcel.pbitool.json
├── app.config
├── banner-500x70.jpg
├── icon-2400px.ico
├── icon-2400px.png
└── packages.config
├── ExternalToolsInstaller
├── ExternalToolConfiguration.cs
├── ExternalToolsInstaller.Designer.cs
├── ExternalToolsInstaller.cs
├── ExternalToolsInstaller.csproj
├── ExternalToolsInstaller.resx
├── FodyWeavers.xml
├── FodyWeavers.xsd
├── Properties
│ └── AssemblyInfo.cs
├── app.config
├── icon-2400px.ico
└── packages.config
├── LICENSE
├── README.md
├── SetupAnalyzeInExcel
└── SetupAnalyzeInExcel.vdproj
├── azure-pipelines-1.yml
└── azure-pipelines.yml
/.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 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/AnalyzeInExcel.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30317.65
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AnalyzeInExcel", "AnalyzeInExcel\AnalyzeInExcel.csproj", "{E951EFB4-3CFF-4B1A-9313-27A5A3166B0F}"
7 | EndProject
8 | Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "SetupAnalyzeInExcel", "SetupAnalyzeInExcel\SetupAnalyzeInExcel.vdproj", "{E690AAF8-7226-44C6-824C-63D2EC27EC23}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExternalToolsInstaller", "ExternalToolsInstaller\ExternalToolsInstaller.csproj", "{91B65004-6E31-4F13-8523-5A4B188A7546}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {E951EFB4-3CFF-4B1A-9313-27A5A3166B0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {E951EFB4-3CFF-4B1A-9313-27A5A3166B0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {E951EFB4-3CFF-4B1A-9313-27A5A3166B0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {E951EFB4-3CFF-4B1A-9313-27A5A3166B0F}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {E690AAF8-7226-44C6-824C-63D2EC27EC23}.Debug|Any CPU.ActiveCfg = Debug
23 | {E690AAF8-7226-44C6-824C-63D2EC27EC23}.Release|Any CPU.ActiveCfg = Release
24 | {91B65004-6E31-4F13-8523-5A4B188A7546}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {91B65004-6E31-4F13-8523-5A4B188A7546}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {91B65004-6E31-4F13-8523-5A4B188A7546}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {91B65004-6E31-4F13-8523-5A4B188A7546}.Release|Any CPU.Build.0 = Release|Any CPU
28 | EndGlobalSection
29 | GlobalSection(SolutionProperties) = preSolution
30 | HideSolutionNode = FALSE
31 | EndGlobalSection
32 | GlobalSection(ExtensibilityGlobals) = postSolution
33 | SolutionGuid = {3797C216-8F8C-4A72-9C2E-BF91DBD4A6B2}
34 | EndGlobalSection
35 | EndGlobal
36 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/AnalyzeInExcel.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Debug
7 | AnyCPU
8 | {E951EFB4-3CFF-4B1A-9313-27A5A3166B0F}
9 | WinExe
10 | AnalyzeInExcel
11 | AnalyzeInExcel
12 | v4.5
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 | true
17 |
18 |
19 |
20 | publish\
21 | true
22 | Disk
23 | false
24 | Foreground
25 | 7
26 | Days
27 | false
28 | false
29 | true
30 | 0
31 | 1.0.0.%2a
32 | false
33 | false
34 | true
35 |
36 |
39 | .allowedextension
40 |
41 |
42 |
43 | AnyCPU
44 | true
45 | full
46 | false
47 | bin\Debug\
48 | DEBUG;TRACE
49 | prompt
50 | 4
51 | false
52 |
53 |
54 | AnyCPU
55 | none
56 | true
57 | bin\Release\
58 | TRACE
59 | prompt
60 | 4
61 | false
62 |
63 |
64 | icon-2400px.ico
65 |
66 |
67 |
68 | ..\packages\Autoupdater.NET.Official.1.6.3\lib\net45\AutoUpdater.NET.dll
69 |
70 |
71 | ..\packages\CommandLineParser.2.8.0\lib\net45\CommandLine.dll
72 | True
73 |
74 |
75 | ..\packages\Costura.Fody.3.3.3\lib\net40\Costura.dll
76 |
77 |
78 | ..\packages\Microsoft.ApplicationInsights.2.14.0\lib\net45\Microsoft.ApplicationInsights.dll
79 | True
80 |
81 |
82 | ..\packages\Microsoft.Office.Interop.Excel.15.0.4795.1000\lib\net20\Microsoft.Office.Interop.Excel.dll
83 | True
84 |
85 |
86 |
87 | ..\packages\System.Buffers.4.5.1\lib\netstandard1.1\System.Buffers.dll
88 | True
89 |
90 |
91 |
92 | ..\packages\System.Diagnostics.DiagnosticSource.4.7.1\lib\net45\System.Diagnostics.DiagnosticSource.dll
93 |
94 |
95 | ..\packages\System.Memory.4.5.4\lib\netstandard1.1\System.Memory.dll
96 | True
97 |
98 |
99 |
100 | ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll
101 |
102 |
103 |
104 | ..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | 4.0
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | MSBuild:Compile
121 | Designer
122 |
123 |
124 | SplashLoading.xaml
125 |
126 |
127 |
128 | MSBuild:Compile
129 | Designer
130 |
131 |
132 | App.xaml
133 | Code
134 |
135 |
136 |
137 | MainWindow.xaml
138 | Code
139 |
140 |
141 | Designer
142 | MSBuild:Compile
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | Code
151 |
152 |
153 | True
154 | True
155 | Resources.resx
156 |
157 |
158 | True
159 | Settings.settings
160 | True
161 |
162 |
163 | ResXFileCodeGenerator
164 | Resources.Designer.cs
165 |
166 |
167 |
168 |
169 |
170 | SettingsSingleFileGenerator
171 | Settings.Designer.cs
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | False
187 | .NET Framework 3.5 SP1
188 | false
189 |
190 |
191 |
192 |
193 |
194 |
195 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/AnalyzeInExcelAutoUpdater.xml:
--------------------------------------------------------------------------------
1 |
2 | -
3 | 1.1.3.0
4 | https://cdn.sqlbi.com/updates/AnalyzeInExcel-1.1.3.msi
5 | https://github.com/sql-bi/AnalyzeInExcel/releases/
6 | false
7 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using CommandLine;
2 | using System;
3 | using System.Data;
4 | using System.Linq;
5 | using System.Windows;
6 | using System.Diagnostics;
7 | using AutoUpdaterDotNET;
8 | using System.Windows.Input;
9 | using System.Threading.Tasks;
10 | using System.Collections;
11 |
12 | namespace AnalyzeInExcel
13 | {
14 | ///
15 | /// Interaction logic for App.xaml
16 | ///
17 | public partial class App : Application
18 | {
19 | public Options AppOptions;
20 | const string MSOLAP_DRIVER_URL = @"https://go.microsoft.com/fwlink/?LinkId=746283";
21 |
22 | const string EV_MSOLAP_NOTFOUND = "MSOLAP driver not found";
23 | const string EV_MSOLAP_SETUP = "Requested MSOLAP driver setup";
24 | const string EV_MODEL_NOT_AVAILABLE = "Model not available";
25 | const string EV_EXCEL_NOT_AVAILABLE = "Excel not available";
26 | const string EV_CONFIGURATION_INCOMPLETE = "Configuration incomplete";
27 | const string EV_RUNEXCEL = "Run Excel";
28 |
29 | public void CheckUpdates(bool synchronous = true)
30 | {
31 | AutoUpdater.HttpUserAgent = "AutoUpdater";
32 | AutoUpdater.ShowSkipButton = true;
33 | AutoUpdater.ShowRemindLaterButton = true;
34 | AutoUpdater.LetUserSelectRemindLater = true;
35 | AutoUpdater.Synchronous = synchronous;
36 | // The random number guarantees that the web client cache is not used (it is applied often even though internally the policy is disabled)
37 | AutoUpdater.Start($@"https://cdn.sqlbi.com/updates/AnalyzeInExcelAutoUpdater.xml?random={new Random().Next()}");
38 | }
39 |
40 | ///
41 | /// THe user requested an options window instead of running the default action
42 | ///
43 | public bool OptionsRequested { get; private set; }
44 |
45 | ///
46 | /// Check conditions to open Options window instead of directly opening Excel
47 | ///
48 | protected void InitializeOptionRequested()
49 | {
50 | // Pressing CTRL (left or right) when the external tool is launched activates the option window
51 | OptionsRequested = System.Windows.Input.Keyboard.IsKeyDown(Key.LeftCtrl) || System.Windows.Input.Keyboard.IsKeyDown(Key.RightCtrl);
52 | }
53 |
54 | public MessageBoxResult ShowMessage( string message )
55 | {
56 | return MessageBox.Show(message, "Analyze in Excel for Power BI Desktop");
57 | }
58 | public MessageBoxResult ShowMessageQuestion(string message)
59 | {
60 | return MessageBox.Show(message, "Analyze in Excel for Power BI Desktop",MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);
61 | }
62 |
63 | protected override void OnStartup(StartupEventArgs e)
64 | {
65 |
66 | #if DEBUG
67 | System.Diagnostics.Debugger.Launch();
68 | #endif
69 |
70 | // Store request to access options
71 | InitializeOptionRequested();
72 |
73 | // Read configuration
74 | var result = Parser.Default.ParseArguments(e.Args)
75 | .WithNotParsed(errors => ShowMessage("Invalid configuration, check the pbitool.json file\n" + String.Join(";", from err in errors select err.ToString())))
76 | .WithParsed(options => AppOptions = options);
77 |
78 | bool disableTelemetry = (AppOptions.Telemetry == false);
79 | TelemetryHelper th = new TelemetryHelper(disableTelemetry);
80 |
81 | try
82 | {
83 | string serverName = ((App)Application.Current).AppOptions?.Server;
84 | string databaseName = ((App)Application.Current).AppOptions?.Database;
85 | bool goodMsOlapDriver = ModelHelper.HasMsOlapDriver();
86 | if (!goodMsOlapDriver)
87 | {
88 | th.TrackEvent(EV_MSOLAP_NOTFOUND);
89 | if (ShowMessageQuestion($"Excel needs a component called MSOLAP driver to connect to Power BI. The MSOLAP driver might be missing or not updated on this device. Therefore, Excel might not connect to Power BI. You can install the updated Microsoft MSOLAP driver from this link: {MSOLAP_DRIVER_URL} \n\nClick YES if you want to download the updated MSOLAP driver and install it.\nClick NO to continue without any update.") == MessageBoxResult.Yes)
90 | {
91 | try
92 | {
93 | th.TrackEvent(EV_MSOLAP_SETUP);
94 | UpdateMsOlapDriver();
95 | }
96 | catch (Exception ex)
97 | {
98 | // Send any exception to Telemetry
99 | th.TrackException(ex);
100 | ShowMessage($"Error running MSOLAP update: {ex.Message}");
101 | }
102 | }
103 | }
104 | // We use the default "Model" string if the MSOLAP driver is not available - if this happens, the previous warning helps understanding possible issues
105 | string cubeName = goodMsOlapDriver ? ModelHelper.GetModelName(serverName, databaseName, th) : "Model";
106 | if (serverName != null && databaseName != null)
107 | {
108 | try
109 | {
110 | if (string.IsNullOrEmpty(cubeName))
111 | {
112 | ShowMessage("Power BI has an empty model or it is connected to an unkonwn external dataset. You cannot connect Excel.");
113 | th.TrackEvent(EV_MODEL_NOT_AVAILABLE);
114 | }
115 | else if (ExcelHelper.IsExcelAvailable())
116 | {
117 | // TODO: Manage options requested
118 | if (OptionsRequested)
119 | {
120 | // TODO request action / configuration to users
121 | }
122 |
123 | var splashScreen = new SplashLoading();
124 | try
125 | {
126 | this.MainWindow = splashScreen;
127 | splashScreen.Show();
128 |
129 | bool excelStarted = ExcelHelper.CreateInstanceWithPivotTableViaInterop(serverName, databaseName, cubeName, out string excelVersion, (ex) => th.TrackException(ex));
130 | if (excelStarted)
131 | {
132 | th.TrackEvent(EV_RUNEXCEL, new (string propertyName, string propertyValue)[] { ("RunType", "Interop"), ("ExcelVersion", excelVersion) });
133 | }
134 | else {
135 | excelStarted = ExcelHelper.CreateInstanceWithPivotTableViaDispatch(serverName, databaseName, cubeName, out excelVersion, (ex) => th.TrackException(ex));
136 | if (excelStarted)
137 | {
138 | th.TrackEvent(EV_RUNEXCEL, new (string propertyName, string propertyValue)[] { ("RunType", "Dispatch"), ("ExcelVersion", excelVersion) });
139 | }
140 | else
141 | {
142 | RunExcelProcess(serverName, databaseName, cubeName);
143 | th.TrackEvent(EV_RUNEXCEL, new (string propertyName, string propertyValue)[] { ("RunType", "ODC File") });
144 | }
145 | }
146 | }
147 | finally
148 | {
149 | splashScreen.Close();
150 | }
151 | }
152 | else
153 | {
154 | ShowMessage("Excel is not available. Please check whether Excel is correctly installed.");
155 | th.TrackEvent(EV_EXCEL_NOT_AVAILABLE);
156 | }
157 | th.Flush();
158 |
159 | // Check updates synchronously when Excel starts, no wait for Excel
160 | CheckUpdates(true);
161 | this.Shutdown(0);
162 | }
163 | catch (Exception ex)
164 | {
165 | th.TrackException(ex);
166 | th.Flush();
167 | ShowMessage("Error launching Excel: " + ex.Message);
168 | }
169 | }
170 | else
171 | {
172 | th.TrackEvent(EV_CONFIGURATION_INCOMPLETE);
173 | th.Flush();
174 | }
175 |
176 | // Check updates asynchronously when there is an error, while displaying the diagnostic message
177 | CheckUpdates(false);
178 |
179 | OpenDiagnosticWindow(serverName, databaseName);
180 | }
181 | catch (Exception ex)
182 | {
183 | // Send any exception to Telemetry
184 | th.TrackException(ex);
185 | th.Flush();
186 | throw;
187 | }
188 |
189 | void UpdateMsOlapDriver()
190 | {
191 | var p = new Process
192 | {
193 | StartInfo = new ProcessStartInfo(MSOLAP_DRIVER_URL)
194 | {
195 | UseShellExecute = true
196 | }
197 | };
198 | p.Start();
199 | }
200 | }
201 | private void OpenDiagnosticWindow(string serverName, string databaseName)
202 | {
203 | //// start application window
204 | MainWindow mw = new MainWindow();
205 | this.MainWindow = mw;
206 | mw.diagnosticInfo.Content = $@"Current configuration
207 | Server={serverName ?? "(blank)"}
208 | Database={databaseName ?? "(blank)"}
209 |
210 | Check that the file
211 | {Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86)}\Microsoft Shared\Power BI Desktop\External Tools\analyzeinexcel.pbitool.json
212 | includes the following argument:
213 | ""arguments"": ""--telemetry --server =\""%server%\"" --database=\""%database%\""
214 | ";
215 | mw.Show();
216 | }
217 |
218 | private void RunExcelProcess(string serverName, string databaseName, string cubeName)
219 | {
220 | // Create ODC file
221 | var fileName = OdcHelper.CreateOdcFile(serverName, databaseName, cubeName);
222 |
223 | // Open ODC file
224 | var p = new Process
225 | {
226 | StartInfo = new ProcessStartInfo(fileName)
227 | {
228 | UseShellExecute = true
229 | }
230 | };
231 | p.Start();
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/ExcelHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Windows;
4 | using System.Windows.Threading;
5 | using System.Runtime.InteropServices;
6 | using Excel = Microsoft.Office.Interop.Excel;
7 | using System.Linq;
8 |
9 | namespace AnalyzeInExcel
10 | {
11 | public class ExcelHelper
12 | {
13 | [DllImport("user32.dll")]
14 | [return: MarshalAs(UnmanagedType.Bool)]
15 | static extern bool SetForegroundWindow(IntPtr hWnd);
16 |
17 | ///
18 | /// Check whether Excel is installed
19 | ///
20 | /// true if Excel is installed
21 | public static bool IsExcelAvailable()
22 | {
23 | var type = Type.GetTypeFromProgID("Excel.Application");
24 | return (type != null);
25 | }
26 |
27 | public static string GetSafeConnectionName( string serverName, string databaseName, string cubeName )
28 | {
29 | string connectionName = $"AnalyzeInExcel [{ serverName }].[{ databaseName }].[{ cubeName }]";
30 | connectionName = System.IO.Path.GetInvalidFileNameChars().Aggregate(connectionName, (current, c) => current.Replace(c.ToString(), "_"));
31 | return connectionName;
32 | }
33 |
34 | ///
35 | /// Create a new Excel file with a PivotTable connected to the server/database/cube provided
36 | ///
37 | ///
38 | ///
39 | ///
40 | /// Action that processes any exception - the function will return false, this is a way to manage logging/telemetry
41 | /// true if the operation completes without errors, otherwise false (any exception is removed and the function returns false)
42 | public static bool CreateInstanceWithPivotTableViaInterop(string serverName, string databaseName, string cubeName, out string excelVersion, Action exceptionAction )
43 | {
44 | var connectionString = ModelHelper.GetOleDbConnectionString(serverName, databaseName);
45 | var connectionName = GetSafeConnectionName( serverName, databaseName, cubeName );
46 | var commandText = cubeName;
47 | var pivotTableName = $"AnalyzeInExcelPivotTable";
48 |
49 | try
50 | {
51 | Excel.Application app = new Excel.Application();
52 |
53 | // Return Excel Version for diagnostics
54 | excelVersion = app.Version;
55 |
56 | // Create a new workbook
57 | var workbook = app.Workbooks.Add();
58 |
59 | // Create the connection
60 | var workbookConnection = workbook.Connections.Add2(
61 | Name: connectionName,
62 | Description: "",
63 | ConnectionString: $"OLEDB;{ connectionString }",
64 | CommandText: commandText,
65 | lCmdtype: 1
66 | );
67 | workbookConnection.OLEDBConnection.MaintainConnection = true;
68 |
69 | // Create the pivotcache
70 | var pivotCache = workbook.PivotCaches().Create(
71 | SourceType: Excel.XlPivotTableSourceType.xlExternal,
72 | SourceData: workbookConnection
73 | );
74 | pivotCache.RefreshOnFileOpen = false;
75 |
76 | // Get the active worksheet
77 | var worksheet = workbook.ActiveSheet;
78 |
79 | // Create the PivotTable
80 | var pivotTable = pivotCache.CreatePivotTable(
81 | TableDestination: worksheet.Range["A1"],
82 | TableName: pivotTableName,
83 | ReadData: false
84 | );
85 |
86 | // Show Excel
87 | app.Visible = true;
88 |
89 | // Set Excel window as foreground window
90 | var hwnd = app.Hwnd;
91 | SetForegroundWindow((IntPtr)hwnd); // Note Hwnd is declared as int
92 | }
93 | catch (Exception ex)
94 | {
95 | // In case of error simply fails the request and forward the exception
96 | exceptionAction?.Invoke(ex);
97 | excelVersion = "";
98 | return false;
99 | }
100 | return true;
101 | }
102 | public static bool CreateInstanceWithPivotTableViaDispatch(string serverName, string databaseName, string cubeName, out string excelVersion, Action exceptionAction)
103 | {
104 | string connectionString = ModelHelper.GetOleDbConnectionString(serverName, databaseName);
105 | string connectionName = GetSafeConnectionName(serverName, databaseName, cubeName);
106 | string commandText = cubeName;
107 | string pivotTableName = $"AnalyzeInExcelPivotTable";
108 | string foundExcelVersion = null;
109 |
110 | try
111 | {
112 | var type = Type.GetTypeFromProgID("Excel.Application");
113 | dynamic app = Activator.CreateInstance(type);
114 |
115 | // Return Excel Version for diagnostics
116 | excelVersion = app.Version;
117 | foundExcelVersion = excelVersion;
118 |
119 | // Create a new workbook
120 | dynamic workbook = app.Workbooks.Add();
121 |
122 | // Create the connection
123 | dynamic workbookConnection = workbook.Connections.Add2(
124 | Name: connectionName,
125 | Description: "",
126 | ConnectionString: $"OLEDB;{ connectionString }",
127 | CommandText: commandText,
128 | lCmdtype: 1
129 | );
130 | workbookConnection.OLEDBConnection.MaintainConnection = true;
131 |
132 | // Create the pivotcache
133 | dynamic pivotCache = workbook.PivotCaches().Create(
134 | SourceType: Excel.XlPivotTableSourceType.xlExternal,
135 | SourceData: workbookConnection
136 | );
137 | pivotCache.RefreshOnFileOpen = false;
138 |
139 | // Get the active worksheet
140 | dynamic worksheet = workbook.ActiveSheet;
141 |
142 | // Create the PivotTable
143 | dynamic pivotTable = pivotCache.CreatePivotTable(
144 | TableDestination: worksheet.Range["A1"],
145 | TableName: pivotTableName,
146 | ReadData: false
147 | );
148 |
149 | // Show Excel
150 | app.Visible = true;
151 |
152 | // Set Excel window as foreground window
153 | long hwnd = app.Hwnd;
154 | SetForegroundWindow((IntPtr)hwnd); // Note Hwnd is declared as int
155 | }
156 | catch (Exception ex)
157 | {
158 | // In case of error simply fails the request and forward the exception
159 | exceptionAction?.Invoke(ex);
160 | excelVersion = foundExcelVersion ?? "";
161 | return false;
162 | }
163 | return true;
164 | }
165 |
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/ExcelIconFromSvg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sql-bi/AnalyzeInExcel/846180e8d28a1b2ec1d76636f1be573e72794bbe/AnalyzeInExcel/ExcelIconFromSvg.png
--------------------------------------------------------------------------------
/AnalyzeInExcel/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/FodyWeavers.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks
13 |
14 |
15 |
16 |
17 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.
18 |
19 |
20 |
21 |
22 | A list of unmanaged 32 bit assembly names to include, delimited with line breaks.
23 |
24 |
25 |
26 |
27 | A list of unmanaged 64 bit assembly names to include, delimited with line breaks.
28 |
29 |
30 |
31 |
32 | The order of preloaded assemblies, delimited with line breaks.
33 |
34 |
35 |
36 |
37 |
38 | This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.
39 |
40 |
41 |
42 |
43 | Controls if .pdbs for reference assemblies are also embedded.
44 |
45 |
46 |
47 |
48 | Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.
49 |
50 |
51 |
52 |
53 | As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.
54 |
55 |
56 |
57 |
58 | Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.
59 |
60 |
61 |
62 |
63 | Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.
64 |
65 |
66 |
67 |
68 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |
69 |
70 |
71 |
72 |
73 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.
74 |
75 |
76 |
77 |
78 | A list of unmanaged 32 bit assembly names to include, delimited with |.
79 |
80 |
81 |
82 |
83 | A list of unmanaged 64 bit assembly names to include, delimited with |.
84 |
85 |
86 |
87 |
88 | The order of preloaded assemblies, delimited with |.
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
97 |
98 |
99 |
100 |
101 | A comma-separated list of error codes that can be safely ignored in assembly verification.
102 |
103 |
104 |
105 |
106 | 'false' to turn off automatic generation of the XML Schema file.
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Navigation;
13 | using System.Windows.Shapes;
14 |
15 | namespace AnalyzeInExcel
16 | {
17 | ///
18 | /// Interaction logic for MainWindow.xaml
19 | ///
20 | public partial class MainWindow : Window
21 | {
22 | public MainWindow()
23 | {
24 | InitializeComponent();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/ModelHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.OleDb;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace AnalyzeInExcel
9 | {
10 | public class ModelHelper
11 | {
12 | const string MSOLAP_DRIVER_NAME = "MSOLAP"; // We get the latest available. We currently don't enforce MSOLAP.8
13 |
14 | internal enum AsInstanceType
15 | {
16 | Other,
17 | AsAzure,
18 | PbiDedicated,
19 | PbiPremium,
20 | PbiDataset
21 | }
22 |
23 | private static bool IsProtocolSchemeInstance(string dataSourceUri, string protocolScheme)
24 | {
25 | return dataSourceUri?.StartsWith(protocolScheme, StringComparison.InvariantCultureIgnoreCase) ?? false;
26 | }
27 | internal static AsInstanceType GetAsInstanceType(string dataSourceUri)
28 | {
29 | if (IsProtocolSchemeInstance(dataSourceUri, "asazure://"))
30 | {
31 | return AsInstanceType.AsAzure;
32 | }
33 | if (IsProtocolSchemeInstance(dataSourceUri, "pbidedicated://"))
34 | {
35 | return AsInstanceType.PbiDedicated;
36 | }
37 | if (IsProtocolSchemeInstance(dataSourceUri, "powerbi://"))
38 | {
39 | return AsInstanceType.PbiPremium;
40 | }
41 | if (IsProtocolSchemeInstance(dataSourceUri, "pbiazure://"))
42 | {
43 | return AsInstanceType.PbiDataset;
44 | }
45 | return AsInstanceType.Other;
46 | }
47 |
48 | ///
49 | /// Check whether the machine has the MSOLAP driver installed
50 | /// The driver could be available in 32-bit and not in 64-bit
51 | /// This would work in Excel, but it is better to try get the driver in that case
52 | ///
53 | ///
54 | public static bool HasMsOlapDriver()
55 | {
56 | const string SOURCES_NAME = "SOURCES_NAME";
57 |
58 | var oleEnum = new OleDbEnumerator();
59 | var elems = oleEnum.GetElements();
60 | if (elems != null && elems.Rows != null)
61 | foreach (System.Data.DataRow row in elems.Rows)
62 | if (!row.IsNull(SOURCES_NAME) && row[SOURCES_NAME] is string)
63 | if (row[SOURCES_NAME].ToString() == MSOLAP_DRIVER_NAME )
64 | return true;
65 | return false;
66 | }
67 |
68 | ///
69 | /// Returns the OLE DB connection string based on serverName and databaseName
70 | ///
71 | ///
72 | ///
73 | /// Connection string for OLE DB
74 | public static string GetOleDbConnectionString( string serverName, string databaseName )
75 | {
76 | // Choose the proper connection string
77 | string connectionString;
78 | switch (GetAsInstanceType(serverName))
79 | {
80 | case AsInstanceType.PbiDataset: // Integrated Security=ClaimsToken;
81 | connectionString = $"Provider={MSOLAP_DRIVER_NAME};Persist Security Info=True;Initial Catalog=sobe_wowvirtualserver-{databaseName};Data Source={serverName};MDX Compatibility=1;Safety Options=2;MDX Missing Member Mode=Error;Identity Provider=https://login.microsoftonline.com/common, https://analysis.windows.net/powerbi/api, 929d0ec0-7a41-4b1e-bc7c-b754a28bddcc;Update Isolation Level=2";
82 | break;
83 | case AsInstanceType.PbiDedicated:
84 | case AsInstanceType.PbiPremium:
85 | case AsInstanceType.AsAzure:
86 | connectionString = $"Provider={MSOLAP_DRIVER_NAME};Persist Security Info=True;Data Source={serverName};Update Isolation Level=2;Initial Catalog={databaseName}";
87 | break;
88 | case AsInstanceType.Other:
89 | default:
90 | connectionString = $"Provider={MSOLAP_DRIVER_NAME};Integrated Security=SSPI;Persist Security Info=True;Data Source={serverName};Update Isolation Level=2;Initial Catalog={databaseName}";
91 | break;
92 | }
93 | return connectionString;
94 | }
95 |
96 | ///
97 | /// Check whether the connection has a data model
98 | ///
99 | /// Server name
100 | /// Database name
101 | /// true it the connection has a data model
102 | public static string GetModelName(string serverName, string databaseName, TelemetryHelper th)
103 | {
104 | string result = null;
105 | string connectionString = GetOleDbConnectionString(serverName, databaseName);
106 | try
107 | {
108 | using (OleDbConnection connection = new OleDbConnection(connectionString))
109 | {
110 | using (OleDbCommand command = new OleDbCommand("select CUBE_NAME from $SYSTEM.MDSCHEMA_CUBES", connection))
111 | {
112 | connection.Open();
113 | using (OleDbDataReader reader = command.ExecuteReader())
114 | {
115 | if (reader.Read())
116 | {
117 | result = reader.GetString(0);
118 | }
119 | reader.Close();
120 | }
121 | }
122 | }
123 | }
124 | catch (System.Data.Common.DbException ex)
125 | {
126 | // Ignore DbException and return a null model name
127 |
128 | // Send exception to Telemetry for further investigation
129 | th.TrackException(ex);
130 | th.Flush();
131 | }
132 | return result;
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/OdcHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Windows;
4 |
5 | namespace AnalyzeInExcel
6 | {
7 | public static class OdcHelper
8 | {
9 | public static string CreateOdcFile(string datasource, string database, string cube)
10 | {
11 | string oledbConnectionString = ModelHelper.GetOleDbConnectionString(datasource, database);
12 | string odcHeader = @"
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Analyze in Excel for Power BI Desktop - ODC
23 |
26 | mtbsql608v-dev_mssqlinst01 PRS Model
27 |
28 | ";
29 | var odcBody = @"
32 |
33 | {0}
34 | Cube
35 | {1}
36 |
37 |
38 | ";
39 |
40 | var odcFooter = @"
41 |
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 |
117 |
118 |
119 |
120 |
121 |
122 | ";
123 |
124 | var odcPath = GetOdcFilePath();
125 | File.WriteAllText(odcPath, odcHeader + string.Format(odcBody, oledbConnectionString, cube) + odcFooter);
126 | return odcPath;
127 | }
128 |
129 | private static string GetOdcFilePath()
130 | {
131 | const string ODC_FILENAME = "AnalyzeInExcel.odc";
132 | const string MY_DATA_SOURCES = "My Data Sources"; // This is not localized - TODO find the localized version of this name
133 |
134 | var myDocs = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments, Environment.SpecialFolderOption.Create);
135 | var dsPath = Path.Combine(myDocs, MY_DATA_SOURCES, ODC_FILENAME);
136 |
137 | try
138 | {
139 | // ensure that the folder exists
140 | Directory.CreateDirectory(Path.GetDirectoryName(dsPath));
141 | }
142 | catch (Exception)
143 | {
144 | // If the folder is not available or accessible, try the file in MyDocuments
145 | dsPath = Path.Combine(
146 | Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
147 | ODC_FILENAME);
148 | }
149 |
150 | try
151 | {
152 | using (StreamWriter w = File.AppendText(dsPath))
153 | {
154 | // If the file can be opened this way, it should be writable
155 | }
156 | }
157 | catch ( Exception )
158 | {
159 | // If the previous attempt fails, the last resort is creating the file in the TEMP directory
160 | dsPath = Path.GetTempFileName().Replace(".tmp", "AnalyzeInExcel.odc");
161 | }
162 | return dsPath;
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/Options.cs:
--------------------------------------------------------------------------------
1 | using CommandLine;
2 |
3 | namespace AnalyzeInExcel
4 | {
5 | public class Options
6 | {
7 | [Option('d', "database", HelpText = "Database name")]
8 | public string Database { get; set; }
9 |
10 | [Option('s', "server", HelpText = "Server name")]
11 | public string Server { get; set; }
12 |
13 | [Option('n', "telemetry", HelpText = "Enable Telemetry")]
14 | public bool Telemetry { get; set; }
15 |
16 | //[Option('x', "experiment", HelpText = "Experiment feature")]
17 | //public bool Experiment { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 | [assembly: AssemblyTitle("AnalyzeInExcel")]
11 | [assembly: AssemblyDescription("Analyze in Excel for Power BI Desktop")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("SQLBI")]
14 | [assembly: AssemblyProduct("Analyze in Excel for Power BI Desktop")]
15 | [assembly: AssemblyCopyright("")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | //In order to begin building localizable applications, set
25 | //CultureYouAreCodingWith in your .csproj file
26 | //inside a . For example, if you are using US english
27 | //in your source files, set the to en-US. Then uncomment
28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
29 | //the line below to match the UICulture setting in the project file.
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
36 | //(used if a resource is not found in the page,
37 | // or application resource dictionaries)
38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
39 | //(used if a resource is not found in the page,
40 | // app, or any theme specific resource dictionaries)
41 | )]
42 |
43 |
44 | // Version information for an assembly consists of the following four values:
45 | //
46 | // Major Version
47 | // Minor Version
48 | // Build Number
49 | // Revision
50 | //
51 | // You can specify all the values or you can default the Build and Revision Numbers
52 | // by using the '*' as shown below:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.1.3.0")]
55 | [assembly: AssemblyFileVersion("1.1.3.0")]
56 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AnalyzeInExcel.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AnalyzeInExcel.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace AnalyzeInExcel.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/SQLBI MIT License.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31506\stshfloch31506\stshfhich31506\stshfbi31507\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
2 | {\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
3 | {\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}
4 | {\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
5 | {\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
6 | {\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f45\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f46\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
7 | {\f48\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f49\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f50\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f51\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
8 | {\f52\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f53\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f415\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f416\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}
9 | {\f418\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f419\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f420\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f421\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}
10 | {\f422\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f423\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
11 | {\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
12 | {\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
13 | {\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
14 | {\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
15 | {\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
16 | {\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}
17 | {\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}
18 | {\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
19 | {\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
20 | {\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
21 | {\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
22 | {\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
23 | {\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
24 | {\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
25 | {\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
26 | {\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
27 | {\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
28 | {\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
29 | {\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
30 | {\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
31 | {\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}
32 | {\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;
33 | \red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue0;\red0\green0\blue0;}{\*\defchp \f31506\fs22 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1
34 | \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025
35 | \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
36 | \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1
37 | \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}}{\*\pgptbl {\pgp
38 | \ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid291007\rsid2439811\rsid4029700\rsid5055490\rsid8280818\rsid11093112\rsid11208125\rsid12472459\rsid14180778\rsid15823986}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0
39 | \mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Marco Russo}{\operator Marco Russo}{\creatim\yr2020\mo8\dy3\hr16\min53}{\revtim\yr2020\mo8\dy3\hr16\min55}{\version1}{\edmins2}{\nofpages1}{\nofwords157}{\nofchars901}{\nofcharsws1056}{\vern5}}
40 | {\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect
41 | \widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen
42 | \expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1440\dgvorigin1440\dghshow1\dgvshow1
43 | \jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\viewnobound1\snaptogridincell\allowfieldendsel
44 | \wrppunct\asianbrkrule\rsidroot8280818\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
45 | {\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang
46 | {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang
47 | {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}
48 | \pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8280818 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {
49 | \rtlch\fcs1 \ab\af31507 \ltrch\fcs0 \b\insrsid8280818\charrsid8280818 MIT License
50 | \par }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 Copyright (c) 2020 SQLBI
51 | \par Permission is hereby granted, free of charge, to any person obtaining a copy}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818
52 | of this software and associated documentation files (the "Software"), to deal}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818
53 | in the Software without restriction, including without limitation the rights}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell}{
54 | \rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 copies of the Software, and to permit persons to whom the Software is}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507
55 | \ltrch\fcs0 \insrsid8280818 furnished to do so, subject to the following conditions:
56 | \par The above copyright notice and this permission notice shall be included in all}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 copies or substantial portions of the Software.
57 | \par THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,}{
58 | \rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507
59 | \ltrch\fcs0 \insrsid8280818 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 LIABILITY, WHETHER IN AN ACTION OF C
60 | ONTRACT, TORT OR OTHERWISE, ARISING FROM,}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE}{\rtlch\fcs1 \af31507
61 | \ltrch\fcs0 \insrsid8280818 }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid8280818 SOFTWARE.}{\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid11208125
62 | \par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
63 | 9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
64 | 5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
65 | b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
66 | 0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
67 | a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
68 | c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
69 | 0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
70 | a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
71 | 6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
72 | 4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
73 | 4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100b6f4679893070000c9200000160000007468656d652f7468656d652f
74 | 7468656d65312e786d6cec59cd8b1bc915bf07f23f347d97f5d5ad8fc1f2a24fcfda33b6b164873dd648a5eef2547789aad28cc56208de532e81c026e49085bd
75 | ed21842cecc22eb9e48f31d8249b3f22afaa5bdd5552c99e191c3061463074977eefd5afde7bf5de53d5ddcf5e26d4bbc05c1096f6fcfa9d9aefe174ce16248d
76 | 7afeb3d9a4d2f13d2151ba4094a5b8e76fb0f03fbbf7eb5fdd454732c609f6403e1547a8e7c752ae8eaa5531876124eeb0154ee1bb25e30992f0caa3ea82a34b
77 | d09bd06aa3566b55134452df4b51026a1f2f97648ebd9952e9dfdb2a1f53784da5500373caa74a35b6243476715e5708b11143cabd0b447b3eccb3609733fc52
78 | fa1e4542c2173dbfa6fffceabdbb5574940b517940d6909be8bf5c2e17589c37f49c3c3a2b260d823068f50bfd1a40e53e6edc1eb7c6ad429f06a0f91c569a71
79 | b175b61bc320c71aa0ecd1a17bd41e35eb16ded0dfdce3dc0fd5c7c26b50a63fd8c34f2643b0a285d7a00c1feee1c3417730b2f56b50866fede1dbb5fe28685b
80 | fa3528a6243ddf43d7c25673b85d6d0159327aec8477c360d26ee4ca4b144443115d6a8a254be5a1584bd00bc6270050408a24493db959e1259a43140f112567
81 | 9c7827248a21f056286502866b8ddaa4d684ffea13e827ed5174849121ad780113b137a4f87862cec94af6fc07a0d537206f7ffef9cdeb1fdfbcfee9cd575fbd
82 | 79fdf77c6eadca923b466964cafdf2dd1ffef3cd6fbd7ffff0ed2f5fff319b7a172f4cfcbbbffdeedd3ffef93ef5b0e2d2146ffff4fdbb1fbf7ffbe7dfffebaf
83 | 5f3bb4f7393a33e1339260e13dc297de5396c0021dfcf119bf9ec42c46c494e8a791402952b338f48f656ca11f6d10450edc00db767cce21d5b880f7d72f2cc2
84 | d398af2571687c182716f094313a60dc6985876a2ec3ccb3751ab927e76b13f714a10bd7dc43945a5e1eaf579063894be530c616cd2714a5124538c5d253dfb1
85 | 738c1dabfb8210cbaea764ce99604be97d41bc01224e93ccc899154da5d03149c02f1b1741f0b7659bd3e7de8051d7aa47f8c246c2de40d4417e86a965c6fb68
86 | 2d51e252394309350d7e8264ec2239ddf0b9891b0b099e8e3065de78818570c93ce6b05ec3e90f21cdb8dd7e4a37898de4929cbb749e20c64ce4889d0f6394ac
87 | 5cd829496313fbb938871045de13265df05366ef10f50e7e40e941773f27d872f787b3c133c8b026a53240d4376beef0e57dccacf89d6ee8126157aae9f3c44a
88 | b17d4e9cd131584756689f604cd1255a60ec3dfbdcc160c05696cd4bd20f62c82ac7d815580f901dabea3dc5027a25d5dcece7c91322ac909de2881de073bad9
89 | 493c1b9426881fd2fc08bc6eda7c0ca52e7105c0633a3f37818f08f480102f4ea33c16a0c308ee835a9fc4c82a60ea5db8e375c32dff5d658fc1be7c61d1b8c2
90 | be04197c6d1948eca6cc7b6d3343d49aa00c9819822ec3956e41c4727f29a28aab165b3be596f6a62ddd00dd91d5f42424fd6007b4d3fb84ffbbde073a8cb77f
91 | f9c6b10f3e4ebfe3566c25ab6b763a8792c9f14e7f7308b7dbd50c195f904fbfa919a175fa04431dd9cf58b73dcd6d4fe3ffdff73487f6f36d2773a8dfb8ed64
92 | 7ce8306e3b99fc70e5e3743265f3027d8d3af0c80e7af4b14f72f0d46749289dca0dc527421ffc08f83db398c0a092d3279eb838055cc5f0a8ca1c4c60e1228e
93 | b48cc799fc0d91f134462b381daafb4a492472d591f0564cc0a1911e76ea5678ba4e4ed9223becacd7d5c16656590592e5782d2cc6e1a04a66e856bb3cc02bd4
94 | 6bb6913e68dd1250b2d721614c6693683a48b4b783ca48fa58178ce620a157f65158741d2c3a4afdd6557b2c805ae115f8c1edc1cff49e1f06200242701e07cd
95 | f942f92973f5d6bbda991fd3d3878c69450034d8db08283ddd555c0f2e4fad2e0bb52b78da2261849b4d425b46377822869fc17974aad1abd0b8aeafbba54b2d
96 | 7aca147a3e08ad9246bbf33e1637f535c8ede6069a9a9982a6de65cf6f35430899395af5fc251c1ac363b282d811ea3717a211dcbccc25cf36fc4d32cb8a0b39
97 | 4222ce0cae934e960d122231f728497abe5a7ee1069aea1ca2b9d51b90103e59725d482b9f1a3970baed64bc5ce2b934dd6e8c284b67af90e1b35ce1fc568bdf
98 | 1cac24d91adc3d8d1797de195df3a708422c6cd795011744c0dd413db3e682c0655891c8caf8db294c79da356fa3740c65e388ae62945714339967709dca0b3a
99 | faadb081f196af190c6a98242f8467912ab0a651ad6a5a548d8cc3c1aafb6121653923699635d3ca2aaa6abab39835c3b60cecd8f26645de60b53531e434b3c2
100 | 67a97b37e576b7b96ea74f28aa0418bcb09fa3ea5ea12018d4cac92c6a8af17e1a56393b1fb56bc776811fa07695226164fdd656ed8edd8a1ae19c0e066f54f9
101 | 416e376a6168b9ed2bb5a5f5adb979b1cdce5e40f2184197bba6526857c2c92e47d0104d754f92a50dd8222f65be35e0c95b73d2f3bfac85fd60d80887955a27
102 | 1c57826650ab74c27eb3d20fc3667d1cd66ba341e31514161927f530bbb19fc00506dde4f7f67a7cefee3ed9ded1dc99b3a4caf4dd7c5513d777f7f5c6e1bb7b
103 | 8f40d2f9b2d598749bdd41abd26df627956034e854bac3d6a0326a0ddba3c9681876ba9357be77a1c141bf390c5ae34ea5551f0e2b41aba6e877ba9576d068f4
104 | 8376bf330efaaff23606569ea58fdc16605ecdebde7f010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d65
105 | 2f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d36
106 | 3f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e
107 | 3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d985
108 | 0528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000000000
109 | 0000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000
110 | 000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019020000
111 | 7468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100b6f4679893070000c92000001600000000000000
112 | 000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027000000
113 | 000000000000000000009d0a00007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000980b00000000}
114 | {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
115 | 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
116 | 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
117 | 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
118 | {\*\latentstyles\lsdstimax376\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;
119 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
120 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;
121 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1;
122 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5;
123 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9;
124 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;
125 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;
126 | \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent;
127 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer;
128 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures;
129 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference;
130 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text;
131 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List;
132 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3;
133 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3;
134 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3;
135 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing;
136 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent;
137 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4;
138 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;
139 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading;
140 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3;
141 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
142 | \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature;
143 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym;
144 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition;
145 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter;
146 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;
147 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1;
148 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2;
149 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2;
150 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3;
151 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2;
152 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6;
153 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2;
154 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6;
155 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2;
156 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional;
157 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2;
158 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme;\lsdsemihidden1 \lsdlocked0 Placeholder Text;
159 | \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;
160 | \lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;
161 | \lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;
162 | \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;
163 | \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;
164 | \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;
165 | \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;
166 | \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;
167 | \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;
168 | \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;
169 | \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;
170 | \lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;
171 | \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;
172 | \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;
173 | \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;
174 | \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
175 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
176 | \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6;
177 | \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
178 | \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
179 | \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
180 | \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography;
181 | \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4;
182 | \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4;
183 | \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1;
184 | \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1;
185 | \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2;
186 | \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2;
187 | \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3;
188 | \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4;
189 | \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4;
190 | \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5;
191 | \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5;
192 | \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6;
193 | \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6;
194 | \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark;
195 | \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1;
196 | \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1;
197 | \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2;
198 | \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3;
199 | \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3;
200 | \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4;
201 | \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4;
202 | \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5;
203 | \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5;
204 | \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6;
205 | \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention;
206 | \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hashtag;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Unresolved Mention;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Link;}}{\*\datastore 01050000
207 | 02000000180000004d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000
208 | d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
209 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
210 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
211 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
212 | fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
213 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
214 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
215 | ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
216 | ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e500000000000000000000000010c3
217 | ac2ea669d601feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
218 | 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
219 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
220 | 0000000000000000000000000000000000000000000000000105000000000000}}
--------------------------------------------------------------------------------
/AnalyzeInExcel/SplashLoading.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 | Starting Excel...
17 |
18 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/SplashLoading.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Shapes;
15 |
16 | namespace AnalyzeInExcel
17 | {
18 | ///
19 | /// Interaction logic for SplashLoading.xaml
20 | ///
21 | public partial class SplashLoading : Window
22 | {
23 | public struct POINT
24 | {
25 | public int X;
26 | public int Y;
27 |
28 | public POINT(int x, int y)
29 | {
30 | this.X = x;
31 | this.Y = y;
32 | }
33 | }
34 |
35 | [DllImport("user32.dll")]
36 | [return: MarshalAs(UnmanagedType.Bool)]
37 | public static extern bool GetCursorPos(out POINT pPoint);
38 |
39 | public static int SM_CXSCREEN = 0; // GetSystemMetrics index.
40 | [DllImport("USER32.DLL", SetLastError = true)]
41 | public static extern int GetSystemMetrics(int nIndex);
42 |
43 | public SplashLoading()
44 | {
45 | InitializeComponent();
46 |
47 | Point ptMouse = GetCursorPosition();
48 |
49 | Left = ptMouse.X;
50 | Top = ptMouse.Y;
51 | }
52 |
53 | private static Point GetCursorPosition()
54 | {
55 | GetCursorPos(out POINT cursorScreenPosition);
56 |
57 | double widthInDevicePixels = SplashLoading.GetSystemMetrics(SplashLoading.SM_CXSCREEN);
58 | double widthInDIP = SystemParameters.WorkArea.Right; // Device independent pixels.
59 | double scalingFactor = widthInDIP / widthInDevicePixels;
60 |
61 | var ptMouse = new System.Windows.Point(cursorScreenPosition.X * scalingFactor, cursorScreenPosition.Y * scalingFactor);
62 | return ptMouse;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/TelemetryHelper.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.ApplicationInsights;
2 | using Microsoft.ApplicationInsights.DataContracts;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace AnalyzeInExcel
10 | {
11 | public class TelemetryHelper
12 | {
13 | protected TelemetryClient TC { get; }
14 |
15 | private string Version { get; }
16 |
17 | public TelemetryHelper( bool disableTelemetry = false )
18 | {
19 | Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration configuration = Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.CreateDefault();
20 | configuration.InstrumentationKey = "60ab83db-108f-45ee-b537-d70dc47d3193";
21 | configuration.DisableTelemetry = disableTelemetry;
22 | TC = new TelemetryClient(configuration);
23 |
24 | var assemblyVersion = this.GetType().Assembly.GetName().Version;
25 | Version = $"{assemblyVersion.Major}.{assemblyVersion.Minor}.{assemblyVersion.Build}";
26 | }
27 |
28 | protected virtual EventTelemetry CreateEvent( string eventName )
29 | {
30 | var ev = new EventTelemetry
31 | {
32 | Name = eventName
33 | };
34 | ev.Properties["Version"] = Version;
35 | return ev;
36 | }
37 |
38 | public void TrackEvent( string eventName )
39 | {
40 | TC.TrackEvent(CreateEvent(eventName));
41 | }
42 | public void TrackEvent(string eventName, IEnumerable<(string propertyName, string propertyValue)> properties)
43 | {
44 | var ev = CreateEvent(eventName);
45 | foreach (var (propertyName, propertyValue) in properties)
46 | {
47 | ev.Properties[propertyName] = propertyValue;
48 | }
49 | TC.TrackEvent(ev);
50 | }
51 |
52 | public void TrackException(Exception exception)
53 | {
54 | TC.TrackException(exception);
55 | }
56 |
57 | public void TrackException(ExceptionTelemetry exceptionTelemetry)
58 | {
59 | TC.TrackException(exceptionTelemetry);
60 | }
61 |
62 | public void Flush()
63 | {
64 | TC.Flush();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/analyzeinexcel.pbitool.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "name": "Analyze in Excel",
4 | "description": "Analyze in Excel for Power BI Desktop",
5 | "path": "C:\\Program Files (x86)\\Sqlbi\\AnalyzeInExcel\\AnalyzeInExcel.exe",
6 | "arguments": "--server=\"%server%\" --database=\"%database%\"",
7 | "iconData": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACWAAAAlgCAMAAAA7k/xcAAAA/1BMVEUAAAAPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0HH4NL////i7+iWxatCl2k/lWcYgEgXf0cYgEkUfkUghE5FmWx9t5it0r4hhU8piVZXo3uSw6k2kGARfEIZgUlprIgTfURUoXgzj14bgksPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0EPe0ERfENImm4UfkU4kWKAuZokhlERfEMVfkUrilcihVAagUohhU+jzLf///////////////////////////////////////////////////////////8cgkvl7f68AAAAVXRSTlMAcB88nNzv//avV8/7/ofA5//////08Pj3+fv4+Pj/+fb79/b9+vn79fP8EECAoNAg4FCQYLAw8P78/Pn//P38+Pr7qJ6AwCBAsOBg8FCgEHCQMNCOCXH8dQAAaT1JREFUeAHs3IWV7TAMQEEFFU76b/YzLKPfUmaquMeWFNwLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKgDOoQ7g8pq26xOA8xi6cQrgcqZ5yfMBYO22uASgHs9bVwCscxOFAfW+5qkB0JVNLEBeAZA511EKUPkc/AmAdYsygDl/A4CjjtcD6iEB4K9lCuC1pjUB4L+1DUBfAVCWwgJ9BYDCAn0FgMICfQXA2VQB2B8EoKi1CeBFugSAuw0BvMSWAHCfOYDnq9cEgHtNAbzzByEAPgmBKgHArQYoqk8AeMgSgAcsADxhwbs6EgA8YUFJTQLAY7YAnmFMAHhMF8AzLAkAj6oD8EMIwF38EYIfQgD8EYIdQgDsEQJrvj0ADGGBESwAqKIocMYdAPYoCsy4A8AcTwTs+RQA0McTAXMWBYDAAvosAACBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAIEFCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYILAAQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAIEFCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYILAAQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAIEFCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYILAAQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAIEFCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYILAAQGCBwAJAYIHAAkBggcAC4AeBBQgsAAQWCCwABBYILAAEFiCwABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAgCBBQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFiCwABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAgCBBQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFiCwABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAgCBBQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFiCwABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAovv7N3BkupUFIbR4R5lkHNyvQYBgqSjvv8LOrIstRs7dCC5O2u9QncVX+0fEgCBBQILAIEFAgsABBYILAAEFggsAAQWCCwAEFggsAAQWCCwABBYILAAEFiAwAJAYIHAAkBggcACQGABAgsAgQUCCwCBBQILAIEFAgsABBYILAAEFggsAAQWCCwAEFggsAAQWCCwABBYILAAEFiAwAJAYIHAAkBggcACQGABAgsAgQUCCwCBBQILAIEFAgsABBYILAAEFggsAAQWCCwAEFggsAAQWCCwABBYILAAEFiAwAJAYIHAAkBggcACQGABAgsAgQUCCwCBBQILAIEFAgsABBYILAAEFggsAAQWCCwAMhNYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwAEBggcACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQgsAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsABBYILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBgAQILAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAAQWCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYgMACQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAIEFCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYILAAQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAIEFCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYILAAQGCBwAJAYIHAAkBggcACAIEFAgsAgQUCCwCBBQILAIEFCCwABBYILAAEFggsAAQWILAAEFggsAAQWCCwABBYILAAQGCBwAJAYIHAAkBggcACAIEFAgsA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"
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/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 |
--------------------------------------------------------------------------------
/AnalyzeInExcel/banner-500x70.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sql-bi/AnalyzeInExcel/846180e8d28a1b2ec1d76636f1be573e72794bbe/AnalyzeInExcel/banner-500x70.jpg
--------------------------------------------------------------------------------
/AnalyzeInExcel/icon-2400px.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sql-bi/AnalyzeInExcel/846180e8d28a1b2ec1d76636f1be573e72794bbe/AnalyzeInExcel/icon-2400px.ico
--------------------------------------------------------------------------------
/AnalyzeInExcel/icon-2400px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sql-bi/AnalyzeInExcel/846180e8d28a1b2ec1d76636f1be573e72794bbe/AnalyzeInExcel/icon-2400px.png
--------------------------------------------------------------------------------
/AnalyzeInExcel/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/ExternalToolConfiguration.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 ExternalToolsInstaller
8 | {
9 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Use names of external configuration")]
10 | public class ExternalToolConfiguration
11 | {
12 | public string version { get; set; }
13 | public string name { get; set; }
14 | public string description { get; set; }
15 | public string path { get; set; }
16 | public string arguments { get; set; }
17 | public string iconData { get; set; }
18 | }
19 |
20 | public class PathExternalToolConfiguration
21 | {
22 | public PathExternalToolConfiguration( string filename )
23 | {
24 | Filename = filename;
25 | string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86);
26 | FullPath = System.IO.Path.Combine(path, @"Microsoft Shared\Power BI Desktop\External Tools\" + Filename);
27 | }
28 |
29 | public string Filename { get; }
30 |
31 | public string FullPath { get; }
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/ExternalToolsInstaller.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ExternalToolsInstaller
2 | {
3 | partial class ExternalToolsInstaller
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | //
32 | // ExternalToolsInstaller
33 | //
34 | this.AfterInstall += new System.Configuration.Install.InstallEventHandler(this.ExternalToolsInstaller_AfterInstall);
35 | this.AfterUninstall += new System.Configuration.Install.InstallEventHandler(this.ExternalToolsInstaller_AfterUninstall);
36 |
37 | }
38 |
39 | #endregion
40 | }
41 | }
--------------------------------------------------------------------------------
/ExternalToolsInstaller/ExternalToolsInstaller.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.ApplicationInsights.DataContracts;
2 | using System;
3 | using System.Collections;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Configuration.Install;
7 | using System.Diagnostics;
8 | using System.Linq;
9 | using System.Net;
10 | using System.Runtime.Remoting.Contexts;
11 | using System.Threading.Tasks;
12 | using Newtonsoft.Json;
13 | using System.Reflection;
14 | using Microsoft.ApplicationInsights;
15 | using Microsoft.ApplicationInsights.Extensibility;
16 |
17 | namespace ExternalToolsInstaller
18 | {
19 | [RunInstaller(true)]
20 | public partial class ExternalToolsInstaller : System.Configuration.Install.Installer
21 | {
22 | ///
23 | /// Name of external tool executable
24 | ///
25 | const string EXTERNALTOOLS_EXENAME = @"AnalyzeInExcel.exe";
26 |
27 | ///
28 | /// Name of external tool configuration file
29 | ///
30 | const string EXTERNALTOOLS_CONFIGFILENAME = @"analyzeinexcel.pbitool.json";
31 |
32 | ///
33 | /// The "assemblypath" setup argument corresponds to the path of the DLL invoked by the installer
34 | /// we assume it is the same folder where we installed the AnalyzeInExcel.exe file
35 | ///
36 | const string SETUP_ASSEMBLYPATH = "assemblypath";
37 |
38 | ///
39 | /// The telemetry setup argument correspond to the radio button selection
40 | /// to enable or disable telemetry (1=enabled, 0=disabled)
41 | ///
42 | const string SETUP_TELEMETRY = "telemetry";
43 |
44 | ///
45 | /// The product version setup argument correspond to the version of the product installed
46 | ///
47 | const string SETUP_PRODUCT_VERSION = "version";
48 |
49 | ///
50 | /// Command line argument to enable telemetry in external tool
51 | /// Add this command line argument if the telemetry is enabled
52 | ///
53 | const string TELEMETRY_ARGUMENT = "--telemetry";
54 |
55 | public ExternalToolsInstaller()
56 | {
57 | InitializeComponent();
58 |
59 | PathConfiguration = new PathExternalToolConfiguration(EXTERNALTOOLS_CONFIGFILENAME);
60 | }
61 |
62 | private PathExternalToolConfiguration PathConfiguration { get; }
63 |
64 | private ExternalToolConfiguration ReadExternalToolConfiguration()
65 | {
66 | string config = System.IO.File.ReadAllText(PathConfiguration.FullPath);
67 | return JsonConvert.DeserializeObject(config, typeof(ExternalToolConfiguration)) as ExternalToolConfiguration;
68 | }
69 |
70 | private void WriteExternalToolConfiguration(ExternalToolConfiguration configuration)
71 | {
72 | string updatedConfig = JsonConvert.SerializeObject(configuration, Formatting.Indented);
73 | System.IO.File.WriteAllText(PathConfiguration.FullPath, updatedConfig);
74 | }
75 |
76 | private string GetInstallerProductVersion()
77 | {
78 | if (Context.Parameters.ContainsKey(SETUP_PRODUCT_VERSION))
79 | {
80 | return Context.Parameters[SETUP_PRODUCT_VERSION];
81 | }
82 | else
83 | {
84 | return null;
85 | }
86 | }
87 |
88 | private bool IsSetupTelemetryEnabled()
89 | {
90 | if (Context.Parameters.ContainsKey(SETUP_TELEMETRY))
91 | {
92 | string telemetryValue = Context.Parameters[SETUP_TELEMETRY] ?? string.Empty;
93 | return (telemetryValue.Trim() != "0");
94 | }
95 | else
96 | {
97 | // In case of missing argument enable telemetry to further investigate
98 | return true;
99 | }
100 | }
101 |
102 | private TelemetryClient GetTelemetryClient( bool telemetryEnabled )
103 | {
104 | TelemetryConfiguration telemetryConfiguration = TelemetryConfiguration.CreateDefault();
105 | telemetryConfiguration.InstrumentationKey = "60ab83db-108f-45ee-b537-d70dc47d3193";
106 | telemetryConfiguration.DisableTelemetry = (telemetryEnabled == false);
107 | TelemetryClient tc = new Microsoft.ApplicationInsights.TelemetryClient(telemetryConfiguration);
108 | return tc;
109 | }
110 |
111 | private void ExternalToolsInstaller_AfterInstall(object sender, InstallEventArgs e)
112 | {
113 | bool telemetryEnabled = IsSetupTelemetryEnabled();
114 | var ev = new EventTelemetry
115 | {
116 | Name = "Install"
117 | };
118 |
119 | // Fix version installed
120 | ExternalToolConfiguration externalToolConfiguration = ReadExternalToolConfiguration();
121 | externalToolConfiguration.version = GetInstallerProductVersion() ?? externalToolConfiguration.version;
122 | ev.Properties["Version"] = externalToolConfiguration.version;
123 |
124 | // Fix executable in configuration
125 | string assemblyPath;
126 | if (Context.Parameters.ContainsKey(SETUP_ASSEMBLYPATH))
127 | {
128 | assemblyPath = Context.Parameters[SETUP_ASSEMBLYPATH];
129 | }
130 | else
131 | {
132 | Context.LogMessage($"The {"ASSEMBLYPATH"} property is not available, assume directory of installer DLL instead.");
133 | assemblyPath = Assembly.GetExecutingAssembly().Location;
134 | }
135 | string externalToolsDirectory = System.IO.Path.GetDirectoryName(assemblyPath);
136 | string externalToolsExe = System.IO.Path.Combine(externalToolsDirectory, EXTERNALTOOLS_EXENAME);
137 | externalToolConfiguration.path = externalToolsExe;
138 |
139 | // Remove existing telemetry option
140 | string telemetryOption = $" {TELEMETRY_ARGUMENT}";
141 | externalToolConfiguration.arguments = externalToolConfiguration.arguments.Replace(telemetryOption, "");
142 | externalToolConfiguration.arguments = externalToolConfiguration.arguments.Replace(telemetryOption.Trim(), "");
143 |
144 | // Add telemetry argument if telemetry is enabled during setup
145 | if (telemetryEnabled)
146 | {
147 | externalToolConfiguration.arguments += telemetryOption;
148 | Context.LogMessage($"Telemetry enabled");
149 | }
150 |
151 | // Initialize Telemetry
152 | TelemetryClient tc = GetTelemetryClient(telemetryEnabled);
153 | try
154 | {
155 | // Update external tool configuration
156 | WriteExternalToolConfiguration(externalToolConfiguration);
157 |
158 | // Send telemetry
159 | tc.TrackEvent(ev);
160 | tc.Flush();
161 | }
162 | catch (Exception ex)
163 | {
164 | // In case of error, send exception to Telemetry
165 | tc.TrackException(ex);
166 | tc.Flush();
167 | throw;
168 | }
169 | }
170 |
171 | private void ExternalToolsInstaller_AfterUninstall(object sender, InstallEventArgs e)
172 | {
173 | // Read version installed
174 | ExternalToolConfiguration externalToolConfiguration = ReadExternalToolConfiguration();
175 | string versionInstalled = GetInstallerProductVersion() ?? externalToolConfiguration?.version ?? "unknown";
176 |
177 | // Enable telemetry if it was enabled in configuration file or if there is no configuration
178 | bool telemetryEnabled = externalToolConfiguration?.arguments?.Contains(TELEMETRY_ARGUMENT) ?? true;
179 | var ev = new EventTelemetry
180 | {
181 | Name = "Uninstall"
182 | };
183 | ev.Properties["Version"] = versionInstalled;
184 |
185 | // Initialize Telemetry
186 | TelemetryClient tc = GetTelemetryClient(telemetryEnabled);
187 | try
188 | {
189 | // Send telemetry
190 | tc.TrackEvent(ev);
191 | tc.Flush();
192 | }
193 | catch (Exception ex)
194 | {
195 | // In case of error, send exception to Telemetry
196 | tc.TrackException(ex);
197 | tc.Flush();
198 | throw;
199 | }
200 | }
201 |
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/ExternalToolsInstaller.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Debug
7 | AnyCPU
8 | {91B65004-6E31-4F13-8523-5A4B188A7546}
9 | Library
10 | Properties
11 | ExternalToolsInstaller
12 | ExternalToolsInstaller
13 | v4.5
14 | 512
15 | true
16 |
17 |
18 |
19 |
22 | .allowedextension
23 |
24 |
25 |
26 | true
27 | full
28 | false
29 | bin\Debug\
30 | DEBUG;TRACE
31 | prompt
32 | 4
33 |
34 |
35 | none
36 | true
37 | bin\Release\
38 | TRACE
39 | prompt
40 | 4
41 |
42 |
43 | icon-2400px.ico
44 |
45 |
46 |
47 | ..\packages\Costura.Fody.3.3.3\lib\net40\Costura.dll
48 |
49 |
50 | ..\packages\Microsoft.ApplicationInsights.2.14.0\lib\net45\Microsoft.ApplicationInsights.dll
51 |
52 |
53 | ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
54 |
55 |
56 |
57 | ..\packages\System.Buffers.4.5.1\lib\netstandard1.1\System.Buffers.dll
58 |
59 |
60 |
61 |
62 | ..\packages\System.Diagnostics.DiagnosticSource.4.7.1\lib\net45\System.Diagnostics.DiagnosticSource.dll
63 |
64 |
65 |
66 | ..\packages\System.Memory.4.5.4\lib\netstandard1.1\System.Memory.dll
67 |
68 |
69 | ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | Component
82 |
83 |
84 | ExternalToolsInstaller.cs
85 |
86 |
87 |
88 |
89 |
90 | ExternalToolsInstaller.cs
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/ExternalToolsInstaller.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | False
122 |
123 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/FodyWeavers.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks
13 |
14 |
15 |
16 |
17 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.
18 |
19 |
20 |
21 |
22 | A list of unmanaged 32 bit assembly names to include, delimited with line breaks.
23 |
24 |
25 |
26 |
27 | A list of unmanaged 64 bit assembly names to include, delimited with line breaks.
28 |
29 |
30 |
31 |
32 | The order of preloaded assemblies, delimited with line breaks.
33 |
34 |
35 |
36 |
37 |
38 | This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.
39 |
40 |
41 |
42 |
43 | Controls if .pdbs for reference assemblies are also embedded.
44 |
45 |
46 |
47 |
48 | Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.
49 |
50 |
51 |
52 |
53 | As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.
54 |
55 |
56 |
57 |
58 | Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.
59 |
60 |
61 |
62 |
63 | Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.
64 |
65 |
66 |
67 |
68 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |
69 |
70 |
71 |
72 |
73 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.
74 |
75 |
76 |
77 |
78 | A list of unmanaged 32 bit assembly names to include, delimited with |.
79 |
80 |
81 |
82 |
83 | A list of unmanaged 64 bit assembly names to include, delimited with |.
84 |
85 |
86 |
87 |
88 | The order of preloaded assemblies, delimited with |.
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
97 |
98 |
99 |
100 |
101 | A comma-separated list of error codes that can be safely ignored in assembly verification.
102 |
103 |
104 |
105 |
106 | 'false' to turn off automatic generation of the XML Schema file.
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/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("ExternalToolsInstaller")]
9 | [assembly: AssemblyDescription("Configuration for External Tools in Power BI Desktop")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ExternalToolsInstaller")]
13 | [assembly: AssemblyCopyright("")]
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("91b65004-6e31-4f13-8523-5a4b188a7546")]
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.1.3.0")]
36 | [assembly: AssemblyFileVersion("1.1.3.0")]
37 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/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 |
--------------------------------------------------------------------------------
/ExternalToolsInstaller/icon-2400px.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sql-bi/AnalyzeInExcel/846180e8d28a1b2ec1d76636f1be573e72794bbe/ExternalToolsInstaller/icon-2400px.ico
--------------------------------------------------------------------------------
/ExternalToolsInstaller/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 SQLBI
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AnalyzeInExcel
2 | Analyze in Excel for Power BI Desktop
3 |
4 | This is an External Tool for Power BI Desktop to connect Excel to the local model hosted in Power BI Desktop.
5 | The goal is to be just one click away from an Excel report.
6 | While the initial version must be essential, the following versions could extend features, finding a way to keep the one-click experience consistent.
7 |
8 | ## v1 Open Excel
9 | A button in External Tools opens Excel through an ODC file.
10 | - The user gets an empty PivotTable connected to the same AS instance hosted by Power BI Desktop.
11 | - If the user creates a more complex report in Excel and saves the file, the connection string is no longer valid as soon as the Power BI Desktop window is closed.
12 | - The next time the user opens Power BI Desktop, the connection is different, and a file saved in Excel does not have a valid connection.
13 | ## v2 Create Excel Report
14 | A button in External Tools that creates a specific report in Excel, using PivotTable and/or PivotChart
15 | - The user gets a configured Excel PivotTable connected to the same AS instance hosted by Power BI Desktop.
16 | - The report could be based on a template, on an Excel macro, or on a dynamic report created by using Office SDK
17 | - If the user saves the file, the connection string is no longer valid as soon as the Power BI Desktop window is closed.
18 | - The next time the user opens Power BI Desktop, the connection is different, and a file saved in Excel does not have a valid connection.
19 | ## v3 Open Excel Report
20 | A button in External Tools that opens an existing report in Excel, or create a new one if it is the first connection to that Power BI report.
21 | - The first time the user uses the button on a PBIX file, the user gets a configured Excel PivotTable connected to the same AS instance hosted by Power BI Desktop.
22 | - The initial report could be based on a template, on an Excel macro, or on a dynamic report created by using Office SDK.
23 | - The connection is lost as soon as the Power BI Desktop window is closed.
24 | - The next time the user opens Power BI Desktop and uses the tool, the tool modifies the Excel file restoring a valid connection and then open the file in Excel.
25 | ## v4 Excel Add-In to connect to Power BI Desktop
26 | An Excel add-in written in VSTO that opens Power BI Desktop and connects a PivotTable to Power BI Desktop.
27 | - The user can initiate a connection in Excel, opening a specific Power BI Desktop if it is not already open.
28 | - If the Excel file was saved by using the “Open Excel Report” external tool, then the Add-In has additional information to retrieve the Power BI Desktop file to open.
29 |
--------------------------------------------------------------------------------
/azure-pipelines-1.yml:
--------------------------------------------------------------------------------
1 | # Build on Azure DevOps pipeline - no MSI, no sign
2 |
3 | trigger:
4 | - master
5 |
6 | pool:
7 | vmImage: 'windows-2019'
8 |
9 | variables:
10 | solution: '**/*.sln'
11 | buildPlatform: 'Any CPU'
12 | buildConfiguration: 'Release'
13 |
14 | steps:
15 | - task: NuGetToolInstaller@1
16 |
17 | - task: NuGetCommand@2
18 | inputs:
19 | restoreSolution: '$(solution)'
20 |
21 | - task: VSBuild@1
22 | inputs:
23 | solution: '$(solution)'
24 | platform: '$(buildPlatform)'
25 | configuration: '$(buildConfiguration)'
26 |
27 | - task: CopyFiles@2
28 | inputs:
29 | Contents: '**\bin\release\**'
30 | TargetFolder: '$(build.artifactstagingdirectory)/drop'
31 | flattenFolders: true
32 |
33 | #publish artifacts
34 | - task: PublishBuildArtifacts@1
35 | displayName: 'Publish Artifact: drop'
36 | inputs:
37 | PathtoPublish: '$(build.artifactstagingdirectory)/drop'
38 |
39 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | # Build and sign executable and installer for AnalyzeInExcel external tool
2 | # The BuildInstaller@1 task requires VS2017
3 |
4 | trigger:
5 | - none
6 |
7 | pool: Default
8 |
9 | variables:
10 | solution: '**/*.sln'
11 | buildPlatform: 'Any CPU'
12 | buildConfiguration: 'Release'
13 |
14 | steps:
15 |
16 | - task: UseDotNet@2
17 | displayName: Use .NET Core 2.1
18 | inputs:
19 | version: '2.1.x'
20 | packageType: runtime
21 |
22 | - task: DotNetCoreCLI@2
23 | inputs:
24 | command: 'custom'
25 | custom: 'tool'
26 | arguments: 'update --global azuresigntool'
27 | displayName: Install AzureSignTool
28 |
29 | - task: NuGetToolInstaller@1
30 |
31 | - task: NuGetCommand@2
32 | inputs:
33 | restoreSolution: '$(solution)'
34 |
35 | - task: VSBuild@1
36 | inputs:
37 | solution: '$(solution)'
38 | platform: '$(buildPlatform)'
39 | configuration: '$(buildConfiguration)'
40 |
41 | - script: AzureSignTool sign -kvu "$(SigningVaultURL)" -kvi "$(SigningClientId)" -kvs "$(SigningClientSecret)" -kvc "$(SigningCertName)" -tr http://timestamp.digicert.com -v "$(Build.SourcesDirectory)/AnalyzeInExcel/bin/Release/AnalyzeInExcel.exe" "$(Build.SourcesDirectory)/ExternalToolsInstaller/bin/Release/ExternalToolsInstaller.dll"
42 | name: CodeSigningEXEDLL
43 |
44 | - task: BatchScript@1
45 | inputs:
46 | filename: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\VSI\DisableOutOfProcBuild\DisableOutOfProcBuild.exe'
47 | workingFolder: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\VSI\DisableOutOfProcBuild\'
48 |
49 | - task: BuildInstaller@1
50 | inputs:
51 | installTaskMode: 'vdproj'
52 | SlnPath: 'AnalyzeInExcel.sln'
53 | VdprojPath: 'SetupAnalyzeInExcel/SetupAnalyzeInExcel.vdproj'
54 | VsVersion: 'VS2017'
55 |
56 | - task: BatchScript@1
57 | inputs:
58 | filename: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\VSI\DisableOutOfProcBuild\DisableOutOfProcBuild.exe'
59 | workingFolder: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\VSI\DisableOutOfProcBuild\'
60 | arguments: 'undo'
61 |
62 | - script: AzureSignTool sign -kvu "$(SigningVaultURL)" -kvi "$(SigningClientId)" -kvs "$(SigningClientSecret)" -kvc "$(SigningCertName)" -tr http://timestamp.digicert.com -v "$(Build.SourcesDirectory)/SetupAnalyzeInExcel/Release/AnalyzeInExcel.msi"
63 | name: CodeSigningMSI
64 |
65 | - task: CopyFiles@2
66 | inputs:
67 | Contents: '$(Build.SourcesDirectory)/SetupAnalyzeInExcel/Release/AnalyzeInExcel.msi'
68 | TargetFolder: '$(build.artifactstagingdirectory)/drop'
69 | flattenFolders: true
70 |
71 | #publish artifacts
72 | - task: PublishBuildArtifacts@1
73 | displayName: 'Publish Artifact: drop'
74 | inputs:
75 | PathtoPublish: '$(build.artifactstagingdirectory)/drop'
76 |
77 |
--------------------------------------------------------------------------------