Excel sans attendre la fin [Résolu]

cs_Ptinico 4 Messages postés vendredi 20 décembre 2002Date d'inscription 31 mai 2007 Dernière intervention - 3 mai 2007 à 21:03 - Dernière réponse : cs_Ptinico 4 Messages postés vendredi 20 décembre 2002Date d'inscription 31 mai 2007 Dernière intervention
- 4 mai 2007 à 21:40
Salut,
Question toute bête :
- J'ai un fichier Excel ouvert contenant un macro déclenchée par un "Worksheet_SelectionChange"
- Depuis Delphi, je me connecte au fichier Excel ouvert (par OLE), je remplis la case qui va bien, puis je selectionne une autre case. Ca force donc le "Worksheet_SelectionChange" de Excel.
Par contre, je veux conserver la main sur mon application Delphi, sans attendre la fin de l'éxecution de la macro Excel....

Qq'un a une idée ? J'ai essayé les thread, mais le "GetActiveOleObject" ne semble pas fonctionner dans un thread !!
Merci d'avance.
Afficher la suite 

6 réponses

Répondre au sujet
florenth 1105 Messages postés dimanche 1 août 2004Date d'inscription 17 août 2008 Dernière intervention - 4 mai 2007 à 13:33
+3
Utile
Salut à tous

@Cari: il est possible d'utiliser OLE dans un thread. Il faut juste faire attention à plusieurs trucs:
- Si tu utilises le type TThread de Delphi, il faut absolument tout faire dans le méthode Execute() car c'est la seule qui est réellement threadée (donc, tu ne peux pas initialiser OLE dans le constructeur et l'utiliser dans Execute()).

- Ensuite, il ne faut pas oublier d'initialiser OLE et de le libérer DANS ce même thread (Delphi le fait par défaut dans le thread principal mais pas dans les autres)

- Donc, appel de CoInitialize(nil) au début et CoUnInitialize() à la fin.

- Donc, bien sûr, Variants, ActiveX et ComObj dans les uses.

- Et ensuite, tout fonctionne ! Faire gaffe à ne pas utiliser la même instance dans un autre thread, ça plante sinon ...

- Préférer CreateOLEObject('Excel.Application') plutôt que GetActiveOLEObject().

++
Flo
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de florenth
florenth 1105 Messages postés dimanche 1 août 2004Date d'inscription 17 août 2008 Dernière intervention - 4 mai 2007 à 19:50
+3
Utile
Oui ça a l'air correct car j'ai du mal à lire à cause de la mise en page ...
Par contre, pourquoi faire cela :

<hr size="2" width="100%" />// --- Connexion à Excel ---
thExcel1:=GetActiveOleObject('Excel.Application');
thEXCEL:=Unassigned;
thExcel1:=Unassigned;
thEXCEL:=GetActiveOleObject('Excel.Application');

<hr size="2" width="100%" />
Tu t'embettes pour rien. autant directement faire thEXCEL:=GetActiveOleObject('Excel.Application');sans le reste, non !
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de florenth
Caribensila 2671 Messages postés jeudi 15 janvier 2004Date d'inscription 18 janvier 2018 Dernière intervention - 3 mai 2007 à 22:56
0
Utile
Salut!
Je crois que tu es mal barré, là.


L'idée de OLE est qu'une application en contienne une autre.
C'est une technique qui permet d'inclure dans ton application un document d'une autre application.


Mais, à ma connaissance, y'a pas de

threading possible.




Ton idée d'utilser un

thread secondaire me semble prouver que
ton problème, si j'ai bien compris, c'est plutôt un problème de multitâche...



Moi, perso, j'abandonnerais l'idée d'OLE et je lancerais les deux applications séparément. Ce qui revient à dire 2 processus ou 2 threads (Problème du multitâche résolu).

Ensuite, il suffira de les faire communiquer.

Et y'a plein de techniques pour ça dont tu trouveras les exemples ici.
Commenter la réponse de Caribensila
jelume 122 Messages postés mardi 3 avril 2007Date d'inscription 15 novembre 2007 Dernière intervention - 4 mai 2007 à 12:39
0
Utile
Bonjour

Ne serait-il pas possible d'envoyer une message à Excel par un sendmessage par exemple ? Juste pour le forcer à un refresh ?

J-L
Commenter la réponse de jelume
cs_Ptinico 4 Messages postés vendredi 20 décembre 2002Date d'inscription 31 mai 2007 Dernière intervention - 4 mai 2007 à 19:25
0
Utile
Flo, t'es un chef. Merci vraiment !
J'y étais presque, manquait que le CoInitialize et le CoUnInitialize. J'avais déjà remarqué que dans les DLL les librairies COM n'étaient pas forcément initialisées correctement.

Voilà mon unité du thread. Pour info, même le GetActiveOleObject fonctionne !


unit XlsSendWeightThreadUnit;


interface


uses


Classes, Variants, ComObj, IniFiles, SysUtils, ActiveX;


type


TXlsSendWeight = class(TThread)


private


{ Déclarations privées }


thMessage, thCfgFile : string;


thNewWeight : double;


procedure EcritMessage;


protected


procedure Execute; override;


public


constructor Create(dWeight : double; sCfgFile : string); overload;


end;


implementation


uses MainForm;


constructor TXlsSendWeight.Create(dWeight : double; sCfgFile : string);


begin


inherited Create(true);


// Initialisation des variables de poids et fichier de config


thCfgFile:=sCfgFile;


thNewWeight:=dWeight;


FreeOnTerminate := True;


end;


procedure TXlsSendWeight.EcritMessage;


begin


frmMain.ReProgramme.Lines.Add(thMessage);


end;


procedure TXlsSendWeight.Execute;


Var thEXCEL, thExcel1 : variant;


thWorkBook, thSheet : variant;


thFicIni : TIniFile;


i, index, iCellRow, iCellCol : integer;


s, sSheetName : string;


begin


// Initialisation libraire COM => manuelle car dans thread


CoInitialize(nil);


try


try


// --- Connexion à Excel ---


thExcel1:=GetActiveOleObject('Excel.Application');


thEXCEL:=Unassigned;


thExcel1:=Unassigned;


thEXCEL:=GetActiveOleObject('Excel.Application');


//thEXCEL.visible:=TRUE;


// --- Lecture des paramètres dans le fichier INI ---


If not FileExists(thCfgFile) then begin


thMessage:='Fichier de config inexistant (' + thCfgFile + ')...';


Synchronize(EcritMessage);


Exit;


end;


thFicIni:=TIniFile.Create(s);


try


sSheetName:=thFicIni.ReadString('Excel', 'NvPds_feuille', 'reglage');


iCellRow:=thFicIni.ReadInteger('Excel', 'NvPds_ligne', 21);


iCellCol:=thFicIni.ReadInteger('Excel', 'NvPds_colonne', 5);


finally


thFicIni.free;


end;


// --- Recherche de la feuille sSheetName dans Excel ---


thWorkBook:=thEXCEL.ActiveWorkBook;


index:=-1;


For i:=1 to thWorkBook.WorkSheets.Count do begin


s:=UpperCase(thWorkBook.WorkSheets.Item[i].Name);


If s = UpperCase(sSheetName) then index:=i;


end;


// --- Ecriture du poids ---


If index>-1 then begin


thWorkBook.WorkSheets.Item[index].Activate;


thSheet:=thEXCEL.ActiveSheet;


thSheet.Cells[iCellRow, iCellCol]:=thNewWeight;


thMessage:=Format('Poids transmis à Excel : %0.3f. Création du ' +


'du fichier d''échange avec la presse', [thNewWeight]);


Synchronize(EcritMessage);


// On force le "Worksheet_SelectionChange" sous Excel => prend du


// temps, d'où ce thread séparé


thSheet.Cells[iCellRow+1, iCellCol].Select;


end


else begin


thMessage:='Feuille ' + sSheetName + ' introuvable !';


Synchronize(EcritMessage);


Exit;


end;


except


thMessage:='Erreur dans l''écriture du poids sous Excel';


Synchronize(EcritMessage);


end;


finally


thEXCEL:=Unassigned;


CoUnInitialize; //Fermeture librairie COM


end;


end;


end.
Commenter la réponse de cs_Ptinico
cs_Ptinico 4 Messages postés vendredi 20 décembre 2002Date d'inscription 31 mai 2007 Dernière intervention - 4 mai 2007 à 21:40
0
Utile
C'est un copier coller malencontreux d'un bout de code qui trainait chez moi ds un coin.
Ca marche effectivement juste avec la ligne indiquée.
Merci encore pour ton aide.

PS : le but de mon appli :
- aller chercher dans le port série un poids transmis par une balance, qui pèse des pièces produites en série par une presse
- compiler en temps réel ces poids, les faire manger à un algo qui décide s'il faut corriger le programme Excel de la presse
- envoyer le poids corrigé à Excel pour qu'il recalcule le nouveau programme
- envoyer enfin un message via TPC/IP à la presse pour qu'elle s'arrête, mange le programme recalculé, et redémarre.
Tout ça en temps réel.
Grace à toi je vois maintenant le bout du tunnel, tout ce qui était port série + tcp/ip marche déjà en multi-thread..
Commenter la réponse de cs_Ptinico

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.