Je teste actuellement la mise en place d’un PIM pour gérer notre bibliothèque de médias et les informations produits. L’idée est de centraliser l’information et la rendre accessible au plus grand nombre au travers d’un navigateur mais aussi pour d’autres applications. Dans cet article je vous expliquerais comment procéder pour récupérer ces informations depuis Excel en utilisant l’API d’Akeneo et Flyimg-Akeneo.
Je pars principe que vous savez ce qu’est un PIM, que vous connaissez la solution proposé par Akeneo, que vous connaissez Docker.
Je remercie l’équipe d’Akeneo qui m’a orienté sur les bonnes pistes et je précise que je ne suis pas un expert en VBA.
Pré-requis
- Une instance Akeneo fonctionnelle comportant un catalogue avec quelques produits;
- La possibilité de créer un container Docker pour Flyimg et Traefik activé (marche sans mais vous devrez exposer/mapper le port 80 de votre container);
- Excel avec quelques librairies que nous ajouterons plus tard.
Activer l’API
Connectez-vous en tant qu’administrateur ou bien avec un compte ayant les droits administrateurs. Allez sur la page Système > Connexions API. Créer une autorisation spécifique pour VBA, ensuite attribuez à un groupe dédié afin de gérer les habilitations. Pour mes tests j’ai utilisé le compte administrateur.
Création du container Flyimg-Akeneo
Flyimg-Akeneo est un fork de Flyimg dont le rôle est de générer à la demande la déclinaison d’une image source. Il est possible de redimensionner l’image, la faire pivoter, « croper » l’image et bien d’autres choses que je vous laisse découvrir sur le site de Flyimg (https://github.com/flyimg).
Connectez-vous à votre serveur Docker et télécharger la dernière version sur le dépôt Github (https://github.com/opengento/flyimg-akeneo).
Modifier le fichier config/parameters.yml
akeneo_api: base_url: "http://192.168.xxx.xxx" client_id: "1_xxxxx" client_secret: "1xxxx" user: "admin" password: "admin"
base_url : correspond à votre serveur Akeneo
client_id et client_secret correspond aux valeurs que vous avez généré sur la page Système > Connexions API d’Akeneo.
user et password correspond à l’utilisateur faisant partie du groupe autorisé à utiliser cette clé d’API.
Construisez votre image avec la commande
docker build –t flyimg-akeneo --label flyimg-akeneo
Créer votre container avec les labels permettant à Traefik de faire le mappage de port vers le 80. Connectez vous en shell à votre container et lancez la commande
composer install
FlyImg va s’installer en quelques minutes. Une fois fini lancez votre navigateur et essayez de vous connecter à votre container. Si tout se passe bien vous arrivez à une page sur fond gris.
Excel et VBA
Avant d’aller plus loin vous allez avoir besoin du module VBA-Json disponible ici (https://github.com/VBA-tools/VBA-JSON). Dans l’éditeur VBA ajoutez ce module à votre projet et activez la référence « Microsoft Scripting Runtime ».
Commencé par créer un UserForm que vous nommerez : FmOptionsImportImage sur lequel vous ajouterez :
- Une liste déroulante nommée : LsTaille;
- Trois champs texte nommés : TxtLigneRecherche, TxtColonneRecherche, TxtColonneImage;
- Deux boutons : BtValide et BtAnnuler.
Double cliquez sur le bouton « BtValide » et collez ce code
' Quitte le programme Private Sub BtAnnuler_Click() Unload Me End Sub ' Appel de la procédure d'import Private Sub BtValide_Click() ' Appel de la procédure d'import Call getRoot(LigRech, ColRech, ColAct) End Sub ' Charge la liste déroulante Private Sub UserForm_Activate() FmOptionsImportImage.LsTaille.AddItem ("50 px") FmOptionsImportImage.LsTaille.AddItem ("60 px") FmOptionsImportImage.LsTaille.AddItem ("70 px") FmOptionsImportImage.LsTaille.AddItem ("80 px") FmOptionsImportImage.LsTaille.AddItem ("100 px") FmOptionsImportImage.LsTaille.AddItem ("110 px") FmOptionsImportImage.LsTaille.AddItem ("120 px") FmOptionsImportImage.LsTaille.AddItem ("150 px") End Sub
Créer un module nommez “importImage” et collez tout ce code
'Option Explicit Public Product, Token As Object Public strUrl, ColRech, ColAct As String Public LigRech, CellHeight, imgWidth As Integer ' Encode client_id et secret en base64 ' ne marche pas pour le moment Function EncodeBase64(text As String) As String Dim arrData() As Byte arrData = StrConv(text, vbFromUnicode) Dim objXML As MSXML2.DOMDocument Dim objNode As MSXML2.IXMLDOMElement Set objXML = New MSXML2.DOMDocument Set objNode = objXML.createElement("b64") objNode.DataType = "bin.base64" objNode.nodeTypedValue = arrData EncodeBase64 = objNode.text Set objNode = Nothing Set objXML = Nothing End Function ' Connexion et création du token Akeneo Sub ConnectAuth() Dim objRequest, scriptControl As Object Dim client_id, secret As String client_id = "1_xxxx" secret = "1xxxx" strUrl = "http://192.168.xxx.xxxx" Set scriptControl = CreateObject("MSScriptControl.ScriptControl") scriptControl.Language = "JScript" Set objRequest = CreateObject("MSXML2.XMLHTTP") With objRequest .Open "POST", strUrl & "/api/oauth/v1/token", False .SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" ' ToDo : ne marche pas en générant à la volée le base64 ? .SetRequestHeader "Authorization", "Basic EncodeBase64" .Send "grant_type=password&username=admin&password=admin" Set Token = scriptControl.Eval("(" & .responseText & ")") End With End Sub ' Stockage de la largeur de l'image ' et conserve la plus grande Sub upWidth(imgNewWidth) If (imgNewWidth > imgWidth) Then imgWidth = imgNewWidth End If End Sub ' Gestion des erreurs json Sub getError(Code, Message) Dim pErreur As String pErreur = CStr(Code) If (pErreur = 404) Then MsgBox ("Erreur " & Code & " : " & Message) Else MsgBox ("Erreur inconnue") End If End Sub ' Récupération de l'objet Product ' Itmref : sku du produit à chercher Sub getProduct(Itmref) Dim objRequest As Object Set objRequest = CreateObject("MSXML2.XMLHTTP") With objRequest .Open "GET", strUrl & "/api/rest/v1/products/" & Itmref, False .SetRequestHeader "Content-Type", "application/json" .SetRequestHeader "Authorization", "Bearer " & Token.access_token .Send Set Product = JsonConverter.ParseJson(.responseText) End With End Sub ' Transformation de l'image akeneo par ' flyimg-akeneo Sub getPicture(ImgHeight) If (Product("values").Exists("img_0")) Then ‘ Changer img_0 par le nom du champ qui représente l’image que vous voulez insérer Set img = ActiveSheet.Pictures.Insert("http://AdresseDuServeurFlyImg/upload/st_1,h_" & ImgHeight & "/" & Product("values")("img_0")(1)("data")) img.Top = ActiveCell.Top + 2 img.Left = ActiveCell.Left + 2 img.Placement = 2 img.PrintObject = 1 ' Mise à jour de la largeur de la cellule Call upWidth(img.Width) End If End Sub Sub getRoot(LigRech, ColRech, ColAct) Dim ImgHeight As Integer imgWidth = 0 ' Dimension de la cellule ' hauteur de cellule ' 50 -> 50 px ' 60 -> 60 px ' 70 -> 70 px ' 81 -> 80 px ' 100 -> 100 px ' 110 -> 110 px ' 120 -> 120 px ' 150 -> 150 px ' Largeur de la celulle ' 9 -> 50 px ' 11 -> 60 px ' 13 -> 70 px ' 15 -> 80 px ' 19 -> 100 px ' 21 -> 110 px ' 23 -> 120 px ' 28 -> 150 px Select Case FmOptionsImportImage.LsTaille.List(FmOptionsImportImage.LsTaille.ListIndex) Case "50 px" To "50 px" CellHeight = 50 ' hauteur de cellule ImgHeight = 50 'ImgWidth = 50 Case "60 px" To "60 px" CellHeight = 60 ' hauteur de cellule ImgHeight = 60 'ImgWidth = 60 Case "70 px" To "70 px" CellHeight = 70 ' hauteur de cellule ImgHeight = 70 'ImgWidth = 70 Case "80 px" To "80 px" CellHeight = 80 ' hauteur de cellule ImgHeight = 80 'ImgWidth = 80 Case "100 px" To "100 px" CellHeight = 100 ' hauteur de cellule ImgHeight = 100 'ImgWidth = 100 Case "110 px" To "110 px" CellHeight = 110 ' hauteur de cellule ImgHeight = 110 'ImgWidth = 110 Case "120 px" To "120 px" CellHeight = 120 ' hauteur de cellule ImgHeight = 120 'ImgWidth = 120 Case "150 px" To "150 px" CellHeight = 150 ' hauteur de cellule ImgHeight = 150 'ImgWidth = 150 Case "" To "" MsgBox ("Vous devez choisir une taille d'images") End Select ' Ligne à laquelle commencer la recherche If LigRech = 0 Then LigRech = FmOptionsImportImage.TxtLigneRecherche.Value If LigRech = "" Then Exit Sub End If ' Colonne de recherche. If ColRech = "" Then ColRech = FmOptionsImportImage.TxtColonneRecherche.Value If ColRech = "" Then Exit Sub End If ' Colonne d'affichage If ColAct = "" Then ColAct = FmOptionsImportImage.TxtColonneImage.Value If ColAct = "" Then Exit Sub End If ' Connexion et récupération du Token Call ConnectAuth Range(ColRech & LigRech).Select For i = 1 To Range("A" & "65535").End(xlUp).Row If (Range(ColRech & i).Value <> "") Then ' Récupération des informations produit Call getProduct(Range(ColRech & i).Value) If (CStr(Product.Exists("code"))) Then Call getError(Product("code"), Product("message")) Else Range(ColAct & i).Select ActiveCell.EntireRow.RowHeight = CellHeight Call getPicture(ImgHeight) End If End If Next i ' Ajuste la largeur de la colonne avec ' la largeur de l'image la plus grande ' 4.75 permet la convertion de pixel à points... en gros ActiveCell.EntireColumn.ColumnWidth = (imgWidth / 4.75) + 0.5 FmOptionsImportImage.BtValide.Visible = False FmOptionsImportImage.BtAnnuler.Caption = "Quitter" End Sub
Avant de lancer le programme vous devez modifier dans la fonction ConnectAuth() les variables client_id, secret, strUrl.
Normalement le programme est censé réaliser l'encodage en base64 automatiquement mais pour une raison que je ne connais pas cela ne marche pas (encore), du coups vous allez devoir le faire à la main. Allez sur le site https://www.base64decode.org/ copier/coller les valeurs client_id et secret mais attention sous cette forme
client_id:secret
ne pas oublier le : de séparateur. Ensuite coller le résultat dans la fonction ConnectAuth à la ligne
.SetRequestHeader "Authorization", "Basic VotreEncodageBase64"
Dans la fonction getPicture l'adresse de votre serveur FlyImg est à modifier et le nom du champ contenant le chemin d'accès à l'image (dans mon cas img_0)
If (Product("values").Exists("img_0")) Then [...] Set img = ActiveSheet.Pictures.Insert("http://AdresseDuServeurFlyImg/upload/st_1,h_" & ImgHeight & "/" & Product("values")("img_0")(1)("data"))
Test
Dans votre projet VBA, sur la Feuil1, dans la colonne de votre choix saisissez un sku par ligne et lancez le programme en lancant la feuille FmOptionsImportImage. Renseignez les valeurs de taille et dans quelle colonne mettre les images et cliquez sur le bouton "Insérer".
Si tout ce passe bien les images devraient être insérée sur la ligne correspondante au sku et au dimenssion que vous avez séléctionné.
Evolution
Dans le cas où il y a plusieurs images disponible, ouvrir une fenêtre pour permettre à l'utilisateur de sélectionner l'image qu'il souhaite importer.