Universal klient eksport import

Navision og Business Central tilbyder allerede forskellige måder at udrulle mandanter på og - i princippet - at importere dem til en anden database. Desværre fungerer disse ofte ikke som ønsket, forventet eller håbet. Her tilbyder jeg dig en enkel (!) OG universel mulighed. Men selvfølgelig kan denne heller ikke udrette mirakler. For mirakler i Navision, Dynamics, Financials og Business Central skal du allerede kontakte mig direkte.

Anvendelsestilfælde (Eksempler)

Cronus lejer eller gendanner

Det var den oprindelige anmodning til denne funktion. I en kundedatabase havde systemhuset slettet Cronus-mandanten. Hvorfor? Aner det ikke. Det var i hvert fald en dum idé. Jeg har også haft kunder, der ved et uheld har slettet Cronus AG. Og så opdager man (også jeg), at en enkelt mandant ikke er så nem at gendanne! Så man lever med det, at Cronus AG slettet forbliver. Men: Det behøver ikke at være sådan!

Opret testmiljø

Jeg ville ikke bruge denne funktion til det, der er her og her en bedre metode til det. Men hvis det gør dig glad…

Overførsel af en tilpasset database til en standarddatabase

Dette er i sandhed en meget praktisk anvendelse! Antag, at du har en meget uheldigt bøjet database fra Navision eller Business Central, og ønsker desperat at skifte til en standard Navision-version i samme releaseversion. Min universelle eksport giver alle datafelter for alle tabeller som findes. Den tilhørende universel import hingegen indlæser kun de felter i tabellerne, som i måldatabasen findes. Jeg tror, ​​at selv denne funktion vil opfylde mange ønsker. Selvfølgelig er der også massive begrænsninger her. For eksempel vil du aldrig kunne køre en Food Vision-version, uanset hvilken, i en standardversion. Tilpasningerne (hvis man overhovedet kan kalde dem det) foretaget af Modus griber også så dybt ind i standarden for Navision og Business Central, at det kræver intensiv behandling. Dette gælder selvfølgelig ikke kun for Foodvision, men for mange Brancheløsninger. Lider du også af en dårligt sammensat branchenløsning?

Opdatering af Navision på tværs af versionsgrænser

Ofte er forskellene mellem store versionsskift (f.eks. mellem Navision Dynamics 2015 og Navision Dynamics 2016) ikke så store, at man kan prøve sig frem for at se, hvor langt man kommer med denne hammer. Der er dog også versionsskift, som griber så massivt ind i datastrukturen, at man mindst skal foretage en masse efterarbejde på de overtagede data. Man kunne f.eks. i de tidligere Navision-versioner stadig problemfrit håndtere tabel 339 Artikelaftale-poster slet simpelthen. I senere versioner er tabel 339, udligningsposter for artikler, afgørende for -der gang på gang førte til munterhed- Lagerstyring. Omstillingen til værdiposter og detaljer om debitor/kreditor-poster ville også gøre en fungerende overførsel fra FØR værdipostdatabaser til EFTER værdipostdatabaser umulig. Men er det måske nok til at kunne se en gammel klient i selv et ultramoderne Navision / Business Central? Hvis du anvender denne funktion her, vil du vide, hvad du gør... ellers kontakt mig hellereMåske vil du også bare se din 2009R2-database i RTC uden for meget besvær? Du har alligevel Cronus i en ny demoinstallation. Med dette lille værktøj her kan du dog også nemt overføre en rigtig mandant, diverse statistikker, ordremodtagelse, debitoroplysninger og meget mere vil i det mindste fungere en smule.

Manipulation af data

Ja... en meget interessant brugsmulighed. Udlæs klient, modificer data, læs klient tilbage... Jeg fraråder det stærkt!

Udskriv alle data til analyse

Dette kan igen være ret praktisk. Du kan eksportere alle data, som din Navision kender, ud i datafiler på én gang og derefter indlæse de ønskede data via f.eks. en CSV-driver i Access eller Excel. Men også her vil jeg andre metoder vælge.

Udskriv alle data til systemændring

Virkelig? Du vil afskaffe Navision/Business Central? Hvorfor? Gør det ikke! Selvom det hedder, at man ikke skal holde rejsende tilbage, er jeg ikke så glad for Navision og Business Central. Sandsynligvis har du haft dårlige erfaringer med Navision eller Business Central hidtil? Skal vi give det et forsøg sammen?

