Skip to content

Commit bcba15a

Browse files
committed
v1.1.0 - Launch Excel through Interop and create a new file with embedded connection. If this fails, creates the ODC connection as in v1.0.
1 parent 33021f8 commit bcba15a

8 files changed

Lines changed: 79 additions & 105 deletions

File tree

AnalyzeInExcel/AnalyzeInExcel.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@
7878
<HintPath>..\packages\Microsoft.ApplicationInsights.2.14.0\lib\net45\Microsoft.ApplicationInsights.dll</HintPath>
7979
<Private>True</Private>
8080
</Reference>
81+
<Reference Include="Microsoft.Office.Interop.Excel, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
82+
<HintPath>..\packages\Microsoft.Office.Interop.Excel.15.0.4795.1000\lib\net20\Microsoft.Office.Interop.Excel.dll</HintPath>
83+
<EmbedInteropTypes>True</EmbedInteropTypes>
84+
</Reference>
8185
<Reference Include="System" />
8286
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
8387
<HintPath>..\packages\System.Buffers.4.5.1\lib\netstandard1.1\System.Buffers.dll</HintPath>

AnalyzeInExcel/App.xaml.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ public partial class App : Application
1818
public Options AppOptions;
1919
const string MSOLAP_DRIVER_URL = @"https://go.microsoft.com/fwlink/?LinkId=746283";
2020

