diff --git a/.gitignore b/.gitignore index 342c97e2..3deb3ed6 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ +.pkgrefgen/ # Visual Studio 2015/2017 cache/options directory .vs/ diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/PBIEmbedGenerator.csproj b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/PBIEmbedGenerator.csproj index 1f6d4ca6..d7285230 100644 --- a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/PBIEmbedGenerator.csproj +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/PBIEmbedGenerator.csproj @@ -5,6 +5,14 @@ net7.0 + + + + + + + + @@ -13,4 +21,19 @@ + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Program.cs b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Program.cs index 5d1cf7ce..58a64227 100644 --- a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Program.cs +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Program.cs @@ -4,6 +4,7 @@ using System.IO; using Mono.Options; using System.Collections.Generic; +using PBIEmbedGenerator.Properties; namespace APIQueryGenerator { @@ -60,7 +61,7 @@ static void Main(string[] args) catch (Exception e) { Console.WriteLine("Could not read input file as a xml file."); - Environment.Exit(0); + Environment.Exit(-1); } @@ -121,383 +122,153 @@ static void Main(string[] args) } - private static void indents(StringBuilder sb, int indentLevel) - { - var indent = " "; - - for (int i = 0; i < indentLevel; i++) - { - sb.Append(indent); - } - } - - private static void indentAppendLine(StringBuilder sb, int indentLevel, string s) - { - indents(sb, indentLevel); - sb.AppendLine(s); - } - public static string GeneratePBIRCExtensionCode(string alNamespace, XmlNode rcExt) { - StringBuilder sb = new StringBuilder(); - - /* - pageextension 50100 BusinessManagerRoleCenterExt extends "Business Manager Role Center" - */ - - sb.AppendLine("// Auto-generated al file for PBI role centre extension " + rcExt.Attributes["id"].Value); - sb.AppendLine("// "); - sb.AppendLine("// Adding actions for the following AL PBI pages:"); - foreach (XmlNode action in rcExt.SelectNodes("action")) - { - sb.AppendLine("// * " + action.Attributes["pbipagename"].Value ); - } - sb.AppendLine(""); - - sb.AppendLine("namespace " + alNamespace); - sb.AppendLine(""); - - sb.AppendLine("pageextension " + rcExt.Attributes["id"].Value + " \"" + rcExt.Attributes["name"].Value + "\" extends \"" + rcExt.Attributes["extends"].Value + "\""); - sb.AppendLine("{"); - - indents(sb, 1); - sb.AppendLine("actions"); - - indents(sb, 1); - sb.AppendLine("{"); - - indents(sb, 2); - sb.AppendLine(rcExt.Attributes["where"].Value); - - indents(sb, 2); - sb.AppendLine("{"); - - indents(sb, 3); - sb.AppendLine("group(\"PBIReports\")"); - - indents(sb, 3); - sb.AppendLine("{"); - - indents(sb, 4); - sb.AppendLine("Caption = 'Power BI Reports';"); - - indents(sb, 4); - sb.AppendLine("Image = PowerBI;"); - - indents(sb, 4); - sb.AppendLine("ToolTip = '" + rcExt.Attributes["tooltip"].Value + "';"); - + StringBuilder actionssb = new StringBuilder(); foreach (XmlNode action in rcExt.SelectNodes("action")) { - var content = GeneratePBIRCExtensionActionCode(action, sb); + GeneratePBIRCExtensionActionCode(action, actionssb); } - indents(sb, 3); - sb.AppendLine("}"); - - indents(sb, 2); - sb.AppendLine("}"); - - indents(sb, 1); - sb.AppendLine("}"); + StringBuilder sb = new StringBuilder(); - sb.AppendLine("}"); + sb.AppendFormat(Encoding.UTF8.GetString(Resources.RoleCenterExtensionTemplate), + alNamespace, // 0 + rcExt.Attributes["rolecenternamespace"].Value, // 1 + rcExt.Attributes["id"].Value, // 2 + EscapeALTextString(rcExt.Attributes["name"].Value), // 3 + EscapeALTextString(rcExt.Attributes["extends"].Value), // 4 + rcExt.Attributes["where"].Value, // 5 + rcExt.Attributes["image"].Value, // 6 + rcExt.Attributes["tooltip"].Value, // 7 + actionssb.ToString() // 8 + ); return sb.ToString(); } - public static string GeneratePBIRCExtensionActionCode(XmlNode action, StringBuilder sb) + public static void GeneratePBIRCExtensionActionCode(XmlNode action, StringBuilder sb) { - //action(PBIFinancialOverview) - //{ - // ApplicationArea = Basic, Suite; - // Caption = 'Financial Overview'; - // Image = "PowerBI"; - // RunObject = page PBIFinancialOverview; - // ToolTip = 'Open a Power BI report that shows your company''s assets, liabilities, and equity.'; - //} - - sb.AppendLine(""); - - indents(sb, 4); - sb.AppendLine("action(" + action.Attributes["name"].Value + ")"); - - indents(sb, 4); - sb.AppendLine("{"); - - indents(sb, 5); - sb.AppendLine("ApplicationArea = Basic, Suite;"); - - indents(sb, 5); - sb.AppendLine("Caption = '" + action.Attributes["caption"].Value + "';"); - - indents(sb, 5); - sb.AppendLine("Image = \"PowerBI\";"); - - indents(sb, 5); - sb.AppendLine("RunObject = page \"" + action.Attributes["pbipagename"].Value + "\";"); - - indents(sb, 5); - sb.AppendLine("Tooltip = '" + action.Attributes["tooltip"].Value + "';"); - - indents(sb, 4); - sb.AppendLine("}"); - - return sb.ToString(); + if (action.Attributes["obsolete"].Value.Length > 0) + { + sb.AppendLine($"#if not CLEAN{action.Attributes["obsolete"].Value}"); + } + StringBuilder additionalActionProperties = new StringBuilder(); + if (!string.IsNullOrEmpty(action.Attributes["tooltip"].Value)){ + additionalActionProperties.AppendLine($" Tooltip = '{EscapeALTextString(action.Attributes["tooltip"].Value)}';"); + } + if (action.Attributes["obsolete"].Value.Length > 0) + { + var indentationInAction = " "; + additionalActionProperties.AppendFormat(Encoding.UTF8.GetString(Resources.ObsoletePropertiesTemplate), + indentationInAction, + EscapeALTextString(action.Attributes["obsolete"].Value) + ); + additionalActionProperties.AppendLine(); + additionalActionProperties.AppendLine(indentationInAction + "Visible = false;"); + } + sb.AppendFormat(Encoding.UTF8.GetString(Resources.RoleCenterActionTemplate), + action.Attributes["name"].Value, // 0 + EscapeALTextString(action.Attributes["caption"].Value), // 1 + action.Attributes["pbipagename"].Value, // 2 + additionalActionProperties // 3 + ); + if (action.Attributes["obsolete"].Value.Length > 0) + { + sb.AppendLine("#endif"); + } } - public static string GeneratePBIEmbedPageCode(string alNamespace, XmlNode query, Version version) { StringBuilder sb = new StringBuilder(); - string context = query.Attributes["id"].Value + "-" + query.Attributes["name"].Value; - - /* - // Auto-generated al file for PBI embed page - // - // Adding a PBI embed page for this PBI content: - // PBI ReportId = '' - // PBI ReportName = '' - - namespace Microsoft.PowerBIApps - - page "" + StringBuilder additionalProperties = new StringBuilder(); + if (query.Attributes["obsolete"].Value.Length > 0) { - UsageCategory = ReportsAndAnalysis; - Caption = ''; - AboutTitle = ''; - AboutText = ''; - - layout - { - area(Content) - { - part(EmbeddedReport; "Power BI Embedded Report Part") - { - Caption = 'Financial Overview'; - SubPageView = where(Context = const('-')); - ApplicationArea = All; - } - } - } - */ - - sb.AppendLine("// Auto-generated al file for PBI embed page " + query.Attributes["id"].Value); - sb.AppendLine("// "); - sb.AppendLine("// Adding a PBI embed page for this PBI content:"); - sb.AppendLine("// PBI ReportId = '" + query.Attributes["PBIReportId"].Value); - sb.AppendLine("// PBI ReportName = '" + query.Attributes["PBIReportName"].Value); - sb.AppendLine(""); - - sb.AppendLine("namespace " + alNamespace); - sb.AppendLine(""); - - sb.AppendLine("page " + query.Attributes["id"].Value + " \"" + query.Attributes["name"].Value + "\""); - sb.AppendLine("{"); - - indentAppendLine(sb, 1, "UsageCategory = ReportsAndAnalysis;"); - indentAppendLine(sb, 1, "Caption = '" + query.Attributes["caption"].Value + "';"); - indentAppendLine(sb, 1, "AboutTitle = '" + query.Attributes["aboutTitle"].Value + "'; "); - indentAppendLine(sb, 1, "AboutText = '" + query.Attributes["aboutText"].Value + "'; "); - sb.AppendLine(""); - - indentAppendLine(sb, 1, "layout"); - indentAppendLine(sb, 1, "{"); - - indentAppendLine(sb, 2, "area(Content)"); - indentAppendLine(sb, 2, "{"); - - indentAppendLine(sb, 3, "part(EmbeddedReport; \"Power BI Embedded Report Part\")"); - indentAppendLine(sb, 3, "{"); - - indentAppendLine(sb, 4, "ApplicationArea = All;"); - indentAppendLine(sb, 4, "Caption = '" + query.Attributes["caption"].Value + "';"); - indentAppendLine(sb, 4, "SubPageView = where(Context = const ('" + context + "'));"); - - indentAppendLine(sb, 3, "}"); - - indentAppendLine(sb, 2, "}"); - - indentAppendLine(sb, 1, "}"); - sb.AppendLine(""); - - /* - trigger OnOpenPage() - var - PowerBIDisplayedElement: Record "Power BI Displayed Element"; - PowerBIServiceMgt: Codeunit "Power BI Service Mgt."; - begin - EnsureUserAcceptedPowerBITerms(); - - // Cleanup previously added reports for this context - PowerBIDisplayedElement.SetRange(Context, vContext); - PowerBIDisplayedElement.DeleteAll(); - PowerBIDisplayedElement.SetRange(Context); - - // Add the report - PowerBIServiceMgt.AddReportForContext(vReportId, vContext); - - // Customize page and other settings - PowerBIDisplayedElement.Get(UserSecurityId(), vContext, PowerBIDisplayedElement.MakeReportKey(vReportId), - PowerBIDisplayedElement.ElementType::Report); - PowerBIDisplayedElement.ReportPage := vReportPage; - PowerBIDisplayedElement.ShowPanesInExpandedMode := true; - PowerBIDisplayedElement.ShowPanesInNormalMode := true; - PowerBIDisplayedElement.Modify(); - - CurrPage.EmbeddedReport.Page.SetFullPageMode(true); - end; - */ - indentAppendLine(sb, 1, "trigger OnOpenPage()"); - indentAppendLine(sb, 1, "var"); - - indentAppendLine(sb, 2, "PowerBIDisplayedElement: Record \"Power BI Displayed Element\";"); - indentAppendLine(sb, 2, "PowerBIServiceMgt: Codeunit \"Power BI Service Mgt.\";"); - - indentAppendLine(sb, 1, "begin"); - - indentAppendLine(sb, 2, "EnsureUserAcceptedPowerBITerms();"); - sb.AppendLine(""); - indentAppendLine(sb, 2, "// Cleanup previously added reports for this context"); - indentAppendLine(sb, 2, "PowerBIDisplayedElement.SetRange(Context, vContext);"); - indentAppendLine(sb, 2, "PowerBIDisplayedElement.DeleteAll();"); - indentAppendLine(sb, 2, "PowerBIDisplayedElement.SetRange(Context);"); - sb.AppendLine(""); - indentAppendLine(sb, 2, "// Add the report"); - indentAppendLine(sb, 2, "PowerBIServiceMgt.AddReportForContext(vReportId, vContext);"); - sb.AppendLine(""); - indentAppendLine(sb, 2, "// Customize page and other settings"); - indentAppendLine(sb, 2, "PowerBIDisplayedElement.Get(UserSecurityId(), vContext, PowerBIDisplayedElement.MakeReportKey(vReportId), PowerBIDisplayedElement.ElementType::Report);"); - indentAppendLine(sb, 2, "PowerBIDisplayedElement.ReportPage := vReportPage;"); - indentAppendLine(sb, 2, "PowerBIDisplayedElement.ShowPanesInExpandedMode := true;"); - indentAppendLine(sb, 2, "PowerBIDisplayedElement.ShowPanesInNormalMode := true;"); - indentAppendLine(sb, 2, "PowerBIDisplayedElement.Modify();"); - sb.AppendLine(""); - - if (version == new Version() | version >= new Version("24.2")) - { - indentAppendLine(sb, 2, "CurrPage.EmbeddedReport.Page.SetFullPageMode(true);"); + var indentationInAction = " "; + sb.AppendLine($"#if not CLEAN{query.Attributes["obsolete"].Value}"); + additionalProperties.AppendFormat(Encoding.UTF8.GetString(Resources.ObsoletePropertiesTemplate), + indentationInAction, + EscapeALTextString(query.Attributes["obsolete"].Value) + ); } - indentAppendLine(sb, 1, "end;"); - sb.AppendLine(""); - - /* - local procedure EnsureUserAcceptedPowerBITerms() - var - PowerBIContextSettings: Record "Power BI Context Settings"; - PowerBIEmbedSetupWizard: Page "Power BI Embed Setup Wizard"; - begin - PowerBIContextSettings.SetRange(UserSID, UserSecurityId()); - if PowerBIContextSettings.IsEmpty() then begin - PowerBIEmbedSetupWizard.SetContext(vContext); - if PowerBIEmbedSetupWizard.RunModal() <> Action::OK then; - - if PowerBIContextSettings.IsEmpty() then - Error(PowerBiNotSetupErr); - end; - - PowerBIContextSettings.CreateOrReadForCurrentUser(vContext); - if not PowerBIContextSettings.LockToSelectedElement then begin - PowerBIContextSettings.LockToSelectedElement := true; - PowerBIContextSettings.Modify(); - end; - end; - */ - indentAppendLine(sb, 1, "local procedure EnsureUserAcceptedPowerBITerms()"); - indentAppendLine(sb, 1, "var"); - - indentAppendLine(sb, 2, "PowerBIContextSettings: Record \"Power BI Context Settings\";"); - indentAppendLine(sb, 2, "PowerBIEmbedSetupWizard: Page \"Power BI Embed Setup Wizard\";"); - - indentAppendLine(sb, 1, "begin"); - - indentAppendLine(sb, 2, "PowerBIContextSettings.SetRange(UserSID, UserSecurityId());"); - indentAppendLine(sb, 2, "if PowerBIContextSettings.IsEmpty() then begin"); - - indentAppendLine(sb, 3, "PowerBIEmbedSetupWizard.SetContext(vContext);"); - indentAppendLine(sb, 3, "if PowerBIEmbedSetupWizard.RunModal() <> Action::OK then;"); - sb.AppendLine(""); - indentAppendLine(sb, 3, "if PowerBIContextSettings.IsEmpty() then"); - - indentAppendLine(sb, 4, "Error(PowerBiNotSetupErr);"); - - indentAppendLine(sb, 2, "end;"); - sb.AppendLine(""); - indentAppendLine(sb, 2, "PowerBIContextSettings.CreateOrReadForCurrentUser(vContext);"); - indentAppendLine(sb, 2, "if not PowerBIContextSettings.LockToSelectedElement then begin"); - - indentAppendLine(sb, 3, "PowerBIContextSettings.LockToSelectedElement := true;"); - indentAppendLine(sb, 3, "PowerBIContextSettings.Modify();"); - - indentAppendLine(sb, 2, "end;"); - - indentAppendLine(sb, 1, "end;"); - sb.AppendLine(""); - - /* - var - PowerBiNotSetupErr: Label 'Power BI is not set up. You need to set up Power BI in order to see this report.'; - vReportId: Label '', Locked = true; - vReportPage: Label '', Locked = true; - vContext: Label '-', MaxLength = 30, Locked = true, Comment = 'IMPORTANT: keep it unique across pages. Also, make sure this value is the same used in the SubPageView above.'; - */ - indentAppendLine(sb, 1, "var"); - - indentAppendLine(sb, 2, "PowerBiNotSetupErr: Label 'Power BI is not set up. You need to set up Power BI in order to see this report.';"); - indentAppendLine(sb, 2, "vReportId: Label '" + query.Attributes["PBIReportId"].Value + "', Locked = true;"); - indentAppendLine(sb, 2, "vReportPage: Label '" + query.Attributes["PBIReportPage"].Value + "', Locked = true;"); - indentAppendLine(sb, 2, "vContext: Label '" + context + "', MaxLength = 30, Locked = true, Comment = 'IMPORTANT: keep it unique across pages. Also, make sure this value is the same used in the SubPageView above.';"); + var applicationArea = query.Attributes["applicationArea"].Value.Length > 0 ? query.Attributes["applicationArea"].Value : "All" ; - sb.AppendLine(""); - sb.AppendLine("}"); - + sb.AppendFormat(Encoding.UTF8.GetString(Resources.ReportPageTemplate), + alNamespace, // 0 + query.Attributes["id"].Value, // 1 + query.Attributes["name"].Value, // 2 + EscapeALTextString(query.Attributes["caption"].Value), // 3 + EscapeALTextString(query.Attributes["aboutTitle"].Value), // 4 + EscapeALTextString(query.Attributes["aboutText"].Value), // 5 + query.Attributes["PBIReportPage"].Value, // 6 + query.Attributes["PBIReportIdFieldName"].Value, // 7 + additionalProperties, // 8 + applicationArea // 9 + ); + if (query.Attributes["obsolete"].Value.Length > 0) + { + sb.AppendLine("#endif"); + } return sb.ToString(); } public static string GeneratePBIEmbedPagePerm(string alNamespace, XmlNode permSet, XmlNode pages) { - StringBuilder sb = new StringBuilder(); - - /* - // Auto-generated al file for PBI permissions 50120 - - namespace Microsoft.PowerBIApps - - permissionset 50120 "Power BI Finance App - Objects" - { - Access = Internal; - Assignable = false; - Permissions = - page "PBIFinancialOverview" = X, - page "PBIIncomeStatementbyMonth" = X, - page "PBIBalanceSheetbyMonth" = X, - page "PBIBudgetComparison" = X, - page "PBILiquidityKPIs" = X, - page "PBIProfitability" = X, - } - */ - - indentAppendLine(sb, 0, "// Auto-generated al file for PBI permissions " + permSet.Attributes["id"].Value); - indentAppendLine(sb, 0, ""); - indentAppendLine(sb, 0, "namespace " + alNamespace); - indentAppendLine(sb, 0, ""); - indentAppendLine(sb, 0, "permissionset " + permSet.Attributes["id"].Value + " \"" + permSet.Attributes["name"].Value + "\""); - indentAppendLine(sb, 0, "{"); - indentAppendLine(sb, 1, "Access = Internal;"); - indentAppendLine(sb, 1, "Assignable = false;"); - indentAppendLine(sb, 1, "Permissions ="); - + StringBuilder pageStringBuilder = new StringBuilder(); foreach (XmlNode page in pages.SelectNodes("page")) { - indentAppendLine(sb, 2, "page \"" + page.Attributes["name"].Value + "\" = X,"); + if (page.Attributes["name"].Value == pages.LastChild.Attributes["name"].Value) + { + pageStringBuilder.AppendLine(" page \"" + page.Attributes["name"].Value + "\" = X;"); + } + else + { + if (page.NextSibling.Attributes["obsolete"].Value.Length > 0 && page.NextSibling.Attributes["name"].Value == pages.LastChild.Attributes["name"].Value) + { + pageStringBuilder.AppendLine($"#if not CLEAN{page.NextSibling.Attributes["obsolete"].Value}"); + pageStringBuilder.AppendLine(" page \"" + page.Attributes["name"].Value + "\" = X,"); + pageStringBuilder.AppendLine("#pragma warning disable AL0432"); + pageStringBuilder.AppendLine(" page \"" + page.NextSibling.Attributes["name"].Value + "\" = X;"); + pageStringBuilder.AppendLine("#pragma warning restore AL0432"); + pageStringBuilder.AppendLine("#else"); + pageStringBuilder.AppendLine(" page \"" + page.Attributes["name"].Value + "\" = X;"); + pageStringBuilder.AppendLine("#endif"); + break; + } + + if (page.Attributes["obsolete"].Value.Length > 0) + { + pageStringBuilder.AppendLine($"#if not CLEAN{page.Attributes["obsolete"].Value}"); + pageStringBuilder.AppendLine("#pragma warning disable AL0432"); + } + pageStringBuilder.AppendLine(" page \"" + page.Attributes["name"].Value + "\" = X,"); + if (page.Attributes["obsolete"].Value.Length > 0) + { + pageStringBuilder.AppendLine("#pragma warning restore AL0432"); + pageStringBuilder.AppendLine("#endif"); + } + } } - indentAppendLine(sb, 0, "}"); + StringBuilder sb = new StringBuilder(); + + sb.AppendFormat(Encoding.UTF8.GetString(Resources.PermissionSetTemplate), + alNamespace, // 0 + permSet.Attributes["id"].Value, // 1 + permSet.Attributes["name"].Value, // 2 + pageStringBuilder.ToString() // 3 + ); return sb.ToString(); } + public static string EscapeALTextString(string s) + { + return s.Replace("'", "''"); + } + // https://epsicodecom.wordpress.com/2019/08/12/tutorial-generate-seperate-files-from-a-t4-template/ public static void SaveFile(string folder, string fileName, string content) { diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources.Designer.cs b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources.Designer.cs new file mode 100644 index 00000000..6a95b471 --- /dev/null +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources.Designer.cs @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PBIEmbedGenerator.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PBIEmbedGenerator.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] ObsoletePropertiesTemplate { + get { + object obj = ResourceManager.GetObject("ObsoletePropertiesTemplate", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] PermissionSetTemplate { + get { + object obj = ResourceManager.GetObject("PermissionSetTemplate", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] ReportPageTemplate { + get { + object obj = ResourceManager.GetObject("ReportPageTemplate", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] RoleCenterActionTemplate { + get { + object obj = ResourceManager.GetObject("RoleCenterActionTemplate", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] RoleCenterExtensionTemplate { + get { + object obj = ResourceManager.GetObject("RoleCenterExtensionTemplate", resourceCulture); + return ((byte[])(obj)); + } + } + } +} diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources.resx b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources.resx new file mode 100644 index 00000000..5cb0b27a --- /dev/null +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Resources\PermissionSetTemplate.txt;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Resources\ReportPageTemplate.txt;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Resources\RoleCenterActionTemplate.txt;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Resources\RoleCenterExtensionTemplate.txt;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Resources\ObsoleteProperties.txt;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/ObsoleteProperties.txt b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/ObsoleteProperties.txt new file mode 100644 index 00000000..7e4f6347 --- /dev/null +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/ObsoleteProperties.txt @@ -0,0 +1,3 @@ +{0}ObsoleteState = Pending; +{0}ObsoleteReason = 'The Power BI report has been changed/removed and this is no longer required.'; +{0}ObsoleteTag = '{1}.0'; \ No newline at end of file diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/PermissionSetTemplate.txt b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/PermissionSetTemplate.txt new file mode 100644 index 00000000..bc5c1a9d --- /dev/null +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/PermissionSetTemplate.txt @@ -0,0 +1,8 @@ +namespace {0}; + +permissionset {1} "{2}" +{{ + Access = Internal; + Assignable = false; + Permissions = +{3}}} diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/ReportPageTemplate.txt b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/ReportPageTemplate.txt new file mode 100644 index 00000000..8a0183e6 --- /dev/null +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/ReportPageTemplate.txt @@ -0,0 +1,51 @@ +namespace {0}; + +using System.Integration.PowerBI; + +page {1} "{2}" +{{ + UsageCategory = ReportsAndAnalysis; + ApplicationArea = {9}; +#pragma warning disable AS0035 // Changed from Card to UserControlHost + PageType = UserControlHost; +#pragma warning restore AS0035 + Caption = '{3}'; + AboutTitle = '{4}'; + AboutText = '{5}'; +{8} + layout + {{ + area(Content) + {{ + usercontrol(PowerBIAddin; PowerBIManagement) + {{ + ApplicationArea = All; + + trigger ControlAddInReady() + begin + SetupHelper.InitializeEmbeddedAddin(CurrPage.PowerBIAddin, ReportId, ReportPageLbl); + end; + + trigger ErrorOccurred(Operation: Text; ErrorText: Text) + begin + SetupHelper.ShowPowerBIErrorNotification(Operation, ErrorText); + end; + }} + }} + }} + + var + SetupHelper: Codeunit "Setup Helper"; + ReportId: Guid; +#pragma warning disable AA0240 + ReportPageLbl: Label '{6}', Locked = true; +#pragma warning restore AA0240 + + trigger OnOpenPage() + var + PowerBIReportsSetup: Record "PowerBI Reports Setup"; + begin + SetupHelper.EnsureUserAcceptedPowerBITerms(); + ReportId := SetupHelper.GetReportIdAndEnsureSetup(CurrPage.Caption(), PowerBIReportsSetup.FieldNo("{7}")); + end; +}} diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/RoleCenterActionTemplate.txt b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/RoleCenterActionTemplate.txt new file mode 100644 index 00000000..6034684d --- /dev/null +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/RoleCenterActionTemplate.txt @@ -0,0 +1,7 @@ + action("{0}") + {{ + ApplicationArea = Basic, Suite; + Caption = '{1}'; + Image = "PowerBI"; + RunObject = page "{2}"; +{3} }} diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/RoleCenterExtensionTemplate.txt b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/RoleCenterExtensionTemplate.txt new file mode 100644 index 00000000..05ac1252 --- /dev/null +++ b/samples/PowerBi/EmbedYourPBIApp/PBIEmbedGenerator/Properties/Resources/RoleCenterExtensionTemplate.txt @@ -0,0 +1,19 @@ +namespace {0}; + +using {1}; + +pageextension {2} "{3}" extends "{4}" +{{ + actions + {{ + {5} + {{ + group("PBI Reports") + {{ + Caption = 'Power BI Reports'; + Image = {6}; + ToolTip = '{7}'; +{8} }} + }} + }} +}} diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/ActionDefinition.cs b/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/ActionDefinition.cs index 4b31d542..f13803e3 100644 --- a/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/ActionDefinition.cs +++ b/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/ActionDefinition.cs @@ -9,14 +9,16 @@ internal class ActionDefinition string caption { get; set; } string pbipagename { get; set; } string tooltip { get; set; } + string obsolete { get; set; } - public ActionDefinition(string rcExtenionName, string name, string caption, string pbipagename, string tooltip) + public ActionDefinition(string rcExtenionName, string name, string caption, string pbipagename, string tooltip, string obsolete) { this.rcExtensionName = rcExtenionName; this.name = name; this.caption = caption; this.pbipagename = pbipagename; this.tooltip = tooltip; + this.obsolete = obsolete; } public XElement asXElement() @@ -25,7 +27,8 @@ public XElement asXElement() new XAttribute("name", name), new XAttribute("caption", caption), new XAttribute("pbipagename", pbipagename), - new XAttribute("tooltip", tooltip) + new XAttribute("tooltip", tooltip), + new XAttribute("obsolete", obsolete) ); return action; diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/PBIPageDefinition.cs b/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/PBIPageDefinition.cs index dc540d6f..d4a9e896 100644 --- a/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/PBIPageDefinition.cs +++ b/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/PBIPageDefinition.cs @@ -18,13 +18,16 @@ internal class PBIPageDefinition string caption { get; set; } string aboutTitle { get; set; } string aboutText { get; set; } - string PBIReportId { get; set; } + string PBIReportIdFieldName { get; set; } string PBIReportName { get; set; } string PBIReportPage { get; set; } + string obsolete { get; set; } + string applicationArea { get; set; } public PBIPageDefinition( - string id, string name, string fileName, string caption, string aboutTitle - , string aboutText, string PBIReportId, string PBIReportName, string PBIReportPage + string id, string name, string fileName, string caption, string aboutTitle, + string aboutText, string PBIReportId, string PBIReportName, string PBIReportPage, + string obsolete, string applicationArea ) { this.id = id; @@ -33,9 +36,11 @@ public PBIPageDefinition( this.caption = caption; this.aboutTitle = aboutTitle; this.aboutText = aboutText; - this.PBIReportId = PBIReportId; + this.PBIReportIdFieldName = PBIReportId; this.PBIReportName = PBIReportName; this.PBIReportPage = PBIReportPage; + this.obsolete = obsolete; + this.applicationArea = applicationArea; } @@ -48,9 +53,11 @@ public XElement asXElement() new XAttribute("caption", caption), new XAttribute("aboutTitle", aboutTitle), new XAttribute("aboutText", aboutText), - new XAttribute("PBIReportId", PBIReportId), + new XAttribute("PBIReportIdFieldName", PBIReportIdFieldName), new XAttribute("PBIReportName", PBIReportName), - new XAttribute("PBIReportPage", PBIReportPage) + new XAttribute("PBIReportPage", PBIReportPage), + new XAttribute("obsolete", obsolete), + new XAttribute("applicationArea", applicationArea) ); return page; diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/Program.cs b/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/Program.cs index 66279ede..fbf9ffa9 100644 --- a/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/Program.cs +++ b/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/Program.cs @@ -1,20 +1,8 @@ -using System; -using System.Xml; -using System.Text; -using System.IO; +using DocumentFormat.OpenXml.Packaging; +using DocumentFormat.OpenXml.Spreadsheet; using Mono.Options; -using System.Collections.Generic; -using System.Reflection.Metadata; -using static System.Runtime.InteropServices.JavaScript.JSType; -using System.Xml.Serialization; +using System.Text.RegularExpressions; using System.Xml.Linq; -using System.Collections.ObjectModel; -using CsvHelper; -using System.Globalization; -using CsvHelper.Configuration; -using DocumentFormat.OpenXml.Packaging; -using DocumentFormat.OpenXml.Spreadsheet; -using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing; namespace PayloadGenerator @@ -77,9 +65,9 @@ static void Main(string[] args) } Console.WriteLine("Worksheet '{0}'. Found : {1} rows", NamespaceSheetName, NamespaceRows.Count.ToString()); string ALNamespace = ""; - if (NamespaceRows.Count >= 2 && NamespaceRows[1].Length > 0) + if (NamespaceRows.Count >= 1 && NamespaceRows[0].Length > 0) { - ALNamespace = NamespaceRows[1][0]; + ALNamespace = NamespaceRows[0][0]; } var PBIReportsSheetName = "PBIReports"; @@ -122,17 +110,9 @@ static void Main(string[] args) if (outputfile.Equals("")) { Console.WriteLine("Output file parameter required."); - Environment.Exit(0); - } - - - if (outputdir.Equals("")) - { - outputdir = System.IO.Directory.GetCurrentDirectory(); + Environment.Exit(-1); } Console.WriteLine("Using directory for output files: " + outputdir); - - Console.WriteLine("Generating payload file..."); XDocument payloaddoc = GeneratePayload(ALNamespace, pages, rcExtensions, permSets); @@ -216,18 +196,39 @@ static private List readExcelWorksheet(string inputfile, string worksh var sheet = workbookPart.Workbook.Descendants().FirstOrDefault(s => s.Name == worksheetName); var worksheetPart = (WorksheetPart)(workbookPart.GetPartById(sheet.Id)); var sheetData = worksheetPart.Worksheet.Elements().First(); + var columnRefs = new List(); + var regex = new Regex("\\d+"); foreach (var row in sheetData.Elements()) { - List cells = new List(); - - foreach (var cell in row.Elements()) + if (row.RowIndex == 1) + { + foreach (var cell in row.Elements()) + { + columnRefs.Add(regex.Replace(cell.CellReference, "")); + } + } + else { - cells.Add(GetCellValue(cell, workbookPart)); + List cells = new List(); + + foreach(var columnRef in columnRefs) + { + var query = row.Elements().Where(cell => regex.Replace(cell.CellReference, "") == columnRef).FirstOrDefault(); + + if (query == null) + { + cells.Add(""); + } + else + { + cells.Add(GetCellValue(query, workbookPart)); + } + } + + var cellArray = cells.ToArray(); + rows.Add(cellArray); } - - var cellArray = cells.ToArray(); - rows.Add(cellArray); } } return rows; @@ -246,8 +247,10 @@ static private void ExcelRowstoPBIPageDefinitions(List PBIReportRows, row[5], row[6], row[7], - row[8] - ); + row[8], + row[9], + row[10] + ); if (!row[0].Equals("id")) { @@ -267,7 +270,9 @@ static private void ExcelRowstoRCExtensionDefinitions(List RCExtension row[2], row[3], row[4], - row[5] + row[5], + row[6], + row[7] ); if (!row[0].Equals("id")) @@ -287,7 +292,8 @@ static private void ExcelRowstoRCExtensionActionDefinitions(List RCExt row[1], row[2], row[3], - row[4] + row[4], + row[5] ); if (!row[0].Equals("rcextensionname")) diff --git a/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/RCExtensionDefinition.cs b/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/RCExtensionDefinition.cs index 485ede42..240f91aa 100644 --- a/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/RCExtensionDefinition.cs +++ b/samples/PowerBi/EmbedYourPBIApp/PBIPayloadGenerator/RCExtensionDefinition.cs @@ -16,6 +16,8 @@ internal class RCExtensionDefinition string extends{ get; set; } string where { get; set; } string tooltip { get; set; } + string rolecenternamespace { get; set; } + string image { get; set; } //id = "50140" //name = "BusinessManagerRoleCenterExt" @@ -36,7 +38,9 @@ public RCExtensionDefinition( string filename, string extends, string where, - string tooltip + string tooltip, + string rolecenternamespace, + string image ) { this.id = id; @@ -45,6 +49,8 @@ string tooltip this.extends = extends; this.where = where; this.tooltip = tooltip; + this.rolecenternamespace = rolecenternamespace; + this.image = image; } @@ -56,7 +62,9 @@ public XElement asXElement() new XAttribute("filename", filename), new XAttribute("extends", extends), new XAttribute("where", where), - new XAttribute("tooltip", tooltip) + new XAttribute("tooltip", tooltip), + new XAttribute("rolecenternamespace", rolecenternamespace), + new XAttribute("image", image) ); foreach(ActionDefinition action in actions)