{"id":8053,"date":"2021-09-29T04:28:20","date_gmt":"2021-09-29T04:28:20","guid":{"rendered":"https:\/\/berg-software.com\/?p=8053"},"modified":"2022-06-23T13:44:03","modified_gmt":"2022-06-23T13:44:03","slug":"custom-reporting-tool-from-html-to-pdf","status":"publish","type":"post","link":"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/","title":{"rendered":"Custom reporting tool from HTML to PDF: flexible, straightforward &#038; regulatory compliant"},"content":{"rendered":"<p>[et_pb_section fb_built=&#8221;1&#8243; fullwidth=&#8221;on&#8221; _builder_version=&#8221;4.4.1&#8243;][et_pb_fullwidth_post_title meta=&#8221;off&#8221; featured_placement=&#8221;background&#8221; _builder_version=&#8221;4.7.7&#8243; title_font=&#8221;||||||||&#8221; title_text_color=&#8221;#ff6317&#8243; title_font_size=&#8221;3.5em&#8221; meta_font=&#8221;|300|||||||&#8221; meta_text_color=&#8221;#ffffff&#8221; meta_font_size=&#8221;1em&#8221; background_enable_color=&#8221;off&#8221; use_background_color_gradient=&#8221;on&#8221; background_color_gradient_start=&#8221;rgba(248,248,248,0.85)&#8221; background_color_gradient_end=&#8221;rgba(248,248,248,0.75)&#8221; background_color_gradient_overlays_image=&#8221;on&#8221; min_height=&#8221;20vh&#8221; height=&#8221;400px&#8221; custom_padding=&#8221;6vh||6vh||false|false&#8221; global_module=&#8221;403&#8243; locked=&#8221;off&#8221;][\/et_pb_fullwidth_post_title][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; admin_label=&#8221;intro&#8221; _builder_version=&#8221;4.4.6&#8243; custom_padding=&#8221;|||0px||&#8221; locked=&#8221;off&#8221;][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.4.6&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; hover_enabled=&#8221;0&#8243; border_color_left=&#8221;#ff6317&#8243; sticky_enabled=&#8221;0&#8243;]<\/p>\n<p>One of the projects we worked on for the <a href=\"https:\/\/www.berg-software.com\/en\/category\/case-studies-retail-automation\/\">retail industry<\/a> was a custom reporting tool from HTML to PDF.<\/p>\n<p>In the business world, reporting is a necessary evil: it is accepted\/must be done in order to achieve a better outcome (e.g., organizational oversight, standardization, discipline). Then, as if not enough pressure, regulatory bodies will keep piling up.<\/p>\n<p>Take for example EU\u2019s Payment Services Directive 2015\/2366 (check <a href=\"https:\/\/ec.europa.eu\/info\/law\/payment-services-psd-2-directive-eu-2015-2366_en\" target=\"_blank\" rel=\"noopener noreferrer\">the official page<\/a>, its <a href=\"https:\/\/en.wikipedia.org\/wiki\/Payment_Services_Directive\" target=\"_blank\" rel=\"noopener noreferrer\">Wikipedia page<\/a>, and EU\u2019s <a href=\"https:\/\/joinup.ec.europa.eu\/collection\/rolling-plan-ict-standardisation\/retail-payments\">official rolling plan<\/a>): due to the technological changes in payments, \u201c<em>it aims at better protecting consumers when they pay online, promoting the development and use of innovative online and mobile payments, and making cross-border European payment services safer<\/em>\u201d. In plain English, this ends up in developing and implementing a \u201c<em>single, open and secure European technical standard for QR-codes [that] would support the uptake and interoperability of instant payments<\/em>\u201d. The final deadline to comply: 14th September 2019 (unofficially extended \u201cbecause of pandemics\u201d).<\/p>\n<p>For virtually all B2C companies, this means they have to include standardized security marks (i.e., QR codes) on all the bills. Furthermore, this means the payment software needs to be updated, in order to accommodate the regulatory requests and to create leaner reporting that supports internal needs. But then, some (very) old software can\u2019t easily be upgraded, and it\u2019s easy to start afresh.<\/p>\n<p><strong>Working with a retail client, we have developed a custom reporting tool<\/strong> that is:<\/p>\n<ul>\n<li><strong>regulatory compliant<\/strong>: it includes all the security items required by the Directive (EU) 2015\/2366<\/li>\n<li><strong>programmatic<\/strong>: it defines the structure of all the needed reports, creates their templates, then fills them automatically anytime a report is needed.<\/li>\n<\/ul>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"why_build_your_own_reports&quot;\">Why build your own reports instead of using ready-made reports generators<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>First of all, it takes time to learn how to use a report generator and -most important- how to communicate with its APIs. This results in high installation effort (and possibly tedious maintenance along the way).<\/p>\n<p>Then, the costs of a really good, high-performing report generator are not far away from the cost of a custom reporting tool.<\/p>\n<p>By building your own, you can focus on your specific requirements without the overhead of a \u201csatisfy all\u201d ready-made solution. This results in higher flexibility (of design, data sources, etc.) and unmatched performance.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"our_reporting_solution\">Our reporting solution<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>For this specific customer, we had already built a cashbox module as the first part of a bigger ERP system. The reporting capabilities were a natural extension, in the form of an additional microservice that could be used by other modules along the way.<\/p>\n<p>For each needed report, we created a three-step process:<\/p>\n<ul>\n<li>creating a static HTML template<\/li>\n<li>inject dynamic data<\/li>\n<li>converting the HTML to .pdf<\/li>\n<\/ul>\n<p>[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;8061&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;45%&#8221; module_alignment=&#8221;left&#8221; max_height=&#8221;45%&#8221; custom_padding=&#8221;||35px||false|false&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>We started by defining the layouts with HTML, as it is the most popular language that describes layouts. For each type of report, we needed three HTML files: a body, a header, and a footer. (This is because the client\u2019s different reports all needed different headers\/body\/footers). We could easily create and modify report mock-ups in HTML alone to get useful feedback from the client in the earlier stage.<\/p>\n<p>Once we had the layout defined, the next step was to inject the dynamic data. We used a heterogeneous data source (SQL tables, JSON files, and in-memory data). When the data was available, we used Razor as a template engine to inject the data into HTML.<\/p>\n<p>To integrate Razor into our software, we used the NuGet package and we installed RazorEngine 3.10.0. You can see an example below, of how Razor is used inside HTML. In this example, the code creates a table of articles with three columns, the position of the article, the article\u2019s code and its price.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">&lt;table&gt;\n    @foreach(var article in @Model.Items){\n    &lt;tr&gt;\n        &lt;td&gt;\n            &lt;span&gt; @article.Position&lt;\/span&gt;\n            &lt;span&gt; @article.Code&lt;\/span&gt;\n        &lt;\/td&gt;\n        &lt;td&gt;\n            &lt;span&gt; @article.Price \u20ac&lt;\/span&gt;\n        &lt;\/td&gt;\n    &lt;\/tr&gt;\n    }\n&lt;\/table&gt;<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>@Model represents the root of the model, where Razor expects to find the data. In the code, we tell Razor to use the customized ReportModel, C# object as the @Model.<\/p>\n<p>We call the Razor method RunCompile with the following parameters:<\/p>\n<ul>\n<li>HTML template\u2019s content as string<\/li>\n<li>Template identifier to differentiate one type of template from another<\/li>\n<li>Type of the data model<\/li>\n<li>An instance of the data model<\/li>\n<\/ul>\n<p>This method returns the HTML string with injected data as the final HTML result.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">    var result = Engine.Razor.RunCompile(File.ReadAllText(htmlPath), templateIdentifier,typeof(ReportModel), reportModel);<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]ReportModel class looks like below:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">public class ReportModel\n{\n&nbsp;\n    public List&lt;Item&gt; Items {get; set;}\n}\n&nbsp;\npublic class Item\n{\n    public int Position {get; set;}\n    public double Price {get; set;}\n    public string Code {get; set;}\n}<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>After these steps, we end up with a complete HTML and the final step takes care of the conversion of the HTML into a pdf report.<\/p>\n<p>Converting HTML to pdf could look like a basic operation and there are a lot of free tools on the internet to do just that. But a report is not just a pdf file, is more than that. It comes with features like adding header, footer, pagination, and printing support.<\/p>\n<p>We started to evaluate commercial HTML to pdf libraries that could support our needs for professional reports. We tried IronPDF, Spire.PDF, and <a href=\"https:\/\/www.evopdf.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">EVO PDF<\/a>, all of them with comparable pricing tiers (around 500 \u20ac\/instance).<\/p>\n<p>Finally, we chose EVO PDF because (A) the generated .pdf file looked how we wanted, with the integrated header and footer (also when printing), and (B) the documentation was up to date and easy to use (<strong>very<\/strong> important). As a bonus: you don\u2019t need to buy EVO PDF in the development step, as they offer a fully functional free version that only inserts a red watermark in the report.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"how_to_use_evo_pdf\">How to use EVO PDF<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>First, we had to add EVO PDF as a NuGet package to our project. In fact, EVO PDF provides installation options for multiple platforms, such as .NET, .NET CORE, Java, and more.<\/p>\n<p>Once available, using it is straightforward and <a href=\"https:\/\/www.evopdf.com\/html-to-pdf-converter.aspx\" target=\"_blank\" rel=\"noopener noreferrer\">well documented<\/a>.<\/p>\n<p>Here is a sample code from our implementation:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">    var htmlToPdfConverter = new HtmlToPdfConverter(); \n\/\/ next 5 settings are to optimize the size of the pdf file\n    htmlToPdfConverter.ConversionDelay = 0;\n    htmlToPdfConverter.PdfDocumentOptions.EmbedFonts = true;\n    htmlToPdfConverter.PdfDocumentOptions.CompressCrossReference = true;\n    htmlToPdfConverter.PdfDocumentOptions.PdfCompressionLevel = PdfCompressionLevel.Best;\n    htmlToPdfConverter.PdfDocumentOptions.ImagesScalingEnabled = true;\n&nbsp;\n\/\/ Razor method is the same that we explained above\n\/\/ injecting dynamic data in header \n    var headerPathAfterRazor = _razorService.Razor(headerPath, templatesDirectoryPath, reportModel); \n\/\/ injecting dynamic data in footer\n    var footerPathAfterRazor = _razorService.Razor(footerPath,\n&nbsp;\n    var headerHtml = new HtmlToPdfElement(headerPathAfterRazor);\n    var footerHtml = new HtmlToPdfElement(footerPathAfterRazor);\n    htmlToPdfConverter.PdfDocumentOptions.ShowHeader = true;\n    htmlToPdfConverter.PdfDocumentOptions.ShowFooter = true;\n&nbsp;\n\/\/ setting the desired height for header \/ footer\n    htmlToPdfConverter.PdfHeaderOptions.HeaderHeight = 100;  \n    htmlToPdfConverter.PdfFooterOptions.FooterHeight = 110;\n    headerHtml.FitHeight = true;\n    footerHtml.FitHeight = true;\n\/\/ adding the header and the footer to the pdf report\n    htmlToPdfConverter.PdfHeaderOptions.AddElement(headerHtml);  \n    htmlToPdfConverter.PdfHeaderOptions.AddElement(footerHtml);  \n&nbsp;\n\/\/ injecting dynamic data in body \n    var bodyPathAfterRazor = _razorService.RazorbodyPath,                templatesDirectoryPath, reportModel);      \n\/\/ converting html to pdf\n  var pdfAsBytes = htmlToPdfConverter.ConvertUrl(bodyPathAfterRazor);\n<\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Once we generated the pdf document, for printing capabilities the default windows command was reliable and just enough for our needs.[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">print \/d: C:\\inetpub\\reportsservice\\myReport.pdf<\/pre>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"encountered_problems\">Encountered problems<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||35px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>Reports can go big quickly, even for simple pages. The size can reach hundreds of kilobytes, especially when large pictures or customized fonts are used.<\/p>\n<p>Then, Razor can take some time to compile a template for the first time. That\u2019s why it\u2019s better to do the template compiling in advance, and not during generating the report itself. At this step, the dummy report model will be empty as it has no role here. Once compiled, the next compilation of the same template will be instant.<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;||35px|20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"text\" style=\"font-family: monospace;\">    var result = Engine.Razor.RunCompile(File.ReadAllText(htmlPath), templateIdentifier,typeof(ReportModel), dummyReportModel);<\/pre>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||0px||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;2em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||10px||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2>Conclusions<\/h2>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<p>When approached as a customized solution, the reporting tools stop being the necessary evil:<\/p>\n<ul>\n<li>they adapt to clients\u2019 specific contexts and needs<\/li>\n<li>are relatively straightforward to develop and implement<\/li>\n<li>can be very flexible to any changes in regulations and\/or client specifics.<\/li>\n<\/ul>\n<p>\u2014<br \/>\nShould you need more info, or insights into developing your own reporting tools, <a href=\"mailto:contact@bergsoftprod.wpengine.com\">please get in touch<\/a>.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;|||0px||&#8221; locked=&#8221;off&#8221;][et_pb_row use_custom_gutter=&#8221;on&#8221; gutter_width=&#8221;3&#8243; admin_label=&#8221;\uff3f&#8221; _builder_version=&#8221;4.4.6&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;4vh||8vh||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.6&#8243;][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;3.22&#8243; background_color=&#8221;#eeeeee&#8221; custom_padding=&#8221;50px||50px||false|false&#8221; border_color_top=&#8221;#ff6317&#8243; global_module=&#8221;1642&#8243;][et_pb_row column_structure=&#8221;1_3,1_3,1_3&#8243; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;0px|||||&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_social_media_follow _builder_version=&#8221;4.4.4&#8243; text_orientation=&#8221;left&#8221;][et_pb_social_media_follow_network social_network=&#8221;linkedin&#8221; url=&#8221;https:\/\/www.linkedin.com\/company\/berg-computers-srl\/&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#007bb6&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]linkedin[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;twitter&#8221; url=&#8221;https:\/\/twitter.com\/berg_software&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#00aced&#8221; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]twitter[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;facebook&#8221; url=&#8221;https:\/\/www.facebook.com\/bergCOMPUTERS&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#3b5998&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]facebook[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;instagram&#8221; url=&#8221;https:\/\/www.instagram.com\/berg_software\/&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#ea2c59&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]instagram[\/et_pb_social_media_follow_network][\/et_pb_social_media_follow][\/et_pb_column][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_post_nav in_same_term=&#8221;on&#8221; show_next=&#8221;off&#8221; _builder_version=&#8221;4.4.1&#8243; title_text_color=&#8221;#ff6317&#8243; custom_padding=&#8221;|25px|||false|false&#8221;][\/et_pb_post_nav][\/et_pb_column][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_post_nav in_same_term=&#8221;on&#8221; show_prev=&#8221;off&#8221; _builder_version=&#8221;4.4.1&#8243; title_text_color=&#8221;#ff6317&#8243; custom_padding=&#8221;|||25px|false|false&#8221;][\/et_pb_post_nav][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; admin_label=&#8221;CONTACT&#8221; _builder_version=&#8221;4.4.1&#8243; background_color=&#8221;#d2d2d2&#8243; custom_padding=&#8221;75px||75px||false|false&#8221;][et_pb_row column_structure=&#8221;1_4,3_4&#8243; admin_label=&#8221;Service Section Title&#8221; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;||25px||false|false&#8221; animation_direction=&#8221;top&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;1_4&#8243; _builder_version=&#8221;3.25&#8243; custom_padding=&#8221;|||&#8221; custom_padding__hover=&#8221;|||&#8221;][\/et_pb_column][et_pb_column type=&#8221;3_4&#8243; _builder_version=&#8221;3.25&#8243; custom_padding=&#8221;|||&#8221; custom_padding__hover=&#8221;|||&#8221;][et_pb_text _builder_version=&#8221;4.4.1&#8243; text_font=&#8221;|300|||||||&#8221; text_text_color=&#8221;#ffffff&#8221; text_line_height=&#8221;1.1em&#8221; header_5_font=&#8221;|600|||||||&#8221; header_5_text_color=&#8221;#ffffff&#8221; header_5_font_size=&#8221;14px&#8221; header_5_line_height=&#8221;1.5em&#8221; custom_margin=&#8221;||||false|false&#8221;]29 years in business | 2700 software projects | 760 clients | 24 countries<\/p>\n<h5>We turn ideas into software. What is yours?<\/h5>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;Title&#8221; _builder_version=&#8221;4.4.6&#8243; header_text_align=&#8221;center&#8221; header_2_font=&#8221;|300|||||||&#8221; header_2_text_align=&#8221;left&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;50px&#8221; header_2_line_height=&#8221;0.9em&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;25px||25px||false|false&#8221;]<\/p>\n<h2 id=\"Getintouch\">Get in touch<\/h2>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row column_structure=&#8221;1_4,3_4&#8243; _builder_version=&#8221;4.4.4&#8243;][et_pb_column type=&#8221;1_4&#8243; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_column][et_pb_column type=&#8221;3_4&#8243; _builder_version=&#8221;4.4.4&#8243;][et_pb_contact_form email=&#8221;contact@bergsoftprod.wpengine.com&#8221; custom_message=&#8221;WEBFORM MESSAGE||et_pb_line_break_holder||\uff3f||et_pb_line_break_holder||FROM: %%Name%%||et_pb_line_break_holder||EMAIL: %%Email%%||et_pb_line_break_holder||PHONE NUMBER: %%Phone_number%%||et_pb_line_break_holder||COMPANY: %%Company_name%%||et_pb_line_break_holder||TERMS &amp; CONDITIONS: %%Terms_and_Conditions%%||et_pb_line_break_holder||DATA PRIVACY POLICY: %%Data_Privacy_Policy%%||et_pb_line_break_holder||\uff3f||et_pb_line_break_holder||MESSAGE:||et_pb_line_break_holder||%%Message%%&#8221; success_message=&#8221;Thank you for reaching out! Your message was sent. We will get back to you right away.&#8221; _builder_version=&#8221;4.7.7&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_text_color=&#8221;#ffffff&#8221; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; title_level=&#8221;h2&#8243; title_font=&#8221;|300|||||||&#8221; title_text_color=&#8221;#ff6317&#8243; title_font_size=&#8221;30px&#8221; form_field_line_height=&#8221;1.5em&#8221; custom_button=&#8221;on&#8221; button_text_size=&#8221;14px&#8221; button_text_color=&#8221;#ffffff&#8221; button_bg_color=&#8221;#ff6317&#8243; button_border_width=&#8221;0px&#8221; button_border_radius=&#8221;0px&#8221; button_icon=&#8221;%%3%%&#8221; button_on_hover=&#8221;off&#8221; border_color_all=&#8221;#ffffff&#8221; border_width_bottom=&#8221;1px&#8221;][et_pb_contact_field field_id=&#8221;Name&#8221; field_title=&#8221;Name *&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_text_color=&#8221;#ffffff&#8221; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; border_width_bottom=&#8221;1px&#8221; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Email&#8221; field_title=&#8221;Email address *&#8221; field_type=&#8221;email&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Phone_number&#8221; field_title=&#8221;Phone number&#8221; required_mark=&#8221;off&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Company_name&#8221; field_title=&#8221;Company name&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Message&#8221; field_title=&#8221;Message *&#8221; field_type=&#8221;text&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; border_width_bottom=&#8221;1px&#8221; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Terms_and_Conditions&#8221; field_title=&#8221; &#8221; field_type=&#8221;checkbox&#8221; checkbox_options=&#8221;%91{%22value%22:%22I have read and accepted the Terms and Conditions%22,%22checked%22:0,%22dragID%22:-1}%93&#8243; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Data_Privacy_Policy&#8221; field_title=&#8221; &#8221; field_type=&#8221;checkbox&#8221; checkbox_options=&#8221;%91{%22value%22:%22I have read and accepted the Data Privacy Policy%22,%22checked%22:0,%22dragID%22:-1}%93&#8243; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][\/et_pb_contact_form][\/et_pb_column][\/et_pb_row][\/et_pb_section]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Reporting is a necessary evil: it is accepted\/must be done in order to achieve a better outcome. Here\u2019s how we built a custom reporting tool, from HTML to PDF.<\/p>\n","protected":false},"author":10,"featured_media":8054,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"on","_et_pb_old_content":"","_et_gb_content_width":"2880","footnotes":""},"categories":[138,33],"tags":[],"class_list":["post-8053","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","category-insights"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v16.1.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Custom reporting tool from HTML to PDF | Berg Software<\/title>\n<meta name=\"description\" content=\"One of the projects we worked on for the retail industry was a custom reporting tool from HTML to PDF.In the business world, reporting is a necessary evil\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Custom reporting tool from HTML to PDF | Berg Software\" \/>\n<meta property=\"og:description\" content=\"One of the projects we worked on for the retail industry was a custom reporting tool from HTML to PDF.In the business world, reporting is a necessary evil\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/\" \/>\n<meta property=\"og:site_name\" content=\"Berg Software\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/bergCOMPUTERS\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-09-29T04:28:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-06-23T13:44:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Alternate-reporting-tools-from-HTML-to-PDF.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@berg_software\" \/>\n<meta name=\"twitter:site\" content=\"@berg_software\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"10 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\",\"name\":\"Berg Software\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"sameAs\":[\"https:\/\/www.facebook.com\/bergCOMPUTERS\/\",\"https:\/\/www.instagram.com\/berg_software\/\",\"https:\/\/www.linkedin.com\/company\/berg-computers-srl\/\",\"https:\/\/www.youtube.com\/channel\/UCw1FfcRJnC-CoKPwlcM10Iw\",\"https:\/\/twitter.com\/berg_software\"],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#logo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/berg-software.com\/wp-content\/uploads\/berg-software-logo.png\",\"contentUrl\":\"https:\/\/berg-software.com\/wp-content\/uploads\/berg-software-logo.png\",\"width\":512,\"height\":512,\"caption\":\"Berg Software\"},\"image\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#website\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"name\":\"Berg Software\",\"description\":\"We turn ideas into software.\",\"publisher\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/www.berg-software.com\/en\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Alternate-reporting-tools-from-HTML-to-PDF.jpg\",\"contentUrl\":\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Alternate-reporting-tools-from-HTML-to-PDF.jpg\",\"width\":1200,\"height\":600,\"caption\":\"Alternate reporting tools from HTML to PDF\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#webpage\",\"url\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/\",\"name\":\"Custom reporting tool from HTML to PDF | Berg Software\",\"isPartOf\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#primaryimage\"},\"datePublished\":\"2021-09-29T04:28:20+00:00\",\"dateModified\":\"2022-06-23T13:44:03+00:00\",\"description\":\"One of the projects we worked on for the retail industry was a custom reporting tool from HTML to PDF.In the business world, reporting is a necessary evil\",\"breadcrumb\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/category\/insights\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/category\/insights\/\",\"name\":\"Insights\"}},{\"@type\":\"ListItem\",\"position\":3,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/\",\"name\":\"Custom reporting tool from HTML to PDF: flexible, straightforward &#038; regulatory compliant\"}}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#webpage\"},\"author\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#\/schema\/person\/c30f728cd36ad12eb903071b34eee31f\"},\"headline\":\"Custom reporting tool from HTML to PDF: flexible, straightforward &#038; regulatory compliant\",\"datePublished\":\"2021-09-29T04:28:20+00:00\",\"dateModified\":\"2022-06-23T13:44:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/custom-reporting-tool-from-html-to-pdf\/#primaryimage\"},\"articleSection\":\"How to,Insights\",\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#\/schema\/person\/c30f728cd36ad12eb903071b34eee31f\",\"name\":\"Mirela Berzescu\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","_links":{"self":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts\/8053","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/comments?post=8053"}],"version-history":[{"count":0,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts\/8053\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/media\/8054"}],"wp:attachment":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/media?parent=8053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/categories?post=8053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/tags?post=8053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}