<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rohith_Veerapalli</title>
    <description>The latest articles on DEV Community by Rohith_Veerapalli (@ni_klaus_4eb1581f851becee).</description>
    <link>https://dev.to/ni_klaus_4eb1581f851becee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3669234%2Fe69557f9-60ca-40fa-a9e7-8c78420322a8.png</url>
      <title>DEV Community: Rohith_Veerapalli</title>
      <link>https://dev.to/ni_klaus_4eb1581f851becee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ni_klaus_4eb1581f851becee"/>
    <language>en</language>
    <item>
      <title>Fixing Unbalanced TTS Error in D365FO Excel Upload</title>
      <dc:creator>Rohith_Veerapalli</dc:creator>
      <pubDate>Sat, 27 Dec 2025 17:14:16 +0000</pubDate>
      <link>https://dev.to/ni_klaus_4eb1581f851becee/excel-upload-in-custom-script-5ec5</link>
      <guid>https://dev.to/ni_klaus_4eb1581f851becee/excel-upload-in-custom-script-5ec5</guid>
      <description>&lt;p&gt;When developing Excel upload in custom script functionality in Dynamics 365 Finance &amp;amp; Operations (D365FO) using X++, we commonly encounter the unbalanced X++ TTSBEGIN/TTSCOMMIT error. This guide shows you exactly how to fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Error You'll Encounter
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3n6ly4pxwip7pezn7uec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3n6ly4pxwip7pezn7uec.png" alt=" " width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding How Custom Scripts Process Transactions
&lt;/h2&gt;

&lt;p&gt;Lets understand how custom script is processing, when we see the class AppConsistencyCustomScriptStateChange, &lt;br&gt;
when we do &lt;strong&gt;Run test&lt;/strong&gt; the operation runs under &lt;strong&gt;ttsbegin&lt;/strong&gt; and &lt;strong&gt;ttsabort&lt;/strong&gt;, when we do &lt;strong&gt;Run&lt;/strong&gt; operation, it process under &lt;strong&gt;ttsbegin&lt;/strong&gt;, &lt;strong&gt;ttscommit&lt;/strong&gt;.&lt;br&gt;
the process is already in transaction when we upload the package&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6brku9hs4xf4gluogjb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6brku9hs4xf4gluogjb.png" alt=" " width="774" height="631"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Error Occurs
&lt;/h2&gt;

&lt;p&gt;When you read an Excel file using classes like OfficeOpenXml.ExcelPackage or similar COM objects, these operations internally manage transactions. If your code already has an active TTS level, you'll get an unbalanced transaction error.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution: Abort Transactions Before Reading Excel
&lt;/h2&gt;

&lt;p&gt;The fix is simple but crucial: abort all existing transactions before reading the Excel file, then restore the TTS level afterward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight abap"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ttsLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ttsAbort&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we are aborting the transaction, we need to add &lt;strong&gt;ttsBegin&lt;/strong&gt; transaction begin in the end of the process to not get Unbalanced transaction errors&lt;/p&gt;

