Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi DevExpress cxGridView Daten auslesen (https://www.delphipraxis.net/132769-devexpress-cxgridview-daten-auslesen.html)

Alfredo 19. Apr 2009 11:04


DevExpress cxGridView Daten auslesen
 
Ich möchte den gerade in einem Datagrid eingegeben Wert, der ja noch nicht im Dataset steht
auslesen und aufgrund dieses Wertes in einer anderen Spalten einen Wert hineinschreiben.

z.B. im Feld GKTO habe ich 4910 erfasst und in das Feld Buchtext soll 'Porto'.

Dass das im EditValueChanged erfolgen muss ist mir klar.

Mir fehlt jedoch die Wertabfrage und das Wertwegschreiben im Datagrid.

Gruß
Alfred

Thomas Horstmann 20. Apr 2009 02:22

Re: DevExpress cxGridView Daten auslesen
 
Hallo,

die Werte im Grid kann man über den "DataController" auslesen und ändern:

Delphi-Quellcode:
...
MyGridView.DataController.Values[Zeilennummer,MeineSpalte.Index] := 4711 ;
...
Die aktuelle angezeigten Werten werden mit "ViewData" bearbeitet. Der
Unterschied ist notwendig, da evtl. Filter gesetzt sind.

Delphi-Quellcode:
MyGridView.ViewData.Records[Zeilennummer].Values[MeineSpalte.Index] := 4711 ;
Ggf. ist es besser den abhängigen Wert via "BeforePost" im DataSet
zu setzen. Dabei ist aber zu beachten, dass im "EditValueChanged" kein "Post"
direkt abgesetzt werden kann. Das Grid immer noch den Fokus und bekommt
dann schon wieder die Aufforderung Daten neu anzuzeigen.

In diesem Fall muss der Umweg über die Message gegangen werden.
Leider etwas umständlich.

...
Application.OnMessage := ApplicationMessage ;
...

Alfredo 20. Apr 2009 11:44

Re: DevExpress cxGridView Daten auslesen
 
Hallo Thomas,

sowohl .Datacontroller als auch .ViewData geben im EditValueChanged den
vorhergehenden Wert und nicht den Wert den man gerade eingegeben hat zurück.

Ich verwende momentan folgenden Code:

Delphi-Quellcode:
SDQuery1.ApplyUpdates;
SDQuery1.CommitUpdates;
SDQuery1.Edit;
nread1 := SDQuery1.FieldbyName('GKTO').asInteger;
if nread1 = 4910 then
begin
SDQuery1.FieldbyName('BUCHTEXT').Value := 'Porto';
SDQuery1.ApplyUpdates;
SDQuery1.CommitUpdates;
SDQuery1.Edit;
end;
Gruß
Alfred

Thomas Horstmann 20. Apr 2009 12:39

Re: DevExpress cxGridView Daten auslesen
 
Hallo,

das ist das Problem mit dem "Editor" des Views, der währende der Eingabe alles andere sperrt.
Und beim Drücken von "Enter" ist dieser noch aktiv.

1. Die Kunst ist jetzt, den Editor "sauber" zu beenden und dann die gewünschte Aktion auszuführen.
2. Dafür wird nach "EditValueChanged" eine Message abgesetzt.
3. Die Message wird im Hauptfenster verarbeitet.
4. Der Editor schliesst sich vor der Message (zum Glück).
5. Den zusätzlichen Wert würde ich mit "BeforePost" im DataSet holen.
Damit steht er gleich an der richtigen Stelle. Sauberer wäre
eine Verarbeitung auf der Datenbank z.B. per Trigger (meine Empfehlung).
6. Der Wert "ForceRefresh" sollte im DataSet aktiviert sein, damit alle
Spalten neu ausgelesen werden.

Ich verwende folgenden Code im Hauptfenster des Projekts:

Delphi-Quellcode:
...
public
  procedure ApplicationMessage
  ( var Msg    : TMsg  ;
    var Handled : Boolean) ;
...
const
WM_GRIDPOSTMESSAGE = WM_USER + 10000 ;
...
procedure TStart_Form.FormCreate(Sender: TObject);
begin
{ Messages abfangen }
Application.OnMessage := ApplicationMessage ;
end ;
...
procedure TStart_Form.ApplicationMessage
( var Msg    : TMsg  ;
  var Handled : Boolean) ;
var
iDataSet : TDataSet ;
begin
{ Grid }
if Msg.message = WM_GRIDPOSTMESSAGE then
  begin
  iDataSet := TcxGridDBTableView(Msg.wParam).DataController.DataSet ;
  if iDataSet.State in [dsInsert,dsEdit] then
    begin
    iDataSet.Post ;
    // gGlobalIBConnection.Transaction.CommitRetaining ;
    end ;
  end ;
end ;
...
Code im GridView:

Delphi-Quellcode:
procedure TGlobal_EditFields_Form.GridDBViewEditValueChanged(
  Sender: TcxCustomGridTableView; AItem: TcxCustomGridTableItem);
begin
PostMessage(Handle, WM_GRIDPOSTMESSAGE, Integer(Sender), 0) ;
end ;
Hinweis:
Wenn der "neue" Wert nicht in der Datenmenge benötigt wird, dann kann
der Wert z.B. via "ImageComboBox" angezeigt werden. Dafür muss
diese Spalte als "Unbound" deklariert werden.

Alternativ geht evtl. auch OnGetText.

Viele Grüsse
Tom

uligerhardt 20. Apr 2009 12:53

Re: DevExpress cxGridView Daten auslesen
 
Vorneweg: Ich arbeite mit ungebundenen Grids (nix DB), also ist vielleicht nicht alles auf deine Situation übertragbar.

Ich habe ein ähnliches Problem wie du in einem Handler für TableView.DataController.OnRecordChanged gelöst:
Delphi-Quellcode:
procedure TMyGrid.TableViewRecordChanged(
  ADataController: TcxCustomDataController; ARecordIndex, AItemIndex: Integer);
begin
  if AItemIndex = InteressanteSpalte.Index then
    MachWasMit(ARecordIndex, InteressanteSpalte.EditValue);
end;

Alfredo 20. Apr 2009 21:55

Re: DevExpress cxGridView Daten auslesen
 
Hallo Tom,

ich versuche gerade deinen Code nachzuvollziehen und stolpere bereits zu Beginn.

Delphi-Quellcode:
public
  procedure ApplicationMessage
  (var MSg : TMsg ;
   var Handled : Boolean);
end;
liefert: E2065 Ungenügende Forward -oder External-Deklartion.

:gruebel:

Gruß
Alfred

mkinzler 20. Apr 2009 22:00

Re: DevExpress cxGridView Daten auslesen
 
Hast du auch die Implementierung übernommen?

Thomas Horstmann 20. Apr 2009 22:10

Re: DevExpress cxGridView Daten auslesen
 
Hallo,

Wurde ApplicationMessage richtig auf die Form verwiesen?
In meinem Fall auf "TStart_Form"?

Delphi-Quellcode:
procedure TStart_Form.ApplicationMessage
Hier mal ein paar Auszug aus meiner "Start_Form".

Delphi-Quellcode:
unit Start;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, dxSkinsCore ;

type
  TStart_Form = class(TForm)
    XPManifest: TXPManifest;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);

  private
    { Private-Deklarationen }

  public
    { Public-Deklarationen }
    procedure QuitApplication ;
    procedure ApplicationMessage
    ( var Msg    : TMsg   ;
      var Handled : Boolean ) ;
  end;

var
  Start_Form: TStart_Form;

implementation

uses
...
// *** Start FormCreate/Close/KeyDown ******************************************
// *****************************************************************************
procedure TStart_Form.FormCreate(Sender: TObject);
begin
{ Messages }
Application.OnMessage := ApplicationMessage ;
end ;
// *** Ende FormCreate/Close/KeyDown *******************************************
// *****************************************************************************
...
// *** Start ApplicationMessage ************************************************
// *****************************************************************************
procedure TStart_Form.ApplicationMessage
( var Msg    : TMsg   ;
  var Handled : Boolean ) ;
var
iDataSet : TDataSet ;
begin
{ Grid }
if Msg.Message = WM_GRIDPOSTMESSAGE then
  begin
  TcxGridDBTableView(Msg.wParam).DataController.DataSet.Post ;
  end ;
end ;
// *** Ende ApplicationMessage ************************************************
// *****************************************************************************
...
Viele Grüße :-)

alzaimar 21. Apr 2009 06:57

Re: DevExpress cxGridView Daten auslesen
 
Beim 'Buchungstext' handelt es soch doch um ein simples Lookupfeld, wieso also diese Mühe. Wenn man das entsprechend deklariert, befüllt Delphi das doch ganz alleine :gruebel:

Alternativ kann auch ein OnCalcFields herhalten, aber das wird -glaube ich- erst nach dem Post ausgeführt.

