TextBox Multiligne - Sélection & insertion de données

pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 - 8 juin 2015 à 13:05
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 - 11 juin 2015 à 10:37
Bonjour CodeS SourceS,

Je rencontre une difficulté assez curieuse.

Tout d'abord le but de ce code : faire en sorte de "formater" le contenu d'un textbox MultiLine pour l'affichage dans une cellule Excel.

Il s'agit d'ajouter donc des "balises" dans le texte du textbox pour que lors de la restitution dans la cellule, le texte puisse être formaté (couleur de texte, gras, souligne...).

Le code fonctionne bien si le texte sélectionné est, au maximum, sur une seule ligne. Par contre, lors de la sélection de plusieurs lignes de texte, les balises ne se placent pas dans le textbox. La curiosité tiens dans le fait que la variable Par les contient bien ces balises...
Grrr!

Voici le code, en trois étapes :
Module de l'userform :
Option Explicit

Private Sub UserForm_Initialize()
Dim monTxtBox As TextBoxFormat
Dim Obj As Object
Dim Defaut_txt$
Dim Cpt%

   Set CollectTxt = New Collection
   Defaut_txt = "Bonjour," & vbCrLf & _
            "Merci de ne sélectionner qu'une partie du texte, choisir les différents formats (disponibles lors d'un clic droit) en cliquant sur les boutons et VALIDER!" & vbCrLf & _
            "Vous pourrez ainsi visualiser le résultat du formatage dans le textbox et dans la cellule active." & vbCrLf & _
            "Les différents codes fonctionnent pour une sélection d'une ligne maxi." & vbCrLf & _
            "Pour une sélection de plusieurs lignes les balises ne s'affichent pas!"
   For Cpt = 1 To 4
      Set Obj = Me.Controls.Add("forms.TextBox.1")
      With Obj
         .Move 24, 6 + (75 * (Cpt - 1)), 480, 70
         .MultiLine = True
         .Name = TXTBOXNAME & Cpt
         .Value = Defaut_txt
         .WordWrap = True
      End With
      Set monTxtBox = New TextBoxFormat
      Set monTxtBox.TxtF = Me.Controls(TXTBOXNAME & Cpt)
      CollectTxt.Add monTxtBox
   Next Cpt
   Me.Move Me.Left, Me.Top, 544, 411
End Sub

Module "standard" :
Option Explicit

Public Nom_Tb$
Public CollectTxt As Collection

Public Const TXTBOXNAME$ = "F_TextBox"
Public Const PARAM$ = "Noir;Blanc;Rouge;Vert;Bleu;Jaune;Gras;Italic;Souligne"
Public Const BALISES$ = "N;W;R;V;B;Y;G;I;S"

Public Sub Format_Txt(Balise As String)
Dim Valeur$, S%, L%, Quoi$, Par$
   With UserForm1.Controls(Nom_Tb)
      Valeur = .Value
      S = .SelStart
      L = .SelLength
      Quoi = .SelText
      Par = "<" & Balise & ">" & .SelText & "</" & Balise & ">"
      'On VOIT ICI que Par contient bien les balises "<X>" & "</X>"...
      'Debug.Print Par
      .Value = Replace(Valeur, Quoi, Par)
   End With
End Sub

Module de classe nommé : TextBoxFormat
Option Explicit

Public WithEvents TxtF As MSForms.TextBox

Private Sub TxtF_MouseUp(ByVal Button%, ByVal Shift%, ByVal X!, ByVal Y!)
   Select Case Button
      Case XlMouseButton.xlSecondaryButton
         With TxtF
            If .SelText = "" Then
               MsgBox "Veuillez sélectionner le texte à formater."
               Exit Sub
            End If
            Nom_Tb = .Name
         End With
         CreerMenu
         Application.CommandBars("Menu").ShowPopup
   End Select
End Sub

Public Sub CreerMenu()
Dim cBar As CommandBar, i%, Bal$, Texto$
Const NOMB As String = "Menu"

   On Error Resume Next
      Application.CommandBars(NOMB).Delete
   On Error GoTo 0
   Set cBar = Application.CommandBars.Add(Name:=NOMB, Position:=msoBarPopup, temporary:=True)
   For i = 0 To UBound(Split(BALISES, ";"))
      Texto = Split(PARAM, ";")(i)
      Bal = Split(BALISES, ";")(i)
      With Application.CommandBars(NOMB).Controls.Add(Type:=msoControlButton)
         .Caption = Texto
         .OnAction = "'Format_Txt """ & Bal & """'"
      End With
   Next i
   Set cBar = Nothing
End Sub

10 réponses

ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
Modifié par ucfoutu le 8/06/2015 à 15:47
Bonjour, Franck,

Ton problème résulte des vbxcrl présents et qui se font des croche-pieds entre l'aller et le retour.
On pourrait bien sûr suivre ta logique et "formater" chaque sous-chaîne issue d'un split sur les retours à la ligne.
Mais pourquoi s'embarrasser, alors que la propriété seltext est déjà le texte sélectionné et qu'elle est en lecture/écriture. Sers-t'en et affranchis toi au passage du Replace, du Selstart, du Sellength, de la variable valeur, de la variable Par et de la variable quoi ===>>>
Public Sub Format_Txt(Balise As String)
With UserForm1.Controls(Nom_Tb)
.SelText = "<" & Balise & ">" & .SelText & "</" & Balise & ">"
End With
End Sub


________________________
Nul ne saurait valablement coder ce qu'il ne saurait exposer clairement.
1
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 14
8 juin 2015 à 15:48
Bonjour Jacques,
J'avais réussit à pointer du doigt le souci (vbcrlf), mais n'ai trouvé aucune explication à ce sujet.
Merci pour la réponse en tout cas.
Je vais tester sur le champs.
0
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 14
8 juin 2015 à 15:50
Test effectué.
Super!
Cette solution n'est que du bonheur.
Merci encore.
A bientôt.
0
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 14
9 juin 2015 à 09:40
Bonjour,

Je rouvre ce sujet afin de comprendre certains "détails".

La saisie de caractères (Via Chr(CodeAscii)) dans le textbox entraine des réactions assez "particulières".
C'est le cas pour VbCrlf qui nous empêche, par exemple, d'utiliser la fonction Replace dans mon exemple.
C'est également le cas d'autres caractères.

Par exemple :
Debug.Print "--" & .SelText = Chr(157) & "<" & Balise & ">" & .SelText & "</" & Balise & ">" & Chr(157) & "--"
.SelText = Chr(157) & "<" & Balise & ">" & .SelText & "</" & Balise & ">" & Chr(157) 

Affiche, dans le textbox, un "grand" espace avant la balise "ouvre" et après la balise "ferme", mais n'affiche rien avant la balise "ouvre" et après la balise "ferme" dans la fenêtre d'exécution...

Debug.Print "--" & .SelText = Chr(0) & "<" & Balise & ">" & .SelText & "</" & Balise & ">" & Chr(0) & "--"
.SelText = Chr(0) & "<" & Balise & ">" & .SelText & "</" & Balise & ">" & Chr(0) 

Efface la sélection dans le textbox et affiche dans la fenêtre d'exécution un espace avant la balise "ouvre" et après la balise "ferme".

Je n'ai pas, de fait, testé tous les Chr() possibles, mais y a t'il un endroit, un site ou se renseigner sur ces particularités?

Pourquoi ces "réactions" particulières? sont-elles explicables?
[Oui, il y a une explication à chacune de ces particularités. Mais qu'elle est-elle???]

S'il n'en existe pas, est-il opportun de créer un tutoriel à ce sujet?

Merci par avance.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
9 juin 2015 à 11:28
Je vais commencer par le chr(0), qui est très particulier ===>>>
Le caractère 0 est un caractère nul de terminaison.
Il n'est pas lu au Debug Print, d'une part et, d'autre part, le debug print ne lit pas au delà de ce caractère
Idem avec une msgbox, d'ailleurs (et pour la même raison)
Fais l'expérience ===>>
toto = "aaa" & Chr(0) & "bbb"
MsgBox toto

L'affichage n'ira pas au delà de "aaa", bien que la chaîne soit plus longue ===>>>
Msgbox len(toto)
t'affichera bien 7
et pour cause, car le caractère 0 a bel et bien été pris en compte et le voilà :
Dim titi() As Byte
titi = StrConv(toto, vbFromUnicode)
For i = 0 To UBound(titi)
MsgBox titi(i)
Next

Mais termine la "lecture".
Regarde maintenant :
MsgBox Left(toto, 3) & Right(toto, 3)

tu vois bien, que le "bbb" est bien là, mais que le chr(0) a interrompu la lecture de la chaîne (c'est sa vocation, d'ailleurs).
0
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 14
9 juin 2015 à 11:48
Bonjour Jacques,

Et une fois de plus, merci.

Ok. J'ai bien saisi la vocation du Chr(0).

Le but était, mais je penses que tu t'en doutes, de "préparer" la restitution du contenu du textbox dans la cellule, afin que le formatage se fasse sans souci.
Pour cela, j'aurais utilisé un simple Split(montext, Chr(0)).

Mais si l'affichage ne peut se faire, cela ne m'arrange pas.
Je cherchais un caractère "invisible" pour indiquer les débuts et fins de balise.
J'ai également testé Chr(2) et Chr(3) mais ces caractères ne sont pas "invisibles" à l'affichage...

Je vais continuer à explorer d'autres possibilités.
0
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
9 juin 2015 à 23:29
Ah ...
Tu veux le beurre et l'argent du beurre (des balises, mais invisibles)
Pourquoi ne pas alors utiliser une RichtextBox, ce qui te permettrait de formater ton texte comme tu l'entends, sans aucune balise ?
La "récupération", ensuite, du format pourra se faire sans problème caractère par caractère (une simple boucle).
Et tu pourras (toujours sans aucune balise apparente) "conjuguer" à ton aise (la taille, le style, la couleur, etc ...)

0
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 14
Modifié par pijaku le 10/06/2015 à 14:38
Bonjour Jacques,

Oui, je veux le beurre, son argent et ... la crémière (tu va comprendre pourquoi)...

1- je ne veux pas utiliser le Contrôle RichTextBox car cela obligerait les utilisateurs du fichier à tous l'installer sur leur machine. (ici, tu comprends bien que ce fichier n'est pas pour moi, mais pour un forumeur)

2- Je ne souhaites pas que mes balises (<N>, <W>, <B> etc) soient invisibles car l'utilisateur s'en sert pour visualiser la mise en forme qu'il est en train d'effectuer.

3- Je souhaitais ajouter de part et d'autres de ces balises, un caractère invisible (dans mon exemple prenons Chr(0) même s'il ne convient pas) afin de pourvoir restituer le plus facilement du monde :

création des "balises" :
.SelText = Chr(0) & "<" & Balise & ">" & Chr(0) & .SelText & Chr(0) &  "</" &  Balise & ">" & Chr(0)


Ainsi, pour la restitution, je n'avais qu'à faire un Split :
Tb() = Split(TextBox.Value, Chr(0))
pour obtenir quelque chose comme ceci :
Tb(1) => <B>
Tb(2) => Bonjour,
Tb(3) => </B>
Tb(4) => <N>
Tb(5) => Comment allez-vous par ici?
Tb(6) => </N>
etc...


EDIT : ps : tu dois te demander : "pourquoi ne pas faire la mise en forme directement dans la cellule?"
En effet, c'est comme cela que je ferais. Mais bon, à ce moment là, pourquoi créer un Userform pour saisir dans une cellule? Aucun intérêt non plus.
Je respecte seulement les consignes...
0
ucfoutu Messages postés 18038 Date d'inscription lundi 7 décembre 2009 Statut Modérateur Dernière intervention 11 avril 2018 211
11 juin 2015 à 07:16
L'inconvénient majeur de ces "balises" incluses directement dans le texte de la textbox est qu'elles sont dépendantes des gestes (tous) de l'utilisateur et donc extrêmement vulnérables.
0
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 14
11 juin 2015 à 10:37
Bonjour,

Effectivement, je n'ai pas pensé à cet aspect...
Si l'utilisateur, dans un mauvais geste supprime un < ou un > ou encore /... ça risque de planter toute restitution.
Pour moi, cela semble sans issue.
Les deux seules raisonnables solutions étant :
- Le contrôle RichTextBox
- formater le texte directement dans la cellule.

Je vais toutefois reposer le problème posément, on ne sait jamais.
Encore merci pour ton intervention.
A++
0
Rejoignez-nous