Probleme Tableau 1dimension avec structure

[Résolu]
Signaler
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018
-
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018
-
Bonjour

Voila j'ai un probleme avec un tableau a une dimension structuré

1. Public Structure mouvement

2. <VBFixedString(10)> Dim datemv As String

3. <VBFixedString(10)> Dim libellé As String

4. <VBFixedString(50)> Dim débit As String

5. <VBFixedString(10)> Dim crédit As String

6. End Structure

7. Dim n As Integer = 0

8. Dim tabmouv() As mouvement

9. tabmouv(n).datemv = "0"
10. tabmouv(n).libellé = "0"

11. tabmouv(n).débit = "0"

12. tabmouv(n).crédit = "0"

J'ai un avertissement sur la ligne souligné

"Avertissement 2 La variable 'tabmouv' est utilisée avant qu'une
valeur ne lui ait été assignée. Une exception de référence null peut se
produire au moment de l'exécution."

J'ai l'erreur suivante sur la ligne soulignée lorsque j'execute

"System.NullReferenceException : La référence d'objet n'est pas définie à une instance d'un objet."

Il faudrait initialiser le tableau non ?
merci de votre aide

12 réponses

Messages postés
14825
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
20 octobre 2021
157
Bonjour

C'est normal, tu as déclarer un tableau sans le dimmensionné, c'est un tableau dynamique, il faut que tu utilises l'instruction Redim pour définir sa taille.

Le fer à souder a besoin d'une panne pour fonctionner.
VB (6, .NET1&2), C++, C#.Net1
Mon site
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
9
Salut,

Ouais, donc soit tu déclare sa taille directement:
Dim tabmouv(10) As mouvement
Ou plus tard:
Dim tabmouv() As mouvement
ReDim tabmouv(10) As mouvement
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
9
1. New est utilsé pour instancier une classe en effet. Mais là tu travail avec un tableau de structures, qui sont des types par valeurs, donc pas besoin de new. Si tu connais pas la différence entre les types par valeur ou par référence, je te conseil de lire des trucs sur le sujet.
Dim VariableParValeur as UneStrucure ' Créer une structure UneStrucure en mémoire
Dim VariableParReference as UneClasse ' Créer une référence à un objet (la classe UneClasse ) en mémoire, mais l'objet n'existe pas encore. Il faut utiliser le mot clé New pour créer cet objet.
VariableParReference = New UneClasse
ou
Dim VariableParReference as New UneClasse

Si tu t'y connais en C/C++, une référence n'est rien d'autre qu'un pointeur. Si tu copie un objet ByRef tu copie son pointeur, pas l'objet sur lequel il pointe. Et créer le pointeur et créer l'objet sont 2 choses distincts.

2. Mtn, pour répondre à ta demande. On est en .NET là, donc utilisons les possibilité de .NET

' La structure. Pourquoi as-tu utilsé VBFixedString? C'est utile que lorsque c'est absolument nécessaire, par exemple lors de l'appel d'APIs
' De plus, pourquoi déclarer tous les membres en string? datemv semble plutot être de type Date et débit et crédit des Integer
Public Structure mouvement
    Dim datemv As Date
    Dim libellé As String
    Dim débit As Integer
    Dim crédit As Integer
End Structure

' Création d'une liste dans laquelle mettre les mouvements. Une bonne liste générique .NET ;-)
Dim mouvements as New Generic.List(of mouvement)

' Après pour ton truc MySQL, je vois pas pourquoi MySQL_Select te retournerais un Integer. Donc:
Dim nbmv As odbc.odbcdataReader = monAccesBD.MySQL_Select("select count(numéro)
from mouvements")
' Je ne connais pas, mais il y a forcément une propriété qui te retourne le nombre d'enregistrement dans la BDD. Mais tu n'en a pas forcément besoin pour construire ta liste, il suffit de parcourir chaque enregistrement de ta BDD. Pour ca je peux pas t'aider...
' Mais dès que tu as un enregistrement:
Dim mouvement as mouvement
mouvement .datemv = LaDate
mouvement .libellé = LeLibellé
mouvement .débit = LeDébit
mouvement .crédit = LeCrédit
mouvements.Add(mouvement)

Voila
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
9
Je voudrait savoir le format exacte du type date car moi j'utilise le
format suivant "25/04/2008" pour enregistrer les mouvement donc si le
type date ne correspond pas je garde le type string et pour trier les
date je ferai comme cela



Une date, c'est un long qui inclut la date et l'heure. Mais les structure Date ou DateTime te permetent de convertir cette valeur long en années, mois, jours, jour de l'année, jour de la semaine, heures, minutes, secondes, miliseconde, ticks... tout ce que tu veux donc :)
Je te conseil vivement d'utiliser le type Date donc, ca peut que te faciliter la vie, même si tu doit au préalable convertir tes formats String en Date:

        Dim DateString As String = "23/02/1989"
        Dim tabDate() As String = DateString.Split("/")
        Dim MyDate As New Date(tabDate(2), tabDate(1), tabDate(0))

Remarque: System.String.Split est bien plus rapide que Microsoft.VisualBasic.Strings.Split. Donc au lieu de faire Split(MonString, Sep) tu fais MonString.Split(Sep). Meme chose pour left, mid, right, et toute ces autres fonctions du genre. (Evite les fonctions offertes par l'outils de développement en général, et utilise plutot celle offertes par le Framework)
<hr size="2" width="100%" /> maintenant je voudrait trier cette liste par date croissante
Toutes les listes on un système de triage intégré. Donc encore une fois, inutile de te compliquer la vie ;)
Il y a un comparateur par défaut pour le triage, mais pour trier la liste en fonction du membre 'date' de ta structure, il faut en définir en sois-même:

     Private Class mouvementComparer
        Inherits System.Collections.Generic.Comparer(Of mouvement)

        Public Overrides Function Compare(ByVal x As mouvement, ByVal y As mouvement) As Integer
            Return Date.Compare(x.datemv, y.datemv)
        End Function
    End Class

Puis pour trier ta liste en fonction de la date:

List.Sort(New mouvementComparer)

Si tu veux trier en fonction d'autre chose que la date, soit tu fais un Comparer pour chaque triage, ou alors un unique Comparer ou tu peux choisir le type de triage, et pourquoi pas aussi le triage chronologique ou inverse:

List.Sort(New mouvementComparer(SortByCredit, SortDescending))

Pour trier une ListView, même façon de procéder. La Listbox par contre n'intègre pas cette fonction, c'est donc un peu plus compliqué à mettre en oeuvre. En passant, si le triage de ta liste générique n'est pas indispensable, évite le et fais le seulement à l'affichage dans une ListView par ex.
<hr size ="2" width="100%" />si j'utilise dans la forme Gérer_ses_comptes (donc la ou il y a la ListeBox "LstCompte") Il
trouve aucune valeur a "lesComptes.LstComptes.SelectedItem", il veut
que je mette "LstComptes.SelectedItem" ou "Me.LstComptes.SelectedItem".

Bah oui normal...

Dim lesComptes As New Gérer_ses_comptes

La tu créé une nouvelle forme 'Gérer_ses_comptes', tu ne fais pas référence à ta forme déjà ouverte.
Accède directement à ta forme déjà ouverte au lieu d'en créer une nouvelle. Tu peux utiliser My.Forms pour afficher puis accéder à tes formes, ou My.Application.OpenForms lorsque tu ouvre plusieurs fois la même.
Messages postés
840
Date d'inscription
mercredi 22 octobre 2003
Statut
Membre
Dernière intervention
7 janvier 2009
9
Comment efface-t-on la liste générique svp ?


List.Items.Clear
<hr size="2" width="100%" />le tri fonctionne aussi par contre je comprend pas le code, si tu pouvais m'expliquer un peu plus en détail
Pour classer une liste, on utilise une classe implémentant l'interface IComparer. Cette interface expose une fonction 'Compare' qui permet de comparer 2 objets, sa valeur de retour (1, -1 ou 0) définit si l'objet X se place avant, après ou à la même place que l'objet Y.
Par appels successifs de cette fonction, une liste pourra donc trier son contenu.
La classe de base 'Generic.Comparer(Of mouvement)' que j'utilise dans mon exemple implémente cette interface 'IComparer'.
Pour trier notre liste générique, on passe une instance d'une classe implémentant cette interface au moment d'appeler la méthode Sort::
List.Sort(New mouvementComparer)
Pour une ListView par exemple, on définit cette classe à une propriété de la ListView avant d'appeler sa méthode Sort:
Listview.ListViewItemSorter = New ListViewComparer
Listview.Sort
Exemple sur MSDN
<hr size="2" width="100%" />Je voudrais vérifier lorsque l'on saisit un mouvement que la date est
bien au format date (ex "12/08/1985"). La date est saisie dans une
textbox
Dim myDate as TimeDate = GetDate(TextBox1.Text)
If myDate = Nothing Then
    MsgBox("Format de date invalide")
Else
    ' La date est correct
End If

Private Function GetDate(StringDate as String) as Date
    Dim tabDate() As String = StringDate.Split("/")
    If tabDate.Lenght <> 3 Then Return Nothing
    Try
        Dim MyDate As New Date(tabDate(2), tabDate(1), tabDate(0))
        Return MyDate
    Catch Ex As Exception
        Return Nothing
    End Try
End Function

Il y aurait des façons plus élégante de tester la date, par exemple avec DateTime.TryParse, ce qui éviterait l'utlisation d'un Try/End Try, mais mon exemple est plus simple et fonctionne très bien quand même (je crois, j'ai pas testé).
Note que mon exemple ne vérifie pas vraiment le format d'entrée, mais si la date est valide. Donc, par exemple, la date est aussi valide si on écrit "2/8/01985" au lieu de "02/08/1985".
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018

ok merci les gars

Es-ce que je ne pourrai pas faire de l'allocation dynamique ? avec New ?
Je ne sais pas trop comment m'y prendre mais il en parle dans l'aide de l'erreur
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018

Le probleme c'est que je ne sais pas combien d'élément je vais mettre dans mon tableau

Je vais parcourrir une base de donnée et ajouter dans le tableau tout les mouvements
Je voudrai compter le nombre d'éléments que je vais mettre dans ce tableau avec cette requete :

Dim monAccesBD = New gestionBD("127.0.0.1", "baseig", "root", "root")

Dim nbmv As Integer = monAccesBD.MySQL_Select("select count(numéro) from mouvements") 
//numéro est l'identifiant de la table mouvements
Dim tabmouv(nbmv) As mouvement

mais il me dit que nbmv doit être de type odbc.odbcdataReader
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018

merci de ta réponse
Bon j'ai pas tout compris pourtant ByVal, ByRef c'est la dernière chose que j'ai vu en cours

Pour la Generic.List ça marche !!! J'arrive à la remplir c'est impec
maintenant je voudrait trier cette liste par date croissante
Je voudrait savoir le format exacte du type date car moi j'utilise le format suivant "25/04/2008" pour enregistrer les mouvement donc si le type date ne correspond pas je garde le type string et pour trier les date je ferai comme cela :

            Dim trouve As Boolean
            Dim tabdate1(3) As String
            Dim tabdate2(3) As String
            Dim stock As mouvement
            Dim i As Integer
            Dim j As Integer
            For i = listmouv.Count To 1
                For j = 1 To i
                    tabdate1 = Split(listmouv.Item(i).datemv, "/", 3)
                    tabdate2 = Split(listmouv.Item(i + 1).datemv, "/", 3)
                    trouve = False
                    If Val(tabdate1(2)) < Val(tabdate2(2)) Then
                        trouve = True
                    Else
                        If Val(tabdate1(2)) = Val(tabdate2(2)) And Val(tabdate1(1)) < Val(tabdate2(1)) Then
                            trouve = True
                        Else                            If Val(tabdate1(2)) Val(tabdate2(2)) And Val(tabdate1(1)) Val(tabdate2(1)) And Val(tabdate1(0)) <= Val(tabdate2(0)) Then
                                trouve = True
                            End If
                        End If
                    End If
                    If trouve = False Then
                        stock = listmouv.Item(j - 1)
                        listmouv.Item(j - 1) = listmouv.Item(j)
                        listmouv.Item(j) = stock
                    End If
                Next
            Next
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018

ça y est mon tri fonctionne je l'ai mis dans une procedure qui est sur un fichier de code vb a part pour pouvoir l'utiliser plusieur fois, et sur d'autre forme
- Pour le tri ça fonctionne
- Je voudrais faire d'autre procédure mais dedans j'utilise une ListBox qui est sur une forme donc dans la procédure il faudrait que je référence la ListBox en absolue pour qu'elle soit reconnue quant j'utiliserai la procédure sur les autres formes

- par exemple j'ai 2 formes : Gérer_ses_comptes et Gestion_du_compte
- La ListBox se trouve sur Gérer_ses_comptes

Dans la procédure j'ai fait :
Dim lesComptes As New Gérer_ses_comptes
Dim leCompte As New Gestion_du_compte
If lesComptes.LstComptes.SelectedItem = UneVariable Then
'des instruction
End If

si j'utilise dans la forme Gérer_ses_comptes (donc la ou il y a la ListeBox "LstCompte")
Il trouve aucune valeur a "lesComptes.LstComptes.SelectedItem", il veut que je mette "LstComptes.SelectedItem" ou "Me.LstComptes.SelectedItem"
Merci pour votre attention
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018

ok merci, pour le référencement des formes c'est bon, les procédures fonctionnent
Je verai toute à leur pour le reste. Comment efface-t-on la liste générique svp ?
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018

la date c'est bon aussi
le tri fonctionne aussi par contre je comprend pas le code, si tu pouvais m'expliquer un peu plus en détail
Je voudrais vérifier lorsque l'on saisit un mouvement que la date est bien au format date (ex "12/08/1985"). La date est saisie dans une textbox
merci
Messages postés
42
Date d'inscription
dimanche 20 février 2011
Statut
Membre
Dernière intervention
1 avril 2018

ok merci sa fonctionne, par contre
Dim myDate as TimeDate = GetDate(TextBox1.Text)
Il reconnait pas de type TimeDate par contre DateTime oui
Dim myDate as DateTime = GetDate(TextBox1.Text)