VBA - ODBC - Type TEXT dans mysql

Bonjour à tous,

J'ai un petit bout de code qui me permet de récupérer des données dans une base MySQL. Je débute en VBA donc j'ai trouvé ça en farfouillant sur le net et en adaptant à mes besoins.

Sub ProduitDolibarrSQL()

    Dim Cn As ADODB.Connection
    Dim Server_Name As String
    Dim Database_Name As String
    Dim User_ID As String
    Dim Password As String
    Dim SQLStr As String
    Dim Categorie As String
    Dim ValCat As String

    Dim rs As ADODB.Recordset
    Set rs = New ADODB.Recordset

    Server_Name = "IP_SERVEUR"
    Database_Name = "MaBASE"
    User_ID = "MonUSER"
    Password = "MonMDP"

    Sheets("Parametres").Select
    ValCat = Range("C4").Value

    Select Case ValCat
        Case "1"
            Categorie = Range("B5").Value
        Case "2"
            Categorie = Range("B6").Value
        Case "3"
            Categorie = Range("B7").Value
        Case "4"
            Categorie = Range("B8").Value
        Case "5"
            Categorie = Range("B9").Value
        Case "6"
            Categorie = Range("B10").Value
        Case "7"
            Categorie = Range("B11").Value
        Case "8"
            Categorie = Range("B12").Value
        Case "9"
            Categorie = Range("B13").Value
        Case "10"
            Categorie = Range("B14").Value
        Case "11"
            Categorie = Range("B15").Value
        Case "12"
            Categorie = Range("B16").Value
        Case "13"
            Categorie = Range("B17").Value
        Case "14"
            Categorie = Range("B18").Value
        Case "15"
            Categorie = Range("B19").Value
        Case "16"
            Categorie = Range("B20").Value
        Case "17"
            Categorie = Range("B21").Value
        Case "18"
            Categorie = Range("B22").Value
        Case "19"
            Categorie = Range("B23").Value
        Case "20"
            Categorie = Range("B24").Value
        Case "21"
            Categorie = Range("B25").Value
        Case "22"
            Categorie = Range("B26").Value
        Case "23"
            Categorie = Range("B27").Value
        Case "24"
            Categorie = Range("B28").Value
        Case "25"
            Categorie = Range("B29").Value
        Case "26"
            Categorie = Range("B30").Value
        Case "27"
            Categorie = Range("B31").Value
        Case "28"
            Categorie = Range("B32").Value
        Case "29"
            Categorie = Range("B33").Value
        Case "30"
            Categorie = Range("B34").Value
        Case "31"
            Categorie = Range("B35").Value
        Case "32"
            Categorie = Range("B36").Value
        Case "33"
            Categorie = Range("B37").Value
        Case "34"
            Categorie = Range("B38").Value
        Case "35"
            Categorie = Range("B39").Value
        Case "36"
            Categorie = Range("B40").Value
        Case "37"
            Categorie = Range("B41").Value
        Case "38"
            Categorie = Range("B42").Value
        Case "39"
            Categorie = Range("B43").Value
        Case "40"
            Categorie = Range("B44").Value
        Case "41"
            Categorie = Range("B45").Value
        Case "42"
            Categorie = Range("B46").Value
        Case "43"
            Categorie = Range("B47").Value
        Case "44"
            Categorie = Range("B48").Value
        Case "45"
            Categorie = Range("B49").Value
        Case "46"
            Categorie = Range("B50").Value
        Case "47"
            Categorie = Range("B51").Value
        Case "48"
            Categorie = Range("B52").Value
        Case "49"
            Categorie = Range("B53").Value
        Case "50"
            Categorie = Range("B54").Value
        Case "51"
            Categorie = Range("B55").Value
        Case "52"
            Categorie = Range("B56").Value
        Case "53"
            Categorie = Range("B57").Value
        Case "54"
            Categorie = Range("B58").Value
        Case "55"
            Categorie = Range("B59").Value
        Case "56"
            Categorie = Range("B60").Value
        Case "57"
            Categorie = Range("B61").Value
        Case "58"
            Categorie = Range("B62").Value
        Case "59"
            Categorie = Range("B63").Value
        Case "60"
            Categorie = Range("B64").Value
    Case Else
            Categorie = ""
    End Select

     SQLStr = "SELECT c.ref, c.label, c.fk_product_type, c.tosell, c.tobuy, c.description, c.url, c.customcode, c.fk_country, c.accountancy_code_sell, c.accountancy_code_sell_intra, c.accountancy_code_sell_export, c.accountancy_code_buy, c.accountancy_code_buy_intra, c.accountancy_code_buy_export, c.note, c.note_public, c.weight, c.weight_units, c.length, c.length_units, c.width, c.width_units, c.height, c.height_units, c.surface, c.surface_units, c.volume, c.volume_units, c.duration, c.finished, c.price_base_type, c.price, c.price_ttc, c.price_min, c.price_min_ttc, c.tva_tx, c.datec, c.cost_price, d.ref, c.tobatch, c.stock, c.seuil_stock_alerte, c.desiredstock, c.pmp, c.barcode FROM llx_product c JOIN llx_entrepot d ON c.fk_default_warehouse = d.rowid WHERE c.rowid IN (SELECT distinct a.fk_product FROM `llx_categorie_product` a JOIN `llx_categorie` b ON a.fk_categorie = b.rowid WHERE b.label='" & Categorie & "')"

    Set Cn = New ADODB.Connection
    Cn.Open "Driver={MariaDB ODBC 3.0 Driver};Server=" & Server_Name & ";Database=" & Database_Name & ";Uid=" & User_ID & ";Pwd=" & Password & ";"
    rs.Open SQLStr, Cn, adOpenStatic

    With Worksheets("Export Dolibarr").Range("a2:az15000")
        .ClearContents
        .CopyFromRecordset rs
    End With

    rs.Close
    Set rs = Nothing
    Cn.Close
    Set Cn = Nothing

