{"id":62,"date":"2024-05-02T09:38:04","date_gmt":"2024-05-02T07:38:04","guid":{"rendered":"https:\/\/kev-it.fr\/?p=62"},"modified":"2024-05-02T09:38:04","modified_gmt":"2024-05-02T07:38:04","slug":"faire-du-html-via-powershell-avec-le-module-wks_htmlreporting","status":"publish","type":"post","link":"https:\/\/kev-it.fr\/index.php\/2024\/05\/02\/faire-du-html-via-powershell-avec-le-module-wks_htmlreporting\/","title":{"rendered":"Faire du HTML via PowerShell avec le module wks_htmlReporting"},"content":{"rendered":"\n<p>Il fut un temps o\u00f9 me demandait r\u00e9guli\u00e8rement de g\u00e9n\u00e9rer des rapports de sant\u00e9 qu&rsquo;il fallait envoyer quotidiennement par mail. Vous me direz : il est fou, pourquoi cr\u00e9er des script de reporting alors qu&rsquo;il suffit de deux mot dans son moteur de recherche pr\u00e9f\u00e9r\u00e9 pour obtenir tout ce qu&rsquo;il faut !<\/p>\n\n\n\n<p>A cela je r\u00e9pondrait :<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Parce que je fais ce que je veux et j&rsquo;aime le challenge \ud83d\ude42<\/li>\n\n\n\n<li>Souvent le contenu est top mais la mise en page plut\u00f4t d\u00e9cevante<\/li>\n<\/ol>\n\n\n\n<p>Comme vous l&rsquo;avez vous dans mon <a href=\"https:\/\/kev-it.fr\/s91y\">article pr\u00e9c\u00e9dent<\/a>, il est tr\u00e8s facile de cr\u00e9er un module PowerShell. Alors pourquoi ne pas se faire un module custom pour g\u00e9n\u00e9rer de beaux rapports HTML ? C&rsquo;est ce que j&rsquo;ai fait avec le module <a href=\"https:\/\/www.powershellgallery.com\/packages\/wks_htmlReporting\">wks_htmlReporting<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Comment faire du HTML en PowerShell ?<\/h2>\n\n\n\n<p>PowerShell permet facilement de g\u00e9n\u00e9rer du code HTML simple et notamment de convenir des objets en table HTML : <a href=\"https:\/\/learn.microsoft.com\/en-us\/powershell\/module\/microsoft.powershell.utility\/convertto-html\">ConvertTo-HTML<\/a>. Par d\u00e9faut la cmd-let g\u00e9n\u00e8re le code complet d&rsquo;une page HTML. Si on lui fournit un objet en entr\u00e9e, il va l&rsquo;int\u00e9grer dans un tableau. Voici un exemple :<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\nGet-Service | ConvertTo-Html\n<\/pre><\/div>\n\n\n<p>Mais pour le coup, c&rsquo;est pas trop sexy \ud83d\ude41<br>Heureusement, on peut faire beaucoup mieux :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Int\u00e9grer une CSS pour la mise en page<\/li>\n\n\n\n<li>Int\u00e9grer des modules Javascript pour rendre les page un peu plus dynamiques<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Comment faire des graphiques ?<\/h2>\n\n\n\n<p>Le plus simple est de demander de l&rsquo;aide \ud83d\ude42<br>Il faut que la page HTML soit autonome, donc un seul fichier et pas de traitement c\u00f4t\u00e9 serveurs. Ca limite les options. La conclusion logique est : Javascript !<\/p>\n\n\n\n<p>Je suis donc parti sur l&rsquo;utilisation de <a href=\"https:\/\/getbootstrap.com\/docs\/3.4\/\">Bootstrap <\/a>et <a href=\"https:\/\/www.chartjs.org\/\">Chart.js<\/a>. Je vous invite \u00e0 jeter un \u0153il sur leurs sites respectifs. Techniquement on proc\u00e9dera comme suit:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Le script powershell ajoute les liens vers les sources JS dans le Header et charge les donn\u00e9es au format JSON dans le fichier HTML<\/li>\n\n\n\n<li>Bootstrap va g\u00e9rer la mise en page HTML (pagination des tableaux, colorisation automatique, etc.)<\/li>\n\n\n\n<li>Char.js s&rsquo;occupera de faire des jolis camembert et autres donuts (\u00e7a donne faim &#8230;)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Comment utiliser la librairie de K\u00e9vin ?<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Fonctionnement du module et architecture du rapport<\/h3>\n\n\n\n<p>Le module se base sur une approche orient\u00e9e objet afin de fournir de la flexibilit\u00e9 dans son utilisation.<\/p>\n\n\n\n<p>On dispose de 3 classes :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>htmlReport <\/strong>: qui repr\u00e9sente un rapport dans sa globalit\u00e9. Une fois compl\u00e9t\u00e9 avec le contenu souhait\u00e9, il ne reste plus qu&rsquo;\u00e0 g\u00e9n\u00e9rer le code HTML ou le fichier selon l&rsquo;usage souhait\u00e9<\/li>\n\n\n\n<li><strong>htmlSection <\/strong>: un <strong>htmlReport <\/strong>se compose de sections (chapitres). On y regroupe des donn\u00e9es qui ont un lien entre elles. Par exemple des graphiques accompagn\u00e9s du tableau avec les informations d\u00e9taill\u00e9es. Une section dispose aussi d&rsquo;un titre qui sert \u00e0 d\u00e9limiter la section dans le rapport.<\/li>\n\n\n\n<li><strong>htmlItem <\/strong>: il s&rsquo;agit des \u00e9l\u00e9ments unitaires qui composent les <strong>htmlSection<\/strong>. Ce sont des graphiques, des arborescences, des notifications ou encore des tableaux.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Installer le module PowerShell<\/h3>\n\n\n\n<p>Rien de plus facile, il est publi\u00e9 dans la PowerShell Gallery<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\nInstall-module wks_htmlReporting\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Cr\u00e9er un rapport simple<\/h3>\n\n\n\n<p>Voici un exemple avec la liste des services Windows du poste local.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\n# Initialize script\n$filename = &quot;$($env:temp)\\wks_htmlReporting.html&quot;\n# Generate simple data\n$services = get-service |select status, name, DisplayName\n\n# Create a section\n$section1 = new-htmlSection &quot;Services Windows&quot; -foldable -folded\n# Adds a simple table to the section\n$section1 |add-htmlSectionItem -itemList (\n    new-htmlItemTable -dataset $services\n)\n# Creates a Report\n$report = new-htmlReport -title &quot;Rapport sur les services Windows&quot; `\n            -subtitle &quot;Feature demonstration of the &lt;b&gt;wks_htmlReporting&lt;\/b&gt; module&quot; `\n# Add section to report        \n$report |add-htmlReportSection -sectionList ($section1)\n# Export report to HTML file\n$report.toFile($filename)\n<\/pre><\/div>\n\n\n<p>On obtient alors un rapport avec un seul paragraphe et une table. N\u00e9anmoins, de base on a :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Un paragraphe qui se d\u00e9plie lorsqu&rsquo;on clique dessus<\/li>\n\n\n\n<li>Un tableau avec pagination<\/li>\n\n\n\n<li>Une fonction de recherche (filtrage les r\u00e9sultats)<\/li>\n<\/ul>\n\n\n\n<p>Pas mal pour un d\u00e9but ?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ajouter des graphiques<\/h3>\n\n\n\n<p>Faire un tableau c&rsquo;est bien mais moi les rapports je pr\u00e9f\u00e8re les regarder, pas les lires \ud83d\ude41<br>Je veux des graphiques ! Allez, qu&rsquo;\u00e0 cela ne tienne, on va ajouter des Items dans la Section.<br>Je reprends le script pr\u00e9c\u00e9dent pour ajouter mes graphiques :<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\n# Define output report file\n$filename = &quot;$($env:temp)\\wks_htmlReporting.html&quot;\n\n# Generate simple data\n$services = get-service -ea SilentlyContinue |select name, DisplayName, @{N=&quot;Status&quot;;E={$_.Status.toString()}}\n\n# Create a section\n$section1 = new-htmlSection &quot;Services Windows&quot; -foldable\n\n# create hashtable with data to display\n$dataChart1 = @{}; ($services |group status |select name, count) |% { $dataChart1&#x5B;$_.name] = $_.count }\n# generate chart item\n$chart1 = new-htmlItemChart -title &quot;R\u00e9partition des services par status&quot; `\n    -data $dataChart1 `\n    -chartType 'doughnut'\n\n# create table\n$table = new-htmlItemTable -dataset $services\n\n# force item line break in report to have the table below the graphs ;)\nadd-htmlItemNewRowAfter -item $chart1\n\n# Generate section\n$section1 |add-htmlSectionItem -itemList ($chart1, $table)\n\n# Creates a Report\n$report = new-htmlReport -title &quot;Rapport sur les services Windows&quot; `\n            -subtitle &quot;Feature demonstration of the &lt;b&gt;wks_htmlReporting&lt;\/b&gt; module&quot; `\n# Add section to report        \n$report |add-htmlReportSection -sectionList ($section1)\n# Export report to HTML file\n$report.toFile($filename)\n#&amp; $filename\n<\/pre><\/div>\n\n\n<p>Pour ajouter un graphique, on cr\u00e9\u00e9 un objet htmlItem suppl\u00e9mentaire de type Chart. La seule subtilit\u00e9 est que les donn\u00e9es qui servent au graphique doivent \u00eatre fournies sous forme de HashTable. C&rsquo;est ce que je fais en cr\u00e9ant la variable $dataChart1.<br>Parmi les type de graphique support\u00e9s, il y a :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>bar<\/li>\n\n\n\n<li>pie<\/li>\n\n\n\n<li>doughnut <\/li>\n<\/ul>\n\n\n\n<p>Alors, \u00e7a commence \u00e0 ressembler \u00e0 un vrai rapport, non ?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ajouter un filtrage automatique des donn\u00e9es<\/h3>\n\n\n\n<p>Maintenant qu&rsquo;on a un graphique qui synth\u00e9tise des \u00e9l\u00e9ments du tableau juste en dessous, je me suis dit :  on n&rsquo;est pas trop mal, mais ce serait bien de pouvoir cliquer sur le graphique afin de filtrer automatiquement le tableau. N&rsquo;est-ce pas ?<\/p>\n\n\n\n<p>Et bien rien de plus simple, il suffit d&rsquo;ajouter les param\u00e8tres \u00e0 l&rsquo;item Chart afin de r\u00e9f\u00e9rencer l&rsquo;item Table et le champ \u00e0 filtrer&#8230; Ah, je vous ait perdu. Regardez l&rsquo;exemple, c&rsquo;est hyper intuitif en fait \ud83d\ude09 Il suffit d&rsquo;ajouter 3 param\u00e8tre quand on cr\u00e9\u00e9 le htlmItemChart :<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\n# Define output report file\n$filename = &quot;$($env:temp)\\wks_htmlReporting.html&quot;\n\n# Generate simple data\n$services = get-service -ea SilentlyContinue |select name, DisplayName, @{N=&quot;Status&quot;;E={$_.Status.toString()}}\n\n# Create a section\n$section1 = new-htmlSection &quot;Services Windows&quot; -foldable\n\n# create hashtable with data to display\n$dataChart1 = @{}; ($services |group status |select name, count) |% { $dataChart1&#x5B;$_.name] = $_.count }\n# create table\n$table = new-htmlItemTable -dataset $services\n\n# generate chart item\n$chart1 = new-htmlItemChart -title &quot;R\u00e9partition des services par status&quot; `\n    -data $dataChart1 `\n    -chartType 'doughnut' `\n    -linkedTableId $table.id `\n    -linkedFieldName 'Status' `\n    -linkedTableExactMatch\n\n# force item line break in report to have the table below the graphs ;)\nadd-htmlItemNewRowAfter -item $chart1\n\n# Generate section\n$section1 |add-htmlSectionItem -itemList ($chart1, $table)\n\n# Creates a Report\n$report = new-htmlReport -title &quot;Rapport sur les services Windows&quot; `\n            -subtitle &quot;Feature demonstration of the &lt;b&gt;wks_htmlReporting&lt;\/b&gt; module&quot; `\n# Add section to report        \n$report |add-htmlReportSection -sectionList ($section1)\n# Export report to HTML file\n$report.toFile($filename)\n#&amp; $filename\n<\/pre><\/div>\n\n\n<p>Les points \u00e0 noter sont :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>cr\u00e9ation du tableau avant le graphique (pour r\u00e9cup\u00e9rer son ID au moment de cr\u00e9er le graphique)<\/li>\n\n\n\n<li>ajout des param\u00e8tres linkedTableId, linkedFieldName, linkedTableExactMatch<\/li>\n\n\n\n<li>attention la valeur du param\u00e8tre linkedFieldName est sensible \u00e0 la case &#8230; javascript oblige !<\/li>\n<\/ul>\n\n\n\n<p>Bon c&rsquo;est pas du grafana, c&rsquo;est c&rsquo;est cool non !<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Voil\u00e0 pour le usages simple du module wks_htmlReporting.<br>Je vous donne rendez-vous dans mon prochain article pour les usages un peu plus exotiques \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Il fut un temps o\u00f9 me demandait r\u00e9guli\u00e8rement de g\u00e9n\u00e9rer des rapports de sant\u00e9 qu&rsquo;il fallait envoyer quotidiennement par mail. Vous me direz : il est fou, pourquoi cr\u00e9er des script de reporting alors qu&rsquo;il suffit de deux mot dans son moteur de recherche pr\u00e9f\u00e9r\u00e9 pour obtenir tout ce qu&rsquo;il faut ! A cela je [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[12,8,10],"class_list":["post-62","post","type-post","status-publish","format-standard","hentry","category-dev","tag-html","tag-powershell","tag-tips"],"_links":{"self":[{"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/posts\/62","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/comments?post=62"}],"version-history":[{"count":6,"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/posts\/62\/revisions"}],"predecessor-version":[{"id":76,"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/posts\/62\/revisions\/76"}],"wp:attachment":[{"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/media?parent=62"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/categories?post=62"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kev-it.fr\/index.php\/wp-json\/wp\/v2\/tags?post=62"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}