{"id":28057,"date":"2019-11-06T00:00:00","date_gmt":"2019-11-05T23:00:00","guid":{"rendered":"https:\/\/blexin.com\/?p=28057"},"modified":"2021-01-13T09:40:22","modified_gmt":"2021-01-13T08:40:22","slug":"creare-report-con-open-xml-sdk","status":"publish","type":"post","link":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/","title":{"rendered":"Creare report con Open XML SDK"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" data-attachment-id=\"28058\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/attachment\/ab37f718-0d69-4960-9b90-8eb7ff437b53\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&amp;ssl=1\" data-orig-size=\"1024,608\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"ab37f718-0d69-4960-9b90-8eb7ff437b53\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?resize=1024%2C608&#038;ssl=1\" alt=\"\" class=\"wp-image-28058\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png 1024w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53-980x582.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53-480x285.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Nell&#8217;ambito delle nostre attivit\u00e0 di sviluppo, sia per clienti che per progetti interni, ci siamo spesso trovati di fronte alla necessit\u00e0 di creare report contenenti dati di diversa natura. Il formato che di solito utilizziamo &#8211; e anche il pi\u00f9 richiesto &#8211; per tali report \u00e8 sicuramente Office Open XML, che viene letto ed elaborato dai software per fogli di calcolo delle principali suite di office e che assicura qualit\u00e0 e leggerezza del documento.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nel mondo&nbsp;<em>.NET<\/em>&nbsp;esistono diversi plugin di terze parti che ci consentono di creare file Office Open XML. Dopo averne testati diversi, abbiamo deciso di optare per Open XML SDK, che ci \u00e8 sembrata la migliore scelta in termini di funzionalit\u00e0, di performance e di configurabilit\u00e0, e, non ultimo, poich\u00e9 consente l&#8217;utilizzo nativo del formato Office Open XML<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Alcune note su Office Open XML<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Il formato Office Open XML \u00e8 uno standard per documenti di testo, presentazioni e fogli di calcolo, che pu\u00f2 essere implementato da pi\u00f9 applicazioni su piattaforme differenti. Lo scopo principale del formato Open XML \u00e8 quello di disaccoppiare l&#8217;informazione dal software col quale viene creato senza perdere dati. Un file Open XML \u00e8 strutturato naturalmente in un file di testo creato con markup XML conservato in un archivio ZIP ed \u00e8 costituito da pi\u00f9 parti, a seconda della tipologia di documento.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nel caso dei fogli di calcolo, il documento Open XML pu\u00f2 contenere al suo interno:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Sezioni del documento (obbligatoria)<\/li><li>Uno o pi\u00f9 fogli di lavoro<\/li><li>Grafici<\/li><li>Tabelle<\/li><li>XML personalizzato<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Open XML SDK<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Open XML SDK \u00e8 una libreria open source, rilasciata sotto licenza Apache 2.0 da Microsoft per gli sviluppatori, che fornisce una serie di namespace e membri a supporto dei pi\u00f9 comuni software di office, tra cui naturalmente Microsoft Office.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La documentazione ufficiale \u00e8 disponibile al link:&nbsp;<a href=\"https:\/\/docs.microsoft.com\/en-us\/office\/open-xml\/open-xml-sdk\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/docs.microsoft.com\/en-us\/office\/open-xml\/open-xml-sdk<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creazione del documento<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Nell&#8217;esempio di seguito, abbiamo riportato uno scenario reale riguardante la creazione del report dei prodotti di uno store.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Abbiamo aggiunto una classe chiamata\u00a0<em>ColumnAttribute<\/em>, derivata da una classe base\u00a0<em>Attribute<\/em>, che serve a definire una serie di metadati relativi alla singola colonna. Tale annotazione verr\u00e0 aggiunta alle singole propriet\u00e0 della classe su cui sar\u00e0 basato il report.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/\/ &lt;summary &gt;\n\/\/\/ ColumnAttribute:\n\/\/\/ Inherits from System.Attribute class\n\/\/\/ &lt;\/summary &gt;\npublic class ColumnAttribute : Attribute\n{\n\u00a0\u00a0\u00a0\u00a0\/\/ column name\n\u00a0\u00a0\u00a0\u00a0public string Name { get; set; }\n\u00a0\u00a0\u00a0\u00a0\/\/ is it a date?\n\u00a0\u00a0\u00a0\u00a0&#x5B;DefaultValue(false)]\n\u00a0\u00a0\u00a0\u00a0public bool IsDate { get; set; }\u00a0\u00a0 \n\u00a0\u00a0\u00a0\u00a0\/\/ is it a time?\n\u00a0\u00a0\u00a0\u00a0&#x5B;DefaultValue(false)]\n\u00a0\u00a0\u00a0\u00a0public bool IsTime { get; set; }\n\u00a0\u00a0\u00a0\u00a0\/\/ is it a currency?\n\u00a0\u00a0\u00a0\u00a0&#x5B;DefaultValue(false)]\n\u00a0\u00a0\u00a0\u00a0public bool IsCurrency { get; set; }\n\u00a0\u00a0\u00a0\u00a0\/\/ is it a percentage?\n\u00a0\u00a0\u00a0\u00a0&#x5B;DefaultValue(false)]\n\u00a0\u00a0\u00a0\u00a0public bool IsPercentage { get; set; }\n\u00a0\u00a0\u00a0\u00a0\/\/ has it a width based on content?\n\u00a0\u00a0\u00a0\u00a0&#x5B;DefaultValue(false)]\n\u00a0\u00a0\u00a0\u00a0public bool AutoSize { get; set; }\n\u00a0\u00a0\u00a0\u00a0\/\/ has it to be sorted?\n\u00a0\u00a0\u00a0\u00a0\/\/ Sort: -1 descending, 0 none, 1 ascending\n\u00a0\u00a0\u00a0\u00a0&#x5B;DefaultValue(0)]\n\u00a0\u00a0\u00a0\u00a0public int Sort { get; set; }\n\u00a0\u00a0\u00a0\u00a0\/\/ custom style index\n\u00a0\u00a0\u00a0\u00a0public uint StyleIndex { get; set; }\n}\n\u00a0\npublic class Product\n{\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Id&quot;)]\n\u00a0\u00a0\u00a0\u00a0public int Id { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Ean&quot;)]\n\u00a0\u00a0\u00a0\u00a0public string Ean { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Name&quot;, AutoSize = true, Sort = 1)]\n\u00a0\u00a0\u00a0\u00a0public string Name { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Description&quot;)]\n\u00a0\u00a0\u00a0\u00a0public string Description { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Brand&quot;, AutoSize = true)]\n\u00a0\u00a0\u00a0\u00a0public string Brand { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Category&quot;, AutoSize = true)]\n\u00a0\u00a0\u00a0\u00a0public string Category { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Price&quot;, IsCurrency = true)]\n\u00a0\u00a0\u00a0\u00a0public decimal Price { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Quantity&quot;)]\n\u00a0\u00a0\u00a0\u00a0public int Quantity { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;Rating&quot;, IsPercentage = true)]\n\u00a0\u00a0\u00a0\u00a0public decimal Rating { get; set; }\n\u00a0\u00a0\u00a0\u00a0&#x5B;Column(Name = &quot;ReleaseDate&quot;, IsDate = true)]\n\u00a0\u00a0\u00a0\u00a0public DateTime ReleaseDate { get; set; }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">I campi che non hanno l\u2019annotation&nbsp;<strong>ColumnAttribute<\/strong>&nbsp;vengono ignorati dall\u2019export.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per centralizzare la creazione dei fogli di calcolo Office Open XML abbiamo invece realizzato la classe\u00a0<em>OpenXMLProvider<\/em>, che ci fornisce un metodo generico\u00a0<strong>GenerateWorksheet<\/strong>\u00a0che ci consente di prendere in input una lista di elementi, eventualmente escludere alcuni campi e definire il nome dello sheet principale.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class OpenXMLProvider\n{\n\u00a0\u00a0\u00a0\u00a0public byte&#x5B;] File { get; private set; }\n\u00a0\n\u00a0\u00a0\u00a0\u00a0public void GenerateWorksheet&lt;T&gt; (IEnumerable&lt;T&gt; list, IEnumerable&lt;String&gt; fieldsToExclude = null, String name = &quot;Foglio 1&quot;)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0File = WorksheetUtilities.CreateGenericReport&lt;T&gt;(list, fieldsToExclude, name);\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Il core della nostra soluzione \u00e8 sicuramente la classe&nbsp;<em>OpenXMLWorksheetBuilder<\/em>, che ci consente di creare un foglio di calcolo Office Open XML scrivendo codice XML nativo all&#8217;interno dello sheet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prima di scrivere la lista dei nostri prodotti nel file, definiamo gli stili del file, tramite il metodo\u00a0<strong>GenerateWorkbookStylesPartContent<\/strong>. A prima vista pu\u00f2 sembrare un po&#8217; cervellotico, ma ci\u00f2 ci consentir\u00e0 di creare una lista di stili, formattazioni e formati da utilizzare nel nostro foglio di calcolo.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nprivate void GenerateWorkbookStylesPartContent(WorkbookStylesPart workbookStylesPart)\n{\n\u00a0\u00a0\u00a0\u00a0\/\/ Declaring stylesheet and main namespaces\n\u00a0\u00a0\u00a0\u00a0Stylesheet stylesheet = new Stylesheet() { MCAttributes = new MarkupCompatibilityAttributes() { Ignorable = &quot;x14ac&quot; } };\n\u00a0\u00a0\u00a0\u00a0stylesheet.AddNamespaceDeclaration(&quot;mc&quot;, &quot;http:\/\/schemas.openxmlformats.org\/markup-compatibility\/2006&quot;);\n\u00a0\u00a0\u00a0\u00a0stylesheet.AddNamespaceDeclaration(&quot;x14ac&quot;, &quot;http:\/\/schemas.microsoft.com\/office\/spreadsheetml\/2009\/9\/ac&quot;);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\/\/ Declaring customer number format:\n\u00a0\u00a0\u00a0\u00a0NumberingFormats numberingFormats = new NumberingFormats() { Count = 5U };\n\u00a0\u00a0\u00a0\u00a0NumberingFormat numberingFormatDateTime = new NumberingFormat() { NumberFormatId = 1U, FormatCode = &quot;dd\/mm\/yyyy\\\\ hh:mm;@&quot; };\n\u00a0\u00a0\u00a0\u00a0NumberingFormat numberingFormatCurrency = new NumberingFormat() { NumberFormatId = 2U, FormatCode = &quot;#,##0.00\\\\ \\&quot;\u20ac\\&quot;&quot; };\n\u00a0\u00a0\u00a0\u00a0NumberingFormat numberingFormatPercentage = new NumberingFormat() { NumberFormatId = 3U, FormatCode = &quot;###,000\\\\ \\&quot;%\\&quot;&quot; };\n\u00a0\u00a0\u00a0\u00a0NumberingFormat numberingFormatDate = new NumberingFormat() { NumberFormatId = 4U, FormatCode = &quot;dd\/mm\/yyyy;@&quot; };\n\u00a0\u00a0\u00a0\u00a0NumberingFormat numberingFormatTime = new NumberingFormat() { NumberFormatId = 5U, FormatCode = &quot;hh:mm;@&quot; };\n\u00a0\n\u00a0\u00a0\u00a0\u00a0numberingFormats.Append(numberingFormatDateTime);\n\u00a0\u00a0\u00a0\u00a0numberingFormats.Append(numberingFormatCurrency);\n\u00a0\u00a0\u00a0\u00a0numberingFormats.Append(numberingFormatPercentage);\n\u00a0\u00a0\u00a0\u00a0numberingFormats.Append(numberingFormatDate);\n\u00a0\u00a0\u00a0\u00a0numberingFormats.Append(numberingFormatTime);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\/\/ Declaring fonts:\n\u00a0\u00a0\u00a0\u00a0Fonts fonts = new Fonts() { Count = 2U, KnownFonts = true };\n\u00a0\n\u00a0\u00a0\u00a0\u00a0Font fontNormal = new Font(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new FontName() { Val = &quot;Calibri&quot; },\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new FontSize() { Val = _fontWidth }\n\u00a0\u00a0\u00a0\u00a0);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0Font fontWhiteBold = new Font(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new FontName() { Val = &quot;Calibri&quot; },\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new FontSize() { Val = _fontWidth },\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Bold(),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new Color() { Rgb = HexBinaryConverter(System.Drawing.Color.White) }\n\u00a0\u00a0\u00a0\u00a0);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0fonts.Append(fontNormal);\n\u00a0\u00a0\u00a0\u00a0fonts.Append(fontWhiteBold);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\/\/ Declaring cell filling:\n\u00a0\u00a0\u00a0\u00a0Fills fills = new Fills() { Count = 2U };\n\u00a0\n\u00a0\u00a0\u00a0\u00a0Fill fillNone = new Fill(new PatternFill() { PatternType = PatternValues.None });\n\u00a0\n\u00a0\u00a0\u00a0\u00a0Fill fillGray125 = new Fill(new PatternFill() { PatternType = PatternValues.Gray125 });\n\u00a0\n\u00a0\u00a0\u00a0\u00a0Fill fillDodgerBlue = new Fill(new PatternFill()\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0PatternType = PatternValues.Solid,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ForegroundColor = new ForegroundColor() { Rgb = HexBinaryConverter(System.Drawing.Color.DodgerBlue) }\n\u00a0\u00a0\u00a0\u00a0});\n\u00a0\n\u00a0\u00a0\u00a0\u00a0fills.Append(fillNone);\n\u00a0\u00a0\u00a0\u00a0fills.Append(fillGray125);\n\u00a0\u00a0\u00a0\u00a0fills.Append(fillDodgerBlue);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\/\/ Declaring borders:\n\u00a0\u00a0\u00a0\u00a0Borders borders = new Borders() { Count = 2U };\n\u00a0\n\u00a0\u00a0\u00a0\u00a0Border borderNone = new Border();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0Border borderFullThinGray = new Border(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new LeftBorder() { Style = BorderStyleValues.Thin, Color = new Color() { Rgb = HexBinaryConverter(System.Drawing.Color.Gray) } },\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new RightBorder() { Style = BorderStyleValues.Thin, Color = new Color() { Rgb = HexBinaryConverter(System.Drawing.Color.Gray) } },\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new TopBorder() { Style = BorderStyleValues.Thin, Color = new Color() { Rgb = HexBinaryConverter(System.Drawing.Color.Gray) } },\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0new BottomBorder() { Style = BorderStyleValues.Thin, Color = new Color() { Rgb = HexBinaryConverter(System.Drawing.Color.Gray) } }\n\u00a0\u00a0\u00a0\u00a0);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0borders.Append(borderNone);\n\u00a0\u00a0\u00a0\u00a0borders.Append(borderFullThinGray);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\/\/ Declaring cell formats\n\u00a0\u00a0\u00a0\u00a0CellFormats cellFormats = new CellFormats() { Count = 7U };\n\u00a0\n\u00a0\u00a0\u00a0\u00a0CellFormat cellFormatBase = new CellFormat() { FontId = 0U, FillId = 0U, BorderId = 0U };\n\u00a0\u00a0\u00a0\u00a0CellFormat cellFormatNormal = new CellFormat() { FontId = 0U, FillId = 0U, BorderId = 1U, FormatId = 0U, ApplyBorder = true };\n\u00a0\u00a0\u00a0\u00a0CellFormat cellFormatHeader = new CellFormat() { FontId = 1U, FillId = 2U, BorderId = 1U, FormatId = 0U, ApplyFont = true, ApplyFill = true, ApplyBorder = true, ApplyAlignment = true, Alignment = new Alignment() { Horizontal = HorizontalAlignmentValues.Center } };\n\u00a0\u00a0\u00a0\u00a0CellFormat cellFormatDate = new CellFormat() { NumberFormatId = 4U, FontId = 0U, FillId = 0U, BorderId = 1U, FormatId = 0U, ApplyNumberFormat = true, ApplyBorder = true };\n\u00a0\u00a0\u00a0\u00a0CellFormat cellFormatTime = new CellFormat() { NumberFormatId = 5U, FontId = 0U, FillId = 0U, BorderId = 1U, FormatId = 0U, ApplyNumberFormat = true, ApplyBorder = true };\n\u00a0\u00a0\u00a0\u00a0CellFormat cellFormatDateTime = new CellFormat() { NumberFormatId = 1U, FontId = 0U, FillId = 0U, BorderId = 1U, FormatId = 0U, ApplyNumberFormat = true, ApplyBorder = true };\n\u00a0\u00a0\u00a0\u00a0CellFormat cellFormatCurrency = new CellFormat() { NumberFormatId = 2U, FontId = 0U, FillId = 0U, BorderId = 1U, FormatId = 0U, ApplyNumberFormat = true, ApplyBorder = true, ApplyAlignment = true };\n\u00a0\u00a0\u00a0\u00a0CellFormat cellFormatPercentage = new CellFormat() { NumberFormatId = 3U, FontId = 0U, FillId = 0U, BorderId = 1U, FormatId = 0U, ApplyNumberFormat = true, ApplyBorder = true, ApplyAlignment = true };\n\u00a0\n\u00a0\u00a0\u00a0\u00a0cellFormats.Append(cellFormatBase);\n\u00a0\u00a0\u00a0\u00a0cellFormats.Append(cellFormatNormal);\n\u00a0\u00a0\u00a0\u00a0cellFormats.Append(cellFormatHeader);\n\u00a0\u00a0\u00a0\u00a0cellFormats.Append(cellFormatDate);\n\u00a0\u00a0\u00a0\u00a0cellFormats.Append(cellFormatTime);\n\u00a0\u00a0\u00a0\u00a0cellFormats.Append(cellFormatDateTime);\n\u00a0\u00a0\u00a0\u00a0cellFormats.Append(cellFormatCurrency);\n\u00a0\u00a0\u00a0\u00a0cellFormats.Append(cellFormatPercentage);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\/\/ Append all defined styles to worksheet\n\u00a0\u00a0\u00a0\u00a0stylesheet.Append(numberingFormats);\n\u00a0\u00a0\u00a0\u00a0stylesheet.Append(fonts);\n\u00a0\u00a0\u00a0\u00a0stylesheet.Append(fills);\n\u00a0\u00a0\u00a0\u00a0stylesheet.Append(borders);\n\u00a0\u00a0\u00a0\u00a0stylesheet.Append(cellFormats);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0workbookStylesPart.Stylesheet = stylesheet;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In questo metodo abbiamo definito, in ordine:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Foglio di calcolo e principali namespace<\/li><li>Formati numerici e date<\/li><li>Font<\/li><li>Colori di cella<\/li><li>Bordi<\/li><li>Formati di cella<\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">I formati di cella sono quelli che poi verranno utilizzati nella formattazione delle nostre celle. Nell&#8217;ordine in cui sono inseriti, i formati prendono un Id uint progressivo: il primo avr\u00e0 id 0U, il secondo 1U, ecc .<br>Una enum ci aiuta a semplificare nel nostro codice l\u2019accesso ai vari formati di cella disponibili<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic enum CustomStyles\n{\n\u00a0\u00a0\u00a0\u00a0Base = 0,\n\u00a0\u00a0\u00a0\u00a0Normal = 1,\n\u00a0\u00a0\u00a0\u00a0Header = 2,\n\u00a0\u00a0\u00a0\u00a0Date = 3,\n\u00a0\u00a0\u00a0\u00a0Time = 4,\n\u00a0\u00a0\u00a0\u00a0DateTime = 5,\n\u00a0\u00a0\u00a0\u00a0Currency = 6,\n\u00a0\u00a0\u00a0\u00a0Percentage = 7\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Una volta inseriti gli stili del nostro foglio, possiamo finalmente iniziare a scrivere i dati partendo dalle intestazioni delle colonne che inseriamo grazie al metodo CreateHeaderCell:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nprivate Cell CreateHeaderCell(PropertyInfo propertyInfo)\n{\n\u00a0\u00a0\u00a0\u00a0\/\/ Get custom ColumnAttribute from PropertyInfo object\n\u00a0\u00a0\u00a0\u00a0var columnAttribute = propertyInfo.GetColumnAttribute();\n\u00a0\u00a0\u00a0\u00a0Cell cell = new Cell();\n\u00a0\u00a0\u00a0\u00a0cell.DataType = CellValues.String;\n\u00a0\u00a0\u00a0\u00a0cell.StyleIndex = columnAttribute.StyleIndex &gt; 0 ? columnAttribute.StyleIndex : (uint)CustomStyles.Header;\n\u00a0\u00a0\u00a0\u00a0cell.CellValue = new CellValue(columnAttribute.Name.ToUpperInvariant());\n\u00a0\u00a0\u00a0\u00a0return cell;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Per le celle contenenti i dati, invece, abbiamo creato un metodo generico chiamato\u00a0<strong>CreateContentCell<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nprivate Cell CreateContentCell &lt;T &gt; (T element, PropertyInfo propertyInfo)\n{\n\u00a0\u00a0\u00a0\u00a0\/\/ Get custom ColumnAttribute from PropertyInfo object\n\u00a0\u00a0\u00a0\u00a0var columnAttribute = propertyInfo.GetColumnAttribute();\n\u00a0\u00a0\u00a0\u00a0var value = propertyInfo.GetValue(element, null);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0Cell cell = new Cell();\n\u00a0\u00a0\u00a0\u00a0CellValues dataType = CellValues.String;\n\u00a0\u00a0\u00a0\u00a0String text = String.Empty;\n\u00a0\u00a0\u00a0\u00a0uint style = (uint)CustomStyles.Normal;\n\u00a0\u00a0\u00a0\u00a0if (value == null)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0else if (value is DateTime?)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dataType = CellValues.Number;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text = (value as DateTime?).Value.ToOADate().ToString(CultureInfo.InvariantCulture);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (columnAttribute.IsDate)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0style = (uint)CustomStyles.Date;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else if (columnAttribute.IsTime)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0style = (uint)CustomStyles.Time;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0style = (uint)CustomStyles.DateTime;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0else if (value is decimal)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dataType = CellValues.Number;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (columnAttribute.IsCurrency)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text = (Math.Round((value as decimal?).Value, 3)).ToString(CultureInfo.InvariantCulture);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0style = (uint)CustomStyles.Currency;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else if (columnAttribute.IsPercentage)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text = (Math.Round((value as decimal?).Value * 100, 3)).ToString(CultureInfo.InvariantCulture);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0style = (uint)CustomStyles.Percentage;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text = (Math.Round((value as decimal?).Value \/ 100, 3)).ToString(CultureInfo.InvariantCulture);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0else if (value is int)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dataType = CellValues.Number;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text = ((value as int?).Value).ToString(CultureInfo.InvariantCulture);\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0else if (value is double)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0dataType = CellValues.Number;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text = ((value as double?).Value).ToString(CultureInfo.InvariantCulture);\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0else if (value is bool?)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text = ((value as bool?).Value ? &quot;SI&quot; : &quot;NO&quot;).ToString(CultureInfo.InvariantCulture);\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0else if (value is String)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text = (value as String).Replace(&quot;\\0&quot;, String.Empty).ToString(CultureInfo.InvariantCulture);\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0cell.DataType = dataType;\n\u00a0\u00a0\u00a0\u00a0cell.StyleIndex = style;\n\u00a0\u00a0\u00a0\u00a0cell.CellValue = new CellValue(text.ToUpperInvariant());\n\u00a0\u00a0\u00a0\u00a0return cell;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><strong>CreateContentCell<\/strong>&nbsp;elabora il contenuto della cella e lo mette a confronto con gli attributi definiti per la colonna corrispondente al fine di scegliere la formattazione migliore.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nel nostro caso, ad esempio, i valori di tipo decimal che hanno l\u2019attributo&nbsp;<em>IsCurrency<\/em>&nbsp;vengono elaborati diversamente da quelli che hanno l\u2019attributo&nbsp;<em>IsPercentage<\/em>, in modo da ottenere due formattazioni differenti e congrue a partire dallo stesso tipo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo stesso vale per le date, che di default sono date complete (con data e ora), ma all\u2019occorrenza possono essere formattate come solo data o solo ora, a seconda degli attributi&nbsp;<em>IsDate<\/em>&nbsp;o<em>&nbsp;IsTime<\/em>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Inoltre, possiamo aggiungere dei metadati al nostro file, tramite il metodo\u00a0<strong>SetDocumentMetadata<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nprivate void SetDocumentMetadata(OpenXmlPackage document)\n{\n\u00a0\u00a0\u00a0\u00a0document.PackageProperties.Title = &quot;Sample report&quot;;\n\u00a0\u00a0\u00a0\u00a0\/\/ for example: it retrieves &#039;Creator&#039; attribute from appsettings.json\n\u00a0\u00a0\u00a0\u00a0document.PackageProperties.Creator = _configuration.GetValue&lt;string&gt;(&quot;AppSettings:WorksheetAuthority&quot;);\n\u00a0\u00a0\u00a0\u00a0document.PackageProperties.Created = DateTime.Now;\n\u00a0\u00a0\u00a0\u00a0document.PackageProperties.Language = &quot;en-US&quot;;\n}\n&lt;\/string&gt;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">dove, ad esempio, l&#8217;attributo\u00a0<em>Creator<\/em>\u00a0\u00e8 stato recuperato da file di configurazione.<br>Tutte le classi e i metodi presentati finora, vengono utilizzati dal metodo generico\u00a0<strong>CreateReport<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic byte&#x5B;] CreateReport &lt;T &gt;(IEnumerable &lt;T &gt; list, IEnumerableString&gt; fieldsToExclude, String name)\n{\n\u00a0\u00a0\u00a0\u00a0using (MemoryStream memoryStream = new MemoryStream())\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Add a WorkbookPart\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Add a WorkbookStylesPart\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WorkbookStylesPart workbookStylesPart = workbookPart.AddNewPart &lt;WorkbookStylesPart &gt;();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Create and define workbook styles\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0GenerateWorkbookStylesPartContent(workbookStylesPart);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Add a WorksheetPart\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WorksheetPart worksheetPart = workbookPart.AddNewPart &lt;WorksheetPart &gt; ();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0OpenXmlWriter openXmlWriter = OpenXmlWriter.Create(worksheetPart);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteStartElement(new Worksheet());\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteElement(new Columns());\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteStartElement(new SheetData());\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var propertyInfos = GetColumnAttributePropertyInfos &lt;T &gt; (fieldsToExclude).ToList();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0List &lt;OpenXmlAttribute &gt; openXmlAttribute = new List &lt;OpenXmlAttribute &gt; ();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlAttribute.Add(new OpenXmlAttribute(&quot;r&quot;, null, &quot;1&quot;));\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteStartElement(new Row(), openXmlAttribute);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Create header row\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0foreach (var propertyInfo in propertyInfos)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteElement(CreateHeaderCell(propertyInfo));\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ end tag for header row\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteEndElement();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0foreach (var (element, rowIndex) in list.Select((v, i) = &gt; (v, i)))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlAttribute = new List &lt;OpenXmlAttribute &gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ this is the row index\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlAttribute.Add(new OpenXmlAttribute(&quot;r&quot;, null, (rowIndex + 2).ToString()));\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteStartElement(new Row(), openXmlAttribute);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0foreach (var (propertyInfo, columnIndex) in propertyInfos.Select((v, i) = &gt; (v, i)))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlAttribute = new List &lt;OpenXmlAttribute &gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlAttribute.Add(new OpenXmlAttribute(&quot;t&quot;, null, (columnIndex + 1).ToString()));\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteElement(CreateContentCell(element, propertyInfo));\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ end tag for Row\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteEndElement();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ end tag for SheetData\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteEndElement();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ end tag for Worksheet\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteEndElement();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.Close();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter = OpenXmlWriter.Create(workbookPart);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteStartElement(new Workbook());\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteStartElement(new Sheets());\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteElement(new Sheet()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Name = name,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SheetId = 1U,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Id = spreadsheetDocument.WorkbookPart.\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0GetIdOfPart(worksheetPart)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ end tag for Sheets\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteEndElement();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ end tag for Workbook\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.WriteEndElement();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0openXmlWriter.Close();\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Set column widths\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SetColumnWidths(worksheetPart.Worksheet, propertyInfos, list);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Set filtering and sorting\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SetAutoFilterAndSorting(worksheetPart, workbookPart.Workbook, name, propertyInfos, list.Count() + 1);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Set metadata for document\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SetDocumentMetadata(spreadsheetDocument);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0spreadsheetDocument.Close();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return memoryStream.ToArray();\n\u00a0\u00a0\u00a0\u00a0}\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In questo metodo, dopo aver creato l\u2019oggetto workbook e gli stili, procediamo alla scrittura delle intestazioni e dei dati.<br>Per scrivere in maniera veloce ed efficiente le celle, procediamo cos\u00ec:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Apertura container esterno tag tramite&nbsp;<em>OpenXmlWriter.WriteStartElement<\/em><\/li><li>Eventuale aggiunta attributi tramite la classe&nbsp;<em>OpenXmlAttribute<\/em>&nbsp;(consigliato per la leggibilit\u00e0 del file XML)<\/li><li>Scrittura del valore nella cella tramite&nbsp;<em>OpenXmlWriter.WriteElement<\/em><\/li><li>Chiusura container esterno con&nbsp;<em>OpenXmlWriter.WriteEndElement<\/em><\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Per quanto riguarda la parte Web, il controller API di esempio,&nbsp;<em>ProductsController<\/em>, ha un unico metodo&nbsp;<strong>GetExport<\/strong>&nbsp;che, a scopo dimostrativo, prende in input il numero di prodotti da creare e restituisce uno stream di dati contenente il file Open XML.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La lista dei prodotti viene generata dinamicamente tramite la libreria\u00a0<strong>Bogus<\/strong>, che permette di creare oggetti fake, e che ci \u00e8 risultata comodo da utilizzare in questo contesto.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;HttpGet(&quot;export\/{count}&quot;)]\npublic ActionResult GetExport(int count = 0)\n{\n\u00a0\u00a0\u00a0\u00a0\/\/ it defines a product template with fake data\n\u00a0\u00a0\u00a0\u00a0var productFaker = new Faker&lt;Product&gt; ()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.CustomInstantiator(f =&gt; new Product())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Id, f =&gt; f.IndexFaker)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Ean, f =&gt; f.Commerce.Ean13())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Name, f =&gt; f.Commerce.ProductName())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Description, f =&gt; f.Lorem.Sentence(f.Random.Int(5, 20)))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Brand, f =&gt; f.Company.CompanyName())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Category, f =&gt; f.Commerce.Categories(1).First())\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Price, f =&gt; f.Random.Decimal(1, 1000))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Quantity, f =&gt; f.Random.Int(0, 1000))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.Rating, f =&gt; f.Random.Decimal(0, 1))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.RuleFor(p =&gt; p.ReleaseDate, f =&gt; f.Date.Past(2));\n\u00a0\n\u00a0\u00a0\u00a0\u00a0_openXMLProvider.GenerateWorksheet(productFaker.Generate(count), null, &quot;Sheet 1&quot;);\n\u00a0\n\u00a0\u00a0\u00a0\u00a0return File(_openXMLProvider.File, &quot;application\/octet-stream&quot;);\n}\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Esecuzione del progetto<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A scopo di esempio, abbiamo realizzato una piccola interfaccia grafica, in cui \u00e8 possibile inserire il numero di elementi e, dopo aver cliccato su\u00a0<strong>Download Report<\/strong>, scaricare il file.<br>Avviando il progetto, otteniamo questa schermata:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"371\" data-attachment-id=\"28065\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/attachment\/image01-15\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-15.png?fit=1819%2C659&amp;ssl=1\" data-orig-size=\"1819,659\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image01-15\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-15.png?fit=1024%2C371&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-15.png?resize=1024%2C371&#038;ssl=1\" alt=\"\" class=\"wp-image-28065\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-15-980x355.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-15-480x174.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Scaricato il file, possiamo aprirlo e visualizzare il risultato:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"359\" data-attachment-id=\"28068\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/attachment\/image02-14\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-14.png?fit=1827%2C641&amp;ssl=1\" data-orig-size=\"1827,641\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image02-14\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-14.png?fit=1024%2C359&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-14.png?resize=1024%2C359&#038;ssl=1\" alt=\"\" class=\"wp-image-28068\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-14-980x344.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-14-480x168.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Testare il file con Open XML Productivity Tool<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Nel generare file pi\u00f9 o meno complessi, pu\u00f2 capitare che questi siano corrotti o addirittura illeggibili. In tal caso, alla loro apertura ci viene mostrata uno sgradevole alert che ci avvisa di non poter leggere il file e che verr\u00e0 tentato un recupero.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per ovviare a questo problema e capire cosa sbagliamo nel creare il file, c&#8217;\u00e8 il tool Open XML Productivity Tool, che scansiona il file e ne verifica la correttezza sintattica e semantica.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Il tool \u00e8 di facile utilizzo. Basta avviarlo, selezionare un file, e, dopo averlo aperto, cliccare su Validate. Nella colonna a sinistra ci vengono indicate le parti di cui \u00e8 composto il Worksheet, e a destra sono indicati avvisi ed errori. Solitamente i warning generano alert di file danneggiato, ma comunque leggibile, cosa che invece non avviene per i file con errori.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Scorrendo la sezione a destra verifichiamo gli eventuali errori che ci porteranno a correggere il codice che ha generato il report.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"559\" data-attachment-id=\"28070\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/attachment\/image03-13\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-13.png?fit=1627%2C888&amp;ssl=1\" data-orig-size=\"1627,888\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image03-13\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-13.png?fit=1024%2C559&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-13.png?resize=1024%2C559&#038;ssl=1\" alt=\"\" class=\"wp-image-28070\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-13-980x535.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-13-480x262.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Il codice utilizzato in questo articolo \u00e8 disponibile\u00a0<a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/enricobencivenga\/Reporting\" target=\"_blank\">qui<\/a><\/p>\n\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>Vediamo come creare report leggeri ed efficienti grazie a Open XML<\/p>\n","protected":false},"author":196716247,"featured_media":28058,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"off","_et_pb_old_content":"","_et_gb_content_width":"","_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_wpcom_ai_launchpad_first_post":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"{title}\n\n{excerpt}\n\n{url}","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false},"categories":[688637374],"tags":[688637382],"class_list":["post-28057","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-c"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Creare report con Open XML SDK - Blexin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creare report con Open XML SDK - Blexin\" \/>\n<meta property=\"og:description\" content=\"Vediamo come creare report leggeri ed efficienti grazie a Open XML\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/\" \/>\n<meta property=\"og:site_name\" content=\"Blexin\" \/>\n<meta property=\"article:published_time\" content=\"2019-11-05T23:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-13T08:40:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i2.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"608\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Enrico Bencivenga\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Enrico Bencivenga\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/\"},\"author\":{\"name\":\"Enrico Bencivenga\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/74e4443d1d7ad12d5b4a8db7f63f0194\"},\"headline\":\"Creare report con Open XML SDK\",\"datePublished\":\"2019-11-05T23:00:00+00:00\",\"dateModified\":\"2021-01-13T08:40:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/\"},\"wordCount\":1130,\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1\",\"keywords\":[\"C#\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/\",\"name\":\"Creare report con Open XML SDK - Blexin\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1\",\"datePublished\":\"2019-11-05T23:00:00+00:00\",\"dateModified\":\"2021-01-13T08:40:22+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/74e4443d1d7ad12d5b4a8db7f63f0194\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1\",\"width\":1024,\"height\":608},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/creare-report-con-open-xml-sdk\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blexin.com\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Creare report con Open XML SDK\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/\",\"name\":\"Blexin\",\"description\":\"Con noi \u00e8 semplice\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blexin.com\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/74e4443d1d7ad12d5b4a8db7f63f0194\",\"name\":\"Enrico Bencivenga\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g\",\"caption\":\"Enrico Bencivenga\"},\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/author\\\/enrico-bencivengablexin-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Creare report con Open XML SDK - Blexin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/","og_locale":"it_IT","og_type":"article","og_title":"Creare report con Open XML SDK - Blexin","og_description":"Vediamo come creare report leggeri ed efficienti grazie a Open XML","og_url":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/","og_site_name":"Blexin","article_published_time":"2019-11-05T23:00:00+00:00","article_modified_time":"2021-01-13T08:40:22+00:00","og_image":[{"width":1024,"height":608,"url":"https:\/\/i2.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1","type":"image\/png"}],"author":"Enrico Bencivenga","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"Enrico Bencivenga","Tempo di lettura stimato":"13 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/#article","isPartOf":{"@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/"},"author":{"name":"Enrico Bencivenga","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/74e4443d1d7ad12d5b4a8db7f63f0194"},"headline":"Creare report con Open XML SDK","datePublished":"2019-11-05T23:00:00+00:00","dateModified":"2021-01-13T08:40:22+00:00","mainEntityOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/"},"wordCount":1130,"image":{"@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1","keywords":["C#"],"articleSection":["Blog"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/","url":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/","name":"Creare report con Open XML SDK - Blexin","isPartOf":{"@id":"https:\/\/blexin.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/#primaryimage"},"image":{"@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1","datePublished":"2019-11-05T23:00:00+00:00","dateModified":"2021-01-13T08:40:22+00:00","author":{"@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/74e4443d1d7ad12d5b4a8db7f63f0194"},"breadcrumb":{"@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/#primaryimage","url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1","contentUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1","width":1024,"height":608},{"@type":"BreadcrumbList","@id":"https:\/\/blexin.com\/it\/blog\/creare-report-con-open-xml-sdk\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blexin.com\/it\/"},{"@type":"ListItem","position":2,"name":"Creare report con Open XML SDK"}]},{"@type":"WebSite","@id":"https:\/\/blexin.com\/it\/#website","url":"https:\/\/blexin.com\/it\/","name":"Blexin","description":"Con noi \u00e8 semplice","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blexin.com\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Person","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/74e4443d1d7ad12d5b4a8db7f63f0194","name":"Enrico Bencivenga","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4ea7187309674789d6f02c6b757e1f21c8cf800abb2419b4edaa8b09d4c99548?s=96&d=identicon&r=g","caption":"Enrico Bencivenga"},"url":"https:\/\/blexin.com\/it\/author\/enrico-bencivengablexin-com\/"}]}},"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/pcyUBx-7ix","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/ab37f718-0d69-4960-9b90-8eb7ff437b53.png?fit=1024%2C608&ssl=1","_links":{"self":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28057","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/users\/196716247"}],"replies":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/comments?post=28057"}],"version-history":[{"count":6,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28057\/revisions"}],"predecessor-version":[{"id":28072,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/28057\/revisions\/28072"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media\/28058"}],"wp:attachment":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media?parent=28057"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/categories?post=28057"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/tags?post=28057"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}