Tidligere metoder til at eksportere og importere klienter fra Navision / Business Central

Eksporter til en datafil / Importer fra en datafil

Har du funktionen(e) Eksporter til en datafil eller. Importer fra en datafil Allerede én gang kaldt under RTC? Hvis du har været med et stykke tid: Kom det dig bekendt? Korrekt! Det er den gamle datasikkerhed, som du kunne kalde i det gamle Navision via Ekstra/Datasikkerhed!

Oversigt over funktionen "Eksporter til datafil" i RTC: Det er den gamle datasikkerhedskopi!
„Eksporter til datafil“ i RTC: Det er den tidligere datasikkerhedskopi!
Visning af funktionen "Opret sikkerhedskopi" i den gamle 2009-klient: Dette er grundlaget for "Eksporter til datafil"!
Skærmbillede af funktionen „Opret sikkerhedskopi“ i den gamle klient fra 2009: Dette er grundlaget for „Eksporter til datafil“!

Og dermed har du også lignende begrænsninger. Hvis du kun eksporterer én enkelt klient her (med de mindste data) og ønsker at importere den til en anden database, skal kilde- og måldatabasen være 100%(snarere 110% ) identiske. Selv udvidelser skal være absolut identiske, selv hvis de slet ikke ændrer datastrukturer eller ikke er aktive. Derudover kodes dataene under eksporten, så klartekstbehandling ikke er mulig.

Til alle ovennævnte anvendelsesscenarier er en migrering af klienter fra en database til en anden database derfor med denne funktion praktisk talt umuligt.

Dette gælder også for den tilsvarende Powershell-kommando, som kalder den samme Navision-funktion.

Export-NAVData -Serverinstans  -Tenant  -CompanyName "" -FilePath

Teknisk set er både PowerShell-kommandoen og funktionen Eksporter til en datafil intet andet end kaldet af den (relativt nye) kommando [Database.]ExportérData:

Kaldning af Navision / Business Central-kommandoen ExportData direkte via programkoden genererer de samme filer som Eksporter til datafil, faktisk en gammel Navision-sikkerhedskopi.

Hvis du har søgt og fundet denne side, ved du sikkert allerede, at den ikke er egnet til de beskrevne anvendelsestilfælde.

Konfigurationspakker / Rapidstart / Dataeksport (tidligere GdPDU-eksport)

Dataeksport lader jeg ligge her, de er for specifikke, men kan bestemt også være det rette værktøj! Tidligere hed de GdPDU Eksport, hvilket allerede giver et fingerpeg om det egentlige formål.

Konfigurationspakkerne (tidligere navn: Rapidstart) er et utroligt fedt værktøj, som er blevet en ægte schweizerkniv på tværs af de forskellige versioner.
Du kan bruge den til at sende ALLE data fra Navision til Excel (ja... „alle“ op til 2 millioner dataposter...) og også læse en masse data tilbage. „Meget“ er begrænset til tabeller, der ikke er skrivebeskyttede. Så ingen bogførte dokumenter som salgsfakturaer, følgesedler, registrerede rykkere ... og bogførte varer (vareposter, værdiposter, debitorposter ...). Bortset fra dette anbefales det dog stærkt, at du sætter dig ind i konfigurationspakkerne, hvis du ikke allerede har gjort det. Dette værktøj er ikke egnet til hurtigt at gendanne en Cronus eller kopiere en klient fra en gammel Navision-version til en ny version. A) det er ofte ikke tilgængeligt i den ældre version, B) nogle gange er den interne struktur i outputfilerne forskellig mellem forskellige konfigurationspakker / Rapidstart-versioner af Navision, og C) det er simpelthen alt for tidskrævende at indtaste alle de tabeller, du har brug for, der. Nå ja, og D) igen, selvfølgelig, at dette værktøj ikke kan eksportere/importere til beskyttede områder som bogførte fakturaer eller direkte til kundeposter.

Kopiér og indsæt

