![]() |
Datenbank: Firebird • Version: 2.5 • Zugriff über: dataset
Stringgrid oder dbgrid
Hallo,
habe eine Form1 "Auftrag" mit einigen Editfeldern, wie Name, Adresse usw. (keine DBEdits). Zugriff auf die Tabelle über ein Dataset. Soweit kein Problem. Im Auftragsformular gibt es ein oder mehrere Positionen. Ebenfalls alles Editfelder. Die Übersicht über die Positionen möchte ich in einem Grid darstellen. Die Positionen haben eine eigene Tabelle mit einem Verweis auf die AuftragsID. Die Editfelder möchte ich haben, weil ich erst beim Speichern des Auftrages ein neue AuftragsID generieren möchte. Probleme habe ich mit den Grids. Der Vorteil von einem Stringgrid ist, dass ich die Zellen füttern kann und erst beim Speichern des Auftrages die Positionen in die Datenbanktabelle schreibe. Leider ist ein Stringgrid, so in Delphi7, blöd mit den verschieden Zellenformatierungen. Alles muß man da selbst Programmieren. Die andere Möglichkeit, die ich ausprobiert habe ist eine JediDBGrid einzusetzen. Da lassen sich schon verschiedene Spaltenformatierungen vornehmen. Da aber dieses Grid mit der Tabelle verbunden ist, müßte ich, so denke ich, mit einer temporären Tabelle und DBGrid arbeiten. Ich weiß nicht, ob ich das jetzt so verständlich erklärt habe, aber möglicherweise habt Ihr eine Standardweg, wie man in einer Auftragsverwaltung so vorgeht. Über jede Anregung wäre ich dankbar. Danke, Luckner |
AW: Stringgrid oder dbgrid
Zitat:
Unter keinen Umständen sollte diese jemals für den Anwender sichtbar sein. Damit ist egal ob man dafür Integer, Int64 oder GOID als Datentyp wählt, sie müssen auch nicht fortlaufend vergeben werden, aber sie müssen eindeutig sein. Für den Anwender gibts Auftragsnummer, Kundennummer, Belegnummer usw. über die er die Objekte im Programm finden und identifizieren kann. Damit ist dein Wunsch eigentlich unsinnig. |
AW: Stringgrid oder dbgrid
Hallo Blub,
es ist nicht so das Problem. Die ID's sind für den Anwender nicht sichtbar und erzeugt werden sie von einem Generator. Möchte jedoch den Generator nicht unnötig hochschaukeln, wenn der Anwender, während des Auftraganlegens, mal eine oder mehrere Positionen wieder löscht. Und das im Netzwerk mit mehreren Anwendern. Möchte mit den ID's und Generatorwerten möglichst sparsam umgehen. Luckner |
AW: Stringgrid oder dbgrid
Wen interessiert denn der Wert eines Generators/einer ID?
|
AW: Stringgrid oder dbgrid
Und wenn der Generator auch noch ein Int64 ist, dann dauert´s bis er "erschöpft" ist ... Ich gehe mal davon aus, dass Du einen Generator in der DB oder eine Sequence in selbiger meinst.
Aber Spaß beiseite. Wenn es wirklich TEdit-Felder sind, dann verstehe ich die Fragestellung nicht so wirklich. Zu dem Zeitpunkt besteht doch noch kein Bezug zur DB ! Erst wenn der User "Speichern" drückt, kann man entweder über ein SQL-Statement ("INSERT INTO ...") einfügen oder man übernimmt die Werte nach einem Dataset.Insert mit DataSet.FieldByName(..).As.. := TEdit ... mit anschließendem DataSet.Post ! Gruß Thomas |
AW: Stringgrid oder dbgrid
@Luckner:
Firebird erzeugt eine Id für einen neuen Record automatisch, wenn man das beim Erstellen der Tabelle angegeben hat: Im IbExpert beim Erstellen des Id-Feldes einfach die CheckBox AI im Feldeditor anklicken, danach erscheint eine Dialogbox, in der du Generator, Procedure und Trigger erstellst. Voreingestellt ist der Trigger auf BeforeInsert, du kannst aber auch AfterInsert wählen, was aber nicht ratsam und auch nicht notwendig ist. Meiner Erfahrung nach wird ein erzeugter Generatorwert wieder gelöscht, wenn auf ein Append ein Cancel folgt, wenn du also den neu erzeugten Record verworfen hast. Beim Löschen von Records stellt der Generator den gelöschten Id-Wert natürlich nicht mehr zur Verfügung, da er einfach nur hochzählt (incrementiert). Dein Sparsamkeitsgedanke hinsichtlich der Generatorwerte ist völlig sinn- und zwecklos. Du wirst wohl kaum die Anzahl der Aufträge erreichen, um hier auch nur bei Integer (über 4 Milliarden Aufträge) an die Grenze zu kommen, bei BigInt schon gar nicht – es sei denn, deine Lebenserwartung beträgt das Vielfache des Durchschnittsmenschen, so ein paar tausend Jahre würdest du wohl brauchen :lol: ![]() Dein Problem mit dem DBGrid und der angeblich notwendigen temporären Tabelle habe ich nicht wirklich verstanden. Aber ich versuch's mal: Wenn du via DBGrid eine Tabelle anzeigen läßt, du aber die einzelnen Felder in Edits bearbeiten willst, mußt du selbst dafür sorgen, daß der Anwender eben nur in den Edits arbeiten kann. Dazu versetzt du das DBGrid vor dem Bearbeiten in den Disabled-Mode (MyDBGrid.Enabled := False), nach Post oder Cancel wieder Enabled := True. Die Editfelder setzt du für gewöhnlich auf ReadOnly := True, das Grid ebenfalls. Im Edit-Modus setzt du die Editfelder auf ReadOnly := False. Sollte das DBGrid die Änderungen nicht automatisch übernehmen, kannst du mit einem MyQuery.Refresh nachhelfen. Befinden sich in deiner Tabelle ForeignKeys, die auf Einträge in Subtabellen verweisen, verwendest du für das DBGrid ein View und stellst in dessen AfterScroll-Behandlung sicher, daß ein Scrollen im View stets den jeweiligen Record in der Ursprungstabelle selektiert. |
AW: Stringgrid oder dbgrid
Habe mich etwas falsch ausgedrückt. Die Editfelder werden aus der Tabelle direckt gefüttert. Das Grid ist nur für die Anzeige der Positionen. Erst ein Doppelklick auf das Grid (Zeile) öffnet ein Panel mit den Edit's. In dieser Zeit ist das Grid ausgeblendet. Meine Vorstellung ist, die Neuanlage eines Auftrages, wird einen temporäre Tabelle erstellt (Zugriff über ein Dataset), die Positionen dieses Auftrages werden eingetragen bzw. gelöscht und in diesem Auftrag auch dargestellt (im Grid als Tabelle) und dann beim Speichern des Auftrages in die tatsächliche Tabelle übernommen. Aschliessend TempTabelle in der Datenbank gelöscht. Weil ich beim Erstellen eines neuen Auftrages keinen neuen Generatorwert erzeuge (erst beim Speichern), habe ich das Problem nach dem Posten und Open auf die Orginal-Positionstabelle, alle bereits eingetragenen Positionen zu sehen, weil mein select * where auftragsid = ? nicht funktioniert.
Ist das schwer zu erklären, aber ich hoffe, das es jetzt einigermassen geklappt hat. Luckner |
AW: Stringgrid oder dbgrid
Also du hast einen Auftrag mit diversen Positionen (Waren, Dienstleistungen etc.). Du legst einen Auftrag neu an und erhältst dadurch eine Auftrags-Id. Danach legst du zu diesem Auftrag die benötigten Positionen an. Wozu du da eine temporäre Tabelle benötigst, erschließt sich mir nicht.
Ich würde das Konzept, das du da umzusetzen im Begriff stehst, noch einmal überdenken. Wenn du einen Auftrag in einer temporären Tabelle anlegst, weißt du die Id, die dieser Auftrag dann in der regulären Tabelle haben wird, immer noch nicht. Deshalb legst du den Auftrag gleich in der regulären Tabelle an und merkst dir die vergebene Id. Erst wenn der Auftrag angelegt ist, erstellst du dessen Positionen mit der gemerkten Auftrags-Id. Deine Positionen-Tabelle beinhaltet im günstigsten Fall einen PK, der eine AutoInc-Id beherbergt, und ein Feld AuftragsId, das die Position dem jeweiligen Auftrag zuordnet. Beim Scrollen der Autrags-Tabelle setzt du dann immer gleich einen Filter auf die Positionen-Tabelle, um so nur die Positionen des aktuellen Auftrags anzuzeigen. So macht man das gewöhnlich. Ich verstehe dein Problem nur insoweit, als du ein etwas merkwürdiges Datenbank- und Anwendungs-Konzept beschreibst :? |
AW: Stringgrid oder dbgrid
Man nehme ein ClientDataSet für die Kopfdaten und eine ClientDataSet für die Positionsdaten (jede beliebige InMemory-Tabelle geht natürlich auch).
Die Auftrags-ID ist bei einem neuen Auftrag erstmal 0. Man füllt den Kopf und die Positionen und beim Speichern schreibt man erst den Kopf, bekommt die ID und speichert alle Positionen mit der eben erhaltenen AuftragsID. Alles natürlich innerhalb einer Transaktion. |
AW: Stringgrid oder dbgrid
Zitat:
|
AW: Stringgrid oder dbgrid
Hallo Perlsau, Sir Rufo,
ich lege neuen Auftrag an und habe erstmal keine neue ID. Die erzeuge ich erst beim Speichern. Sir Rufo, die neue ID=0 ist klar, aber was passiert wenn 2 oder mehr Anwender gleichzeitig neue Aufträge anlegen? Luckner |
AW: Stringgrid oder dbgrid
Beim Speichern wird dann ein eindeutiger Schlüssel generiert
|
AW: Stringgrid oder dbgrid
Zitat:
|
AW: Stringgrid oder dbgrid
Zitat:
Zitat:
Und weil dem so ist, haben die Datenbank-System-Hersteller darauf geachtet, dass eine ID gesichert nur einmal vergeben wird. Darum braucht man sich eben keine Sorgen machen, da kann man auch eine Million Datensätze im exakt gleichen Zeitpunkt in der gleichen Tabelle der gleichen Datenbank erzeugen - aber nicht wundern, dass es etwas dauert, denn der Server verarbeitet diese gleichzeitigen Anfragen nacheinander ;) |
AW: Stringgrid oder dbgrid
Zitat:
Luckner: "Der Vorteil von einem Stringgrid ist, dass ich die Zellen füttern kann und erst beim Speichern des Auftrages die Positionen in die Datenbanktabelle schreibe." Wenn ja, worin besteht dieser Vorteil? Ob du jetzt als erstes die Auftragsdaten eingibst (Kunde, Datum, Verkäufer etc.) und den Auftrag anlegst, bevor du die Positionen abspeicherst, oder ob du das alles erst virtuell machst, um es dann als Ganzes zu speichern, bleibt sich doch gleich. Wenn du natürlich Hunderte oder mehr Fakturisten hast, die den ganzen Tag nichts anderes machen als Aufträge einzugeben, und das auch noch auf einem entfernten Server, wäre es natürlich, um Übertragungs-Ressourcen zu schonen, schon von Vorteil, nicht mehrere Transaktionen pro Auftrag ausführen zu müssen oder sogar mehrere Aufträge in einer Transaktion unterzubringen. Zitat:
Zitat:
|
AW: Stringgrid oder dbgrid
Was würde mir ein Auftrag auf dem Server bringen, wo nur der Kopf besteht aber noch keine Positionen?
Oder willst du die Transaktion so lange offen halten, bis alle Positionen drin sind? Und dann wird der Auftrag abgebrochen und der Datensatz muss gelöscht werden (oder storniert, was aber irgendwie nicht der Wahrheit ganz entspricht, denn der Auftrag ist nie zustande gekommen). Oder die Anwendung stürtzt ab, Strom fällt aus, etc. Dann doch lieber alles in einem Rutsch (eine Transaktion) wenn fertig in die Datenbank schreiben. Dann braucht man auch nicht aufräumen, weil man es niemals durcheinander gebracht hat. Das ist auch der Weg um den Auftrag wieder zu bearbeiten. Alles einlesen, bearbeiten und dann alle Änderungen in einem Rutsch wieder zurück in die Datenbank. Und so ein ClientDataSet bringt dafür schon alles von Haus aus mit. |
AW: Stringgrid oder dbgrid
Danke :thumb:
Das hab ich jetzt verstanden :stupid: |
AW: Stringgrid oder dbgrid
Hallo Sir Rufo,
das ist genau die Erklärung, die ich versucht habe hier zu bringen. Irgenwie tendiere ich deshalb zum Stringgrid. Aber die Handhabe mit so einem Grid ist mir noch völlig schleierhaft. Habe schon einige Sachen probiert, manche Sachen funktionieren auch. Aber so richtig kann ich mit dem Stringgrid nichts anfangen. Zellen füllen schon. Beim Blob wird schon schwieriger. Jetzt habe ich ein TMS.Grid endeckt. Mal schauen. Luckner. |
AW: Stringgrid oder dbgrid
Du kannst jedes beliebige Grid nehmen, aber warum nicht beim DBGrid bleiben? Da wird dir vieles schon abgenommen, was du anders erst wieder umständlich implementieren musst.
Es wäre auch sehr hilfreich, wenn man die Delphi-Version wüsste - ganz findige User tragen die Version einfach in ihr Profil ein, schon hat man das immer vor Augen. |
AW: Stringgrid oder dbgrid
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Delphi-Quellcode:
Procedure TFormDeckblatt.DBGrid_DeckblattDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
Var Bild : TImage; begin If DatMod.Qset_Deckblatt.RecordCount > 0 Then Begin If Column.FieldName = 'BLATT' Then Begin Bild := TImage.Create(Self); Try Bild.Visible := False; Bild.Width := 300; Bild.Height := 300; Bild.Center := True; Bild.Proportional := True; Bild.Stretch := True; If DatMod.BlobToImage(DatMod.Qset_Deckblatt.FieldByName('BLATT'),Bild) Then Begin DBGrid_Deckblatt.Canvas.FillRect(Rect); DBGrid_Deckblatt.Canvas.StretchDraw(Rect,Bild.Picture.Bitmap); End; Finally Bild.Free; End; End; End; end; Function TDatMod.BlobToImage(Feld: TField; Bild: TImage): Boolean; Var S : TStream; JBild : TJpegImage; begin Result := False; IF Feld.IsNull THEN Exit; JBild := TJPegImage.Create; S := Feld.DataSet.CreateBlobStream(Feld, bmRead); Try JBild.LoadFromStream(S); Bild.Picture.Bitmap.Assign(JBild); Result := True; Finally S.Free; JBild.Free; End; end; |
AW: Stringgrid oder dbgrid
Sir Rufo,
habe mein Prtofil jetzt ergänzt. Werde mir ende des Monats eine Delphi XE7 Pro-version kaufen, wobei mitten drin in der Programmierung umzusteigen wird nicht funktionieren. Aber ein neues Projekt möglicherweise. Welchen Vorteil bring ein clientdataset? Ich benutze eigentlich imme ein IBDataset Luckner. |
AW: Stringgrid oder dbgrid
Ein ClientDataSet sammelt z.B. alle Änderungen bis du diese wieder zurück zur Datenbank überträgst. Macht also genau das was du suchst.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:09 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