<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Philben - Ms Access &#187; Chaîne de caractères</title>
	<atom:link href="https://blog.developpez.com/philben/ptag/string/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/philben</link>
	<description></description>
	<lastBuildDate>Thu, 26 Sep 2013 19:43:53 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>VBA : Exemple comparatif des indices de similarité</title>
		<link>https://blog.developpez.com/philben/p12219/vba-access/vba-exemple-comparatif-des-indices-de-similarite</link>
		<comments>https://blog.developpez.com/philben/p12219/vba-access/vba-exemple-comparatif-des-indices-de-similarite#comments</comments>
		<pubDate>Sat, 07 Sep 2013 17:38:26 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Similarité]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/philben/?p=772</guid>
		<description><![CDATA[Après avoir vu différents algorithmes de similarité dans des billets précédents, je vous propose un petit comparatif à travers un exemple qui consiste à trouver le doublon de restaurants par leur nom, adresse, téléphone et type de cusine. Les données &#8230; <a href="https://blog.developpez.com/philben/p12219/vba-access/vba-exemple-comparatif-des-indices-de-similarite">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Après avoir vu différents algorithmes de similarité dans des billets précédents, je vous propose un petit comparatif à travers un exemple qui consiste à trouver le doublon de restaurants par leur nom, adresse, téléphone et type de cusine.<br />
<span id="more-772"></span><br />
<strong>Les données</strong><br />
Les données sont issues d&rsquo;un exemple connu de recherche de doublons et sont présentées ici dans une seule colonne où nom, adresse, téléphone et type de cuisine sont fusionnés. <a href="http://philben.developpez.com/restos.txt" title="Fichier texte des restaurants" target="_blank">Le fichier de données</a> contient 224 lignes et chaque resto possède un et un seul doublon. Cet exemple reste donc plus simple qu&rsquo;un cas général de recherche de doublons&#8230;<br />
Extrait du fichier :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Katsu 1972 Hillhurst Ave. Los Feliz 213-665-1891 Japanese<br />
Restaurant Katsu 1972 N. Hillhurst Ave. Los Angeles 213/665-1891 Asian<br />
Les Celebrites 155 W. 58th St. New York City 212-484-5113 French (Classic)<br />
Les C&amp;eacute;l&amp;eacute;brit&amp;eacute;s 160 Central Park S New York 212/484-5113 French</div></div>
<p>Une difficulté s&rsquo;ajoute pour le dernier restaurant car les &lsquo;é&rsquo; de Célébrités sont convertis en HTML (&amp; eacute;)&#8230;</p>
<p>Le fichier source original est <a href="http://www.cs.utexas.edu/users/ml/riddle/data/restaurant.tar.gz" title="Fichier source des restaurants" target="_blank">ici</a>.</p>
<p><strong>Principe</strong><br />
Le principe est donc de rechercher pour chaque ligne, le restaurant qui a la similarité la plus forte soit 49 952 mesures (224 x 223) après conversion des chaînes en majuscule.<br />
Pour chaque restaurant, je considère que le bon doublon a été correctement trouvé s&rsquo;il arrive avec le plus fort indice par rapport aux 222 autres restaurants.<br />
J&rsquo;ai comparé les 3 algorithmes <a href="http://blog.developpez.com/philben/p12207/vba-access/vba-distance-de-jaro-winkler" title="VBA : Distance de Jaro-Winkler" target="_blank">Jaro-Winkler (JW)</a>, <a href="http://blog.developpez.com/philben/p11268/vba-access/similarite_entre_deux_chaines_de_caracte" title="Similarité entre deux chaînes de caractères" target="_blank">Damerau-Levenshtein (DL)</a> et les <a href="http://blog.developpez.com/philben/p11340/vba-access/indices-de-similarite-entre-deux-chaines-de-caracteres" title="Indices de similarité entre deux chaînes de caractères" target="_blank">6 indices Cosinus/Dice/Jaccard/&#8230; (IS)</a>, en recherchant pour chacun la meilleure configuration.</p>
<p><strong>Résultats</strong><br />
Concernant DL, pas de problème pour trouver la meilleure configuration car il suffit de passer les 2 chaînes en argument de la fonction.<br />
<strong>Damerau-Levenshtein a permis de détecter <strong>185 doublons sur 224 soit 82,6%</strong> de réussite.</strong></p>
<p>Concernant Jaro-Winkler, on peut jouer sur la longueur du préfixe entre 0 et 4. Les résultats obtenus sont :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Longueur préfixe &nbsp; &nbsp; &nbsp; &nbsp;Doublons détectés<br />
&nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 206<br />
&nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 209<br />
&nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 214<br />
&nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 213<br />
&nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 212</div></div>
<p>Dans cet exemple, la <strong>meilleure longueur de préfixe est 2 avec 214 doublons détectés soit un taux de réussite de 95,5%</strong>, la distance de Jaro seule (0) donne le moins bon résultat.</p>
<p>Enfin pour l&rsquo;algorithme IS, le choix du paramétrage est plus complexe car on peut choisir entre 6 indices de similarités, la longueur des Grammes (0 = mot à 5), l&rsquo;inversion ou non des grammes et une distance maximum de recherche des grammes communs.<br />
Pour la distance maxi, j&rsquo;ai laissé à -1 (pas de limite de distance) car elle fournit les meilleurs résultats dans cet exemple et la recherche de grammes inversés donne ici de moins bons résultats.</p>
<p>J&rsquo;ai donc joué sur le reste des paramètres (type d&rsquo;indice et longueur des grammes) et les résultats sont synthétisés ici :<br />
<img src="http://philben.developpez.com/restos.png" alt="Paramétrage des indices de similarité et résultats" /><br />
Les unigrammes (1) ont les moins bon résultats, la variabilité des résultats entre les indices diminue avec la longueur des grammes, les trigrammes et Simpson ont en moyenne les meilleurs résultats.</p>
<p>Pourcentage de réussite des indices en fonction de la longueur des grammes :<br />
<img src="http://philben.developpez.com/restosGraphe.png" alt="Pourcentage de réussites des indices en fonction de la longueur des grammes" /><br />
<strong>Finalement, l&rsquo;indice de Simpson avec des bigrammes donne ici le meilleur résultat : 219 doublons détectés soit 97,8% de réussite !</strong></p>
<p>Le tableau suivant indique le nombre de doublons détectés par position des résultats hormis le Top 1. Par exemple, 18 nouvelles bonnes détections faites par DL dans les Top 2 des résultats et <strong>Simpson en détecte 4 soit 223 détections cumulées (Top 1 et Top 2) sur 224 !</strong>.<br />
<img src="http://philben.developpez.com/restosPositions.png" alt="Nombre de détections en fonction de la position des résultats" /></p>
<p>Après avoir vu rapidement la capacité des indices à détecter les vrais doublons, il faut vérifier leur capacité à être discriminant entre les restaurants et compter les éventuels ex aequo.<br />
Imaginez un algo qui retourne un indice identique pour tous les restos : Ses résultats seraient parfaits mais pour chaque restaurant on aurait 223 restaurants détectés dans le Top 1 !</p>
<p>Via une requête, j&rsquo;ai donc calculé la position absolue du vrai doublon pour chaque algorithme et chaque ligne. Des ex aequo sont présents si la position absolue est supérieure au classement.</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Indice&nbsp; Classement &nbsp; Position absolue<br />
---------------------------------------<br />
JW&nbsp; &nbsp; &nbsp; 28 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;29<br />
---------------------------------------<br />
IS&nbsp; &nbsp; &nbsp; &nbsp;1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
---------------------------------------<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12<br />
DL&nbsp; &nbsp; &nbsp; &nbsp;9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;11<br />
DL&nbsp; &nbsp; &nbsp; 12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;20<br />
DL&nbsp; &nbsp; &nbsp; 17 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;21<br />
DL&nbsp; &nbsp; &nbsp; 24 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;66</div></div>
<p>JW n&rsquo;est affecté qu&rsquo;une fois par un ex aequo et ceci pour un classement du vrai doublon en 28ème position.<br />
IS en a obtenu un seul sur un Top 1 et DL a eu 13 fois un ou plusieurs ex aequo.</p>
<p><strong>Conclusion</strong><br />
Dans cet exemple, l&rsquo;indice de Simpson a détecté le plus de doublons dans le Top 1 (219 sur 224) et 223 dans le Top 2 des résultats.<br />
Si vous le souhaitez, vous pouvez ajouter <strong>vos propres résultats</strong> de vos algorithmes en commentaire du billet.</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VBA : Recherche d&#8217;une sous-chaîne particulière par la fin</title>
		<link>https://blog.developpez.com/philben/p12218/vba-access/vba-recherche-dune-sous-chaine-particuliere-par-la-fin</link>
		<comments>https://blog.developpez.com/philben/p12218/vba-access/vba-recherche-dune-sous-chaine-particuliere-par-la-fin#comments</comments>
		<pubDate>Sat, 07 Sep 2013 11:13:09 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/philben/?p=763</guid>
		<description><![CDATA[Après avoir vu l&#8217;extraction d&#8217;un token particulier depuis le début de la chaîne de caractère, je vous présente sa version depuis la fin de la chaîne. Objectif Extraire un token par son numéro d&#8217;apparition dans une chaîne de caractère mais &#8230; <a href="https://blog.developpez.com/philben/p12218/vba-access/vba-recherche-dune-sous-chaine-particuliere-par-la-fin">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Après avoir vu <a href="http://blog.developpez.com/philben/p11126/vba-access/extraire_un_token_d_une_chaine" title="Extraire un token d’une chaîne de caractères" target="_blank">l&rsquo;extraction d&rsquo;un token particulier </a>depuis le début de la chaîne de caractère, je vous présente sa version depuis la fin de la chaîne.<br />
<span id="more-763"></span><br />
<strong>Objectif</strong><br />
Extraire un token par son numéro d&rsquo;apparition dans une chaîne de caractère mais en partant de la fin de la chaîne.<br />
Par exemple, de la chaîne &lsquo;ab-cd-ef-gh&rsquo; je souhaite extraire &lsquo;ef&rsquo; qui est l&rsquo;avant-dernier token (ou sous-chaîne délimitée) depuis le dernier caractère séparateur &lsquo;-&lsquo;, ou bien le dernier token (&lsquo;gh&rsquo;), le 3ème (&lsquo;cd&rsquo;),&#8230;</p>
<p><strong>Comment faire simple ?</strong><br />
Pour ne pas réinventer la roue , je me suis appuyé sur notre fonction <a href="http://blog.developpez.com/philben/p11126/vba-access/extraire_un_token_d_une_chaine" title="Extraire un token d’une chaîne de caractères" target="_blank">TokenBySplit()</a> et la fonction standard VBA StrReverse() qui inverse la chaîne de caractère passée en argument (&lsquo;ab&rsquo; deviendra &lsquo;ba&rsquo;).</p>
<p><strong>La fonction</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> TokenReverse(<span style="color: #151B8D; font-weight: bold;">ByVal</span> Texte <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> Separateur <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> Numero <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> TypeComparaison <span style="color: #151B8D; font-weight: bold;">As</span> VbCompareMethod = vbBinaryCompare) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span><br />
<span style="color: #008000;">'Retourne le token spécifié par son numéro à partir de la fin de la chaîne de caractère<br />
</span><span style="color: #008000;">'Auteur : Philben - v1.0<br />
</span><span style="color: #008000;">'Exemple : TokenReverse(&quot;ab-cd-ef-gh&quot;,&quot;-&quot;,2) -&gt; ef (2ème token en partant de la fin)<br />
</span> &nbsp; &nbsp;TokenReverse = StrReverse(TokenBySplit(StrReverse(Texte), Separateur, Numero, TypeComparaison))<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Exemples</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">?TokenReverse(<span style="color: #800000;">&quot;ab-cd-ef-gh&quot;</span>,<span style="color: #800000;">&quot;-&quot;</span>,1) <span style="color: #008000;">'gh<br />
</span>?TokenReverse(<span style="color: #800000;">&quot;ab-cd-ef-gh&quot;</span>,<span style="color: #800000;">&quot;-&quot;</span>,2) <span style="color: #008000;">'ef<br />
</span>?TokenReverse(<span style="color: #800000;">&quot;ab-cd-ef-gh&quot;</span>,<span style="color: #800000;">&quot;-&quot;</span>,3) <span style="color: #008000;">'cd<br />
</span>?TokenReverse(<span style="color: #800000;">&quot;ab-cd-ef-gh&quot;</span>,<span style="color: #800000;">&quot;-&quot;</span>,4) <span style="color: #008000;">'ab<br />
</span>?TokenReverse(<span style="color: #800000;">&quot;ab-cd-ef-gh&quot;</span>,<span style="color: #800000;">&quot;-&quot;</span>,5) 'Nada !</div></div>
<p>&nbsp;</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VBA : Distance de Jaro-Winkler</title>
		<link>https://blog.developpez.com/philben/p12207/vba-access/vba-distance-de-jaro-winkler</link>
		<comments>https://blog.developpez.com/philben/p12207/vba-access/vba-distance-de-jaro-winkler#comments</comments>
		<pubDate>Sat, 31 Aug 2013 03:01:16 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Similarité]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/philben/?p=703</guid>
		<description><![CDATA[Cet algorithme mesure la similarité entre deux chaînes de caractères pour la recherche de doublons par exemple. Tout comme les algorithmes de Damerau-Levenshtein et les indices de similarité Cosinus, Dice, Jaccard&#8230;, la distance est normalisée entre 0 et 1. Plus &#8230; <a href="https://blog.developpez.com/philben/p12207/vba-access/vba-distance-de-jaro-winkler">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Cet algorithme mesure la similarité entre deux chaînes de caractères pour la recherche de doublons par exemple. Tout comme les algorithmes de <a href="http://blog.developpez.com/philben/p11268/vba-access/similarite_entre_deux_chaines_de_caracte" title="Similarité entre deux chaînes de caractères" target="_blank">Damerau-Levenshtein</a> et les <a href="http://blog.developpez.com/philben/p11340/vba-access/indices-de-similarite-entre-deux-chaines-de-caracteres" title="Indices de similarité entre deux chaînes de caractères" target="_blank">indices de similarité Cosinus, Dice, Jaccard&#8230;</a>, la distance est normalisée entre 0 et 1. Plus la similarité est forte plus la distance tend vers 1.<br />
<span id="more-703"></span><br />
<strong>La fonction VBA</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> JaroWinkler(<span style="color: #151B8D; font-weight: bold;">ByVal</span> s1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> s2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> LongueurPrefixe <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Byte</span> = 3, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> TypeComparaison <span style="color: #151B8D; font-weight: bold;">As</span> VbCompareMethod = vbBinaryCompare) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Single</span><br />
<span style="color: #008000;">'La distance de jaro_Winkler mesure la similarité entre deux chaines de caractères (s1 et s2)<br />
</span><span style="color: #008000;">'La distance est normalisée entre 0 et 1 (1 = similarité maximale)<br />
</span><span style="color: #008000;">'si LongueurPrefixe [0,4] = 0 =&gt; Distance de Jaro<br />
</span><span style="color: #008000;">'Référence : http://fr.wikipedia.org/wiki/Distance_de_Jaro-Winkler et références<br />
</span><span style="color: #008000;">'Remarques : Préparation parfois nécessaire des chaînes : ucase(),trim(),diacritiques<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Quelques libertés prises pour le calcul de la fenêtre (dMax) / Wikipédia<br />
</span><span style="color: #008000;">'Auteur : Philben v1.0 - Free to use<br />
</span> &nbsp; Const cMaxLongueurPrefixe <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Byte</span> = 4, cCoeffPrefixe <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Single</span> = 0.1<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> l1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, l2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, dMax <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, j <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, k <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> jMin <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, jMax <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, m <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, t <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, p <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, lam1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> c1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, r <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Single</span>, aUsed() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span>, ac2() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, am1() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span><br />
<br />
&nbsp; &nbsp;l1 = Len(s1): l2 = Len(s2)<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> l1 &gt; 0 <span style="color: #8D38C9; font-weight: bold;">And</span> l2 &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">ReDim</span> aUsed(1 <span style="color: #8D38C9; font-weight: bold;">To</span> l2): <span style="color: #151B8D; font-weight: bold;">ReDim</span> ac2(1 <span style="color: #8D38C9; font-weight: bold;">To</span> l2)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> l2: ac2(i) = Mid$(s2, i, 1): <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> l1 &gt;= l2 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">'dMax (1/2 fenêtre) calculée avec la + courte chaîne et non la + longue ! (voir blog)<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; dMax = (l2 + 1) \ 2 - 1 &nbsp; <span style="color: #008000;">'arrondi sup. de dMax (l=1 =&gt; 0, l=2 =&gt; 0, l=3 =&gt; 1)<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;dMax = (l1 + 1) \ 2 - 1<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> LongueurPrefixe &gt; cMaxLongueurPrefixe <span style="color: #8D38C9; font-weight: bold;">Then</span> LongueurPrefixe = cMaxLongueurPrefixe<br />
<br />
&nbsp; &nbsp; &nbsp; jMin = 1<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> dMax &lt; l2 <span style="color: #8D38C9; font-weight: bold;">Then</span> jMax = dMax <span style="color: #8D38C9; font-weight: bold;">Else</span>: jMax = l2<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> l1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;c1 = Mid$(s1, i, 1)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> i &gt; dMax + 1 <span style="color: #8D38C9; font-weight: bold;">Then</span> jMin = jMin + 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> jMax &lt; l2 <span style="color: #8D38C9; font-weight: bold;">Then</span> jMax = jMax + 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> jMin &gt; jMax <span style="color: #8D38C9; font-weight: bold;">Then</span> <span style="color: #E56717; font-weight: bold;">Exit</span> <span style="color: #8D38C9; font-weight: bold;">For</span> &nbsp; <span style="color: #008000;">'définitivement hors fenêtre =&gt; Fin<br />
</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> j = jMin <span style="color: #8D38C9; font-weight: bold;">To</span> jMax<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> aUsed(j) <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> StrComp(c1, ac2(j), TypeComparaison) = 0 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m = m + 1 &nbsp; <span style="color: #008000;">'Match<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> i = j <span style="color: #8D38C9; font-weight: bold;">And</span> i &lt;= LongueurPrefixe <span style="color: #8D38C9; font-weight: bold;">And</span> p = i - 1 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p = p + 1 &nbsp;<span style="color: #008000;">'Préfixe commun<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lam1 = lam1 + 1: <span style="color: #151B8D; font-weight: bold;">ReDim</span> <span style="color: #151B8D; font-weight: bold;">Preserve</span> am1(1 <span style="color: #8D38C9; font-weight: bold;">To</span> lam1): am1(lam1) = i<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; aUsed(j) = <span style="color: #00C2FF; font-weight: bold;">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #E56717; font-weight: bold;">Exit</span> <span style="color: #8D38C9; font-weight: bold;">For</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> j<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">'Compte les tranpositions<br />
</span> &nbsp; &nbsp; &nbsp;k = p + 1<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> lam1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> j = k <span style="color: #8D38C9; font-weight: bold;">To</span> l2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> aUsed(j) <span style="color: #8D38C9; font-weight: bold;">Then</span> <span style="color: #E56717; font-weight: bold;">Exit</span> <span style="color: #8D38C9; font-weight: bold;">For</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> j<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> StrComp(Mid$(s1, am1(i), 1), ac2(j), TypeComparaison) &lt;&gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> t = t + 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;k = j + 1<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
&nbsp; &nbsp; &nbsp; t = t \ 2<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> m &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;r = (m / l1 + m / l2 + (m - t) / m) / 3 &nbsp; <span style="color: #008000;">'Distance de Jaro<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; r = r + (p * cCoeffPrefixe * (1 - r)) &nbsp; <span style="color: #008000;">'Extension de Winkler<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
<br />
&nbsp; &nbsp;JaroWinkler = r<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Paramètres de la fonction</strong><br />
<strong>&lsquo;S1&prime; et &lsquo;S2&prime;</strong> correspondent aux deux chaînes de caractères à étudier.<br />
<strong>&lsquo;LongueurPrefixe&rsquo;</strong> permet de choisir la longueur du préfixe commun entre les deux chaînes. Cette longueur permet de calculer l&rsquo;apport de Winkler à l&rsquo;algorithme de Jaro. Cette longueur est comprise entre 0 et 4 (3 par défaut). La distance de Jaro est retournée lorsque ce paramètre est égal à 0.<br />
<strong>&lsquo;TypeComparaison&rsquo;</strong> permet de choisir le type de comparaison entre les deux chaînes : Soit une comparaison binaire (par défaut) soit une comparaison textuelle (moins restrictive car ne tient pas compte de la casse des caractères mais généralement moins performante).<br />
Il sera souvent nécessaire de prétraiter les chaînes par UCase()/LCase() (casse uniforme des caractères), Trim() (suppression des espaces en début et fin de chaîne) et remplacer les caractères diacritiques pour ne pas &lsquo;parasiter&rsquo; l&rsquo;algorithme (voir <a href="http://blog.developpez.com/philben/p11217/vba-access/remplacer_les_caracteres_accentues_d_une" title="Remplacer les caractères accentués d’une chaîne" target="_blank">ici</a>).</p>
<p><strong>Tests</strong><br />
J&rsquo;ai récolté dans une publication de W. E. Winkler (voir référence plus bas) et sur le Web des exemples pour tester les résultats de mon code. La longueur du préfixe est fixée à 4.</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> testJW()<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, r <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Single</span>, v() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
<br />
&nbsp; &nbsp;v = Array(<span style="color: #800000;">&quot;SHACKLEFORD&quot;</span>, <span style="color: #800000;">&quot;SHACKELFORD&quot;</span>, 0.982, <span style="color: #800000;">&quot;DUNNINGHAM&quot;</span>, <span style="color: #800000;">&quot;CUNNIGHAM&quot;</span>, 0.896, <span style="color: #800000;">&quot;NICHLESON&quot;</span>, <span style="color: #800000;">&quot;NICHULSON&quot;</span>, 0.956, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #800000;">&quot;JONES&quot;</span>, <span style="color: #800000;">&quot;JOHNSON&quot;</span>, 0.832, <span style="color: #800000;">&quot;MASSEY&quot;</span>, <span style="color: #800000;">&quot;MASSIE&quot;</span>, 0.933, <span style="color: #800000;">&quot;ABROMS&quot;</span>, <span style="color: #800000;">&quot;ABRAMS&quot;</span>, 0.922, <span style="color: #800000;">&quot;HARDIN&quot;</span>, <span style="color: #800000;">&quot;MARTINEZ&quot;</span>, 0#, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #800000;">&quot;ITMAN&quot;</span>, <span style="color: #800000;">&quot;SMITH&quot;</span>, 0#, <span style="color: #800000;">&quot;JERALDINE&quot;</span>, <span style="color: #800000;">&quot;GERALDINE&quot;</span>, 0.926, <span style="color: #800000;">&quot;MARHTA&quot;</span>, <span style="color: #800000;">&quot;MARTHA&quot;</span>, 0.961, <span style="color: #800000;">&quot;MICHELLE&quot;</span>, <span style="color: #800000;">&quot;MICHAEL&quot;</span>, 0.921, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #800000;">&quot;JULIES&quot;</span>, <span style="color: #800000;">&quot;JULIUS&quot;</span>, 0.933, <span style="color: #800000;">&quot;TANYA&quot;</span>, <span style="color: #800000;">&quot;TONYA&quot;</span>, 0.88, <span style="color: #800000;">&quot;DWAYNE&quot;</span>, <span style="color: #800000;">&quot;DUANE&quot;</span>, 0.84, <span style="color: #800000;">&quot;SEAN&quot;</span>, <span style="color: #800000;">&quot;SUSAN&quot;</span>, 0.805, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #800000;">&quot;JON&quot;</span>, <span style="color: #800000;">&quot;JOHN&quot;</span>, 0.933, <span style="color: #800000;">&quot;JON&quot;</span>, <span style="color: #800000;">&quot;JAN&quot;</span>, 0#, <span style="color: #800000;">&quot;DIXON&quot;</span>, <span style="color: #800000;">&quot;DICKSONX&quot;</span>, 0.813, <span style="color: #800000;">&quot;VOYAGE&quot;</span>, <span style="color: #800000;">&quot;AGENDA&quot;</span>, 0.444, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #800000;">&quot;TRAVEL&quot;</span>, <span style="color: #800000;">&quot;TRAIN&quot;</span>, 0.9, <span style="color: #800000;">&quot;ABCVWXYZ&quot;</span>, <span style="color: #800000;">&quot;CABVWXYZ&quot;</span>, 0.958)<br />
<br />
&nbsp; &nbsp;Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Chaîne 1&quot;</span>, <span style="color: #800000;">&quot;Chaîne 2&quot;</span>, <span style="color: #800000;">&quot;Attendue&quot;</span>, <span style="color: #800000;">&quot;Obtenue&quot;</span><br />
&nbsp; &nbsp;Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;--------&quot;</span>, <span style="color: #800000;">&quot;--------&quot;</span>, <span style="color: #800000;">&quot;---------&quot;</span>, <span style="color: #800000;">&quot;-------&quot;</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = <span style="color: #151B8D; font-weight: bold;">LBound</span>(v) <span style="color: #8D38C9; font-weight: bold;">To</span> <span style="color: #151B8D; font-weight: bold;">UBound</span>(v) <span style="color: #8D38C9; font-weight: bold;">Step</span> 3<br />
&nbsp; &nbsp; &nbsp; r = JaroWinkler(v(i), v(i + 1), 4) &nbsp; <span style="color: #008000;">'Longueur Prefixe = 4<br />
</span> &nbsp; &nbsp; &nbsp;Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> v(i), v(i + 1), v(i + 2), Round(r, 3), IIf(Abs(r - v(i + 2)) &gt; 0.001, <span style="color: #800000;">&quot;*** Ecart ***&quot;</span>, <span style="color: #800000;">&quot;&quot;</span>)<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Résultats et commentaires</strong></p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Chaîne 1 &nbsp; &nbsp; &nbsp;Chaîne 2 &nbsp; &nbsp; &nbsp;Attendue &nbsp; &nbsp; &nbsp;Obtenue<br />
-------- &nbsp; &nbsp; &nbsp;-------- &nbsp; &nbsp; &nbsp;--------- &nbsp; &nbsp; -------<br />
SHACKLEFORD &nbsp; SHACKELFORD &nbsp; &nbsp;0,982 &nbsp; &nbsp; &nbsp; &nbsp; 0,982 &nbsp; &nbsp; &nbsp; &nbsp;<br />
DUNNINGHAM &nbsp; &nbsp;CUNNIGHAM &nbsp; &nbsp; &nbsp;0,896 &nbsp; &nbsp; &nbsp; &nbsp; 0,896 &nbsp; &nbsp; &nbsp; &nbsp;<br />
NICHLESON &nbsp; &nbsp; NICHULSON &nbsp; &nbsp; &nbsp;0,956 &nbsp; &nbsp; &nbsp; &nbsp; 0,956 &nbsp; &nbsp; &nbsp; &nbsp;<br />
JONES &nbsp; &nbsp; &nbsp; &nbsp; JOHNSON &nbsp; &nbsp; &nbsp; &nbsp;0,832 &nbsp; &nbsp; &nbsp; &nbsp; 0,832 &nbsp; &nbsp; &nbsp; &nbsp;<br />
MASSEY &nbsp; &nbsp; &nbsp; &nbsp;MASSIE &nbsp; &nbsp; &nbsp; &nbsp; 0,933 &nbsp; &nbsp; &nbsp; &nbsp; 0,933 &nbsp; &nbsp; &nbsp; &nbsp;<br />
ABROMS &nbsp; &nbsp; &nbsp; &nbsp;ABRAMS &nbsp; &nbsp; &nbsp; &nbsp; 0,922 &nbsp; &nbsp; &nbsp; &nbsp; 0,922 &nbsp; &nbsp; &nbsp; &nbsp;<br />
HARDIN &nbsp; &nbsp; &nbsp; &nbsp;MARTINEZ &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,722 &nbsp; &nbsp; &nbsp; &nbsp;*** Ecart ***<br />
ITMAN &nbsp; &nbsp; &nbsp; &nbsp; SMITH &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,622 &nbsp; &nbsp; &nbsp; &nbsp;*** Ecart ***<br />
JERALDINE &nbsp; &nbsp; GERALDINE &nbsp; &nbsp; &nbsp;0,926 &nbsp; &nbsp; &nbsp; &nbsp; 0,926 &nbsp; &nbsp; &nbsp; &nbsp;<br />
MARHTA &nbsp; &nbsp; &nbsp; &nbsp;MARTHA &nbsp; &nbsp; &nbsp; &nbsp; 0,961 &nbsp; &nbsp; &nbsp; &nbsp; 0,961 &nbsp; &nbsp; &nbsp; &nbsp;<br />
MICHELLE &nbsp; &nbsp; &nbsp;MICHAEL &nbsp; &nbsp; &nbsp; &nbsp;0,921 &nbsp; &nbsp; &nbsp; &nbsp; 0,921 &nbsp; &nbsp; &nbsp; &nbsp;<br />
JULIES &nbsp; &nbsp; &nbsp; &nbsp;JULIUS &nbsp; &nbsp; &nbsp; &nbsp; 0,933 &nbsp; &nbsp; &nbsp; &nbsp; 0,933 &nbsp; &nbsp; &nbsp; &nbsp;<br />
TANYA &nbsp; &nbsp; &nbsp; &nbsp; TONYA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0,88 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0,88 &nbsp; &nbsp; &nbsp; &nbsp; <br />
DWAYNE &nbsp; &nbsp; &nbsp; &nbsp;DUANE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0,84 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0,84 &nbsp; &nbsp; &nbsp; &nbsp; <br />
SEAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SUSAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0,805 &nbsp; &nbsp; &nbsp; &nbsp; 0,805 &nbsp; &nbsp; &nbsp; &nbsp;<br />
JON &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JOHN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,933 &nbsp; &nbsp; &nbsp; &nbsp; 0,933 &nbsp; &nbsp; &nbsp; &nbsp;<br />
JON &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*** Ecart ***<br />
DIXON &nbsp; &nbsp; &nbsp; &nbsp; DICKSONX &nbsp; &nbsp; &nbsp; 0,813 &nbsp; &nbsp; &nbsp; &nbsp; 0,813 &nbsp; &nbsp; &nbsp; &nbsp;<br />
VOYAGE &nbsp; &nbsp; &nbsp; &nbsp;AGENDA &nbsp; &nbsp; &nbsp; &nbsp; 0,444 &nbsp; &nbsp; &nbsp; &nbsp; 0,444 &nbsp; &nbsp; &nbsp; &nbsp;<br />
TRAVEL &nbsp; &nbsp; &nbsp; &nbsp;TRAIN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0,9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,79 &nbsp; &nbsp; &nbsp; &nbsp; *** Ecart ***<br />
ABCVWXYZ &nbsp; &nbsp; &nbsp;CABVWXYZ &nbsp; &nbsp; &nbsp; 0,958 &nbsp; &nbsp; &nbsp; &nbsp; 0,958</div></div>
<p>&nbsp;<br />
Les distances obtenues sont parfois différentes des distances attendues (4 écarts constatés).<br />
Concernant les couples <strong>HARDIN/MARTINEZ, ITMAN/SMITH, JON/JAN</strong>, ils sont fournis par W. E. Winkler qui devait utiliser un algo un peu différent de celui décrit dans Wikipédia (en effet, sa fonction strcomp.c est plus complexe&#8230;)</p>
<p>Concernant le couple <strong>TRAVEL/TRAIN</strong> et la distance attendue de 0,9, je pense qu&rsquo;il s&rsquo;agit d&rsquo;une coquille de l&rsquo;auteur car la distance de Jaro dans la même publication était seulement de 0,7.</p>
<p>De plus, l&rsquo;applet java de <a href="http://arantxa.ii.uam.es/~dcamacho/StringDistance/StringDistance.htm" title="String Distance" target="_blank">ce site</a> donne des résultats proches ou identiques aux miens.</p>
<p><strong>Remarque</strong><br />
L&rsquo;éloignement maximal (variable dMax dans mon code) devrait être calculé à l&rsquo;aide de la plus grande longueur de chaîne. J&rsquo;ai préféré utiliser la plus courte pour éviter des résultats &lsquo;étonnants&rsquo; avec certaines chaînes de caractères.<br />
Par exemple, en allongeant la seconde chaîne &lsquo;cba&rsquo; et en utilisant la plus grande longueur des deux chaînes de caractères, on obtient :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">?JaroWinkler(<span style="color: #800000;">&quot;abc&quot;</span>,<span style="color: #800000;">&quot;cba&quot;</span>) <span style="color: #008000;">'0,556<br />
</span>?JaroWinkler(<span style="color: #800000;">&quot;abc&quot;</span>,<span style="color: #800000;">&quot;cbau&quot;</span>) <span style="color: #008000;">'0,528<br />
</span>?JaroWinkler(<span style="color: #800000;">&quot;abc&quot;</span>,<span style="color: #800000;">&quot;cbauu&quot;</span>) <span style="color: #008000;">'0,756<br />
</span>?JaroWinkler(<span style="color: #800000;">&quot;abc&quot;</span>,<span style="color: #800000;">&quot;cbauuu&quot;</span>) '0,722</div></div>
<p>La similarité diminue avec 4 caractères (0,528) puis augmente paradoxalement avec 5 caractères (&lsquo;cbauu&rsquo; donne 0,756)!<br />
<strong>Pourquoi ?</strong><br />
<strong>Dans le 1er exemple</strong>, l&rsquo;éloignement maximal (variable dMax dans le code) est égal à 1 et on obtient une seule concordance (lettre &lsquo;b&rsquo;) entre les 2 chaînes.<br />
<strong>Dans le 2ème exemple</strong>, la similarité chute légèrement car la longueur de la chaîne n°2 est de 4 au lieu de 3 et celle-ci intervient en tant que dénominateur dans le calcul de la distance de Jaro. L&rsquo;éloignement maximal reste égal à 1.<br />
<strong>Dans le 3ème exemple</strong>, l&rsquo;éloignement maximal est égal à <strong>2</strong> car la longueur de la chaîne n°2 est de 5 caractères (arrondi supérieur de 5/2 &#8211; 1 = 2). Cet éloignement permet d&rsquo;obtenir 3 correspondances (&lsquo;a&rsquo;, &lsquo;b&rsquo;, &lsquo;c&rsquo;) et une transposition (&lsquo;a&rsquo; et &lsquo;c&rsquo;). Ces 3 correspondances au lieu d&rsquo;une seule augmentent la similarité malgré la transposition et la longueur de la chaîne n°2.</p>
<p><strong>Pour éviter ce problème</strong>, une solution consiste donc à utiliser la plus petite longueur des deux chaînes :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">?JaroWinkler(<span style="color: #800000;">&quot;abc&quot;</span>,<span style="color: #800000;">&quot;cba&quot;</span>) <span style="color: #008000;">'0,556<br />
</span>?JaroWinkler(<span style="color: #800000;">&quot;abc&quot;</span>,<span style="color: #800000;">&quot;cbau&quot;</span>) <span style="color: #008000;">'0,528<br />
</span>?JaroWinkler(<span style="color: #800000;">&quot;abc&quot;</span>,<span style="color: #800000;">&quot;cbauu&quot;</span>) <span style="color: #008000;">'0,511<br />
</span>?JaroWinkler(<span style="color: #800000;">&quot;abc&quot;</span>,<span style="color: #800000;">&quot;cbauuu&quot;</span>) '0,5</div></div>
<p>&nbsp;<br />
<strong>Conclusion</strong><br />
Algorithme rapide et efficace sur des chaînes relativement courtes.</p>
<p><strong>Références</strong><br />
Wikipédia: <a href="http://fr.wikipedia.org/wiki/Distance_de_Jaro-Winkler" title="Jaro_Winkler sur Wikipédia" target="_blank">Distance de Jaro-Winkler</a><br />
Publication de <a href="http://www.census.gov/srd/papers/pdf/rrs2006-02.pdf" title="Overview of Record Linkage and Current Research Directions" target="_blank">W. E. Winkler</a>.</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Indices de similarité entre deux chaînes de caractères</title>
		<link>https://blog.developpez.com/philben/p11340/vba-access/indices-de-similarite-entre-deux-chaines-de-caracteres</link>
		<comments>https://blog.developpez.com/philben/p11340/vba-access/indices-de-similarite-entre-deux-chaines-de-caracteres#comments</comments>
		<pubDate>Mon, 24 Sep 2012 00:32:03 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Similarité]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/philben/?p=319</guid>
		<description><![CDATA[Après l&#8217;algorithme de Damerau-Levenshtein qui mesure la distance minimale d&#8217;édition entre deux textes, je présente un algorithme plus simple et donc plus rapide qui calcule différents indices de similarité (Cosinus, Dice, Jaccard, Kulczynski,&#8230;) à partir de n-grammes (n-grams/q-grams en anglais) &#8230; <a href="https://blog.developpez.com/philben/p11340/vba-access/indices-de-similarite-entre-deux-chaines-de-caracteres">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Après l&rsquo;algorithme de <a href="http://blog.developpez.com/philben/?p=19" title="Damerau-Levenshtein">Damerau-Levenshtein</a> qui mesure la distance minimale d&rsquo;édition entre deux textes, je présente un algorithme plus simple et donc plus rapide qui calcule différents indices de similarité (Cosinus, Dice, Jaccard, Kulczynski,&#8230;) à partir de n-grammes (n-grams/q-grams en anglais) ou sous-séquences continues de caractères.<br />
<span id="more-319"></span><br />
<strong>Les fonctions</strong><br />
Placer l&rsquo;ensemble du code suivant dans un module standard.<br />
&nbsp;<br />
L&rsquo;énumération pour faciliter le choix du coefficient de similarité :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #F660AB; font-weight: bold;">Enum</span> eIndiceSimilarite<br />
&nbsp; &nbsp;eCosinus = 1<br />
&nbsp; &nbsp;eDice = 2<br />
&nbsp; &nbsp;eJaccard = 3<br />
&nbsp; &nbsp;eKulczynski = 4<br />
&nbsp; &nbsp;eBraunBlanquet = 5<br />
&nbsp; &nbsp;eSimpson = 6<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #F660AB; font-weight: bold;">Enum</span></div></div>
<p>&nbsp;<br />
La fonction Ngram appelée par la fonction principale pour créer les grammes de la chaîne :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Private</span> <span style="color: #E56717; font-weight: bold;">Function</span> Ngram(<span style="color: #151B8D; font-weight: bold;">ByRef</span> qgs() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> s <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> Q <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> InversionGram <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, n <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, Fin <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> Q &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> Q &gt; 1 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> InversionGram <span style="color: #8D38C9; font-weight: bold;">Then</span> Fin = vbVerticalTab <span style="color: #8D38C9; font-weight: bold;">Else</span>: Fin = vbFormFeed<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;s = <span style="color: #F660AB; font-weight: bold;">String</span>(Q - 1, vbVerticalTab) &amp; s &amp; <span style="color: #F660AB; font-weight: bold;">String</span>(Q - 1, Fin)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; n = Len(s) - Q: <span style="color: #151B8D; font-weight: bold;">ReDim</span> qgs(0 <span style="color: #8D38C9; font-weight: bold;">To</span> n)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 0 <span style="color: #8D38C9; font-weight: bold;">To</span> n: qgs(i) = Mid$(s, i + 1, Q): <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
&nbsp; &nbsp; &nbsp; Ngram = n + 1<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span><br />
&nbsp; &nbsp; &nbsp; qgs = Split(s, <span style="color: #800000;">&quot; &quot;</span>, , vbBinaryCompare)<br />
&nbsp; &nbsp; &nbsp; Ngram = <span style="color: #151B8D; font-weight: bold;">UBound</span>(qgs) + 1<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
La fonction principale :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> IndiceSimilarite(<span style="color: #151B8D; font-weight: bold;">ByVal</span> s1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> s2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Indice <span style="color: #151B8D; font-weight: bold;">As</span> eIndiceSimilarite = eIndiceSimilarite.eDice, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> TypeNgram <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> = 1, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> InversionGram <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">False</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> MaxDistance <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> = -1, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> TypeComparaison <span style="color: #151B8D; font-weight: bold;">As</span> VbCompareMethod = vbBinaryCompare) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Single</span><br />
<span style="color: #008000;">'Retourne un indice de similarité [0 à 1] entre deux phrases<br />
</span><span style="color: #008000;">'Options : Indice : Choix de l'indice calculé (Cosinus, Dice, Jaccard, Kulczynski, BraunBlanquet)<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp;: TypeNgram : longueur des sous-séquences (0 : mot, 1 = caractère,...,5)<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp;: InversionGram : Recherche une inversion du gram :'ch' -&gt; 'hc' (sauf pour TypeNgram = 1 !)<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp;: MaxDistance : distance maximum (en gram) de recherche (-1 = pas de limite)<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp;: TypeComparaison : binaire ou textuelle<br />
</span><span style="color: #008000;">'Remarque: parfois nécessaire de prétraiter les chaînes (ucase(),trim(),sans diacritique,...)<br />
</span><span style="color: #008000;">'Auteur : Philben - v1.0 - Free to use<br />
</span><br />
&nbsp; &nbsp;Const cMaxLen <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 256&amp;, cMinNgram <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> = 0, cMaxNgram <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> = 5<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> l1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, l2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, j <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, jMin <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, jMax <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> c <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, n <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, n1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, n2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> aq1() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, aq2() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, q1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, q1Inv <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, Idx <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Single</span>, Res <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span><br />
<br />
&nbsp; &nbsp;l1 = Len(s1): l2 = Len(s2)<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> l1 &gt;= 1 <span style="color: #8D38C9; font-weight: bold;">And</span> l2 &gt;= 1 <span style="color: #8D38C9; font-weight: bold;">And</span> l1 &lt;= cMaxLen <span style="color: #8D38C9; font-weight: bold;">And</span> l2 &lt;= cMaxLen <span style="color: #8D38C9; font-weight: bold;">And</span> TypeNgram &gt;= cMinNgram <span style="color: #8D38C9; font-weight: bold;">And</span> TypeNgram &lt;= cMaxNgram <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> TypeNgram = 1 <span style="color: #8D38C9; font-weight: bold;">And</span> InversionGram <span style="color: #8D38C9; font-weight: bold;">Then</span> InversionGram = <span style="color: #00C2FF; font-weight: bold;">False</span><br />
<br />
&nbsp; &nbsp; &nbsp; n1 = Ngram(aq1, s1, TypeNgram, InversionGram)<br />
&nbsp; &nbsp; &nbsp; n2 = Ngram(aq2, s2, TypeNgram, InversionGram)<br />
&nbsp; &nbsp; &nbsp; n = n2 - 1<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 0 <span style="color: #8D38C9; font-weight: bold;">To</span> n1 - 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;q1 = aq1(i)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> InversionGram <span style="color: #8D38C9; font-weight: bold;">Then</span> q1Inv = StrReverse(q1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jMin = 0: jMax = n<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> MaxDistance &gt; -1 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> i &gt; MaxDistance <span style="color: #8D38C9; font-weight: bold;">Then</span> jMin = i - MaxDistance<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> jMax &gt; i + MaxDistance <span style="color: #8D38C9; font-weight: bold;">Then</span> jMax = i + MaxDistance<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> j = jMin <span style="color: #8D38C9; font-weight: bold;">To</span> jMax<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> aq2(j) &lt;&gt; vbNullString <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Res = (StrComp(q1, aq2(j), TypeComparaison) = 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> Res <span style="color: #8D38C9; font-weight: bold;">And</span> InversionGram <span style="color: #8D38C9; font-weight: bold;">Then</span> Res = (StrComp(q1Inv, aq2(j), TypeComparaison) = 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> Res <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = c + 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; aq2(j) = vbNullString<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #E56717; font-weight: bold;">Exit</span> <span style="color: #8D38C9; font-weight: bold;">For</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> j<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Select</span> <span style="color: #8D38C9; font-weight: bold;">Case</span> Indice<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> eCosinus &nbsp; <span style="color: #008000;">'Ochiai, Otsuka<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; Idx = c / Sqr(CLng(n1) * n2) &nbsp; <span style="color: #008000;">'Cast pour éviter un overflow<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Case</span> eDice &nbsp; <span style="color: #008000;">'Pirlot's index, Sorensen, Tversky (alpha=beta=0.5), ~Czekanowski<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; Idx = 2 * c / (n1 + n2)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> eJaccard &nbsp; <span style="color: #008000;">'Tversky (alpha=beta=1), ~Tanimoto<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; Idx = c / (n1 + n2 - c)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> eKulczynski &nbsp; <span style="color: #008000;">'2nd coeff<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; Idx = 0.5 * (c / n1 + c / n2)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> eBraunBlanquet &nbsp; <span style="color: #008000;">'c/max(n1,n2)<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> n1 &gt;= n2 <span style="color: #8D38C9; font-weight: bold;">Then</span> Idx = c / n1 <span style="color: #8D38C9; font-weight: bold;">Else</span> Idx = c / n2<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> eSimpson &nbsp; <span style="color: #008000;">'c/min(n1,n2)<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> n1 &lt;= n2 <span style="color: #8D38C9; font-weight: bold;">Then</span> Idx = c / n1 <span style="color: #8D38C9; font-weight: bold;">Else</span> Idx = c / n2<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">Select</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span><br />
&nbsp; &nbsp; &nbsp; Idx = -1<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp;IndiceSimilarite = Idx<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Définition</strong><br />
Un gramme (ou gram en anglais) est une sous-séquences continues de caractères de la chaîne.<br />
&nbsp;<br />
<strong>Explications</strong><br />
Cette fonction ne mesure pas une distance entre les deux chaînes, elle compte seulement les grammes communs entre les deux chaînes S1 et S2.  Ce compte est ensuite divisé par un coefficient qui distingue les indices entre eux : Ce dénominateur peut être la moyenne géométrique du nombre de n-grams (n1 et n2), la moyenne arithmétique, le nombre maxi, mini&#8230;<br />
Le choix des indices est :</p>
<ul>
<li>Cosinus (équivalence : coefficients de Ochiai et de Otsuka)</li>
<li>Dice (équivalence : Pirlot&rsquo;s index, Sorensen, Tversky (alpha=beta=0.5), ~Czekanowski)</li>
<li>Jaccard (équivalence : Tversky (alpha=beta=1), ~Tanimoto)</li>
<li>Kulczynski (son second coefficient)</li>
<li>Braun-Blanquet (dénominateur : max(n1,n2))</li>
<li>Simpson (dénominateur : min(n1,n2))</li>
</ul>
<p>Si le nombre de n-grams est identique entre les deux chaînes, les indices retournent la même valeur mis à part l&rsquo;index de Jaccard. Par défaut le coefficient de Dice est utilisé.</p>
<p>La longueur des sous-séquences (paramètre <strong>TypeNgram</strong>) peut varier entre 0 et 5. Zéro indique qu&rsquo;un n-gramme correspond à un mot, 1-gramme ou unigramme correspond à chaque caractère de la chaîne, 2-gramme ou bigramme est composé de deux caractères, jusqu&rsquo;à 5-grammes. Au-dessus de 5-grammes la Prévention Informatique ne conseille pas de prendre le clavier !<br />
Par exemple, les bigrammes de &lsquo;abc&rsquo; seront &lsquo;%a&rsquo;, &lsquo;ab&rsquo;, &lsquo;bc&rsquo; et &lsquo;c#&rsquo; avec % et # des caractères non utilisés.</p>
<p>Le paramètre suivant (<strong>InversionGram</strong>) autorise ou non de compter un gramme inversé. Par exemple, &lsquo;ab&rsquo; et &lsquo;ba&rsquo; seront communs si InversionGram = True.</p>
<p>Le paramètre <strong>MaxDistance</strong> définit ou non une distance maximale (en valeur absolue) entre deux grammes communs. Si deux grammes communs sont trop éloignés, ils ne seront pas comptabilisés. Par exemple, la similarité calculée est égale à 0 si les chaînes sont &lsquo;ab&rsquo; et &lsquo;ba&rsquo; avec n-gram=1 et une distance maxi de zéro. Aucune limite de distance n&rsquo;est définie si MaxDistance = -1.</p>
<p>Enfin, le dernier paramètre définit le type de comparaison entre les deux chaînes (binaire ou textuelle).</p>
<p>Ces indices et celui de Damerau-Levenshtein n&rsquo;ont pas une réelle corrélation car ils ne mesurent pas la même chose.</p>
<p><strong>Exemples</strong><br />
Des anagrammes qui retournent un indice de similarité parfait (1) :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">?IndiceSimilarite(<span style="color: #800000;">&quot;la crise economique&quot;</span>,<span style="color: #800000;">&quot;le scenario comique&quot;</span>)<br />
?IndiceSimilarite(<span style="color: #800000;">&quot;mammifere&quot;</span>,<span style="color: #800000;">&quot;mari femme&quot;</span>,eIndiceSimilarite.eSimpson)<br />
?IndiceSimilarite(<span style="color: #800000;">&quot;pascal obispo&quot;</span>,<span style="color: #800000;">&quot;pablo picasso&quot;</span>)<br />
?IndiceSimilarite(<span style="color: #800000;">&quot;stromae&quot;</span>,<span style="color: #800000;">&quot;maestro&quot;</span>)</div></div>
<p>Dans le deuxième exemple, on utilise l&rsquo;indice de Simpson car il divise le nombre de grammes communs par le plus petit nombre de n-grams entre n1 et n2 ce qui permet d&rsquo;obtenir un indice égal à 1.<br />
&nbsp;<br />
Via une requête SQL, une recherche d&rsquo;anagrammes sur des mots de 12 lettres dans une table a donné (après suppression des accents) :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Tactiquement Acquittement<br />
Conversation Conservation<br />
Premierement Empierrement<br />
Horticulture Horticulteur<br />
Resurrection Reconstruire<br />
Ternissement Ressentiment<br />
Egalisatrice Eclairagiste<br />
Photogravure Photograveur</div></div>
<p>&nbsp;<br />
Si on reprend l&rsquo;exemple de &lsquo;pascal obispo&rsquo; mais avec des bigrammes, l&rsquo;indice tombe à 0,36 et remonte à 0,43 si on autorise les inversions car &lsquo;&#8230; o&#8230;&rsquo; est commun à &lsquo;&#8230;o &#8230;&rsquo; de &lsquo;Pablo Picasso&rsquo;. L&rsquo;indice chute à 0,2 avec des trigrammes.</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">?IndiceSimilarite(<span style="color: #800000;">&quot;pascal obispo&quot;</span>,<span style="color: #800000;">&quot;pablo picasso&quot;</span>,,2)<br />
?IndiceSimilarite(<span style="color: #800000;">&quot;pascal obispo&quot;</span>,<span style="color: #800000;">&quot;pablo picasso&quot;</span>,,2,<span style="color: #00C2FF; font-weight: bold;">True</span>)<br />
?IndiceSimilarite(<span style="color: #800000;">&quot;pascal obispo&quot;</span>,<span style="color: #800000;">&quot;pablo picasso&quot;</span>,,3,<span style="color: #00C2FF; font-weight: bold;">True</span>)</div></div>
<p>On peut aussi jouer sur la distance maxi pour modifier sensiblement le résultat :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>) <span style="color: #008000;">'1<br />
</span>?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>,,,,2) <span style="color: #008000;">'1<br />
</span>?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>,,,,1) <span style="color: #008000;">'0,78<br />
</span>?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>,,,,0) <span style="color: #008000;">'0,56<br />
</span>?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>,,2,<span style="color: #00C2FF; font-weight: bold;">True</span>) <span style="color: #008000;">'1<br />
</span>?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>,,2,<span style="color: #00C2FF; font-weight: bold;">False</span>) <span style="color: #008000;">'0,3<br />
</span>?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>,,2,<span style="color: #00C2FF; font-weight: bold;">True</span>,2) <span style="color: #008000;">'0,8<br />
</span>?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>,,2,<span style="color: #00C2FF; font-weight: bold;">True</span>,0) <span style="color: #008000;">'0,4<br />
</span>?IndiceSimilarite(<span style="color: #800000;">&quot;rehcehcre&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>,,3,<span style="color: #00C2FF; font-weight: bold;">True</span>,0) '0,36</div></div>
<p>&nbsp;<br />
<strong>Performance</strong><br />
Cette fonction semble être 5 à 6 fois plus rapide que la fonction de Damerau-Levenshtein. Le principe mis en jeu est différent et les différentes possibilités de réglages permettent d&rsquo;adapter l&rsquo;algorithme à de nombreux cas de figures.</p>
<p>Voir aussi le billet sur la <a href="http://blog.developpez.com/philben/p12207/vba-access/vba-distance-de-jaro-winkler" title="VBA : Distance de Jaro-Winkler" target="_blank">distance de Jaro-Winkler</a>.</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Transformer le nom d&#8217;un mois de l&#8217;année ou son abréviation en son numéro</title>
		<link>https://blog.developpez.com/philben/p11335/vba-access/transformer-le-nom-dun-mois-de-lannee-ou-son-abreviation-en-son-numero</link>
		<comments>https://blog.developpez.com/philben/p11335/vba-access/transformer-le-nom-dun-mois-de-lannee-ou-son-abreviation-en-son-numero#comments</comments>
		<pubDate>Sat, 22 Sep 2012 10:19:26 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Date]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/philben/?p=264</guid>
		<description><![CDATA[Je vous propose une petite fonction VBA pour convertir le nom d&#8217;un mois de l&#8217;année en son numéro. Les noms/abréviations sont composés au minimum de 2 lettres, écrits en français ou en anglais. Le nom des mois L&#8217;abréviation à une &#8230; <a href="https://blog.developpez.com/philben/p11335/vba-access/transformer-le-nom-dun-mois-de-lannee-ou-son-abreviation-en-son-numero">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Je vous propose une petite fonction VBA pour convertir le nom d&rsquo;un mois de l&rsquo;année en son numéro. Les noms/abréviations sont composés au minimum de 2 lettres, écrits en français ou en anglais.<br />
<span id="more-264"></span><br />
<strong>Le nom des mois</strong><br />
L&rsquo;abréviation à <strong>une lettre </strong>(J F M A M J J A S O N D), prise individuellement, ne permet pas de distinguer certains mois comme &lsquo;Janvier&rsquo; et &lsquo;Juin&rsquo; (non implémentée ici).<br />
Les abréviations à <strong>deux lettres </strong>permettent cette distinction, soit en utilisant la première et la dernière lettre du mois (JR FR MS AL MI JN JT AT&#8230;) pour le codage à 2 caractères, soit en utilisant la première lettre du nom et une autre lettre du nom anglais (JA FE MR AL MA JN JL AU&#8230;) pour le codage bilingue.<br />
L&rsquo;abréviation à <strong>trois caractères </strong>correspond aux 3 premiers caractères du nom (sauf pour Juin et Juillet) et les accents sont conservés (JAN FÉV MAR AVR MAI JUN JUL AOÛ&#8230;)<br />
Les abréviations de <strong>longueur variable</strong> correspondent aux premiers caractères du nom suivi d&rsquo;un point dans le cas d&rsquo;une troncation (Janv. Févr. Mars Avr. Mai Juin Juill. Août&#8230;).<br />
Voir <a href="http://fr.wikipedia.org/wiki/Mois" title="Wikipedia : Les mois de l'année" target="_blank">ici</a> pour en savoir plus sur les mois.<br />
&nbsp;<br />
<strong>La fonction en VBA</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> NumMois(<span style="color: #151B8D; font-weight: bold;">ByVal</span> Mois <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span><br />
<span style="color: #008000;">'Retourne le numéro mois (abréviation ou non, français ou anglais) passé en paramètre<br />
</span><span style="color: #008000;">'Auteur : Philben - v1.0 - Free to use<br />
</span><span style="color: #008000;">'Exemples : NumMois(&quot;at&quot;)/NumMois(&quot;au&quot;)/NumMois(&quot;aou&quot;)/NumMois(&quot;aout&quot;)/NumMois(&quot;aug&quot;) -&gt; n°8 (Août)<br />
</span><span style="color: #008000;">'références : http://fr.wikipedia.org/wiki/Mois<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : http://66.46.185.79/bdl/gabarit_bdl.asp?Th=3&amp;id=3619<br />
</span><br />
&nbsp; &nbsp;<span style="color: #008000;">'Seuls É et Û sont présents dans le nom des mois, mais recherche élargie au cas où:<br />
</span> &nbsp; &nbsp;Const cAvecAccent <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;ÀÁÂÄÇÈÉÊËÌÍÎÏÒÓÔÖÙÚÛÜ&quot;</span><br />
&nbsp; &nbsp;Const cSansAccent <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;AAAACEEEEIIIIOOOOUUUU&quot;</span><br />
&nbsp; &nbsp;Const cCode3Car <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;JAN FEV MAR AVR MAI JUN JUL AOU SEP OCT NOV DEC JAN FEB MAR APR MAY JUN JUL AUG&quot;</span><br />
&nbsp; &nbsp;Const cCode2Car <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;JRFRMSALMIJNJTATSEOENEDEJAFEMRALMAJNJLAUSEOCNODE&quot;</span><br />
&nbsp; &nbsp;Const cEspace <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot; &quot;</span>, cJUI <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;JUI&quot;</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> l <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, p <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, f <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span><br />
<br />
&nbsp; &nbsp;Mois = UCase$(Left$(Trim$(Mois), 4))<br />
&nbsp; &nbsp;<span style="color: #008000;">'supprime les espaces intra-chaîne pour ne pas fausser les étapes suivantes<br />
</span> &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> InStr(1, Mois, cEspace, vbBinaryCompare) &lt;&gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> Mois = Replace(Mois, cEspace, vbNullString, , , vbBinaryCompare)<br />
<br />
&nbsp; &nbsp;l = Len(Mois)<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> l &gt; 1 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> l &nbsp; <span style="color: #008000;">'Supprime les accents - 4 boucles au maximum<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; f = Mid$(Mois, i, 1)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p = InStr(1, cAvecAccent, f, vbBinaryCompare)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> p &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> Mois = Replace(Mois, f, Mid$(cSansAccent, p, 1), , , vbBinaryCompare)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> l &gt; 2 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;f = Left$(Mois, 3)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p = InStr(1, cCode3Car, f, vbBinaryCompare)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> p = 0 <span style="color: #8D38C9; font-weight: bold;">And</span> l &gt; 3 <span style="color: #8D38C9; font-weight: bold;">Then</span> &nbsp; <span style="color: #008000;">'si non trouvé, recherche Juin/Juillet<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> StrComp(f, cJUI, vbBinaryCompare) = 0 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p = InStr(1, cCode3Car, Left$(Mois, 2) &amp; Mid$(Mois, 4, 1), vbBinaryCompare)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;l = 4<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Else</span> &nbsp; <span style="color: #008000;">'si longueur de la chaîne est strictement égale à 2<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; p = InStr(1, cCode2Car, Mois, vbBinaryCompare)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> (p <span style="color: #8D38C9; font-weight: bold;">And</span> 1) = 1 <span style="color: #8D38C9; font-weight: bold;">Then</span> &nbsp; <span style="color: #008000;">'une correspondance a été trouvée<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; NumMois = Int(p / l) + 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> NumMois &gt; 12 <span style="color: #8D38C9; font-weight: bold;">Then</span> NumMois = (NumMois - 1) <span style="color: #151B8D; font-weight: bold;">Mod</span> 12 + 1<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Explications</strong><br />
<strong>Les premières étapes </strong>consistent à formater le nom du mois pour réduire son espace de liberté et faciliter ainsi la transformation. On ne conserve que les 4 premiers caractères du nom qui doivent permettre une identification sans ambiguïté. Ces caractères sont tranformés en lettres capitales pour réaliser par la suite des recherches/remplacements/comparaisons binaires.<br />
Cette première étape consiste aussi à supprimer les espaces et à retirer les accents en balayant large pour tenir compte des fautes de frappes&#8230;</p>
<p><strong>Deuxième étape :</strong> Suivant la longueur du nom/abréviation du mois, on distingue ensuite deux cas pour ne pas interférer entre les abréviations à deux lettres et le reste.<br />
Concernant les abréviations à 2 lettres, on recherche simplement sa présence dans une chaîne constante &lsquo;cCode2Car&rsquo; qui les contient toutes. La fonction InStr() renvoie la position de l&rsquo;abréviation dans la constante ou 0.<br />
Pour les autres abréviations, le principe est le même en utilisant la constante &lsquo;cCode3Car&rsquo;. Pour distinguer le mois de Juin du mois de Juillet et seulement pour ces deux mois , il est parfois nécessaire d&rsquo;analyser la 4ème lettre (&lsquo;N&rsquo; ou &lsquo;L&rsquo;).<br />
Après cette étape, on a donc une position du nom (variable p) dans les chaînes constantes ou 0 si le nom n&rsquo;est pas trouvé.</p>
<p><strong>La troisième et dernière étape </strong>de la fonction consiste, premièrement, à vérifier que la position existe et qu&rsquo;elle soit conforme. Conforme veut dire que la première lettre du mois correspond bien à la première lettre d&rsquo;une abréviation pour éviter par exemple que le mois &lsquo;RF&rsquo; qui est sans signification soit interprété comme le mois de janvier. En effet, la constante &lsquo;cCode2Car&rsquo; contient le motif &lsquo;RF&rsquo; (J<strong>RF</strong>RMS&#8230;)<br />
Pour ce faire, chaque abréviation dans les constantes commence à une position impaire, il suffit alors de vérifier que la position trouvée est bien impaire en vérifiant que le reste de la division par 2 est égal à 1 <code class="codecolorer vb blackboard"><span class="vb"><span style="color: #8D38C9; font-weight: bold;">If</span> (p <span style="color: #8D38C9; font-weight: bold;">And</span> 1) = 1 <span style="color: #8D38C9; font-weight: bold;">Then</span> ...</span></code>.<br />
Le numéro du mois correspondant est calculé en divisant la position par la longueur des motifs + 1.<br />
Le numéro de mois calculé peut être supérieur à 12 car les chaînes de constante contiennent plus de 12 motifs chacune. On retourne dans ce cas le reste de la division par 12 pour obtenir le bon numéro <code class="codecolorer vb blackboard"><span class="vb"><span style="color: #8D38C9; font-weight: bold;">If</span> NumMois &gt; 12 <span style="color: #8D38C9; font-weight: bold;">Then</span> NumMois = (NumMois - 1) <span style="color: #151B8D; font-weight: bold;">Mod</span> 12 + 1</span></code>.<br />
&nbsp;<br />
<strong>Test de la fonction</strong><br />
La fonction suivante contrôle que les abréviations sont bien reconnues et qu&rsquo;il n&rsquo;existe pas d&rsquo;interférence (&lsquo;RF&rsquo;, &lsquo;AN F&rsquo;, &#8230;)</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> TestMois()<br />
&nbsp; &nbsp;Const cCode3Car <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;JAN FEV MAR AVR MAI JUN JUL AOU SEP OCT NOV DEC JAN FEB MAR APR MAY JUN JUL AUG&quot;</span><br />
&nbsp; &nbsp;Const cCode2Car <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;JRFRMSALMIJNJTATSEOENEDEJAFEMRALMAJNJLAUSEOCNODE&quot;</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, j <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, k <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, l <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, n <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> c <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, m <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span><br />
<br />
&nbsp; &nbsp;Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Mois&quot;</span>, <span style="color: #800000;">&quot;Théorique&quot;</span>, <span style="color: #800000;">&quot;Calculé&quot;</span>, <span style="color: #800000;">&quot;Conforme ?&quot;</span><br />
&nbsp; &nbsp;c = cCode2Car<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = 2 <span style="color: #8D38C9; font-weight: bold;">To</span> 4 <span style="color: #8D38C9; font-weight: bold;">Step</span> 2<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> j = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> 2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> k = j <span style="color: #8D38C9; font-weight: bold;">To</span> Len(c) <span style="color: #8D38C9; font-weight: bold;">Step</span> i<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m = Mid$(c, k, i)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; l = NumMois(m)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; n = n + 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> n &gt; 12 <span style="color: #8D38C9; font-weight: bold;">Then</span> n = 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> m, n, l, IIf(l = 0, <span style="color: #800000;">&quot;?&quot;</span>, l = n)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> k<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> j<br />
&nbsp; &nbsp; &nbsp; n = 0<br />
&nbsp; &nbsp; &nbsp; c = cCode3Car<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
Résultat attendu :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Mois &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Théorique &nbsp; &nbsp; Calculé &nbsp; &nbsp; &nbsp; Conforme ?<br />
JR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
FR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
MS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
AL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
MI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
JN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
JT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
AT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
SE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
OE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
NE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
DE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
JA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
FE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
MR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
AL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
MA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
JN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
JL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
AU &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
SE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
OC &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
NO &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
DE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
RF &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
RM &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
SA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
LM &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
IJ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
NJ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
TA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
TS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EO &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
ED &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EJ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
AF &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EM &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
RA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
LM &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
AJ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
NJ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
LA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
US &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EO &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
CN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
OD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
JAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
FEV &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
MAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
AVR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
MAI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
JUN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
JUL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
AOU &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
SEP &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
OCT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
NOV &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
DEC &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vrai<br />
JAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
FEB &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
MAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
APR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
MAY &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
JUN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
JUL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
AUG &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Vrai<br />
AN F &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EV M &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
AR A &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
VR M &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
AI J &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
UN J &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
UL A &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
OU S &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EP O &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
CT N &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
OV D &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EC J &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
AN F &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
EB M &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
AR A &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
PR M &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
AY J &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
UN J &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
UL A &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?<br />
UG &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;?</div></div>
<p>&nbsp;<br />
<strong>Exemples</strong><br />
N° de &lsquo;Décembre&rsquo; : <code class="codecolorer vb blackboard"><span class="vb">?NumMois(<span style="color: #800000;">&quot;décembre&quot;</span>) '12</span></code><br />
N° de &lsquo;Dèçënbre&rsquo; (avec fautes !) : <code class="codecolorer vb blackboard"><span class="vb">?NumMois(<span style="color: #800000;">&quot;Dèçënbre&quot;</span>) '12</span></code><br />
N° de &lsquo;February&rsquo; : <code class="codecolorer vb blackboard"><span class="vb">?NumMois(<span style="color: #800000;">&quot;February&quot;</span>) '2</span></code><br />
N° de &lsquo;Aug&rsquo; : <code class="codecolorer vb blackboard"><span class="vb">?NumMois(<span style="color: #800000;">&quot;Aug&quot;</span>) '8 - Août</span></code><br />
N° de &lsquo; D e&rsquo; : <code class="codecolorer vb blackboard"><span class="vb">?NumMois(<span style="color: #800000;">&quot; D e&quot;</span>) '12 - Décembre</span></code><br />
N° de &lsquo;JT&rsquo; : <code class="codecolorer vb blackboard"><span class="vb">?NumMois(<span style="color: #800000;">&quot;JT&quot;</span>) '7 - Juillet</span></code><br />
N° de &lsquo;JM&rsquo; : <code class="codecolorer vb blackboard"><span class="vb">?NumMois(<span style="color: #800000;">&quot;JM&quot;</span>) '0 - abréviation non reconnue</span></code><br />
N° de &lsquo;Marche pied&rsquo; : <code class="codecolorer vb blackboard"><span class="vb">?NumMois(<span style="color: #800000;">&quot;Marche pied&quot;</span>) '3 - Mars !!!</span></code><br />
&nbsp;<br />
<strong>Performance</strong><br />
Compter au mieux 0,1 seconde pour 100 000 appels et 3 ou 5 fois plus de temps si présence de lettres accentuées.</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Transposer des lignes en une colonne</title>
		<link>https://blog.developpez.com/philben/p11320/vba-access/transposer-des-lignes-en-une-colonne</link>
		<comments>https://blog.developpez.com/philben/p11320/vba-access/transposer-des-lignes-en-une-colonne#comments</comments>
		<pubDate>Sun, 16 Sep 2012 08:34:58 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Requête SQL]]></category>
		<category><![CDATA[Transposer]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/philben/?p=193</guid>
		<description><![CDATA[On a parfois besoin de concaténer dans une colonne le contenu de plusieurs lignes d&#8217;une table ou d&#8217;une requête. Par exemple, On part de : pour arriver à : Je vous propose une fonction écrite en VBA qui réalise cette &#8230; <a href="https://blog.developpez.com/philben/p11320/vba-access/transposer-des-lignes-en-une-colonne">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>On a parfois besoin de concaténer dans une colonne le contenu de plusieurs lignes d&rsquo;une table ou d&rsquo;une requête.<br />
<span id="more-193"></span><br />
<strong>Par exemple</strong>, On part de :<br />
<img src="http://philben.developpez.com/ConcatenationTable.png" alt="Concaténation de la table" /><br />
<br />
pour arriver à :<br />
<img src="http://philben.developpez.com/ConcatenationResultat.png" alt="Résultat de la concaténation" /><br />
<br />
Je vous propose une fonction écrite en VBA qui réalise cette transposition.</p>
<p><strong>Code de la fonction VBA</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'----------------------------------------------------------------------------------------------------------<br />
</span><span style="color: #008000;">' Procédure &nbsp; &nbsp;: ConcatColonne &nbsp; [Function]<br />
</span><span style="color: #008000;">' Retour &nbsp; &nbsp; &nbsp; : String<br />
</span><span style="color: #008000;">' Auteur &nbsp; &nbsp; &nbsp; : PhilBen - Free to use<br />
</span><span style="color: #008000;">' Version &nbsp; &nbsp; &nbsp;: 1.06<br />
</span><span style="color: #008000;">' Création/Maj : Samedi 15 septembre 2012<br />
</span><span style="color: #008000;">' Objet &nbsp; &nbsp; &nbsp; &nbsp;: Permet de concaténer en lignes les données d'une colonne en fonction d'un pivot<br />
</span><span style="color: #008000;">' Arguments &nbsp; &nbsp;: - ValeurPivot : La valeur de la colonne pivot<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: - NomColonnePivot : Nom de la colonne pivot<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: - NomColonneConcat : Nom de la colonne à concaténer<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: - NomDomaine : Table ou requête des colonnes<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: - Filtre : Permet d'appliquer un filtre supplémentaire sur le domaine (&quot;&quot; pour aucun)<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: - RegrouperCompter : Regrouper (=1 ou &gt;0 et 2) ET Compter (=2) ou pas de regroupement (=0) des éléments concaténés<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: - PasVideNULL : ne retourne pas les éléments concaténés vide &quot;&quot; et NULL (=True) sinon False<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: - TriAscendant : Tri Ascendant (=True), Descendant (=False)<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: - Separateur : String qui sépare les éléments concaténés (ex: &quot;,&quot;,&quot;---&quot;,...)<br />
</span><span style="color: #008000;">' Remarques &nbsp; &nbsp;: * Cette fonction ralentit sensiblement la requête :<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-&gt; Meilleure performance si au moins la colonne pivot est indexée avec doublons<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: * Le type de la colonne pivot peut être Date, numérique, string<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: * Pour des raisons de performance, éviter de faire un filtre, un tri, <br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: &nbsp; un regroupement sur la colonne de concaténation, la déclarer si possible 'Expression' !<br />
</span><span style="color: #008000;">' Exemple &nbsp; &nbsp; &nbsp;: SELECT [MaColPivot],<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: ConcatColonne([MaColPivot],&quot;MaColPivot&quot;,&quot;MaColConcat&quot;,&quot;MaTable&quot;,&quot;&quot;,1,True,True,&quot;, &quot;)<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: FROM MaTable Group By [MaColPivot]<br />
</span><span style="color: #008000;">' Historique &nbsp; : 1.03 : Correction bug si le pivot est de type date<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: 1.04 : Complément d'information dans l'en-tête de la fonction<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: 1.05 : Correction bug si Pivot numérique avec décimales (, -&gt; .)<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: 1.06 : Ajout compte des données regroupées + modification des paramètres (type et nom)<br />
</span><span style="color: #008000;">'----------------------------------------------------------------------------------------------------------<br />
</span><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> ConcatColonne(<span style="color: #151B8D; font-weight: bold;">ByVal</span> ValeurColonnePivot <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">ByVal</span> NomColonnePivot <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">ByVal</span> NomColonneConcat <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">ByVal</span> NomDomaine <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Filtre <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = vbNullString, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> RegrouperCompter <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> = 1, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> PasVideNULL <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">True</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> TriAscendant <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">True</span>, _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Separateur <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;, &quot;</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">On</span> <span style="color: #151B8D; font-weight: bold;">Error</span> <span style="color: #8D38C9; font-weight: bold;">GoTo</span> Catch<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> oDb <span style="color: #151B8D; font-weight: bold;">As</span> DAO.Database, oRs <span style="color: #151B8D; font-weight: bold;">As</span> DAO.Recordset, sSQL <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span><br />
<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> IsNull(ValeurColonnePivot) <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> RegrouperCompter = 2 <span style="color: #8D38C9; font-weight: bold;">Then</span> &nbsp; &nbsp; &nbsp;<span style="color: #008000;">'regrouper ET compter<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; sSQL = NomColonneConcat &amp; <span style="color: #800000;">&quot; &amp; &quot;</span><span style="color: #800000;">&quot; (&quot;</span><span style="color: #800000;">&quot; &amp; &quot;</span> &amp; <span style="color: #800000;">&quot;COUNT(*)&quot;</span> &amp; <span style="color: #800000;">&quot; &amp; &quot;</span><span style="color: #800000;">&quot;)&quot;</span><span style="color: #800000;">&quot; &amp; &quot;</span> &amp; <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot;&quot;</span> &amp; Separateur &amp; <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot; As C&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sSQL = NomColonneConcat &amp; <span style="color: #800000;">&quot; &amp; &quot;</span><span style="color: #800000;">&quot;&quot;</span> &amp; Separateur &amp; <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot; As C&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; sSQL = <span style="color: #800000;">&quot;SELECT &quot;</span> &amp; sSQL &amp; <span style="color: #800000;">&quot; FROM &quot;</span> &amp; NomDomaine &amp; <span style="color: #800000;">&quot; WHERE &quot;</span> &amp; NomColonnePivot &amp; <span style="color: #800000;">&quot;=&quot;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Select</span> <span style="color: #8D38C9; font-weight: bold;">Case</span> VarType(ValeurColonnePivot)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> vbString<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sSQL = sSQL &amp; <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot;&quot;</span> &amp; ValeurColonnePivot &amp; <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> vbDate<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sSQL = sSQL &amp; Format(ValeurColonnePivot, <span style="color: #800000;">&quot;\#m-d-yyyy h:n:s\#&quot;</span>)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> <span style="color: #8D38C9; font-weight: bold;">Else</span> &nbsp; <span style="color: #008000;">'Numériques<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; sSQL = sSQL &amp; Replace(ValeurColonnePivot, <span style="color: #800000;">&quot;,&quot;</span>, <span style="color: #800000;">&quot;.&quot;</span>)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">Select</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> Filtre &lt;&gt; vbNullString <span style="color: #8D38C9; font-weight: bold;">Then</span> sSQL = sSQL &amp; <span style="color: #800000;">&quot; And &quot;</span> &amp; Filtre<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> PasVideNULL = <span style="color: #00C2FF; font-weight: bold;">True</span> <span style="color: #8D38C9; font-weight: bold;">Then</span> sSQL = sSQL &amp; <span style="color: #800000;">&quot; AND LEN(NZ(&quot;</span> &amp; NomColonneConcat &amp; <span style="color: #800000;">&quot;))&gt;0&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> RegrouperCompter &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> sSQL = sSQL &amp; <span style="color: #800000;">&quot; GROUP BY &quot;</span> &amp; NomColonneConcat<br />
&nbsp; &nbsp; &nbsp; sSQL = sSQL &amp; <span style="color: #800000;">&quot; ORDER BY &quot;</span> &amp; NomColonneConcat<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> TriAscendant <span style="color: #8D38C9; font-weight: bold;">Then</span> sSQL = sSQL &amp; <span style="color: #800000;">&quot; DESC&quot;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">'Lance la requête et concatène les lignes<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Set</span> oDb = CurrentDb<br />
&nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Set</span> oRs = oDb.OpenRecordset(sSQL, dbOpenSnapshot)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> oRs.EOF <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ConcatColonne = ConcatColonne &amp; oRs(0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oRs.MoveNext<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Loop</span> <span style="color: #8D38C9; font-weight: bold;">Until</span> oRs.EOF<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne = Left$(ConcatColonne, Len(ConcatColonne) - Len(Separateur))<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; oRs.<span style="color: #8D38C9; font-weight: bold;">Close</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
Finally:<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Set</span> oRs = <span style="color: #00C2FF; font-weight: bold;">Nothing</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Set</span> oDb = <span style="color: #00C2FF; font-weight: bold;">Nothing</span><br />
&nbsp; &nbsp;<span style="color: #E56717; font-weight: bold;">Exit</span> <span style="color: #E56717; font-weight: bold;">Function</span><br />
Catch:<br />
&nbsp; &nbsp;ConcatColonne = <span style="color: #800000;">&quot;Erreur !&quot;</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Resume</span> Finally<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Exemples d&rsquo;utilisation</strong><br />
Un collectionneur de modèles réduits, a noté consciencieusement ses achats de lots de voitures sur une feuille quadrillée. Un ami, utilisateur débutant d&rsquo;Access, a porté ce document dans une table Access sans connaître les formes normales de Codd !</p>
<p>Voici le code pour créér et peupler partiellement la table dont la structure n&rsquo;est pas à suivre&#8230;</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> CreationTableConcat()<br />
&nbsp; &nbsp;Const cInsert <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;INSERT INTO tConcat (Marque, Modele, DateAchat, Couleur, Nombre, Prix) VALUES &quot;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">With</span> DoCmd<br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">False</span><br />
<br />
&nbsp; &nbsp; &nbsp; .RunSQL <span style="color: #800000;">&quot;CREATE TABLE tConcat (Marque VARCHAR, Modele VARCHAR, DateAchat DATE, Couleur VARCHAR, Nombre LONG, Prix DOUBLE);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL <span style="color: #800000;">&quot;CREATE INDEX IdxMarque ON tConcat (Marque);&quot;</span><br />
<br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Citroën','DS',#6/3/1993#,'blanc',2,85.25);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Citroën','DS',#2/13/1999#,'blanc',5,405.3);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Peugeot','205',#11/18/1998#,'vert',1,31.2);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Peugeot','404',#03/25/1978#,'noir',3,NULL);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Peugeot','205',#12/07/1997#,'bleu',1,31.2);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Peugeot','404',#03/25/1978#,'marron',1,42.1);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Renault','R5',#01/28/1982#,'rouge',5,255.5);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Renault','R4',#07/11/1991#,'bleu',3,159.9);&quot;</span><br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('Renault','R4',#07/11/1991#,'rouge',5,238.75);&quot;</span><br />
<br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">True</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">With</span><br />
<br />
&nbsp; &nbsp;MsgBox <span style="color: #800000;">&quot;Création terminée&quot;</span><br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Cette table contient 6 colonnes (Marque, Modèle, DateAchat, Couleur des voitures, Nombre de voiture du lot, Prix du lot).<br />
Chaque ligne de la table correspond à l&rsquo;achat d&rsquo;un lot de voitures et toutes les voitures d&rsquo;un lot ont la même couleur.</p>
<p>Le collectionneur souhaite obtenir des infos sur sa collection en concaténant l&rsquo;information dans une colonne car c&rsquo;est plus simple à lire&#8230;</p>
<p><strong>Quels sont les modèles achetés de la marque Peugeot ?</strong><br />
Comme la colonne pivot &lsquo;Marque&rsquo; doit être égale à &lsquo;Peugeot&rsquo;, on peut écrire la simple requête suivante :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;Peugeot&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;peugeot&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;marque&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;modele&quot;</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;,&quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">MOD</span>èles<span style="color: #66cc66;">&#93;</span></div></div>
<p>La valeur pivot est &lsquo;Peugeot&rsquo;, la colonne pivot (ou de regroupement) est &lsquo;Marque&rsquo;, la colonne à concaténer est &lsquo;Modele&rsquo;, la table est &lsquo;tConcat&rsquo;, la clause Where est vide &laquo;&nbsp;&nbsp;&raquo;, pas de regroupement des lots ayant le même modèle d&rsquo;où la valeur 0, on retourne les modèles dont le nom est vide ou NULL (False), on souhaite trier par ordre Ascendant les modèles concaténés (True), et le séparateur entre les modèles est une virgule &lsquo;,&rsquo;.<br />
<br />
On obtient donc :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Modèles &nbsp; <br />
Peugeot | 205,205,404,404</div></div>
<p>
Le collectionneur est satisfait mais il préfère regrouper les modèles communs et ajouter un espace après la &lsquo;,&rsquo;<br />
La requête devient :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;Peugeot&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;peugeot&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;marque&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;modele&quot;</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;, &quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">MOD</span>èles<span style="color: #66cc66;">&#93;</span></div></div>
<p>Pour regrouper les modèles, il suffit de passer à <strong>1</strong> au lieu de <strong>0</strong> le paramètre &lsquo;RegrouperCompter&rsquo;. De plus, le séparateur devient &lsquo;, &lsquo; au lieu de &lsquo;,&rsquo;.<br />
<br />
On obtient alors :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Modèles &nbsp; <br />
Peugeot | 205, 404</div></div>
<p>
Il est satisfait mais il perd une information importante qui est le nombre de lots achetés et finalement il se demande si le séparateur &lsquo; / &lsquo; ne serait pas mieux&#8230;<br />
La solution devient :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;Peugeot&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;peugeot&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;marque&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;modele&quot;</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; / &quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">MOD</span>èles<span style="color: #66cc66;">&#93;</span></div></div>
<p>Pour afficher le compte par modèle, on passe la valeur du paramètre &lsquo;RegrouperCompter&rsquo; à <strong>2</strong>, et le séparateur est modifié.<br />
<br />
Résultat :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Modèles &nbsp; <br />
Peugeot | 205 (2) / 404 (2)</div></div>
<p>&nbsp;<br />
<strong>Qu&rsquo;elles sont les dates d&rsquo;achat de ces lots du plus récent au plus ancien ?</strong></p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;Peugeot&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;peugeot&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;marque&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;dateachat&quot;</span><span style="color: #66cc66;">,</span> &nbsp;<span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; ; &quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Dates achat<span style="color: #66cc66;">&#93;</span></div></div>
<p>La colonne à concaténer devient &lsquo;DateAchat&rsquo; et le paramètre &lsquo;TriAscendant&rsquo; devient &lsquo;False&rsquo;.<br />
<br />
Résultat :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Dates achat<br />
Peugeot | 18/11/1998 (1) ; 07/12/1997 (1) ; 25/03/1978 (2)</div></div>
<p>&nbsp;<br />
<strong>Quels sont les prix d&rsquo;achat de ces lots ?</strong></p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;Peugeot&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;peugeot&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;marque&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;prix&quot;</span> &nbsp; <span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; ; &quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Prix<span style="color: #66cc66;">&#93;</span></div></div>
<p>
On obtient :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Prix<br />
Peugeot | 42,1 (1) ; 31,2 (2) ; &nbsp;(1)</div></div>
<p>On remarque que le dernier compte (1) est sans valeur. En effet, un prix n&rsquo;était pas renseigné dans le document&#8230;<br />
Le collectionneur me dit alors : &lsquo;Cachez-moi cette erreur que je ne saurais voir&#8230;&rsquo;<br />
<br />
La requête devient donc :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;Peugeot&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;peugeot&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;marque&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;prix&quot;</span> &nbsp; <span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; ; &quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Prix<span style="color: #66cc66;">&#93;</span></div></div>
<p>Il suffit de mettre à &lsquo;True&rsquo; le paramètre &lsquo;PasVideNULL&rsquo;.<br />
<br />
On obtient finalement :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Prix<br />
Peugeot | 42,1 (1) ; 31,2 (2)</div></div>
<p>&nbsp;<br />
<strong>Quels sont les prix d&rsquo;achat, toutes marques confondues ?</strong><br />
Il est normalement nécessaire de renseigner la valeur et la colonne du pivot&#8230;<br />
La solution consiste à mettre 0 pour &lsquo;ValeurColonnePivot&rsquo; et &lsquo;0&rsquo; pour &lsquo;NomColonnePivot&rsquo;<br />
La requête devient :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;Toutes&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;0&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;prix&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; ; &quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Prix<span style="color: #66cc66;">&#93;</span></div></div>
<p>et le résultat :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Prix<br />
Toutes &nbsp;| 405,3 (1) ; 255,5 (1) ; 238,75 (1) ; 159,9 (1) ; 85,25 (1) ; 42,1 (1) ; 31,2 (2)</div></div>
<p>
Ca serait possible d&rsquo;avoir tous les prix unitaires ?<br />
Requête :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #ff0000;">&quot;Toutes&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;0&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;[prix]/[nombre]&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; - &quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Prix<span style="color: #66cc66;">&#93;</span></div></div>
<p>On déclare que la colonne concaténée est la division du prix sur le nombre de voiture du lot.<br />
Résultat :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Prix<br />
Toutes &nbsp;| 81,06 - 53,3 - 51,1 - 47,75 - 42,625 - 42,1 - 31,2</div></div>
<p>&nbsp;<br />
<strong>Quels sont les modèles de chaque marque ?</strong><br />
Cette fois-ci, il faut utiliser la <strong>clause FROM </strong> de la requête pour passer en revue l&rsquo;ensemble des marques :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; Marque<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span>marque<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;marque&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;modele&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; - &quot;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">MOD</span>èles par marque<span style="color: #66cc66;">&#93;</span> <br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; tconcat <br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> marque <br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> marque</div></div>
<p>Résultat :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Modèles par marque<br />
Citroën | DS<br />
Peugeot | 205 - 404<br />
Renault | R4 - R5</div></div>
<p>&nbsp;<br />
<strong>Quels sont les marques et modèles pour chaque couleur ?</strong></p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; Couleur<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span>couleur<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;couleur&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;marque &amp; &quot;</span><span style="color: #ff0000;">&quot; &quot;</span><span style="color: #ff0000;">&quot; &amp; modele&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; - &quot;</span><span style="color: #66cc66;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Marque et <span style="color: #993333; font-weight: bold;">MOD</span>èle<span style="color: #66cc66;">&#93;</span> <br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; tconcat <br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> Couleur <br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> Couleur</div></div>
<p>Résultat :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Couleur | Marque et modèle<br />
blanc &nbsp; | Citroën DS<br />
bleu &nbsp; &nbsp;| Peugeot 205 - Renault R4<br />
marron &nbsp;| Peugeot 404<br />
noir &nbsp; &nbsp;| Peugeot 404<br />
rouge &nbsp; | Renault R4 - Renault R5<br />
vert &nbsp; &nbsp;| Peugeot 205</div></div>
<p>
Puis-je avoir une présentation inversée ?</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; <span style="color: #66cc66;">&#91;</span>Marque<span style="color: #66cc66;">&#93;</span> &amp; <span style="color: #ff0000;">&quot; &quot;</span> &amp; <span style="color: #66cc66;">&#91;</span>modele<span style="color: #66cc66;">&#93;</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Marque et <span style="color: #993333; font-weight: bold;">MOD</span>èle<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span>marque<span style="color: #66cc66;">&#93;</span> &amp; <span style="color: #ff0000;">&quot; &quot;</span> &amp; <span style="color: #66cc66;">&#91;</span>Modele<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;[Marque] &amp; &quot;</span><span style="color: #ff0000;">&quot; &quot;</span><span style="color: #ff0000;">&quot; &amp; [modele]&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;couleur&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot; - &quot;</span><span style="color: #66cc66;">&#41;</span> &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Couleur<span style="color: #66cc66;">&#93;</span> <br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; tconcat <br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #66cc66;">&#91;</span>Marque<span style="color: #66cc66;">&#93;</span> &amp; <span style="color: #ff0000;">&quot; &quot;</span> &amp; <span style="color: #66cc66;">&#91;</span>modele<span style="color: #66cc66;">&#93;</span> <br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> <span style="color: #66cc66;">&#91;</span>Marque<span style="color: #66cc66;">&#93;</span> &amp; <span style="color: #ff0000;">&quot; &quot;</span> &amp; <span style="color: #66cc66;">&#91;</span>modele<span style="color: #66cc66;">&#93;</span></div></div>
<p>qui donne :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque et modèle | Couleur<br />
Citroën DS &nbsp; &nbsp; &nbsp; | blanc<br />
Peugeot 205 &nbsp; &nbsp; &nbsp;| bleu - vert<br />
Peugeot 404 &nbsp; &nbsp; &nbsp;| marron - noir<br />
Renault R4 &nbsp; &nbsp; &nbsp; | bleu - rouge<br />
Renault R5 &nbsp; &nbsp; &nbsp; | rouge</div></div>
<p>Enfin, je souhaite afficher séparément les colonnes &lsquo;Marque&rsquo; et &lsquo;Modèle&rsquo; et ne pas voir les informations pour &lsquo;Citroën&rsquo;<br />
La requête :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Modele<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ConcatColonne<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span>Marque<span style="color: #66cc66;">&#93;</span> &amp; <span style="color: #ff0000;">&quot; &quot;</span> &amp; <span style="color: #66cc66;">&#91;</span>Modele<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;[Marque] &amp; &quot;</span><span style="color: #ff0000;">&quot; &quot;</span><span style="color: #ff0000;">&quot; &amp; [modele]&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;couleur&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;tConcat&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot;Marque &lt;&gt; 'citroën'&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">FALSE</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">TRUE</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">&quot; - &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#41;</span> &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Couleur<span style="color: #66cc66;">&#93;</span> <br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; tconcat <br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> Marque<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Modele<br />
<span style="color: #993333; font-weight: bold;">HAVING</span> &nbsp; Marque <span style="color: #66cc66;">&lt;&gt;</span> <span style="color: #ff0000;">'Citroën'</span><br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> Marque<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Modele</div></div>
<p>On remarquera l&rsquo;utilisation du paramètre &lsquo;Filtre&rsquo; de la fonction ConcatColonne pour écarter la marque &lsquo;Citroën&rsquo; de la concaténation. Dans ce cas précis, l&rsquo;utilisation du filtre n&rsquo;est pas indispensable puisque la requête écarte elle-même cette marque (voir clause HAVING).<br />
Résultat attendu :</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Marque &nbsp;| Modele | Couleur<br />
Peugeot | 205 &nbsp; &nbsp;| bleu - vert<br />
Peugeot | 404 &nbsp; &nbsp;| marron - noir<br />
Renault | R4 &nbsp; &nbsp; | bleu - rouge<br />
Renault | R5 &nbsp; &nbsp; | rouge</div></div>
<p>&nbsp;<br />
<strong>Performance</strong><br />
La fonction (et la requête sous-jacente!) est exécutée pour chaque ligne de la table ce qui ralentit sensiblement la requête principale.<br />
Il faudra donc limiter son usage à une table ou requête peu peuplée (&lt; 10 000 lignes ?) et si possible, indexer avec doublons la colonne pivot.<br />
De plus, pour ne pas dégrader les performances, éviter de réaliser des opérations complémentaires sur la colonne concaténée (Where, Order by, Group by) dans la requête principale.</p>
<p><strong>Lien</strong><br />
Voir ce <a href="http://blog.developpez.com/philben/p11140/ms-access-vba/transposer_une_colonne_en_lignes" title="Transposer une colonne en lignes">billet</a> pour réaliser une transposition inverse.</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Similarité entre deux chaînes de caractères</title>
		<link>https://blog.developpez.com/philben/p11268/vba-access/similarite_entre_deux_chaines_de_caracte</link>
		<comments>https://blog.developpez.com/philben/p11268/vba-access/similarite_entre_deux_chaines_de_caracte#comments</comments>
		<pubDate>Fri, 31 Aug 2012 16:06:49 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Similarité]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Pour tenter de réduire l&#8217;imperfection des ITCC, IPCC, ITPCC voire ITPCCC et plus généralement ICC(*), de nombreux algorithmes sont proposés (Soundex, Jaro-Winkler, &#8230;) et l&#8217;algorithme de Damerau-Levenshtein que j&#8217;ai implémenté ici en VBA. Voir aussi le billet sur les indices &#8230; <a href="https://blog.developpez.com/philben/p11268/vba-access/similarite_entre_deux_chaines_de_caracte">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Pour tenter de réduire l&rsquo;imperfection des ITCC, IPCC, ITPCC voire ITPCCC et plus généralement ICC(<strong>*</strong>), de nombreux algorithmes sont proposés (Soundex, Jaro-Winkler, &#8230;) et l&rsquo;algorithme de Damerau-Levenshtein que j&rsquo;ai implémenté ici en VBA.<br />
Voir aussi le billet sur les <a href="http://blog.developpez.com/philben/p11340/vba-access/indices-de-similarite-entre-deux-chaines-de-caracteres" title="Indices de similarité entre deux chaînes de caractères" target="_blank">indices de similarité</a> et le billet sur la <a href="http://blog.developpez.com/philben/p12207/vba-access/vba-distance-de-jaro-winkler" title="VBA : Distance de Jaro-Winkler" target="_blank">distance de Jaro-Winkler</a>.<br />
<span id="more-19"></span><br />
<strong>Le code source</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> DamerauLevenshteinSimilarite(<span style="color: #151B8D; font-weight: bold;">ByVal</span> s1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> s2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Single</span><br />
<span style="color: #008000;">'Calcul la similarité (de [0 à 1]) entre deux chaines d'après l'algorithme de Damerau-Levenshtein<br />
</span><span style="color: #008000;">'références : http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://mwh.geek.nz/2009/04/26/python-damerau-levenshtein-distance/<br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://www-igm.univ-mlv.fr/~lecroq/seqcomp/node2.html<br />
</span><span style="color: #008000;">'Remarques &nbsp;: Préparer les chaines car les comparaisons sont binaires : UCase(), Trim(),...<br />
</span><span style="color: #008000;">'Philben v1.0 - Free to Use<br />
</span> &nbsp; Const cFacteur <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = &amp;H100&amp;, cMaxLen <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 256&amp; &nbsp; <span style="color: #008000;">'Longueur maxi autorisée des chaines analysées<br />
</span> &nbsp; <span style="color: #151B8D; font-weight: bold;">Dim</span> l1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, l2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, c1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, c2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> r() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, rp() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, rpp() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, j <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> c <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, x <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, y <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, z <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, f1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>, f2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> dls <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Single</span>, ac1() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Byte</span>, ac2() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Byte</span><br />
<br />
&nbsp; &nbsp;l1 = Len(s1): l2 = Len(s2)<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> l1 &gt; 0 <span style="color: #8D38C9; font-weight: bold;">And</span> l1 &lt;= cMaxLen <span style="color: #8D38C9; font-weight: bold;">And</span> l2 &gt; 0 <span style="color: #8D38C9; font-weight: bold;">And</span> l2 &lt;= cMaxLen <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; ac1 = s1: ac2 = s2 &nbsp; <span style="color: #008000;">'conversion des chaines en tableaux de bytes<br />
</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">'Initialise la ligne précédente (rp) de la matrice<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">ReDim</span> rp(0 <span style="color: #8D38C9; font-weight: bold;">To</span> l2)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 0 <span style="color: #8D38C9; font-weight: bold;">To</span> l2: rp(i) = i: <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> l1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">'Initialise la ligne courante de la matrice<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">ReDim</span> r(0 <span style="color: #8D38C9; font-weight: bold;">To</span> l2): r(0) = i<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">'Calcul le CharCode du caractère courant de la chaine<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; f1 = (i - 1) * 2: c1 = ac1(f1 + 1) * cFacteur + ac1(f1)<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> j = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> l2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f2 = (j - 1) * 2: c2 = ac2(f2 + 1) * cFacteur + ac2(f2)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c = -(c1 &lt;&gt; c2) &nbsp; <span style="color: #008000;">'Cout : True = -1 =&gt; c = 1<br />
</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">'suppression, insertion, substitution<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;x = rp(j) + 1: y = r(j - 1) + 1: z = rp(j - 1) + c<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> x &lt; y <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> x &lt; z <span style="color: #8D38C9; font-weight: bold;">Then</span> r(j) = x <span style="color: #8D38C9; font-weight: bold;">Else</span> r(j) = z<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> y &lt; z <span style="color: #8D38C9; font-weight: bold;">Then</span> r(j) = y <span style="color: #8D38C9; font-weight: bold;">Else</span> r(j) = z<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">'transposition<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> i &gt; 1 <span style="color: #8D38C9; font-weight: bold;">And</span> j &gt; 1 <span style="color: #8D38C9; font-weight: bold;">And</span> c = 1 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> c1 = ac2(f2 - 1) * cFacteur + ac2(f2 - 2) <span style="color: #8D38C9; font-weight: bold;">And</span> c2 = ac1(f1 - 1) * cFacteur + ac1(f1 - 2) <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> r(j) &gt; rpp(j - 2) + c <span style="color: #8D38C9; font-weight: bold;">Then</span> r(j) = rpp(j - 2) + c<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> j<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">'Reculer d'un niveau la ligne précédente (rp) et courante (r)<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; rpp = rp: rp = r<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">'Calcul la similarité via la distance entre les chaines r(l2)<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> l1 &gt;= l2 <span style="color: #8D38C9; font-weight: bold;">Then</span> dls = 1 - r(l2) / l1 <span style="color: #8D38C9; font-weight: bold;">Else</span> dls = 1 - r(l2) / l2<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">ElseIf</span> l1 &gt; cMaxLen <span style="color: #8D38C9; font-weight: bold;">Or</span> l2 &gt; cMaxLen <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; dls = -1 &nbsp; <span style="color: #008000;">'indique un dépassement de longueur de chaine<br />
</span> &nbsp; <span style="color: #8D38C9; font-weight: bold;">ElseIf</span> l1 = 0 <span style="color: #8D38C9; font-weight: bold;">And</span> l2 = 0 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; dls = 1 &nbsp; <span style="color: #008000;">'cas particulier<br />
</span> &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
<br />
&nbsp; &nbsp;DamerauLevenshteinSimilarite = dls<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Explications</strong><br />
L&rsquo;algorithme de Levenshtein mesure la distance entre deux chaînes de caractères qui est basée sur le nombre minimal de suppressions/insertions/substitutions de caractères pour passer d&rsquo;une chaîne à l&rsquo;autre.<br />
L&rsquo;algorithme de Damerau-Levenshtein ajoute en plus la <strong>transposition</strong> bien connue des dyslexiques du clavier (&lsquo;rehcerhce&rsquo; au lieu de &lsquo;recherche&rsquo;)&#8230;</p>
<p>Mon implémentation ne retourne pas une distance mais un indice de similarité allant de 0 à 1. La valeur 1 indique une similarité maximale entre deux chaînes. De plus, elle réalise une comparaison binaire des caractères, d&rsquo;où parfois la nécessité de prétraiter les chaînes (UCase(), Trim(), sans accent,&#8230;)</p>
<p>La complexité de l&rsquo;algorithme est O(m*n) avec m et n la longueur des chaînes ce qui limite son usage à des chaînes relativement courtes, des mots.<br />
&nbsp;<br />
<strong>Exemples</strong><br />
On peut utiliser cette fonction dans une requête SQL pour rechercher des doublons sur une petite(!) base de données en se basant sur une ou des colonnes (nom/prénom/adresse/&#8230;) ou afficher les données les plus similaires à une chaîne de recherche.</p>
<p>Par exemple, mon doigt a rippé par deux fois sur mon clavier AZERTY et j&rsquo;ai enchaîné un redressement un peu tardif qui a eu pour résultat : <strong>&lsquo;tbalrette&rsquo;</strong></p>
<p>La recherche de similarité dans une table de synonymes (+ de 36 000 entrées) a affiché :</p>
<ul>
<li>barette (0,78)</li>
<li>tablette (0,78)</li>
<li>turlurette (0,70)</li>
<li>targette (0,67)</li>
<li>&#8230;</li>
</ul>
<p>Je voulais écrire <strong>&lsquo;tablette&rsquo;</strong>.</p>
<p>Comme d&rsquo;habitude, vous pouvez tester la fonction dans la fenêtre Exécution du VBE :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">?DamerauLevenshteinSimilarite(<span style="color: #800000;">&quot;tbalrette&quot;</span>,<span style="color: #800000;">&quot;tablette&quot;</span>) <span style="color: #008000;">'=&gt;0,7777778 <br />
</span>?DamerauLevenshteinSimilarite(<span style="color: #800000;">&quot;apple&quot;</span>,<span style="color: #800000;">&quot;appel&quot;</span>) <span style="color: #008000;">'=&gt;0,8 <br />
</span>?DamerauLevenshteinSimilarite(<span style="color: #800000;">&quot;chrizantème&quot;</span>,<span style="color: #800000;">&quot;chrysanthème&quot;</span>) <span style="color: #008000;">'=&gt;0,75 <br />
</span>?DamerauLevenshteinSimilarite(<span style="color: #800000;">&quot;rehcerche&quot;</span>,<span style="color: #800000;">&quot;recherche&quot;</span>) <span style="color: #008000;">'=&gt;0,8888889 <br />
</span>?DamerauLevenshteinSimilarite(<span style="color: #800000;">&quot;dnas&quot;</span>,<span style="color: #800000;">&quot;dans&quot;</span>) <span style="color: #008000;">'=&gt;0,75 <br />
</span>?DamerauLevenshteinSimilarite(<span style="color: #800000;">&quot;machine&quot;</span>,<span style="color: #800000;">&quot;appareil&quot;</span>) <span style="color: #008000;">'=&gt;0,125 <br />
</span>?DamerauLevenshteinSimilarite(<span style="color: #800000;">&quot;le jour se lève&quot;</span>,<span style="color: #800000;">&quot;le jour se couche&quot;</span>) '=&gt;0,7058824</div></div>
<p>&nbsp;<br />
<strong>(*)</strong></p>
<ul>
<li>ICC : Interface Chaise-Clavier</li>
<li>ITCC : Interface Téléphone-Chaise-Clavier</li>
<li>IPCC : Interface Papier-Chaise-Clavier</li>
<li>ITPCC : Interface Téléphone-Papier-Chaise-Clavier</li>
<li>ITPCCC : Interface Téléphone-Papier-Collègue-Chaise-Clavier</li>
</ul>
<p>Pour en savoir plus sur le <a href="http://en.wikipedia.org/wiki/User_error">thème</a> <em>errare humanum est</em>&#8230;</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Encoder un texte en UTF-8</title>
		<link>https://blog.developpez.com/philben/p10825/vba-access/encoder_un_texte_en_utf8</link>
		<comments>https://blog.developpez.com/philben/p10825/vba-access/encoder_un_texte_en_utf8#comments</comments>
		<pubDate>Mon, 12 Mar 2012 20:36:16 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[UTF-8]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Si vous êtes utilisateur de web services ou si vous avez besoin d&#8217;encoder des chaînes de caractères en UTF-8, Cette fonction en VBA va vous aider&#8230; Public Function URIEncodeUTF8(ByVal sURI As String) As String 'Author : Philben - v1.0 - &#8230; <a href="https://blog.developpez.com/philben/p10825/vba-access/encoder_un_texte_en_utf8">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Si vous êtes utilisateur de web services ou si vous avez besoin d&rsquo;encoder des chaînes de caractères en UTF-8,<br />
Cette fonction en <strong>VBA</strong> va vous aider&#8230;<br />
<span id="more-3"></span></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> URIEncodeUTF8(<span style="color: #151B8D; font-weight: bold;">ByVal</span> sURI <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span><br />
<span style="color: #008000;">'Author : Philben - v1.0 - free to use<br />
</span> &nbsp; <span style="color: #151B8D; font-weight: bold;">Dim</span> sUTF8 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, lCode <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, abyURI() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Byte</span><br />
<br />
&nbsp; &nbsp;abyURI = StrConv(sURI, vbUnicode)<br />
<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = 0 <span style="color: #8D38C9; font-weight: bold;">To</span> <span style="color: #151B8D; font-weight: bold;">UBound</span>(abyURI) <span style="color: #8D38C9; font-weight: bold;">Step</span> 4<br />
&nbsp; &nbsp; &nbsp; lCode = abyURI(i) + abyURI(i + 1) * &amp;H10&amp; + abyURI(i + 2) * &amp;H100&amp; + abyURI(i + 3) * &amp;H1000&amp;<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Select</span> <span style="color: #8D38C9; font-weight: bold;">Case</span> lCode<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> 48 <span style="color: #8D38C9; font-weight: bold;">To</span> 57, 65 <span style="color: #8D38C9; font-weight: bold;">To</span> 90, 97 <span style="color: #8D38C9; font-weight: bold;">To</span> 122 &nbsp; <span style="color: #008000;">'1-9, A-Z, a-z =&gt; pas d'encodage<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; sUTF8 = sUTF8 &amp; Chr(lCode)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> <span style="color: #8D38C9; font-weight: bold;">Is</span> &lt; &amp;H80&amp; &nbsp; <span style="color: #008000;">'de 0 à 127<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; sUTF8 = sUTF8 &amp; Format(Hex(lCode), <span style="color: #800000;">&quot;%@@&quot;</span>)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> <span style="color: #8D38C9; font-weight: bold;">Is</span> &lt; &amp;H800&amp; &nbsp; <span style="color: #008000;">'de 128 à 2047<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; sUTF8 = sUTF8 &amp; Format(Hex(&amp;HC0&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> (lCode \ &amp;H40&amp;)) &amp; _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Hex(&amp;H80&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> (lCode <span style="color: #8D38C9; font-weight: bold;">And</span> &amp;H3F&amp;)), <span style="color: #800000;">&quot;%@@%@@&quot;</span>)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> <span style="color: #8D38C9; font-weight: bold;">Is</span> &lt; &amp;H10000 &nbsp; <span style="color: #008000;">'de 2048 à 65535<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; sUTF8 = sUTF8 &amp; Format(Hex(&amp;HE0&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> (lCode \ &amp;H1000&amp;)) &amp; _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Hex(&amp;H80&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> ((lCode \ &amp;H40&amp;) <span style="color: #8D38C9; font-weight: bold;">And</span> &amp;H3F&amp;)) &amp; _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Hex(&amp;H80&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> (lCode <span style="color: #8D38C9; font-weight: bold;">And</span> &amp;H3F&amp;)), <span style="color: #800000;">&quot;%@@%@@%@@&quot;</span>)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Case</span> <span style="color: #8D38C9; font-weight: bold;">Else</span> &nbsp; <span style="color: #008000;">'&gt;= 65536<br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; sUTF8 = sUTF8 &amp; Format(Hex(&amp;HF0&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> (lCode \ &amp;H40000)) &amp; _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Hex(&amp;H80&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> ((lCode \ &amp;H1000&amp;) <span style="color: #8D38C9; font-weight: bold;">And</span> &amp;H3F&amp;)) &amp; _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Hex(&amp;H80&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> ((lCode \ &amp;H40&amp;) <span style="color: #8D38C9; font-weight: bold;">And</span> &amp;H3F&amp;)) &amp; _<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Hex(&amp;H80&amp; <span style="color: #8D38C9; font-weight: bold;">Or</span> (lCode <span style="color: #8D38C9; font-weight: bold;">And</span> &amp;H3F&amp;)), <span style="color: #800000;">&quot;%@@%@@%@@%@@&quot;</span>)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">Select</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
&nbsp; &nbsp;URIEncodeUTF8 = sUTF8<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Exemple d&rsquo;utilisation</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">? URIEncodeUTF8(<span style="color: #800000;">&quot;un hélicoptère&quot;</span>) 'Chaîne obtenue : un%20h%C3%A9licopt%C3%A8re</div></div>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fonctions Min / Max d&#8217;une série de valeurs</title>
		<link>https://blog.developpez.com/philben/p10821/vba-access/fonctions_min_max_d_une_serie_de_valeurs</link>
		<comments>https://blog.developpez.com/philben/p10821/vba-access/fonctions_min_max_d_une_serie_de_valeurs#comments</comments>
		<pubDate>Sun, 11 Mar 2012 20:57:10 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Date]]></category>
		<category><![CDATA[Numérique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Deux petites fonctions qui permettent d&#8217;extraire la valeur minimale ou maximale d&#8217;une série de valeurs dans une requête SQL ou dans un code VBA. Les fonctions Public Function getMin(ParamArray pa() As Variant) As Variant &#160; &#160;Dim v As Variant &#160; &#8230; <a href="https://blog.developpez.com/philben/p10821/vba-access/fonctions_min_max_d_une_serie_de_valeurs">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Deux petites fonctions qui permettent d&rsquo;extraire la valeur minimale ou maximale d&rsquo;une série de valeurs dans une requête SQL ou dans un code VBA.<br />
<span id="more-1"></span><br />
<strong>Les fonctions</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> getMin(<span style="color: #151B8D; font-weight: bold;">ParamArray</span> pa() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> v <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> <span style="color: #8D38C9; font-weight: bold;">Each</span> v <span style="color: #8D38C9; font-weight: bold;">In</span> pa<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> getMin &gt; v <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getMin = v<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">ElseIf</span> IsEmpty(getMin) <span style="color: #8D38C9; font-weight: bold;">And</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> IsNull(v) <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getMin = v<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> v<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span><br />
<br />
<span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> getMax(<span style="color: #151B8D; font-weight: bold;">ParamArray</span> pa() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> v <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> <span style="color: #8D38C9; font-weight: bold;">Each</span> v <span style="color: #8D38C9; font-weight: bold;">In</span> pa<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> getMax &lt; v <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getMax = v<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">ElseIf</span> IsEmpty(getMax) <span style="color: #8D38C9; font-weight: bold;">And</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> IsNull(v) <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getMax = v<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> v<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Paramètre</strong><br />
Elles acceptent un nombre quelconque de valeurs en paramètre grâce à l&rsquo;utilisation du type ParamArray.</p>
<p><strong>Particularités</strong></p>
<ul>
<li>Ces fonctions gèrent les NULL c&rsquo;est à dire qu&rsquo;elles ne renvoient un NULL que si toutes les valeurs passées en paramètre sont nulles.</li>
<li>Le type des paramètres doit être uniforme et peut être numérique, date ou string. Une adaptation du code sera nécessaire pour une bonne gestion des accents et autres caractères particuliers.</li>
</ul>
<p><strong>Exemples</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Pas d'erreur si aucun paramètre... <br />
</span>? getMax(), getMin() <br />
<br />
<span style="color: #008000;">'Renvoient 0 : &nbsp;<br />
</span>? getMax(<span style="color: #00C2FF; font-weight: bold;">NULL</span>, 0, <span style="color: #00C2FF; font-weight: bold;">NULL</span>), getMin(<span style="color: #00C2FF; font-weight: bold;">NULL</span>, 0, <span style="color: #00C2FF; font-weight: bold;">NULL</span>) <br />
<br />
<span style="color: #008000;">'Renvoient 5 et -1 <br />
</span>? getMax(<span style="color: #00C2FF; font-weight: bold;">NULL</span>, 0, 5, -1, <span style="color: #00C2FF; font-weight: bold;">NULL</span>), getMin(<span style="color: #00C2FF; font-weight: bold;">NULL</span>, 0, 5, -1, <span style="color: #00C2FF; font-weight: bold;">NULL</span>)</div></div>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Substituer des sous-chaînes</title>
		<link>https://blog.developpez.com/philben/p11230/vba-access/substituer_des_sous_chaines</link>
		<comments>https://blog.developpez.com/philben/p11230/vba-access/substituer_des_sous_chaines#comments</comments>
		<pubDate>Sat, 18 Aug 2012 01:56:07 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Requête SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Je vous présente une fonction polyvalente écrite en VBA qui permet de remplacer une ou plusieurs sous-chaînes en tenant compte ou non de la casse des caractères. La fonction Public Function Substituer(ByVal Chaine As String, ParamArray Substitutions() As Variant) As &#8230; <a href="https://blog.developpez.com/philben/p11230/vba-access/substituer_des_sous_chaines">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Je vous présente une fonction polyvalente écrite en VBA qui permet de remplacer une ou plusieurs sous-chaînes en tenant compte ou non de la casse des caractères.<br />
<span id="more-17"></span><br />
<strong>La fonction</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> Substituer(<span style="color: #151B8D; font-weight: bold;">ByVal</span> Chaine <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, <span style="color: #151B8D; font-weight: bold;">ParamArray</span> Substitutions() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> <br />
<span style="color: #008000;">'Remplacer une ou plusieurs sous-chaines <br />
</span><span style="color: #008000;">'Philben - v1.0 - free to use <br />
</span> &nbsp; <span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, a <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, b <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> f <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span>, r <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> TypeComparaison <span style="color: #151B8D; font-weight: bold;">As</span> VbCompareMethod &nbsp; <span style="color: #008000;">'0 = vbBinaryCompare par défaut <br />
</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> Len(Chaine) &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 0 <span style="color: #8D38C9; font-weight: bold;">To</span> <span style="color: #151B8D; font-weight: bold;">UBound</span>(Substitutions) <span style="color: #8D38C9; font-weight: bold;">Step</span> 2 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> VarType(Substitutions(i)) = vbString <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f = Substitutions(i) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = Substitutions(i + 1) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">'si la longueur de la sous-chaine recherchée est &gt; à la chaine de remplacement =&gt; boucle de substitution <br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> Len(f) &gt; Len(r) <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a = Len(Chaine) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Do</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b = a <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> InStr(1, Chaine, f, TypeComparaison) &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Chaine = Replace(Chaine, f, r, , , TypeComparaison) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a = Len(Chaine) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Loop</span> <span style="color: #8D38C9; font-weight: bold;">Until</span> a = b <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #008000;">'sinon, substitution unique <br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">ElseIf</span> InStr(1, Chaine, f, TypeComparaison) &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Chaine = Replace(Chaine, f, r, , , TypeComparaison) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span> &nbsp; <span style="color: #008000;">'nouveau type de comparaison <br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TypeComparaison = IIf(Substitutions(i) &lt;&gt; 0, vbTextCompare, vbBinaryCompare) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i = i - 1 &nbsp; <span style="color: #008000;">'Ajustement car step 2 de la boucle <br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp;<br />
&nbsp; &nbsp;Substituer = Chaine <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p><strong>Exemple d&rsquo;utilisation</strong><br />
Recopier la ligne suivante dans la fenêtre &lsquo;Exécution&rsquo; de l&rsquo;éditeur Visual Basic (F11) puis appuyer sur &lsquo;Entrée&rsquo; pour l&rsquo;exécuter.</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">? Substituer(<span style="color: #800000;">&quot;MA_Chaîne_______A_Corrigé&quot;</span>,<span style="color: #800000;">&quot;_&quot;</span>,<span style="color: #800000;">&quot; &quot;</span>,<span style="color: #800000;">&quot; &nbsp;&quot;</span>,<span style="color: #800000;">&quot; &quot;</span>,<span style="color: #800000;">&quot; A &quot;</span>,<span style="color: #800000;">&quot; à &quot;</span>,<span style="color: #800000;">&quot;î&quot;</span>,<span style="color: #800000;">&quot;i&quot;</span>,<span style="color: #800000;">&quot;é&quot;</span>,<span style="color: #800000;">&quot;er&quot;</span>,<span style="color: #00C2FF; font-weight: bold;">true</span>,<span style="color: #800000;">&quot;ma&quot;</span>,<span style="color: #800000;">&quot;La&quot;</span>)<br />
'Résultat:La Chaine à Corriger</div></div>
<p><strong>Explications</strong><br />
Le premier paramètre de la fonction contient la chaine à modifier.<br />
Le deuxième paramètre est un peu particulier car il s&rsquo;agit d&rsquo;une suite de paramètres qui sera interprétée comme un tableau de variants. Ce tableau contient l&rsquo;ensemble des substitutions à réaliser (couple chaine recherchée/chaine de remplacement) et éventuellement un booléen qui indique le type de comparaison (binaire ou textuelle) pour les remplacements suivants.</p>
<p>Par défaut, la fonction effectue une comparaison binaire pour rechercher et remplacer les sous-chaines c&rsquo;est à dire qu&rsquo;elle est <strong>sensible</strong> à la casse des caractères.</p>
<p>Dans notre exemple, on va tout d&rsquo;abord substituer le caractère &lsquo;_&rsquo; par un espace (&lsquo;_&rsquo;,&rsquo; &lsquo;) puis réduire le nombre d&rsquo;espaces contigus en un (&lsquo;  &lsquo;,&rsquo; &lsquo;). A ce stade on obtient :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">? Substituer(<span style="color: #800000;">&quot;MA_Chaîne_______A_Corrigé&quot;</span>,<span style="color: #800000;">&quot;_&quot;</span>,<span style="color: #800000;">&quot; &quot;</span>,<span style="color: #800000;">&quot; &nbsp;&quot;</span>,<span style="color: #800000;">&quot; &quot;</span>) <br />
'Résultat:MA Chaîne A Corrigé</div></div>
<p>Lorsque la chaine de remplacement est plus courte que la chaine recherchée, la fonction réalise une boucle de réduction. Par exemple, 5 espaces contigus seront réduits en un même si la chaine recherchée n&rsquo;est que de deux espaces.</p>
<p>L&rsquo;étape suivante (&lsquo; A &lsquo;,&rsquo; à &lsquo;) recherche la lettre A en majuscule entourée d&rsquo;espaces, on remplace ensuite le i accentué par son équivalent sans accent (&lsquo;î&rsquo;,&rsquo;i&rsquo;) puis le &lsquo;é&rsquo; par &lsquo;er&rsquo;.</p>
<p>L&rsquo;étape suivante (True ou tout chiffre différent de 0) indique à la fonction que l&rsquo;on souhaite réaliser maintenant des comparaisons textuelles (vbTextCompare) donc insensibles à la casse des caractères. L&rsquo;étape suivante (&lsquo;ma&rsquo;,&rsquo;La&rsquo;) remplacera donc le texte &lsquo;ma&rsquo; par &lsquo;la&rsquo; quel que soit la casse des caractères.</p>
<p>On pourrait ajouter d&rsquo;autres remplacements et revenir aussi à une comparaison binaire (False ou le chiffre 0).</p>
<p><strong>Remarque</strong><br />
Dans le cas d&rsquo;une réduction de chaine, on réalise une boucle qui ne s&rsquo;arrête que si la longueur de la chaine est inchangée (&#8230;Loop Until a = b) après la fonction Replace(). Cette méthode est moins efficace que :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #8D38C9; font-weight: bold;">While</span> InStr(1, Chaine, f, TypeComparaison) &gt; 0 <br />
&nbsp; &nbsp; &nbsp; Chaine = Replace(Chaine, f, r, , , TypeComparaison) <br />
Wend</div></div>
<p>mais on risque d&rsquo;entrer dans une <strong>boucle infinie</strong> si on souhaite réduire par exemple &lsquo;oe&rsquo; en &lsquo;Œ&rsquo; avec une comparaison <strong>textuelle</strong>&#8230; En effet, cette ligature est interprétée comme équivalente à &lsquo;oe&rsquo; :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">? InStr(1, <span style="color: #800000;">&quot;oe&quot;</span>, <span style="color: #800000;">&quot;Œ&quot;</span>, vbTextCompare)</div></div>
<p>Access retourne la valeur 1 bien que l&rsquo;on s&rsquo;attend à obtenir 0&#8230;</p>
<p><strong>Pour le fun !</strong><br />
Une autre solution pour réduire les espaces :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'---<br />
</span>Substituer(<span style="color: #800000;">&quot;a &nbsp; &nbsp; &nbsp;b&quot;</span>, <span style="color: #800000;">&quot; &quot;</span>, vbVerticalTab &amp; vbFormFeed, vbFormFeed &amp; vbVerticalTab, vbNullString, vbVerticalTab &amp; vbFormFeed, <span style="color: #800000;">&quot; &quot;</span>) <br />
'---</div></div>
<p>Ce type de méthode est parfois utilisé dans les requêtes SQL pour s&rsquo;affranchir d&rsquo;une fonction personnelle dans la requête :</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">REPLACE</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">REPLACE</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">REPLACE</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#91;</span>Ma Colonne<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot; &quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot; &quot;</span> &amp; Chr<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> Chr<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> &amp; <span style="color: #ff0000;">&quot; &quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> Chr<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> TEST <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #66cc66;">...</span></div></div>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