&lt;h2&gt;
  
  
  Complete Working Code Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight abap"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;OfficeOpenXml&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;OfficeOpenXml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExcelPackage&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;OfficeOpenXml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExcelRange&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="n"&gt;ExcelReaderForCustomScript&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt;  &lt;span class="n"&gt;CustAccount&lt;/span&gt;      &lt;span class="n"&gt;accountNum&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;CCMNum_BR&lt;/span&gt;         &lt;span class="n"&gt;ccmNum&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;///&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;summary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;///&lt;/span&gt; &lt;span class="k"&gt;Class&lt;/span&gt; &lt;span class="k"&gt;entry&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="k"&gt;method&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;designated&lt;/span&gt; &lt;span class="n"&gt;menu&lt;/span&gt;
    &lt;span class="o"&gt;///&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;selected&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt; &lt;span class="n"&gt;starts&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;startup&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="o"&gt;///&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;summary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;///&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="k"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;"_args"&amp;gt;The specified arguments.&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;void&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt; &lt;span class="n"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ExcelReaderForCustomScript&lt;/span&gt; &lt;span class="n"&gt;curentClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ExcelReaderForCustomScript&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;curentClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;importData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'script executed'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;void&lt;/span&gt; &lt;span class="n"&gt;importData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stream&lt;/span&gt;                        &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;DialogGroup&lt;/span&gt;                             &lt;span class="n"&gt;dlgUploadGroup&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;FileUploadBuild&lt;/span&gt;                         &lt;span class="n"&gt;fileUploadBuild&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;FormBuildControl&lt;/span&gt;                        &lt;span class="n"&gt;formBuildControl&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;list&lt;/span&gt; &lt;span class="k"&gt;List&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;types&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="k"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ttsLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ttsAbort&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;Dialog&lt;/span&gt;           &lt;span class="k"&gt;dialog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c1"&gt;"Upload file");&lt;/span&gt;

        &lt;span class="n"&gt;dlgUploadGroup&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c1"&gt;"File");&lt;/span&gt;
        &lt;span class="n"&gt;formBuildControl&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;formBuildDesign&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;control&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dlgUploadGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;fileUploadBuild&lt;/span&gt;         &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formBuildControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addControlEx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classstr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FileUpload&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Upload'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;fileUploadBuild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FileUploadStyle&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MinimalWithFilename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;fileUploadBuild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fileTypesAccepted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.xlsx'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;closedOk&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;FileUpload&lt;/span&gt; &lt;span class="n"&gt;fileUploadControl&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;formRun&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;control&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;formRun&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;controlId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Upload'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;FileUploadTemporaryStorageResult&lt;/span&gt; &lt;span class="n"&gt;fileUploadResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fileUploadControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getFileUploadResult&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;CustTable&lt;/span&gt;   &lt;span class="n"&gt;custTable&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileUploadResult&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;fileUploadResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getUploadStatus&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fileUploadResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;openResult&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ExcelPackage&lt;/span&gt; &lt;span class="k"&gt;Package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ExcelPackage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;int&lt;/span&gt; &lt;span class="n"&gt;rowCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;columncount&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

                    &lt;span class="k"&gt;Package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;ExcelWorksheet&lt;/span&gt; &lt;span class="n"&gt;worksheet&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_Workbook&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;get_Worksheets&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;get_Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;OfficeOpenXml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExcelRange&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;worksheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cells&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

                    &lt;span class="n"&gt;rowCount&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worksheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dimension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;End&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worksheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dimension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;columncount&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;worksheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dimension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;End&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

                    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="k"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;rowCount&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="k"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;accountNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                        &lt;span class="n"&gt;ccmNum&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_Item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                        &lt;span class="k"&gt;List&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accountNum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

                        &lt;span class="n"&gt;ttsbegin&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                        &lt;span class="n"&gt;update_recordset&lt;/span&gt; &lt;span class="n"&gt;custTable&lt;/span&gt; &lt;span class="n"&gt;setting&lt;/span&gt; &lt;span class="n"&gt;CCMNum_BR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ccmNum&lt;/span&gt;
                            &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;custTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccountNum&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;accountNum&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                        &lt;span class="n"&gt;ttscommit&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;

                    &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strFmt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'AccountNum %1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;list&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;
                    &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;ttsbegin&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Critical Implementation Note
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind, since we are aborting transaction, Run Test process will write the data to system. we dont have to process Run operation again.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>backend</category>
      <category>dotnet</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Computed columns in D365FO – Using Correlated Subqueries with Real SQL</title>
      <dc:creator>Rohith_Veerapalli</dc:creator>
      <pubDate>Thu, 18 Dec 2025 16:30:25 +0000</pubDate>
      <link>https://dev.to/ni_klaus_4eb1581f851becee/implementing-correlated-subqueries-in-d365fo-computed-columns-a-practical-guide-2672</link>
      <guid>https://dev.to/ni_klaus_4eb1581f851becee/implementing-correlated-subqueries-in-d365fo-computed-columns-a-practical-guide-2672</guid>
      <description>&lt;p&gt;When working in Dynamics 365 Finance &amp;amp; Operations, we often need to display or filter data that doesn’t physically exist in a table. Adding a new field and populating it with batch jobs or event handlers is sometimes overkill — and that’s where computed columns shine.&lt;/p&gt;

&lt;p&gt;In this post, I’ll explain computed columns in D365FO, when to use them, and a real-world SQL subquery pattern .&lt;/p&gt;

&lt;h2&gt;
  
  
  Computed Columns in D365FO
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Computed Column in D365FO x++?
&lt;/h2&gt;

&lt;p&gt;A computed column is a virtual field whose value is calculated at runtime using SQL, not stored in the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key points:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No physical column is created in SQL&lt;/p&gt;

