<?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; SQL &#8211; Ms Access</title>
	<atom:link href="https://blog.developpez.com/philben/pcategory/sql-access/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 : 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>Calcul direct de la date de Pâques en SQL</title>
		<link>https://blog.developpez.com/philben/p11430/sql-access/calcul-direct-de-la-date-de-paques-en-sql</link>
		<comments>https://blog.developpez.com/philben/p11430/sql-access/calcul-direct-de-la-date-de-paques-en-sql#comments</comments>
		<pubDate>Sat, 13 Oct 2012 19:44:07 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Date]]></category>
		<category><![CDATA[Requête SQL]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/philben/?p=469</guid>
		<description><![CDATA[La requête paramétrée suivante calcule directement la date du Dimanche de Pâques entre 1900 et 2099 sans faire intervenir une fonction VBA personnelle grâce à une formule dérivée de l&#8217;algorithme de Carter. La date des 3 jours fériés mobiles français &#8230; <a href="https://blog.developpez.com/philben/p11430/sql-access/calcul-direct-de-la-date-de-paques-en-sql">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>La requête paramétrée suivante calcule directement la date du Dimanche de Pâques entre <strong>1900 et 2099</strong> sans faire intervenir une fonction VBA personnelle grâce à une formule dérivée de l&rsquo;algorithme de <strong>Carter</strong>.<br />
La date des 3 jours fériés mobiles français (Lundi de Pâques, Ascension et Lundi de Pentecôte) est également formulée, bien que le lundi de  Pentecôte ne soit plus chômé depuis 2005 (journée de solidarité).<br />
<span id="more-469"></span><br />
<strong>La requête SQL pour ACCESS</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">PARAMETERS Annee Short;<br />
<span style="color: #993333; font-weight: bold;">SELECT</span> IIF<span style="color: #66cc66;">&#40;</span>Annee <span style="color: #993333; font-weight: bold;">BETWEEN</span> <span style="color: #cc66cc;">1900</span> <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #cc66cc;">2099</span><span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DateSerial<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Annee<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">204</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">11</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">&#40;</span>Annee <span style="color: #993333; font-weight: bold;">MOD</span> <span style="color: #cc66cc;">19</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">MOD</span> <span style="color: #cc66cc;">30</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">28</span> <span style="color: #66cc66;">+</span> <span style="color: #66cc66;">&#40;</span>Annee <span style="color: #993333; font-weight: bold;">MOD</span> <span style="color: #cc66cc;">19</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">16</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #66cc66;">&#40;</span>Annee <span style="color: #66cc66;">+</span> Annee \ <span style="color: #cc66cc;">4</span> <span style="color: #66cc66;">+</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">204</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">11</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">&#40;</span>Annee <span style="color: #993333; font-weight: bold;">MOD</span> <span style="color: #cc66cc;">19</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">MOD</span> <span style="color: #cc66cc;">30</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">22</span> <span style="color: #66cc66;">+</span> <span style="color: #66cc66;">&#40;</span>Annee <span style="color: #993333; font-weight: bold;">MOD</span> <span style="color: #cc66cc;">19</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">16</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">MOD</span> <span style="color: #cc66cc;">7</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">NULL</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Dimanche de Pâques<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>Dimanche de Pâques<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span> &nbsp;<span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Lundi de Pâques<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>Dimanche de Pâques<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">39</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Ascension<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#91;</span>Dimanche de Pâques<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">50</span> <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Lundi de Pentecôte<span style="color: #66cc66;">&#93;</span></div></div>
<p>&nbsp;<br />
<strong>Remarques</strong><br />
Si vous souhaitez extrapoler la formule à d&rsquo;autres SQL, il faut savoir que sous Access :</p>
<ul>
<li>True = -1 donc <code class="codecolorer sql blackboard"><span class="sql"><span style="color: #66cc66;">&#40;</span>Annee <span style="color: #993333; font-weight: bold;">MOD</span> <span style="color: #cc66cc;">19</span> <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">16</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></span></code> retourne -1 si vrai;</li>
<li>L&rsquo;opérateur &lsquo;\&rsquo; de <code class="codecolorer sql blackboard"><span class="sql">Annee \ <span style="color: #cc66cc;">4</span></span></code> retourne seulement la partie entière de la division;</li>
<li>Attention aussi à la priorité des opérateurs&#8230;
</ul>
<p>Il n&rsquo;est pas possible non plus de copier directement la formule dans une fonction VBA car elle utilise des opérateurs spécifiques SQL (Between et In).<br />
&nbsp;<br />
<strong>Exemples</strong><br />
Au lancement de la requête, un popup demande de saisir l&rsquo;année souhaitée.</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">Dimanche &nbsp; &nbsp;Lundi de <br />
de Pâques &nbsp; Pâques &nbsp; &nbsp; &nbsp;Ascension &nbsp; Lundi de Pentecôte<br />
15/04/1900 &nbsp;16/04/1900 &nbsp;24/05/1900 &nbsp;04/06/1900<br />
18/04/1954 &nbsp;19/04/1954 &nbsp;27/05/1954 &nbsp;07/06/1954<br />
08/04/2012 &nbsp;09/04/2012 &nbsp;17/05/2012 &nbsp;28/05/2012<br />
21/04/2019 &nbsp;22/04/2019 &nbsp;30/05/2019 &nbsp;10/06/2019<br />
12/04/2099 &nbsp;13/04/2099 &nbsp;21/05/2099 &nbsp;01/06/2099</div></div>
<p>Si l&rsquo;année est en dehors de la plage 1900 &#8211; 2099, NULL est renvoyé pour chaque colonne.</p>
<p><strong>A noter</strong><br />
La formule pour le <a href="http://access.developpez.com/faq/?page=TAManip#NbJourOuvr" title="Comment calculer le nombre de jours ouvrables entre deux dates ?" target="_blank">calcul des jours ouvrables</a> de la <strong>FAQ Access</strong> n&rsquo;est valable que pour la période comprise entre <strong>1982 et 2048.</strong></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>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>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>
		<item>
		<title>Remplacer les caractères accentués d&#8217;une chaîne</title>
		<link>https://blog.developpez.com/philben/p11217/vba-access/remplacer_les_caracteres_accentues_d_une</link>
		<comments>https://blog.developpez.com/philben/p11217/vba-access/remplacer_les_caracteres_accentues_d_une#comments</comments>
		<pubDate>Mon, 13 Aug 2012 10:56:14 +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>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Lors d&#8217;une recherche de sous-chaine, il est parfois nécessaire de substituer les lettres accentuées par leurs équivalents sans accent. En effet, le moteur Jet des bases de données Access est insensible à la casse des caractères mais ne fait pas &#8230; <a href="https://blog.developpez.com/philben/p11217/vba-access/remplacer_les_caracteres_accentues_d_une">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Lors d&rsquo;une recherche de sous-chaine, il est parfois nécessaire de substituer les lettres accentuées par leurs équivalents sans accent.<br />
En effet, le moteur Jet des bases de données Access est insensible à la casse des caractères mais ne fait pas le lien entre un caractère accentué et son équivalent.<br />
La FAQ propose déjà deux fonctions ayant le même objectif, mais voici une troisième voie qui se caractérise par sa vitesse d&rsquo;exécution et la possibilité ou non de conserver la casse des caractères de la chaine initiale.<br />
<span id="more-16"></span><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> SupprimerAccents(<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;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> ConserverCasseChaine <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>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> <br />
<span style="color: #008000;">'Substituer les caractères accentués et conserver ou non la casse des caractères de la chaine <br />
</span><span style="color: #008000;">'La fonction est plus rapide : <br />
</span><span style="color: #008000;">' &nbsp; - si on ne conserve pas la casse des caractères de la chaine (par défaut) <br />
</span><span style="color: #008000;">' &nbsp; - si les deux constantes (cMajAvecAccent, cMajSansAccent) sont réduites au strict nécessaire <br />
</span> &nbsp; Const cMajAvecAccent <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> &nbsp; <span style="color: #008000;">'Caractères à substituer (en MAJUSCULE) <br />
</span> &nbsp; Const cMajSansAccent <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;AAAAAACDEEEEIIIINOOOOOSUUUUYYZ&quot;</span> &nbsp; <span style="color: #008000;">'Caractères de substitution (en MAJUSCULE) <br />
</span> &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>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> ConserverCasseChaine <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; Chaine = UCase$(Chaine) <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> Len(cMajAvecAccent) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;f = Mid$(cMajAvecAccent, i, 1) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> InStr(1, Chaine, f, vbBinaryCompare) &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Chaine = Replace(Chaine, f, Mid$(cMajSansAccent, i, 1), , , vbBinaryCompare) <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; <span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</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> Len(cMajAvecAccent) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;f = Mid$(cMajAvecAccent, i, 1) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> InStr(1, Chaine, f, vbBinaryCompare) &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Chaine = Replace(Chaine, f, Mid$(cMajSansAccent, i, 1), , , vbBinaryCompare) <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;<span style="color: #8D38C9; font-weight: bold;">If</span> InStr(1, Chaine, LCase$(f), vbBinaryCompare) &gt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Chaine = Replace(Chaine, LCase$(f), LCase$(Mid$(cMajSansAccent, i, 1)), , , vbBinaryCompare) <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; <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;SupprimerAccents = Chaine <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>La fonction est d&rsquo;autant plus rapide si on ne conserve pas la casse de la chaine et si on réduit les caractères accentués recherchés au strict nécessaire.<br />
Il est parfois utile de conserver la casse des caractères de la chaine dans une requête d&rsquo;insertion ou de mise à jour ou si l&rsquo;on souhaite faire une recherche sur la casse des caractères seulement.</p>
<p>Suivant les cas, il est performant de tester avant de rentrer dans les boucles si la longueur de la chaine est supérieure à zéro et/ou dans le cas où l&rsquo;on souhaite conserver la casse, de faire un screening avant les deux recherches InStr().</p>
<p><strong>Exemple d&rsquo;utilisation</strong><br />
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"><span style="color: #008000;">'Attendu: HEOOODFGFDGOOEEFDG <br />
</span>?supprimeraccents(<span style="color: #800000;">&quot;hêÒÓôdfgfdgÕÖÈÉfdg&quot;</span>)<br />
<br />
<span style="color: #008000;">'Attendu: heOOodfgfdgOOEEfdg &nbsp;<br />
</span>?supprimeraccents(<span style="color: #800000;">&quot;hêÒÓôdfgfdgÕÖÈÉfdg&quot;</span>,<span style="color: #00C2FF; font-weight: bold;">True</span>)</div></div>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Regroupement de périodes chevauchées</title>
		<link>https://blog.developpez.com/philben/p11285/sql-access/regroupement-de-periodes-chevauchees</link>
		<comments>https://blog.developpez.com/philben/p11285/sql-access/regroupement-de-periodes-chevauchees#comments</comments>
		<pubDate>Tue, 07 Aug 2012 22:33:16 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[Date]]></category>
		<category><![CDATA[Requête SQL]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/philben/?p=141</guid>
		<description><![CDATA[Vous avez une table avec une date de début et de fin et vous souhaitez connaître la date mini et la date maxi des périodes qui se chevauchent. Création de la table et des lignes Public Function CreationTablePeriode() &#160; &#160;Const &#8230; <a href="https://blog.developpez.com/philben/p11285/sql-access/regroupement-de-periodes-chevauchees">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Vous avez une table avec une date de début et de fin et vous souhaitez connaître la date mini et la date maxi des périodes qui se chevauchent.<br />
<span id="more-141"></span><br />
<strong>Création de la table et des lignes</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> CreationTablePeriode() <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 tPeriode (DateDebut, DateFin) VALUES &quot;</span> <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 />
&nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; .RunSQL <span style="color: #800000;">&quot;CREATE TABLE tPeriode (Id AUTOINCREMENT PRIMARY KEY, DateDebut DATE NOT NULL, DateFin DATE NOT NULL)&quot;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2012-01-03', '2012-01-03');&quot;</span> <br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2011-12-20', '2012-01-04');&quot;</span> <br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2012-01-04', '2012-01-07');&quot;</span> <br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2012-01-06', '2012-01-10');&quot;</span> <br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2012-05-01', '2012-05-01');&quot;</span> <br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2012-05-02', '2012-05-03');&quot;</span> <br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2012-05-03', '2012-05-03');&quot;</span> <br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2012-05-03', '2012-05-05');&quot;</span> <br />
&nbsp; &nbsp; &nbsp; .RunSQL cInsert &amp; <span style="color: #800000;">&quot;('2012-05-04', '2012-05-10');&quot;</span> <br />
&nbsp; &nbsp; &nbsp;<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 />
&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><strong>Résultat attendu du jeu de test</strong><br />
Nous remarquons que la période :</p>
<ul>
<li>de la 1ère ligne [<strong>03/01/2012</strong>-03/01/2012] est chevauchée par celle de la 2ème [20/12/2011-<strong>04/01/2012</strong>]</li>
<li>de la 3ème ligne [<strong>04/01/2012</strong>-07/01/2012] chevauche celle de la 2ème [20/12/2011-<strong>04/01/2012</strong>]</li>
<li>de la 4ème ligne [<strong>06/01/2012</strong>-10/01/2012] chevauche celle de la 3ème [04/01/2012-<strong>07/01/2012</strong>]
</li>
</ul>
<p>Après regroupement, l&rsquo;étendue de cette première période va du <strong>20/12/2011</strong> au <strong>10/01/2012</strong></p>
<p><strong>La ligne n°5</strong> (01/05/2012-01/05/2012) n&rsquo;est chevauchée par aucune autre période et les 4 dernières lignes donnent une période du 02/05/2012 au 10/05/2012.</p>
<p>Le résultat attendu est :</p>
<ul>
<li>20/12/2012 &#8211; 10/01/2012</li>
<li>01/05/2012 &#8211; 01/05/2012</li>
<li>02/05/2012 &#8211; 10/05/2012</li>
</ul>
<p><strong>La requête</strong><br />
Il existe plusieurs méthodes pour arriver au résultat mais voici la requête la plus performante sous MS Access (et cerise sur le gâteau, visible dans l&rsquo;éditeur de 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; &nbsp; &nbsp;DateDebutAS <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">DATE</span> Début<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">MIN</span><span style="color: #66cc66;">&#40;</span>DateFin<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;">DATE</span> Fin<span style="color: #66cc66;">&#93;</span><br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp;DateDebut<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp;tPeriode <span style="color: #993333; font-weight: bold;">AS</span> T1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp; t1<span style="color: #66cc66;">.</span>DateDebut <span style="color: #66cc66;">&lt;=</span> <span style="color: #993333; font-weight: bold;">ALL</span> <span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> DateDebut<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; tPeriode T2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp;T2<span style="color: #66cc66;">.</span>DateDebut <span style="color: #66cc66;">=</span> T1<span style="color: #66cc66;">.</span>DateDebut<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> DateDebut<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> T1<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp;DateFin<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp;tPeriode <span style="color: #993333; font-weight: bold;">AS</span> T1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp; t1<span style="color: #66cc66;">.</span>DateFin <span style="color: #66cc66;">&gt;=</span> <span style="color: #993333; font-weight: bold;">ALL</span> <span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> DateFin<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; tPeriode T2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp;T2<span style="color: #66cc66;">.</span>DateFin <span style="color: #66cc66;">&gt;=</span> T1<span style="color: #66cc66;">.</span>DateDebut<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AND</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;T2<span style="color: #66cc66;">.</span>DateDebut <span style="color: #66cc66;">&lt;=</span> T1<span style="color: #66cc66;">.</span>DateFin<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> DateFin<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> T2<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>DateDebut <span style="color: #66cc66;">&lt;=</span> t2<span style="color: #66cc66;">.</span>DateFin<br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> &nbsp;DateDebut;</div></div>
<p><strong>Explications</strong><br />
La première sous-requête de la clause FROM (SELECT DateDebut&#8230;) retourne la date minimale des périodes chevauchées. En effet, la clause WHERE de cette sous-requête ne conserve que les dates de début qui sont inférieures ou égales aux périodes qui les chevauchent éventuellement.<br />
<strong>Prenons par exemple</strong> la ligne n°1 (03/01/2012). Sa date de début est-elle &lt;= à la date de début de la  période qui la chevauche ? La réponse est non puisque la date de début de la période du 20/12/2011 au 04/01/2012 est inférieure. La date du 03/01/2012 est donc retirée et ainsi de suite pour chaque ligne de la table.<br />
Le &#039;Group By DateDebut&#039; permet, au cas où,  de regrouper les lignes qui ont une même date de début.</p>
<p><strong>La deuxième sous-requête</strong> de la clause FROM (SELECT DateFin &#8230;) applique le même principe mais pour la date de fin.</p>
<p>A ce niveau là, on a visiblement pas de lien entre la date de début et la date de fin des périodes regroupées&#8230; d&rsquo;autant plus que l&rsquo;on réalise une jointure croisée entre les dates pour que la requête soit visible dans l&rsquo;éditeur.</p>
<p><strong>Pour s&rsquo;en sortir</strong>, on retire dans un premier temps les lignes incohérentes qui ont une date de fin &lt; à la date de début (&#8230;WHERE  t1.DateDebut &lt;= t2.DateFin&#8230;)<br />
Et la finesse finale qui consiste à dire que la date de fin de chaque regroupement de périodes est celle qui est la plus petite puisque nous avons retiré dans la clause WHERE précédente les périodes incohérentes et que les périodes restantes ne peuvent se chevaucher.<br />
On ajoute un GROUP BY sur la date de début pour permettre l&#039;utilisation de la fonction MIN() sur la date de fin.</p>
<p><strong>Test de performance</strong><br />
Voici une petite fonction qui va générer 2000 lignes dans la table pour tester la performance de la requête</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> TablePeriodeAddLines() <br />
&nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Dim</span> odb <span style="color: #151B8D; font-weight: bold;">As</span> DAO.Database <br />
&nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Dim</span> ors <span style="color: #151B8D; font-weight: bold;">As</span> DAO.Recordset <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;">Long</span> <br />
&nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Set</span> odb = CurrentDb <br />
&nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Set</span> ors = odb.OpenRecordset(<span style="color: #800000;">&quot;select * from tperiode&quot;</span>, dbOpenDynaset) <br />
&nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; Randomize <br />
&nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">With</span> ors <br />
&nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> 2000 <br />
&nbsp; &nbsp; &nbsp; &nbsp; .AddNew <br />
&nbsp; &nbsp; &nbsp; &nbsp; !datedebut = DateAdd(<span style="color: #800000;">&quot;d&quot;</span>, Rnd() * 1000 - 500, <span style="color: #F660AB; font-weight: bold;">Date</span>) <br />
&nbsp; &nbsp; &nbsp; &nbsp; !datefin = !datedebut + Int(Rnd() * 5) <br />
&nbsp; &nbsp; &nbsp; &nbsp; .Update <br />
&nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp; &nbsp; .<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;">With</span> <br />
&nbsp; &nbsp; &nbsp;<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; MsgBox <span style="color: #800000;">&quot;Ajout 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>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
