Showing posts with label C/AL Programming. Show all posts
Showing posts with label C/AL Programming. Show all posts

Friday, October 21, 2016

DATA MIGRATION IN NAV 2016 FROM NAV 2009

DATA MIGRATION IN NAV 2016 FROM NAV 2009
Hi all,
Today i came across with different type of requirement, Sometimes we need to move/Copy our NAV data from one Database to others, OR One server to other server.
we can do this task using "Departments -> Administration -> Application Setup -> RapidStart Services for Microsoft Dynamics NAV -> Config. Package Card.
Note: In this scenario, BLOB fields are not copied, Due to overcome this we have to do using SQL Server.
But Now today i am going to talk about Data migration using Rapid Start Services.
Look guys, Earlier we are simply Export the Excel format and Import it, but in NAV 2016 if we go for import we will get exception, see the bellow screenshot.



To Overcome this we need to customize our NAV 2009 Objects, But before going i just want to tell you why this issue came.
See the bellow screenshot of NAV 2016 Excel file, there i marked PackageCode that are added.



You can also check NAV 2009 Excel, In that you can’t find PackageCode.
So now our job to add this PackageCode in NAV 2009 Excel file, To do this we have to customize several objects, these are as:
                Table ID                :               8613, 8614, 8615, 8616
                Form ID                                :               8614
                XmlPort ID          :               8610
                Codeunit ID        :               8611
                                In this Codeunit we have to upgrade 2 functions, these are as:
ExportSetupDataToExcel
CreateRecordNodes
Step 1:  Add the PackageCode field of type Code in Tables 8613, 8614, 8615, 8616.
In Table 8614 and 8615 give the Table relation to 8613 i.e. ”Migration Table”.
After adding the field write code for initializing the PackageCode, See the bellow screenshot.

               



Step 2:  Add codes in Codeunit 8611 ”Migration Management”, in this codeunit we have to upgrade two function as earlier i discussed. These are
                                ExportSetupDataToExcel
CreateRecordNodes
See the bellow screenshot for added code.



Find the ExportSetupDataToExcel function and update as like in screenshot.



Now update the second function i.e. ”CreateRecordNodes”, See the bellow screenshot
Note:    In Both images only the customize code, remaing Upper and lower code as in standard.
                Just match the code something like:
For ExportDataSetupToExcel find the CreateBook and start writting from screenshot, because some code are removed.
Also go thru something like other function called ”CreateRecordNodes”.





Now Compile, Save, Exit from this codeunit.

Step 3:  In this step we are going to upgrade XmlPort 8610 "Setup Data Schema" something like NAV 2016.
Design  XmlPort 8610 "Setup Data Schema" and upgrade as it is in bellow screenshot.



After designing the Xmlport Open the CAL Editor in this Xmlport only. And make changes



Now Compile, Save, and exit from this Xmlport.
Step 4:  Upgrade the Form 8614 ”Migration Overview” , Add the PackageCode field, so we can export.
See the bellow screenshot for Form, and update as it is.




Compile, Save & Exit from this form.

Step 5:  Now export the Data from Data migration, see the bellow screenshot.



Note: Whatever you given here PackageCode value that you need to give in NAV 2009.
Also remeber onething still it create a .xls file, So you have to just open and save as .xlsx format.
Also remeber one thing, if you are going to export multiple tables then you have to delete manually Sheet1 from exported file, it creates by default sheet1 extra. So to avoid exception delete manually sheet1.
See the bellow screenshot for exported excel file from NAV 2009 after upgraded.
Once the file is exported and save as with .xlsx, then you can import in NAV 2016 directly.


                                                       

Step 6 :                                         Now i am going to import this file. See the bellow screenshot.











Wednesday, October 5, 2016

Creating/Populating the Sales & Purchase Journal from Ledger/Buffer Table in NAV

Hi all,
Today i came across with different type of requirement, Sometimes we need to populate/Create Journals thru codding.


Bellow are the whole codeunit with business logic.