Ja, faktisk! I det gamle Navision kan du direkte over tabellerne (Designer, Table, Run) få adgang til rigtig mange tabeldata (alle Data fra Navision ligger i forskellige tabeller! Kopier fra den ene tabel/database ved at trykke CTRL+A (Marker alt), CTRL+C (Kopiér, i Navision RTC og Business Central CTRL+Shift+C), og indsæt derefter i den anden Navision-database ved at trykke CTRL+V (Indsæt, V minder om en tragt, i Navision RTC og Business Central CTRL+Shift+V).
Dog skal de respektive berørte tabeller også være 100%identiske her (med RTC ikke længere helt 100% ), og afhængigt af antallet af poster tager kopieringen (ikke indsættelsen!) evigheder. En ulempe skal nævnes separat: Alle tabeltriggere og kontroller gennemgås, derfor spiller rækkefølgen af kolonner på skærmen og rækkefølgen, hvori tabellerne indsættes, en stor rolle. Og f.eks. er „Korrigeret den“-datoen derefter altid en aktuel dato. Her eller der er kopiering og indsættelse dog faktisk en praktisk ting, der kan spare meget tid.

Arbejdsmåde for min universelle kundeeksport og kundeimport

Grundlæggende har jeg blot skrevet en Serializer og De-serializer, som simpelthen gennemgår alle tabeller efter hinanden, opretter en fil per tabel, og derefter skriver hver post som en linje i denne fil. Tomme felter, Flowfields og Flowfiltre springes automatisk over, hvilket gør filen/filerne lidt slankere. Ved tilpasninger i funktionen kan tabeller naturligvis også begrænses.
Deserializeren kan til gengæld forstå dette dataformat, hvorefter den opretter en post igen i den rigtige tabel for hver linje i filen.

Ved siden af er dette også et godt eksempel på brugen af Recordref (recRef) og Fieldref, hvilket holder programkoden forbavsende kort.

Hver enkelt brugt tabel fra Navision / Business Central eksporteres til en enkelt datafil
Eksporten skriver til en enkelt datafil for hver enkelt brugt tabel fra Navision / Business Central. På denne måde kan en fil f.eks. også nemt slettes før en import (f.eks. vareposttabellen). Denne vil så simpelthen ikke blive læst/importeret i destinationsmandanten.

Der eksporteres ingen BLOB-felter, så f.eks. ingen varebilleder mv. kan ses i den importerede klient. Hvis du har brug for dette, bedes du kontakte mig. Du kan dog nemt selv udvide funktionen med binær eksport/import. Teknisk set eksporteres og importeres indholdet af hvert BLOB-felt simpelthen som en separat fil.

Denne funktion er „gratis at bruge“ med denne udgivelse, selvfølgelig uden nogen funktionalitetsgarantier eller sikkerheder.
En anvendelse er IKKE tilladt, heller ikke i uddrag, for firmaet Landefeld Druckluft & Pneumatik fra Kassel og for Dr. Ulrich Obermüller (bopæl muligvis Kiel). Begge har en forhistorie, som jeg vil offentliggøre, når lejligheden byder sig. Jeg har haft utroligt dårlige oplevelser med begge.

Egnede Navision eller Business Central versioner

Uden RecordRef kan det ikke lade sig gøre. Recordref eller RecRef blev introduceret med Navision version 3.60, stabilt fra 3.70. Den gode nyhed er, at ældre Navision-databaser, f.eks. fra 2.01(b) osv., nemt kan konverteres til en 2009 eller 2009 R2 eller 4er/5er.
Endvidere er der draget fordel af den ubegrænsede strenglængde, der blev introduceret med RTC (Navision 2013, 2015 etc.). Her kunne datafelter dog simpelthen udskrives linje for linje i stedet for i en linje for ældre versioner. Der er ingen yderligere begrænsninger, så alle tabeller og felter, der er identiske i Navision 2009R2 og Navision 2018 (Business Central BC 14), kunne for eksempel også overføres fra 2.01b eller 2009R2 til BC14. Ved import ignoreres automatisk alle felter, der ikke kan mappes. Mindre ændringer, for eksempel ændringen fra et heltalsfelt til et kodefelt, foretages automatisk.
Spoileralarm: Med denne database vil der helt sikkert ikke ske mere end „lidt kiggen“! Men det er jo allerede mere, end hvad der overhovedet kan gøres med officielle værktøjer.

Grundlæggende kunne man med dette også indlæse en 3.56 Navision i en 2.01 Navision, som så konverteres til 2009R2, og så videre. Men! Det behøver du slet ikke! Du kan ganske enkelt indlæse en Navision 3.53, 3.56, 3.5x datasikkerhed direkte med en 2.01(b) Navision! Her bliver alle tabeller og felter, der mangler, automatisk oprettet af Navision i den forinden tomme database. Der indlæses dog ingen proceslogik, kun dataene. Det kan du så konvertere til 2009R2 med et fingerknips (nå ja... næsten...), og så hurtigt se dine stamdata under RTC eller i webklienten.

Koden er offentliggjort her, som den fungerede. Den bliver ikke vedligeholdt eller udvidet her! Hvis du er interesseret i denne funktion, men håber på mere end bare en hurtig gendannelse af en Cronus AG, så giv venligst besked.

OBJECT Codeunit 50003 RTH_ExportImportCompany
{
  OBJECT-PROPERTIES
  {
  }
  PROPERTIES
  {
    Tilladelser=TableData 17=id,
                TableData 21=id,
                TableData 25=id,
                TableData 32=id,
                TableData 45=id,
                TableData 46=id,
                TableData 110=id,
                TableData 111=id,
                TableData 112=id,
                TableData 113=id,
                TableData 114=id,
                TableData 115=id,
                TableData 120=id,
                TableData 121=id,
                TableData 122=id,
                TableData 123=id,
                TableData 124=id,
                TableData 297=id,
                TableData 298=id,
                TableData 339=id,
                TableData 379=id,
                TableData 380=id,
                TableData 405=id,
                TableData 480=id,
                TableData 5802=id,
                TableData 5811=id,
                TableData 9004=id,
                TableData 9006=id,
                TableData 9008=id,
                TableData 9999=id;
    OnRun=VAR
            TXTImportExport@1000000000 : TextConst 'DEU=Export company %1 to File,Migrate File into client %1,Initialise client %1 with File;ENU=Export company %1 to File,Migrate File into Company %1,Init Company %1 with File';
            ConfirmString@1000000001 : Tekst;
          BEGIN
            ConfirmString := STRSUBSTNO(TXTImportExport,COMPANYNAME);
            CASE STRMENU(ConfirmString) OF
              1 : ExportCompany;
              2 : ImportCompany(FALSE);
              3 : ImportCompany(TRUE);
            END;
          SLUT;

  }
  CODE
  {
    VAR
      Tables@1000000002 : Record 2000000028;
      SystemObject@1000000008 : Record 2000000029;
      RecRef@1000000000 : RecordRef;
      TXTbasicPath@1000000003 : TextConst 'DEU=c:\temp\';
      Window@1000000004 : Dialogue;
      DataFile@1000000001 : Fil;
      RecCounter@1000000005 : Heltal;
      TXTextension@1000000007 : TextConst 'DEU=NavCompany';
      TXTdivider@1000000006 : TextConst 'DEU=Ý';

    LOCAL PROCEDURE ExportCompany@1000000000();
    VAR
      Filnavn@1000000000 : Tekst;
    BEGIN
      Tables.SETRANGE("Table No.",1,1999999999);
      Tables.SETFILTER("Antal poster",'>0');
      Tables.SETRANGE("Firmanavn",COMPANYNAME);
      Window.OPEN('Eksportér #1########################################\@2@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@');
      IF Tables.FINDSET THEN REPEAT
        FileName := TXTbasicPath + FORMAT(Tables. "Table No.") + '_'+ DELCHR(Tables. "Table Name",'=','/\?*+') +'.'+ TXTextension;
        Window.UPDATE(1,Filnavn);
        CLEAR(RecRef);
        RecRef.OPEN(Tables. "Table No.");
        IF RecRef.READPERMISSION THEN
          IF RecRef.FINDSET THEN BEGIN
            CLEAR(DataFile);
            DataFile.TEXTMODE(TRUE);
            DataFile.CREATE(Filnavn,TEXTENCODING::UTF8);
            CLEAR(RecCounter);
            GENTAG
              RecCounter += 1;
              IF RecCounter MOD 1000 = 0 THEN BEGIN
                Window.UPDATE(2,ROUND(RecCounter / Tables. "No. of Records" * 10000,1,'<'));
                CLEAR(RecCounter);
              END;
              DataFile.WRITE(ExportRecord(RecRef));
            UNTIL RecRef.NEXT = 0;
            DataFile.CLOSE;
          END;
      UNTIL Tables.NEXT = 0;
      Window.CLOSE;
    SLUT;

    LOCAL PROCEDURE ExportRecord@1000000002(pRecRef@1000000000 : RecordRef) RecordString : Text;
    VAR
      FieldRef@1000000001 : FieldRef;
      FieldCounter@1000000002 : Heltal;
      FieldAsText@1000000003 : Tekst;
    BEGIN
      FOR FieldCounter := 1 TO pRecRef.FIELDCOUNT DO BEGIN
        FieldRef := pRecRef.FIELDINDEX(FieldCounter);
        IF FORMAT(FieldRef.CLASS) = 'Normal' THEN BEGIN
          CLEAR(FieldAsText);
          CASE FORMAT(FieldRef.TYPE) OF
            'BLOB','Binary','Media','MediaSet':;
          ELSE
            FieldAsText := FORMAT(FieldRef,0,9);
          SLUT;
          FieldAsText := CONVERTSTR(FieldAsText,TXTdivider,'_');
          HVIS FieldAsText  '' SÅ
            RecordString += TXTdivider + FORMAT(FieldRef.NUMBER) +';'+FieldAsText;
        SLUT;
      SLUT;
    SLUT;

    LOCAL PROCEDURE ImportCompany@1000000001(pInitTables@1000000000 : Boolean);
    VAR
      FileList@1000000001 : Record 2000000022;
      TableNo@1000000002 : Heltal;
      TXTallTables@1000000003 : TextConst 'DEU="Skal ALLE tabeller slettes? Nej=kun de importerede.”;ENU="Ryd ALLE tabeller? Nej=kun importerede."";
      DataFileLen@1000000004 : Heltal;
      DataFileLine@1000000005 : Tekst;
    BEGIN
      IF pInitTables THEN
        IF CONFIRM(TXTallTables) THEN BEGIN
          Window.OPEN('Slet tabel #1############');
          Tables.SETFILTER('Antal poster",">0');
          Tables.SETRANGE('Table No.",1,1999999999);
          IF Tables.FINDSET THEN REPEAT
            Window.UPDATE(1,Tables. "Table No.");
            CLEAR(RecRef);
            RecRef.OPEN(Tables. "Table No.");
            RecRef.DELETEALL;
          UNTIL Tables.NEXT = 0;
          Window.CLOSE;
          COMMIT;
        SLUT;

      Window.OPEN(
        "Import #1########################################\'+
        '@2@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\'+
        '#3########################################');
      FileList.SETRANGE(Sti,TXTbasicPath);
      FileList.SETFILTER(Navn,'@*'+TXTextension);
      FileList.SETFILTER(Størrelse,'>0');
      IF FileList.FINDSET THEN REPEAT
        Window.UPDATE(1,FileList.Name);
        EVALUATE(TableNo,COPYSTR(FileList.Name,1,STRPOS(FileList.Name,'_')-1));
        CLEAR(RecRef);
        RecRef.OPEN(TableNo);
        IF RecRef.WRITEPERMISSION THEN BEGIN
          DataFile.TEXTMODE(TRUE);
          DataFile.OPEN(FileList.Path + FileList.Name,TEXTENCODING::UTF8);
          DataFileLen := DataFile.LEN;
          WHILE DataFile.POS < DataFileLen DO BEGIN
            IF DataFile.POS MOD 1000 = 0 THEN
              Window.UPDATE(2,ROUND(DataFile.POS / DataFileLen * 10000,1,' 0 DO BEGIN
        IF COPYSTR(pDataLine,1,1) = TXTdivider THEN
          pDataLine := COPYSTR(pDataLine,2);
        EVALUATE(FieldNo,COPYSTR(pDataLine,1,STRPOS(pDataLine,';')-1));
        IF pRecRef.FIELDEXIST(FieldNo) THEN BEGIN
          FieldRef := RecRef.FIELD(FieldNo);
          FieldContentPosition := STRPOS(pDataLine,';')+1;
          IF STRPOS(pDataLine,TXTdivider) > 0 THEN BEGIN
            FieldContentLen := STRPOS(pDataLine,TXTdivider) - FieldContentPosition;
            FieldContent := COPYSTR(pDataLine,FieldContentPosition,FieldContentLen);
            pDataLine := COPYSTR(pDataLine,STRPOS(pDataLine,TXTdivider)+1);
          END ELSE BEGIN
            FieldContent := COPYSTR(pDataLine,STRPOS(pDataLine,';')+1);
            CLEAR(pDataLine);
          END;
          IF EVALUATE(FieldRef,FieldContent) THEN;
        END;

      SLUT;
      IF pRecRef.INSERT THEN BEGIN
        RecCounter += 1;
        IF RecCounter = 100 THEN BEGIN
          Window.UPDATE(3,pRecRef.GETPOSITION);
          CLEAR(RecCounter);
        END;
      END;
    SLUT;

    BEGIN
    END.
  }
}