XL 2019 Combobox à partir d'un fichier fermé

gui64600

XLDnaute Nouveau
Bonjour,
Jai un fichier source.xlsm qui en colonne A de la feuille "source" contient des noms.
Je voudrais dans un autre fichier résultat.xlsm créer une combobox me permettant une saisie semi-automatique des noms du fichier source en cellule C2

Le fichier A est fermé.

Merci de votre aide
 

Dudu2

XLDnaute Barbatruc
Oui je n'ai pas nettoyé le range A1:A100 des valeurs vides. Je suppose qu'il connait son Range ou qu'il fera le nécessaire pour ne garder que les valeurs non nulles.

En testant j'ai remarqué que SQL ne gère par une plage de 1 cellule dans mon code.
Faut passer par ExecuteExcel4Macro.

J'ai donc pris ça en compte dans le fichier du Post #8.

Concernant le UsedRange, quand la feuille est vide UsedRange.Address = "$A$1"
Je vais peut-être (?) gérer ça aussi car dans ce cas le SQL sur feuille rend 0 record évidemment.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
J'utilise IMEX = 1 pour ne pas laisser SQL déterminer le type de valeur à partir des 8 premières valeurs de la colonne. L'inconvénient c'est qu'on obtient en retour que du format Texte.

Tu crois que ça marche parce que tu charges une ComboBox dont les termes de la liste sont par définition en format Texte. Mais l'affaire est différente s'il s'agit de charger un Range.

J'ai utilisé ton fichier du Post #3.
Prenons par exemple ces valeurs comme source qui contient un échantillon à problèmes dont 1 date non valide en format anglais (23/01/1953).
1607103586952.png


Si tu charges un Range avec la table résultant directement du SQL...

1 - En ayant pris soin de formater ton Range cible en Texte
ActiveSheet.[A1:A6].NumberFormat = "@"
ActiveSheet.[A1:A6].Value = Tbl
Tu n'obtiens que du texte évidemment comme la ComboBox (pas très intéressant) .
1607103865011.png


2 - en ayant pris soin de formater ton Range cible en Standard
ActiveSheet.[A1:A6].NumberFormat = "General"
ActiveSheet.[A1:A6].Value = Tbl
Tu obtiens ce qu'Excel a pu interpréter des valeurs texte retournées par SQL dans la table de retour (pas très utile).
1607103976810.png


