Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi PosNummern in Rechnungsdaten (https://www.delphipraxis.net/75758-posnummern-rechnungsdaten.html)

LOMBI 24. Aug 2006 15:34

Datenbank: Paradox • Zugriff über: TQuery, TDataSource

PosNummern in Rechnungsdaten
 
Tabelle: Rechnungsdaten
Feld: PosNr (n)umerisch


Hallo,

die Rechnungsdaten (Artikel) werden in einem DBGrid angezeigt. Jeder Artikel erhält eine fortlaufende PosNr

1.0 Artikel1
2.0 Artikel2
3.0 Artikel3
...

Delphi-Quellcode:
TFRechnungen.QueryRechnungsdatenAfterInsert(DataSet. TDataSet);                    
begin            //PosNr hochzählen
  with DataSet do
    if QueryRechnungsdaten.FieldByName('PosNr').IsNull then
      QueryRechnungsdaten.FieldByName('PosNr').AsInteger :=
      NextKey('PosNr', 'Rechnungsdaten');
    end;
Problem:

Mit dem ersten Artikel in einer neuen Rechnung muß die PosNr wieder bei 1.0 starten.

Wie bitte erreiche ich das?

Gruß
Lombi

mkinzler 24. Aug 2006 15:39

Re: PosNummern in Rechnungsdaten
 
Was steckt hinter NextKey?
Ggf mußt du diese Funktion anpassen.

LOMBI 24. Aug 2006 16:39

Re: PosNummern in Rechnungsdaten
 
Delphi-Quellcode:
function NextKey (fldName, tblName: String): Integer;
begin
  with TQuery.Create do
  begin
  DatabaseName := QueryRechnungen.DatabaseName;
  SQL.Text := Format('SELECT MAX(%s) FROM %s', [fldName, tblName]);
  Open;
  Result: succ(Fields[0].AsInteger);
  Close;
end;
Gruß
Lombi

mkinzler 24. Aug 2006 17:29

Re: PosNummern in Rechnungsdaten
 
SQL-Code:
SELECT MAX(PosNr) FROM RechPos where RechPos.RechNr = RechNr;

LOMBI 24. Aug 2006 19:18

Re: PosNummern in Rechnungsdaten
 
Hallo mkinzler,

danke für den Code, aber damit erhalte ich leider keine Veränderung.
Die PosNr wird in einer neuen Rechnung einfach weiter hochgezählt und
fängt nicht wieder bei PosNr. 1.0 für den ersten angelegten Artikel an.
Grüße
Lombi

mkinzler 24. Aug 2006 19:22

Re: PosNummern in Rechnungsdaten
 
Zitat:

Die PosNr wird in einer neuen Rechnung einfach weiter hochgezählt
Das dürfte aber nicht sein. Bei einer neuen Rechnungsnummer müßte die Abfrage NULL zurückliefern, da ja keine Datensätze da sind, über die er eine Summierung durchführen könnte.

Poste mal dei Metadaten der Tabelle.

LOMBI 24. Aug 2006 19:46

Re: PosNummern in Rechnungsdaten
 
Rechnungsdaten-Tabelle:

RechnungsNr I(nteger)
PosNr N(umerisch)
ArtNr A(lphanumerisch)
ArtBez A(lphanumerisch)
ArtBez2 A(lphanumerisch)
Datum D(ate)
Anzahl N(umerisch)
EinzelPreis N(umerisch)
GesamtPreis N(umerisch)
MwSt N(umerisch)
Rabatt N(umerisch)

QueryRechnungsdaten
DataSource: DataSourceRechnungen
SQL.Text : SELECT * FROM Rechnungen WHERE RechnungsNr= :RechnungsNr;

mkinzler 24. Aug 2006 19:49

Re: PosNummern in Rechnungsdaten
 
Setze mal für RechnungsNr eine nicht vorhandene ein. Was bekommst du als Ergebnis der Max()-Funktion?

LOMBI 24. Aug 2006 20:08

Re: PosNummern in Rechnungsdaten
 
Ungültiger Feldname.

Ich habe zusätzlich eine Query auf die Form gelegt:

Name: QueryPosNr
DataSource: DataSourceRechnungsdaten
SQL.Text: SELECT MAX(PosNr)
FROM Rechnungsdaten
WHERE Rechnungsdaten.RechnungsNr = RechnungsNr;

mkinzler 24. Aug 2006 20:14

Re: PosNummern in Rechnungsdaten
 
SQL-Code:
SELECT MAX(PosNr)
FROM Rechnungsdaten
WHERE Rechnungsdaten.RechnungsNr = 999999;

LOMBI 25. Aug 2006 10:49

Re: PosNummern in Rechnungsdaten
 
Hi mkinzler,

leider, es will nicht klappen. Vielleicht liegt's an
der function NextKey und dem darin enthalten SQL.Text?

Delphi-Quellcode:
SQL.Text := Format('SELECT MAX(%s) FROM %s', [fldName, tblName]);
Gruß
Lombi

mkinzler 25. Aug 2006 10:57

Re: PosNummern in Rechnungsdaten
 
Ich habe gedacht, du hast diesen durch meine Erweiterung ersetzt!

LOMBI 25. Aug 2006 11:58

Re: PosNummern in Rechnungsdaten
 
Delphi-Quellcode:
function PosNr(fldName, tblName: String): Integer;
begin
  with TQuery.Create do
  begin
  DatabaseName := QueryRechnungen.DatabaseName;
  SQL.Text := 'SELECT MAX(Pos) FROM Rechnungsdaten WHERE
               Rechnungsdaten.RechnungsNr = 999999';
  Open;
  Result: succ(Fields[0].AsInteger);
  Close;
end;
Den SQL.Text habe ich ersetzt. Nun beginnen alle Artikelpositionen
mit der PosNr. 1.0. Das "succ" in Result wird hier scheinbar ignoriert.

mkinzler 25. Aug 2006 12:05

Re: PosNummern in Rechnungsdaten
 
Der Wert von 99999 ist natürlich falsch, war nur wegen meiner frage was er liefret wenn die Rechnungsnummer unbeknnat ist.
Bisher liefert die Abfarge ja das Maximum aller Positionen durch Erweiterung um die Rechnungsnummer liefert er das Maximum bezogen auf dise Nummer.

Bsp:
RechNr Pos
1 1
1 2
1 3
2 1
2 2

Die Abfrage

SQL-Code:
SELECT MAX(Pos) FROM Rechnungsdaten WHERE Rechnungsdaten.RechNr = 1
liefert also 3

Die Abfrage

SQL-Code:
SELECT MAX(Pos) FROM Rechnungsdaten WHERE Rechnungsdaten.RechNr = 2
2

und die Abfrage

SQL-Code:
SELECT MAX(Pos) FROM Rechnungsdaten WHERE Rechnungsdaten.RechNr = 3
NULL.

Das kannst du dann abfangen und dann den Wert 1 setzen.

hoika 25. Aug 2006 16:49

Re: PosNummern in Rechnungsdaten
 
Hallo Lombi,

ein etwas anderer Ansatz.
Warum merkst du dir während der Bearbeitung der Positionen
die bisherige Anzahl in einer Variablen
oder lade gleiche alle Positionen in eine Liste.

Dann kannst du beim Speichern gleich neu durchnumerieren
und hast beim Löschen von Positionen keine Lücken.


Heiko

LOMBI 25. Aug 2006 17:17

Re: PosNummern in Rechnungsdaten
 
@mkinzler

Ich habe den SQL.Text in der function PosNr nochmals überarbeit,
aber es will einfach nicht funktionieren. In den Rechnungen
haben alle gespeicherten Artikel die PosNr 1.0 oder die
Artikel starten z.B ab PosNr 6.0 ...

@hoika

Ich möchte vorerst keine Positionen bearbeiten. Zunächst muß eine
Rechnung mit den Artikeln eingeben und gespeichert werden. Oder
habe ich etwas mißverstanden? Soll ich etwa für die PosNr eine
neue Tabelle anlegen?

Gruß
Lombi

mkinzler 25. Aug 2006 17:25

Re: PosNummern in Rechnungsdaten
 
Versuchs mal so
Delphi-Quellcode:
function PosNr(fldName, tblName: String; RechNr: Integer): Integer;
begin
  with TQuery.Create do
  begin
  DatabaseName := QueryRechnungen.DatabaseName;
  SQL.Text := 'SELECT MAX(Pos) FROM Rechnungsdaten WHERE
               Rechnungsdaten.RechnungsNr = RechNr';
  Open;
  if not Fields[0].isNull then
      Result := succ(Fields[0].AsInteger)
  else
    Result := 1;
  Close;
end;

LOMBI 25. Aug 2006 19:14

Re: PosNummern in Rechnungsdaten
 
Ist mir echt peinlich, aber wieder Fehlanzeige!

mkinzler 25. Aug 2006 19:15

Re: PosNummern in Rechnungsdaten
 
Dann schau mal was Field[0] für ein Wert hat.

Michael Habbe 25. Aug 2006 22:04

Re: PosNummern in Rechnungsdaten
 
Hi.

Guck Dir das mal an, wie ich es löse. Ich verwende zwar ADS, aber mit Paradox sollte es auch gehen.

Zunächst brauchst Du zwei Funktionen (das vereinfacht es später, den Aufruf woanders zu wiederholen).
Die erste kapselt einfach nur den Aufruf des SQLs.
"AsInteger" gibt immer einen Wert zurück, auch wenn noch kein Datensatz existiert, also hast Du automatisch die aktuelle Positionsnummer (im ersten Fall NULL --> 0 --> +1 = 1).
Die "GlobaleQry" (bei Dir also eine TQuery) muss mit dem Database verbunden werden. Sie dient mir in vielerlei Hinsicht. Dies ist eins davon.
Delphi-Quellcode:
function TDataModul.NaechsteNummerErmitteln(SQLString, FeldName: String): Integer;
begin
  GlobaleQry.Close;
  GlobaleQry.SQL.Clear;
  GlobaleQry.SQL.Add(SQLString);
  GlobaleQry.Open;
  Result := GlobaleQry.FieldByName(FeldName).AsInteger + 1;
  GlobaleQry.Close;
end;
In dieser Funktion wird der SQL zusammengebaut.
Delphi-Quellcode:
function TDataModul.NaechsteNummerErmitteln(Tabelle, FeldName, BedingungsFeld, BedingungsWert: String; BedingungsFeldIsString: Boolean = False): Integer;
begin
  if BedingungsFeldIsString then
    Bedingungswert := '''' + Bedingungswert + '''';
  result := NaechsteNummerErmitteln('Select max(' + FeldName + ') NUMM from ' + Tabelle
                                  + ' where ' + BedingungsFeld + ' = ' + BedingungsWert,
                                    'NUMM');
end;
Somit kannst Du nun anfangen, die Nummern zu ermitteln.
Delphi-Quellcode:
procedure TFormIrgendo.RechnungTblAfterInsert....
begin
  ...
  DataModul.RechnungTblPositionsnummer.AsInteger :=
    NaechsteNummerErmitteln('Rechnung', 'Positionsnummer', 'Rechnungsnummer', RechnungTblRechnungsnummer.AsInteger);
  ...
end;
Mittlerweile bin ich bei fünf Funktionen, die sich mit der Ermittlung der nächsten fortlaufenden Nummer und der Ermittlung von Lücken befassen.
Ist also quasi ausgereift.

Jelly 25. Aug 2006 22:35

Re: PosNummern in Rechnungsdaten
 
Michael,

Du bist dir aber schon bewusst, dass zwischen deinem Ermitteln der neuen ID im AfterInsert Event bis zum Post des Records eine Weile vergehen kann. Wer garantiert dir denn ,dass genau in der Zeit nicht ein anderer User einen Datensatz eingefügt hat... DEINE ID wird nämlich erst beim Post vom Server vergeben, und nicht nach dem Aufruf von Dataset.Insert...

hoika 26. Aug 2006 09:42

Re: PosNummern in Rechnungsdaten
 
Hallo,

mkinzler,
dein SQL-Text ist falsch !

SQL-Code:
SQL.Text := 'SELECT MAX(Pos) FROM Rechnungsdaten WHERE
               Rechnungsdaten.RechnungsNr = RechNr';
Es muss heissen

entweder

SQL-Code:
SQL.Text := 'SELECT MAX(Pos) FROM Rechnungsdaten WHERE
               Rechnungsdaten.RechnungsNr = '+IntToStr(RechNr);
oder

SQL-Code:
SQL.Text := 'SELECT MAX(Pos) FROM Rechnungsdaten WHERE
               Rechnungsdaten.RechnungsNr = :RechNr';
ParamByName('RechNr').AsInteger:= rechNr;
Heiko

Michael Habbe 26. Aug 2006 11:34

Re: PosNummern in Rechnungsdaten
 
Hi Tom.

Zitat:

Zitat von Jelly
Michael,

Du bist dir aber schon bewusst, dass zwischen deinem Ermitteln der neuen ID im AfterInsert Event bis zum Post des Records eine Weile vergehen kann. Wer garantiert dir denn ,dass genau in der Zeit nicht ein anderer User einen Datensatz eingefügt hat... DEINE ID wird nämlich erst beim Post vom Server vergeben, und nicht nach dem Aufruf von Dataset.Insert...

Bei mir wird insgesamt anders vorgegangen. Da werden nicht einzelne Positionen einer Rechnungsnummer zugeordnet, sondern einer Vorgangsnummer. Da aber jeder Vorgang nur von einem Anwender bearbeitet werden darf, passt das schon. Die Rechnungsnummer wird erst beim Druck der Rechnung geholt.
Aber generell hast Du schon recht. Das ist ein Problem von vielen in einer Mehrbenutzeranwendung.

mkinzler 26. Aug 2006 20:19

Re: PosNummern in Rechnungsdaten
 
Zitat:

mkinzler,
dein SQL-Text ist falsch !
Einfach schneller getippt als gedacht. :oops:

LOMBI 11. Sep 2006 18:55

Re: PosNummern in Rechnungsdaten
 
Guten Abend,

ich bekomme das mit den Positionsnummern einfach nicht hin:

Delphi-Quellcode:
function GetPosNr(fldName, tblName: String): Integer;
var
  QueryRechnungsdaten:TQuery;
begin
  with TQuery.Create(nil) do
    begin
      DatabaseName := Rechnungen.DatabaseName;
      SQL.Text := Format('SELECT MAX(%s) FROM %s WHERE
                  Rechnungsdaten.RechnungsNr= :RechnungsNr',
                  [fldName, tblName]);            
      ParamByName('RechnungsNr') := RechnungsNr;
      Open;
      Result := succ(Fields[0].AsInteger;
      Close;
    end;
  end;

procedure FRechnungen.QueryRechnungsdatenAfterInsert(DataSet: TDataSet);
begin
  with DataSet do
    begin
      if FieldByName('PosNr').IsNull then
        FieldByName('PosNr').AsInteger := GetPosNr('PosNr',
        Rechnungsdaten');
        QueryRechnungsdaten['RechnungsNr'] :=
        QueryRechnungen['RechnungsNr']
        ...
       end;
Fehlermeldung: "Undefinierter Bezeichner 'RechnungsNr'"

Delphi-Quellcode:
SQL.Text := Format('SELECT MAX(%s) FROM %s WHERE
                  Rechnungsdaten.RechnungsNr= :RechnungsNr',
      //":RechnungsNr" stammt aus Tabelle Rechnungen und ist vom Typ
          I(nteger)!
Wer hilft mir bitte nochmals?

Grüße
Lombi

uwewo 11. Sep 2006 19:42

Re: PosNummern in Rechnungsdaten
 
Hi,

habe mir jetzt nicht komplett alles durchgelesen, also Sorry wenn ich etwas wiederhole.
Beim erstellen einer neuen Rechnung, sind sehr wahrscheinlich noch keine Daten in Deinem DBGrid.
Was hindert Dich daran, beim anlegen eines neuen Datensatzes den Wert der PosNr. auf die Anzahl(+1) der gezeigten Datensätze im Grid zu setzen.

z.B. bei AfterInsert oder BeforePost

marabu 11. Sep 2006 19:47

Re: PosNummern in Rechnungsdaten
 
Hallo Lombi,

du brauchst beide Generatoren - NextKey() ermittelt die nächste laufende Nummer und NextSubkey() macht das für einen sogenannten compound key (zusammengesetzter Schlüssel) - in deinem Fall Rechnungsdaten(RechNr, PosNr). Hier nochmal ausführlich, was dir Markus bereits am Anfang geschrieben hatte:

Delphi-Quellcode:
function NextKey (fldName, tblName: String): Integer;
begin
  with TQuery.Create do
  begin
    DatabaseName := QueryRechnungen.DatabaseName;
    SQL.Text := Format('SELECT MAX(%s) FROM %s', [fldName, tblName]);
    Open;
    Result := Succ(Fields[0].AsInteger);
    Close;
  end;
end;

function NextSubKey (
  keyValue: Integer; // RechNr Wert
  fldName,           // RechNr Feldname
  subName,           // PosNr FeldName
  tblName: String    // Tabellenname
): Integer;
begin
  with TQuery.Create do
  begin
    DatabaseName := QueryRechnungen.DatabaseName;
    SQL.Text := Format('SELECT MAX(%s) FROM %s WHERE %s = %d', [subName, tblName, fldName, keyValue]);
    Open;
    Result := Succ(Fields[0].AsInteger);
    Close;
  end;
end;
Der Ansatz von Uwe führt zwar auch zum richtigen Ergebnis, aber die Vermischung von Datenmodell und GUI ist dabei nicht so schön.

Gute Nacht

marabu

LOMBI 13. Sep 2006 11:18

Re: PosNummern in Rechnungsdaten
 
Herzlichen Dank, auch für Eure Geduld mit einem Greenhorn in Sachen Progr.

@minzler
Delphi-Quellcode:
function PosNr(fldName, tblName: //String; RechNr: Integer//): Integer;
Entschuldigung, hatte in dieser Zeile eine wesentliche Änderung übersehen!

Gruß
Lombi


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:06 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz