{"id":230,"date":"2010-06-01T15:13:43","date_gmt":"2010-06-01T22:13:43","guid":{"rendered":"http:\/\/45.63.48.66\/?p=230"},"modified":"2010-09-23T19:55:34","modified_gmt":"2010-09-24T02:55:34","slug":"how-to-track-report-usage-in-dynamics-nav","status":"publish","type":"post","link":"https:\/\/gotcal.com\/index.php\/2010\/06\/how-to-track-report-usage-in-dynamics-nav\/","title":{"rendered":"How to track report usage in Dynamics NAV"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"alignright size-medium wp-image-243\" title=\"reportstack\" src=\"http:\/\/45.63.48.66\/wp-content\/uploads\/2010\/06\/reportstack-238x300.jpg\" alt=\"\" width=\"238\" height=\"300\" srcset=\"https:\/\/gotcal.com\/wp-content\/uploads\/2010\/06\/reportstack-238x300.jpg 238w, https:\/\/gotcal.com\/wp-content\/uploads\/2010\/06\/reportstack.jpg 476w\" sizes=\"auto, (max-width: 238px) 100vw, 238px\" \/>I was quoting an upgrade proposal for a client that had a lot of custom reports. Trying to identify which ones were actively being used today, the client did not have a definitive answer. So we needed an strategy to identify the reports that was being used. And at the same time we would like to know who used them, and how often &#8211; that way we could make a more qualified decision about the reports to upgrade.<\/p>\n<p>Of course every report could be modified so it wrote to a report usage table (but that would require you to modify every report in the system). Fortunately there is an easier way to handle this. In codeunit 1 Application Management, the function FindPrinter():<\/p>\n<p><!--more--><\/p>\n<p><span style=\"color: #ff0000;\"><strong>Update 9-23-2010: Embarrasing! Trying out some searches on Bing.com i found this on Marq&#8217;s blog: <a href=\"http:\/\/dynamicsuser.net\/blogs\/mark_brummel\/archive\/2009\/12\/01\/tip-20-save-report-usage.aspx\">http:\/\/dynamicsuser.net\/blogs\/mark_brummel\/archive\/2009\/12\/01\/tip-20-save-report-usage.aspx<\/a><\/strong><\/span><\/p>\n<p><span style=\"color: #ff0000;\"><strong>Nice trick with the temporary table. In case you dont have any tables available keep reading this post :).<br \/>\n<\/strong><\/span><\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nFindPrinter(ReportID : Integer) : Text&#x5B;250]\r\n<\/pre>\n<p>is always called for a report you run. Well at least for any report that is not ProcessingOnly=Yes. And since it is called with the report id, we already know the userid of the logged in user as well as the current date and time, we have all the information needed for our log.<\/p>\n<p>Unfortunately you can&#8217;t start any transactions in the database at the point this function is called, as it is called right after the OnIniReport() trigger. To get around this we can just have our report usage table reside in another database. In this example, I have setup a table on a SQL server:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nif exists (select * from dbo.sysobjects where id = object_id(N'&#x5B;dbo].&#x5B;ReportUsage]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)\r\ndrop table &#x5B;dbo].&#x5B;ReportUsage]\r\nGO\r\n\r\nCREATE TABLE &#x5B;dbo].&#x5B;ReportUsage] (\r\n  &#x5B;ReportID] &#x5B;int] NOT NULL ,\r\n  &#x5B;UserID] &#x5B;varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,\r\n  &#x5B;Date] &#x5B;varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,\r\n  &#x5B;Time] &#x5B;varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,\r\n  &#x5B;Notes] &#x5B;varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL\r\n  ) ON &#x5B;PRIMARY]\r\nGO\r\n<\/pre>\n<p>In codeunit 1 we are going to add this code in the first part of FindPrinter().<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nInteger.SETRANGE(Number,ReportID);\r\nInteger.FIND('-');\r\nIF CODEUNIT.RUN(CODEUNIT::&quot;Report Usage&quot;,Integer) THEN;\r\n<\/pre>\n<p>The function is on the OnRun trigger of the codeunit, that way we can avoid any errors, like if users don&#8217;t have connectivity to the external database etc.<\/p>\n<p>The codeunit itself has this code:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nOnRun(VAR Rec : Record Integer)\r\nReportUsageToSQL(Number);\r\n<\/pre>\n<p>and the function:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nReportUsageToSQL(ReportID : Integer)\r\nIF ISCLEAR(ADOConnection) THEN\r\n  IF NOT CREATE(ADOConnection) THEN\r\n    ERROR('Cannot create ADO Connection automation variable.');\r\n\r\nADOConnection.ConnectionString(\r\n  'Driver={SQL Server};Server=server;Database=database;Uid=user;Pwd=password;');\r\n\r\nADOConnection.Mode := 2;\r\nADOConnection.Open;\r\n\r\nRecordsAffected := '';\r\nRSOption := 0;\r\n\r\nSQLString :=\r\n  STRSUBSTNO(\r\n    'INSERT INTO ReportUsage VALUES' +\r\n    '(''%1'',''%2'',''%3'',''%4'',''%5'')',\r\n    ReportID,                                                   \/\/1\r\n    USERID,                                                     \/\/2\r\n    FORMAT(TODAY),                                              \/\/3\r\n    FORMAT(TIME),                                               \/\/4\r\n    '');                                                        \/\/5\r\n\r\nADOConnection.Execute(SQLString,RecordsAffected,RSOption);\r\nADOConnection.Close;\r\n<\/pre>\n<p>After a while you end up with some very useful statistics in your little sql table, that you can query in every imaginable way.<\/p>\n<div id=\"attachment_236\" style=\"width: 257px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/45.63.48.66\/wp-content\/uploads\/2010\/06\/reportdata.png\" rel=\"lightbox[230]\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-236\" class=\"size-medium wp-image-236\" title=\"reportdata\" src=\"http:\/\/45.63.48.66\/wp-content\/uploads\/2010\/06\/reportdata-247x300.png\" alt=\"\" width=\"247\" height=\"300\" srcset=\"https:\/\/gotcal.com\/wp-content\/uploads\/2010\/06\/reportdata-247x300.png 247w, https:\/\/gotcal.com\/wp-content\/uploads\/2010\/06\/reportdata.png 545w\" sizes=\"auto, (max-width: 247px) 100vw, 247px\" \/><\/a><p id=\"caption-attachment-236\" class=\"wp-caption-text\">Report Statistics in SQL<\/p><\/div>\n<p>[dm]3[\/dm]<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>I was quoting an upgrade proposal for a client that had a lot of custom reports. Trying to identify which ones were actively being used today, the client did not have a definitive answer. So we needed an strategy to identify the reports that was being used. And at the same time we would like [&hellip;]<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[3],"tags":[23,77,22,15,21,24,25],"class_list":["post-230","post","type-post","status-publish","format-standard","hentry","category-navision","tag-ado","tag-navision","tag-object","tag-report","tag-sql","tag-statistics","tag-upgrade"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/posts\/230","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/comments?post=230"}],"version-history":[{"count":22,"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/posts\/230\/revisions"}],"predecessor-version":[{"id":241,"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/posts\/230\/revisions\/241"}],"wp:attachment":[{"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/media?parent=230"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/categories?post=230"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gotcal.com\/index.php\/wp-json\/wp\/v2\/tags?post=230"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}