21+
const string EV_MSOLAP_NOTFOUND = "MSOLAP driver not found";
22+
const string EV_MSOLAP_SETUP = "Requested MSOLAP driver setup";
23+
const string EV_MODEL_NOT_AVAILABLE = "Model not available";
24+
const string EV_EXCEL_NOT_AVAILABLE = "Excel not available";
25+
const string EV_CONFIGURATION_INCOMPLETE = "Configuration incomplete";
26+
const string EV_RUNEXCEL = "Run Excel";
27+
2128
public void CheckUpdates(bool synchronous = true)
2229
{
2330
AutoUpdater.HttpUserAgent = "AutoUpdater";
@@ -72,12 +79,12 @@ protected override void OnStartup(StartupEventArgs e)
7279
bool goodMsOlapDriver = ModelHelper.HasMsOlapDriver();
7380
if (!goodMsOlapDriver)
7481
{
75-
th.TrackEvent("MSOLAP driver not found");
82+
th.TrackEvent(EV_MSOLAP_NOTFOUND);
7683
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)
7784
{
7885
try
7986
{
80-
th.TrackEvent("Requested MSOLAP driver setup");
87+
th.TrackEvent(EV_MSOLAP_SETUP);
8188
UpdateMsOlapDriver();
8289
}
8390
catch (Exception ex)
@@ -97,7 +104,7 @@ protected override void OnStartup(StartupEventArgs e)
97104
if (string.IsNullOrEmpty(cubeName))
98105
{
99106
ShowMessage("Power BI has an empty model or it is connected to an unkonwn external dataset. You cannot connect Excel.");
100-
th.TrackEvent("Model not available");
107+
th.TrackEvent(EV_MODEL_NOT_AVAILABLE);
101108
}
102109
else if (ExcelHelper.IsExcelAvailable())
103110
{
@@ -118,12 +125,12 @@ protected override void OnStartup(StartupEventArgs e)
118125
if (experiment)
119126
{
120127
excelStarted = ExcelHelper.CreateInstanceWithPivotTable(serverName, databaseName, cubeName, (ex) => th.TrackException(ex));
121-
if (excelStarted) th.TrackEvent("Run Excel Experiment");
128+
if (excelStarted) th.TrackEvent(EV_RUNEXCEL, "RunType", "Interop");
122129
}
123130
if (!excelStarted)
124131
{
125132
RunExcelProcess(serverName, databaseName, cubeName);
126-
th.TrackEvent("Run Excel");
133+
th.TrackEvent(EV_RUNEXCEL, "RunType", "ODC File");
127134
}
128135
}
129136
finally
@@ -134,7 +141,7 @@ protected override void OnStartup(StartupEventArgs e)
134141
else
135142
{
136143
ShowMessage("Excel is not available. Please check whether Excel is correctly installed.");
137-
th.TrackEvent("Excel not available");
144+
th.TrackEvent(EV_EXCEL_NOT_AVAILABLE);
138145
}
139146
th.Flush();
140147

@@ -151,7 +158,7 @@ protected override void OnStartup(StartupEventArgs e)
151158
}
152159
else
153160
{
154-
th.TrackEvent("Configuration incomplete");
161+
th.TrackEvent(EV_CONFIGURATION_INCOMPLETE);
155162
th.Flush();
156163
}
157164

AnalyzeInExcel/ExcelHelper.cs

Lines changed: 47 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Windows;
44
using System.Windows.Threading;
55
using System.Runtime.InteropServices;
6+
using Excel = Microsoft.Office.Interop.Excel;
67

78
namespace AnalyzeInExcel
89
{
@@ -22,105 +23,60 @@ public static bool IsExcelAvailable()
2223
return (type != null);
2324
}
2425

26+
/// <summary>
27+
/// Create a new Excel file with a PivotTable connected to the server/database/cube provided
28+
/// </summary>
29+
/// <param name="serverName"></param>
30+
/// <param name="databaseName"></param>
31+
/// <param name="cubeName"></param>
32+
/// <param name="exceptionAction">Action that processes any exception - the function will return false, this is a way to manage logging/telemetry</param>
33+
/// <returns>true if the operation completes without errors, otherwise false (any exception is removed and the function returns false)</returns>
2534
public static bool CreateInstanceWithPivotTable(string serverName, string databaseName, string cubeName, Action<Exception> exceptionAction )
26-
{
27-
const int XlLayoutRowType_xlCompactRow = 0; // Excel.XlLayoutRowType.xlCompactRow
28-
const int XlPivotTableSourceType_xlExternal = 2; // Excel.XlPivotTableSourceType.xlExternal
29-
const int XlPivotFieldRepeatLabels_xlRepeatLabels = 2; // Excel.XlPivotFieldRepeatLabels.xlRepeatLabels
30-
35+
{
3136
var connectionString = ModelHelper.GetOleDbConnectionString(serverName, databaseName);
3237
var connectionName = $"AnalyzeInExcel [{ serverName }].[{ databaseName }].[{ cubeName }]";
3338
var commandText = cubeName;
3439
var pivotTableName = $"AnalyzeInExcelPivotTable";
3540

36-
var type = Type.GetTypeFromProgID("Excel.Application");
37-
if (type == null)
38-
return false;
39-
40-
dynamic app = Activator.CreateInstance(type);
4141
try
4242
{
43-
try
44-
{
45-
var workbook = app.Workbooks.Add();
46-
47-
var workbookConnection = workbook.Connections.Add(
48-
Name: connectionName,
49-
Description: "",
50-
ConnectionString: $"OLEDB;{ connectionString }",
51-
CommandText: commandText,
52-
lCmdtype: 1
53-
);
54-
55-
var pivotCache = workbook.PivotCaches().Create(
56-
SourceType: XlPivotTableSourceType_xlExternal,
57-
SourceData: workbookConnection
58-
);
59-
60-
#region Configure PivotCache
61-
62-
pivotCache.RefreshOnFileOpen = false;
63-
64-
#endregion
65-
66-
var worksheet = workbook.ActiveSheet;
67-
68-
var pivotTable = pivotCache.CreatePivotTable(
69-
TableDestination: worksheet.Range["A1"],
70-
TableName: pivotTableName,
71-
ReadData: false
72-
);
73-
74-
#region Configure PivotTable
75-
76-
pivotTable.ColumnGrand = true;
77-
pivotTable.HasAutoFormat = true;
78-
pivotTable.DisplayErrorString = true;
79-
pivotTable.DisplayNullString = true;
80-
pivotTable.EnableDrilldown = true;
81-
pivotTable.ErrorString = "";
82-
pivotTable.MergeLabels = false;
83-
pivotTable.NullString = "";
84-
pivotTable.PageFieldOrder = 2;
85-
pivotTable.PageFieldWrapCount = 0;
86-
pivotTable.PreserveFormatting = true;
87-
pivotTable.RowGrand = true;
88-
pivotTable.PrintTitles = false;
89-
pivotTable.RepeatItemsOnEachPrintedPage = true;
90-
pivotTable.TotalsAnnotation = true;
91-
pivotTable.CompactRowIndent = 1;
92-
pivotTable.VisualTotals = false;
93-
pivotTable.InGridDropZones = false;
94-
pivotTable.DisplayFieldCaptions = true;
95-
pivotTable.DisplayMemberPropertyTooltips = true;
96-
pivotTable.DisplayContextTooltips = true;
97-
pivotTable.ShowDrillIndicators = true;
98-
pivotTable.PrintDrillIndicators = false;
99-
pivotTable.DisplayEmptyRow = false;
100-
pivotTable.DisplayEmptyColumn = false;
101-
pivotTable.AllowMultipleFilters = false;
102-
pivotTable.SortUsingCustomLists = true;
103-
pivotTable.DisplayImmediateItems = true;
104-
pivotTable.ViewCalculatedMembers = true;
105-
pivotTable.EnableWriteback = false;
106-
pivotTable.ShowValuesRow = false;
107-
pivotTable.CalculatedMembersInFilters = true;
108-
pivotTable.RowAxisLayout(XlLayoutRowType_xlCompactRow);
109-
pivotTable.RepeatAllLabels(XlPivotFieldRepeatLabels_xlRepeatLabels);
110-
111-
#endregion
112-
113-
// Show Excel
114-
app.Visible = true;
115-
116-
// Set Excel window as foreground window
117-
var hwnd = app.Hwnd;
118-
SetForegroundWindow((IntPtr)hwnd); // Note Hwnd is declared as int
119-
}
120-
finally
121-
{
122-
Marshal.ReleaseComObject(app);
123-
}
43+
Excel.Application app = new Excel.Application();
44+
45+
// Create a new workbook
46+
var workbook = app.Workbooks.Add();
47+
48+
// Create the connection
49+
var workbookConnection = workbook.Connections.Add(
50+
Name: connectionName,
51+
Description: "",
52+
ConnectionString: $"OLEDB;{ connectionString }",
53+
CommandText: commandText,
54+
lCmdtype: 1
55+
);
56+
57+
// Create the pivotcache
58+
var pivotCache = workbook.PivotCaches().Create(
59+
SourceType: Excel.XlPivotTableSourceType.xlExternal,
60+
SourceData: workbookConnection
61+
);
62+
pivotCache.RefreshOnFileOpen = false;
63+
64+
// Get the active worksheet
65+
var worksheet = workbook.ActiveSheet;
66+
67+
// Create the PivotTable
68+
var pivotTable = pivotCache.CreatePivotTable(
69+
TableDestination: worksheet.Range["A1"],
70+
TableName: pivotTableName,
71+
ReadData: false
72+
);
73+
74+
// Show Excel
75+
app.Visible = true;
76+
77+
// Set Excel window as foreground window
78+
var hwnd = app.Hwnd;
79+
SetForegroundWindow((IntPtr)hwnd); // Note Hwnd is declared as int
12480
}
12581
catch (Exception ex)
12682
{

AnalyzeInExcel/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,5 @@
5151
// You can specify all the values or you can default the Build and Revision Numbers
5252
// by using the '*' as shown below:
5353
// [assembly: AssemblyVersion("1.0.*")]
54-
[assembly: AssemblyVersion("1.0.5.0")]
55-
[assembly: AssemblyFileVersion("1.0.5.0")]
54+
[assembly: AssemblyVersion("1.1.0.0")]
55+
[assembly: AssemblyFileVersion("1.1.0.0")]

AnalyzeInExcel/TelemetryHelper.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ public void TrackEvent( string eventName )
3939
{
4040
TC.TrackEvent(CreateEvent(eventName));
4141
}
42+
public void TrackEvent(string eventName, string propertyName, string propertyValue)
43+
{
44+
var ev = CreateEvent(eventName);
45+
ev.Properties[propertyName] = propertyValue;
46+
TC.TrackEvent(ev);
47+
}
4248

4349
public void TrackException(Exception exception)
4450
{

AnalyzeInExcel/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<package id="Costura.Fody" version="3.3.3" targetFramework="net45" />
66
<package id="Fody" version="4.2.1" targetFramework="net45" developmentDependency="true" />
77
<package id="Microsoft.ApplicationInsights" version="2.14.0" targetFramework="net45" />
8+
<package id="Microsoft.Office.Interop.Excel" version="15.0.4795.1000" targetFramework="net45" />
89
<package id="System.Buffers" version="4.5.1" targetFramework="net45" />
910
<package id="System.Diagnostics.DiagnosticSource" version="4.6.0" targetFramework="net45" />
1011
<package id="System.Memory" version="4.5.4" targetFramework="net45" />

ExternalToolsInstaller/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@
3232
// You can specify all the values or you can default the Build and Revision Numbers
3333
// by using the '*' as shown below:
3434
// [assembly: AssemblyVersion("1.0.*")]
35-
[assembly: AssemblyVersion("1.0.5.0")]
36-
[assembly: AssemblyFileVersion("1.0.5.0")]
35+
[assembly: AssemblyVersion("1.1.0.0")]
36+
[assembly: AssemblyFileVersion("1.1.0.0")]

SetupAnalyzeInExcel/SetupAnalyzeInExcel.vdproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3420,15 +3420,15 @@
34203420
{
34213421
"Name" = "8:Microsoft Visual Studio"
34223422
"ProductName" = "8:Analyze in Excel for Power BI Desktop"
3423-
"ProductCode" = "8:{F8E449F6-8A4F-4180-8B64-CE249CC54AB6}"
3424-
"PackageCode" = "8:{D1F0DFC5-AAE9-4282-8940-E24A25F38878}"
3423+
"ProductCode" = "8:{2A931BB2-2905-4541-807D-052EAAF1C9E7}"
3424+
"PackageCode" = "8:{A16768BA-B97F-495F-A961-295AA58D2547}"
34253425
"UpgradeCode" = "8:{FC2F9C00-CAD5-455E-BD9D-B1C607F4ABDA}"
34263426
"AspNetVersion" = "8:4.0.30319.0"
34273427
"RestartWWWService" = "11:FALSE"
34283428
"RemovePreviousVersions" = "11:TRUE"
34293429
"DetectNewerInstalledVersion" = "11:TRUE"
34303430
"InstallAllUsers" = "11:TRUE"
3431-
"ProductVersion" = "8:1.0.5"
3431+
"ProductVersion" = "8:1.1.0"
34323432
"Manufacturer" = "8:Sqlbi"
34333433
"ARPHELPTELEPHONE" = "8:"
34343434
"ARPHELPLINK" = "8:"

0 commit comments

Comments
 (0)