Seite 1 von 1

Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: So, 26. Mai 2013 16:44
von Jojo
Hallo zusammen,

ich muss eine .dbf-Datei abfragen und die Ergebnisse in einer Druckdatei unterbringen.

In der .dbf gibt es exemplarisch die Spalten "Jahr/Monat"", "Anzahl" und "Betrag".
Alles eingerichtet und funktioniert auch, aaaber...auf der Druckausgabe sollen alle Einträge zu einem "Jahr/Monat" kummuliert werden.

Wie stelle ich es an, dass alle Einträge zu einem Monat in einer Zeile angedruckt werden?

Bin für jede Art von Tipp dankbar.

Grüße
Jojo

P.S.: Das Ganze passiert auf einem Linux-System und programmiert habe ich in/mit FlagShip.

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: So, 26. Mai 2013 17:23
von Klaus Stebner
Hallo Jojo,

wenn Flagship die Clipper/Xbase DB-Befehle kennt dürfte es keine großen Probleme geben,
die entsprechenden Ergebnisse zu erzielen.

a) Ausgabe dann in neue DB oder Textdatei möglich.

b) Falls ein Reportprogramm zur Verfügung steht, geht es wahrscheinlich noch einfacher.
-> nur Summenreport ausgeben.

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: So, 26. Mai 2013 17:47
von Jojo
Hallo Klaus,

ja, Flagship ist Clipper/Xbase kompatibel.

Ein Reportprogramm steht (glaube ich zumindest ) nicht zur Verfügung.
Wie bilde ich Summen beim selben Monat/Jahr Eintrag?

Grüße
Jojo

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: So, 26. Mai 2013 21:14
von UliTs
ich schlage vor, dass dieses Thema nach "andere Sprachen" verschoben wird (-> FlagShip) :D .

Uli

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: So, 26. Mai 2013 23:37
von Klaus Stebner
Hallo Jojo,

hier ein Beispielprogramm wie man es machen könnte:

Code: Alles auswählen

/*
 **********************************************************
 * Notice     : Bilde Summen über Felder und speichere die
 * .......... : Ergebnisse in einer anderen DB
 *********************************************************
*/

FUNCTION SumFelder()

LOCAL cJahr_Monat:= "", nSumAnzahl:=0, nSumBetrag:=0
LOCAL oldrec

USE SUMMEN VIA DBFNTX NEW EXCLUSIVE ALIAS SN
// gleiche DB wie Werte (event. Felder erweitern)

USE WERTE VIA DBFNTX NEW ALIAS WE 
// DB muss nach Jahr_Monat sortiert oder indiziert sein.

// setze einen Index auf Jahr_Monat
  Index on WE->JAHR_MONAT to WEDatum
  SET INDEX TO WEDATUM
  GO TOP

Do while .not. EOF()
    IF cJahr_Monat <> WE->JAHR_MONAT     // hier muß summiert werden!
        cJahr_Monat := WE->JAHR_MONAT   
        oldrec      := Recno()           // speichere akt. Satznummer

     	SUM WE->Anzahl TO nSumAnzahl FOR WE->JAHR_MONAT == cJahr_Monat  
     	SUM WE->Betrag TO nSumBetrag FOR WE->JAHR_MONAT == cJahr_Monat  

        GOTO oldrec                      // gehe zum alten Satz, da nach Summierung
                                         // Datensatzzeiger auf EOF steht und Schleife
                                         // beim ersten Mal gleich beendet würde.
        // Werte in neue DB
        SN->(DBAPPEND())
        SN->JAHR_MONAT := cJahr_Monat
        SN->Anzahl     := nSumAnzahl
        SN->Betrag     := nSumBetrag
            
    ENDIF
    
    SKIP
Enddo    

Close Databases

Return (NIL)


Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: So, 16. Jun 2013 21:07
von Jojo
Hallo Klaus,

vielen Dank für die Antwort.
Ich will aber keine neue DBF erzeugen, sondern einfach nur die Ausgabe kummuliert ausgeben.

Ich habe in der tag.dbf folgende Spalten:
▒BER_JM▒ ZEIT_JM▒ A_NB▒ W_NB ▒ A_VL▒ D_VL ▒ V_VL ▒ A_AM ▒
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
▒201306 ▒ 201305 ▒ 0 ▒ 0.00 ▒ 0 ▒ 0.00 ▒ 0.00 ▒ 2 ▒
▒201306 ▒ 201306 ▒ 6 ▒ 2100.00 ▒ 0 ▒ 0.00 ▒ 0.00 ▒ 0 ▒
▒201306 ▒ 201212 ▒ 0 ▒ 0.00 ▒ 1 ▒ 2000.00 ▒ 345.80 ▒ 0 ▒
▒201306 ▒ 201303 ▒ 0 ▒ 0.00 ▒ 7 ▒ 2020.00 ▒ 148.40 ▒ 0 ▒
▒201306 ▒ 201301 ▒ 0 ▒ 0.00 ▒ 7 ▒ 3410.00 ▒ 520.70 ▒ 0 ▒
▒201306 ▒ 201303 ▒ 0 ▒ 0.00 ▒ 1 ▒ 300.00 ▒ 27.00 ▒ 0 ▒


Und da wo ZEIT_JM identisch sind sollen alle folgenden Spalten zusammengerechnet werden.
Anschließend erfolgt die Druckausgabe.
Die dbf soll dabei aber nicht geändert werden.

Angeblich soll ich das mit ASCAN lösen können.
Aber wie?

Ich habe mir die ascan man schon ein dutzend Mal durchgelsen, aber wie ich zwei Zellen prüfe und bei identischem Inhalt die restlichen Zellen zusammenrechne habe ich nicht herausgefunden.

Grüße
Jojo

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: So, 16. Jun 2013 22:50
von brandelh
Vermutlich meinte der Ratgeber mit ASCAN(), dass du die DBF in ein Array zwischenspeicherst, da erst am Ende der DBF sicher ist, dass alle gleichen Zeilen kummuliert sind.
Ich schreibe jetzt ohne zu testen das grundsätzliche Gerüst. Es gibt undokumentierte Funktionen, die einen kompletten Datensatz in ein Array einlesen, ich bin mir aber nie sicher welche was macht und schon gar nicht, ob du die auch nutzen kannst (scatter(), gather()), daher hier ausgeschrieben ;-)

Code: Alles auswählen

function Summenbildung()
   local aDaten := {}, aRecord
   local nSortSpalte
   local nDatenZeile, nFeld, nFeldAnz
   use DB alias DB
   if netuse
      fehlermeldung()
      return .f.
   endif
   nSortSpalte := 2 // oder FieldPos( <cFieldName> )  etc. Fehlerbehandlung bei falschem Namen ...
   nFeldAnz     := (DB)->(fCount()) // die Anzahl ist immer gleich, spart Zeit
   // eventuell einen Index setzen, ist aber keine Voraussetzung.
   go top

   do while ! (DB)->(eof())
      nDatenZeile := ascan( aDaten, {|aR| aR[nSortSpalte] == (DB)->(fieldget(nSortSpalte))} )
      if nDatenZeile > 0 .and. nDatenZeile // die Zeile gibt es schon 
         // Sicherheitshalber die gleichen Felder prüfen (Indexfehler ?) BER_JM und Zeit_JM ...
         for nFeld := 3 to nFeldAnz
            aDaten[nDatenZeile,nFeld] += (DB)->(fieldget(nFeld))  // += entspricht n := n + w
         next
      else
         aRecord := {}
         for nFeld := 1 to nFeldAnz // Alle Felder in einen Satz.
            aadd( aRecord, (DB)->(fieldget(nFeld)) )
         next
         aadd( aDaten, aRecord )
         aRecord := NIL  // Die Daten sollten immer noch in aDaten sein, sicherheitshalber prüfen, es ist schon spät ;-) !
      endif
      (DB)->(dbskip())
   enddo
   close DB 
   // hier sollten nun alle Sätze einmalig eventuell mit Summen enthalten sein.

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Mo, 17. Jun 2013 22:44
von Klaus Stebner
Hallo Jojo,

für dein Problem gibt es viele Lösungswege.
Ob nun mit DB'en, Textdateien oder Arrays ist erst mal sekundär.

Hast Du mein Beispielprgramm mal getestet?

Wenn Ja, wo gab es Probleme?

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: So, 04. Aug 2013 20:41
von Jojo
Hallo Klaus,

sorry, kam nicht eher zum Antworten...
Ja, ich habs getestet, aber ich bekomme bereits in der ersten Programmzeile einen Syntax Error:

Code: Alles auswählen

jm@sles11ext:/ru0/prg> make

-- FS compiler phase:
p100.prg
p100.prg(3459): Error, syntax


v


_FUN SumFelder()

** Warning: C compiler not invoked (1).
make: *** [p100.o] Fehler 1
Und die Zeile 3459 sieht so aus: FUNCTION SumFelder().
So werden auch an anderen Stellen im Prgramm Funktionen eingeleitet. Ich verstehe es nicht.

Ich habe Mal ne generelle Frage zu Flagship:
Wenn man vom Programmieren eher gar keine Ahnung hat insbesondere nicht von Flagship, wie geht man am Besten an die Sache ran?
Einiges habe ich jetzt durch "learning by doing "am bestehenden Programm gelernt und kann auch schon kleine Modifizierungen vornehmen, aber sowas wie das hier schaffe ich nicht alleine.
Zu Flagship gibt es ausser FSMan keine Dokumentationen.
Wäre es da sinnvoll sich ein XBase oder Clipper Lehrbuch anzuschaffen?
Wenn ja welches kannst Du empfehlen?

Grüße
Jojo

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Mo, 05. Aug 2013 0:30
von matyschik
Hallo jojo,

zu Visuel FlagShip gibt es außer dem Fsman auch die Handbücher als PDF Dateien. Diese PDF Dateien stehen auf der MultiSoft Seite
zum Download zur Verfügung. Allerdings ist nur das Online Fsman zur jeweiligen Version aktuell.

Zu XBase++ gibt es kein gedrucktes ausführliches Handbuch. Für Clipper gab es früher viel Literatur, heute aber eventuell nur noch über eine
Suchmaschine zu bekommen.

Das der Compiler bei dem Funktionsaufruf in der Zeile einen Syntaxfehler bekommt ist nicht nachzuvollziehen.
Ich arbeite zwar mit Visuel FlagShip, komme aber mit Deiner Darstellung nicht klar. Es müssten noch ein paar mehr Informationen
vorhanden sein. Arbeitest Du mit Fsmake ?

Bei Visul FlagShip dürfen Variablenname nicht länger als 10 Zeichen, wie auch bei Clipper, lang sein!

Gruß
Johann

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Mo, 05. Aug 2013 11:18
von Rudolf
Hi,
ich würde Harbour verwenden, kann weit mehr und viele User sowie Support. Meinen Flagship hab ich eingemottet, wer ihn haben will kann sich melden, kostet ein Bier ;-)
Grüße
Rudolf

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Mo, 05. Aug 2013 14:14
von matyschik
Hallo Rudolf,

Harbour ist mit Visual FlagShip 7 nicht vergleichbar. Mit Visual FlagShip kann bei gleichem Quellcode sowohl eine GUI Applikation
als auch eine Terminal Version erstellt werden. Hierfür ist beim Compiler der Schalter -io=g für GUI und -io=t für Terminal zu verwenden.

Im folgenden meine Startparameter damit Umlaute, deutsche Sortierung , usw. richtig dargestellt werden.

Code: Alles auswählen

** -----------------------------------------------------------------------------
** Die Schrift SET FONT 'Consolas', 9.5 gibt es in Windows XP noch nicht.
** Sie ist erst ab Windows Vista verfügbar. Man sollte daher z. B.
** die Schrift Cumberland verwenden oder Consolas nachinstallieren.
 
PUBLIC Hilfe_lpp, RowFuss_npp, RowPrm_npp, Version_cp

** -1- PUBLIC für Windows Hauptfenser schließen
////PUBLIC _menu_quit := {|obj, menuID| InQuitWin_(obj, menuID)}
       
** -1- Update Informationen
Version_cp := "0.00.00  ..2013"

** SET Einstellungen setzen
SET BELL OFF
SET CENTURY ON
SET CONSOLE ON
SET DATE GERMAN
SET DEVICE TO SCREEN
SET EXACT OFF
SET SCOREBOARD OFF
SET WRAP ON

** Flagship SET Einstellungen
READINSERT(.T.)
SET AUTOLOCK ON
SET EXCLUSIVE OFF
SET GUICOLORS ON
SET GUITRANSL BOX ON
SET SOURCE ISO
SET FONT 'Consolas', 9.5

** Set German sorting table
FS_SET('loadLang', 1, 'FSsortab.ger')
FS_SET('setLang' , 1)
FS_SET('mapping' , 'FSchrmap.def')

** FlagShip andere Einstellungen
oTopBar:CLEAR()
oApplic:Font:Charset(FONT_ISO8859_15)
FS_SET('guikey', 'FSguikey.iso1')
_aGlobSetting[GSET_G_N_REFRESHDRAW] := -1
oAppWindow:SetFixSize(30, 115)
** -----------------------------------------------------------------------
Die Schalter -io=a Hybrid braucht man nicht, -io=b Basic sollte man nicht verwenden. Mit welcher Version von FS hast Du denn mal gearbeitet?
Mit Harbour ist in der Grundversion kein GUI verfügbar.

Gruß
Johann

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Mo, 05. Aug 2013 15:05
von brandelh
Ich erhalte auch Fehlermeldungen bei PROCEDURE oder FUNCTION etc. wenn in der Routine DAVOR die Struktur nicht sauber abgeschlossen wurde.
z.B.
if end ... endif => Do case ... und ENDIF nicht gegen END(case) getauscht oder FOR NEXT nach DO WHILE etc. geändert ...
oder in einer IF Bedingung ist ein Fehler, der dort nicht richtig erkannt wird ...

Bei Xbase++ sind das dann "Strukturfehler" ... wobei meist zuvor noch andere Fehlermeldungen stehen.

Eine Fehlerquelle sind auch unbedacht gewählte #DEFINE NAMEN, da diese ja einfach getauscht werden könnte das unerwünschte Teile treffen.

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Mo, 05. Aug 2013 18:46
von Rudolf
Hallo,
na dann viel Spass, Harbour mit FiveWin ist weit mächtiger als Flagship, habe lange herumprobiert und Flagship als Fehlinvestition abgeschrieben. Aber jeder muss da seine eigene Erfahrung machen.
Grüße
Rudolf

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Mo, 05. Aug 2013 21:39
von Jojo
Hallo zusammen,

da ist ja richtig Leben in den Thread gekommen :D

@Hubert: Ich habe die Funktion mitten in eine "Do While" Schleife gesetzt :banghead: Danke!
Jetzt bekomme ich zumindest eine andere Fehlermeldung an der ich weiter arbeiten kann :D

@Rudolph: Wenn ich bei einem Kunden ein komplettes, lauffähiges Programm in Flagship habe stellt sich die Frage auf eine andere Programmiersprache umzusteigen eher nicht... Und der Kunde ist mit seinem Programm seit Jahrzenten zufrieden :-)

@Johann: Ich arbeite mit VFS7. Das FSmake hat mein Vorgänger eingerichtet. Ist ganz nützlich, weil wirklich nur die veränderten Quellen compilliert werden und nicht jedesmal das ganze Programm.

Aber meine Frage an die Flagshipper war eigentlich...wie habt Ihr Flagship "gelernt"?

Grüße
Jojo

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Di, 06. Aug 2013 7:40
von Rudolf
Hallo Jojo, dann ist es natürlich klar. Um Flagship zu lernen müsste die klassische Clipper Literatur reichen, ich habe leider meine Bücher alle schon entsorgt.

Grüße
Rudolf

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Mo, 30. Sep 2013 23:41
von Jojo
Für alle die es interessiert, bzw. die ein ähnliches Problem haben...

Der "Vater des Programms" hat es wie folgt gelöst:

Code: Alles auswählen

do while ! eof()

    x_i = ascan( a_jj, { | ava | ava[1] = zeit_jm })
    if x_i = 0

       aadd( a_jj, { zeit_jm, a_nb, w_nb, a_vl, d_vl, (a_am+a_ao),;
                       d_au, a_tr, d_tr, a_bk, w_bk } )
    else

       a_jj[ x_i ][ 2 ] += a_nb
       a_jj[ x_i ][ 3 ] += w_nb
       a_jj[ x_i ][ 4 ] += a_vl
       a_jj[ x_i ][ 5 ] += d_vl
       a_jj[ x_i ][ 6 ] += (a_am+a_ao)
       a_jj[ x_i ][ 7 ] += d_au
       a_jj[ x_i ][ 8 ] += a_tr
       a_jj[ x_i ][ 9 ] += d_tr
       a_jj[ x_i ][10 ] += a_bk
       a_jj[ x_i ][11 ] += w_bk
    endif
    skip
    loop
 enddo
...ich bin immer wieder beeindruckt wie leicht das aussieht. :notworthy:
Aber wenn ich mich selbst daran versuche scheitere ich jedesmal kläglich #-o

Grüße
Jojo

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Di, 01. Okt 2013 9:10
von Jan
Stimmt, sieht einfach und vertraut aus. Genau sowas mache ich auch öfters mal.

Das Einzige, was mich irritiert, ist das LOOP unten. Mir ist bewußt, daß das legal ist. Aber ich seh den Sinn an genau dieser Stelle nicht, da ja ohnehin das Ende der Schleife erreicht ist und sowieso nach oben gesprungen wird.

Jan

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Di, 01. Okt 2013 15:09
von Tom
Das ist tägliches Handwerkszeug und eigentlich ganz simpel. Man sammelt Daten in einem Array, und eine Spalte des Arrays ist quasi der "Index". Existiert ein neu zu erfassender Wert/Eintrag noch nicht in diesem Index, wird das Array verlängert. Anschließend erhöht man die Werte in den entsprechenden Spalten. Wer es ganz fein mag, sortiert das Array am Ende noch. Sehr elegant ist es, die Inhalte der Arrayspalten über DEFINEs zu referenzieren, das hilft auch später bei Anzeige und Auswertung:

Code: Alles auswählen

#define INDEX 1
#define KILOMETER 2
#define ZEIT 3
#define SUMME 4

* Sammelfunktion:

n := SuchenachIndexPosition

IF n = 0 // existiert der Eintrag schon?
  aAdd(a,{"",0,0,0})
  n := Len(a)
  a[n,INDEX] := cSummenkriterium  
ENDIF
a[n,KILOMETER] += nKilometer
a[n,ZEIT] += nZeit
usw.

Früher - zu Clipper-Zeiten - hat man Hilfsdateien erzeugt und sich mit diesen ganz ähnlich verhalten.

Re: Abfrage einer .dbf ->Daten zusammenziehen

Verfasst: Di, 01. Okt 2013 17:13
von Wolfgang Ciriack
Das mit den #defines erleichtert dann später auch ungemein das Einfügen von Werten und die Lesbarkeit. :wink: