Anytone AT-D878 : importer les contacts DMR sans les caractères spéciaux

Anytone AT-D878 : importer les contacts DMR sans les caractères spéciaux

Les dernières versions de la radio Anytone AT-D878UVII Plus peuvent contenir jusqu’à 500 000 contacts ce qui permet de télécharger et d’importer en une fois toute la base de contacts DMR (un peu plus de 200 000 contacts au moment de rédiger cet article).

Pourquoi importer tous les contacts et ne pas simplement enregistrer les quelques amis avec qui vous faite QSO ? Et bien ainsi, lorsque vous être sur un nouveau TG, vous pouvez quand même voir apparaitre l’indicatif radio et le nom de l’OM/YL qui parle. Plus pratique à retenir qu’un CSS7 composé de 7 chiffres absconds.

Différentes sources vous proposent de télécharger cette fameuse liste de contact :

Le problème

Les contacts sont extraits tels quels sans considération pour le jeu de caractères utilisé par la radio. Résultat, les accents et autres caractères spéciaux apparaissent « déformés » ou remplacés par des points d’interrogation.

Le problème vient clairement du CPS (customer programming software) d’Anytone et non du fichier d’import car en saisissant le nom, il apparait correctement jusqu’à la sauvegarde et la réouverture du fichier.

Première solution le charset (ça ne fonctionne pas)

Choix jeu de caractères AnytoneEn cherchant un peu, j’ai remarqué que le CPS offrait le support de trois jeux de caractères

  • ISO7
  • ISO8
  • Unicode

Il s’agit peu ou prou de la même chose, chaque fois, mais je me suis dit « qui sait, peut-être que l’un d’eux résoudra mon problème ».

Seconde solution supprimer les accents (oui mais…)

Plus facile à dire qu’à faire. On m’a naïvement suggéré de remplacer les quelques accents que l’on utilise le plus fréquemment en français, hélas la base de données et mondiale et le nombre de caractères spéciaux est assez impressionnant.

Ajouter à cela le temps pour effectuer un seul « rechercher/remplacer » dans un fichier Excel de 200 000 lignes ou dans le bloc-notes de Windows… et je ne vous parle même pas de Notepad++ qui plante purement et simplement.

J’ai tenté de recopier une macro, mais là aussi le temps est inimaginable (je soupçonne aussi Excel de planter pendant le traitement).

 

Ma méthode

Objectifs

  • Limiter le temps de traitement
    • Ne pas y passer plus de 15 minutes de mon temps
    • Ne pas devoir laisser tourner la macro toute une nuit
  • Vérifier qu’il n’y a pas de plantage en affichant un compteur indiquant la ligne en cours de traitement
  • Automatiser au maximum : limiter la préparation du fichier en entrée pour pouvoir mettre à jour la liste en toute simplicité.

Organisation du travail

Dans un premier temps, je répertorie les caractères spéciaux présents. L’idée est de traiter un maximum des caractères courants et d’identifier les caractères plus rares afin de ne pas avoir à traiter le minimum de caractères spéciaux ce qui revient à limiter le temps de traitement (mon premier objectif).

Pour ce faire, je remplace une par une les 26 lettres de l’alphabet et les signes de ponctuations dans le Bloc-notes de Windows. Pourquoi le Bloc-notes de Windows parce que les logiciels plus avancés plantent ou prennent bien plus de temps a effectuer l’opération alors qu’une simple Expression Régulière [A-Z][a-z] aurait permit de sélectionner tous les caractères à supprimer en une fois ☹

Sub SupprimerCaracterNormaux(zone)
  Rem On ne supprime surtout pas le caractère 42 = *.
  Rem On supprime la ponctuation (code ASCII 33 à 41).
  For i = 33 To 41 
    Range(zone).Replace What:=Chr(i), Replacement:="" 
  Next i

  Rem On supprime les symboles mathématiques et les chiffres (code 43 à 62).
  For i = 43 To 62
    Range(zone).Replace What:=Chr(i), Replacement:="", MatchCase:=False
  Next i   

  Rem On ne supprime surtout pas le caractères 63 = ?.
  Rem On supprime les lettres (64 à 90) et encore quelques symboles.
  For i = 64 To 96
    Range(zone).Replace What:=Chr(i), Replacement:=""
  Next i

  Rem On supprime encore les accolades.
  For i = 123 To 125
    Range(zone).Replace What:=Chr(i), Replacement:=""
  Next i

  Rem On supprime les espace et les virgules.
  Range(zone).Replace What:=" ", Replacement:=""
  Range(zone).Replace What:=",", Replacement:=""
End Sub

 

Ensuite, je vérifie les colonnes vides. Supprimer les colonnes vides permet d’accélérer les traitements ultérieurs.

Sub Concatener()
  Rem On nettoie les caractères ASCII pour rendre possibles les traitements ultérieurs.
  SupprimerCaracterNormaux ("A:J") 

  Rem On fixe le nombre de ligne que lequel travailler
  nb_lignes = 240000 

  Rem Insertion d'une colonne qui recevra tous les caractères de chaque ligne.
  tous_caractere = WorksheetFunction.Concat(Range("A1:J" & nb_lignes)) 

  Rem Création d'une colonne ou figurera chaque caractère trouvé, un à un dans une case.
  Columns(1).Insert 
  For i = 1 To Len(tous_caractere)
    Cells(i, 1) = Mid$(tous_caractere, i, 1)
    Range("L1") = i
  Next i

  Rem Suppression des doublons : on tri d'abord la colonne.
  With ActiveSheet.Sort
    .SortFields.Add Key:=Columns("A:A")
    .SetRange Columns("A:A")
    .Apply
  End With

  Rem Suppression des doublons.
  ActiveSheet.Range("A:A").RemoveDuplicates Columns:=1 

  Rem Suppression des caractères ASCII restants à l'aide de la fonction ci-dessus.
  SupprimerCaracterNormaux ("A:A")
End Sub

Une fois chaque caractère identifié j’ai créé un tableau de correspondance pour savoir par quelle lettre le substituer, hélas, nous obtenons une liste de 800 caractères, je ne m’attendais pas à autant.

Si on y regarde de plus près, nous avons :

  • Des signes de ponctuations exotiques
    Signes de ponctuation exotiques
  • Des symboles ressemblant à des caractères latins mais qui n’en sont pas si on regarde leur code ASCII
    Symboles ressemblant à des caractères latins qui n’en sont pas
  • Des caractères latins accentués
    Caractères latins accentués
  • Des caractères grecs (on trouveras la translitération sur Wikipédia notamment)
    Caractères grecs
  • Des caractères cyrilliques (la translitération se trouve aussi sur Wikipédia)
    Caractères Cyrilliques
  • Des caractères asiatiques
    • Japonais
      Caractères japonais
    • Thaï
      Caractères Thaïs
    • Coréen
      Caractères coréens
    • Chinois (400 symboles, soit la moitié de la liste)
      Caractères chinois

Devant la charge de travail représentée par la translitération des caractères asiatiques, j’ai décidé de ne travailler que sur les caractères latins. J’ai créé un tableau de correspondance pour savoir par quelle lettre le substituer puis une formule Excel pour créer les ligne de substitution en VBA.

=".Add"""&A1&""", """&B1&""""

A1 est le caractère à remplacer et B1 le caractère de remplacement.

Et là, c’est le drame ! Une fois toutes les chaines de substitution copiées dans l’éditeur VBA, je m’aperçois que seuls certains caractères accentués subsistent, les langues asiatiques font défauts ainsi que quelques caractères spéciaux exotiques.

Caractères en erreur

Il me faut donc supprimer tous ces caractères, premièrement parce que le dictionnaire de substitution ne peut contenir qu’une seule fois chaque caractère à remplacer et deuxièmement le point d’interrogation est considéré comme un joker qui signifie « n’importe quel symbole » et donc tous les caractères du fichier seraient remplacés ce qui serait un peu gênant.

Au final, il ne reste plus que 65 caractères remplaçables, ce qui devrait considérablement accélérer le traitement.

Caractères restants

Le code VBA s’exécute en quelques dizaines de secondes et ressemble à cela :

Sub remplacer()
  Set replacements = CreateObject("Scripting.dictionary")
  With replacements
    .Add "–", "-"
    .Add "~", ""
    .Add "¡", "i"
    .Add "¦", "|"
    .Add "¨", ""
    .Add "´", "'"
    .Add "¸", ""
    .Add "¿", ""
    .Add "’", "'"
    .Add "‚", ","
    .Add "“", '"'
    .Add "”", '"'
    .Add "‹", "<" .Add "›", ">"
    .Add "¤", ""
    .Add "¥", "Y"
    .Add "±", ""
    .Add "©", "(c)"
    .Add "°", "o"
    .Add "¶", ""
    .Add "•", "."
    .Add "ƒ", "f"
    .Add "„", '"'
    .Add "…", "..."
    .Add "‡", ""
    .Add "Ÿ", "Y"
    .Add "¼", "1/4"
    .Add "½", "1/2"
    .Add "¾", "3/4"
    .Add "²", "2"
    .Add "³", "3"
    .Add "ª", "a"
    .Add "Á", "A"
    .Add "à", "a"
    .Add "â", "a"
    .Add "ä", "a"
    .Add "Ã", "A"
    .Add "å", "a"
    .Add "Æ", "AE"
    .Add "ç", "c"
    .Add "é", "e"
    .Add "è", "e"
    .Add "ê", "e"
    .Add "ë", "e"
    .Add "í", "i"
    .Add "ì", "i"
    .Add "Î", "i"
    .Add "ï", "i"
    .Add "ñ", "n"
    .Add "º", "o"
    .Add "ó", "o"
    .Add "ò", "o"
    .Add "ô", "o"
    .Add "ö", "o"
    .Add "Õ", "o"
    .Add "Ø", "e"
    .Add "œ", "oe"
    .Add "š", "s"
    .Add "ß", "ss"
    .Add "ú", "u"
    .Add "ù", "u"
    .Add "ü", "u"
    .Add "ý", "y"
    .Add "ž", "z"
  End With

  For Each Key In replacements.Keys
    Value = replacements(Key)
    If Key <> Value Then
      Range("A:J").Replace What:=Key, Replacement:=Value, LookAt:=xlPart
    End If
  Next
End Sub

Et voilà !
Si vous avez des remarques, des suggestions, des questions, n’hésitez pas ➡️ utilisez les commentaires ⬇️

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.