die Lösung mit einer Unbound-Spalte zur Anzeige des Buchungstextes funktioniert bei mir nicht, da dieser Wert beim Verlassen der Zeile wieder gelöscht wird.

Alfredo 21. Apr 2009 09:35

Re: DevExpress cxGridView Daten auslesen
 
Hallo Tom,

hatte einmal Start_Form :(.

Jetzt läuft das alles, aber das Problem besteht weiterhin.

An welcher Stelle sollte denn der geänderte Wert abgreifbar sein?

Gruß
Alfred

Alfredo 21. Apr 2009 09:57

Re: DevExpress cxGridView Daten auslesen
 
Hallo alzaimer,

das ganze soll ein Datenerfassungsprogramm werden. Die Automatik soll nur die
Erfassungarbeit vereinfachen und ein indvidueller Text sollte noch möglich sein.

Gruß
Alfred

Thomas Horstmann 21. Apr 2009 10:08

Re: DevExpress cxGridView Daten auslesen
 
Hallo,

das GridView ist mit einem "DataSet" verbunden. Dort gibt es "BeforePost".
An dieser Stelle kann alles mögliche abgefrage/gesetzt werden.
Ggf. kann mit Locate (sehr langsam) oder einem Query (besser) gearbeitet werden
umd Referenzwerte zu holen.

Wichtig ist, dass "ForceRefresh" im DataSet aktiv ist.

Delphi-Quellcode:
procedure TFM_Test_Form.dxMemData1BeforePost(DataSet: TDataSet);
begin
if DataSet.FieldByName('Nummer').AsInteger > 1000 then
  DataSet.FieldByName('Text').AsString := 'OK'
else
  DataSet.FieldByName('Text').AsString := 'Nicht OK' ;
end;
Viele Grüße :-)

dataspider 21. Apr 2009 10:22

Re: DevExpress cxGridView Daten auslesen
 
Hi,

es gibt IMHO verschiedene einfache Wege, an den Wert zu kommen.

Mal eine Möglichkeit
GridView.OnEditValueChanged...

Delphi-Quellcode:
procedure TFilterByCodeDemoMainForm.tvCustomersEditValueChanged(Sender:
    TcxCustomGridTableView; AItem: TcxCustomGridTableItem);
Var
  v: Variant;
begin
  // Sender.Controller.EditingController.Edit liefert aktuellen Editor
  // neuer Wert steht immer in EditingValue
  v := Sender.Controller.EditingController.Edit.EditingValue;
  // v hat eigegebenen Wert.
end;
Das ist nur ein Ansatz. Du musst AItem natürlich noch verifizieren oder halt gleich die Evenst von AItem setzen anstatt von GridView.
Das Setzen der neuen Werte kann z.B. über die Columns (GridView.GetColumnByFieldName('FeldName')) erfolgen.

Vielleich hilft es ja weiter.

Cu, Frank

alzaimar 21. Apr 2009 17:27

Re: DevExpress cxGridView Daten auslesen
 
Zitat:

Zitat von Alfredo
Hallo alzaimer,

das ganze soll ein Datenerfassungsprogramm werden. Die Automatik soll nur die
Erfassungarbeit vereinfachen und ein indvidueller Text sollte noch möglich sein.

Gruß
Alfred

Eben. Dafür sind extra angelegte Lookupfelder im Dataset da. Da Du das QuantumGrid verwendest, kannst Du auch eine TcxGridDBColumn mit TcxLookupProperties anlegen und dort die Lookupverknüpfung anlegen. Das Ganze geht ohne jeglichen Code.

Alfredo 22. Apr 2009 14:14

Re: DevExpress cxGridView Daten auslesen
 
@Frank

So funktioniert das super: :thumb:


Delphi-Quellcode:
procedure TForm1.cxGrid1DBTableView1GKTOPropertiesEditValueChanged(Sender: TObject);
begin
edit3 := cxGrid1DbTableView1.Controller.EditingController.Edit.EditingValue;
if edit3 = 4910 then
  begin
  cxGrid1DBTableView1.GetColumnByFieldName('BUCHTEXT').EditValue := 'Porto';
  cxGrid1DBTableView1.GetColumnByFieldName('GKTO').EditValue := edit3;  
  end
end;
Hinweis: der 2. EditValue ist notwendig, weil wohl durch den ersten Befehl der aufrufende Editor geschlossen wird, ohne dass der eingegebene Wert abgespeichert wird.


@alzaimer
Ich werde mir das mit dem Lookup, wegen der zu erwartenden größeren Anzahl an Abfragen, noch anschauen.

Gruß
Alfred

dataspider 22. Apr 2009 14:48

Re: DevExpress cxGridView Daten auslesen
 
Hi,

man sollte IMHO:
Delphi-Quellcode:
cxGrid1DbTableView1.Controller.EditingController.Edit.PostEditValue;
verwenden (statt der erneuten Zuweisung).

Frank

uligerhardt 22. Apr 2009 15:25

Re: DevExpress cxGridView Daten auslesen
 
Zitat:

Zitat von dataspider
Delphi-Quellcode:
cxGrid1DbTableView1.Controller.EditingController.Edit.PostEditValue;

Mit dem DevEx-Zeug kann man ja tolle Sachen machen, aber diese ganzen Controller gehen mir auf den ****. :mrgreen:
Z.B. Edit-Modus programmatisch abwürgen:
Delphi-Quellcode:
    TableView.BeginUpdate;
    try
      TableView.DataController.Cancel;                       // <= hier einer
      TableView.Controller.EditingController.HideEdit(False); // <= hier noch zwei
    finally
      TableView.EndUpdate;
    end;

Alfredo 22. Apr 2009 19:36

Re: DevExpress cxGridView Daten auslesen
 
@Frank,

it works. :)

Wie kommt man denn an das ganze Wissen über diese Editoren?



@Uli

dann mußt Du halt ********.cancel; machen :mrgreen:


Gruß
Alfred

uligerhardt 23. Apr 2009 08:10

Re: DevExpress cxGridView Daten auslesen
 
Zitat:

Zitat von Alfredo
dann mußt Du halt ********.cancel; machen :mrgreen:

Aua. :lol:

dataspider 23. Apr 2009 08:36

Re: DevExpress cxGridView Daten auslesen
 
Zitat:

Zitat von Alfredo
Wie kommt man denn an das ganze Wissen über diese Editoren?

In der Regel finde ich die Lösung immer hier:
DevExpressSupportCenter

Ich nutze die Kompo' s halt schon ein paar Jahre.

Freut mich, dass ich helfen konnte.

Frank

Alfredo 23. Apr 2009 19:04

Re: DevExpress cxGridView Daten auslesen
 
Hallo Frank.

welche Datenbankkomponenten verwendest Du?

Gruß
Alfred

dataspider 24. Apr 2009 08:12

Re: DevExpress cxGridView Daten auslesen
 
Zitat:

Zitat von Alfredo
Hallo Frank.

welche Datenbankkomponenten verwendest Du?

Gruß
Alfred

Du verwendest ja offensichtlich SQLDirect. Damit kannst du auf verschiedene DB' s zugreifen.
Da ich nur Firebird benötige, verwende ich IBObjects.
Allerdings habe ich aud die SQLDirect und benutze diese für Tools (Daten hin und her schaufeln),
wo ich Zugriff auf Oracle, MSSQL oder SQLBase brauche.

Gruß,

Frank

Alfredo 24. Apr 2009 09:30

Re: DevExpress cxGridView Daten auslesen
 
Hallo Frank,

vielen Dank für Deine Info. Als Einzelkämpfer ist man immer froh über eine klare Aussage.

Ich bin gerade dabei von Xbase++(Alaska) auf Delphi 2009 Prof Win32 umzustellen.

Ich habe bislang mit SQLDirect gute Erfahrungen gemacht, insbesondere war der Support für
einen Testkunden sehr gut.

In einem anderen Thema in Delphi-Praxis hat ein Mitglied von diesem Produkt jedoch abgeraten,
es aber leider nicht begründet.

Ich habe danach noch die Produkte von DevArt(UniDAC, IBDAC) getestet und mir damit Delphi 2009
ins Nirvana befördert.

Wegen der einfacheren Handhabung setzte ich auch auf Firebird und da sieht man schon erhebliche
Unterschiede zwischen SQLDirect und IBDac, die für mich, da ich nur auf den CS setze nicht so
relevant sind.

Was mir am meisten abgeht ist eine direkter, funktionsfähiger Zugriff auf *.dbf(alte Version).

Gruß
Alfred


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:25 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