OBJECT Codeunit 50081 Populate Journals
{
  OBJECT-PROPERTIES
  {
    Date=10/05/16;
    Time=[ 6:33:05 AM];
    Modified=Yes;
    Version List=Sbinesh;
  }
  PROPERTIES
  {
    OnRun=BEGIN
            CLEARLASTERROR;
            IF NOT PopulateSalesJournal THEN
              ERROR('Not populated, for more info read bellow lines\\%1',GETLASTERRORTEXT);
            IF NOT PopulatePurchaseJournal THEN
              ERROR('Not populated, for more info read bellow lines\\%1',GETLASTERRORTEXT);
          END;

  }
  CODE
  {

    [TryFunction]
    PROCEDURE PopulateSalesJournal@1000000000();
    VAR
      GenJournalTemplate@1000000006 : Record 80;
      GenJournalLine@1000000005 : Record 81;
      GenJournalBatch@1000000004 : Record 232;
      CustLedgerEntry@1000000003 : Record 21;
      CustLedgerEntryBuffer@1000000002 : Record 80021;
      GenJournalTemplateName@1000000001 : Text;
      GenJournalBatchName@1000000000 : Text;
      LineNo@1000000007 : Integer;
      MyDialog@1000000008 : Dialog;
      CountL@1000000009 : Integer;
    BEGIN
      IF GenJournalTemplate.GET('SALES') THEN
        GenJournalTemplateName := GenJournalTemplate.Name;

      IF GenJournalBatch.GET(GenJournalTemplateName,'DEFAULT') THEN
        GenJournalBatchName := GenJournalBatch.Name;

      CustLedgerEntryBuffer.RESET;
      IF CustLedgerEntryBuffer.FINDSET THEN BEGIN
        GenJournalLine.RESET;
        GenJournalLine.SETRANGE(GenJournalLine."Journal Template Name",GenJournalTemplateName);
        GenJournalLine.SETRANGE(GenJournalLine."Journal Batch Name",GenJournalBatchName);
        IF GenJournalLine.FINDLAST THEN
          LineNo := GenJournalLine."Line No."
        ELSE
          CLEAR(LineNo);
        MyDialog.OPEN('Record populating... #1###############');
        REPEAT
          LineNo += 10000;
          GenJournalLine.INIT;
          GenJournalLine.VALIDATE(GenJournalLine."Journal Template Name",GenJournalTemplateName);
          GenJournalLine.VALIDATE(GenJournalLine."Journal Batch Name",GenJournalBatchName);
          GenJournalLine.VALIDATE("Line No.",LineNo);
          GenJournalLine.VALIDATE(GenJournalLine."Posting Date",CustLedgerEntryBuffer."Posting Date");
          GenJournalLine.VALIDATE(GenJournalLine."Document Type",CustLedgerEntryBuffer."Document Type");
          GenJournalLine.VALIDATE(GenJournalLine."Document No.",CustLedgerEntryBuffer."Document No.");
          GenJournalLine.VALIDATE(GenJournalLine."Account Type",GenJournalLine."Account Type"::Customer);//Bcoz in Buffer table 1 option is there.
          GenJournalLine.VALIDATE(GenJournalLine."Account No.",CustLedgerEntryBuffer."Account No.");
          GenJournalLine.VALIDATE(GenJournalLine.Description,CustLedgerEntryBuffer.Description);
          GenJournalLine.VALIDATE(GenJournalLine.Amount,CustLedgerEntryBuffer."Remaining Amount");
          GenJournalLine.VALIDATE(GenJournalLine."Bal. Account Type",GenJournalLine."Bal. Account Type"::"G/L Account");
          GenJournalLine.VALIDATE(GenJournalLine."Bal. Account No.",'31040');
          GenJournalLine.VALIDATE(GenJournalLine."External Document No.",CustLedgerEntryBuffer."External Document No.");
          GenJournalLine.VALIDATE(GenJournalLine."Due Date",CustLedgerEntryBuffer."Due Date");
          GenJournalLine.VALIDATE(GenJournalLine."Document Date",CustLedgerEntryBuffer."Document Date");
          GenJournalLine.VALIDATE(GenJournalLine."Territory Code",CustLedgerEntryBuffer."Territory Code");
          GenJournalLine.VALIDATE(GenJournalLine."Ship-to Territory Code",CustLedgerEntryBuffer."Ship-to Territory Code");
          GenJournalLine.VALIDATE(GenJournalLine."Salespers./Purch. Code",CustLedgerEntryBuffer."Salesperson Code");
          GenJournalLine.VALIDATE(GenJournalLine."Ship-to Salesperson Code",CustLedgerEntryBuffer."Ship-to Salesperson Code");
          GenJournalLine.VALIDATE(GenJournalLine."Mark Text",CustLedgerEntryBuffer."Mark Text");
          GenJournalLine.VALIDATE(GenJournalLine."Payment Terms Code",CustLedgerEntryBuffer."Payment Terms Code");
          GenJournalLine.INSERT(TRUE);
          CountL += 1;
          MyDialog.UPDATE(1,CountL);
        UNTIL CustLedgerEntryBuffer.NEXT = 0;
      END;
      MyDialog.CLOSE();
      MESSAGE('[%1] record(s) populated!',CountL);
    END;

    [TryFunction]
    PROCEDURE PopulatePurchaseJournal@1000000002();
    VAR
      GenJournalTemplate@1000000006 : Record 80;
      GenJournalLine@1000000005 : Record 81;
      GenJournalBatch@1000000004 : Record 232;
      VendorLedgerEntry@1000000003 : Record 25;
      VendorLedgerEntryBuffer@1000000002 : Record 80025;
      GenJournalTemplateName@1000000001 : Text;
      GenJournalBatchName@1000000000 : Text;
      LineNo@1000000007 : Integer;
      MyDialog@1000000008 : Dialog;
      CountL@1000000009 : Integer;
    BEGIN
      IF GenJournalTemplate.GET('PURCHASES') THEN
        GenJournalTemplateName := GenJournalTemplate.Name;

      IF GenJournalBatch.GET(GenJournalTemplateName,'DEFAULT') THEN
        GenJournalBatchName := GenJournalBatch.Name;

      VendorLedgerEntryBuffer.RESET;
      IF VendorLedgerEntryBuffer.FINDSET THEN BEGIN
        GenJournalLine.RESET;
        GenJournalLine.SETRANGE(GenJournalLine."Journal Template Name",GenJournalTemplateName);
        GenJournalLine.SETRANGE(GenJournalLine."Journal Batch Name",GenJournalBatchName);
        IF GenJournalLine.FINDLAST THEN
          LineNo := GenJournalLine."Line No."
        ELSE
          CLEAR(LineNo);
        MyDialog.OPEN('Record populating... #1###############');
        REPEAT
          LineNo += 10000;
          GenJournalLine.INIT;
          GenJournalLine.VALIDATE(GenJournalLine."Journal Template Name",GenJournalTemplateName);
          GenJournalLine.VALIDATE(GenJournalLine."Journal Batch Name",GenJournalBatchName);
          GenJournalLine.VALIDATE("Line No.",LineNo);
          GenJournalLine.VALIDATE(GenJournalLine."Posting Date",VendorLedgerEntryBuffer."Posting Date");
          GenJournalLine.VALIDATE(GenJournalLine."Document Type",VendorLedgerEntryBuffer."Document Type");
          GenJournalLine.VALIDATE(GenJournalLine."Document No.",VendorLedgerEntryBuffer."Document No.");
          GenJournalLine.VALIDATE(GenJournalLine."Account Type",GenJournalLine."Account Type"::Vendor);
          GenJournalLine.VALIDATE(GenJournalLine."Account No.",VendorLedgerEntryBuffer."Account No.");
          GenJournalLine.VALIDATE(GenJournalLine.Description,VendorLedgerEntryBuffer.Description);
          GenJournalLine.VALIDATE(GenJournalLine.Amount,VendorLedgerEntryBuffer."Remaining Amount");
          GenJournalLine.VALIDATE(GenJournalLine."Bal. Account Type",GenJournalLine."Bal. Account Type"::"G/L Account");
          GenJournalLine.VALIDATE(GenJournalLine."Bal. Account No.",'31040');
          GenJournalLine.VALIDATE(GenJournalLine."External Document No.",VendorLedgerEntryBuffer."External Document No.");
          GenJournalLine.VALIDATE(GenJournalLine."Due Date",VendorLedgerEntryBuffer."Due Date");
          GenJournalLine.VALIDATE(GenJournalLine."Document Date",VendorLedgerEntryBuffer."Document Date");
          GenJournalLine.VALIDATE(GenJournalLine."Payment Terms Code",VendorLedgerEntryBuffer."Payment Terms Code");
          GenJournalLine.VALIDATE(GenJournalLine."Salespers./Purch. Code",VendorLedgerEntryBuffer."Purchaser Code");
          GenJournalLine.INSERT(TRUE);
          CountL += 1;
          MyDialog.UPDATE(1,CountL);
        UNTIL VendorLedgerEntryBuffer.NEXT = 0;
      END;
      MyDialog.CLOSE();
      MESSAGE('[%1] record(s) populated!',CountL);
    END;

    BEGIN
    {
      October, 05 2016 :  This codeunit is developed for creating the Sales & Purchase Journal from buffer table.
                          Cust. Ledger Entry Buffer table contains the mandatory fields from Cust. Ledger Entry.
                          Vendor Ledger Entry Buffer table contains the mandatory fields from Vendor Ledger Entry.
      Solution Developed by Binesh Singh Rajput
    }
    END.
  }
}


You can download this solution from here.
 

Thursday, July 14, 2016

Print & Open any document in NAV using DotNet Variables.

Hi all,
Today i came across with different type of requirement, where someone asking for how could we Print & Open any document in NAV using DotNet Variables.

This Generic solution for Running/Opening and Printing any document, without any custom dlls, that always works, whenever, however, with any software, as long as you have “any” software installed that can Open & print that “any”-document with any extension ...
In-case if not Open or Print, it should give an error notification regarding failure...

To achieve these requirement i created two functions, and declared local dotnet variables for both functions, where as FileNameWithPathG is a Global Text variable.

See the bellow screenshot for better understanding.










Tuesday, June 21, 2016

How You Can Take Input From End User In Codeunit Object

How You Can Take Input From End User In Codeunit Object

Hi all,
Today i came across with different type of requirement, where someone asking for how could we input from codeunit.
This example illustrates how you can take input from end user in Codeunit Object.
And update the excel sheet from inputted data, using dotnet variables.
To achieve these requirement follow these steps:

Step 1:  Create a new codeunit.
Step 2:  Create function "CreatePopOfWindow" and  "UpdateExcelData" See the bellow screenshot].







Excel Function:



Excel Variable:




Step 3:  Save, Compile and run the newly created codeunit, See the bellow screenshot].




