Un fichier Excel fourre-tout

Inclure un fichier quelconque dans un fichier Excel puis le récupérer


On sait inclure, dans une page Excel, un fichier quelconque (fichier texte, fichier son, fichier image...) en utilisant la commande : Insertion / Objet / Créer à partir du fichier....
Pour ouvrir le fichier inclu, il suffit de double-cliquer sur son icone dans le fichier Excel.
On peut bien sûr programmer toutes ces opérations par VBA.

Par contre, à partir d'un fichier ainsi "encapsulé" dans une page Excel, il est difficile de recréer une copie du fichier initial.
Par exemple, comment enregistrer un fichier .wav à partir du fichier son encapsulé dans Excel ?

Imaginons un programme VBA qui nécessite plusieurs fichiers (son, image..) en plus du fichier Excel. En général, tous les fichiers sont transmis à l'utilisateur sous forme d'archive zip, charge étant laissée à l'utilisateur d'installer chacun des fichiers dans le répertoire adéquat avant de lancer la macro... La procédure est un peu laborieuse et manque d'élégance.
L'idéal serait de partir d'un fichier Excel contenant tous les fichiers annexes sous forme encapsulée, l'ouverture de ce fichier Excel provoquant l'installation automatique des fichiers annexes. Il nous faut donc être capable d'insérer et de désinsérer à la demande par macro, des fichiers dans une page Excel.

Le fichier Excel deviendra ainsi un fichier valise fourre-tout !

Le fichier Excel proposé au téléchargement (cliquez ici) contient quatre fichiers son (.wav, .mp3 et .mid), deux fichiers textes (.doc et .txt), quatre fichiers image (.bmp, .gif, .ico), un fichier html, un fichier Excel et un fichier .zip (le raton-laveur ne tient pas).
Dans la page Excel se trouvent deux boutons,
- le premier donne accès à l'arborescence des fichiers présents sur le disque dur. Il suffit d'en sélectionner un pour qu'il soit inséréré dans le fichier Excel.
- le second permet de recopier sur le disque dur un des fichiers inclus dans la page Excel (enregistrement directement sur c:\).

Comment ça marche ?

Le fichier à insérer est stocké octet par octet, tout simplement dans les cellules du fichier Excel.
Pas de difficulté à cela :
Le fichier à insérer est ouvert en lecture par Open (le nom complet du fichier est fich) :
Open fich For Binary Access Read As #1

puis lu par paquets d'octets grace à Input :
octt = Input(1024, #1)
'(lit un kilooctet du fichier #1)

Reste à inscrire les octets dans une cellule. Petite difficulté, une fois collés dans une cellule, les caractères acsii sont transformés en texte, avec comme principal inconvénient la perte de tous les espaces (chaines vides, CHR(0)) séparant les paquets de données dans le fichier initial.
Impossible de trouver un 256 ème caractère pour enregistrer ces chaines vides.
Une solution brutale consiste à transformer chaque caractère en une chaine de trois chiffres correspondant à leur code ascii (utilisation de la fonction Asc). Le caractère chr(0) peut ainsi sans problème être codé par 000.
Cette méthode fonctionne près bien, mais présente un gros inconvénient : chaque octet est codé sur 3 chiffres au lieu d'un seul caractère. Le fichier encapsulé par cette méthode tient donc beaucoup de place.
Autre inconvénient, les opérations de codage et décodage caractère par caractère sont longues.

Pour tourner ces difficultés, la solution retenue dans le fichier proposé au téléchargement consiste à coder sur plusieurs caractères, seulement les chaines vides (par exemple en remplacant dans le fichier tous les chr(0) par "#$".
Mis bout à bout, les caractères feront une longue chaine contenant toutes les informations constituant le fichier à insérer, chaine qu'il suffit de répartir dans un nombre suffisant de cellules.

Pour récupérer le fichier ainsi codé, il suffit de faire la manoeuvre en sens inverse, lire la chaine de caractères dans chacune des cellules, y repérer les chaines de caractères représentant des chaines vides et les remplacer par chr(0), puis inscrire bout à bout tous les caractères dans un fichier texte muni de l'extension convenable (.wav, .txt, .zip...)... Il suffit ensuite d'ouvrir le fichier sur C:\ pour s'assurer du succès de l'opération.

cliquez ici pour télécharger le fichier Excel zippé
cliquez ici pour voir le texte de la macro

Petite difficulté, le risque de trouver, dans un fichier, une chaine de caractères correspondant à la chaine retenue pour le codage de chr(0) n'est pas nul et pourrait faire perdre des données (rien n'empêche dans ce cas de changer de chaine).

Autre exemple, cliquez ici pour télécharger un fichier Excel contenant une douzaine de fichiers son de formats différents. Les fichiers sont cette fois codés par une suite de chiffres. A l'ouverture du fichier, un nouveau répertoire est créé sur c:\ et les fichiers son y sont enregistrés.

Une autre méthode pour stocker des fichiers dans un classeur Excel, consiste à utiliser les zones de noms pour y entreposer les octets.
Il suffit d'utiliser
ThisWorkbook.Names.Add "zz5", txt
Pour stocher txt dans le nom zz5
Puis txt = ThisWorkbook.Names("zz5").RefersTo pour récupérer le texte (qu'il faut encore retraiter pour retirer les guillemets que Excel ajoute au moment du stockage).
Cette technique est limité par le nombre de caractères que peut stocker un Name et par le nombre de Names que sait gérer Excel. Elle marche bien pour de petits fichiers :
cliquez ici pour télécharger le fichier exemple (fichier .html inclu dans un fichier Excel).

Enfin, on peut aussi utiliser les pages de code (modules) pour stocker de l'information :
Set modl = ThisWorkbook.VBProject.VBComponents("Module2").CodeModule
modl.InsertLines modl.CountOfLines + 1, "zaza"
modl.AddFromString "toto"

La première ligne permet d'insérer une ligne en fin du module 2, la seconde ajoute simplement le texte en fin de module (sans saut de ligne à la fin).