&lt;p&gt;Logic is executed at query time&lt;/p&gt;

&lt;p&gt;Implemented using an X++ static method that returns an SQL expression&lt;/p&gt;

&lt;p&gt;Commonly used in views, data entities, and computed fields&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern Most People Use (and Its Limitation)
&lt;/h2&gt;

&lt;p&gt;Most examples online show simple patterns like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concatenating fields&lt;/li&gt;
&lt;li&gt;Simple CASE WHEN&lt;/li&gt;
&lt;li&gt;Basic SUM or COUNT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in real projects, we often need context-aware values, based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Date ranges&lt;/li&gt;
&lt;li&gt;Related transactions&lt;/li&gt;
&lt;li&gt;Conditional joins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s where subqueries inside computed columns become powerful.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Real-World Example: Fetching a Request ID Based on Transaction Date&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s look at a computed column that returns a Leave Request ID for a worker, based on whether a transaction date falls within a leave period.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static str requestId()
{
    str sqlQuery;

    sqlQuery = strFmt(
        "(SELECT TOP 1 LR.REQUESTID " +
        " FROM LeaveRequest LR " +
        " JOIN LeaveOfAbsenceRequestDetail LRD " +
        "   ON LRD.REQUEST = LR.RECID " +
        "  AND LRD.DATAAREAID = LR.DATAAREAID " +
        " WHERE LR.WORKER = T1.WORKER " +
        "   AND LRD.STARTDATE &amp;lt;= T1.TRANSACTIONDATE " +
        "   AND LRD.ENDDATE   &amp;gt;= T1.TRANSACTIONDATE " +
        "   AND LR.DATAAREAID = T1.DATAAREAID " +
        "   AND LR.PARTITION  = T1.PARTITION)"
    );

    return sqlQuery;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Understanding What’s Happening&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why T1?
&lt;/h2&gt;

&lt;p&gt;T1 refers to the primary datasource of the view or entity where this computed column is defined.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;T1.WORKER&lt;/p&gt;

&lt;p&gt;T1.TRANSACTIONDATE&lt;/p&gt;

&lt;p&gt;These values come from the current record being queried.&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Why SELECT TOP 1?
&lt;/h2&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;p&gt;Computed columns must return a single scalar value.&lt;br&gt;
If multiple records are possible, SQL must be constrained to one result.&lt;/p&gt;

&lt;p&gt;You can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add ORDER BY&lt;/li&gt;
&lt;li&gt;Add additional filters&lt;/li&gt;
&lt;li&gt;Use MAX() or MIN() if appropriate&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  3. Why This Is Powerful
&lt;/h2&gt;

&lt;p&gt;This pattern allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamically resolve relationships&lt;/li&gt;
&lt;li&gt;Use date-effective logic&lt;/li&gt;
&lt;li&gt;Avoid storing derived data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use the field in:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filters&lt;/li&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;Data entities&lt;/li&gt;
&lt;li&gt;Reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All without writing X++ loops.&lt;/p&gt;
&lt;h2&gt;
  
  
  More examples
&lt;/h2&gt;

&lt;p&gt;Lets say we have multiple approvers for single invoice, we can concatenate multiple pending approvers like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static str pendingApprovers()
{
    str sqlQuery;


    sqlQuery = strFmt( 
                     "STUFF((" +
                    " SELECT ', ' + USERINFO.Name" +
" FROM WORKFLOWWORKITEMTABLE WWI" +
" JOIN DIRPERSONUSER PU ON PU.USER_ = WWI.USERID" +
" JOIN HCMWORKER HW ON HW.PERSON = PU.PERSONPARTY" +
" join USERINFO ON USERINFO.ID = WWI.USERID"+
" WHERE WWI.PURCHINVOICE = T1.RECID" +
" AND WWI.STATUS  = 0"+
" AND WWI.PARTITION = T1.PARTITION" +
" FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')" +
", 1, 2, '')"
        );

        return sqlQuery;


}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here T1 is the primary data source table&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlntana5wvk9k1qtou1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlntana5wvk9k1qtou1k.png" alt=" " width="742" height="481"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;This is how the view design will be&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F406qexgu3xwcszkkxv1u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F406qexgu3xwcszkkxv1u.png" alt=" " width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and final result &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7d56g9sh111qiebdc8s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7d56g9sh111qiebdc8s.png" alt=" " width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep experimenting 🚀&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dynamics365fo</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
