vendredi 28 mars 2014

Paramétrer un lecteur code barre Sumikon (de chez Pearl)

Acheter un lecteur code barre a toujours été une idée que j'ai repoussé à cause du prix. Heureusement, les prix de ces lecteurs se sont démocratisés. J'ai acheté le mien pour 39€.


Malheureusement, il n'a pas voulu fonctionner, loi de Murphy oblige. J'ai perdu pas mal de temps pour y arriver. Le symptôme était simple: à chaque fois que je scannais un code barre de livre ou de CD (constitué de 13 digits), j'obtenais à la place une série de lettres.

J'ai donc fait une demande au support de mon vendeur, sans succès: celui-ci m'enjoignait de paramétrer mon lecteur code barre en majuscule, ce qui n'a eu aucun effet positif, mis à part récupérer la même série de lettres mais cette fois en majuscules.

Ma méthode pour trouver le bon paramétrage fut d'essayer systématiquement tous les codes de paramétrages imprimés dans le livret "mode d'emploi". Voici la méthode:

- Ouvrir un éditeur de texte pour afficher chaque test de lecture d'un code barre (un livre par exemple, et toujours le même évidement).
- A chaque test, je scanne  "Paramétrages d'usine".
- Je scanne"Démarrer réglages"
- Je scanne alors un paramètre (un à la fois dans un premier temps, et l'un après l'autre)
- Je scanne"Arrêter réglages"
- Je teste à nouveau (dans l'éditeur de texte)
- Si j'obtiens encore des lettres, je recommence avec un autre paramétrage (sans oublier "Paramètres d'usine")

Voici donc la solution qui m'a permis de résoudre mon soucis:
  • je scanne  "Paramétrages d'usine".
  • Je scanne"Démarrer réglages"
  • Ensuite paramétrage "Francais" page 48 de mon livret mode d'emploi.
    Ce paramétrage est dans la catégorie "réglages de base", sous rubrique "réglage de la langue".
  • Pour finaliser, paramétrage du caractère de fin de lecture: "CR"
    (au lieu de "CR-LF")
  • Puis "Arrêter réglages"
  • Penser à scanner la fonction "Enregistrer réglages" à la fin, sous peine de devoir recommencer ce paramétrage lors du prochain branchement du code barre.

Et depuis, ce lecteur de code barre est un véritable plaisir. Je regrette d'avoir attendu si longtemps, tant le gain de temps est significatif. Je signale que j'utilise ce code barre sous lubuntu (linux) sans aucun soucis. Je vais pouvoir travailler dorénavant sur la saisie de mes collections de livres, CD, DVD et autres.

vendredi 21 mars 2014

Sudoku: aide à la résolution sous Libre Office Calc (plutôt qu'Excel)

Une des choses qui caractérise un véritable geek, c'est sa manière de résoudre des problèmes simples à l'aide de solutions complexes.
C'est pour cela que je me suis donné comme objectif de résoudre un Sudoku, à l'aide d'un tableur (Libre Office Calc plutôt qu'Excel). Avec une contrainte (sinon c'est pas drôle): ne pas utiliser le langage de programmation du tableur. C'est donc à l'aide des fonctions natives du tableur (exemple RechercheV), et de la mise en forme conditionnelle (Exemple, colorer en rouge les doublons d'une grille).
Et voilà le résultat, après une bonne journée de travail (avec l'age on apprécie prendre son temps). J'ai surtout dû réapprendre à utiliser Libre Office Calc.


Le fichier est réalisé avec Libre Office Calc (v4.1.5.3). Il contient 3 onglets:
  1. Onglet "grille"=> à remplir uniquement avec la grille de départ
  2. Onglet "vérification" =>C'est cette grille qu'il faut remplir et qui permet en temps réel de vérifier l'absence de doublons
  3. Onglet "possibilités" => cet onglet permet de 'tricher' en affichant les cases faciles à remplir

Il doit rester quelques bugs, mais globalement il fonctionne. Il reste encore quelques cases inutiles (suite à des essais itératifs), mais l'essentiel est opérationnel. Je vous entend déjà dire qu'en C ou en PHP, on aurait pu le faire plus simplement. Mais parfois, c'est justement dans l’adversité que l'on trouve du plaisir.
A noter que ce fichier n'est pas compatible Excel (il pourrait l'être à peu de frais). Mais je préfère des outils pérennes dans leur forme et leur ergonomie, contrairement à Microsoft qui tous les 3 ou 4 ans révolutionne les deux sans aucune justification, mettant dans la panade des millions d'utilisateurs. Ce fichier Suduko sera ma petite contribution pour tenter de désintoxiquer les utilisateurs de MS Office.

Fichier pour résoudre un Suduko (à télécharger)
Règles du Sudoku

mercredi 1 janvier 2014

Xlib, C magnifique (avec l'exemple de WM_NAME)

Et oui, je suis membre de la petite minorité de personne aimant programmer directement en X11 avec Xlib. Je ne suis pas un foudre de programmation, mais plutôt un dilettante de la programmation C. Le fait d'utiliser Xlib directement est pour moi comparable à faire un Sudoku: C'est long, parfois ennuyeux, toujours sources d'erreur, magnifiquement vain, mais tellement distrayant. On peut ainsi passer une journée entière pour parvenir simplement à afficher une simple fenêtre à l'écran avec Xlib. Pour résumer, Xlib est une API (liste de fonctions) permettant de programmer pour X Windows et dont la dernière version est la version nommée X11.

Xlib est pour distrayante, car elle oblige à devoir passer un temps fou sur la toile pour glaner quelques infos ou tutoriels, car contrairement aux librairies graphiques plus évoluées (exemple GTK, Xt, Qt), on doit lire des pages et des pages de sites ou de documentation avant de comprendre le début d'une explication pour les choses les plus simples.

Prenons l'exemple par exemple d'une fonction permettant de déterminer le nom d'une fenêtre X (au sens X11 évidement). Cette simple fonctionnalité est déjà toute une histoire, car on doit s'intéresser à un élément périphérique à X11: le Window Manager (WM pour les initiés ou pour les amis les plus proches). Le WM est le chef d'orchestre des fenêtres dans X11. Il possède évidement des privilèges spécifiques lui permettant d’exécuter les tâches qui lui sont dévouées, comme par exemple gérer la barre de titres et différentes "décorations" associées à une fenêtre (cette fois au sens du WM).

Dans mon cas personnel, j'utilise le WM le plus simple, celui qui est inclus à Lubuntu: OpenBox. Normalement, l'usage des nom des fenêtres (ceux qui apparaissent par exemple dans le gestionnaire de taches par exemple), n'est pas tributaire de votre WM. En théorie, l'exemple suivant devrait fonctionner quelques soit votre WM.

Donc voici le résultat de mes recherches: une fonction C permettant de récupérer les noms de chaque fenêtre actives dans X:

/*----------------------------------------------
 * Fonction récupérant le nom d'une fenêtre
 * retour=0 si problème
 * sinon retour=1
 * Le nom_fentre est un buffer fourni par l'appelant
 * dont la longueur est spécifié en argument
 * --------------------------------------------*/
int X11vb_recuperer_nom_fenetre( Display * d, Window w, char * nom_fenetre, int nb_c_nom_fenetre)
{
char **liste;
int i=0;
XTextProperty text_property;

if (nb_c_nom_fenetre<1 class="Apple-tab-span" span="" style="white-space: pre;">
return 0; nom_fenetre[0]=0;

//---- récupération de la property texte WMName
if(!XGetWMName (d, w, &text_property))
{
return 0;
}
if (!XTextPropertyToStringList( &text_property, &liste, &i))
{
printf("XStringListToTextProperty - out of memory\n");
return 0;
}
if (!i)
{
printf("XTextPropertyToStringList=>liste=0\n");
return 0;
}
if (!*liste)
{
printf("XTextPropertyToStringList=>liste[0]=vide\n");
return 0;
}
//------ copie du résultat
strncpy(nom_fenetre, *liste, nb_c_nom_fenetre);
nom_fenetre[nb_c_nom_fenetre-1]=0;
XFreeStringList(liste);
return 1;
}

Pour l'utiliser, voici un source additionnel pour par exemple lister les fenêtres qui possède un nom (et oui, toutes les fenêtre n'ont pas de nom, et pourtant nullement orpheline).

#include
#include
#include
#include
#include
#include



int X11vb_recuperer_nom_fenetre( Display * d, Window w, char * nom_fenetre, int nb_c_nom_fenetre);

// ERROR HANDLER, GENERIC
static int ErrorHandler (Display *display, XErrorEvent *error)
{
   //printf ("\r\n error! \r\n");
   return 0;
}
// END ERROR HANDLER



void ListerWindows (Display *display, Window window, int niveau, char * filtre)
{
static int nb_w=0;
Window parent;
Window root;
Window *enfant;
XWindowAttributes windowattr; 
int nb_enfant=0;
int i=0, h=0, l=0, x=0, y=0;
char nom_fenetre[40]; //---le nom de la fenêtre affiché sera limité à 39 caract.
   
if (filtre) if (!*filtre) filtre=NULL;

//-----récupérer le nom de la fenêtre
if (!X11vb_recuperer_nom_fenetre(display, window, nom_fenetre, sizeof(nom_fenetre)))
*nom_fenetre=0; ;
//---- attributs de la fenêtre
if (XGetWindowAttributes(display, window,   &windowattr) == 0)
printf("failed to get window attributes");
else
{
x= windowattr.x;
y= windowattr.y;
l= windowattr.width;
h= windowattr.height;
}
// les enfants de cette fenêtre----
if (!XQueryTree (display, window, &root, &parent, &enfant, &nb_enfant))
nb_enfant=0;
if (*nom_fenetre)
{
if (!filtre || strstr(nom_fenetre, filtre)) 
printf ("%03i (niv.=%i; enfant=%i) - window: '%s' (x=%i,y=%i;L=%i,H=%i) w=%i\r\n", ++nb_w, niveau,nb_enfant, nom_fenetre, x,y,l,h,(int)window);
}

for (i=0; i < nb_enfant; i++)
ListerWindows (display, enfant[i], niveau+1, filtre);
   
XFree ((char*) enfant);
}


int main(int argc, char *argv[])
{
   // CONNECT TO THE XSERVER
   Display *display;
   int depth;
   int screen;
   int connection;
   char *filtre=NULL;
   Window rootWindow;
      
   display= XOpenDisplay (NULL);
   screen= DefaultScreen (display);
   depth= DefaultDepth (display, screen);
   connection= ConnectionNumber (display);
   XSetErrorHandler (ErrorHandler);
   
   printf ("Lister X11 window ayant un nom pour le Window Manager (WMName)\r\n");
   printf ("--------------------------------------------------------------\r\n");
   printf ("Display: %s\r\n", XDisplayName((char*)display));
   printf ("Width: %d\r\n", DisplayWidth(display, screen));
   printf ("Height: %d\r\n", DisplayHeight(display, screen));
   printf ("Connection: %d\r\n", connection);
   printf ("Color Depth: %d\r\n", depth);
  
   
if (argc>1)
filtre= argv[1];
if (filtre)
printf("=====>filtre sur le nom des fenêtres contenant:%s\n",filtre);
else
printf ("--en option:\r\n--mettre en argument un filtre sur le nom\r\n");
rootWindow = RootWindow (display, screen);  
ListerWindows (display, rootWindow, 0, filtre);
XCloseDisplay (display);

return 0;
}


Pour ne rien oublier, voici le makefile que j'utilise. Vous pourrez donc le tester en réel sur votre machine linux, si votre gcc (compilateur C) est opérationnel.

liste_w: lister_w.c
gcc -o lister_w lister_w.c -L/usr/X11R6/lib -lX11

On peut remarquer à quel point cet exemple est délicieusement complexe pour une opération aussi élémentaire. Pour être complet sur la question, vous avez un utilitaire permettant globalement de faire la même chose en ligne de commande sous linux: xdotool. Un petit tour sur la page d'aide de cet utilistaire vous permettra d'en comprendre toute la puissance. Il peut par exemple vous permettre d'envoyer des touches 'clavier' vers une X window. xprop et xwinfo sont deux utilitaires qui complète xdotool.

Liens:
Excellente page Wiki sur Xlib
Livre important: Xlib programming manual Volume 1.
Page du source que j'ai adapté et adopté





lundi 9 décembre 2013

Ne pas croire au Père Noël peut nuire gravement à l'innovation.

Il est loin le temps où la France se targuait d'avoir des idées à défaut de posséder du pétrole. Aujourd'hui est venu d'être également à court d'idée ou d'envie d'en avoir.

Prenons l'exemple coquasse du dernier poisson d'Avril de la Poste (en 2013), qui affirmait tester des drones pour acheminer des journaux à domicile. Après une levé de bouclier des syndicats, la Poste avoue rapidement la supercherie. C'était une blague de potache. Ouf!
Sauf que quelques mois plus tard, Amazon annonce fièrement une expérimentation équivalente, mais c'est fois c'est du sérieux. Et oui, la Poste invente le Poisson d'Avril version boomerang, celui qui revient à l'envoyeur pour le ridiculiser. Dans la même catégorie, nous attendons que Renault nous avoue officiellement que leur première voiture électrique (celle livrée sans porte) était un poisson d'Avril, et non un véritable produit destiné à être vendu (cela tombe bien, personne ne l'achète).

Mais pourquoi en France nous poussons notre manque d'innovation jusqu'au bout de la plaisanterie?
L'article de ZD (ci-dessous) imagine que notre tradition est peut-être en cause: elle nous pousserait à être trop raisonnable, trop sage, alors qu'ailleurs, ils n'ont pas peur de croire au Père Noël et de s'enchanter à inventer l'avenir. Et pourtant, nous avons dans le passé, surpassé ces contraintes, avec le Minitel, Airbus, le TGV, et d'autres innovations. A cette époque, nous avons prouvé notre capacité et notre envie d'y croire jusqu'au bout. Depuis un vent de résignation souffle sur notre société: La voiture sans permis, l'ascenseur pour l'espace, le tube sous vide pour traverser les continents, ou même la voiture électrique risque bien de venir d'ailleurs. Mais aurons toujours les moyens d'en profiter?

Pauvre Père Noël.


Article relatant le coquasse de l'affaire
Les pères Noël ne sont plus ce qu'ils étaient

vendredi 23 août 2013

(Recherche internet + copier/coller) est devenu un usage normal pour les développeurs




C'est une réflexion qui m'a choquée.
Il y a plus de 20ans, on apprenait un langage en lisant un livre, en passant beaucoup de temps à apprendre la méthode et la syntaxe. Il fallait plusieurs semaines avant d'oser dire que l'on pratiquait un langage. Pour l'anecdote, mon premier langage fut le basic du ZX80 de Sinclair que j'ai appris sans jamais posséder l'ordinateur, mais en lisant tout simplement le livre associé (qu'un ami m'avait prête), car la commande de mon ZX80 n'est jamais arrivée à cause du succès de ce petit ordinateur destiné au plus grand nombre. Tout cela, c'était avant internet. Aujourd'hui, on apprend un langage en une journée, cela signifie que l'on passe à coté de nombreuses points essentiels: la méthode, la connaissances des insuffisances, les moyens de les contourner, etc..
Moi-même aujourd’hui, j'utilise internet et le copier/coller, même pour les instructions les plus élémentaires, et pour des langages que j'ai pratiqué de longue date (PHP, VBA, C). J'ai tenté de déterminer les raisons pour expliquer ce phénomène. Voici 2 des raisons me poussant à utiliser le copier/coller:
1 - Je ne suis plus un développeur à plein temps, et ma mémoire manque d'entrainement
2- Les documentations (VAB par exemple), ne sont pas agréables, ni pour l'apprentissage (c'est une catastrophe sur ce point), ni pour les développeurs (l’absence en particulier d'un moteur de recherche efficace et comparable à google).

Il faut également ajouter l'esprit "zapping" de nos cerveaux d'aujourd'hui. Le temps va trop vite, les yeux et les cerveaux ne parviennent plus à fixer les informations qui défilent devant nous. Nous sommes drogués à la quantité d'information, et nous de passons plus assez de temps à "digérer" cette quantité. A cela s'ajoute malheureusement une dilution importante des bonnes informations noyées dans un flux de très mauvaises qualités. Il est loin le temps où un livre comme le Kernighan & Ritchie (langage C), était un plaisir de lecture tant par sa clarté que par sa pédagogie donnant envie d'apprendre. Maintenant les outils sont souvent obscurs et mal documentés.

Le constat est terrible: le copier/coller est devenu primordial pour un développeur. Je ne suis même pas certain que la productivité y gagne. En revanche, une certaine paresse et un conformisme certain risquent de s'installer durablement dans nos habitudes de développement.

jeudi 22 août 2013

Excel: solution pour générer un classeur contenant plusieurs fichiers CSV

C'était un petit problème qui a ennuyé la plupart des utilisateurs de base de données :
Comment générer automatiquement un fichier Excel contenant plusieurs CSV (à partie d'une base de données par exemple).
Toutes les bases de données sont capables d'exporter une table vers un classeur Excel en utilisant le format CSV, ce format étant reconnu automatiquement par Excel. En revanche, pas moyen d'exporter plusieurs tables d'une base de données vers un unique classeur Excel, avec un onglet par table. Cette impossibilité est la conséquence (entre autre) du format propriétaire d'Excel. Voici une astuce permettant de "créer" ce fichier Excel.

Voici la marche à suivre (avec Excel 2003):
  1. Exportez vos tables vers des fichiers CSV, le tout dans un même répertoire .
  2. Ajoutez dans le même répertoire le fichier Excel disponible plus bas.
  3. Ouvrez le fichier Excel: le chargement des fichiers CSV se fera automatiquement.
Explication:
Ce fichier Excel est un classeur contenant un seul onglet, lui-même contenant une macro en charge d'importer tous les fichiers CSV présent dans le même répertoire. Cette macro se lance automatiquement, mais uniquement si les fichiers n'ont pas été déjà importés lors d'une précédente ouverture. Par la suite, l'opération peut-être reproduite manuellement en modifiant les paramètres présents dans l'onglet 'utilitaire", comme par exemple le préfixe des fichiers à importer.

Voici la copie d'écran de l'onglet "utilitaire" permettant de reproduire l'opération, autant de fois qu'il vous plaira.


Alors me direz vous, cela ne permet pas réellement de générer automatiquement un fichier Excel incluant plusieurs CSV. En revanche, si vous avez besoin d'envoyer automatiquement ce fichier,  rien de plus simple de créer un Zip contenant tous les CSV en question, en incluant ce fichier Excel. Le destinataire (ou vous même) n'auront plus qu'à dézipper la totalité des fichiers dans un nouveau répertoire, pour permettre d'obtenir le même résultat, au moment de l'ouverture du fichier Excel du répertoire.

Ce fichier Excel est utilisable tel quel, mais est facile à adapter selon votre besoin si vous connaissez un minimum de VBA. Personnellement, j'ai ajouté la suppression des fichiers importés à postériori, un renommage du fichier Excel après le chargement, et la gestion automatique des préfixes et suffixes.

En espérant que ce petit fichier vous sera utile.

Lien:
Fichier Excel (version 2003) pour charger automatiquement les fichiers CSV présent dans le même répertoire.



lundi 19 août 2013

Excel le problème de l'importation de fichier CSV avec le point virgule comme délimiteur

Voici un des exemples de pseudo bug qui peuvent perdre une bonne demi-journée. Mon but était d'importer un fichier CSV dans un onglet Excel, à l'aide la macro OpenText (méthode associée à Workbooks). Normalement aucun soucis: pour importer un fichier avec comme séparateur le point virgule (";"), il suffit d'écrire cela:

 Workbooks.OpenText _
   Filename:="toto.csv", _
   DataType:=xlDelimited, _
   Semicolon:=True


Et bien non, cela ne marche pas avec mon Excel 2003. J'ai tout essayé: jouer avec tous les paramètres, changer le type de fin de ligne (LF => CR-LF), et autre gris-gris. A chaque fois, l'importation ne se faisait que sur une colonne. Seul le caractère virgule fonctionnait pour délimiter les colonnes. Le pire, c'est que cela fonctionnait parfaitement avec la méthode Open (l'équivalent de la fonction 'Open' du menu) sans arguments particuliers.

En cherchant sur internet, j'ai découvert que l'extention du fichier à importer devait être .txt. En renomant l'extention du fichier de CSV en TXT, tout fonctionne:


Name  "toto.csv" as "toto.txt"
Workbooks.OpenText _
   Filename:="toto.txt", _
   DataType:=xlDelimited, _
   Semicolon:=True


Et pourquoi? J'ai même pas envie de savoir pourquoi. L'informatique est remplie de bizarreries de ce type, parfaitement illogique, mais toujours chronophage. Merci au forum qui ma donnée la solution.

Voici ce qu'il faut retenir:
Si on tente d'importer un fichier avec l’extension .CSV avec la méthode OpenText, le point virgule ne peut pas être utilisé comme délimiteur, seule la virgule simple fonctionne. Dans ce cas, l’extension .TXT est obligatoire.

Bon courage à vous pour le prochain bug de ce genre.

Doc MicroS.
Merci à ce forum