Activex und Word
Moderator: Moderatoren
- Koverhage
- Der Entwickler von "Deep Thought"
- Beiträge: 2470
- Registriert: Fr, 23. Dez 2005 8:00
- Wohnort: Aalen
- Hat sich bedankt: 102 Mal
- Danksagung erhalten: 3 Mal
- Kontaktdaten:
Activex und Word
Hallo,
habe das Sample (Feed) ausprobiert und auch meine Programme dahingehend abgeändert, da es sehr gut funktioniert.
Jetzt wollen aber einige Anwender das erstellte Dokument nicht sofort drucken, sondern die Möglichkeit haben diesen zu bearbeiten.
Weiß jemand wie das gehen könnte?
Danke
Klaus
habe das Sample (Feed) ausprobiert und auch meine Programme dahingehend abgeändert, da es sehr gut funktioniert.
Jetzt wollen aber einige Anwender das erstellte Dokument nicht sofort drucken, sondern die Möglichkeit haben diesen zu bearbeiten.
Weiß jemand wie das gehen könnte?
Danke
Klaus
- Martin Altmann
- Foren-Administrator
- Beiträge: 16517
- Registriert: Fr, 23. Sep 2005 4:58
- Wohnort: Berlin
- Hat sich bedankt: 111 Mal
- Danksagung erhalten: 48 Mal
- Kontaktdaten:
Hallo Klaus,
wirf doch mal einen Blick auf das XbpRtf()-Control bzw. die -Klasse!
Viele Grüße,
Martin
wirf doch mal einen Blick auf das XbpRtf()-Control bzw. die -Klasse!
Viele Grüße,
Martin
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/
Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
- Tom
- Der Entwickler von "Deep Thought"
- Beiträge: 9367
- Registriert: Do, 22. Sep 2005 23:11
- Wohnort: Berlin
- Hat sich bedankt: 102 Mal
- Danksagung erhalten: 361 Mal
- Kontaktdaten:
Hallo, Klaus.
Nimm einfach
aus dem Beispiel heraus und häng den Code zur Zerstörung der Objekte in den Quit-Callback-Slot des Controls. Hier solltest Du dann auch auslösen, daß Dein Programm seine Ausführung fortsetzt, also zum Beispiel eine Variable setzen, auf deren Zustandsänderung gewartet wird.
Nimm einfach
Code: Alles auswählen
oDoc:close()
oWord:Quit()
Herzlich,
Tom
Tom
- Tom
- Der Entwickler von "Deep Thought"
- Beiträge: 9367
- Registriert: Do, 22. Sep 2005 23:11
- Wohnort: Berlin
- Hat sich bedankt: 102 Mal
- Danksagung erhalten: 361 Mal
- Kontaktdaten:
Noch eine Ergänzung: Die ActiveX-Komponenten der Office-Programme sind sehr träge. Wenn man Excel-Daten bearbeiten will, sollte man überlegen, alternativ per ODBC oder SQLexpress direkt in den Tabellen zu arbeiten, und als Alternative zu Word bietet sich das (allerdings kostenpflichtige) TX TextControl (http://www.textcontrol.com) an, das das DOC-Format beherrscht und zum Beispiel bei gesteuerten Funktionen wie Suchen/Ersetzen dramatisch schneller ist.
Herzlich,
Tom
Tom
- Rudolf
- Programmier-Gott
- Beiträge: 1418
- Registriert: Mo, 02. Jan 2006 23:03
- Wohnort: Salzburg/Österreich
- Kontaktdaten:
Hallo,
weiss jemand was textcontrol kostet ?
kann jemand ein xBase++ Beispiel für die Einbindung im Source zur Verfügung stellen ?
Grüsse
Rudolf
weiss jemand was textcontrol kostet ?
kann jemand ein xBase++ Beispiel für die Einbindung im Source zur Verfügung stellen ?
Grüsse
Rudolf
Rudolf Reinthaler
http://www.formcommander.net
http://www.formcommander.net
- Rudolf
- Programmier-Gott
- Beiträge: 1418
- Registriert: Mo, 02. Jan 2006 23:03
- Wohnort: Salzburg/Österreich
- Kontaktdaten:
Hallo Tom,
vielen Dank für die Info. Ist mir aber leider zu teuer, werde mal nach was günstigerem suchen. Schade, denn sieht sehr leistungsfähig aus.
lg
Rudolf
vielen Dank für die Info. Ist mir aber leider zu teuer, werde mal nach was günstigerem suchen. Schade, denn sieht sehr leistungsfähig aus.
lg
Rudolf
Rudolf Reinthaler
http://www.formcommander.net
http://www.formcommander.net
- Tom
- Der Entwickler von "Deep Thought"
- Beiträge: 9367
- Registriert: Do, 22. Sep 2005 23:11
- Wohnort: Berlin
- Hat sich bedankt: 102 Mal
- Danksagung erhalten: 361 Mal
- Kontaktdaten:
Hallo, Klaus.
Ich habe das FEED.PRG-Sample ein bißchen manipuliert. In diesem Zusammenhang weise ich auf die Doku zu "CreateObject" und alldort Beispiel zwei hin. Da man den Quit-Codeblock von ActiveXObjekten überladen kann, ist folgendes möglich (geänderter Code in rot):
Ich habe das FEED.PRG-Sample ein bißchen manipuliert. In diesem Zusammenhang weise ich auf die Doku zu "CreateObject" und alldort Beispiel zwei hin. Da man den Quit-Codeblock von ActiveXObjekten überladen kann, ist folgendes möglich (geänderter Code in rot):
Code: Alles auswählen
FUNCTION WordFillDocument(cFile,aData,cSaveAs,lPrint)
LOCAL oWord,oBM,oDoc
// Erzeugen einer ActiveX-Komponente
oWord := CreateObject("Word.Application")
IF Empty( oWord )
MsgBox( "Microsoft Word ist nicht installiert" )
ENDIF
[color=red]oWord := oWord:dynamicCast(ActiveXObject())
oWord:Quit := {||lWordFinished := .T.}
[/color]
oWord:visible := .T.
[color=red]lWordFinished := .F.[/color]
// Oeffnen eines Word-Dokuments und Zugriff auf
// eine Sammlung von Lesezeichen
oWord:documents:open( cFile )
oDoc := oWord:ActiveDocument
oBM := oDoc:Bookmarks
// Ersetzen des Lesezeichens durch einen neuen
// Wert
ReplaceBookmark(oBM , "COMPANY" , aData[1] )
ReplaceBookmark(oBM , "TO" , aData[2] )
ReplaceBookmark(oBM , "FAX" , aData[3] )
ReplaceBookmark(oBM , "FROM" , aData[4] )
ReplaceBookmark(oBM , "TOTAL_PAGES" , "1" )
ReplaceBookmark(oBM , "CARBON_COPY" , "" )
ReplaceBookmark(oBM , "SUBJECT" , aData[5] )
ReplaceBookmark(oBM , "SALUTATION" , aData[6] )
ReplaceBookmark(oBM , "TEXT" , aData[7] )
ReplaceBookmark(oBM , "DATE" , DToC(Date()) )
// Speichern des Ergebnisses
IF(ValType(cSaveAs)=="C")
oDoc:saveas(cSaveAs)
ENDIF
// Optionales Ausgeben auf dem Standarddrucker
IF(ValType(lPrint)=="L" .AND. lPrint)
oDoc:PrintOut()
ENDIF
[color=red] Do WHILE !lWordFinished
// Just wait
EndDo
oWord:Destroy()
MsgBox('Word ist beendet')
[/color]
RETURN NIL
Herzlich,
Tom
Tom
- Koverhage
- Der Entwickler von "Deep Thought"
- Beiträge: 2470
- Registriert: Fr, 23. Dez 2005 8:00
- Wohnort: Aalen
- Hat sich bedankt: 102 Mal
- Danksagung erhalten: 3 Mal
- Kontaktdaten:
Hallo,
ich kann jetzt ein bestehendes Dokument laden, ersetzen von Inhalten, editieren, etc.
Aber wie kann ich Word aufrufen um ein neues Dokument zu erstellen ?
und wie oder wo kann ich erfahren welche Funktionen es gibt ?
z.B ein vorhandenes Dokument kann ich mit open bearbeiten
oWord:documents:open( cFile )
Klaus
ich kann jetzt ein bestehendes Dokument laden, ersetzen von Inhalten, editieren, etc.
Aber wie kann ich Word aufrufen um ein neues Dokument zu erstellen ?
und wie oder wo kann ich erfahren welche Funktionen es gibt ?
z.B ein vorhandenes Dokument kann ich mit open bearbeiten
oWord:documents:open( cFile )
Klaus
- Martin Altmann
- Foren-Administrator
- Beiträge: 16517
- Registriert: Fr, 23. Sep 2005 4:58
- Wohnort: Berlin
- Hat sich bedankt: 111 Mal
- Danksagung erhalten: 48 Mal
- Kontaktdaten:
Hallo Klaus,
gerade bei den Officeprogrammen hat sich der Makrorekorder bewährt.
Starte Word, starte den Makrorekorder, mach', was Du später mit Xbase++ machen willst und beende dann den Makrorekorder.
Schau Dir den aufgezeichneten Makro an, koppiere den Code in Deine Xbase++-Sourcen und Du brauchst ihn nur noch geringfügig ändern.
Viele Grüße,
Martin
gerade bei den Officeprogrammen hat sich der Makrorekorder bewährt.
Starte Word, starte den Makrorekorder, mach', was Du später mit Xbase++ machen willst und beende dann den Makrorekorder.
Schau Dir den aufgezeichneten Makro an, koppiere den Code in Deine Xbase++-Sourcen und Du brauchst ihn nur noch geringfügig ändern.
Viele Grüße,
Martin
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/
Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
- brandelh
- Foren-Moderator
- Beiträge: 15697
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Hi,
bei der Umstellung von mehreren tausend AMIPRO Dokumenten auf Word habe ich mit dem Marcorecorder von Wordpro (ist so ähnlich wie VBA von Word) ein Macro aufgezeichnet, welches ein per Komandozeile übergebenes Dokument öffnet und sofort im DOC Format abspeichert.
Dieses Macro habe ich dann im VBA Editor angepaßt und im Programm als Autostart aktiviert.
Mit einem Xbase++ Steuerprogramm habe ich alle Verzeichnisse nach SAM Dateien abgegrast und diese in gleicher Struktur wieder unter DOC erzeugt.
Das Programm war ein echter Konvertierungshammer, kein Konverterprogramm konnte von der Qualität und Geschwindigkeit mithalten.
Der VBA Code zeigt einem die Klassen und Methoden die man auch für ActiveX Fernsteuerung braucht, auch wenn ich diese nicht genutzt habe.
bei der Umstellung von mehreren tausend AMIPRO Dokumenten auf Word habe ich mit dem Marcorecorder von Wordpro (ist so ähnlich wie VBA von Word) ein Macro aufgezeichnet, welches ein per Komandozeile übergebenes Dokument öffnet und sofort im DOC Format abspeichert.
Dieses Macro habe ich dann im VBA Editor angepaßt und im Programm als Autostart aktiviert.
Mit einem Xbase++ Steuerprogramm habe ich alle Verzeichnisse nach SAM Dateien abgegrast und diese in gleicher Struktur wieder unter DOC erzeugt.
Das Programm war ein echter Konvertierungshammer, kein Konverterprogramm konnte von der Qualität und Geschwindigkeit mithalten.
Der VBA Code zeigt einem die Klassen und Methoden die man auch für ActiveX Fernsteuerung braucht, auch wenn ich diese nicht genutzt habe.
Gruß
Hubert
Hubert
- Koverhage
- Der Entwickler von "Deep Thought"
- Beiträge: 2470
- Registriert: Fr, 23. Dez 2005 8:00
- Wohnort: Aalen
- Hat sich bedankt: 102 Mal
- Danksagung erhalten: 3 Mal
- Kontaktdaten:
Habe jetzt rausgefunden, was für eine Function das ist.
Habe allerdings ein anderes Problem:
Nach dem Aufruf von Word, hat das Programm eine CPU Belastung von 100%. Word und die Anwendung reagiert nicht mehr. Dies liegt an dem Do WHILE !lWordFinished ( Code nachstehend)
Der Anwender soll doch nur ein neues Word Dokument anlegen können.
Hat das schon jemand gelöst bzw. wie kann ich das lösen?
Klaus
//////////////////////////////////////////////////////////////////////
// Oeffnet ein bestehendes oder leeres MS Word-Dokument
//////////////////////////////////////////////////////////////////////
FUNCTION WordEditDocument(cFile,cSaveAs,laendern)
LOCAL oWord,oBM,oDoc
local mess1 := LGTrans(('Cdb')->sprache,'0051001','Microsoft Word ist nicht installiert')
local lWordFinished := .f.
local i := 0
#if XPPVER > 01890000
default laendern to .f.
i := Rat( ".",cFile)
if i < 1
cFile := cFile + ".doc"
endif
IF(ValType(cSaveAs)=="C")
i := Rat( ".",cSaveAs)
if i < 1
cSaveAs := cSaveAs + ".doc"
endif
ENDIF
// Erzeugen einer ActiveX-Komponente
oWord := CreateObject("Word.Application")
IF Empty( oWord )
MsgBox( mess1 )
ENDIF
oWord := oWord:dynamicCast(ActiveXObject())
oWord:Quit := {||lWordFinished := .T.}
oWord:visible := .T.
lWordFinished := .F.
// Oeffnen eines Word-Dokuments und Zugriff auf
// eine Sammlung von Lesezeichen
if laendern
oWord:documents:open( cFile )
else
oWord:documents:add( )
endif
oDoc := oWord:ActiveDocument
// Speichern des Ergebnisses
IF(ValType(cSaveAs)=="C")
oDoc:saveas(cSaveAs)
ENDIF
Do WHILE !lWordFinished
// Just wait
EndDo
oWord:destroy()
#endif
RETURN NIL
Habe allerdings ein anderes Problem:
Nach dem Aufruf von Word, hat das Programm eine CPU Belastung von 100%. Word und die Anwendung reagiert nicht mehr. Dies liegt an dem Do WHILE !lWordFinished ( Code nachstehend)
Der Anwender soll doch nur ein neues Word Dokument anlegen können.
Hat das schon jemand gelöst bzw. wie kann ich das lösen?
Klaus
//////////////////////////////////////////////////////////////////////
// Oeffnet ein bestehendes oder leeres MS Word-Dokument
//////////////////////////////////////////////////////////////////////
FUNCTION WordEditDocument(cFile,cSaveAs,laendern)
LOCAL oWord,oBM,oDoc
local mess1 := LGTrans(('Cdb')->sprache,'0051001','Microsoft Word ist nicht installiert')
local lWordFinished := .f.
local i := 0
#if XPPVER > 01890000
default laendern to .f.
i := Rat( ".",cFile)
if i < 1
cFile := cFile + ".doc"
endif
IF(ValType(cSaveAs)=="C")
i := Rat( ".",cSaveAs)
if i < 1
cSaveAs := cSaveAs + ".doc"
endif
ENDIF
// Erzeugen einer ActiveX-Komponente
oWord := CreateObject("Word.Application")
IF Empty( oWord )
MsgBox( mess1 )
ENDIF
oWord := oWord:dynamicCast(ActiveXObject())
oWord:Quit := {||lWordFinished := .T.}
oWord:visible := .T.
lWordFinished := .F.
// Oeffnen eines Word-Dokuments und Zugriff auf
// eine Sammlung von Lesezeichen
if laendern
oWord:documents:open( cFile )
else
oWord:documents:add( )
endif
oDoc := oWord:ActiveDocument
// Speichern des Ergebnisses
IF(ValType(cSaveAs)=="C")
oDoc:saveas(cSaveAs)
ENDIF
Do WHILE !lWordFinished
// Just wait
EndDo
oWord:destroy()
#endif
RETURN NIL
- Martin Altmann
- Foren-Administrator
- Beiträge: 16517
- Registriert: Fr, 23. Sep 2005 4:58
- Wohnort: Berlin
- Hat sich bedankt: 111 Mal
- Danksagung erhalten: 48 Mal
- Kontaktdaten:
Klaus,
Du musst dem System Zeit geben, andere Events abzuarbeiten!
In Deiner Do While.... kannst Du ein inkey(0.01) einbauen - dann sieht das bestimmt besser aus.
Viele Grüße,
Martin
Du musst dem System Zeit geben, andere Events abzuarbeiten!
In Deiner Do While.... kannst Du ein inkey(0.01) einbauen - dann sieht das bestimmt besser aus.
Viele Grüße,
Martin
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/
Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
- brandelh
- Foren-Moderator
- Beiträge: 15697
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Hi Klaus,
Rein in die Schleife, raus aus der Schleife ...
Du könntest mit dem dafür vorgesehen Befehl dein wartentes Programm komplett auf Eis schicken:
da der Aufruf aber nicht asyncron ist, würde dein Programm jetzt nicht mehr auf Eingaben etc. reagieren. Daher wäre es am Besten, wenn du hier eine Eventloop aufbaust - ich habe dafür meinen Haupteventloop in eine Funktion gepackt, es ginge natürlich auch kürzer:
er wartet hier nicht, sondern er schuftet !Koverhage hat geschrieben: Do WHILE !lWordFinished
// Just wait
EndDo
Rein in die Schleife, raus aus der Schleife ...
Du könntest mit dem dafür vorgesehen Befehl dein wartentes Programm komplett auf Eis schicken:
Code: Alles auswählen
Do WHILE !lWordFinished
SLEEP(1) // Just wait
EndDo
Code: Alles auswählen
in Main-Programm statt bisherig Eventloop (nur auf Wunsch)
...
DoEventLoop() // bis Programmende
...
in dem Word-Teil
Do WHILE !lWordFinished
DoEventLoop(1) // Just wait 1 Second
EndDo
*-----------------------------------------------------------------------------
FUNCTION DoEventLoop(nSeconds) // IN Schleifen Events verarbeiten !
local nBisSeconds, nEvent, mp1, mp2, oXbp
DEFAULT nSeconds to 0 // Standard ist endlose Ausführung
nBisSeconds := seconds() + nSeconds
DO WHILE .T.
nEvent := AppEvent( @mp1, @mp2, @oXbp, nSeconds)
do case
case nEvent = xbe_None
* nichts tun ist hier Standard
case nEvent = xbeP_Keyboard .and. mp1 == xbeK_F1
* xbeP_HelpRequest erscheinen f
Zuletzt geändert von brandelh am Fr, 13. Okt 2006 10:58, insgesamt 1-mal geändert.
Gruß
Hubert
Hubert
- Martin Altmann
- Foren-Administrator
- Beiträge: 16517
- Registriert: Fr, 23. Sep 2005 4:58
- Wohnort: Berlin
- Hat sich bedankt: 111 Mal
- Danksagung erhalten: 48 Mal
- Kontaktdaten:
Klaus,
prima.
Viele Grüße,
Martin
prima.
Ist in dem Fall (m.E.) unkritisch, da Du es ja nur nimmst, um dem Prozessor "Luft" zu geben.Koverhage hat geschrieben:Habe aber entsprechend der Dokumentation AppEvent( @mp1, @mp2, , 1) verwendet, da Inkey nicht mehr benutzt werden sollte.
Viele Grüße,
Martin
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/
Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
- brandelh
- Foren-Moderator
- Beiträge: 15697
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
war ich wieder zu langsam beim SchreibenKoverhage hat geschrieben:jetzt funktioniert es einwandfrei. Habe aber entsprechend der Dokumentation AppEvent( @mp1, @mp2, , 1) verwendet
Bedenke aber, wenn du nur ein AppEvent in die Do While Schleife packst, verlierst du die Events, da ja kein Sprung in die Eventbehandlung erfolgt !
Das muß jetzt in deinem Falls nicht stören ...
PS: das trifft bei Inkey() auch zu, da könnten es aber nur Tastendrücke sein, die ja in dem Fall eh nicht gewünscht sind.
Gruß
Hubert
Hubert
- brandelh
- Foren-Moderator
- Beiträge: 15697
- Registriert: Mo, 23. Jan 2006 20:54
- Wohnort: Germersheim
- Hat sich bedankt: 66 Mal
- Danksagung erhalten: 33 Mal
- Kontaktdaten:
Die Events für Word dürften davon nicht betroffen sein,Koverhage hat geschrieben:Hubert,
das stört mich in diesem Fall wirklich nicht, mir ist es völlig egal
was der User in sein Word Dokument schreibt
ich meinte die Events an dein Programm !
Ob es stört oder nicht, hängt natürlich sehr vom Einzelfall ab.
Gruß
Hubert
Hubert