Page 1 of 1

ActiveX open word document

Posted: Thu Feb 01, 2018 11:26 am
by Victorio
Hi,
I work on automatic generate word documents .
I have one document as "template" where are bookmarks.
And then change this bookmarks to my own values and save document to outdocument.

But I want after it open this document also with ActiveX, because with DC_Spawnurl this is some tome to open it.

How can realize waiting to close document, when I show it in word ?

here sample :
lWordFinished := .f.
oWord := CreateObject("Word.Application")
oWord := oWord:dynamicCast(ActiveXObject())
oWord:Quit := {||lWordFinished := .T.}
oWord:visible := .T. // zobrazuje word dokument počas spracovania
lWordFinished := .f.
oWord:documents:open( outdocument )

???

oDoc:close()
oWord:Quit()
oWord:destroy()

when I try to ??? place put for example this :
do while lWordFinished=.T.
sleep(100)
enddo

application frozen, that I mean, this is not good way.

without anything document open, but in a monent close.

many thanks for any advice

Re: ActiveX open word document

Posted: Thu Feb 01, 2018 11:57 am
by rdonnay
I think you need this:

DO WHILE .NOT. lWordFinished
Sleep(100)
ENDDO

Re: ActiveX open word document

Posted: Thu Feb 01, 2018 2:17 pm
by Auge_Ohr
Victorio wrote:Hi,
But I want after it open this document also with ActiveX, because with DC_Spawnurl this is some tome to open it.

How can realize waiting to close document, when I show it in word ?
guess you have 2 Xbase++ Apps and you wait that 2nd App "close" ... what do you need :?:
you need to "communicate" between both Apps ... that is what ActiveX can do :!:

now your Code use only "one Way" : from Xbase++ sending to ActiveX
but you need to receive Events from ActiveX if you want to react on it when User :!: "close" Document.



next are Threads ... :whistle:
ActiveX use its own (GUI) Thread -> not Xbase++ "Event" Loop.
i use PostAppEvent() with UserDef Events to "transfer" it into Xbase++ "Event" Loop.


so Code like this will NEVER work ...

Code: Select all

lWordFinished := .f.
DO WHILE
you have no Control, while you did not receive Events from ActiveX.

remember : Windows does not force any Action ... it react on User and send Events

---

here a Sample how i use Outlook Editor with Xbase++

Code: Select all

//
// activeX Event
//
#define EvClose                 "Close"
#define EvWrite                 "Write"
#define EvPropertyChange        "PropertyChange"
#define EvItemChange            "ItemChange"
#define EvDeactivate            "Deactivate"
#define EvQuit                  "Quit"

      ::oOutlook := ::oOutlook:dynamicCast( ActiveXObject() )
      xVar := ::oOutlook:isEventPublished( EvQuit )
      IF xVar <> NIL
         lSuccess := ::oOutlook:SubscribeEvent( xVar, { | a, b, c, d | IF( NIL = ::oMainApp, NIL, PostAppEvent( xbeE_TerminRefresh, dDate,, ::oMainApp ) ), PostAppEvent( xbeP_Activate,,, ::ButtonOK ) } )
         IF .NOT. lSuccess
            * LOGME("::oOutlook EvQuit FAIL")
         ENDIF
      ENDIF

      ::oItem := ::oItem:dynamicCast( ActiveXObject() )
      xVar := ::oItem:isEventPublished( EvWrite )
      IF xVar <> NIL
         lSuccess := ::oItem:SubscribeEvent( xVar, { | a, b, c, d | PostAppEvent( xbeE_TerminWrite,,, Self ) } )
         IF .NOT. lSuccess
            * LOGME("::oItem EvWrite FAIL")
         ENDIF
      ENDIF

      xVar := ::oItem:isEventPublished( EvClose )
      IF xVar <> NIL
         lSuccess := ::oItem:SubscribeEvent( xVar, { | a, b, c, d | IF( NIL = ::oMainApp, NIL, PostAppEvent( xbeE_TerminRefresh, dDate,, ::oMainApp ) ), PostAppEvent( xbeP_Activate,,, ::ButtonOK ) } )
         IF .NOT. lSuccess
            * LOGME("::oItem EvClose FAIL")
         ENDIF
      ENDIF

      // this show Editor using its own Thread        
      ::oItem:Display()

      // more Xbase++ Code   
---
Word2003_Events.jpg
Word2003_Events.jpg (385.01 KiB) Viewed 15785 times

Re: ActiveX open word document

Posted: Fri Feb 02, 2018 3:04 am
by Victorio
Jimmy: thansk for information, I must study it, because it is a little complicated for me :oops:

I do not have two Xbase apps ,this is all in one , only word is called from it.

I do not understand, but now this works as I want also without any wait loop :

* Open template document and replace bookmarks with my values
**************************************************************
oWord := oWord:dynamicCast(ActiveXObject())
oWord:Quit := {||lWordFinished := .T.}
* oWord:visible := .T. // zobrazuje word dokument počas spracovania
oWord:visible := .F. // nezobrazuje word dokument počas spracovania
lWordFinished := .f.

oWord:documents:open( cFile )
oDoc := oWord:ActiveDocument
oBM := oDoc:Bookmarks

// Replace the Bookmark with a new value
ReplaceBookmark(oBM , "CISLO_ZMLUVY" , aData[1] )
ReplaceBookmark(oBM , "NAJOMCA" , aData[2] )
ReplaceBookmark(oBM , "PRENAJIMATEL" , aData[3] )

IF(ValType(cSaveAs)=="C")
oDoc:saveas(cSaveAs)
ENDIF

// Close the document and destroy the ActiveX
// object
if nBearb # 1
//oDoc:sendfax()
oDoc:close()
oWord:Quit()
endif

sleep(50) // tu časové oneskorenie asi aby stihol zatvoriť dokument

oWord:destroy()

* And now open saved document with new values
**********************************************
lWordFinished := .f.
oWord := CreateObject("Word.Application")
oWord := oWord:dynamicCast(ActiveXObject())
oWord:Quit := {||lWordFinished := .T.}
oWord:visible := .T. // zobrazuje word dokument počas spracovania
lWordFinished := .f.
oWord:documents:open( docsuborout )

*oDoc:close()
*oWord:Quit()

oWord:destroy()


So I am not sure, what is :dynamicCast , and other things but now after changes document this saved, and open new document and word stay open with it. This is what I want.
Only time to open document need some time, about 10 seconds

Re: ActiveX open word document

Posted: Fri Feb 02, 2018 11:11 am
by Victorio
Now this works as I want,
open teplate document,
change bookmarks to my values,
save to new document as DOC and PDF
open new document and wait to close it in word by user.

here this is modal, that's what I need to prevent for some unsuported situations.

Here source ispired by some posts from alaska newsgroup...:
*****************************************************************************
static FUNCTION WordFillDocument(cFile,aData,cSaveAs,cSaveAsPdf,nBearb,acnz1) // funkcia, ktorá vymení bookmarks/záložky za zvolený text
*****************************************************************************
LOCAL oWord,oBM,oDoc,lWordFinished := .f.,x
LOCAL cCakaj

oWord := CreateObject("Word.Application")
IF Empty( oWord )
MsgBox( "Microsoft Word nie je nainštalovaný, dokument sa nedá vytvoriť !" )
return .f.
ENDIF

oWord := oWord:dynamicCast(ActiveXObject())
oWord:Quit := {||lWordFinished := .T.}
*oWord:visible := .T. // zobrazuje word dokument počas spracovania
oWord:visible := .F. // nezobrazuje word dokument počas spracovania
lWordFinished := .f.

oWord:documents:open( cFile, .F., .T. ) // toto som upravil podľa fóra news alaska
oDoc := oWord:ActiveDocument
oBM := oDoc:Bookmarks

* nahradenie bookmarkov hodnotami z poľa aData, resp. priamo zvolenými hodnotami
// Replace the Bookmark with a new value
ReplaceBookmark(oBM , "CISLO_ZMLUVY" , aData[1] )
ReplaceBookmark(oBM , "NAJOMCA" , aData[2] )
ReplaceBookmark(oBM , "PRENAJIMATEL" , aData[3] )

IF(ValType(cSaveAs)=="C")
oDoc:saveas(cSaveAs)
ENDIF

lulozitajpdf:=.T.
if lulozitajpdf==.T.
oDoc:ExportAsFixedFormat( cSaveasPdf, 17 )
cRet := cSaveasPdf
endif

oWord:visible := .T. // nezobrazuje word dokument počas spracovania
oWord:Activate()

* here wait ... to close word
Do While !lWordFinished
nEvent:=AppEvent( @mp1, @mp2, 1 )
Enddo

oDoc:destroy()
oWord:destroy()

RETURN .t.

***********************************************
static FUNCTION ReplaceBookmark(oBM,cBM,cValue)
***********************************************
LOCAL lRet := oBM:Exists(cBM) // zistí, či bookmark existuje
LOCAL oF

IF(lRet)
oF := oBM:Item(cBM) // načíta do premennej objekt pôvodnú hodnotu
oF:Range:Text := cValue // nahradí novým textom
oF:Destroy() // zatvorí objekt
ENDIF

RETURN(lRet)

Re: ActiveX open word document

Posted: Fri Feb 02, 2018 2:08 pm
by Auge_Ohr
Victorio wrote:Now this works as I want,
open teplate document,
change bookmarks to my values,
save to new document as DOC and PDF
open new document and wait to close it in word by user.
ok ... you open a new Session ...
Victorio wrote:

Code: Select all

* here wait ... to close word
Do While !lWordFinished
	nEvent:=AppEvent( @mp1, @mp2, 1 )
Enddo
hm ... :eusa-think:
3th Parameter of AppEvent() is a Object (@oXbp) not a Number :naughty:

Re: ActiveX open word document

Posted: Sat Feb 03, 2018 5:58 am
by Victorio
... nEvent:=AppEvent( @mp1, @mp2, 1 ) ...

yes, I saw this in some example here and it was weird, but for examine I put it also to my program :

https://www.xbaseforum.de/viewtopic.php ... C+1#p92536

but rather I use AppEvent( @mp1, @mp2, @oXbp )

Re: ActiveX open word document

Posted: Sat Feb 03, 2018 12:45 pm
by Auge_Ohr
Victorio wrote:... nEvent:=AppEvent( @mp1, @mp2, 1 ) ...
yes, I saw this in some example here and it was weird, but for examine I put it also to my program :
https://www.xbaseforum.de/viewtopic.php ... C+1#p92536
have a look again

Code: Select all

// Just wait
nEvent := AppEvent( @mp1, @mp2, , 1)
also Koverhage use Event "BeforeClose"

Code: Select all

oBook:BeforeClose := {||lExcelFinished := .T.}
lExcelFinished := .F.