Activex und Word

Nutzung, Komponenten, .NET

Moderator: Moderatoren

Antworten
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
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

Beitrag von Koverhage »

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
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Klaus,
wirf doch mal einen Blick auf das XbpRtf()-Control bzw. die -Klasse!

Viele Grüße,
Martin
:grommit:
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.
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
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:

Beitrag von Koverhage »

XbpRTF mit Doc Dateien?
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:

Beitrag von Tom »

Hallo, Klaus.

Nimm einfach

Code: Alles auswählen

  oDoc:close()
  oWord:Quit()
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.
Herzlich,
Tom
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:

Beitrag von Tom »

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
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
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:

Beitrag von Koverhage »

Tom, und wie mache ich das?
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Beitrag von Rudolf »

Hallo,
weiss jemand was textcontrol kostet ?
kann jemand ein xBase++ Beispiel für die Einbindung im Source zur Verfügung stellen ?
Grüsse
Rudolf
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:

Beitrag von Tom »

Hallo, Rudolf.

TX kostet 949 Dollar. Ein Beispiel für die Einbindung kann ich Dir zur Verfügung stellen.

@Klaus: Ich poste nachher ein Beispiel.
Herzlich,
Tom
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Beitrag von Rudolf »

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
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:

Beitrag von Tom »

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):

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
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
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:

Beitrag von Koverhage »

Tom,

super und danke, werde das ausprobieren.

Klaus
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
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:

Beitrag von Koverhage »

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
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

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
:grommit:
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.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

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.
Gruß
Hubert
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
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:

Beitrag von Koverhage »

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
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

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
:grommit:
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.
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
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:

Beitrag von Koverhage »

Martin,

jetzt funktioniert es einwandfrei. Habe aber entsprechend der Dokumentation
AppEvent( @mp1, @mp2, , 1) verwendet, da Inkey nicht mehr benutzt werden sollte.

Danke.

Klaus

Jetzt kann ich das Gleiche ja auch mt Excel wagen ;-)
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hi Klaus,
Koverhage hat geschrieben: Do WHILE !lWordFinished
// Just wait
EndDo
er wartet hier nicht, sondern er schuftet !
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
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:

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
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16502
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Klaus,
prima.
Koverhage hat geschrieben:Habe aber entsprechend der Dokumentation AppEvent( @mp1, @mp2, , 1) verwendet, da Inkey nicht mehr benutzt werden sollte.
Ist in dem Fall (m.E.) unkritisch, da Du es ja nur nimmst, um dem Prozessor "Luft" zu geben.

Viele Grüße,
Martin
:grommit:
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.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Koverhage hat geschrieben:jetzt funktioniert es einwandfrei. Habe aber entsprechend der Dokumentation AppEvent( @mp1, @mp2, , 1) verwendet
war ich wieder zu langsam beim Schreiben ;)

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
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
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:

Beitrag von Koverhage »

Hubert,

das stört mich in diesem Fall wirklich nicht, mir ist es völlig egal
was der User in sein Word Dokument schreibt ;-)
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

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 ;-)
Die Events für Word dürften davon nicht betroffen sein,
ich meinte die Events an dein Programm !

Ob es stört oder nicht, hängt natürlich sehr vom Einzelfall ab.
Gruß
Hubert
olaf870
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 128
Registriert: Mi, 26. Okt 2005 18:41
Wohnort: Berlin
Kontaktdaten:

Beitrag von olaf870 »

Hallo,

hat jemand schon rausgefunden, wie man den Appfocus auf das Worddoc setzen kann? Ich meine so daß der Anwender nicht erst immer das DOC anklicken muß, bevor anfangen kann zu schreiben.

Gruß
Olaf870
Antworten