Clipper 97 goes Xbase++ goes MDI ?

Auf dem Weg von Clipper, FoxPro u.ä. nach Xbase++

Moderator: Moderatoren

KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

Hallo an alle, ich grüße Euch

Habe früher Programme in clipper 97 geschrieben ( Privat ) -- habe danach Xbase++ verwendet um die Programme auf Windows XP zu portieren -- mit minimalen Änderungen, d.h. so wenig zu ändern wie möglich - keine GUI - hauptsache es läuft :-)

Jetzt habe ich ein Problem:

Adressverwaltung und Terminplanung soll in 2 Fenstern gleichzeitig ablaufen !

Habe Xbase 1.82 + Tools und express++ zur Verfügung !

Anwedung läuft bereits unter xbase++ aber in reinem clipper code compiliert mit minimaler Anpassung !!!


Möchte jetzt praktisch wissen - wir groß der Aufwand ist damit gleichzeitig die Adressen und die Terminplanung in 2 Windows Fenstern aufrufbar und gleichzeitig verwendbar ist - hoffe ich habe mich verständlich ausgedrückt.

Wie fange ich überhaupt an ?
Was muß ich ändern ? --> wenn es geht so wenig wie möglich

mfg klaus
Benutzeravatar
Wolfgang Ciriack
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2932
Registriert: Sa, 24. Sep 2005 9:37
Wohnort: Berlin
Hat sich bedankt: 13 Mal
Danksagung erhalten: 34 Mal
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Wolfgang Ciriack »

Hallo Klaus,
wenn dein Programm netzwerkfähig ist, warum dann nicht einfach das Programm 2x starten ?
Viele Grüße
Wolfgang
KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

Das habe ich mir auch schon gedacht -

es ist aber nicht netzwerkfähig ! wobei das wohl für meine Bedürfnisse die beste Lösung wäre

.... im moment steht im SOURCE ja " set exclusive on " sonst würde xbase ja bei jedem ändern bzw anfügen mit
einer Fehlermeldung aussteigen ...

gibt es eine möglichst einfache Möglichkeit das ganze netzwerktauchlich zu machen ...


habe da auch mal was von der DATA-Komponente DBFDBE gelesen und dem Modus DBF_Autolock
wie müßte ich meinen Clipper Source verändern um diese Funktion zu nutzen ?

Source für Datenbankaufruf ... etc.

mfg klaus
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21165
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 206 Mal
Danksagung erhalten: 67 Mal

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Manfred »

Hi Klaus,

es stellt sich jetzt die alte Gretchenfrage: "Was hast Du noch alles vor unter oder mit Xbase++ zu machen?" Soll es bei diesem Projekt bleiben, oder willst Du mehr machen?

Hier wurde schon ausgiebig im Forum über das Thema diskutiert. Wenn Du vor hast mehr zu machen, dann freunde Dich mit dem Gedanken an, alles neu und unter GUI zu machen und dann gleichzeitig auch netzwerktauglich. Mehrmals öffnen ist auch Netzwerk. Alles andere ist nur vergebene Liebesmühe außer Du willst viel lernen. :roll: (Glaube es mir, ich habe auch viel Erfahrung auf dem Gebiet gesammelt in den letzten Jahren. :lol: )

Wenn es allerdings bei diesem Projekt bleiben soll, dann wirst Du wohl stricken müssen, bis es ungefähr so paßt. Also mit Neterr() usw.

Wie sieht es mit OOP aus? Vielleicht baust Du Dir Klassen, die dann für weitere Projekte alle Arbeiten einfach übernehmen?
Möglichkeiten gibt es einige, Du mußt Dir aussuchen, was für Dich am besten geeignet ist.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von AUGE_OHR »

KlausXXL hat geschrieben:Habe früher Programme in clipper 97
du meinst sicherlich Summer 87
KlausXXL hat geschrieben:Adressverwaltung und Terminplanung soll in 2 Fenstern gleichzeitig ablaufen !
Habe Xbase 1.82 + Tools und express++ zur Verfügung !
Die 3PP Libs haben damit nichts zu tun
KlausXXL hat geschrieben:Möchte jetzt praktisch wissen - wir groß der Aufwand ist damit gleichzeitig die Adressen und die Terminplanung in 2 Windows Fenstern aufrufbar und gleichzeitig verwendbar ist - hoffe ich habe mich verständlich ausgedrückt.
Wie fange ich überhaupt an ?
Was muß ich ändern ? --> wenn es geht so wenig wie möglich
und da gibt es mit S87 eine Menge Probleme z.b. mit Variabeln die ja alle Private/Public sind.

Wolfgang schlug ja schon vor das Programm 2x zu starten.
Ich würde sogar noch weiter gehen und sagen "zerlege" es in 2 separate Programme,
wobei später "gemeinsame" Teile in eine Lib/DLL kommen.
KlausXXL hat geschrieben:.... im moment steht im SOURCE ja " set exclusive on " sonst würde xbase ja bei jedem ändern bzw anfügen mit einer Fehlermeldung aussteigen ...

gibt es eine möglichst einfache Möglichkeit das ganze netzwerktauchlich zu machen ...
Alle Tools die ich damals ausprobiert habe sind nur "Hilfsmittel" um die Stellen zu finden wo eine Modifikation notwendig ist.
Das selbe Ergebniss bekommst du auch mit Try & Error wenn du " set exclusive OFF " nimmst und einfach die Fehlermeldung liest.
Dabei solltest du dann VX20 IDE benutzen dann hast du Editor/Compile/Debug alles zusammen
KlausXXL hat geschrieben: habe da auch mal was von der DATA-Komponente DBFDBE gelesen und dem Modus DBF_Autolock
wie müßte ich meinen Clipper Source verändern um diese Funktion zu nutzen ?
Frage : solle es noch mit Cl*pper arbeiten ?
Der DBFDBE (DATA-Komponente) DBF_AUTOLOCK Modus ist nicht Cl*pper compatible und erfordert die Modifizierung der DBF.
Auf das Problem "lost Update" wird ja hingewiesen, also zusätzliche Arbeiten evtl. notwendig.

aber zurück zu deiner Frage "wie mache ich es Netzwerkfähig" :

1.) " set exclusive OFF "
2.) suche die Stellen wo du eine DBF "öffnest".

Code: Alles auswählen

statt
USE KUNDEN

wird jetzt
IF NET_USE("KUNDEN")
ELSE
ENDIF
In der Function NET_USE() wird dann die DBF mit vollen PATH geöffnet (SHARED).
Ich öffne in NET_USE dann auch die "passenden" INDEX Datei dazu
3.) suche die Stellen mit REPLACE

Code: Alles auswählen

statt
REPLACE a->KDNR WITH cKDNR

wird jetzt
IF NET_RLOCK()
   REPLACE KUNDEN->KDNR WITH cKDNR
   UNLOCK  // wieder freigeben !
ENDIF
4.) suche die Stellen wo du APPEND BLANK hast

Code: Alles auswählen

statt
APPEND BLANK

wird jetzt
APPEND BLANK
IF NETERR()
   // Fehler aufgetreten
ENDIF
das ist es im Grund ... viel Spass
gruss by OHR
Jimmy
KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

OK erstmal DANKE an alle für die schnelle Hilfe ...

werde die einfache Lösung von Auge_Ohr verwenden ...

So habe bis jetzt folgendes gemacht:

habe die Adressverwaltung herausgelößt und als eigenes EXE File compiliert ... Umstellung für Netzbetrieb ist auch fertig

starte diese aus meinem Terminplanerprogramm mit RunShell("","adresse.exe",.T.)

funktioniert soweit

Frage: gibt es eine Möglichkeit wenn ich den Terminplaner beende --> automatisch vorher das geöffnete Adressprogramm automatisch vorher mit zu beenden.

Im Moment bin ich an der Anpassung des Terminplaners --> ist leider ne menge such und tipparbeit :-)

mfg Klaus
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von AUGE_OHR »

KlausXXL hat geschrieben:Frage: gibt es eine Möglichkeit wenn ich den Terminplaner beende --> automatisch vorher das geöffnete Adressprogramm automatisch vorher mit zu beenden.
Ja

Code: Alles auswählen

Text in der Titelzeile der "Fenster"

CloseIt( { "Nachricht lesen", ;
           "Nachricht schreiben", ;
           "Nachrichten Eingang", ;
           "Nachrichten gesendet" } )

**********************************************
#include "DLL.CH"

#define WM_CLOSE        0x0010
#define WM_QUIT         0x0012

DLLFUNCTION SendMessageA( nHwnd, nCmd, wParam, lParam) USING STDCALL FROM USER32.DLL

FUNCTION CloseIt( aNaam )
LOCAL i, nMax := LEN( aNaam )

   FOR i = 1 TO nMax
      CloseNow( aNaam[ i ] )
   NEXT
RETURN NIL

FUNCTION CloseNow( cNaam )
LOCAL oDlg
LOCAL aTasklist
LOCAL aSize     := { 0, 0 }
LOCAL aPos      := { 0, 0 }
LOCAL lRunnin   := .F.
LOCAL i
LOCAL nHwnd, cWind

   oDlg := XbpDialog() :new( AppDesktop(),, aPos, aSize,, .F. )
   oDlg:clipSiblings := .T.
   oDlg:drawingArea:ClipChildren := .T.
   oDlg:create()
   SETAPPFOCUS( oDlg )
   aTasklist := GetTaskList( oDlg:gethWnd( ) )
   FOR i = 1 TO LEN( aTasklist )
      cWind := TRIM( UPPER( SUBSTR( aTasklist[ i ], 9 ) ) )
      cWind := SUBSTR( cWind, 1, LEN( cWind ) - 1 )
      IF cWind == TRIM( UPPER( cNaam ) )
         lRunnin := .T.
         nHwnd := VAL( LEFT( aTasklist[ i ], 8 ) )
         SendMessageA( nHwnd, WM_CLOSE, 0, 0 )
         RETURN lRunnin
      ENDIF
   NEXT
RETURN lRunnin

FUNCTION gettasklist( hWnd )
LOCAL aList       := {}
LOCAL cWindowName
LOCAL nVisible

   DO WHILE hWnd != 0
      cWindowname := SPACE( 100 )
      IF ( getwindowtexta( hWnd, @cWindowName, LEN( cWindowName ) ) <> 0 )
         nVisible := IsWindowVisible( hWnd )
         IF nVisible == 1
            AADD( aList, STR( hWnd, 8 ) + cWindowname )
         ENDIF
      ENDIF
      hWnd = GetWindow( hWnd, GW_HWNDNEXT )
   ENDDO
RETURN aList

FUNCTION GetWindow( hWnd, uCmd )
LOCAL nDll := DllLoad( "USER32.DLL" )
LOCAL xRet := DllCall( nDll, DLL_STDCALL, "GetWindow", hWnd, uCmd )
   DllUnLoad( nDll )
RETURN xRet

FUNCTION GetWindowTextA( hWnd, lPstring, nMax )
LOCAL nDll := DllLoad( "USER32.DLL" )
LOCAL xRet := DllCall( nDll, DLL_STDCALL, "GetWindowTextA", hWnd, @lPstring, nMax )
   DllUnLoad( nDll )
RETURN xRet

FUNCTION IsWindowVisible( hWnd )
LOCAL nDll := DllLoad( "USER32.DLL" )
LOCAL xRet := DllCall( nDll, DLL_STDCALL, "IsWindowVisible", hWnd )
   DllUnLoad( nDll )
RETURN xRet
gruss by OHR
Jimmy
KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

Danke .. werde dies mal versuchen zu verstehen und dann testen

...

hätte da noch was ...

Compilire mein Programm im GUI Mode damit ich setmode (43, 120) verwenden kann

Wie kann ich beim Start die Position des Fensters auf dem Desktop auf dauer festlegen ?

mfg Klaus
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Rolf Ramacher »

Hi Klaus,

ich habe es mir etwas vereinfacht um nicht immer wieder Dialogerstellung zu kopieren, habe ich mir eine Funktion gebaut, diese wird nur aufgerufen.

Hier der aufruf

Code: Alles auswählen

	oDlg:=DialogErzeugen({100,100},{600,400},"Verkaufsprogramm","UP")
Es wird übergeben 1. Position des Dialoges, 2. Dimension des Dialoges, 3. Titel, 4. Hinweis zur internen Farbgestaltung

Hier der Dialogerstellung:

Code: Alles auswählen

#include "Gra.ch"
#include "Xbp.ch"
#include "Appevent.ch"
#include "Font.ch"
#include "Inkey.ch"

Function DialogErzeugen(aPos,aDim,cTitel,Prg,cString)

	Local nEvent, mp1, mp2, lFarbe:=.t., oDlg, drawingArea, aFarbe:={}, cHeimat:=""

	aRueck:=FarbAbfrage(Prg)
	aFarbe:=aRueck[1]

   oDlg := XbpDialog():new( AppDesktop(), , aPos, aDim, , .F.)
   oDlg:taskList := .T.
   oDlg:title := cTitel
	oDlg:maxsize:=aDim
	oDlg:Minsize:=aDim
   oDlg:create()
	CenterControl(oDlg)

	// Abfrage für 16-Bit
	If File("sprinter.bat") .and. cString <> "e"
		use Sysconf New
		cHeimat:=alltrim(Sysconf->Heimat)
		Close Sysconf
		FileDelete("*.cdx")
		Index(oDlg,.t.,cHeimat)
	EndIf
	
   drawingArea := oDlg:drawingArea
   drawingArea:setFontCompoundName( "9.Arial")

	If aRueck[2]=.f. .and. !empty(aFarbe)
		If aFarbe[1] >0 .or. aFarbe[2] >0 .or. aFarbe[3] >0
			drawingArea:setColorBG( GraMakeRGBColor(aFarbe ) ) 
		EndIf
	EndIf

   oDlg:show()
	SetAppFocus(oDlg)

Return oDlg
Vielleicht hilft es dir weiter.
- Wie Manfred schon geschrieben hat. Den Weg bin ich auch gegangen - Wenn du deinen kompletten Programme auf xbase und mit neuer Maskengestaltung arbeiten möchtest (deine Kunden auch) wirst du um den Weg GUI - NICHT vorbeikommen. Ich habe mich dabei auch von "alten Zöpfen" befreit.
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

Performance Problem ???

Mein Test Notebook: XP + Intel Pentium M 1,5GHz + 512 Arbeitsspeicher

da laufen Fenster: 1xTerminplaner + 3xAdresse ohne 'Probleme


auf Benutzer PC: XP + AMD X2 BE2400 + 3GB Arbeitsspeicher

da laufen Fenster: 1xTerminplaner + 2xAdresse da fängt es schon an - wie soll ich es sagen - zu hackeln ,

d.h. keine flüssige Bedienung der Fenster mehr !?!?!?!?!?!?!

WIE KANN DAS SEIN -- da der Benutzer PC wesentlich mehr Leistung und Arbeitsspeicher hat !!!"

jemand ne IDEE ?

mfg Klaus
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Tom »

Hallo, Klaus.

Mit eXpress++ hast Du eigentlich das Mittel der Wahl zur Verfügung, um aus einer alten Clipper-Anwendung innerhalb kürzester Zeit eine MDI-fähige GUI-App zu machen. Nach der Umstellung der Datenbankzugriffe auf nichtexclusive Nutzung (Lock/Unlock) solltest Du allerdings NICHT, wie hier empfohlen wurde, Deine Module als EXEn getrennt starten, sondern mit Multithreading arbeiten. Das ist in Xbase++ sehr simpel. PUBLIC-Variablen sind in allen Threads sichtbar, aber Workareas sind gekapselt. Deshalb kann man Programmteile relativ problemlos mehrfach aufrufen, ohne dass sie sich "beißen" - vorausgesetzt, das ganze ist netzwerkfähig. Wichtig dafür ist, dass Deine eXpress++-Dialoge (bist Du damit schon durch?) NICHT modal erzeugt werden, jedenfalls diejenigen, die mehrfach aufgerufen werden können.

Wenn Du Dein Hauptmodul/-menü bereits mit eXpress++ erzeugst, müssen die Aufrufcodeblöcke für die mehrfach zu startenden Module einfach dieserart geändert werden (ACTION-Codeblöcke von MENUITEMS oder DCPUSHBUTTONS):

Aus "{||MeinTerminkalender()}" wird:

Code: Alles auswählen

{|o|o:=thread():new(),o:start({||MeinTerminKalender()})}
Damit liefe "MeinTerminKalender" in einem neuen Thread, der mit dem RETURN am Ende dieses Moduls automatisch beendet wird. Wenn "MeinTerminKalender" nicht-modal wäre, könnte der Anwender ins Hauptmenü "rüberklicken" und das Modul beliebig oft abermals aufrufen. Aliase und Workareas können mehrfach verwendet werden, da sie im Thread gekapselt sind. Nur bei exclusiven Datenbankzugriffen muss man aufpassen - das crasht so nämlich. Und alle Variablen, die nicht PUBLIC sind, sind in Threads nicht sichtbar. Hier sind möglicherweise noch Vorarbeiten nötig.
Herzlich,
Tom
Juergen
UDF-Programmierer
UDF-Programmierer
Beiträge: 92
Registriert: Di, 19. Dez 2006 19:37
Wohnort: Düsseldorf
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Juergen »

Hallo Klaus,

ich habe das auch so wie Tom programmiert. {|o|o:=thread():new(),o:start({||.... usw. .

Die Netzwerkroutinen konnte ich mit leichten Modifikationen aus meinen alten
Clipper-Quellen übernehmen.

Ich benutze auch eXpress++ .
Das ist einfach genial. Das ist in keiner anderen Programmiersprache so einfach möglich.
Auf diese Art konnte ich schnell und preisgünstig eine Anwendung auf Windows umstellen.

Ich würde allerdings raten, im Thread möglichst keine Public-Variable anzulegen.
Ich benutze hier gegen alle Empfehlungen neben Local- auch Privat-Variable (ist einfach bequemer),
diese werden nach Beendigung des Prozesses gelöscht.

Funktioniert schon seit Jahren ohne Probleme.

Gruß
Jürgen
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von AUGE_OHR »

... wobei später "gemeinsame" Teile in eine Lib/DLL kommen.
nun ich wollte bei meiner Antwort nicht gleich mit DLL und Threads anfangen für jemanden der von S87 kommt ... ;)

Was die Variablen angeht : PRIVATE sind doch auch nicht Thread "safe", oder ? [-X

also unbedingt mit /w compilieren und die angemahnten Variabel deklarieren.
Performance Problem ???
hm ... S87 Code ... verwendest du INKEY() ... evtl mit 0 ? nimmm 0.1 !!!
auch andere Stellen wo Cl*pper "wartet" müssen für Xbase++ modifiziert werden.

starte doch mal den Taskmanager und dann deine S87 vs. Xbase++ Version.
Wenn die Xbase++ Version > 10% braucht sind bestimmt noch "Cl*pper wait-state" in deinem Source vorhanden.
einfach "beobachten" wo die CPU % "ansteigen" ... nimm VX20.EXE als Debugger und mit F8 STEP um die genaue Stelle zu lokalisieren.
... werde dies mal versuchen zu verstehen und dann testen
Was macht der Code :
nun du gibt, als Array, die "Namen" der "Fenster" an welche geschlossen werden sollen.
Die "Namen" sind nun die "Titel" der "Fenster" wie du sie auch im Taskmanager sehen kannst.

Der Code holt mit GetTaskList() die Namen aus dem Taskmanager und vergleicht mit IF cWind == TRIM( UPPER( cNaam ) ) ob du es als Element angegeben hast.
Per SendMessageA( nHwnd, WM_CLOSE, 0, 0 ) wird nun an das "Fenster" der WM_CLOSE Event gesendet.
Wenn du keinen :Close Codeblock hast verwende WM_QUIT
gruss by OHR
Jimmy
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Rolf Ramacher »

Hi,

ich nutze auch wie Jürgen fast ausschließlich Local Variablen, damit diese auch nur in der Function bekannt sind. Privat nutze ich ganz selten - Public gar nicht mehr, da ja jede .exe im eigenen Thread arbeitet.
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

Vielen DANK erstmal für eure Bemühungen und Erklärungen !

Letzter stand:

Werde jetzt erstmal alles auf 3 exe Files ändern

---> express verwende ich ausschließlich im Moment für Druckausgaben --- ich weiß bei dem funktionsumfang gehöre ich dafür gesteinigt ..

Ich habe im Moment probleme mit folgendem code:

...
cdatumn1:=space(8)

clear gets
@35,4 say "VON :" get cdatumn1 picture "99.99.99"
read

...

flock()
aktuell:=ctod(cdatumn1)
? aktuell
wait("")
replace twoche with left(cdow(aktuell),2) <--- fehler
unlock

Fehler bei: twoche
Fehlermeldung: Base/8027
unkown symbol for database field

mfg Klaus
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Tom »

Hallo, Klaus.

Welchen Datentyp hat "TWOCHE"?

Am Rande: Warum initialisierst Du "cdatumn1" als String? Datumsfelder (dDatumn1 := Date() oder dDatumn1 := CtoD(" . . ")) werden bei GETs automatisch formatiert (PICTURE ist überflüssig), darüberhinaus reagieren die GETs auf SET DATE- und SET CENTURY-Einstellungen automatisch - und die Eingabe wird validiert (falsche Datumseingaben sind nicht möglich).
Herzlich,
Tom
KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

Tom hat geschrieben: Welchen Datentyp hat "TWOCHE"?
twoche ist in der Datenbank: twoche --> Character 2

da sollte dann drinstehen : Mo , Di, Mi , Do , Fr ... Wochentag abgekürzt

mfg Klaus
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Tom »

Hallo, Klaus.

Die Datenbank ist nicht selektiert:

8027 - [BASE] - ???
Associated with: "65:Unknown symbol for database field"
Caused by: Accessing of a database FIELD that does not exist in the
currently selected workarea. Use Alias->FieldName instead.


(Aus der XppErrors.chm von Andreas Gehrs-Pahl.)
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von AUGE_OHR »

Tom hat geschrieben:Hallo, Klaus.
Welchen Datentyp hat "TWOCHE"?
Am Rande: Warum initialisierst Du "cdatumn1" als String?
Ich habe ja schon ewig nicht mehr mit S87 gearbeitet, aber viele haben damals noch mit dBase III+ gearbeitet und S87 lediglich als Compiler verwendet.
Wenn ich mich nicht irre gab es aber "damals" das "Problem" beim dBase III Datum ... die meisten (auch ich) haben dann XX.XX.XX statt 99.99.99 verwendet.

Dies ist übrigens, wenn man noch ein 2-stelliges Jahr hat, auch das "2K Problem" gewesen das man dann vom Type "C" auf Type "D" umgestellt hat, aber für andere Sachen wieder auf Type "C" zurück konvertieren musste.
KlausXXL hat geschrieben: flock()
aktuell:=ctod(cdatumn1)
? aktuell
wait("")
replace twoche with left(cdow(aktuell),2) <--- fehler
unlock
Anmerkungen
flock() : warum ? ist schon eine DBF geöffnet ? Was ist der Rückgabe Wert ?
wait() : hoffentlich "nur" hier als "Demo" ... ? siehe mal im Taskmanager nach CPU % beim "Wait"
replace twoche : auf welchem SELECT bist du ? man sollte möglich immer einen ALIAS verwenden
left(cdow(aktuell),2) : du speicherst doch eh das Datum, oder ?
gruss by OHR
Jimmy
KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

Tom hat geschrieben:Die Datenbank ist nicht selektiert:
...
Tom hatte natürlich recht ... falscher select bereich ... war alles so verschachtelt, daß ich es nach mehrmaligem durchsehen ... übersehen habe . Danke Tom

ach ja die wait() kommen natürlich wieder raus ... habe ich mir nur so angewöhnt um zu sehen wenn irgendwo ein Fehler ist

mfg.

ach ja was ist eigentlich die einfachste Möglickeit einen bestehenden Termin zu KOPIEREN , d.h. alle daten des Datensatzes zu Übernehmen außer Terminnr und Datum des Termins

z.B.

terminnr, datum des Satz muß geändert werden

alles ander nur kopiert werden: adresse,Tel, etc

mfg Klaus
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Tom »

Hallo, Klaus.

Die Funktion "Scatter()" liest alle Felder eines Datensatzes in ein Array, "Gather()" ist die Gegenfunktion, die zurückschreibt. Damit kann man sehr leicht kopieren, aber zum Beispiel auch die Daten für Anzeigemasken sammeln. Nach dem "Gather()" auf dem neuen Datensatz musst Du lediglich die veränderten Daten (Terminnummer, Datum) "nachschieben".

Also:

Code: Alles auswählen

* auf dem zu kopierenden Datensatz
a := Scatter()
DbAppend()
Gather(a)
TerminNr := NeueTerminNr()
* use
DbUnlock()
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von AUGE_OHR »

KlausXXL hat geschrieben:ach ja was ist eigentlich die einfachste Möglickeit einen bestehenden Termin zu KOPIEREN , d.h. alle daten des Datensatzes zu Übernehmen außer Terminnr und Datum des Termins
Der Tip von Tom bezieht sich eher auf XbpSLE, den beim GET hätten wir als Array ja die GETlist().
Diese sollte immer als LOCAL GETlist := {} deklariert werden.

In "reinem" Cl*pper Code könnte es so aussehen:

Code: Alles auswählen

LOCAL i, iMAX
LOCAL aKopie := {}

// Anzahl FELDer
iMax := FCOUNT()
// Werte in ein Array einlesen
FOR i := 1 TO iMax
      AADD(aKopie, FIELDGET(i) )
NEXT
// Datensatz anhängen
APPEND BLANK
IF NETERR()
    // ERROR 
ELSE
   // Array Element in die DBF schreiben
   FOR i := 1 TO iMax
         FIELDPUT(i, aKopie[i] )
   NEXT
ENDIF
zum Schluss müsstest du noch die FELDer Terminnr und Datum überschreiben.
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von Tom »

Der Tip von Tom bezieht sich eher auf XbpSLE
Scatter() und Gather() sind zwar nicht explizit dokumentiert, funktionieren aber auch ganz ohne Xbparts. :wink:
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von AUGE_OHR »

Tom hat geschrieben:Scatter() und Gather() sind zwar nicht explizit dokumentiert, funktionieren aber auch ganz ohne Xbparts. :wink:
Ja stimmt ja siehe c:\ALASKA\XPPW32\SOURCE\SYS\Blocks.prg

... ich hatte nur :setdata() / :getdata() im Kopf und dazu braucht man ja einen :datalink und den hat ja das XbpSLE ...

ok wieder was gelernt.
gruss by OHR
Jimmy
KlausXXL
Rookie
Rookie
Beiträge: 12
Registriert: Di, 05. Jan 2010 11:27

Re: Clipper 97 goes Xbase++ goes MDI ?

Beitrag von KlausXXL »

gibt es eine sichere Möglichkeit sicherzustellen, daß ein Datensatz - der gerade neu angelegt wurde
in der Datenbank abgespeichert ist -- auch wenn kurze Zeit später das Programm mit einer Fehlermeldung
aussteigt ?


sozusagen nach

append blank
...
replace Feld1 with xyz
etc.

und

replace KundNr with Kundnr +1
....

* JETZT ALLES IN DATENBANKEN ABSPEICHERN *

Hintergrund --- wenn xbase durch Fehlermeldung aussteigt sind zu 90% die zuletzt eingegebenen DATEN weg ...
und was noch schlimmer ist eine Kundennummer bzw Terminnummer wird nicht mit +1 abgelegt ,
so daß beim erneuten Start des Programms eine doppelte Terminnummer neu angelegt wird ... was die
ganzen Daten dureinander bringt ....

mfg Klaus
Antworten