CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 14:48

Hallo,

Ich will über alle Kreditoren durchgehen und am Anfang der KreditorNr. eine 1 als Ziffer anhängen.
Momentan sind alle Kreditoren mit 5 Stellen bezeichnet. Aber jemand wünscht sich 6 Stellen durch eine anfängliche 1.

Die Nr. in der Tabelle Vendor ist ja Code 20. Kann ich mit PADSTR operieren?

Also in der Art:

Code:

REPEAT
  IF STRLEN(Vendor."No.") < 6 THEN BEGIN
    Vendor."No" := PADSTR(Vendor."No.",0) + '1';
    RENAME(Vendor."No."); //weil Primärschlüssel
    Vendor.VALIDATE("No."); //damit auch die historischen Kreditorposten mitgeändert werden, oder muss ich die manuell ändern=
  END;   
UNTIL

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 15:10

Muss es unbedingt PADSTR sein?

Code:
NeueKredNr := '1' + AlteKredNr;

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 15:18

Natalie hat geschrieben:Muss es unbedingt PADSTR sein?

Code:
NeueKredNr := '1' + AlteKredNr;


Nein, ich wußte gar nicht, dass die Konkatenation von einem '1' + Code20 möglich ist. Danke schön Natalie :-)

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 15:47

Natalie hat geschrieben:Muss es unbedingt PADSTR sein?

Code:
NeueKredNr := '1' + AlteKredNr;


So, leider taucht ein neues Problem auf, es wird immer nur der erste Kreditor und nicht alle innerhalb des Filters gegriffen, warum das so ist, kann ich nur vermuten:

Code:

VenRec.RESET;

WHILE STRLEN(VenRec."No.") < 6 DO BEGIN
  VenRec."No." := '1' + VenRec."No.";
  RENAME(VenRec."No.");
  VenRec.VALIDATE("No.");
END;

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 15:50

Lies dir doch noch mal ganz genau deine While-Bedingung durch :wink:

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 16:04

McClane hat geschrieben:Lies dir doch noch mal ganz genau deine While-Bedingung durch :wink:


Die stimmt doch:

Solange die Kreditornr. kleiner als 6-stellig ist, dann füge eine 1 hinzu.
Alle Kreditorennr. sind 5 stellig, als müßte die Schleife bei einer Filterung 10000..99999 über all diese Kreditoren gehen und eine 1 vorne hinzufügen.

Oder ich müßte es anders aufbauen, also ohne Filter davor:
Code:

VenRec.RESET

REPEAT
  VenRec."No." := '1' + VenRec."No.";
  RENAME...
  VALIDATE...
UNTIL VenRec.NEXT = 0


EDIT: auch folgender Code klappt nicht, er bringt einen Überlauf der Typkonvertierung Text to Code:

Code:

VenRec1.RESET;


IF VenRec1.FINDSET THEN
  REPEAT

      VenRec1."No." := '1' + VenRec1."No.";
      RENAME(VenRec1."No.");
      VenRec1.VALIDATE("No.");

  UNTIL (VenRec1.NEXT = 0) AND (STRLEN(VenRec1."No.") < 6);


Ich weiß leider nicht mehr weiter.

Eigentlich ist das ganze doch einfach, Algorithmus lautet: durchlaufe alle Kreditoren, füge eine 1 hinzu und das war's


EDIT 2: könnte das die Lösung sein:


Code:

VenRec1.RESET;

  REPEAT
    IF VenRec1.FINDLAST THEN BEGIN
      VenRec1."No." := '1' + VenRec1."No.";
      RENAME(VenRec1."No.");
      VenRec1.VALIDATE("No.");
    END;
  UNTIL (VenRec1.NEXT = 0);

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 16:53

Durchlaufe ALLE Vendor-Datensätze (einfaches REPEAT ... UNTIL NEXT = 0).
Innerhalb der REPEAT-Schleife: Nur wenn Zeichen kleiner 6, dann auffüllen.
Nach einem RENAME kein VALIDATE, das ist überflüssig.

Und am wichtigsten: Nicht auf dem originären Vendor-Record (Vendor1) ein RENAME durchführen, das macht die Repeat-Schleife kaputt.
Nimm für die Umbenennung statt dessen eine zweite Vendor-Recordvariable. Setze Vendor2 := Vendor1, danach auf Vendor2 das RENAME.

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 17:01

Natalie hat geschrieben:Durchlaufe ALLE Vendor-Datensätze (einfaches REPEAT ... UNTIL NEXT = 0).
Innerhalb der REPEAT-Schleife: Nur wenn Zeichen kleiner 6, dann auffüllen.
Nach einem RENAME kein VALIDATE, das ist überflüssig.

Und am wichtigsten: Nicht auf dem originären Vendor-Record (Vendor1) ein RENAME durchführen, das macht die Repeat-Schleife kaputt.
Nimm für die Umbenennung statt dessen eine zweite Vendor-Recordvariable. Setze Vendor2 := Vendor1, danach auf Vendor2 das RENAME.


Jo, danke!

Auf ein Neues, mal schauen, ob das klappt:

Code:
VenRec.RESET;
VenRec2.RESET;
VenRec.SETRANGE("No.",'10000','70531');

 IF VenRec.FINDLAST THEN
  REPEAT
      VenRec2.GET(VenRec."No.");
      VenRec2 := '1' + VenRec."No.";
      RENAME(VenRec2."No.");   
  UNTIL (VenRec.NEXT(-1) = 0) AND STRLEN(VenRec."No") >= 6;


EDIT: leider bringt der obige Code nur das Ergebnis, dass aus 10.000 die Nr. 110.000 wird. Der Rest des SETRANGE wird nicht durchlaufen :shock:
Zuletzt geändert von Freestyler am 15. Dezember 2010 17:10, insgesamt 1-mal geändert.

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 17:08

Ich weiß zwar nicht, warum du die REPEAT-Schleife unbedingt rückwärts durchlaufen möchtest :-)
Aber seis drum, kann man durchaus so lassen.
Leider verwendest du RENAME falsch, siehe unten. Habe bei der Gelegenheit noch die Performance berücksichtigt.
Code:
    VenRec.RESET;
    VenRec.SETRANGE("No.",'10000','70531');

    IF VenRec.FIND('+') THEN // kein FINDLAST mit REPEAT!
      REPEAT
          VenRec2 := VenRec;
          VenRec2.RENAME('1' + VenRec."No.); // schau mal in die Onlinehilfe ;-)
      UNTIL VenRec.NEXT(-1) = 0;

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 17:31

Hallo

Code:
 VendRec.setrange("No.",'','99999'); // Filter funktioniert nur bei numerischen Kundennummern, sonst Filterwerte anpassen
IF VenRec.FINDSET THEN // kein FINDLAST mit REPEAT!
   REPEAT
       VenRec2 := VenRec;
       VenRec2.RENAME('1' + VenRec."No.); // schau mal in die Onlinehilfe ;-)
   UNTIL VenRec.NEXT = 0


so würd ich das machen :wink:
:!: Aber der Rename funktioniert nur bei den Tabellen/Feldern, die eine Tablerelation auf Vendor haben. Solltest du irgendwo Tabellen haben, wo die Vendor."No." eingetragen ist, ohne Tablerelation, funktioniert der Rename dort nicht. Und ob der Rename bei bedingten Tablerelations (z.B. in den Postentabellen "Source Code" ) sauber funktioniert, solltest du vorher mal testen.
:!: Sollte deine Datenbank etwas größer sein, mit vielen Posten, ist der Rename er subperformant :wink:

Gruß, Fiddi

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 17:56

fiddi hat geschrieben:Hallo

Code:
 VendRec.setrange("No.",'','99999'); // Filter funktioniert nur bei numerischen Kundennummern, sonst Filterwerte anpassen
IF VenRec.FINDSET THEN // kein FINDLAST mit REPEAT!
   REPEAT
       VenRec2 := VenRec;
       VenRec2.RENAME('1' + VenRec."No.); // schau mal in die Onlinehilfe ;-)
   UNTIL VenRec.NEXT = 0


so würd ich das machen :wink:
:!: Aber der Rename funktioniert nur bei den Tabellen/Feldern, die eine Tablerelation auf Vendor haben. Solltest du irgendwo Tabellen haben, wo die Vendor."No." eingetragen ist, ohne Tablerelation, funktioniert der Rename dort nicht. Und ob der Rename bei bedingten Tablerelations (z.B. in den Postentabellen "Source Code" ) sauber funktioniert, solltest du vorher mal testen.
:!: Sollte deine Datenbank etwas größer sein, mit vielen Posten, ist der Rename er subperformant :wink:

Gruß, Fiddi


Ok, das mit dem "sub-performant" hab ich gerade gemerkt:

für 70.000 bis 70.448 ist NAV native Client nach 20 Min immer noch nicht fertig und das obwohl diese Kreditoren keine Posten haben :-(

WARUM steht eigentlich unter dem REPEAT das hier:
VenRec2 := VenRec;

Ich dachte man kann Records nicht 1:1 zuweisen, sondern nur feldweise oder mit COPY oder mit TRANSFERFIELDS?

hier mein endgültiger Code, der aber nach vielen Minuten immer noch nicht durch ist, das COMMIT hab ich nur zu Testzwecken gesetzt, später muss es natürlich raus, sonst gibt's wohl Ärger:

Code:
    VenRec.RESET;
    VenRec.SETRANGE("No.",'70000','70448');

    IF VenRec.FIND('+') THEN
      REPEAT
          IF VenRec2.GET(VenRec."No.") THEN
            VenRec2.RENAME('1' + VenRec."No.");
          COMMIT;
      UNTIL (VenRec.NEXT(-1) = 0) AND (STRLEN(VenRec."No.") > 5);


EDIT: das mit FINDLAST hab ich gemacht, weil ich gemerkt hab, dass die Sortierung von NAV nach der Umbenennung den umbenannten Kreditor ans Ende der Liste setzt. Daher benenne ich von unten nach oben, damit die Sortierung nicht durcheinander kommt. Aber da Natalie gesagt hat, dass man 2 Record-Variablen definieren soll, denke ich, dass auch von oben nach unten klappen wird.

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 18:17

Lord_British hat geschrieben:EDIT: das mit FINDLAST hab ich gemacht, weil ich gemerkt hab, dass die Sortierung von NAV nach der Umbenennung den umbenannten Kreditor ans Ende der Liste setzt. Daher benenne ich von unten nach oben, damit die Sortierung nicht durcheinander kommt. Aber da Natalie gesagt hat, dass man 2 Record-Variablen definieren soll, denke ich, dass auch von oben nach unten klappen wird.


Das ist genau der Grund, warum Natalie
Code:
VenRec2 := VenRec;
in Ihren Code eingefügt hat.

Damit wird dafür gesorgt, das der ursprüngliche Recordzeiger in VenRec nicht durch den Rename (wie bei dir geschehen) zerstört wird.

Außerdem musst du kein Get mehr auf VenRec mehr machen, da der Venrec.Next den schon gefunden hat. (obige Zuweisung und den Code von Natalie bzw. mir vorausgesetzt)

Gruß, Fiddi

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 18:20

fiddi hat geschrieben:
Lord_British hat geschrieben:EDIT: das mit FINDLAST hab ich gemacht, weil ich gemerkt hab, dass die Sortierung von NAV nach der Umbenennung den umbenannten Kreditor ans Ende der Liste setzt. Daher benenne ich von unten nach oben, damit die Sortierung nicht durcheinander kommt. Aber da Natalie gesagt hat, dass man 2 Record-Variablen definieren soll, denke ich, dass auch von oben nach unten klappen wird.


Das ist genau der Grund, warum Natalie
Code:
VenRec2 := VenRec;
in Ihren Code eingefügt hat.

Damit wird dafür gesorgt, das der ursprüngliche Recordzeiger in VenRec nicht durch den Rename (wie bei dir geschehen) zerstört wird.

Außerdem musst du kein Get mehr auf VenRec mehr machen, da der Venrec.Next den schon gefunden hat. (obige Zuweisung und den Code von Natalie bzw. mir vorausgesetzt)

Gruß, Fiddi


Okay, danke schön!

Wieder was dazugelernt, ich wußte nicht, dass man Record1 := Record2 machen kann/muss. Ich dachte es gibt nur COPY und TRANSFERFIELDS.

Aber wenn ich das Wort Zeiger lese, bekomm ich a bisserl das Gruseln. Ich erinnere mich mal an den Spruch eines Informatik-Profs, wonach 50% aller C++ Fehler durch falsche Zeigerarithmetik entstehen. Ist aber schon 6 Jahre her, dass ich eine Programmiervorlesung hatte...

Re: CC: Kreditoren Nr. um 1 erhöhen?

15. Dezember 2010 18:31

Lord_British hat geschrieben:Ich erinnere mich mal an den Spruch eines Informatik-Profs, wonach 50% aller C++ Fehler durch falsche Zeigerarithmetik entstehen.

Vielleicht hat er den Satz ja auf seine eigenen Fehler bezogen :mrgreen:

In einer DB zeigert so viel herum (oder Pointer auf Pointer), dass es dann ja die perfekte Geisterbahn sein müsste :wink: