FAQ Visual Basic

FAQ Visual Basic Consultez toutes les FAQ
Nombre d'auteurs : 50, nombre de questions : 300, dernière mise à jour : 15 juin 2021
Sommaire→Divers bis→Routines- Comment obtenir le temps d'exécution d'une partie de mon code ?
- Comment exécuter un code à la première exécution d'un programme ?
- Comment transmettre des données à un document Word ?
- Comment extraire un élément d'une chaine délimitée qui est à une position donnée ?
- Comment n'autoriser qu'une seule instance de mon application ?
- Comment lire un fichier XML ?
- Comment générer aléatoirement un mot de passe ?
- Comment faire une capture d'écran ?
- Comment lister les variables d'environnement d'une application ?
- Comment connaître le type du contenu d'un TextBox ?
- Comment savoir si le contenu d'un TextBox est un Integer ?
- Comment effectuer des conversions vers le Décimal, l'Hexadécimal ou le Binaire ?
- Comment convertir un nombre décimal en binaire ?
- Comment Arrondir un nombre à sa valeur supérieure ou inférieure
- Comment effectuer un calcul statistique à partir des valeurs contenues dans un tableau ?
- Comment savoir si un nombre est pair ou non ?
- Comment afficher une image en plein écran ?
- Comment savoir si mon programme est exécuté depuis l'IDE de VB6 ou en mode compilé ?
- Comment utiliser la fonction split en VB5 ?
- Comment Encoder des url ?
- Comment récupérer les propriétés d'un PDF
- Comment effectuer un codage/decodage base64 ?
- Comment effectuer un codage/décodage en Quote-Printable ?
- Comment trier un tableau d'entier ?
- Comment enlever les accents d'une chaîne
Ajoutez cette déclaration au début de votre module :
Private Declare Function GetTickCount Lib "kernel32" () As LongGetTickCount renvoie le nombre de millisecondes qui s'est écoulé depuis le démarrage du système. Appelez-la au début de votre code, puis à la fin, et la différence entre les deux résultats vous donnera le nombre de millisecondes qui s'est écoulé entre les deux appels.
Dim Debut As Long, Fin As Long
Debut = GetTickCount()
'ici le code à chronométrer
Fin = GetTickCount()
MsgBox "Temps mis en millisecondes : " & Fin - DebutIl y a plusieurs méthodes pour faire cela. Habituellement on utilise un emplacement particulier du registre situé sous cette clé :
HKEY_CURRENT_USER\Software\VB and VBA Program Settings\appname\section\key
Cette partie du registre est directement manipulable avec les quatre fonctions suivantes :
- SaveSetting appname, section, key, value : permet de créer ou de modifier une clé du registre.
- GetSetting(appname, section, key [, default]) ou GetAllSettings((appname, section) : permet de récupérer une ou des clés
- DeleteSetting appname, section, key : supprime une clé.
Bien sûr, ces fonctions ne permettent pas une gestion complète du registre mais elles vous permettent de stocker quelques valeurs très simplement. C'est ce que nous allons faire avec le code suivant.
Private Sub Form_Load()
'vérifie l'existence de la clé
If Len(GetSetting("MonAppli", "Demar", "DejaEx")) = 0 Then
'si elle n'existe pas création de celle-ci
SaveSetting "MonAppli", "Demar", "DejaEx", "Vrai"
'Le code placé ici ne s'exécutera qu'une fois
MsgBox "Je n'apparaîtrais plus", vbInformation + vbOKOnly
End If
End SubVoici une méthode utilisant les signets. Dans Microsoft Word, un signet est un emplacement nommé que l'on utilise comme référence. Il est ajouté via la commande Signets qui est dans le menu Insertion. Ici les signets vous serviront de conteneurs pour les informations envoyées par votre programme. Vous devez leur octroyer un nom afin de pouvoir les identifier depuis Visual Basic. Attention, vous ne pouvez pas ajouter plusieurs fois un signet du même nom.
Voici un exemple d'envoi de données. Dans votre projet, n'oubliez pas de cocher la référence Micorosft Word x.0 Object Library.
Dim MyWord As Word.Application, doc As Word.Document
Dim signet As String, i As Long
Set MyWord = New Word.Application
With MyWord
Set doc = .Documents.Open("c:\modele.doc")
'Rs est un recordset Adodb, NomPers et PrenomPers sont des signets
doc.Bookmarks("NomPers").Range.Text = Rs.Fields("nom").Value
doc.Bookmarks("PrenomPers").Range.Text = Rs.Fields("prenom").Value
' exemple de signets allant de Mat1 à Mat11 remplis par les valeurs d'une table TbMat
For i = 0 To 10
signet = "Mat" & Trim(Str(i + 1))
doc.Bookmarks(signet).Range.Text = TbMat(i)
Next i
doc.SaveAs "c:\etat.doc" 'enregistre sous un autre nom
.Visible = True 'rend l'application visible
Set doc = Nothing
End With
DoEvents
Set MyWord = NothingDans cet exemple le modèle est enregistré sous un autre nom puis le document est rendu visible. Vous pouvez au contraire imprimer le document sans que l'utilisateur sache que Word est utilisé et sans que les modifications soient sauvegardées :
doc.PrintOut
doc.Close wdDoNotSaveChangesOn utilise la fonction ci-dessous qui attend en paramètres la chaine, la position de l'élément à extraire
et le délimiteur. Cette fonction renvoie une chaine vide lorsqu'elle ne peut pas procéder à l'extraction.
Dans le cas d'une extraction partielle, cette fonction est beaucoup plus rapide qu'un Split.
Function ExtraitElement(ChaineRecherche As String, Position As Long, Delim As String) As String
'Renvoie une chaine vide si l'extraction n'est pas possible
On Error GoTo Err_Function
Dim compteur As Long, LastPos As Long, CurPos As Long
If InStr(ChaineRecherche, Delim) = 0 Or Len(ChaineRecherche) = 0 Then Exit Function
LastPos = 1
Do
CurPos = InStr(LastPos, ChaineRecherche, Delim)
If CurPos = 0 Then
If compteur = Position - 1 Then ExtraitElement = Mid(ChaineRecherche, LastPos)
Exit Do
Else
compteur = compteur + 1
If compteur = Position Then
ExtraitElement = Mid(ChaineRecherche, LastPos, CurPos - LastPos)
Exit Do
End If
End If
LastPos = CurPos + 1
Loop While CurPos > 0
Exit Function
Err_Function:
MsgBox "Error " & Err.Number & ": " & Err.Description
Resume Next
End FunctionCertaines applications n'acceptent d'être ouverte qu'une seule fois. Si l'on essaie de l'ouvrir une deuxième fois, la fenêtre de la première instance repasse en premier plan et est restaurée si nécessaire.
Pour tester le code ci-dessous, créez un projet et ajoutez une form. Son nom est Form1 par défaut. Ajoutez ensuite le code ci-dessous dans un module standard. Enfin, sélectionnez "Sub Main" comme objet de démarrage dans les propriétés du projet.
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Const SW_RESTORE = 9
Private Const GW_HWNDPREV = 3
Private Sub Main()
Dim lngHandle As Long
'Cherche une fenêtre qui serait déjà ouverte
lngHandle = GetPreviousWindow
If lngHandle > 0 Then
'fenêtre trouvée, on l'affiche
DisplayWindow lngHandle
Else
Form1.Show
End If
End Sub
Private Function GetPreviousWindow() As Long
Dim strTitre As String
Dim lngHwnd As Long
'Sauvegarde le titre de l'application et le modifie
'sinon on trouverait toujours une instance de l'application : celle qui vient d'être lancée
strTitre = App.Title
App.Title = "---" & App.Title
'Récupère le handle de la fenêtre principale (invisible)
lngHwnd = FindWindow("ThunderRT6Main", strTitre)
'Obtient le handle de la fenêtre visible
If lngHwnd > 0 Then GetPreviousWindow = GetWindow(lngHwnd, GW_HWNDPREV)
'Restaure le titre original
App.Title = strTitre
End Function
Private Sub DisplayWindow(ByVal lngHandle As Long)
ShowWindow lngHandle, SW_RESTORE
SetForegroundWindow lngHandle
End SubLa Fonction GetPreviousWindow() renvoie le handle de la fenêtre de l'application si celle-ci a déjà été ouverte. La fonction DisplayWindow() restaure et met au premier plan la fenêtre dont le handle est passé en paramètre. Dans la procédure Main, nous recherchons une instance existante. Si nous en avons trouvé une, nous l'activons, sinon nous affichons Form1.
Il existe aussi un autre moyen :
Private Sub Form_Load()
If App.PrevInstance Then
MsgBox "Désolé, une instance est déjà active" & vbCrLf & "Le programme va s'arréter"
End
End If
End SubLa lecture d'un fichier XML se fait à l'aide d'un parseur. Dans les références du projet, ajoutez Microsoft XML.
Voici un exemple qui affiche dans la fenêtre de débogage la liste des balises contenues dans un document xml.
Private Sub BrowseChildNodes(root_node As IXMLDOMNode)
Dim i As Long
For i = 0 To root_node.childNodes.length - 1
If root_node.childNodes.Item(i).nodeType <> 3 Then Debug.Print root_node.childNodes.Item(i).baseName
BrowseChildNodes root_node.childNodes(i)
Next
End Sub
Private Sub BrowseXMLDocument(ByVal filename As String)
Dim xmlDoc As DOMDocument, root As IXMLDOMElement
Set xmlDoc = New DOMDocument
xmlDoc.async = False
xmlDoc.Load filename
Set root = xmlDoc.documentElement
If Not root Is Nothing Then
Debug.Print root.baseName
BrowseChildNodes root
End If
End SubAppelez simplement la procédure BrowseXMLDocument en passant en paramètre le chemin du fichier. Cette procédure ouvre le fichier puis appelle la procédure BrowseChildNodes qui parcoure l'ensemble des balises de façon récursive.
Lien : Home page de MSXML
Génération de 10 mots de passe de 8 caractères.
Private Const CaracteresAutorises As String = "0123456789abcdefghijklmnopqrstuvwxyz"
Public Sub main()
Dim Index As Integer
For Index = 1 To 10
Debug.Print Generer(8)
Next Index
End Sub
Public Function Generer(Longueur As Integer) As String
Dim Index As Integer
Randomize
For Index = 1 To Longueur
Generer = Generer & Mid(CaracteresAutorises, Int(Len(CaracteresAutorises) * Rnd()) + 1, 1)
Next Index
End FunctionDans une Form ajouter un contrôle PictureBox. Ajouter ces déclarations dans un module :
Private Declare Function BitBlt Lib "gdi32.dll" ( _
ByVal hDestDC As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal hSrcDC As Long, _
ByVal xSrc As Long, _
ByVal ySrc As Long, _
ByVal dwRop As Long) As Long
Private Declare Function GetDesktopWindow Lib "user32.dll" () As Long
Private Declare Function GetDC Lib "user32.dll" ( _
ByVal hwnd As Long) As Long
Private Const SRCCOPY As Long = &HCC0020
Public Sub ScreenShot(Pic As PictureBox)
Pic.AutoRedraw = True
Pic.Width = Screen.Width
Pic.Height = Screen.Height
Pic.Visible = False
BitBlt Pic.hDC, 0&, 0&, Screen.Width, Screen.Height, GetDC(GetDesktopWindow()), 0&, 0&, SRCCOPY
SavePicture Pic.Image, "C:\ScreenShot.bmp"
End SubAppel de la procédure :
ScreenShot Picture1Lien : Page sources : capture d'écran
Lien : Page sources : capture d'écran via API
Lien : Page sources : capture d'écran via PrintScreen
Fonctionne sous Win 2000 et supérieur.
Dim MyStr As String
i = 1
Do
If Environ(i) = "" Then
Exit Do
Else
MyStr = MyStr & Environ(i) & vbCrLf
i = i + 1
End If
LoopDim D as Double
If isNumeric(Text1.Text) Then
D=CDbl(Text1.Text)
If D-Int(D) = 0 Then
'Le nombre est entier
Else
'Le nombre est décimal
End if
Else
'Ce n'est pas un nombre
End ifPrivate Function isInteger(Expression As Variant) As Boolean
Dim D As Double
If IsNumeric(Text1.Text) Then
D = CDbl(Text1.Text)
If D = Int(D) Then isInteger = True
End If
End FunctionFunction Dec2Hex(dec As Long) As String
Dec2Hex = hex(dec)
End Function
Function Hex2Dec(hex As String) As Long
Hex2Dec = Val("&h" & hex)
End Function
Function Hex2Bin(hex As String) As String
Dim i As Byte
Dim resultat As String
For i = 1 To Len(hex)
Select Case Mid(hex, i, 1)
Case "0": resultat = resultat & "0000"
Case "1": resultat = resultat & "0001"
Case "2": resultat = resultat & "0010"
Case "3": resultat = resultat & "0011"
Case "4": resultat = resultat & "0100"
Case "5": resultat = resultat & "0101"
Case "6": resultat = resultat & "0110"
Case "7": resultat = resultat & "0111"
Case "8": resultat = resultat & "1000"
Case "9": resultat = resultat & "1001"
Case "A": resultat = resultat & "1010"
Case "B": resultat = resultat & "1011"
Case "C": resultat = resultat & "1100"
Case "D": resultat = resultat & "1101"
Case "E": resultat = resultat & "1110"
Case "F": resultat = resultat & "1111"
End Select
Next i
Hex2Bin = resultat
End Function
Function Bin2Dec(bin As String) As String
Dim i As Byte
Dim resultat As Long
resultat = 0
For i = 1 To Len(bin)
If Mid(bin, Len(bin) - i + 1, 1) = 1 Then
resultat = resultat + 2 ^ (i - 1)
End If
Next i
Bin2Dec = resultat
End FunctionPour les autres conversions il suffit de combiner les fonctions...
Public Function DecimalToBinaire(DecVal As Double) As String
'Variable temporaire qui sert lors du traitement du nombre à convertir
Dim NbTmp As Double
'Variable/Indice de boucle
Dim IndiceP as Integer
NbTmp = DecVal
For IndiceP = 1 To Int(Log(DecVal) / Log(2)) + 1
DecimalToBinaire = CDbl(NbTmp Mod 2) & DecimalToBinaire
NbTmp = CDbl(Int(NbTmp / 2))
Next IndiceP
End FunctionIl vous suffit ensuite de l'appeler ainsi pour convertir par exemple 1324 en binaire :
DecimalToBinaire(1324)Lien : Comment effectuer des conversions vers le Décimal, l'Hexadécimal ou le Binaire ?
Contrairement à la fonction Round qui arrondi un nombre à sa valeur la plus proche en fonction des décimales choisies,
cette fonction propose la fonction myRound qui arrondi un nombre à sa valeur supérieure et inférieur en fonction des décimales choisies.
Enum myRoundEnum
myRoundup = -1
myRoundDown = 1
End Enum
Public Function myRound(vValeur As Variant, Optional byNbDec As Byte, Optional eSens As myRoundEnum = myRoundup) As Variant
myRound = eSens * Int(eSens * vValeur * 10 ^ byNbDec) / 10 ^ byNbDec
End Function
L'appel de cette Fonction :
Sub test()
MsgBox myRound(4.333, 1, myRoundup)
MsgBox myRound(4.333, 1, myRoundDown)
End SubVoici par exemple une fonction pour calculer un écart type sur les valeurs contenues dans un tableau :Public Function EcartTypeP(tbl As Variant) As Double
Dim Var1, Var2
For i = 1 To UBound(tbl)
Var1 = Var1 + (tbl(i) * tbl(i)) ' somme des carrés
Var2 = Var2 + tbl(i) 'somme des valeurs
Next
EcartTypeP = Sqr(((UBound(tbl) * Var1) - (Var2 * Var2)) / (UBound(tbl) * UBound(tbl)))
End Function
Voici le code à mettre afin de tester cette fonction. Nous remplissons tout d'abord un tableau pour ensuite en calculer l'écart type dont le résultat s'affichera dans la fenêtre d'exécution.
Private Sub Bouton1_Click()
Dim table(10)
'remplir le tableau
For i = 1 To 10
table(i) = i
Next
'dans un module faites ctrl+g pour afficher la fenêtre d'exécution
Debug.Print EcartTypeP(table)
End SubFunction ispair(mavar As Long) As Boolean
ispair = Not mavar And 1
End FunctionExemples : ispair(2) retourne true ispair(1) retoune false
En parlant d'image plein écran, on peut penser à des situations différentes. Soit une image qui doit rester proportionnelle afin de ne pas être déformée,
soit un fond de feuille uni qui peut être étiré sans perdre de qualité.
Le premier exemple s'attache à l'image proportionnelle :
Dans l'événement Click de l'image, placez le code suivant :
Private Sub Picture1_Click()
Form2.Image1.Picture = Picture1.Picture
'intégration de l'image dans image1 de form2
Form2.Show 'afficher form2
Form2.Tag = Picture1.Height / Picture1.Width
'calcul du rapport hauteur sur largeur de l'image à copier et envoi dans le tag de la form2
End SubDans le code de la form2, qui doit comporter un image et un timer, entrez ceci :
Private Sub Form_Click()
Unload Me 'décharger form2
End Sub
Private Sub Form_Load()
Image1.Visible = False
Timer1.Interval = 1
Timer1.Enabled = True
'ces comandes ne sont pas nécessaires mais elles permettent de ne pas avoir à entrer les caractéritiques des objets ci-dessus
End Sub
Private Sub Timer1_Timer()
'le timer est utilisé car il faut un délai minimal avant que l'image se retrouve dans image1
If Me.Tag > (Screen.Height / Screen.Width) Then
Timer1.Tag = 1
Else
Timer1.Tag = 0
End If
'détermine si l'image est plus haute que large
If Timer1.Tag = 1 Then
Me.PaintPicture Image1.Picture, (Screen.Width - (Screen.Width * (Screen.Height / Screen.Width) / _
Me.Tag)) / 2, 0, Screen.Width * (Screen.Height / Screen.Width) / Me.Tag, Screen.Height
Else
Me.PaintPicture Image1.Picture, 0, (Screen.Height - (Screen.Height * (Screen.Width / Screen.Height) * _
Me.Tag)) / 2, Screen.Width, Screen.Height * (Screen.Width / Screen.Height) * Me.Tag
End If
'prendre image sur image1
'si image moins large que l'écran par rapport à sa hauteur, centrer paintpicture
'selon l'axe horisontal hauteur de l'image = hauteur de l'écran et largeur de l'image proportionelle
'sinon centre l'image selon l'axe vertical,
'largeur de l'image = largeur de l'écran et hauteur de l'image proportionnelle
Timer1.Enabled = False
End SubPar contre, pour afficher un fond de feuille qui peut être un fond "plein écran", il suffit de définir les propriétés de la feuille de fond comme suit :
- BorderStyle = 0 - None
- WindowState = 2 - Maximized
Dans la feuille dite "de fond", placez un contrôle Image1 renommé ImgFond et le code suivant :
Private Sub Form_Load()
ImgFond.Picture = LoadPicture(PathGraphiques & "fdbleu.jpg")
End Sub
Private Sub Form_Resize()
ImageFond Me
End SubEnsuite, dans un module BAS, placez la routine de redimensionnement :
Public Sub ImageFond(Feuille As Form)
Feuille.ImgFond.Move 0, 0, Feuille.ScaleWidth, Feuille.ScaleHeight
End SubLe contrôle image ne doit pas spécialement être étendu à toute la feuille, il faut juste spécifier sa propriété Stretch à True.
Une astuce parmi d'autres consiste à utiliser la fonction de l'API Windows GetModuleFileName dans un module ou une form de votre application.
Déclarations :
Private Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" _
(ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As LongGetModuleFileName : cette fonction de l'API Windows retourne ByRef le chemin complet et le nom du fichier exécutable qui contient le module dans lequel cette fonction est appelée.
- renvoie {VB6 install path}\vb6.exe, si le programme est exécuté depuis l'environnement de développement de VB6 (l'IDE).
- renvoie {chemin du projet}\NomProjet.exe, dans le cas contraire.
La fonction ci-dessous retourne :
- Vrai si le programme tourne depuis l'IDE de Visual Basic
- Faux si le programme tourne depuis l'exécutable
(Nécessite la fonction ExtractFileName)
Public Function IsRunningIDE() As Boolean
On Error Resume Next
Dim sBuffer As String
Dim Ret As Integer
sBuffer = String$(255, Chr$(0))
Ret = GetModuleFileName(0, sBuffer, Len(sBuffer))
If Ret > 0 Then
sBuffer = Mid(sBuffer, 1, Ret)
IsRunningIDE = Lcase(ExtractFileName(sBuffer) = "vb6.exe")
End If
End Function
Private Sub Form_Load()
MsgBox IsRunningIDE
End SubNOTA : remplacez "vb6.exe" par votre version de Visual Basic, si vous utilisez une version antérieure
La fonction split, n'existe pas en vb5 mais on peu créer sa propre fonction :
Public Function Split(ByVal MyString As String, Optional ByVal Separator As String = " ") As Variant
Dim iPosit As Long
Dim Table() As String
ReDim Table(0)
iPosit = InStr(MyString, Separator)
If iPosit = 1 Then
MyString = Mid$(MyString, Len(Separator) + 1)
iPosit = InStr(MyString, Separator)
End If
While iPosit > 0
Table(UBound(Table)) = Left(MyString, iPosit - 1)
MyString = Mid$(MyString, iPosit + Len(Separator))
ReDim Preserve Table(UBound(Table) + 1)
iPosit = InStr(MyString, Separator)
Wend
Table(UBound(Table)) = MyString
Split = Table
End FunctionCette fonction s'utilise comme la fonction split standard de VB6, vous trouverez plusieurs exemples dans cette faq.
Lien : Une autre façon d'écrire la fonction voir FAQ Access 97
En utilisant la fonction JavaScrip, Escape :
cochez la référence à Microsoft Script Control
Dim strBase As String, strEncode As String, SC As New ScriptControl
strBase = "Ceci est une chaîne encodée"
SC.Language = "JavaScript"
strEncode = SC.Eval("escape(" + Chr(34) + strBase + Chr(34) + ")")L'inverse est aussi possible par l'utilisation de unescape
SC.Eval("unescape(" + Chr(34) + strEncode + Chr(34) + ")")Pour obtenir les propriétés d'un PDF (nom, titre, etc.), il faut lire le fichier en mode binary. L'utilisation des RegExp permettra d'accéder aux informations recherchées. C'est ce que fait la fonction suivante :
Function GetPDFTitle(ByVal strFic As String, strObj As String) As String
Dim fic As Integer
Dim strExp As String
Dim strBuff As String * 1024
Dim i As Integer
Dim reg As VBScript_RegExp_55.RegExp
Dim Match As VBScript_RegExp_55.Match
Dim Matches As VBScript_RegExp_55.MatchCollection
Set reg = New VBScript_RegExp_55.RegExp
reg.Global = True
reg.MultiLine = False
reg.IgnoreCase = True
reg.Pattern = "/" & strObj & " \((.*)\)"
Reset
fic = FreeFile
Open strFic For Binary Access Read As #fic
Do While Not EOF(fic)
Get #fic, , strBuff
strExp = strExp & strBuff
If reg.Test(strExp) = True Then
Set Matches = reg.Execute(strExp)
For Each Match In Matches
GetPDFTitle = Match.SubMatches(0)
Next Match
Exit Function
Else
strExp = right(strExp, 1024)
End If
Loop
Reset
Set Match = Nothing
Set Matches = Nothing
Set reg = Nothing
End FunctionExemple d'utilisation :
getpdftitle( "d:\temp\20060331164202.pdf", "Title")Il est possible de remplacer title par un des champs suivants :
- CreationDate
- ModDate
- Title
- Creator
- Author
Lien : Tutoriel : Le PDF gratuit pour Access
Lien : Les expressions rationnelles / régulières dans Access par la pratique
Lien : Comment utiliser les expression régulières en VB6
Ceci est plus une astuce qu'un vrai code
On utilise une référence As Microsoft XML,version 2.0 , qui en sous produit, fait le codage/decodage du base 64
fonction d'encodage :
Public Function Encode_Base64(Text As String) As String
Dim Xml As New MSXML.DOMDocument
Dim Conv As MSXML.IXMLDOMElement
Dim Arr() As Byte
If Text = "" Then
Encode_Base64 = ""
Exit Function
End If
Arr = StrConv(Text, vbFromUnicode)
Set Conv = Xml.createElement("Base64")
Conv.dataType = "bin.base64"
Conv.nodeTypedValue = Arr
Encode_Base64 = Conv.Text
End Function
fonction décode :
Public Function Decode_Base64(Text As String) As String
Dim Xml As New MSXML.DOMDocument
Dim Conv As MSXML.IXMLDOMElement
If Text = "" Then
Decode_Base64 = ""
Exit Function
End If
Set Conv = Xml.createElement("Base64")
Conv.dataType = "bin.base64"
Conv.Text = Text
Decode_Base64 = StrConv(Conv.nodeTypedValue, vbUnicode)
End FunctionVous pouvez utiliser une version plus récente de "Microsoft XML", dans ce cas modifiez les déclarations de variables en remplaçant MSXML... par MSXML2...
Le codage Quote-Printable est un codage ou toutes les lettres non comprises dans l'intervalle
[33-60] [62-126] sont remplacés par =XX , ou XX est le code ascii du caractère.
Le tout est découpé en ligne de 76 caractères maximum.
fonction d'encodage :
Public Function EncodeQuotedPrintable(Text As String) As String
Dim lPntIn As Long 'compteur caractères dans Text
Dim lPntOut As Long 'position insertion dans buffer
Dim lLenLign As Long 'Longeur ligne en cours
Dim Buffer As String 'buffer reception du codage
Dim Char As String 'le caratére en cours d'analyse
Dim AsciiCode As Integer 'son code asccii
If Text = "" Then
EncodeQuotedPrintable = ""
Exit Function
End If
Buffer = String(Len(Text) * 3, 0) ' au max, 3 caractères en sortie pour chaque caractère en entrée
lPntOut = 1
lLenLign = 1
For lPntIn = 1 To Len(Text)
Char = Mid(Text, lPntIn, 1)
AsciiCode = Asc(Char)
Select Case AsciiCode
Case 33 To 60, 62 To 126
'caractère litéral
'tous ces caractères peuvent être acceptés tels quels
Mid(Buffer, lPntOut, 1) = Char
lPntOut = lPntOut + 1
lLenLign = lLenLign + 1
Case 9, 32
'----------------------------------------
'version abandonnée
'Mid(Buffer, lPntOut, 1) = Char
'lPntOut = lPntOut + 1
'lLenLign = lLenLign + 1
'----------------------------------------
'le caractère blanc et le caractère tab sont censés être acceptés sans codage
'mais pas s'ils terminent une ligne ! auquel cas il doivent être codés.
'Comme ce n'est pas simple à coder, je les code tous
Mid(Buffer, lPntOut, 3) = "=" & Right("00" & Hex(AsciiCode), 2)
lPntOut = lPntOut + 3
lLenLign = lLenLign + 3
Case Else
'on code tous les autres caractères
Mid(Buffer, lPntOut, 3) = "=" & Right("00" & Hex(AsciiCode), 2)
lPntOut = lPntOut + 3
lLenLign = lLenLign + 3
End Select
If lLenLign > 72 Then
'si on arrive en bout de ligne (qui ne doit pas passer 76 caractères)
'on insére une continuation de ligne ( =CRLF )
Mid(Buffer, lPntOut, 3) = "=" & vbCrLf
lPntOut = lPntOut + 3
lLenLign = 1
End If
Next
EncodeQuotedPrintable = Left(Buffer, lPntOut - 1)
'si on termine par "= & vbcrlf , on le retire
If Right(EncodeQuotedPrintable, 3) = "=" & vbCrLf Then
EncodeQuotedPrintable = Left(EncodeQuotedPrintable, Len(EncodeQuotedPrintable) - 3)
End If
End Function
fonction décode :
Public Function DecodeQuotedPrintable(Text As String) As String
Dim lPntIn As Long 'compteur caractères dans Text
Dim lPntOut As Long 'position insertion dans buffer
Dim Buffer As String 'buffer reception du dé-codage
Dim Char As String 'le caratére en cours d'analyse
Dim AsciiCode As String 'son code asccii en hexadécimal
If Text = "" Then
DecodeQuotedPrintable = ""
Exit Function
End If
Buffer = String(Len(Text), 0) ' au max, 1 caractère en sortie pour chaque caractère en entrée
lPntOut = 1
For lPntIn = 1 To Len(Text)
Char = Mid(Text, lPntIn, 1)
Select Case Char
Case "="
AsciiCode = Mid(Text, lPntIn + 1, 2)
If AsciiCode = vbCrLf Then
'caractère continuation de ligne
lPntIn = lPntIn + 2
Else
'caractère codé
Mid(Buffer, lPntOut, 1) = Chr(Val("&H" & AsciiCode))
lPntOut = lPntOut + 1
lPntIn = lPntIn + 2
End If
Case Else
'caractère litéral
Mid(Buffer, lPntOut, 1) = Char
lPntOut = lPntOut + 1
End Select
Next
DecodeQuotedPrintable = Left(Buffer, lPntOut - 1)
End FunctionVous pouvez utiliser une version plus récente de "Microsoft XML", dans ce cas modifiez les déclarations de variables en remplaçant MSXML... par MSXML2...
Une adaptation du QuickSort des sources algo de développez : page sources algo
Public Function QUICKSORT(ByRef Tableau() As Integer, Optional ByVal Debut As Integer = -1, _
Optional ByVal Fin As Integer = -1)
'attention, ne pas avoir un tableau avec des indices négatifs.
If Debut = -1 Then Debut = LBound(Tableau, 1)
If Fin = -1 Then Fin = UBound(Tableau, 1)
Dim Pivot As Integer
Dim Gauche As Integer
Dim Droite As Integer
Dim temp As Integer
Pivot = Debut
Gauche = Debut
Droite = Fin
Do
If Tableau(Gauche) >= Tableau(Droite) Then
temp = Tableau(Gauche)
Tableau(Gauche) = Tableau(Droite)
Tableau(Droite) = temp
Pivot = Gauche + Droite - Pivot
End If
If Pivot = Gauche Then
Droite = Droite - 1
Else
Gauche = Gauche + 1
End If
DoEvents
Loop Until Gauche = Droite
If Debut < Gauche - 1 Then QUICKSORT Tableau, Debut, Gauche - 1
If Fin > Droite + 1 Then QUICKSORT Tableau, Droite + 1, Fin
End Function
Voici une solution en utilisant les API.
Coller ce code dans un nouveau module :
Private Declare Function FoldString Lib "kernel32.dll" Alias _
"FoldStringA" (ByVal dwMapFlags As Long, ByVal lpSrcStr As Long, _
ByVal cchSrc As Long, ByVal lpDestStr As Long, ByVal cchdest As Long) As Long
Function OteAccents(ByVal str As String) As String
Dim i As Integer
OteAccents = Space(Len(str))
For i = 0 To (Len(str) - 1) * 2 Step 2
FoldString &H40, StrPtr(str) + i, 1, StrPtr(OteAccents) + i, 1
Next i
End Function


