Entwickler-Ecke

Datenbanken - Anfänger braucht Vorschläge für Programmrealisation


crashboy - Mo 07.07.03 08:33
Titel: Anfänger braucht Vorschläge für Programmrealisation
Moin Moin erstmal,

als Anfänger will ich mich mal mit einem kleinen Datenbank-Proggi beschäftigen. Dafür benötige ich von Profis einige Infos zur effektivsten Umsetzung.

Ziel: Mittels eines Barcode-Scanners wird ein Artikel eingescannt, der dazugehörige EAN-Code in einer Tabelle gesucht, vollständig mit Bezeichnung angezeigt und durch Eingabe einer Stückzahl vervollständigt. Anschließend soll dieser Artikel ein einer weiteren Tabelle abgespeichert werden.
Die zu scannenden Artikel liegen vollständig in der ersten Tabelle vor (manuell eingetragen).

System: normaler PC, Handscanner- der in Tastatur eingeschliffen ist und die EAN-Codes in Form von Strings ausgiebt.

Frage: Welches DB-System sollte ich nehmen und wie gehe ich am besten vor.

Habe schonmal angefangen mit dBase. Scheint mir aber zu unflexibel und der Locate-Befehl will sich nicht so richtig mit mir anfreunden. Zumindest sollte doch nach dem Locate der Satzzeiger auf den gescannten Wert zutreffen, wa er jedoch nicht macht.

Danke für jede Hilfe
crashboy


BeniSchindler - Mo 07.07.03 13:04

Was man am besten nehmen sollte, kann man glaube ich nicht so einfach beantworten. Ich selber benutze jedoch eigentlich immer die Opensource-Interbase-Datenbank : Firebird.
Vorteile von Firebird: schnell, sehr klein, Linux und Windows fähig.

Das ist jedoch blos meine Persönliche erste wahl. Das kommt ganz auf einen selber an. Ich würde jedoch immer eine SQL-Datenbank nehmen.

Interbase/Firebird/MySQL/MSSQL/Oracel/etc.

Das einzige von dem ich abrate ist eine Access-Datenbank. Die sind mir einfach zu oft und zu schnell um die Ohren geflogen.

mfg Karr.


hwb - Mo 07.07.03 13:55

Schau erst mal hier nach:

http://www.delphi-forum.de/viewtopic.php?t=160

Und daß dein Programm mit DBase nicht funktioniert liegt aber am Programmierer. Wobei allerdings die große Zeit von DBase vorbei ist.
Auf jeden Fall wurde ich auf die BDE verzichten.

HWB


grayfox - Mo 07.07.03 15:47

halo crashboy!

Zitat:

...als Anfänger will ich mich mal mit einem kleinen Datenbank-Proggi beschäftigen...


dann würd ich dir paradox 7.0 & die BDE empfehlen. das ganze ist bei delphi dabei, ist einfach handzuhaben und hier im forum gibts schon jede menge tipps zum nachlesen wenn du mal nicht weiterweisst.

locate stellt den satzzeiger immer auf den gefundenen datensatz, lookup liefert nur den inhalt zurück
wenn du nach 'ausgibst' suchst, aber 'ausgiebst' in der tabelle erfasst hast, dann kanns vorkommen, dass du nicht das gewünschte ergebnis erhältst ;)

mfg, stefan


Klabautermann - Mo 07.07.03 16:53

Hallo,

vonn der BDE würde ich abraten, sie ist veraltet und wird nciht mehr weiterentwickelt. Außerdem macht sie sobald die Anforderungen etwas höher sind Probleme. Besonders im Netzwerk.

Gruß
Klabautermann


crashboy - Mo 07.07.03 17:19
Titel: Danke
erstmal für Eure Tips.
Nun sieht es so aus, dass das Programm zur simplen Vereinfachung meines Jobs dienen soll.
Ich scanne für ein Marktforschungsinstitut vorgegebene Waren in Supermärkten und vervollständige die Daten manuell mit der vorhandenen Verkaufszahl.
Mehr nicht! Hört sich so simpel an wie es ist und genauso soll das Proggi werden.
Aus diesem Grund will ich mich nicht weiter in die Tiefe der Materie reinsteigern. Letztendlich soll noch ein Ausdruck mit QR der gescannten Daten erfolgen.
Muss ich hierfür extra SQL oder dergleichen lernen?
Ich denke das ich für diese Aufgabe mit Kanonen nach Spatzen schiessen würde.
Wenn möglich, würde ich mal meinen bisherigen Source hier uppen und jemand verrät mir, wie das dann genau mit Locate funktioniert.


Gruss
crashboy


grayfox - Mo 07.07.03 17:28

hallo crashboy!

Zitat:

Muss ich hierfür extra SQL oder dergleichen lernen?


ja und nein. es kommt drauf an, für welches system du dich entscheidest.
bei paradox7 & BDE brauchst du es nicht umbedingt zu lernen. und für die erstellung eines berichtes mit QuickReport ist es auch nicht zwingend notwendig.

das locate bereitet dir noch kopfzerbrechen, gell? ;)
schlag die suchfunktion auf, tipp 'locate' ein und du findest jede menge tipps zu diesem thema.

mfg, stefan


Klabautermann - Mo 07.07.03 17:32

Hallo,

du kannst unter Delphi recht gut mit Datenbanken Arbeiten ohne SQL zu können. Erst wenn die aufgabe komplexer wird solltest du SQL lernen (ist sehr einfach und daber unheinmlich flexibel).
Auf dieser Seite [http://downloads.oitmann.de/samples] findest du ein NoCodeExcampel. Das ist eine kleine datenbankanwendung, die ohne eine Zeile (getippten) Quelltext erstellt wurde. Nur mit der Maus. Wenn du dieses verstanden hast, dann solltest du noch das hier [http://www.delphi-forum.de/viewtopic.php?t=363] lesen und kannst alles was du kennen musst. Nur würde ich dir wie gesagt zu einer anderen DB (z.B. Advantage) raten. Die funktionieren in aller regel genau so, sind aber zuverlässiger.

Gruß
Klabautermann


crashboy - Mo 07.07.03 18:11
Titel: @Klabautermann
Wiederum Danke für die schnelle Antwort.
Soweit habe ich die Problematik mit DB's verstanden. Habe ja auch selber schon rumexperimentiert und gelesen.
Ich komme halt "nur" mit dem Locate-Befehl nicht zurecht.
Die EAN wird gescannt und im DBEdit eingetragen, dann folgt Locate und er sollte dann den richtigen Datensatz finden. Macht er aber nicht. Habe mir ein DBGrid zu Hilfe genommen, um verfolgen zu können, wo der Satzzeiger steht.
Desweiteren kommt die Fehlermeldung " Ungültige Variant-Typumwandlung".

Ich hänge mal die eine Zeile an:


Quelltext
1:
Table1.Locate('Artnummner', VarArrayOf([DBEdit1.Text]), []);                    


Diese Zeile folgt auf ein OnExit-Ereignis im DBEdit.

Gruss
Mario


grayfox - Mo 07.07.03 21:28

hallo crashboy!

genau. wieso einfach, wenns umständlich auch irgendwie vielleicht doch geht? ;)

wie wärs mit:

Delphi-Quelltext
1:
2:
3:
4:
  if Table1.Locate('Artnummner', Edit1.Text, []) then
    .....
  else
    .....  ;


- bist du sicher, dass dein feld 'Artnummner' heisst?
- in welches DBEditFeld welchen Datensatzes liest ihn denn ein?
einfacher gehts mit einem TEdit.Feld. diesen eintrag suchst dann in der tabelle und du hast schon den richtigen datensatz gefunden, falls es ihn gibt.

mfg, stefan


Klabautermann - Di 08.07.03 09:53

Hallo,

ansonsten kannst du es auch mit der Filter funktion versuchen, die ist glaube ich einfacher zu verstehen (aber nicht umbedingt so schnell).

Gruß
Klabautermann


crashboy - Di 08.07.03 11:05
Titel: @grayfox
Danke erstmal.

Ja das Feld heisst artnummner. Hab die Tabelle jetzt aber nochmal neu erstellt. Werds gleich mal ausprobieren.

Gruss
crashboy

So, entweder bin ich zu blöd oder es ist einfacher wie ich denke:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.DBEdit1Change(Sender: TObject);
begin

  if Table1.Locate('Artikelnr', DBEdit1.Text, []) then
  begin
        //hier soll Anweisung rein, in nächste DBEdit zu springen
        end
  else  
        //hier soll Anweisung rein den Tab auf Button3 zu legen

end;

Soweit ich die Locate-Anweisung verstanden habe, wird der Datensatz, falls gefunden, als aktiv markiert. Habe mir ja ein DBGrid dafür draufgesetzt um das verfolgen zu können. Der Datensatzzeiger springt aber immer auf den ersten Satz, egal ob gefunden oder nicht.

Gruss
crashboy


grayfox - Di 08.07.03 14:56

hallo crashboy!

hast deine lesebrille verlegt? vergleich mal die beiden zeilen:
deine version:

Delphi-Quelltext
1:
  if Table1.Locate('Artikelnr', DBEdit1.Text, []) then                    

meine version

Delphi-Quelltext
1:
if Table1.Locate('Artikelnr', Edit1.Text, []) then                    


Zitat:
Der Datensatzzeiger springt aber immer auf den ersten Satz, egal ob gefunden oder nicht.

na no na logisch! :D überleg mal. der datensatzzeiger steht nach dem öffnen der tabelle auf dem ersten datensatz. jetzt beauftragst du locate nach dem inhalt des feldes DBEdit1 zu suchen. in diesem müsste ein eintrag es ersten datensatzes zu finden sein. richtig? daher lies den code des scanners in ein editfeld ein und dann such danach in der tabelle. das ist viel einfacher...

mfg, stefan


crashboy - Di 08.07.03 17:11
Titel: Hurra
Funzt :D :D :D

Letzte Frage: Wie bekomme ich die gescannten Datensätze, also die, die er gefunden hat, in eine 2. existierende Tabelle.
Soll heissen, die Daten in der 1. Tabelle bleiben unverändert und die Felder Artikelnummer und -name sowie ein DBEdit namens Stück sollen in die 2. rein.
Unter Clipper kannte ich den Befehl Replace. Laut Onlinehilfe hat der aber wenig damit zu tun.
Und zweite Frage, in der else anweisung soll ein Sprung auf einen Button erfolgen, wenn der EAN nicht gefunden wurde.

Danke Danke
für Eure Hilfe
Gruss
crashboy


CenBells - Di 08.07.03 19:15

hallo,
ich habe mal ne ganz andere frage, was für einen handscanner verwendest du? Und wie steuerst du den an?

Gruß
Ken


crashboy - Di 08.07.03 22:52
Titel: @cenbells
Das ist so ein Billigteil von aus dem akt. Conrad Katalog. 69 €, Made in TW und frisst jeden Barcode. Programmierbar über beiliegende Barcodes. Anschluss mittels Y-Kabel an Tastatur.
Funzt tadellos.

Gruss
crashboy


hwb - Mi 09.07.03 07:53

Nochmal zurück zu deinem ersten Posting:

Warum arbeitest du mit LOCATE ? Ich geh mal davon aus, daß dei Tabelle in der gesucht wird auch von dir ist. Also was hindert dich daran auf das Feld mit dem EAN-Code einen Index zu setzen und mit FINDKEY zu arbeiten ? Da doch jeder Code einmalig ist, sollte das die bessere Möglichkeit sein.

HWB


grayfox - Mi 09.07.03 08:08

hallo crashboy!

na siehst, so schlecht war mein vorschlag gar nicht ;)

Zitat:

Soll heissen, die Daten in der 1. Tabelle bleiben unverändert und die Felder Artikelnummer und -name sowie ein DBEdit namens Stück sollen in die 2. rein.


mal ein ganz einfaches beispiel:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
{$UNTESTED}
  if quelltable.locate('Artikelnr', ScanCode.Text, []) then begin
    with zieltable do begin
      append;
      FieldByName('Artikelnr').asString:= ScanCode.Text;
      FieldByName('Bezeichnung').asString:= quelltable.FieldByName('Bezeichnung').asString;
      FieldByName('Anzahl').asInteger:= StrToInt(Anzahl.Edit);
      post
    end;
  end else
   ShowMessage('EAN-Code noch nicht angelegt');
  end;

das wäre das grundprinzip des datensatzanlegens, unter der voraussetzung, dass beide tabellen vorhanden und offen sind.

mit dem anzahlfeld als DBEdit könnte sich ein problem ergeben, sobald der EAN-Code nicht gefunden wird. daher würde ich ein normales Edit-Feld verwenden und im OnExitEvent den feldinhalt auf gültigkeit überprüfen. dafür findest hier im forum beispiele zur genüge.

was meinst denn damit?
Zitat:

in der else anweisung soll ein Sprung auf einen Button erfolgen

auf einen button bin ich noch nie gesprungen ;)

mfg, stefan


crashboy - Mi 09.07.03 10:18
Titel: @grayfox
Danke erstmal für Deinen Tip. Learning by doing macht richtig Spass.

Habe Deinen Vorschlag mal folgendermaßen umgesetzt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.Edit1Exit(Sender: TObject);
begin

  if table1.locate('Artikelnr', Edit1.Text, []) then begin
    with Table2 do begin
     Append;
      FieldByName('Artikelnr').asInteger:= Table1.FieldByName('Artikelnr').AsInteger;
      FieldByName('Artikelnam').asString:= Table1.FieldByName('Artikelnam').asString;
      FieldByName('Anzahl').asInteger:= StrToInt(DBEdit2.Text);
      post
    end;
  end else
   ShowMessage('EAN-Code noch nicht angelegt');
  end;


Wie nicht anders zu erwarten funzt es net. :( Noch zur Erläuterung: Der gescannte Code ist vom Typ numerisch, in der 2. Tabelle soll er praktischerweise auch numerisch abgelegt werden. Wenn ich nun aber das Edit1.Exit auslöse, d.h. Artikel wurde gescannt und gefunden, kommt die Fehlermeldung:
Zitat:
"" ist kein Integerwert.

Logisch, Nichts kann nicht Integer sein. Warum ist da aber nichts? Ausserdem darf doch ne Integer nicht mehr als 10 Stellen haben. Da denke ich nur an der EAN13. Hier müsste doch dann ein Int64 rein. Nur wie? :(

In der else-Anweisung soll nicht extra ne ShowMessage erscheinen, sondern der Tab gleich auf den "NEU"-Button erfolgen.

Danke für Deine Hilfe

Gruss
crashboy


CenBells - Mi 09.07.03 11:01
Titel: Re: @grayfox
crashboy hat folgendes geschrieben:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.Edit1Exit(Sender: TObject);
begin

  if table1.locate('Artikelnr', Edit1.Text, []) then begin
...
  end;


Zitat:
"" ist kein Integerwert.

Logisch, Nichts kann nicht Integer sein. Warum ist da aber nichts?


hallo,

ich habe den gesamten thread nicht mit vollem fleiß gelesen, aber wann füllst du denn Edit1? Ich meine, wenn du bsp bei programmstart nichts drin hast und dann das edit verlässt, dann steht doch noch immer nichts drin, oder?

Du könntest vorher noch eine überprüfung einbauuen, ob edit1.text <> '' wenn der text nicht leer ist, kannst du mit deinem locat weiter machen.

Gruß
Ken


crashboy - Mi 09.07.03 11:54
Titel: @cenbells
Der locate-Befehl wird doch erst ausgeführt, wenn ich das Edit verlasse und in dem Moment stehen doch die gescannten Daten drin, sprich der EAN als Zahlenfolge.
Probeweise habe ich einen nichtvorhandenen Artikel gescannt und dann wird ordnungsgemäß else ausgeführt.

Gruss
crashboy


CenBells - Mi 09.07.03 12:01

hast du schon mal mit einem breakpoint die genaue zeile bestimmt, in der der fehler auftritt? das könnte ungemein helfen.

Gruß
Ken


crashboy - Mi 09.07.03 12:18
Titel: @cenbells
Hab das ganze als String umprogrammiert und die Tabellen neu typisiert.
Funzt jetzt.
Jetzt nur noch die Datensätze ohne QR auf Papier bringen und fertig.

Gruss
crashboy


grayfox - Mi 09.07.03 12:49

hallo crashboy!


Delphi-Quelltext
1:
StrToInt(DBEdit2.Text)                    

das hab ich dir aber so sicherlich nicht gesagt. nimm lieber ein Edit-feld zum erfassen der menge, das ist einfacher.
den EAN-code würde ich auch als string und nicht als integer ablegen - du willst ja nicht damit rechnen.

mach deinen bericht lieber mit QR, das geht einfacher und schneller als 'zu fuss'. vor rund 2 wochen hat kiwicht hier im forum ein tolles tutorial über die anwendung von QR erstellt.

mfg, stefan


crashboy - Mi 09.07.03 14:47
Titel: @all
Ich habe das jetzt alles als String gemacht. Problem war nur den Scanner dazu zu kriegen, die Daten nicht numerisch zu schicken. Hätte ich auch erst wieder umwandeln müssen. Nu funzt es erstmal ganz gut und ich hab viel gelernt.

Gruss
crashboy

Hab jetzt 2 allerletzte Fragen:
Soweit haut alles hin. Will aber noch eine 2. Abhängigkeit einbauen.
Die Daten sollen erst dann in die zweite Tabelle eingetragen werden, wenn beide Edit-Felder ausgefüllt sind. Das funzt aber mit dem .AND. nicht ganz.
Wie kann ich das realisieren?
Und 2. wie kann ich am einfachsten einen Tabelleninhalt löschen?


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TForm1.Edit1Exit(Sender: TObject);

begin
Table2.Append;
if Edit1.Text <>'' .AND. Edit2.Text <> '' then
begin
   if table1.locate('Artikelnr', Edit1.Text, [])  then begin
    with Table2 do begin
      FieldByName('Artikelnr').AsString:= Table1.FieldByName('Artikelnr').asString;
      FieldByName('Artikelnam').asString:= Table1.FieldByName('Artikelnam').asString;
      FieldByName('Anzahl').asString:= Edit2.Text;
      Table2.Post
    end;

  end else
   ShowMessage('EAN-Code noch nicht angelegt');
  end else
  ShowMessage('EAN-Feld darf nicht leer sein');
  end;



Gruss
crashboy


grayfox - Mi 09.07.03 14:57

diesen satz hier versteh ich nicht:
Zitat:

die Daten nicht numerisch zu schicken...

mal langsam zum mitschreiben:
du stellst dich auf das eingabefeld es EAN-codes und liest mit dem scanner den code ein - dieser füllt das einabefeld genauso, als wenn du über die tastatur ziffer für ziffer eintippen würdest. richtig?
den inhalt des edit-feldes hast dann als string vorliegen. stimmts?

was hättest denn da hin- und herwandeln müssen?

mfg, stefan


crashboy - Mi 09.07.03 18:24
Titel: @grayfox
Als ich die gescannten EAN's als Typ Character in meiner Tabelle Speichern wollte ging es nicht. Nur Numerisch. Sorry, war aber so.

Bin immernoch dabei die 2. If-Anweisung einzubinden. Ich platziere das dazugehörige Endfalsch. Könnte verrückt werden.
Und dann stören auch immernoch die lästigen Nachbarn weil meine LAG heute ihre Fahrprüfung bestanden hat.

Hier nochmal der derzeit funzende Code:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.Edit1Exit(Sender: TObject);

begin
if Edit1.Text <>''  then
begin
   if table1.locate('Artikelnr', Edit1.Text, [])  then begin
        if Edit2.Text<> ''  then begin
    with Table2 do begin
    Table2.Append;
      FieldByName('Artikelnr').AsString:= Table1.FieldByName('Artikelnr').asString;
      FieldByName('Artikelnam').asString:= Table1.FieldByName('Artikelnam').asString;
      FieldByName('Anzahl').asString:= Edit2.Text;
      Table2.Post
    end
   end;
  end else
   ShowMessage('EAN-Code noch nicht angelegt');
  end else
  ShowMessage('EAN-Feld darf nicht leer sein');
  end;

Problem: jeder Artikel wird 2x in der 2. Tabelle abgespeichert. Einmal mit der Bezeichung des Edit2-Feldes und einmal mit der tatsächlich eingegebenen Anzahl.
Und wie gesagt, wie bekomme ich die Tabelle ohne SQL am schnellsten leer? Records zählen und ne Zählschleife bauen?

Gruss
crashboy


grayfox - Mi 09.07.03 18:48

versuchs mal so - vorsicht: untested ;)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
procedure TForm1.Edit1Exit(Sender: TObject); 
begin 
  if Edit1.Text ='' then begin
    ShowMessage('EAN-Feld darf nicht leer sein');
    Exit 
  end;
 
  Table2.Append;  
  if table1.locate('Artikelnr', Edit1.Text, [])  then begin 
    with Table2 do begin 
    FieldByName('Artikelnr').AsString:= Table1.FieldByName('Artikelnr').asString; 
    FieldByName('Artikelnam').asString:= Table1.FieldByName('Artikelnam').asString; 
    FieldByName('Anzahl').asString:= Edit2.Text; 
    Table2.Post 
  end else 
    ShowMessage('EAN-Code noch nicht angelegt'); 

end;


.AND. gehört zu DBase & Clipper und wird von delphi nicht unterstützt *g*
vergleiche mit mehreren parametern schrteibt man in klammern:


Delphi-Quelltext
1:
  if (Edit1.Text <>'') and (Edit2.Text <> '') then ...                    


sieht dir mal das format des EAN-codes in der tabelle an. ist das ein ziffernfeld?

mfg, stefan
ps: gratulation unbekannterweise an deine freundin. dann feiert mal schön ;)