End Sub

Ce code marche pas trop mal, je récupère bien les infos que je veux suivant la catégorie que je choisi dans la feuille "Parametres" (SELECT CASE).

Mon souci se site au niveau des données récupéré pour le champ c.description

Je récupère toujours le même, c'est à dire, le 1er enregistrement qu'il lit.

La même requête SQL directement dans l'interface de PHPMyAdmin marche très bien et ne pose pas se souci.

En regardant la structure de la table, ce champ est au format TEXT et j'ai l'impression que s'est ça qui pose souci dans Excel par la suite.

Si, dans ma requête, je remplace c.description par SUBSTR(c.description,1,2000) je n'ai plus ce souci, je récupère bien une description différente pour chaque ligne mais je ne sais pas à l'avance combien de caractère j'ai dans ma description. Si je mets un nombre trop élevé, j'ai une erreur (je suppose que le volume de données est trop important pour Excel).

Par contre, si je passe par l'option "Données" puis "Obtenir des données de ODBC" et que je mets dans la case "Instruction SQL" ma requête, je récupère correctement toutes les données. Par contre par ce biais, je ne sais pas comment un paramètre dans ma requete.

Est ce que quelqu'un à déjà été confronté à ce problème? Une piste pour le résoudre?

Merci par avance

Bonjour BourbonSid,

Pour commencer, voici ton code optimisé, pour moi inutile d'utiliser un "Select Case" dans ces conditions

Sub ProduitDolibarrSQL()
    Dim Cn As ADODB.Connection
    Dim Server_Name As String
    Dim Database_Name As String
    Dim User_ID As String
    Dim Password As String
    Dim SQLStr As String
    Dim Categorie As String
    Dim ValCat As String

    Dim rs As ADODB.Recordset
    Set rs = New ADODB.Recordset

    Server_Name = "IP_SERVEUR"
    Database_Name = "MaBASE"
    User_ID = "MonUSER"
    Password = "MonMDP"

    Sheets("Parametres").Select
    ValCat = Range("C4").Value
    ' Choix de la catégorie
    If cnum(ValCat) >= 1 And cnum(ValCat) <= 64 Then
      Categorie = Range("B" & 4 + cnum(ValCat))
    Else
      Categorie = ""
    End If
    ' Requête SQL
     SQLStr = "SELECT c.ref, c.label, c.fk_product_type, c.tosell, c.tobuy, c.description, c.url, c.customcode, c.fk_country, c.accountancy_code_sell," _
     & "c.accountancy_code_sell_intra, c.accountancy_code_sell_export, c.accountancy_code_buy, c.accountancy_code_buy_intra, c.accountancy_code_buy_export," _
     & "c.note, c.note_public, c.weight, c.weight_units, c.length, c.length_units, c.width, c.width_units, c.height, c.height_units, c.surface, c.surface_units," _
     & "c.volume, c.volume_units, c.duration, c.finished, c.price_base_type, c.price, c.price_ttc, c.price_min, c.price_min_ttc, c.tva_tx, c.datec, c.cost_price," _
     & "d.ref, c.tobatch, c.stock, c.seuil_stock_alerte, c.desiredstock, c.pmp, c.barcode" _
     & "FROM llx_product c JOIN llx_entrepot d ON c.fk_default_warehouse = d.rowid" _
     & "WHERE c.rowid IN (SELECT distinct a.fk_product FROM `llx_categorie_product` a JOIN `llx_categorie` b ON a.fk_categorie = b.rowid WHERE b.label='" & Categorie & "')"

    Set Cn = New ADODB.Connection
    Cn.Open "Driver={MariaDB ODBC 3.0 Driver};Server=" & Server_Name & ";Database=" & Database_Name & ";Uid=" & User_ID & ";Pwd=" & Password & ";"
    rs.Open SQLStr, Cn, adOpenStatic

    With Worksheets("Export Dolibarr").Range("a2:az15000")
        .ClearContents
        .CopyFromRecordset rs
    End With

    rs.Close
    Set rs = Nothing
    Cn.Close
    Set Cn = Nothing
End Sub

@+

Bonjour à tous,

3 remarques :

* pourquoi utiliser le driver MariaDB sur une base MySql?

Si besoin le driver MySql DRIVER={MySQL ODBC 8.0 Driver}; est dispo ici=>

https://dev.mysql.com/downloads/connector/odbc/

la connexion devient alors :

Cn.Open "Provider=MSDASQL;DRIVER={MySQL ODBC 8.0 Driver};" & _
        "SERVER=" & Server_Name & ";" & _
        "DATABASE=" & Database_Name & ";" & _
        "USER=" & User_ID & ";" & _
        "PASSWORD=" & Password & ";"

* si ça ne résout pas la question, est-ce qu'un CStr(c.description) ne serait pas utile?

* enfin même remarque que Bruno, se passer du select case (et du Sheets("Parametres").Select) pour simplifier le code

    With Sheets("Parametres")
        ValCat = .Range("C4").Value
        if Valcat=0 or Valcat>60 then  Categorie ="" else Categorie = .Range("B" & ValCat+4).Value
    end with

Pierre

Bonsoir,

je n'es pa changer le driver mais je suis d'Accor avec pierrep56!

Sub ProduitDolibarrSQL()
Const Server_Name = "IP_SERVEUR", Database_Name = "MaBASE", User_ID = "MonUSER", Password = "MonMDP"
Dim SQLStr As String
Dim Categorie As String
With Sheets("Parametres")
    Categorie = .Range("C4").Offset(Val(.Range("C4").Value)).Value
End With
    SQLStr = "SELECT c.ref, c.label, c.fk_product_type, c.tosell, c.tobuy, c.description, c.url, c.customcode, c.fk_country, c.accountancy_code_sell, c.accountancy_code_sell_intra, c.accountancy_code_sell_export, c.accountancy_code_buy, c.accountancy_code_buy_intra, c.accountancy_code_buy_export, c.note, c.note_public, c.weight, c.weight_units, c.length, c.length_units, c.width, c.width_units, c.height, c.height_units, c.surface, c.surface_units, c.volume, c.volume_units, c.duration, c.finished, c.price_base_type, c.price, c.price_ttc, c.price_min, c.price_min_ttc, c.tva_tx, c.datec, c.cost_price, d.ref, c.tobatch, c.stock, c.seuil_stock_alerte, c.desiredstock, c.pmp, c.barcode FROM llx_product c JOIN llx_entrepot d ON c.fk_default_warehouse = d.rowid WHERE c.rowid IN (SELECT distinct a.fk_product FROM `llx_categorie_product` a JOIN `llx_categorie` b ON a.fk_categorie = b.rowid WHERE b.label='" & Categorie & "')"

    With New ADODB.Connection
        .Open "Driver={MariaDB ODBC 3.0 Driver};Server=" & Server_Name & ";Database=" & Database_Name & ";Uid=" & User_ID & ";Pwd=" & Password & ";"
       Worksheets("Export Dolibarr").Range("a2:az15000").ClearContents
        Worksheets("Export Dolibarr").Range("A2").CopyFromRecordset .Execute(SQLStr)
        .Close
    End With
End Sub

Bonjour,

Merci pour vos retours et les conseils pour l'optimisation du code.

Je ne m'étais pas encore penché sur ce sujet, je voulais deja faire en sorte que le reste fonctionne :)

Concernant le driver ODBC, s'est bien le bon. Je parle de MySQL par habitude mais s'est bien un serveur MariaDB.

Dans le doute, j'ai refais une petite installation de serveur avec MySQL cette fois et j'ai modifié le driver en conséquence mais le résultat est le même.

Concernant l'utilisation de CStr(c.description), ça me fait l'erreur si dessous. J'ai tenté avec CVar(c.description) mais le résultat est le même.

erreur excel

Mon 1er message n'était peut être pas très clair, je complète avec 2 captures d’écran. La 1ère est ma requête directement dans PHPMyAdmin. On voit bien que pour chaque ligne de processeur j'ai une description différente. La 2eme est le résultat du code que je vous ai mis dans Excel. La description reste bloqué sur celle de la 1ere ligne

excel sql excel vba

Bonjour,

Je suis dubitatif sur ton type de jointure !

https://www.commentcamarche.net/faq/34631-mysql-quelle-jointure-choisir

je t'invite à utiliser Inner Join!

ici FROM `llx_categorie_product` a JOIN `llx_categorie` b ON a.fk_categorie = b.rowid

tu demande à ta requête d'associer toutes les ligne de la table llx_categorie_product à toutes les ligne de la table llx_categorie et c'est ce que fait ta requête!

le nombre d'enregistrement est count(llx_categorie_product) * count(llx_categorie )

Merci pour ton retour sur la requête.

Effectivement elle n'est pas juste, mais j'ai mis ça de coté quand je me suis rendu compte de l'autre souci.

J'irai creusé les Inner Join dès que je reviendrai sur cette partie la :)

Bonjour le fil

@BourbonSid, je pense que justement, votre problème est lié à ce INNER JOIN

@+

J'ai remplacé ma requete par

SELECT * FROM llx_product

pour éviter tout souci à ce niveau la.

Le résultat est le même, je récupère bien mes données, sauf la colonne description, ou j'ai toujours celle de la 1er ligne

tu fais ça?

 With Worksheets("Export Dolibarr").Range("a2:az15000")
        .ClearContents
        .CopyFromRecordset rs
    End With

ou tu fais ça?

 With New ADODB.Connection
        .Open "Driver={MariaDB ODBC 3.0 Driver};Server=" & Server_Name & ";Database=" & Database_Name & ";Uid=" & User_ID & ";Pwd=" & Password & ";"
       Worksheets("Export Dolibarr").Range("a2:az15000").ClearContents
        Worksheets("Export Dolibarr").Range("A2").CopyFromRecordset .Execute(SQLStr)
        .Close
    End With

Pour le moment, je fais ça. J'ai pris en compte les remarques pour l'optimisation et j'ai fais une requete beaucoup plus simple pour etre sur que le souci ne vient pas de la

Sub ProduitDolibarrSQL()

    Dim Cn As ADODB.Connection
    Dim Server_Name As String
    Dim Database_Name As String
    Dim User_ID As String
    Dim Password As String
    Dim SQLStr As String
    Dim Categorie As String
    Dim ValCat As String

    Dim rs As ADODB.Recordset
    Set rs = New ADODB.Recordset

    Server_Name = "192.168.200.9"
    Database_Name = "dolitest"
    User_ID = "dolibarrExcel"
    Password = "11111"

    With Sheets("Parametres")
        ValCat = .Range("C4").Value
        If ValCat = 0 Or ValCat > 60 Then Categorie = "" Else Categorie = .Range("B" & ValCat + 4).Value
    End With

    SQLStr = "SELECT * FROM llx_product"

    Set Cn = New ADODB.Connection
    Cn.Open "Driver={MariaDB ODBC 3.0 Driver};Server=" & Server_Name & ";Database=" & Database_Name & ";Uid=" & User_ID & ";Pwd=" & Password & ";"
    rs.Open SQLStr, Cn, adOpenStatic

    With Worksheets("Export Dolibarr").Range("a2:az15000")
        .ClearContents
        .CopyFromRecordset rs
    End With

    rs.Close
    Set rs = Nothing
    Cn.Close
    Set Cn = Nothing

End Sub

Voici le résultat sur une feuille Excel. Les données sont bien récupérées, sauf la colonne ou il y a la description

excel vba

En modifiant le code comme ça

Sub ProduitDolibarrSQL()

    Dim Cn As ADODB.Connection
    Dim Server_Name As String
    Dim Database_Name As String
    Dim User_ID As String
    Dim Password As String
    Dim SQLStr As String
    Dim Categorie As String
    Dim ValCat As String

    Dim rs As ADODB.Recordset
    Set rs = New ADODB.Recordset

    Server_Name = "192.168.200.9"
    Database_Name = "dolitest"
    User_ID = "dolibarrExcel"
    Password = "11111"

    With Sheets("Parametres")
        ValCat = .Range("C4").Value
        If ValCat = 0 Or ValCat > 60 Then Categorie = "" Else Categorie = .Range("B" & ValCat + 4).Value
    End With

    SQLStr = "SELECT * FROM llx_product"

  '  Set Cn = New ADODB.Connection
  '  Cn.Open "Driver={MariaDB ODBC 3.0 Driver};Server=" & Server_Name & ";Database=" & Database_Name & ";Uid=" & User_ID & ";Pwd=" & Password & ";"
  '  rs.Open SQLStr, Cn, adOpenStatic

    With New ADODB.Connection
        .Open "Driver={MariaDB ODBC 3.0 Driver};Server=" & Server_Name & ";Database=" & Database_Name & ";Uid=" & User_ID & ";Pwd=" & Password & ";"
        Worksheets("Export Dolibarr").Range("a2:az15000").ClearContents
        Worksheets("Export Dolibarr").Range("A2").CopyFromRecordset .Execute(SQLStr)
        .Close
    End With

  '  With Worksheets("Export Dolibarr").Range("a2:az15000")
  '      .ClearContents
  '      .CopyFromRecordset rs
  '  End With

  '  rs.Close
  '  Set rs = Nothing
  '  Cn.Close
  '  Set Cn = Nothing

End Sub

La description n'est même plus récupéré. D'ailleurs il récupère plus aucune colonne après la colonne description

excel vba

d'une par ça c'est pas bon!

With Worksheets("Export Dolibarr").Range("a2:az15000")
        .ClearContents
        .CopyFromRecordset rs
    End With

ça c'est bon

With Worksheets("Export Dolibarr")
        .Range("a2:az15000").ClearContents
        .Range("a2).CopyFromRecordset rs
    End With

llx_product c'est une table ou une vue car selon ton Imprim écran il n'y a pas quel ma même ligne!

La description n'est même plus récupéré. D'ailleurs il récupère plus aucune colonne après la colonne description

c'est normal si elle fait partie de la deuxième table!

Je crois que nos messages se sont croisés ^^

llx_product s'est le nom de la table dans MariaDB.

Dans un post précédent, j'ai mis une capture de ma feuille Excel et une capture de PhpMyAdmin avec la même requête lancé dans les 2. Le résultat n'était pas le même

Je viens de tester autre chose, peut etre que ça fera avancer le truc

Avec l'enregistreur de macro, j'ai fais ça

Sub Macro1()
'
' Macro1 Macro
'

'
    ActiveWorkbook.Queries.Add Name:="Requête1", Formula:= _
        "let" & Chr(13) & "" & Chr(10) & "    Source = Odbc.Query(""dsn=DoliTest"", ""SELECT * FROM llx_product"")" & Chr(13) & "" & Chr(10) & "in" & Chr(13) & "" & Chr(10) & "    Source"
    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:= _
        "OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=Requête1;Extended Properties=""""" _
        , Destination:=Range("$A$1")).QueryTable
        .CommandType = xlCmdSql
        .CommandText = Array("SELECT * FROM [Requête1]")
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True
        .ListObject.DisplayName = "Requête1"
        .Refresh BackgroundQuery:=False
    End With
End Sub

Et j'obtiens dans Excel ça. Avec cette façon de faire, j'ai bien une description différente par produit.

excel sql

Bonjour,

Après des heures à chercher et à faire des tests, j'ai finalement résolu mon souci.

Il suffisait d'utiliser un autre connecteur ODBC

Je suis passé du "MariaDB ODBC 3.0 Driver" à "MySQL ODBC 8.0 ANSI Driver" et maintenant je récupère bien correctement les données de la colonne Description...

Merci à tous pour vos conseils

Bonjour,

il faut toujours écouter pierrep56!

Effectivement, je vais garder cette info dans un coin de ma mémoire

Mais, comme je l'avais dis au départ, je suis bien sur une base MariaDB, d’où le connecteur MariaDB utilisé au départ...

Finalement j'ai crié victoire un peu trop vite...

Je ne récupère que les 66 1er caractères du champs...

Je ne comprends vraiment pas pourquoi ça réagit comme ça

Voici ma requete de base

SELECT c.ref, c.label, c.fk_product_type, c.tosell, c.tobuy, c.description, c.url, c.customcode, c.fk_country, c.accountancy_code_sell, c.accountancy_code_sell_intra, c.accountancy_code_sell_export, c.accountancy_code_buy, c.accountancy_code_buy_intra, c.accountancy_code_buy_export, c.note, c.note_public, c.duration, c.finished, c.price_base_type, c.price, c.price_ttc, c.price_min, c.price_min_ttc, c.tva_tx, c.datec, c.cost_price, d.ref, c.tobatch, c.stock, c.seuil_stock_alerte, c.desiredstock, c.pmp, c.barcode, e.serieYesNo, e.deee, e.cpriv FROM llx_product c INNER JOIN llx_entrepot d ON c.fk_default_warehouse = d.rowid INNER JOIN llx_product_extrafields e ON c.rowid = e.fk_object WHERE c.label LIKE '" & Libelle & "'

En faisait ça, je récupère bien la description du produit mais tronqué à 66 caractères.

Par contre, si je cible un produit précis avec cette requete

SELECT c.ref, c.label, c.fk_product_type, c.tosell, c.tobuy, c.description, c.url, c.customcode, c.fk_country, c.accountancy_code_sell, c.accountancy_code_sell_intra, c.accountancy_code_sell_export, c.accountancy_code_buy, c.accountancy_code_buy_intra, c.accountancy_code_buy_export, c.note, c.note_public, c.duration, c.finished, c.price_base_type, c.price, c.price_ttc, c.price_min, c.price_min_ttc, c.tva_tx, c.datec, c.cost_price, d.ref, c.tobatch, c.stock, c.seuil_stock_alerte, c.desiredstock, c.pmp, c.barcode, e.serieYesNo, e.deee, e.cpriv FROM llx_product c INNER JOIN llx_entrepot d ON c.fk_default_warehouse = d.rowid INNER JOIN llx_product_extrafields e ON c.rowid = e.fk_object WHERE c.label LIKE '" & Libelle & "' AND c.rowid = '1137'

J'ai la description au complet...

Du coup, pour "contourner" mon souci, je me dis que je pourrai faire une boucle qui exécute la requête pour chaque rowid et copie les données dans Excel ligne par ligne. Mais je trouve pas comment faire?

Rechercher des sujets similaires à "vba odbc type text mysql"