C'est pourquoi j'ai introduit des modifs dans mon code (voir fichiers Post #8 récemment modifié) en traitant les dates et les nombres (de manière très simple) pour les charger dans la table de retour comme des dates et des nombres et non plus comme du texte.
Ça permet de charger aussi bien un Range en format Standard qu'une ComboBox dont la liste est en Texte. Comme le ferait une table chargée à partir d'un Range car le VarType() de chaque élément de la table est représentatif du type de valeur qu'il contient.

ActiveSheet.[A1:A6].NumberFormat = "General"
ActiveSheet.[A1:A6].Value = Tbl
1607107519265.png


La reconnaissance des nombres en format texte n'est pas incluse pour le moment pour les formats pourcentage, monétaire, comptabilité et personnalisé.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Une autre option à creuser, serait de toujours rendre la Table au format Texte.
Le range cible serait préalablement mis au format Texte et chargé avec les valeurs Texte de la Table.
Puis une fonction spéciale de reconnaissance des valeurs dates et nombres serait chargée de définir pour chaque cellule du Range le format reconnu (Standard, Nombre, Date, Monétaire, etc...).
C'est plus efficace que la mise au bon VarType() des valeurs de la Table car la Table ne peut pas stocker un format monétaire ou pourcentage par exemple. Elle ne peut stocker que le nombre correspondant.

D'ailleurs il faut faire 2 fonctions séparées:
- La première qui rend la Table en format Texte (pour les ListBox, ComboBox, autres listes texte)
- La Deuxième qui charge un Range et qui appelle la première et inclut donc la mise au format des cellules du Range

Demain est un autre jour...
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Tu peux redonner le code que tu utilises au final ?

Je vais faire des tests mais à mon avis, y a pas de miracle, on récupère du texte pur et dur (IMEX=1) et quand on charge un Range, Excel reconnaîtra certains formats mais pas d'autres. Et pour ces autres non reconnus, on peut tenter de les retrouver même si on ne peut pas tout retrouver à 100%.

Pour les nombres, il faudrait pouvoir faire en VBA ce qu'Excel fait quand on a une erreur dans la cellule (triangle en haut à gauche) et qu'on choisi "Convertir en nombre". Mais je ne trouve pas. Ce doit être une fonction complexe qu'il faut donc essayer d'imiter.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
En Post #8 se trouve le fichier modifié qui contient les 2 fonctions dont l'une permet de charger un Range en formatant les cellules de manière cohérente avec leurs valeurs.

En Post #13 se trouve le fichier modifié pour la demande de gui64600 pour sa ComboBox.

Bien sûr, lorsqu'on veut charger un Range, rien ne garantit qu'on génère le même format que celui des cellules du Range source exporté par SQL en format texte, mais c'est une manière de s'en rapprocher. Par exemple pour le format Date, je suis resté au plus simple, et même si ça peut ne pas être le format Date original, au moins c'est un format Date.
Edit: J'ai amélioré la reconnaissance des dates pour couvrir tous les formats Date classiques.

1607261048199.png
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
Bonjour @Dudu2
je viens de tester mon code (arr) et les dates importées sont calculables donc pas de soucis
il arrive cependant que la première soit a gauche mais elle est calculable quand même
après il est évident que si le texte d'une valeur est du a un formatage il faut le supprimer dans la valeur et formater la cells de destination
tu t'ennuie pour rien
regarde
ça c'est la source ( une colonne avec plusieurs type de données différentes
base (xlsx).JPG


ca c'est la destination
demo7.gif
 

Dudu2

XLDnaute Barbatruc
Bonjour patricktoulon,

Comme tu peux le voir dans le tableau du Post #23 ci-dessus, en colonne D, et comme je l'ai indiqué avant, Excel peut reconnaître certains format de données Texte et les formater correctement.

MAIS c'est loin d'être le cas pour tout et en particulier pour les dates ça ne marche pas car elles sont transformées en anglais pour les dates compatibles, c'est à dire ayant un jour français <= 12 pour le mois anglais et en texte sinon.

Exemple: date 12/06/1987 -> date 06/12/1987 (qui n'est pas la date d'origine !)
Exemple: date 13/06/1987 -> texte 13/06/1987 (qui est la date d'origine... mais en texte !)

Tu peux faire tout ce que tu veux à la mano pour adapter les formats. Sur un gros tableau, t'auras du boulot... Ou alors tu utilises le code que j'ai fait ;)
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
je récapépète donc
si tu a des problème d'inversion dans les dates tu fait ce que tout le monde fait
tu utilise le format magic
et pas la peine de toucher au cellules
donc je redonne la version arr
VB:
Sub test_récup_plage()
    Dim fichier$, Tbl
    fichier = ThisWorkbook.Path & "\BASE.xlsx"    'à adapter
      Tbl = GetcolumnValueOnClosedWbookskeepblank(fichier, "A1:A20", "Feuil1", False)
    'With ActiveSheet.ComboBox1: .Clear: .List = Tbl: End With
 Sheets("Feuil2").[A1].Resize(UBound(Tbl), 1) = Tbl
  End Sub

Function GetcolumnValueOnClosedWbookskeepblank(fichier As String, RnG As String, Feuille As String, Optional headerTable As Boolean = False)
    Dim AdConn As Object, AdoComand As Object, HDR$, RsT As Object, RsTLigne&, RsTCol&, v$, Arr()
    Set AdConn = CreateObject("ADODB.Connection")
    Set AdoComand = CreateObject("ADODB.Command")
    Set RsT = CreateObject("ADODB.RecordSet")
    HDR = Array("No", "Yes")(Abs(headerTable))
    AdConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & fichier & ";Extended Properties=""Excel 12.0;HDR=NO;IMEX=-1"""
    AdoComand.ActiveConnection = AdConn
    AdoComand.CommandText = "SELECT * from `" & Feuille & "$" & RnG & "`"
    RsT.Open AdoComand, , adOpenKeyset, adLockOptimistic
        RsT.MoveFirst
    
    Do While Not RsT.EOF
        For RsTLigne = 1 To RsT.RecordCount  'lignes
            If Not IsNull(RsT.Fields(0).Value) Then a = a + 1: ReDim Preserve Arr(1 To a): Arr(a) = RsT.Fields(0).Value
                         If IsDate(Arr(a)) Then Arr(a) = Format(CDate(Arr(a)), "m/d/yyyy")
            RsT.MoveNext
        Next
    Loop
    AdConn.Close: Set RsT = Nothing: Set AdoComand = Nothing: Set AdConn = Nothing
    GetcolumnValueOnClosedWbookskeepblank = Application.Transpose(Arr)
End Function
;)
 

Dudu2

XLDnaute Barbatruc
si tu a des problème d'inversion dans les dates tu fait ce que tout le monde fait
tu utilise le format magic
et pas la peine de toucher au cellules
Moi je n'ai pas de problème d'inversion de date. Je ne fais que décrire comment Excel réagit par rapport à une date texte quand on la place manuellement ou par VBA dans une cellule de format Standard.
Et la magie je veux bien mais y a pas encore d'API :).
 

patricktoulon

XLDnaute Barbatruc
Moi je n'ai pas de problème d'inversion de date. Je ne fais que décrire comment Excel réagit par rapport à une date Texte. Et la magie je veux bien mais y a pas encore d'API :).
si il y en a une
"m/d/yyyyy" ne veut pas dire "mois/jour/année" tout du moins comme les autre string formateurs
ce format ne converti que les moins de 12(jour et mois)


07/04/2020 sera converti en 04/07/2020
07/12/2020 ne sera pas converti
20/03/2020 ne sera pas converti

il est donc clair que comme ado renvoie du texte les date (moins de 12 / moins de 12/xxxx) seront comverties donc le format magic veille

cette astuce est connue et vielle comme le monde
;)
 

Discussions similaires

Membres actuellement en ligne

Aucun membre en ligne actuellement.

Statistiques des forums

Discussions
312 206
Messages
2 086 219
Membres
103 158
dernier inscrit
laufin