Scenario - 1:




Scenario - 2:







Click Here for download Object.
Note: 
    It might be changed the version of variables, so better to Re-define/declare the DotNet variables.




Tuesday, June 14, 2016

How to: Implement Location in C/AL NAV 2016

How to: Implement Location in C/AL NAV 2016
This example illustrates how you can retrieve location information. The example implements a GetLocation action on the Customer Card (page 21) that returns the GPS coordinates of the current customers address. It does not save this information to the database. Scenarios in which this functionality could be useful would be displaying a map that shows where your customer is located based on the GPS coordinates. Or, functionality to plan the next round of customer visits based on the addresses of your customers.
Important
The location information is only available on devices that run the Microsoft Dynamics NAV Universal App and have GPS capabilities. This means that location information is not available from the Microsoft Dynamics NAV Windows client or from a browser.
To implement location in C/AL
  1. In the development environment, on the Tools menu, choose Object Designer to open the Object Designer window.
  2. In Object Designer, choose Pages, select the Customer Card (page 21) and then choose the Design button.
  3. From the Page Designer window, on the View menu, choose C/AL Globals.
  4. Create the following variable:
Variable name
DataType
SubType
Location
DotNet
Microsoft.Dynamics.Nav.Client.Capabilities.LocationProvider
Important
Choose the Microsoft.Dynamics.Nav.ClientExtensions dll on the Server tab, and then choose Microsoft.Dynamics.Nav.Client.Capabilities.LocationProvider
Make sure to set the properties RunOnClient and WithEvents to Yes.
LocationAvailable
Boolean
  1. On the View menu, select C/AL Code and in the C/AL Editor locate the OnOpenPage trigger.
  2. Instantiate the Location variable by adding the following code to the OnOpenPage trigger.

Copy Code
IF Location.IsAvailable THEN
BEGIN
  Location := Location.Create;
  LocationAvailable := TRUE;
END;
             
           See the bellow screenshot of OnOpenPage Trigger



  1. Next, create the page action. Choose the View menu, and then select Page Actions. 
  1. Locate the ActionGroup named Customer and create a new action; GetLocation with the following properties.
Property
Value
Name
GetLocation
Visible
LocationAvailable
Promoted
Yes
PromotedCategory
Process
PromotedIsBig
Yes

           See the bellow screenshot of GetLocation action Trigger




  1. Now, in the C/AL Editor, on the GetLocation - OnAction trigger, insert the following line of code.
 Copy Code
Location.RequestLocationAsync;

        See the bellow screenshot of GetLocation - OnAction Trigger



  1. While still in the C/AL Editor, on the LocationChanged trigger add the following code to handle the GPS coordinates. LocationChanged is called when the device has obtained a status.

Copy Code
Location::LocationChanged(Location : DotNet "Microsoft.Dynamics.Nav.Client.Capabilities.Location")
IF(Location.Status = 0) THEN
  MESSAGE('Your position: %1 %2',
  Location.Coordinate.Latitude,Location.Coordinate.Longitude)                               
ELSE
  MESSAGE('Position not available');
Important
Location.Status can be 0 = Available, 1 = NoData (no data could be obtained), 2 = TimedOut (location information not obtained in due time), or 3 = NotAvailable (for example user denied app access to location).

           See the bellow screenshot of Location::LocationChanged Trigger


  1. Close the C/AL Editor, and then save and compile the page.
  2. You can now test the modified Customer Card page in the Microsoft Dynamics NAV Universal App from either a tablet or a phone with GPS capabilities.


LocationOptions Overview

Microsoft Dynamics NAV 2016

When implementing location from C/AL, there are some options that you can optionally pass toLocationProvider.RequestLocationAsync(options)
The options can be accessed by usingMicrosoft.Dynamics.Nav.Client.Capabilities.LocationOptions found in the Microsoft.Dynamics.Nav.ClientExtensionsdll.
For most scenarios it is not necessary to specify options.

Location Options List

bool EnableHighAccuracy
A value to provide a hint to the device that this request must have the best possible location accuracy.
int Timeout
The maximum length of time (milliseconds) that is allowed to pass to a location request.
int MaximumAge
The maximum length of time (milliseconds) of a cached location.



References:   MSDN





Popular Posts