IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

OLEDB UPDATE entre datagridview et base Excel


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 16
    Par défaut OLEDB UPDATE entre datagridview et base Excel
    Bonjour,

    Je fais appel à ce forum pour un problème qui me bloque depuis plusieurs semaines :
    C'est la première fois que développe une application de gestion de données en utilisant OleDB pour gérer des contacts pour une association (pas trop le choix car j'ai + de 3000 lignes de contacts à gérer).

    Ce que je cherche à faire, c'est :
    - de charger les données Excel dans l'appli,
    - de pouvoir faire des modifs directement par le datagridview,
    - puis de sauvegarder les modifications faites dans le datagridview dans le fichier Excel.

    Pour l'instant, et malgré beaucoup de temps passé , voici où j'en suis :

    Chargement des données Excel dans le datagridview (en datasource) => OK
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    	Private Sub ReadExcelFile(DGV As DataGridView, cheminXL As String)
    		ds = New DataSet()
    		If System.IO.Path.GetExtension(XLfilepath) = "xls" Then _
    			connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & cheminXL & "; Extended Properties=""Excel 8.0;HDR=YES;IMEX=1;""" _
    		Else connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & cheminXL & "; Extended Properties=""Excel 12.0 XML;HDR=YES;IMEX=1;"""
    		Using conn As OleDbConnection = New OleDbConnection(connectionString)
    			conn.Open()
    			Dim cmd As OleDbCommand = New OleDbCommand()
    			cmd.Connection = conn
     
    			'Get all Sheets in Excel File
    			Dim dtSheets As DataTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
     
    			'Loop through all Sheets to get data
    			For Each dr As DataRow In dtSheets.Rows
    				Dim sheetName As String = dr("TABLE_NAME").ToString()
    				If Not sheetName.EndsWith("$") Then Continue For
    				'Get all rows from the Sheet
    				cmd.CommandText = "SELECT * FROM [" & sheetName & "]"
    				Dim dt As DataTable = New DataTable()
    				dt.TableName = sheetName
    				da = New OleDbDataAdapter(cmd)
    				Dim cb = New OleDbCommandBuilder(da)
    				da.Fill(dt)
    				ds.Tables.Add(dt)
    			Next
     
    			cmd = Nothing
    			conn.Close()
    		End Using
     
    	End Sub
    => Par contre, pas moyen de sauvegarder les modifs que j'apporte à la datagridview !!

    Voici le code actuel que j'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    	Sub Button2Click(sender As Object, e As EventArgs) Handles button2.Click 'boutn sauvegarde
    		connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & XLfilepath & "; Extended Properties=""Excel 12.0 XML;HDR=YES;IMEX=1;"""
    		conn = New OleDbConnection(connectionString)
    		conn.Open()
     
    		ds.Tables(0).PrimaryKey = New DataColumn() {ds.Tables(0).Columns("id")}
    		da = New OleDbDataAdapter("Select * from [contacts$]", conn)   'contacts est le nom de l'onglet excel, et donc de la table
    		Dim cb = New OleDbCommandBuilder(da)
    		cb.QuotePrefix = "["
    		cb.QuoteSuffix = "]"
    		da.Update(ds.Tables(0))
    		Me.ds.AcceptChanges()
     
    		conn.Close()
    	End Sub
    Au final, ce code semble fonctionner (dataset rempli, table remplie avec le bon nom, etc...), mais il bloque à chaque fois sur :
    "La génération SQL dynamique de UpdateCommand n'est pas prise en charge pour un SelectCommand qui ne retourne pas des informations de colonne clé."

    Avez-vous une idée, car j'ai épuisé toutes les solutions que j'ai pu trouver...

  2. #2
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Bonjour ,
    Je ne connais pas le CommandBuilder mais le message d'erreur que tu présentes me laisse penser que le SELECT devrait expliciter le champ clé (et pas seulement un *).
    Tu travailles avec un "Id" sur objet ds et travailles avec CommandBuilder sur un objet da. Est-ce normal ? Quel est le rapport entre le ds et le da ?
    Bonne journée

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 16
    Par défaut
    Alors, pour te répondre :

    L'id en question est le nom de la 1ere colonne de ma base, que j'ai ajouté pour avoir une colonne avec "des éléments uniques et non vides" afin de pouvoir faire une clé primaire.
    Le ds est le Dataset qui contient ma table "contacts" avec toutes les données.
    Le da est le DataAdapter qui fait le lien entre ma base et le DGV.

    Concernant le Commandbuilder, d'après ce que j'ai pu voir, il est nécessaire pour créer les commandes SQL en automatique.
    Concernant la ligne "id" sur objet ds (ds.Tables(0).PrimaryKey = New DataColumn() {ds.Tables(0).Columns("id")}), il s'agit d'un essai d'ajout de clé primaire que j'ai fais, mais il semble que ça ne fonctionne pas...

    Pour répondre à ta question : est-ce normal ? Ben... je pense que oui, mais sans en être sûr

  4. #4
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Merci pour tes explications.
    Mais mes questions faisaient suite au message d'erreur qui semble signifier "je n'ai pas de clé primaire, je ne sais pas travailler"
    D'où ma proposition d'écrire explicitement dans le SELECT le champ "clé" qui doit exister dans XLS. Si ce champs "clé" n'existe que dans le ds.Table(0), il est normal que l'ordre UPDATE (forcément construit par le CommandBuilder) ne puisse être exécuter.

    Mais comme je l'indiquais dans mon message précédent, je n'ai pas d'expérience du CommandBuilder (et j'ai tendance à considérer qu'il travaille comme je le fais moi-même, en programmant tout le SQL, mais il a sans doute des pratiques que j'ignore ... ).

    Certains participants de ce forum sont vraiment bien informés du CommandBuilder. J'espère que l'un d'eux t’apportera la solution.


  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 16
    Par défaut
    En effet Phil Rob, je pense également que la solution tourne autour du fait d'écrire explicitement dans le SELECT le champ "clé" du fichier XLS (la colonne "id")...
    Mais je bloque sur l'écriture de la syntaxe de cette ligne.

  6. #6
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Si le reste de ta ligne est correcte, l'ajout du champ "clé" se ferait comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    da = New OleDbDataAdapter("Select NOM_DE_LA_COLONNE_DE_LA_CLE, * from [contacts$]", conn)

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 16
    Par défaut
    ... Je dois avoir un problème ailleurs alors, car même avec la syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    da = New OleDbDataAdapter("Select id from [contacts$]", conn)
    J'obtiens toujours l'erreur :
    La génération SQL dynamique de UpdateCommand n'est pas prise en charge pour un SelectCommand qui ne retourne pas des informations de colonne clé.

    Si je tente de mettre un "Select 'id' from... ou "Select ds.Tables(0).Columns("id") from ..., il ne reconnait même plus la commande.

    Le résultat reste le même : on dirait qu'il ne trouve pas cette colonne clé (primary key).
    Je pensais à un autre axe de recherche : normalement, cette colonne clé doit être mise en place directement lors de la création de la table, non ?

    EDIT : J'ai hésité à poster ce sujet dans la section "VB.net", j'aurais peut-être mieux fait de le poster dans la section "SQL et base de données"...?

  8. #8
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Je pensais à un autre axe de recherche : normalement, cette colonne clé doit être mise en place directement lors de la création de la table, non ?
    En effet !

    Je ne crois pas que ton problème soit "SQL" mais plutôt qu'il est "CommandBuilder" et là, je ne peux manifestement pas t'aider (je vais me faire un p'tit labo CommandBulder, il y a trop longtemps que j'en vois passer ...). Je ne crois donc pas qu'un forum SQL t'apportera plus que celui-ci.
    Quant à refaire un post, je pense que tu peux le refaire ici, en changeant de titre, par exemple : "Problème d'Update avec CommandBuilder".



    En revoyant ta dernière requête, me vient à l'esprit la question suivante : cette requête ne doit-elle pas énumérer TOUS les champs susceptibles d'être mis à jour par l'UpDate ?

  9. #9
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Re,

    Je viens de me faire un programme de test du CommandBuilder. Je charge les données dans le DataGridView comme je le fais ordinairement et j'ai ajouté une Sub pour faire la mise à jour de la DB avec CommandBuilder.
    Cela fonctionne comme tu peux le constater sur cette video : https://www.dropbox.com/s/mvcpypt6hf...ilder.mp4?dl=0

    Excuse pour l'usage de l'espagnol dans le code, mais je suis parti d'un autre labo qui était entièrement écrit en espagnol (pas le VB ... ). Je crois que le seul lexique utile est celui-ci : Cargar = Charger. Pour le reste, tout est parfaitement compréhensible sans faire appel à Google Translator.

    Voici ce projet de test : TestAccesDBCommandBuilder.zip. J'espère qu'il t'aidera à trouver ce qui ne va pas dans ton programme.

    Attention, tu dois modifier le chemin de la DB dans la chaine de connexion (il est peu probable que ton système soit organisé de la même manière que le mien).

    Bon travail,

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 16
    Par défaut
    En effet mon cher Phil, tout ça m'a l'air fort interessant ! J'essaie de voir ça dès ce soir.
    A première vue, je dois pouvoir exploiter ce code en effet.

    Merci en tout cas de t'impliquer de la sorte

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 16
    Par défaut
    Alors, résultat des tests, j'ai réussi à :
    - traduire le code (eh oui, je n'ai pas fais Espagnol 2eme langue )
    - adapter ce même code pour qu'il utilise mon fichier Excel (juste modifié le nom et le chemin de la BDD, le nom de la table + le ConnectionString),
    - procéder au chargement correct de ma base dans l'appli.

    Jusque là tout se passe bien, exactement comme dans ta vidéo :
    Je peux charger ma base, aller de ligne en ligne avec les boutons Suivant et Précédent... Mais lorsque je clique sur le bouton "Test" après avoir modifié une valeur du DGV, j'ai à nouveau la même erreur sur la ligne "MonCommandBuilder.GetUpdateCommand()":

    "La génération SQL dynamique de UpdateCommand n'est pas prise en charge pour un SelectCommand qui ne retourne pas des informations de colonne clé" !

    Voici les lignes que j'ai dû adapter pour lire les fichiers Excel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Dim NomCompletDB As String = Application.StartupPath & "\Sauvdata.xlsx"   ' Mon existant
    MaConnexion.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & NomCompletDB & "; Extended Properties=""Excel 12.0 XML"""  ' Exécuter en x64
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    NomTableDB = "[contacts$]"      ' c'est LaTableQueJeVeux
    EDIT : j'en viens à me demander si je ne ferais pas mieux de créer mes propres instructions UPDATE au lieu de passer par le commandbuilder... En faisant une boucle pour passer les colonnes 1 par 1 par exemple ?

  12. #12
    Membre Expert Avatar de Phil Rob
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2013
    Messages
    1 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1 613
    Par défaut
    Attention, dans mon code de tests, la chaine de connexion est définie 2 fois, une fois "derrière" BCargar et une fois derrière BTestar. N'as-tu pas oublié de la corriger là aussi ?

    Si ça ne va pas, envoie-moi un extrait (même fictif) de ta feuille XLS que je puisse tester (demain après 15h).

    Bonne nuit ...

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 16
    Par défaut
    Bon ben, après avoir essayé beaucoup de choses et passé beaucoup (trop) de temps sur ce sujet depuis plusieurs semaines, je vais abandonner cette idée de fichier Excel comme fichier de sauvegarde.

    Je voyais cela comme un bon moyen de récupérer facilement les données en cas de problème avec l'appli mais tant pis, je m'oriente finalement vers la sauvegarde des infos en fichier XML.

    J'aurais pu prendre une solution alternative par le biais d'un fichier Access, mais j'ai déjà pratiqué les échanges avec les fichiers XML, et jamais avec Access (surtout qu'il faudrait faire un import avec définition de la colonne clé pour Access).

    Merci quand même à Phil Rob pour le temps passé !

Discussions similaires

  1. UPDATE entre 2 bases
    Par tete-jaune dans le forum Requêtes
    Réponses: 9
    Dernier message: 20/05/2011, 10h09
  2. Réponses: 7
    Dernier message: 02/09/2010, 02h57
  3. Réponses: 1
    Dernier message: 15/05/2008, 16h54
  4. Update entre deux feuilles excel
    Par foxer98 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 23/07/2007, 12h25
  5. Requête UPDATE entre deux Bases de données
    Par dahu17 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 02/05/2007, 12h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo