XL 2016 VBA - Range to HTML incluant les objets de la feuille (boutons, images, ...)

Dudu2

XLDnaute Barbatruc
Bonjour,

Je n'ai rien trouvé qui fonctionne pour convertir un Range en HTML qui inclurait tout ce qu'il y a dans le Range en question.

J'ai bien récupéré la fonction de Ron de Bruin omni-présente sur le Web qui fonctionne uniquement pour les valeurs de cellules et leurs formats, sauf pour les tableaux structurés qui ne sont pas en exclusivité dans le Range qui perdent alors leurs formats (qui n'en sont pas vraiment !).
 

Pièces jointes

  • Classeur1.xlsm
    261.1 KB · Affichages: 11

patricktoulon

XLDnaute Barbatruc
ok ma fois j'ai toujour la meme erreur au directory
et là il me "F:\temp...."

en fait quand tu a publier une fois il garde ce dossier c'est mort pour moi ton fichier ne fonctionnera que chez toi
demo.gif



en fait si tu a coché au moins une fois ici meme par vba "publich=true" c'est mort tu est le seul a pouvoir l'utiliser et encore je suis pas sur que dans 2016 tu puisse choisir je l'ai pas vu sur le office 2016 chez mon voisin
il y a un argument a mettre mais je ne sais plus le quel
 

Dudu2

XLDnaute Barbatruc
Bon, ça marche nickel avec Base64, évidement.
Et pas avec Outlook, évidemment.
1663268740016.png


Le images placées au début avant la table se mettent dans la 1ère cellule de la table.
Faut trouver une autre solution pour leur placement !
Je regarderai ton code pour les images ou tu trouves la bonne modif de style ou autre.
Ça me fatigue ce truc !
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
c'est pas mal il me manque un bouton
1663268060403.png


par contre outlook ca déraille complètement mais on sait pourquoi ca on y changera rien
c'est shape vml et c'est tout

par contre j'ai fait une découverte super géniale en faisant a ma facon
en 3 click je te transforme un code html/css outline en code inline
le tout par vba bien sur
j'ai halluciné j'en crois pas mes yeux tellement c'est simple
 

patricktoulon

XLDnaute Barbatruc
Bonjour @Dudu2
pour l'occasion (je fait un peu le bilan)
j'ai réuni dans l'exemple ci joint 3 méthodes dans 3 modules différents que j'utilise moi même et depuis longtemps sauf le publish que je découvre en ce moment

les 3 récupèrent la table au format html parfaitement bien
(faut il encore avoir les librairies présentes et/ou non déactivées)

a comparer la IE est un peu plus longue
par contre la methode webbroser dans un userform sans (Show) et publish: ben elles sont au coude à coude

maintenant que cela est dit
revenons a ce qui nous préoccupe (a savoir remettre les images en place )

1° pour le web
somme toute c'est pas bien compliqué on encapsule la table dans un div en position relative
et on y met les images avant ou après la table en position absolute pour les sortir du flux et qu'elles puissent se placer là ou on l'indique dans le style

2° pour Outlook
là ça se complique
en effet Outlook n'accepte pas tout les éléments de style pour tout les éléments (qui pourtant sont valable dans un fichier html web
ce qui fait que les images (tag IMG) sont sorti du flux et placer avant ou après selon quand on les a placé

d'autant plus!!! que seule l'intégration de la shape vml DANS LA CELLULE(TD) est comprise par outlook
Outlook a son propre format avec les shapes VML qui lui accepte l'intégration dans le code
(voir ma fonction putshaphtmloutlook)
et OUI!! MAIS!!!
mais quand on a que la table(sans images) et qu'il n'y a pas de fusion on peut très bien faire la relation entre le topleftcell de la shape avec sa cellule et l'element TD correspondant dans la table HTML
il est donc très facile de placer le code shape+img dans le TD qui doit être en position relative

mais quand il y a des fusions
et bien là c'est la berézina il sera tres compliqué de faire la relation entre une cellules excel et son homlogue html (je rappelle que la lecture des address cells/mergeara est nécessaire pour chopper le bon index de cells car une boucle sur cells lira les address de chaque cells meme si il y a des fusions

voilà pourquoi j'avais conçu cette fonction(createhtmltable) il y a quelques années pour palier au problème de jumelage(cells excel/cellls html) car mon code de construction donne pour id au cells html l'adresse de la cells excel
ce qui me permet même en dehors de la sub de construction de cibler ma bonne cells pour y placer une image ou pour en modifier le style

il conviendra donc si l'on doit continuer avec une table sans image publish ou autre de trouver le moyen de faire la corrélation entre les cells html et excel
j'ai tenté quelques trucs mais sans résultat vraiment probant

de plus il faudrait pas que le temps d'execution s'en trouve rallongé

pour info la méthode publish 800 millième en moyenne et ma méthode createhtmltable pareille

ma méthode ayant un léger problème de surtaille de la table html et decallage parfois des images selon le navigateur

je t'invite donc a trouver un principe pour taguer les cells html avec un id correspondant aux cells excel
je cherche de mon coté bien sur

ci joint les 3 méthodes table only
 

Pièces jointes

  • exemple simply Range To Outlook.xlsm
    303.3 KB · Affichages: 1

Dudu2

XLDnaute Barbatruc
Bonjour @particktoulon,

Si je te suis bien, les images sont placées dans les cellules de table HTML et pas de façon indépendante.

Et si je te suis encore, le problème actuel est de faire le lien entre les cellules Excel et les cellules de table HTML.
Ne suffit-il pas de parcourir la table HTML pour faire le lien avec les cellules Excel ?
Avec les <tr et les <td on doit pouvoir s'y retrouver non ?
 

patricktoulon

XLDnaute Barbatruc
re
Si je te suis bien, les images sont placées dans les cellules de table HTML et pas de façon indépendante.
Oui !! pour outlook elle sont enfant du TD correspondant au toplefcell dans excel
et c'est des shapes pas des IMG

Avec les <tr et les <td on doit pouvoir s'y retrouver non ?
ben non justement tu ne lis pas bien ce que j'ai écris dans mon post précedent
même !!!!!!!! en cas de fusions la boucle lit chaque address de cellule
exemple
j'ai dix lignes fusionnées par ligne de 5 colonnes A1:E1 , A2:E2 , A3:E3 , etc....
cette boucle
for i= 1 to 10
for c= 1 to 5
debug.print cells(i,c).address(0,0)
next
next

va le lire A1,b1,b2,b3,b5 A1,A2,A3,A4,A5 etc.....
il est certains que la cellule b1 qui est la 2d de la ligne n'existe pas dans le html puisque c'est fusionné il n'y a qu'une cellule html dans les ligne tr

alors avec IE ou le Webbrowser c'est assez facile même en cas de fusion j'utilise dans la boucle for each le test getelementbyID(adresse dans la boucle) is nothing
tout simplement par ce qu'il me copie les 10 ligne et 8 colonnes de rng (c4:i13)

par contre publish lui ne copy que les cellules remplies ou formatée (couleur,etc...) et les vides entres deux autres pleine ou formatées

conclusion j'ai une table de 10 ligne sur 3 colonnes

il faut donc trouver une autre façon de voir avec publish

ET youpi J AI TROUVE !!!!!

revoilà donc l'exemple de tout a l'heure avec le targuage des cellules html avec l’adresse des cellules homologues d'excel


tu constatera qu'avec publish par rapport a IE ou le webrowser le codage de la boucle est différent

voila maintenant on la table avec les ID des cellules excel
facile après de lui transplanter ma fonction putshaphtmloutlook

voilà les 3 versions ont le tatouage de l'address de cells respectif

maintenant tu peux y aller ;)
 

Pièces jointes

  • exemple simply Range To Outlook.xlsm
    304.8 KB · Affichages: 3

patricktoulon

XLDnaute Barbatruc
et ben oui mais meme
j'ai A1 , B1 , C1:D1 , E1 , F1
dans ta boucle la cells d1.mergearea c'est la combien dans le tour de boucle ????!!!!
voyons voir puisqu'il faut faire un dessin
1er tour
A1.mergearea="A1"
2d tour
b1.mergearea="b1"
3eme tour
c1.mergearea="c1:d1"
4 eme tour
d1.mergearea="c1:d1"
et voilà tu es out
si tu avais pris la peine de tester tu le saurais
au 4 eme tour la td qui devrait porter l'id"E1 ben toi tu lui donne la même que la précédente

démonstration(puisqu'il faut aller jusque là)
demo.gif
 

Dudu2

XLDnaute Barbatruc
Je répondais à ton message relatif à la supposée impossibilité de faire correspondre cellules Excel et table HTML sans tagger les cellules.

Concernant la solution je ne sais pas précisément ou tu l'as mise. Dans la ressource mise à jour ? Ici ?

Les fichiers fleurissent de tous les côtés sans que je puisse déterminer s'il s'agit d'un test intermédiaire ou d'un fichier final.
Le dernier que J'ai essayé ne prenais pas les objets.
 

patricktoulon

XLDnaute Barbatruc
re oui l'exemple c'est ca
je me doute que tu zape plusieurs de mes messages et ou fichiers
et j'en ai une autre encore mieux pour mettre les id ET CELLE LA NE LA RATE PAS
c'est la solution la plus sur de toute puisque c'est un calque
en fait il faut prendre une partie de ma fonction createhtmltable2 et la modifier pour faire une table provisoire calque
en la construisant je met les ID et je met le ID au meme TD de la table créé par publish
j'ai largement commenté le code
c'est simple comme un bonjour
colle ça dans un module et teste tu vera
tu peux meme regarder le fichier html puisque je le réécris pour que tu puisse voir les ajout d'id

regarde le fichier toto.htm sur ton bureau
VB:
Option Explicit
'sub de test
Sub testByPublish()
    Dim Fichierhtml$, dossier$, rng As Range, codetable$, x&, tim#
    tim = Timer
    Fichierhtml = Environ("userprofile") & "\Desktop\toto.htm"
    'dossier = Replace(fichier, ".htm", "_fichiers")    'pour plus tard  recupérer les shapes
    Set rng = [c4:i13]
    codetable = CreateHtmlPublish(rng, Fichierhtml)    'on récupere le code html par le publish
    'Debug.Print codetable
    'MsgBox Format(Timer - tim, "#0.000 Sec") & " pour obtenir le code avec publish"
    'SendSelectionWithOutlook1 CStr(codetable)    'pour tester j'envoie le code toto2(inline)
End Sub

' on crée le code html en le recuperant du publich
Function CreateHtmlPublish(rng, fichier)
    Dim lachaine As String, x, code, y, TempWB As Workbook, dhtml As New HTMLDocument, Tb, TdS, TrS, Cel, AddR$, A, I&, C&
    Dim table1, tablecalque, tr, td
    Application.DisplayAlerts = False: Application.ScreenUpdating = False
    Set TempWB = Workbooks.Add
    rng.Copy TempWB.Sheets(1).[A1]    ' le (copy To Destination ) est plus rapide  que le (copy et sheet temp.paste......)
    With TempWB.Sheets(1)
        .DrawingObjects.Delete
        For I = 1 To rng.Columns.Count: .Columns(I).ColumnWidth = rng.Columns(I).ColumnWidth: Next
    End With
    DoEvents
    'publie la feuille en fichier html
    With TempWB.PublishObjects.Add(SourceType:=xlSourceRange, Filename:=fichier, _
                                   Sheet:=TempWB.Sheets(1).Name, Source:=TempWB.Sheets(1).UsedRange.Address, _
                                   HtmlType:=xlHtmlStatic): .Publish (True)
    End With
    DoEvents
    ActiveWorkbook.Close

    'apres  avoir publié on recupere le code du fichier
    x = FreeFile: Open fichier For Binary Access Read As #x: lachaine = String(LOF(x), " "): Get #x, , lachaine: Close #x
    
    'on récupere en string le code de la table uniquement
    Tb = "<table" & Split(Split(lachaine, "<table")(1), "</table>")(0) & "</table>"
    
    'on la met dans un htmldocument
    dhtml.body.innerHTML = Tb


    'on la determine en tant qu'object  table1
    Set table1 = dhtml.getElementsByTagName("table")(0)
    'on collectionne les ligne(tr)de cette table
    Set TrS = table1.getElementsByTagName("tr")
    'on crée en memoire( sans afillier au document une table qui va nous servir de calque )
    Set tablecalque = dhtml.createElement("table")
    For I = 1 To rng.Rows.Count    'boucle sur ligne de rng
        Set tr = tablecalque.appendchild(dhtml.createElement("tr"))    'on crée une ligne tr pour chaque ligne de rng
        A = 0    'A on remet A a 0 achaque tour de ligne
        For C = 1 To rng.Columns.Count    'boucle sur colonne de rng
            AddR = rng.Cells(I, C).MergeArea.Address(0, 0)    'on determine l'address de la cellule
            'si cet element n'existe pas dans le document ou la  table calque
            If dhtml.getElementById(AddR) Is Nothing Then
                'alors
                A = A + 1
                'on le crée et on lui met  le id (addr)
                Set td = tr.appendchild(dhtml.createElement("td")): td.ID = AddR
                
                'on prend le meme dans la table d'origine et on lui met le meme ID
                'on gere l'erreur  due au fait que rng a 8 colonne  tandis que la copy en html donc table1 n'en a que 4
                On Error Resume Next
                TrS(I - 1).Children(A - 1).ID = AddR
                On Error GoTo 0
            End If
        Next
    Next
    'on peut supprimer la tablecalque  on en a plus besoins
    Set tablecalque = Nothing
    'on remplace dans le string du fichier le code de la table par le code de la table1
    lachaine = Replace(lachaine, Tb, dhtml.getElementsByTagName("table")(0).outerhtml)
    'pas vraiment necessaire mais pour que tu puisse voir je réécris le fichier publié  avec la table et ces cellule avec ID
    x = FreeFile: Open fichier For Output As #x: Print #x, lachaine: Close #x
    'le return de la fonction c'est le code complet
    CreateHtmlPublish = Replace(lachaine, "align=center x:publishsource=""Excel""", "")
End Function
 

Discussions similaires

Statistiques des forums

Discussions
312 400
Messages
2 088 086
Membres
103 710
dernier inscrit
amin Saadaoui