<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>larswestman.se</title>
	<atom:link href="http://larswestman.se/feed/" rel="self" type="application/rss+xml" />
	<link>https://larswestman.se</link>
	<description>It&#039;s all about Microsoft Dynamics 365 Business Central</description>
	<lastBuildDate>Thu, 20 Apr 2023 11:32:55 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.5</generator>

<image>
	<url>https://larswestman.se/wp-content/uploads/2019/09/bc_icon-150x150.png</url>
	<title>larswestman.se</title>
	<link>https://larswestman.se</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Comparing data between companies</title>
		<link>https://larswestman.se/comparing-data-between-companies/</link>
					<comments>https://larswestman.se/comparing-data-between-companies/#respond</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Thu, 20 Apr 2023 11:28:16 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[TSQL]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=302</guid>

					<description><![CDATA[It&#8217;s not often that I post something here, but I find myself returning to my blog to find tricky SQL statements. This time it&#8217;s about comparing data between companies. Let&#8217;s say you have a large number of companies and you want to compare data in a specific table to see differences. This script will give [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>It&#8217;s not often that I post something here, but I find myself returning to my blog to find tricky SQL statements. This time it&#8217;s about comparing data between companies.</p>
<p>Let&#8217;s say you have a large number of companies and you want to compare data in a specific table to see differences. This script will give you all columns except the timestamp column and display all data in the No. Series table by company.</p>
<pre>&nbsp;
<p>declare @table nvarchar(30) = 'No_ Series'<br>declare @sql nvarchar(MAX), @CompanyName varchar(30)<br>declare @columns nvarchar(max)=''<br>declare @col nvarchar(100) =''<br>declare @num_rows int =0<br>declare @dat_type nvarchar(30)</p>
<p>set @CompanyName = (select top(1) Name from Company)<br>declare cols cursor for<br>select column_name, data_type<br>from INFORMATION_SCHEMA.COLUMNS<br>where TABLE_NAME = ''+@CompanyName+'$'+@table+''</p>
<p>open cols<br>fetch next from cols into @col, @dat_type<br>while(@@FETCH_STATUS = 0)<br>begin<br>set @num_rows +=1<br>if @dat_type = 'timestamp'<br>set @columns += 'null'<br>else <br>set @columns += '['+@col+']'<br>fetch next from cols into @col, @dat_type<br>if @@FETCH_STATUS=0<br>set @columns += ','<br>end<br>close cols<br>deallocate cols</p>
<p>SELECT @sql = 'SELECT TOP(0) space(30) AS CompanyName, * INTO ##TempData FROM ['+ @CompanyName +'$'+@table+']'<br>exec (@sql)</p>
<p>DECLARE CompanyCursor CURSOR FORWARD_ONLY FOR<br>SELECT REPLACE([Name],'.','_')<br>FROM [Company]<br>OPEN CompanyCursor<br>FETCH NEXT FROM CompanyCursor INTO @CompanyName<br><br>WHILE @@FETCH_STATUS = 0<br>BEGIN<br>SELECT @sql = '<br>INSERT INTO ##TempData SELECT ''' + @CompanyName + ''', ' + @columns + ' from ['+@CompanyName+'$'+@table+']' <br>exec (@sql) <br>FETCH NEXT FROM CompanyCursor INTO @CompanyName<br>END</p>
<p>CLOSE CompanyCursor<br>DEALLOCATE CompanyCursor<br>ALTER TABLE ##TempData DROP COLUMN timestamp<br>select * from ##TempData<br>DROP TABLE ##TempData</p>
</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/comparing-data-between-companies/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Access Business Central API&#8217;s in Azure</title>
		<link>https://larswestman.se/access-business-central-apis-in-azure/</link>
					<comments>https://larswestman.se/access-business-central-apis-in-azure/#comments</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Tue, 12 May 2020 09:03:23 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=284</guid>

					<description><![CDATA[Business Central comes with a set of API&#8217;s that you can access from other applications. When running BC in Azure you can choose between basic authentication and Oath 2.0. The latter is preferable since the requesting app does not need to store user name and password. The user will input these when giving consent for [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Business Central comes with a set of API&#8217;s that you can access from other applications. When running BC in Azure you can choose between basic authentication and Oath 2.0. The latter is preferable since the requesting app does not need to store user name and password. The user will input these when giving consent for the app to access the BC API&#8217;s. The problem with Oath 2.0 is that you receive a token for access that expires.</p>
<p>Using basic authentication you store a user name and a web access key in the requesting app and does not have to deale with expiring tokens. Basic authentication does work in production even thoug Microsoft says that Oath shall/should (they actually say both in the same document) be used in production.</p>



<p><strong>AAD authentication</strong></p>



<p>First we take a look at AAD authentication/Oath and how to set that up. The main tasks are:</p>



<ol class="wp-block-list"><li>Create an app in Azure AD</li><li>Get the Access Token in Postman</li><li>Use the Access Token in Postman to access the API</li></ol>



<p><strong>1. Create the App in Azure AD</strong></p>



<p>The AAD App act&#8217;s like a contract between the BC API and the requesting app.</p>



<ol class="wp-block-list"><li>Login to Azure Active Directory</li><li>Select App Registrations</li><li>Click &#8220;New registration&#8221;</li><li>In &#8220;Register an application&#8221;:<ol><li>Give the app a name</li><li>Select from where your app is supposed to be accessed in &#8220;Supported Account Types&#8221;</li><li>Set &#8220;https://businesscentral.dynamics.com&#8221; as redirect URL</li><li>Click on &#8220;Register&#8221; to create the app.</li></ol></li><li>Click on &#8220;Certificates &amp; Secrets&#8221;</li><li>Click on &#8220;New Client Secret&#8221;</li><li>In &#8220;Add a client secret&#8221;:<ol><li>Select if and when the client secret expires</li></ol></li><li>Copy the secret and save it. You will need this in Postman.</li><li>Click on &#8220;API permissions&#8221;</li><li>Click on &#8220;Add a permission&#8221;</li><li>In &#8220;Request API permissions&#8221;:<ol><li>Click on &#8220;Dynamics 365 Business Central&#8221;</li><li>Click on &#8220;Delegated permissions&#8221;</li><li>Select &#8220;user_impersonation&#8221;</li><li>Click on &#8220;Add permissions&#8221; in the bottom of the page</li></ol></li><li>Back in &#8220;API permissions&#8221;:<ol><li>Click on &#8220;Grant admin consent for &lt;organization name&gt;&#8221;</li><li>Click on &#8220;Yes&#8221; to confirm.</li></ol></li><li>Click on &#8220;Overview&#8221; and copy the &#8220;Application (client) ID&#8221;. You will need this in Postman.</li></ol>



<p><strong>2. Get the Access Token in Postman</strong></p>



<p>In this step you will create a collection in Postman and request an access token that is used in the requests you create in the collection.</p>



<ol class="wp-block-list"><li>Create a new collection in Postman</li><li>Give the collection a name and select the Authorization tab</li><li>Select Type = Oauth 2.0</li><li>Click on &#8220;Get New Access Token&#8221;</li><li>Fill in the following:<ol><li>A Token Name</li><li>&#8220;Grant Type&#8221; = &#8220;Authorization Code&#8221;</li><li>&#8220;Callback URL&#8221; = &#8220;https://businesscentral.dynamics.com/&#8221;</li><li>&#8220;Auth URL&#8221; = &#8220;https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize&#8221;</li><li>&#8220;Access Token URL&#8221; = &#8220;https://login.microsoftonline.com/organizations/oauth2/v2.0/token&#8221;</li><li>&#8220;Client ID&#8221; = &lt;your client ID&gt;</li><li>&#8220;Client Secret&#8221; = &lt;your client secret&gt;</li><li>&#8220;Scope&#8221; = &#8220;https://api.businesscentral.dynamics.com/user_impersonation&#8221;</li></ol></li><li>Click on &#8220;Request Token&#8221;</li><li>Authenticate with a valid user and password.</li><li>Click on &#8220;Use Token&#8221;</li><li>Click on &#8220;Create&#8221; to create the collection</li></ol>



<p><strong>3. Access the API</strong></p>



<p>In this step we will create requests in the collection. The requests will inheret the authorization from the collection. Our aim is to retrieve a list of customers.</p>



<p>My example is based on the environment &#8220;sandbox&#8221;. Change that to whatever environment you want to access (e.g. &#8220;production&#8221;).</p>



<ol class="wp-block-list"><li>Expand the collection in the list of collections</li><li>Create a request to list companies in the BC database<ol><li>Click on &#8220;Add requests&#8221; or the three dots at the right and select &#8220;Add request&#8221;</li><li>Give the request a name (e.g. &#8220;Companies&#8221;)</li><li>Click on &#8220;Save to &lt;your collection name&gt;&#8221;</li><li>Select the request in the left pane</li><li>Type in &#8220;https://api.businesscentral.dynamics.com/v2.0/sandbox/api/v1.0/companies&#8221; as the URL</li><li>Click on &#8220;Send&#8221; and you should get a list of companies.</li><li>Copy the id of one of your companies. You will need it in the next step</li><li>Click on &#8220;Save&#8221; to save the request</li></ol></li><li>Create another request<ol><li>Give the request the name &#8220;Customers&#8221;</li><li>Click on &#8220;Save to &lt;your collection name&gt;&#8221;</li><li>Type in https://api.businesscentral.dynamics.com/v2.0/sandbox/api/v1.0/companies(&lt;your company id&gt;)/customers</li><li>Click on &#8220;Send&#8221; and you should get a list of customers</li></ol></li></ol>



<p>Did you make it all the way down here? Good job!</p>



<p>What about using basic authentication? Well, that&#8217;s much easier. There&#8217;s no need to mess around in AAD.</p>



<p><strong>Basic authentication</strong></p>



<ol class="wp-block-list"><li>Create a user in BC with a web access key</li><li>Create a collection in Postman with basic authentication. The username shall not include the domain name</li><li>Create a request to list your companies. The URL now follows this syntax: https://api.businesscentral.dynamics.com/v2.0/&lt;domain>/&lt;environment>/api/v1.0/companies</li></ol>



<p>Basic was a bit easier <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> But is it supported by Microsoft in the long run? I don&#8217;t know.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/access-business-central-apis-in-azure/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Use Excel to create a permission set</title>
		<link>https://larswestman.se/use-excel-to-creating-permission-sets/</link>
					<comments>https://larswestman.se/use-excel-to-creating-permission-sets/#comments</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Thu, 09 May 2019 06:44:40 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=251</guid>

					<description><![CDATA[When developing in AL creating permission sets isn&#8217;t the must fun thing to do&#8230;. I thought it must be possible to find a better tool than editing the xml file manually and found some inspiration here. Based on that I created this excel sheet that you can use to create a permission set xml file. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>When developing in AL creating permission sets isn&#8217;t the must fun thing to do&#8230;. I thought it must be possible to find a better tool than editing the xml file manually and found some inspiration <a href="https://spreadsheeto.com/xml/" target="_blank" rel="noopener">here</a>. Based on that I created <a href="https://larswestman.se/wp-content/uploads/2019/05/PermissionSet.xlsx" target="_blank" rel="noopener">this excel sheet</a> that you can use to create a permission set xml file.</p>
<p>Make sure the developers tab is visible in Excel. Then add the tables and permissions in the excel table and click export on the developers tab and you have a permission set.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/use-excel-to-creating-permission-sets/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>AL and SOAP</title>
		<link>https://larswestman.se/al-and-soap/</link>
					<comments>https://larswestman.se/al-and-soap/#comments</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Wed, 09 May 2018 19:10:26 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=235</guid>

					<description><![CDATA[This sample is based on a page extension for page 8 (Currencies) where an action for downloading exchange rates from the Swedish State Bank has been added. The logic itself isn&#8217;t super advanced and it requires SEK as local currency. The focus here is to show how to: Create SOAP request XML Do an HTTP [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>This sample is based on a page extension for page 8 (Currencies) where an action for downloading exchange rates from the Swedish State Bank has been added. The logic itself isn&#8217;t super advanced and it requires SEK as local currency. The focus here is to show how to:</p>
<ul>
<li>Create SOAP request XML</li>
<li>Do an HTTP Post using httpclient</li>
<li>Read the XML in the response and do something with that.</li>
</ul>
<p>I have used a codeunit for XML DOM management created by <a href="https://diveshboramsdnavblog.wordpress.com/" target="_blank" rel="noopener">Divesh Bora</a> which makes things a lot easier.</p>
<p>I hope you find this useful and helps you on your way to move from C/AL to AL.</p>
<pre>pageextension 57900 CurrencyListExtension extends Currencies
{
    actions
    {
        addafter(UpdateExchangeRates)
        {
            action(DownloadExchRates)
            {
                ApplicationArea = All;
                CaptionML = ENU = 'Get Exchange Rates from State Bank of Sweden', SVE = 'Hämta valutakurser från Sveriges Riksbank';
                Image = CurrencyExchangeRates;
                Promoted = true;
                PromotedCategory = Category4;

                trigger OnAction();
                var
                    DownloadExchRates: codeunit "SE State Bank Exch Rates";
                    TxtDownloadSucceeded: TextConst ENU = 'Exchange Rates updated successfully', SVE = 'Valutakurserna har uppdateras';
                    JobQueueEntry: Record "Job Queue Entry";
                begin
                    if DownloadExchRates.Run(JobQueueEntry) then
                      message(TxtDownloadSucceeded);
                end;
            }
        }
    }
}
</pre>
<pre>codeunit 57900 "SE State Bank Exch Rates"
{
    // <a href="https://swea.riksbank.se/sweaWS/docs/api/call/getLatestInterestAndExchangeRates.htm" target="_blank" rel="noopener">https://swea.riksbank.se/sweaWS/docs/api/call/getLatestInterestAndExchangeRates.htm</a>
    // <a href="https://swea.riksbank.se/sweaWS/wsdl/sweaWS_ssl.wsdl" target="_blank" rel="noopener">https://swea.riksbank.se/sweaWS/wsdl/sweaWS_ssl.wsdl</a>

    TableNo = "Job Queue Entry";
    var
      XMLDOMMgmt: Codeunit "XML DOM Mgt.";
      SoapNS : Label 'http://www.w3.org/2003/05/soap-envelope';
      XsdNS : Label 'http://swea.riksbank.se/xsd';
      URL: label 'https://swea.riksbank.se:443/sweaWS/services/SweaWebServiceHttpSoap12Endpoint';
      NsMgr : XmlNamespaceManager;
    
    trigger OnRun();
    var 
      GLSetup : Record "General Ledger Setup";
      XMLDoc : XmlDocument;
      Currency : Record Currency;
      CurrNode : XmlNode;
      CurrNode2 : XmlNode;
      CurrNodeList : XmlNodeList;
      CurrExchRate : Record "Currency Exchange Rate";
      Unit : Decimal;
      DebugFile: File;
      OutStr: OutStream;
      NsMgr: XmlNamespaceManager;
    begin
      GLSetup.GET;
      GLSetup.TESTFIELD("LCY Code", 'SEK');
      if Currency.FINDSET then
        with XMLDOMMgmt do 
          begin
            AddRootElementWithPrefix(XMLDoc, 'Envelope', 'soap', SoapNS, CurrNode2);
            SetUtf8Declaration(XMLDoc);
            CurrNode := CurrNode2;
            AddPrefix(CurrNode, 'xsd', XsdNS);
            CurrNode := CurrNode2;
            AddElement(CurrNode, 'Header', '', SoapNs, CurrNode2);
            CurrNode := CurrNode2;
            AddElement(Currnode, 'Body', '', SoapNs, CurrNode2);
            CurrNode := CurrNode2;
            AddElement(Currnode, 'getLatestInterestAndExchangeRates', '', XsdNS, CurrNode2);
            CurrNode := CurrNode2;
            if GLOBALLANGUAGE = 1053 then
              AddElement(CurrNode, 'languageid', 'sv', '', CurrNode2)
            else
              AddElement(CurrNode, 'languageid', 'en', '', CurrNode2);
            repeat
              AddElement(CurrNode,'seriesid', GLSetup."LCY Code" + Currency.Code + 'PMI', '', CurrNode2);
            until Currency.NEXT = 0;

            HTTPPost(XMLDoc, URL);

            GetRootNode(XMLDoc, CurrNode);
            AddNameSpace(NsMgr, 'soap', SoapNS);
            AddNameSpace(NsMgr, 'ns2', XsdNS);
            if FindNodesWithNamespaceManager(CurrNode, '//soap:Body/ns2:getLatestInterestAndExchangeRatesResponse/return/groups/series', NsMgr, CurrNodeList) then
              foreach CurrNode in CurrNodeList do
                with CurrExchRate do
                  begin
                    INIT;
                    if FindNode(CurrNode, 'seriesid', CurrNode2) then
                      "Currency Code" := COPYSTR(CurrNode2.AsXmlElement.InnerText, 4, 3);
                    if FindNode(CurrNode, 'unit', CurrNode2) then
                      Unit := FormatDecmialTextImport(CurrNode2.AsXmlElement.InnerText);
                    "Relational Exch. Rate Amount" := 1;
                    "Relational Adjmt Exch Rate Amt" := 1;
                    if FindNode(CurrNode, 'resultrows', CurrNode2) then
                      begin
                        CurrNode := CurrNode2;
                        if FindNode(CurrNode, 'date', CurrNode2) then
                          "Starting Date" := FormatDateTextImport(CurrNode2.AsXmlElement.InnerText);
                        if FindNode(CurrNode, 'value', CurrNode2) then
                          begin
                            "Exchange Rate Amount" := FormatDecmialTextImport(CurrNode2.AsXmlElement.InnerText);
                            "Exchange Rate Amount" := 1 / "Exchange Rate Amount" * Unit;
                            "Adjustment Exch. Rate Amount" := "Exchange Rate Amount";
                            if not INSERT then
                              MODIFY;
                          end;
                      end;
                  end;
          end;
    end;  

    local procedure HTTPPost(var XmlDoc : XmlDocument;URL : Text[250]) : Boolean;
    var
        MyHTTPClient: HttpClient;
        RequestMessage: HttpRequestMessage;
        ResponseMessage: HttpResponseMessage;
        Headers: HttpHeaders;
        Content: HttpContent;
        CurrNodeList : XmlNodeList;
        XML_text: text;
        InStr: InStream;
        OutStr: OutStream;
    begin
        RequestMessage.SetRequestUri(URL);
        RequestMessage.Method('POST');
        XmlDoc.WriteTo(XML_text); 
        Content.WriteFrom(XML_text);
        Content.GetHeaders(Headers);
        Headers.Remove('Content-Type');
        Headers.Add('Content-Type', 'application/soap+xml;charset=UTF-8;action="urn:getLatestInterestAndExchangeRates"');
        RequestMessage.Content := Content;
        MyHTTPClient.send(RequestMessage, ResponseMessage);
        if not ResponseMessage.IsSuccessStatusCode then
          error(format(ResponseMessage.HttpStatusCode) +' , ' + ResponseMessage.ReasonPhrase);
        if ResponseMessage.IsSuccessStatusCode then
           begin
             ResponseMessage.Content.ReadAs(InStr);
             XMLDOMMgmt.LoadXMLDocumentFromInStream(InStr, XmlDoc);
             XMLDOMMgmt.SetUtf8Declaration(XmlDoc);
           end
         else
           error(format(ResponseMessage.HttpStatusCode));
    end;

    local procedure FormatDecmialTextImport(TextDec : Text[30]) : Decimal;
    var
        TempDec : Decimal;
    begin
        if TextDec = '' then
          exit(0)
        else
          begin
            TempDec := 0.01;
            EVALUATE(TempDec, CONVERTSTR(TextDec, '.', COPYSTR(FORMAT(TempDec),2,1)));
            exit(TempDec);
          end;
    end;

    local procedure FormatDateTextImport(DateText : Text) : Date;
    var
        MyYear : Integer;
        MyMonth : Integer;
        MyDay : Integer;
    begin
        EVALUATE(MyYear, COPYSTR(DateText, 1, 4));
        EVALUATE(MyMonth, COPYSTR(DateText, 6, 2));
        EVALUATE(MyDay, COPYSTR(DateText, 9, 2));
        exit(DMY2DATE(MyDay, MyMonth, MyYear));;
    end;
}
</pre>
<pre>codeunit 57901 "XML DOM Mgt."
{   
    <a href="https://diveshboramsdnavblog.wordpress.com/2018/03/09/vs-code-xml-dom-management-part-2/" target="_blank" rel="noopener">https://diveshboramsdnavblog.wordpress.com/2018/03/09/vs-code-xml-dom-management-part-2/</a>
    trigger OnRun();
    begin
    end;

    procedure AddElement(var pXMLNode: XmlNode; pNodeName: Text; pNodeText: Text; pNameSpace: Text; var pCreatedNode: XmlNode): Boolean
    begin
        IF pNodeText &lt;&gt; '' then
            pCreatedNode := XmlElement.Create(pNodeName, pNameSpace, pNodeText).AsXmlNode
        else
            pCreatedNode := XmlElement.Create(pNodeName, pNameSpace).AsXmlNode;
        Exit(pXMLNode.AsXmlElement.Add(pCreatedNode));
    end;

    procedure AddRootElement(var pXMLDocument: XmlDocument; pNodeName: Text; var pCreatedNode: XmlNode): Boolean
    begin
        pXMLDocument := XmlDocument.Create;
        pCreatedNode := XmlElement.Create(pNodeName).AsXmlNode;
        Exit(pXMLDocument.Add(pCreatedNode));
    end;

    procedure AddRootElementWithPrefix(var pXMLDocument: XmlDocument; pNodeName: Text; pPrefix: Text; pNameSpace: text; var pCreatedNode: XmlNode): Boolean
    begin
        pXMLDocument := XmlDocument.Create;
        pCreatedNode := XmlElement.Create(pNodeName, pNameSpace).AsXmlNode;
        pCreatedNode.AsXmlElement.Add(XmlAttribute.CreateNamespaceDeclaration(pPrefix, pNameSpace));
        Exit(pXMLDocument.Add(pCreatedNode));
    end;

    procedure AddElementWithPrefix(var pXMLNode: XmlNode; pNodeName: Text; pNodeText: Text; pPrefix: Text; pNameSpace: text; var pCreatedNode: XmlNode): Boolean
    begin
        IF pNodeText &lt;&gt; '' then
            pCreatedNode := XmlElement.Create(pNodeName, pNameSpace, pNodeText).AsXmlNode
        else
            pCreatedNode := XmlElement.Create(pNodeName, pNameSpace).AsXmlNode;
        pCreatedNode.AsXmlElement.Add(XmlAttribute.CreateNamespaceDeclaration(pPrefix, pNameSpace));
        exit(pXMLNode.AsXmlElement.Add(pCreatedNode));
    end;

    procedure AddPrefix(var pXMLNode: XmlNode; pPrefix: Text; pNameSpace: text): Boolean
    begin
        pXMLNode.AsXmlElement.Add(XmlAttribute.CreateNamespaceDeclaration(pPrefix, pNameSpace));
        exit(true);
    end;

    procedure AddAttribute(var pXMLNode: XmlNode; pName: Text; pValue: Text): Boolean
    begin
        pXMLNode.AsXmlElement.SetAttribute(pName, pValue);
        exit(true);
    end;

    procedure AddAttributeWithNamespace(var pXMLNode: XmlNode; pName: Text; pNameSpace: text; pValue: Text): Boolean
    begin
        pXMLNode.AsXmlElement.SetAttribute(pName, pNameSpace, pValue);
        exit(true);
    end;

    procedure FindNode(pXMLRootNode: XmlNode; pNodePath: Text; var pFoundXMLNode: XmlNode): Boolean
    begin
        exit(pXMLRootNode.SelectSingleNode(pNodePath, pFoundXMLNode));
    end;

    procedure GetRootNode(pXmlDoc: XmlDocument; var pFoundXMLNode: XmlNode): Boolean
    var
        lXmlElement : XmlElement;
    begin
        pXMLDoc.GetRoot(lXmlElement);
        pFoundXMLNode := lXmlElement.AsXmlNode;
    end;

    procedure FindNodeWithNameSpace(pXMLRootNode: XmlNode; pNodePath: Text; pPrefix: Text; pNamespace: Text; var pFoundXMLNode: XmlNode): Boolean
    var
        lXmlNsMgr: XmlNamespaceManager;
        lXMLDocument: XmlDocument;
    begin

        if pXMLRootNode.IsXmlDocument then
            lXmlNsMgr.NameTable(pXMLRootNode.AsXmlDocument.NameTable)
        else begin
            pXMLRootNode.GetDocument(lXMLDocument);
            lXmlNsMgr.NameTable(lXMLDocument.NameTable);
        end;
        lXMLNsMgr.AddNamespace(pPrefix, pNamespace);
        exit(pXMLRootNode.SelectSingleNode(pNodePath, lXmlNsMgr, pFoundXMLNode));
    end;

    procedure FindNodesWithNameSpace(pXMLRootNode: XmlNode; pXPath: Text; pPrefix: Text; pNamespace: Text; var pFoundXmlNodeList: XmlNodeList): Boolean
    var
        lXmlNsMgr: XmlNamespaceManager;
        lXMLDocument: XmlDocument;
    begin
        if pXMLRootNode.IsXmlDocument then
            lXmlNsMgr.NameTable(pXMLRootNode.AsXmlDocument.NameTable)
        else begin
            pXMLRootNode.GetDocument(lXMLDocument);
            lXmlNsMgr.NameTable(lXMLDocument.NameTable);
        end;
        lXMLNsMgr.AddNamespace(pPrefix, pNamespace);
        exit(FindNodesWithNamespaceManager(pXMLRootNode, pXPath, lXmlNsMgr, pFoundXmlNodeList));
    end;

    procedure FindNodesWithNamespaceManager(pXMLRootNode: XmlNode; pXPath: Text; pXmlNsMgr: XmlNamespaceManager; var pFoundXmlNodeList: XmlNodeList): Boolean
    begin
        IF not pXMLRootNode.SelectNodes(pXPath, pXmlNsMgr, pFoundXmlNodeList) then
            exit(false);
        IF pFoundXmlNodeList.Count = 0 then
            exit(false);
        exit(true);
    end;

    procedure FindNodeXML(pXMLRootNode: XmlNode; pNodePath: Text): Text
    var
        lFoundXMLNode: XmlNode;
    begin
        IF pXMLRootNode.SelectSingleNode(pNodePath, lFoundXMLNode) then
            Exit(lFoundXMLNode.AsXmlElement.InnerXml);
    end;

    procedure FindNodeText(pXMLRootNode: XmlNode; pNodePath: Text): Text
    var
        lFoundXMLNode: XmlNode;
    begin
        IF pXMLRootNode.SelectSingleNode(pNodePath, lFoundXMLNode) then
            Exit(lFoundXMLNode.AsXmlElement.InnerText);
    end;

    procedure FindNodeTextWithNameSpace(pXMLRootNode: XmlNode; pNodePath: Text; pPrefix: Text; pNamespace: Text): Text
    var
        lXmlNsMgr: XmlNamespaceManager;
        lXMLDocument: XmlDocument;
    begin

        if pXMLRootNode.IsXmlDocument then
            lXmlNsMgr.NameTable(pXMLRootNode.AsXmlDocument.NameTable)
        else begin
            pXMLRootNode.GetDocument(lXMLDocument);
            lXmlNsMgr.NameTable(lXMLDocument.NameTable);
        end;
        lXMLNsMgr.AddNamespace(pPrefix, pNamespace);
        Exit(FindNodeTextNs(pXMLRootNode, pNodePath, lXmlNsMgr));
    end;

    procedure FindNodeTextNs(pXMLRootNode: XmlNode; pNodePath: Text; pXmlNsMgr: XmlNamespaceManager): Text
    var
        lFoundXMLNode: XmlNode;
    begin
        IF pXMLRootNode.SelectSingleNode(pNodePath, pXmlNsMgr, lFoundXMLNode) then
            Exit(lFoundXMLNode.AsXmlElement.InnerText);
    end;

    procedure FindNodes(pXMLRootNode: XmlNode; pNodePath: Text; var pFoundXMLNodeList: XmlNodeList): Boolean
    begin
        IF not pXMLRootNode.SelectNodes(pNodePath, pFoundXmlNodeList) then
            exit(false);
        IF pFoundXmlNodeList.Count = 0 then
            exit(false);
        exit(true);
    end;

    procedure FindAttribute(pXMLNode: XmlNode; var pXmlAttribute: XmlAttribute; pAttributeName: Text): Boolean
    begin
        exit(pXMLNode.AsXmlElement.Attributes.Get(pAttributeName, pXmlAttribute));
    end;

    procedure GetAttributeValue(pXMLNode: XmlNode; pAttributeName: Text): Text
    var
        lXmlAttribute: XmlAttribute;
    begin
        If pXMLNode.AsXmlElement.Attributes.Get(pAttributeName, lXmlAttribute) then
            exit(lXmlAttribute.Value);
    end;

    procedure AddDeclaration(var pXMLDocument: XmlDocument; pVersion: Text; pEncoding: Text; pStandalone: Text)
    var
        lXmlDeclaration: XmlDeclaration;
    begin
        lXmlDeclaration := XmlDeclaration.Create(pVersion, pEncoding, pStandalone);
        pXMLDocument.SetDeclaration(lXmlDeclaration);
    end;

    procedure AddGroupNode(var pXMLNode: XmlNode; pNodeName: Text)
    var
        lXMLNewChild: XmlNode;
    begin
        AddElement(pXMLNode, pNodeName, '', '', lXMLNewChild);
        pXMLNode := lXMLNewChild;
    end;

    procedure AddNode(var pXMLNode: XmlNode; pNodeName: Text; pNodeText: Text)
    var
        lXMLNewChild: XmlNode;
    begin
        AddElement(pXMLNode, pNodeName, pNodeText, '', lXMLNewChild);
    end;

    procedure AddLastNode(var pXMLNode: XmlNode; pNodeName: Text; pNodeText: Text)
    var
        lXMLNewChild: XmlNode;
        lXMLElement: XmlElement;
    begin
        AddElement(pXMLNode, pNodeName, pNodeText, '', lXMLNewChild);
        if pXMLNode.GetParent(lXMLElement) then
            pXMLNode := lXMLElement.AsXmlNode;
    end;

    procedure AddNamespaces(var pXmlNsMgr: XmlNamespaceManager; pXMLDocument: XmlDocument)
    var
        lXmlAttributeCollection: XmlAttributeCollection;
        lXmlAttribute: XmlAttribute;
        lXMLElement: XmlElement;
    begin
        pXmlNsMgr.NameTable(pXMLDocument.NameTable);
        pXMLDocument.GetRoot(lXMLElement);
        lXmlAttributeCollection := lXMLElement.Attributes;
        IF lXMLElement.NamespaceUri &lt;&gt; '' then
            pXmlNsMgr.AddNamespace('', lXMLElement.NamespaceUri);
        Foreach lXmlAttribute in lXmlAttributeCollection do
        begin
            if StrPos(lXmlAttribute.Name, 'xmlns:') = 1 then
                pXmlNsMgr.AddNamespace(DELSTR(lXmlAttribute.Name, 1, 6), lXmlAttribute.Value);
        end;
    end;
    
    procedure AddNameSpace(var pXmlNsMgr: XmlNamespaceManager; pPrefix: text; pNamespace: text);
    begin
        pXmlNsMgr.AddNamespace(pPrefix, pNamespace);
    end;

    procedure XMLEscape(pText: Text): Text
    var
        lXMLDocument: XmlDocument;
        lRootXmlNode: XmlNode;
        lXmlNode: XmlNode;
    begin
        lXMLDocument := XmlDocument.Create;
        AddElement(lRootXmlNode, 'XMLEscape', pText, '', lXmlNode);
        exit(lXmlNode.AsXmlElement.InnerXml);
    end;

    procedure LoadXMLDocumentFromText(pXMLText: Text; var pXMLDocument: XmlDocument)
    begin
        IF pXMLText = '' then
            exit;
        XmlDocument.ReadFrom(pXMLText, pXMLDocument);
    end;

    procedure LoadXMLNodeFromText(pXMLText: Text; var pXMLNode: XmlNode)
    var
        lXmlDocument: XmlDocument;
    begin
        LoadXMLDocumentFromText(pXMLText, lXmlDocument);
        pXMLNode := lXmlDocument.AsXmlNode;
    end;

    procedure LoadXMLDocumentFromInStream(pInStream: InStream; var pXMLDocument: XmlDocument)
    begin
        XmlDocument.ReadFrom(pInStream, pXMLDocument);
    end;

    procedure LoadXMLNodeFromInStream(pInStream: InStream; var pXMLNode: XmlNode)
    var
        lXmlDocument: XmlDocument;
    begin
        LoadXMLDocumentFromInStream(pInStream, lXmlDocument);
        pXMLNode := lXmlDocument.AsXmlNode;
    end;

    procedure RemoveNamespaces(pXmlText: Text): Text
    var
        XMLDOMMgt: Codeunit "XML DOM Management";
    begin
        Exit(XMLDOMMgt.RemoveNamespaces(pXmlText));
    end;

    procedure SetUtf8Declaration(var pXMLDocument: XmlDocument);
    var
        Declaration : XmlDeclaration;
    begin
        Declaration := XmlDeclaration.Create('1.0', 'utf-8', 'yes');
        pXMLDocument.SetDeclaration(Declaration);
    end;
}
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/al-and-soap/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Unix Datetime UTC</title>
		<link>https://larswestman.se/unix-datetime-utc/</link>
					<comments>https://larswestman.se/unix-datetime-utc/#respond</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Mon, 23 Apr 2018 08:45:49 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=232</guid>

					<description><![CDATA[Here&#8217;s a little trick to generate a Unix Datetime in UTC. PROCEDURE DT2UnixDTUTC@81237(DtIn@81200 : DateTime) : BigInteger; VAR DtOffset@81203 : DotNet "'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.DateTimeOffset"; DtUtc@81206 : DateTime; Duration@81208 : Duration; TempDate@81209 : Date; TempTime@81210 : Time; BEGIN EVALUATE(TempDate, COPYSTR(FORMAT(DtIn, 0, 9), 1, 10)); EVALUATE(TempTime, COPYSTR(FORMAT(DtIn, 0, 9), 12, 8)); DtUtc := CREATEDATETIME(TempDate, TempTime); Duration [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Here&#8217;s a little trick to generate a Unix Datetime in UTC.</p>
<pre> PROCEDURE DT2UnixDTUTC@81237(DtIn@81200 : DateTime) : BigInteger;
 VAR
   DtOffset@81203 : DotNet "'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.DateTimeOffset";
   DtUtc@81206 : DateTime;
   Duration@81208 : Duration;
   TempDate@81209 : Date;
   TempTime@81210 : Time;
 BEGIN
   EVALUATE(TempDate, COPYSTR(FORMAT(DtIn, 0, 9), 1, 10));
   EVALUATE(TempTime, COPYSTR(FORMAT(DtIn, 0, 9), 12, 8));
   DtUtc := CREATEDATETIME(TempDate, TempTime);
   Duration := DtIn - DtUtc;
   DtOffset := DtOffset.DateTimeOffset(DtIn);
   EXIT(DtOffset.ToUnixTimeMilliseconds + Duration);
 END;</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/unix-datetime-utc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Json, REST and Zendesk</title>
		<link>https://larswestman.se/json-rest-and-zendesk/</link>
					<comments>https://larswestman.se/json-rest-and-zendesk/#comments</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Thu, 07 Sep 2017 12:20:48 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C/AL]]></category>
		<category><![CDATA[Json]]></category>
		<category><![CDATA[REST]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=223</guid>

					<description><![CDATA[Many of us have been using XML and SOAP for a long time now. This time my task was to create tickets in Zendesk based on events in NAV. I soon discovered that Zendesk uses REST web services and that it talks Json&#8230;. 😯 I soon found Gunnar Gestssons blog post on &#8220;JSON meets NAV&#8220;. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Many of us have been using XML and SOAP for a long time now. This time my task was to create tickets in Zendesk based on events in NAV. I soon discovered that Zendesk uses REST web services and that it talks Json&#8230;. <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/1f62f.png" alt="😯" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>I soon found Gunnar Gestssons blog post on &#8220;<a href="http://www.dynamics.is/?p=2303" target="_blank">JSON meets NAV</a>&#8220;. Many thanks to Gunnar for doing the hard work! All I did was some tweaking to make it work with Zendesk.</p>
<p>On the link below you&#8217;ll find a textfile with two codeunits (99100 and 99101). 99100 is based on Gunnars work and in 99101 there&#8217;s some code which shows how to work with Zendesk. All you need to do is to setup a Zendesk trial account and do some setup there (more details in the documentation trigger in cu 99101). Then change some hard coded parameters in codeunit 99101 and you can create tickets in Zendesk.</p>
<p>I hope this can be useful for some of you guys out there. Enjoy!</p>
<p>Objects: <a href="https://larswestman.se/wp-content/uploads/2017/09/Zendesk-demo.txt" rel="">Zendesk demo</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/json-rest-and-zendesk/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Blocked add-in files after copying CU-files to an existing NAV installation</title>
		<link>https://larswestman.se/issues-with-add-ins-after-copying-cu-files-to-an-existing-nav-installation/</link>
					<comments>https://larswestman.se/issues-with-add-ins-after-copying-cu-files-to-an-existing-nav-installation/#respond</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Thu, 19 Jan 2017 09:24:28 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=216</guid>

					<description><![CDATA[Have you ever had problems with add-in&#8217;s after you have copied files from a CU to an existing installation? The reason can be that the dll&#8217;s are blocked since they are downloaded from internet to your local hard drive. Windows keeps track of zone information as meta data linked to each file and block the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Have you ever had problems with add-in&#8217;s after you have copied files from a CU to an existing installation? The reason can be that the dll&#8217;s are blocked since they are downloaded from internet to your local hard drive. Windows keeps track of zone information as meta data linked to each file and block the files by default. There are a couple of approaches to solve this problem:</p>
<ul>
<li>Unblock an individual file by right clicking the file and click the checkbox to unblock.</li>
<li>Open Windows PowerShell or an elevated Windows PowerShell depending on if your user account has access rights to where the folder containing the blocked file(s) is located and execute this: get-childitem -recurse |Unblock-File</li>
<li>Completely disable the zone blocking ib the gpe: <a href="http://winaero.com/blog/disable-downloaded-files-from-being-blocked-in-windows-10/" target="_blank">http://winaero.com/blog/disable-downloaded-files-from-being-blocked-in-windows-10/</a></li>
</ul>
<p>Happy updating <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/issues-with-add-ins-after-copying-cu-files-to-an-existing-nav-installation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Data Exchange Definition for Yahoo Exchange Rates in NAV2016</title>
		<link>https://larswestman.se/data-exchange-definition-for-yahoo-exchange-rates-in-nav2016/</link>
					<comments>https://larswestman.se/data-exchange-definition-for-yahoo-exchange-rates-in-nav2016/#comments</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Fri, 01 Apr 2016 09:05:32 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=210</guid>

					<description><![CDATA[It seems as there&#8217;s some issue with the Data Exchange Definition for Yahoo! Exchange Rates that NAV creates automatically when you open the Exchange Rates Services. When I previewed the exchange rates I got an empty list. The debugger showed that there&#8217;s an error in a try function because of the file format doesn&#8217;t correspond [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>It seems as there&#8217;s some issue with the Data Exchange Definition for Yahoo! Exchange Rates that NAV creates automatically when you open the Exchange Rates Services. When I previewed the exchange rates I got an empty list. The debugger showed that there&#8217;s an error in a try function because of the file format doesn&#8217;t correspond to the field mappings in the Data Exchange Definition.</p>
<p>I didn&#8217;t want to spend more time on this than necessary, so I removed the definition, exported the same definition from a Cronus database and imported it in the customers database and it all started to work.</p>
<p>BTW: When you import a definition you must change field type in the import dialog. The developer at Microsoft forgot to set it to xml. Otherwise you wont find the xml-file.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/data-exchange-definition-for-yahoo-exchange-rates-in-nav2016/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>TableType::ExternalSQL</title>
		<link>https://larswestman.se/tabletypeexternalsql/</link>
					<comments>https://larswestman.se/tabletypeexternalsql/#comments</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Wed, 23 Mar 2016 14:04:41 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=200</guid>

					<description><![CDATA[One very cool feature in NAV2016 is the table type &#8220;ExternalSQL&#8221;. In older versions you had to use a view in SQL for each table and set the property LinkedObject. Now you don&#8217;t have to do that any more. Let&#8217;s take a look at it: Here you can see how you can use TableType, ExternalName [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>One very cool feature in NAV2016 is the table type &#8220;ExternalSQL&#8221;. In older versions you had to use a view in SQL for each table and set the property LinkedObject. Now you don&#8217;t have to do that any more.</p>
<p>Let&#8217;s take a look at it:</p>
<p><a href="https://larswestman.se/wp-content/uploads/2016/03/table.jpg" rel="attachment wp-att-201"><img decoding="async" class="alignnone size-full wp-image-201" src="https://larswestman.se/wp-content/uploads/2016/03/table.jpg" alt="table" width="280" height="335" srcset="https://larswestman.se/wp-content/uploads/2016/03/table.jpg 280w, https://larswestman.se/wp-content/uploads/2016/03/table-251x300.jpg 251w" sizes="(max-width: 280px) 100vw, 280px" /></a></p>
<p>Here you can see how you can use TableType, ExternalName and ExternalSchema instead of LinkedObject. In NAV this table is called &#8220;My Table&#8221; but in SQL it&#8217;s called &#8220;mytable&#8221;.</p>
<p>You can also set ExternalName for fields. Below I want to use the field name &#8220;No.&#8221; although it&#8217;s called &#8220;number&#8221; in the SQL table.</p>
<p><a href="https://larswestman.se/wp-content/uploads/2016/03/field.jpg" rel="attachment wp-att-202"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-202" src="https://larswestman.se/wp-content/uploads/2016/03/field.jpg" alt="field" width="628" height="588" srcset="https://larswestman.se/wp-content/uploads/2016/03/field.jpg 628w, https://larswestman.se/wp-content/uploads/2016/03/field-300x281.jpg 300w" sizes="auto, (max-width: 628px) 100vw, 628px" /></a></p>
<p>&nbsp;</p>
<p>The connection to the server, database and the user credentials is controlled with C/AL.</p>
<p>Here&#8217;s a sample:</p>
<pre>UNREGISTERTABLECONNECTION(TABLECONNECTIONTYPE::ExternalSQL, 'MyDatabaseName');

REGISTERTABLECONNECTION(TABLECONNECTIONTYPE::ExternalSQL, 'MyDatabaseName', 'Data Source='MyServerName';Initial Catalog='MyDatabaseName';User ID='MySQLUserID';Password='MyPassword');

SETDEFAULTTABLECONNECTION(TABLECONNECTIONTYPE::ExternalSQL, 'MyDatabaseName');
</pre>
<p>This code will first try to unregister any existing connection to the database I want to connect to. Then it will register using a connectionstring (which you of course shouldn&#8217;t hard code like this) and then it will set the connection as the default connection.</p>
<p>The connection needs to be established on each login so it would make sense to store server name, database name and credentials in a setup table and register the datasource on login.</p>
<p>According to the MSDN documentation any rollbacks will also take place in the external tables. I haven&#8217;t tested that myself though.</p>
<p>I&#8217;m on my first project using this feature so I&#8217;ll probably update this post later on when I&#8217;ve got some more time on this functionality.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/tabletypeexternalsql/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title>AltSearchField in NAV2016</title>
		<link>https://larswestman.se/altsearchfield-in-nav2016/</link>
					<comments>https://larswestman.se/altsearchfield-in-nav2016/#comments</comments>
		
		<dc:creator><![CDATA[Lars Westman]]></dc:creator>
		<pubDate>Fri, 12 Feb 2016 09:33:04 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C/AL]]></category>
		<guid isPermaLink="false">http://larswestman.se/?p=191</guid>

					<description><![CDATA[The property AltSearchField is removed in NAV2016 but importing an object from NAV2015/2013 which had that property set will still keep the property value even though it&#8217;s not visible in the development environment. This might not be an issue until you try to rename the field that is set as AltSearchField. Then you&#8217;ll end up [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The property AltSearchField is removed in NAV2016 but importing an object from NAV2015/2013 which had that property set will still keep the property value even though it&#8217;s not visible in the development environment.</p>
<p>This might not be an issue until you try to rename the field that is set as AltSearchField. Then you&#8217;ll end up with an error like &#8220;You cannot enter &#8216;YourSearchName&#8217; in FieldNo.&#8221;. The only way to solve this is to export the object to a txt file and manually remove the property.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://larswestman.se/altsearchfield-in-nav2016/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/


Served from: larswestman.se @ 2026-04-19 17:03:05 by W3 Total Cache
-->