Connecter Dynamo à Microsoft Access

Olivier Bayle Olivier Bayle 17/05/2016

5 min de lecture

image

 

Encore une façon d’augmenter les possibilités de Dynamo est de le connecter à une base de données de type Microsoft Access. C’est ce que propose mon collègue Italien Stefano Toparini sur son blog  dal BIM in poi.…

Stefano, à partir de Dynamo Studio (et non Dynamo for Revit) et du package Lunchbox, nous montre qu’il est possible de lire une base de données Access. Pour réaliser cet exploit, il a du créer son propre nœud en langage Python.

Je vais vous en faire l’explication (exercice difficile mais à cœur volontaire…).

Le nœud s’appelle “ReadAccessTable”. Pour découvrir le code Python, double cliquer sur le nœud, puis clic droit “Edit” sur le nœud python script”.

image

 

Le nœud accepte trois paramètres, dont seule le premier est obligatoire:

image

 

 

image

 

 

image

Essayons de détailler son code:

Partie Importations de modules et déclarations :

 

image

 

Important : cette partie permet d’importer la classe “Access” issue du module “Microsoft.Office.Interop”.

La ligne “ac.Visible = False”  évite d’afficher l’interface Access.

Le mot clé “try:” permet d’essayer un “ bout de code”. Si une erreur est rencontrée, on cesse d'interpréter le code et on passe à l’autre mot clé “except:”. De cette façon cela évite de bloquer dans une boucle et d’agir en fonction de l'erreur qui s'est produite.

Donc :

ac.OpenCurrentDatabase(IN[0]): ouvre la base dont le chemin est contenue dans la variable”IN[0]” (première entrée de script python),

ac.Quit” : méthode qui permet de quitter Access. 
sys.exit(0) : sortie de Python avec le statut de sortie zéro.

Enfin :

database = ac.DBEngine”: assigne de la variable “database” au moteur de base de données.

wrks = database.Workspaces(0)” : alloue la variable “wrks ” à la collection “Workspaces” représentant un espace de travail au sein du moteur de base de données.

db = wrks.Databases(0)” : attribut de la variable “db “ à la collection “Databases” regroupant l'ensemble des objets “Database” ouverts dans l'objet “Workspace” correspondant.

 

1- Partie “si aucun nom de table est affecté” au script python :

 

image

 

if IN[1] == None :” : si la deuxième entrée (“Nom de la table”) est vide, il va faire ce qui suit sinon il saute au code situé en dessous de “else:” (explication partie suivante).

La variable ts récupère le nombre d'objet dans la collectiondb.

tables” : création d’une variable vide de type tableau.

for t in db.TableDefs :” réalise une boucle de t=0 jusqu’au nombre d’objet dans la collectiondb.

Nota : l’auteur aurait pu écrire “for t in ts:

if not t.Name.startswith('MSys') : filtre les éléments dans la liste qui ne commence pas par le texte 'MSys'. Dans le cas contraire, nous aurions ce résultat :

 

image

 

Donc si la condition n’est pas respectée, “tables.append(t.Name)” permet d’enregistrer dans la table la valeur à l’indice “t”.

OUT = tables” donne comme résultat de la variable tableau “tables” comme résultat du script python.

 

2- Partie si un nom de table est affecté  :

 

image

 

Le “else:” en début permet de rentrer dans cette boucle dans le cas où une table est affectée.

if IN[2] == None :: si la variable d’entrée du script phyton “IN[2]” n’est pas attribuée (sinon on passe au “else : suivant, voir plus loin).
    “rs = db.OpenRecordset(IN[1]) : la méthode “OpenRecordset” assigne à la variable “rs” du nom de la table de la base de données.
    “fields = []” : création d’une variable “fields” vide de type tableau.
    “for f in rs.Fields : : réalise une boucle jusqu’au nombre de champs dans la collectionrs.
        “fields.append(f.Name) : enregistre dans la tableau “fields” la valeur des champs à l’indice “f“.
else: “ : si la variable d’entrée du script python “IN[2]” est attribuée, on passe au code ci-dessous:

q = 'SELECT ' + IN[2] + ' FROM ' + IN[1] : la variable est la concaténation de mots (SELECT et FROM) et de la deuxième (nom de la table de la base de données) / troisième variable (liste des valeurs) d’entrée du script python.
rs = db.OpenRecordset(q)” : la méthode “OpenRecordset” qui attribue à la variable “rs” du nom de la table de la base de données indiquée par la variable “q” (requête SQL).
fields = IN[2].split(",")” : création d’une variable “fields”  de type tableau dans laquelle on supprime le symbole de type “virgule” issue des différentes données.
for i in range(len(fields)) : “ effectue un boucle de i=0 au nombre de champs “(Len(Fields)”.
fields[i] = fields[i].strip()” : supprime les espaces de chaque champ.

Enfin la dernière partie :

rows = []” : création d’une variable de type tableau vide (attention variable au pluriel).
while not rs.EOF:” : boucle de type “tant que l’on n’est pas” balaye tous les champs jusqu’a la fin du fichier – End Of FIle.
row = rs.GetRows(1)” : la méthode “GetRows(1)” extrait une seule ligne de la base de donnée et l’affecte à la variable “row” (en fait on effectue cette opération ligne par ligne).

Attention, “row” (au singulier) est une nouvelle variable non déclarée. 
rows.append(row)” : la méthode “append” ajoute l’enregistrement de la variable “row” dans à la variable de type tableau “rows”.

OUT = [fields, rows]” : en fin de boucle, nous restituons au script python les deux variables :

– “fields” : les intitulés du tableau.

– “rows” : les valeurs des champs.

"ac.Quit” : méthode qui permet de quitter Access (libère la mémoire).

J’espère que j’ai été assez clair car comme vous avez pu le voir ce n’est pas si facile à expliquer.

Vous trouverez la totalité de l’article de mon confrère Italien ici avec le téléchargement de son exemple (en fin d’article).

Bravovisimo Stefano et grazie pour ton billet.

Abonnement e-mail