jplausanne
Messages postés12Date d'inscriptionmercredi 17 décembre 2008StatutMembreDernière intervention 1 juillet 2012
-
31 janv. 2009 à 09:28
PCPT
Messages postés13280Date d'inscriptionlundi 13 décembre 2004StatutMembreDernière intervention 3 février 2018
-
1 févr. 2009 à 19:57
Bonjour,
J'ai une base de données Access avec une table contenant un champ OLE dans lequel est introduit (directement par l'utilisateur) (Click Droit, Inserer objet etc...) dans documents Word ou Excel.
Je ne trouve pas le moyen d'ouvrir ces documents depuis VB après avoir accéder à l'enregistrement qui contient ce document .
Par exemple, un des documents Word (introduit dans le champ OLE) doit servir pour un publipostage. Le publiposte fonctionne si le document est externe (on l'appelle alors avec son chemin complet ex: C:\temp\.... ) mais comment accéder à un document stocké dans la bd Access dans un champ OLE (donc l'ouvrir pour ce traitement...).
Pas mal cherché sur le Net... rien trouvé!
Si quelqu'un a une idée... merci d'avance!
PCPT
Messages postés13280Date d'inscriptionlundi 13 décembre 2004StatutMembreDernière intervention 3 février 201848 31 janv. 2009 à 10:13
salut,
tu le charges dans un tableau de bytes
après.., çà dépend de ce que ton champ contient
génériquement il te suffit d'écrire ton tableau dans un fichier et de lancer ce fichier par shellexecute
jplausanne
Messages postés12Date d'inscriptionmercredi 17 décembre 2008StatutMembreDernière intervention 1 juillet 2012 31 janv. 2009 à 11:15
Salut et merci pour ta réponse, je continue à m’arracher les cheveux… Je ne suis absolument pas familier avec les tableaux de bytes : je peux bien-sûr chercher mais si tu as des idées…<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /??>
Pour le moment, j’en suis là. Je retrouve l’enregistrement contenant le document Word à utiliser pour le publipostage selon différent critères :
WordDoc = DLookup(Nom du champ OLE, Nom de la table, strfiltre)
Et là je ne sais plus quoi faire…. Si j’affiche le contenu de Worddoc je vois des caractères ésotériques… j’imagine que c’est bien le document Word. Mais je ne vois toujours pas comment l’ouvrir ou le traiter (par exemple le sauver sur le disque etc…) ?
jplausanne
Messages postés12Date d'inscriptionmercredi 17 décembre 2008StatutMembreDernière intervention 1 juillet 2012 31 janv. 2009 à 15:57
Merci encore infiniment… Je n’aurais pas pensé à cela, je m’attendais à une commande toute simple permettant de lire directement l’objet OLE dans VB depuis l’enregistrement.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /??>
Tout ce qui m’a dit fonctionne : le fichier est bien créé mais il contient des choses illisibles du style (quand il s’affiche dans Word):
Par contre si je fais l’opération sur un autre champ (texte) du même enregistrement cela marche : Le texte est bien sauvegardé tel quel dans le fichier.
Cela doit donc être la façon dont je récupère le contenu du champ OLE (document Word) qui est fausse et pourtant je n’en vois pas 36 hormis le bon vieux Dlookup (Tout ceci se fait dans un modue Access)! Donc j’investigue encore, nous ne sommes pas loin.
jplausanne
Messages postés12Date d'inscriptionmercredi 17 décembre 2008StatutMembreDernière intervention 1 juillet 2012 31 janv. 2009 à 17:11
Merci pour ta réponse… plus ça va plus je m’y perds. La solution qui m’a été proposée avant semble OK mais il semble que l’objet OLE soit récupéré comme du binaire et non comme un document Word.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /??>
Déjà que VB et moi on n'est pas vraiment copains, je ne comprends pas qu’il soit si difficile de travailler sur un objet OLE stocké dans la base.
Tes propositions
DataSource
, DataField
, OleTypeAllowed=1-Embedded sont certainement intéressantes et, comme elles ne me disent rien à ce stade, je vais chercher. Je ne vois comment tout cela s’articule et s’utilise !
Snif ! je veux simplement ouvrir ce document OLE, depuis un module Access, et éventuellement le copier ailleurs sur le disque pour faire un publiposte avec des données Access (ce publipostage fonctionne bien avec un fichier word sur le disque qu'il suffit de référencer avec son chemin) ! D’autant que si je crée une requête bête comme chou pour accéder à cet objet : je le vois et il suffit de cliquer dessus pour qu’il s’ouvre dans Word.
jplausanne
Messages postés12Date d'inscriptionmercredi 17 décembre 2008StatutMembreDernière intervention 1 juillet 2012 1 févr. 2009 à 08:45
c'est déjà fait... mais dans un formulaire c'est facile puisque toute l'interface est là. Le problème que j'ai est hors formulaire. en gros l'utillisateur choisi les personnes à qui le publipostage doit être adressé (dans un formulaire) et clique sur un bouton pour lancer celui-ci. C'est là où j'ai le problème: je recherche (selon des critères) l'enregistrement qui contient le document Word (champ OLE) à utliser pour le publipostage....je le trouve... mais je reste incapable de l'ouvrir dans un module Access
jplausanne
Messages postés12Date d'inscriptionmercredi 17 décembre 2008StatutMembreDernière intervention 1 juillet 2012 1 févr. 2009 à 08:48
Merci PCPT pour toutes ces infos... je dois faire le tri devant cette multitude d'instructions... beaucoup reste liées aux formulaires mais dans mon cas, je n'ai pas de formulaire: c'est une recherche directe dans la base de données afin d'ouvrir un maudit document Word!
PCPT
Messages postés13280Date d'inscriptionlundi 13 décembre 2004StatutMembreDernière intervention 3 février 201848 1 févr. 2009 à 09:26
t'énerve pas
[../auteur/JPLAUSANNE/1555805.aspx jplausanne]
, on a compris ^^
en access (base de données) OLE c'est du BLOB... du BINARY
mon tout premier code donné doit donc fonctionner à partir du moment où le tableau de bytes est valide
le lien vb6 ci-dessus indique comment faire avec une image (binary), donc avec un type STREAM ADO. aucune idée si en VBA-access tu as accès à ces méthodes sans ajouter de références (ADO, ADOX)
le dernier lien quant à lui est spécifique à VBA, avec divers exemples ne correspondant pas forcément tous, mais çà peut donner des idées
au pire des cas - APRèS RECHERCHES ET MULTIPLES TESTS!!! - tu peux héberger ton projet (cijoint.fr) et indiquer comment arriver à ton blocage. indique précisément la marche à suivre, je jetterai un oeil (access 2000 et access 2007 à dispo)
bon courage
Prenez un instant pour répondre à [sujet-SONDAGE-POP3-POUR-CS_769706.aspx ce sondage] svp
jplausanne
Messages postés12Date d'inscriptionmercredi 17 décembre 2008StatutMembreDernière intervention 1 juillet 2012 1 févr. 2009 à 10:01
Je ne m'énerve pas PCPT... j'ai simplement frôlé la depression nerveuse.... mais je viens de trouver (beaucoup grace à toi et tes idées de chemin d'accès, de copie de fichier...!)
en fait, l'engregistrement OLE récupéré ainsi à un header qu'il faut traiter/éliminer pour lire et copier le document. Ca marche!!!!
Le seul problème, certainement mineur, qui me reste est la connexion à la db, ici dans cet exemple:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=e:\My Documents\db1 XP.mdb;" & _
"Jet OLEDB:Engine Type=4;"
Si je remplace la bd par ma base de données. le système me dit qu'elle est déjà ouverte (ce qui est vrai puisque je développe dedans...), j'ai donc ouvert une copie de ma bd (sous un autre nom juste pour faire le test) et ça marche. Si tu as une idée pour adapter le code ci-dessus à la bd en cours
quoiqu'il en soit merci infiniment pour tous tes "trucs" et astuces. Quant au traitement des champs OLE c'est complètement délirant... Je suis aussi contre (mieux vaut stocker les chemins des documents que les documents eux-mêmes) il s'agit d'une application d'une bonne dizaine d'années que j'ai reprise.
PCPT
Messages postés13280Date d'inscriptionlundi 13 décembre 2004StatutMembreDernière intervention 3 février 201848 1 févr. 2009 à 11:27
umm...
pas testé mais çà devrait fonctionner comme çà (dans un module) :
Private Type
PT
Width As Integer
Height As Integer
End Type
Private Type OBJECTHEADER
Signature As Integer
HeaderSize As Integer
ObjectType As Long
NameLen As Integer
ClassLen As Integer
NameOffset As Integer
ObjectSize As PT
OleInfo As String * 256
End Type
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As
Long
' adaptation depuis
http://www.tech-archive.net/Archive/VB/microsoft.public.vb.general.discussion/2005-10/msg01640.html Function GetOLEWordDoc2File(ByRef vLookUpResult As Variant, ByVal sExt
As String) As String
Dim abArr() As Byte
Dim sDest As String
Dim ObjHeader As OBJECTHEADER
Dim ObjectOffset As Long
Dim Buffer As String
Dim i As Long
Dim FileOffset As Long
Dim FileHeaderOffset As Integer
Dim FileStream() As Byte
' tableau
de bytes
On Local Error GoTo Err_Handler
abArr = vLookUpResult
On Error GoTo 0
'Copy the first 19
bytes into a variable of the defined type OBJECTHEADER
' copie le header du champ
CopyMemory ObjHeader, abArr(0), 19
'Determine where the
header ends
' position de la fin du
header
ObjectOffset = ObjHeader.HeaderSize +
1
'Grab enough
bytes after the OLE header to get file header
'
récypère le header string du fichier sans le header du ole
Buffer = ""
For i = ObjectOffset To ObjectOffset + 512
Buffer = Buffer & Chr$(abArr(i))
Next i
'Make sure the class
of the object is Word Document
' le header
informe bien d'un doc word?
If Mid$(Buffer, 12, 13) = "Word.Document" Then
' récupère la
position de la fin de la première partie du header
FileHeaderOffset = InStr(Buffer, "ÐÏ")
If FileHeaderOffset > 0 Then
'Calculate the
beginning of the document
' fin du
header => début du document
FileOffset = ObjectOffset + FileHeaderOffset - 1
'Move
document into its own array
' 2e tableau
dans le header parasite
ReDim FileStream(UBound(abArr) -
FileOffset)
CopyMemory FileStream(0), abArr(FileOffset), UBound(abArr) - FileOffset +
1
'Document file path
' enregistrement du tableau dans le doc
temp
Call CreateFileFromBytes(sDest,
FileStream)
'
retour
GetOLEWordDoc2File = sDest
End If
End If
Err_Handler:
Erase FileStream
Erase abArr
End Function
'
'
'http://www.codyx.org/snippet_recuperer-chemin-temp_772.aspx#2291
Private Function GetTempDirectory() As String
Dim sBuffer As String
sBuffer = String$(260, vbNullChar)
If GetTempPath(Len(sBuffer), sBuffer) Then
'
enlève les NULL
GetTempDirectory = LeftB$(sBuffer, InStrB(1, sBuffer,
vbNullChar))
Else
GetTempDirectory = Environ$("TEMP")
End If
' ajoute le slash
If Not (RightB$(GetTempDirectory, 2) = "") Then GetTempDirectory = GetTempDirectory & ""
End Function
'
'
'http://www.codyx.org/snippet_enregistrer-tableau-bytes-dans-fichier_5.aspx#1367
Private Sub CreateFileFromBytes(ByVal sPath As String, ByRef aBytes() As Byte)
Dim FF As Integer
FF = FreeFile
Open sPath For Binary As #FF
Put #FF, , aBytes
Close #FF
End Sub
'
'
'http://www.codyx.org/snippet_ouvrir-document-lancer-executable_25.aspx#1548
Public Sub StartProcess(ByVal sFile As String, Optional ByVal sParameters As String =
vbNullString)
ShellExecute 0&, "open", sFile, sParameters, vbNullString, 1&
End Sub
Dim sPathRet As String
sPathRet = GetOLEWordDoc2File(DLookup("[Nom du champ OLE]", "[Nom de la table]", strfiltre))
If Len(sPathRet) Then
StartProcess sPathRet
DoEvents
'Kill
sPathRet
Else
MsgBox "Erreur lors de l'extraction du
champ OLE", vbExclamation
End If
End Sub
jplausanne
Messages postés12Date d'inscriptionmercredi 17 décembre 2008StatutMembreDernière intervention 1 juillet 2012 1 févr. 2009 à 16:07
Chapeau bas ! Je viens de tester : c’est parfait (encore mieux car peut-être plus paramétrable – pour moi en tous cas !).<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>
Deux remarques vraiment insignifiantes :
Il manque dans Test() :
Dim Strfiltre as String
Et le deuxième argument/paramètre dans l’appel à GetOLEWordDoc2File
On y est arrivé, je sors donc de ma dépression nerveuse : Merci mille fois et à la prochaine (vais chercher quelque chose de plus tordu encore )!