none
VS2015 - Mehrdimensionale Variablen füllen - Fehler ="System.NullReferenceException" RRS feed

  • Frage

  • Hallo liebe User,

    ich möchte nun einen Schritt weiter gehen und mein (sehr umfangreiches) Programm in Visual Studio 2015 programmieren.

    Leider musste ich feststellen, das diese Sprache und Art der Programmierung fast komplett anders ist.

     

    Das Grobe lässt sich zwar umsetzen, ich bekomme allerdings Probleme bei Mehrdimensionalen Arrays und denen dann Werte zuzuweisen.

     

    Ich wäre schön, wenn es hier jemanden gibt, der mir dabei helfen könnte.

    Ich habe z.B. dei Variable: Public ChkKomOK(10) as Byte generiert, da sie in allen Modulen und Forms mit Werten gefüllt wird.

    Ein Wert zuweisen wollte ich dann in einem anderen Modul mit: ChkKomOk(1) = 0

    Da kommt aber eine Fehlermeldung:

    "Eine Ausnahme vom Typ "System.NullReferenceException" ist in Test-01.exe aufgetreten, doch wurde diese im Benutzercode nicht verarbeitet." Dazu kommt dann aus der Hilfedatei folgende Info:

    "Eine NullReferenceException tritt auf, wenn Sie versuchen, eine Methode oder Eigenschaft eines Verweistyps ( C#, Visual Basic) zu verwenden, deren Wert null ist. Möglicherweise haben Sie versucht, ein Objekt zu verwenden, ohne zunächst das Schlüsselwort new ( New in Visual Basic) zu verwenden, oder der Wert des Objekts war null ( Nothing in Visual Basic)"

     

    ALSO

    ich habe NULL Ahnung

     

    Bitte helft mir....

    Freitag, 27. Januar 2017 20:55

Antworten

  • Hi,
    Deine Anweisung "Public ChkKomOK(10) as Byte" erzeugt ein eindimensionales Array. Beim Zugriff auf ein Element in diesem Array kann der von Dir genannte Fehler NICHT kommen. Die Erzeugung eines Arrays in VB.NET weicht etwas von der Erzeugung eines Arrays in C#.NET ab, auf die sich Tom bezieht.

    Anhand Deiner kurzen Beschreibung vermute ich, dass Du irgendwo im Programm den Variablenbezeichner "ChkKomOK" nutzt, der mit Deiner Deklaration von "ChkKomOK" nichts zu tun hat, weil sich beide Variablen in unterschiedlichen Gültigkeitsbereichen befinden. Um diesem Problem auf die Schliche zu kommen, solltest Du im Projekt setzen:

    Option Strict On
    Option Explicit On


    Weiterhin kannst Du über das Kontextmenü (rechte Maustaste über der Variablen "ChkKomOK" in der Anweisung, die den Fehler auslöst) mit "Go to Definition" prüfen, wo die wirklich genutzte Variable deklariert ist.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks



    Samstag, 28. Januar 2017 05:45

Alle Antworten

  • Hallo,

    ich gehe mal davon aus, dass du VB.NET als Programmiersprache verwendest.

    Wie gut kannst du denn die Sprache? Denn die Fehlermeldung ist eigentlich mehr als Eindeutig. Dein Array ist Nothing weil du es nie zugewiesen hast. Entsprechend bekommst du eine Exception, sobald du versuchst auf das Array zuzugreifen. Es fehlt also irgendwo die Zuweisung vor der ersten Verwendung. Siehe auch: How to: Initialize an Array Variable in Visual Basic

    Rein von der Deklaration sind deine Arrays aber auch noch nicht mehrdimensional.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Freitag, 27. Januar 2017 23:44
    Moderator
  • Hi,
    Deine Anweisung "Public ChkKomOK(10) as Byte" erzeugt ein eindimensionales Array. Beim Zugriff auf ein Element in diesem Array kann der von Dir genannte Fehler NICHT kommen. Die Erzeugung eines Arrays in VB.NET weicht etwas von der Erzeugung eines Arrays in C#.NET ab, auf die sich Tom bezieht.

    Anhand Deiner kurzen Beschreibung vermute ich, dass Du irgendwo im Programm den Variablenbezeichner "ChkKomOK" nutzt, der mit Deiner Deklaration von "ChkKomOK" nichts zu tun hat, weil sich beide Variablen in unterschiedlichen Gültigkeitsbereichen befinden. Um diesem Problem auf die Schliche zu kommen, solltest Du im Projekt setzen:

    Option Strict On
    Option Explicit On


    Weiterhin kannst Du über das Kontextmenü (rechte Maustaste über der Variablen "ChkKomOK" in der Anweisung, die den Fehler auslöst) mit "Go to Definition" prüfen, wo die wirklich genutzte Variable deklariert ist.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks



    Samstag, 28. Januar 2017 05:45
  • Hallo Tom Lambert,

    erstmal vielen Dank für Dein Interesse an mein Problem. Ich programmier derzeit in Excel-VBA.

    Dort habe ich ein Programm mit ca. 20 Userforms und gut 15 Modulen programmiert.

    Mit diesem Programm werden Spezifikatione mit 300 Feldern erstellt. Diese werden später in einem Bestellformular eingelesen und auf verschiedene Weise noch weiterverarbeitet (Druck mit EAN-Code usw.).

    Nun habe ich das MS Visualstudio 2015 entdeckt, und hoffte die VB ist ähnlich der des Excel-VBA... dem ist leider nicht so!

    Im Excel VBA reichte ein DIM Spezi(10,300) oder Public xxx und man mußte nicht noch die Werte initialisieren. Die wurden im späteren Verlauf des Programms einfach mit einem Wert gefüllt, wenn der Bedarf da war.

    Wie kann ich nun mit einem Befehl ein komplettes Array oder Mehrdimensionales Array initialisieren. Da ich im Vorfeld nicht die Werte kenne, die im Programmablauf dort hinein geschrieben werden. Muss ich jede Variable im Vorfeld mit einem Wert füllen?

    Dann gibt es noch im Excel-VBA den Befehl "Controls" um z.B. von anderen Modulen in eine Form-Textbox Daten zu schreiben. Z.B. so:

    Dim UFX as Object

    Dim NAME as String

    Im UserForm Init stand dann: Set UFX as UserForm1

    Nun konnte ich in Modulen per Befehl UFX.Controls(NAME).Text = "Hallo" einen Wert schreiben.

    Der Wert in NAME wurde vor dem Sprung in das Modul definiert mit z.B. "txtPreis_UF1".

    Da nun das Modul von mehreren Userforms angesprungen wird, war dies die einfachste und komfortabelste Variante. Auch das Auslesen aller Textboxen, Comboboxen usw. kann durch Schleifenbildungen in dieser Art mit wenig Programmcode realisiert werden.

    Naja, jedenfalls bekomme ich das im VS-VB nicht hin, da hier komplett anders programmiert wird.

    Auch das Buch "Einstieg in VS VB2015 hilft Einsteigern nicht wirklich...

    Das Handling mit "Class" und Proberty mit Get und Set() habe ich auch noch nicht so richtig verstanden.

    Ich glaube fast, ich benötige ein Buch, welches mich als totalen Anfänger betrachtet...

    Seufz.

    Ich hoffe, ich habe mich etwas verständlich ausgedrückt  ;-(

    Montag, 30. Januar 2017 18:51
  • Hallo,

    ich bin eigentlich C#ler und kann VB.NET auch eher nur lesen als schreiben. Von daher solltest du auch Peters Antwort beachten. Es könnte sein, dass ich in meiner ersten Antwort etwas falsch lag.

    Was die ganzen anderen Probleme betrifft, so sind mMn die Namen VB, VBA, VB.NET etc. sehr unglücklich gewählt. Es kommt ständig zu Verwechslungen obwohl sie, bis auf ein paar syntaktische Elemente, oftmals fast nichts gemeinsam haben.

    Das von dir genannte Buch kenne ich zwar nicht, aber auf etwas derartiges wirst du setzen müssen, um die Sprache richtig zu erlernen. VBA ist (meinem Empfinden nach) deutlich weniger komplex als VB.NET, was es natürlich kompliziert macht. Und dann kommen noch gewisse Einschränkungen hinzu, weil man ja ordentlich programmieren will und da verwirren die syntaktisch ähnlichen Elemente vermutlich mehr, als das sie helfen.

    Was VBAs Controls und ähnliches Betrifft, so ist der größte Unterschied bei VB.NET, dass man hier grundlegend erstmal gar nichts hat und alles selbst bauen muss. Es ist zwar einfach weitere Fenster hinzuzufügen usw., aber das folgt halt einer anderen - viel grundlegenderen - Logik.

    Ich will dich jetzt nicht von der VB.NET Schiene abbringen, aber falls die ähnliche, aber anders arbeitende Syntax ein Problem für dich ist, dann solltest du dir mal C# ansehen. Beide basieren auf .NET und funktionieren bis auf wenige Stellen gleich. Aber die Syntax ist eine komplett andere Welt. Aber auch dort wirst du mit Klassen, Eigenschaften etc. zurecht kommen müssen.

    Einzelne Verständnisprobleme können wir hier im Forum gerne in getrennte Threads klären. Aber für die komplette Sprache wird wohl niemand Zeit haben :)


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Montag, 30. Januar 2017 19:17
    Moderator
  • Hallo Tom,

    Vielen Dank für Deine ausführliche Antwort. Finde ich Super.

    Ich werde wohl noch weiter nach Büchern suchen Müssen. Leider gibt es bei MS kein Richtiges Forum, in dem man die Befehlsstruktur nachlesen kann.

    Trotzdem erstmal vielen Dank an alle und weiterhin frohes tippen...

    ;-)

    Vielleicht kann mir der Peter zu meinem Problem mit dem Ansprechen eines Formulars aus einem Modul heraus etwas helfen.

    Der Gedanke ist, mit einer FORMVariablen und einer FELDVariablen aus einem Modul heraus die Elemente in einer  Form zu füllen oder zu lesen.

    Z.B. 

    FORMvariable.FELDvariable.Text = WERT      ' rein schreiben)

    oder

    WERT = FORMvariable.FELDvariable.Text (.Listindex / .Checked usw.)     ' auslesen

    Wie bereits erwähnt, ging das im Excel-VBA so:

    Global Feldname, WERT As String

    Global   UFX As Object

    Set   UFX = UserForm2  (Wäre im VB sozusagen das: Form2.vb  mit seinem "Public Class UF_Order"

    Im Modul dann : 

         UFX.Controls(Feldname).Value= WERT    ' rein schreiben

    oder

         WERT= UFX.Controls(Feldname).Value       ' auslesen

    Hier konnte z.B. durch eine Schleife eine Abfrage erstellt werden:

    For R=1 To 10

       Feldname = "Textbox_" & R

       Spezi(IDX, R) = UFX.Controls(Feldname).Value

    Next R

    Wäre schön, wenn es dafür eine Lösung gäbe...

    Bis dahin erstmal Danke

    Gruß

    Ralf

    Dienstag, 31. Januar 2017 17:21
  • Hi,
    unklar ist, wozu Du ein zweidimensionales Array mit Werten aus Steuerelementen benötigst.

    Das Prinzip der Kapselung in Klassen bedeutet, dass Innereien in der Kapsel versteckt werden und üblicherweise außen nicht benötigt werden. Bezogen auf Deine Frage ist ein Zugriff auf die Controls von außen nicht erforderlich. Innerhalb der Kapsel (=Klasse) kann man auf die Werte in den Steuerelementen zugreifen. Da üblicherweise jede TextBox zu einem speziellen Sachverhalt gehört, ist ein Array sinnlos (außer vielleicht in Matrizendarstellungen, für die aber komplexe Steuerelemente meist besser sind). Das bedeutet, dass in der Kapsel jeder TextBox-Inhalt einer Eigenschaft eines Datenobjektes zugewiesen wird. Das sind dann anstelle einer Schleife meist Einzelzuweisungen. Wenn das Datenobjekt zwischen den Forms weitergegeben werden soll, dann kann dazu ein statisches Feld (in einem Modul) genutzt werden, in welchem ein Verweis auf das Datenobjekt gehalten wird (analog der Set-Anweisung im VB6/VBA).

    Falls Du etwas genauer Dein Ziel beschreibst, kann ich eine VB.NET-Demo posten.

    Wärmstens zu empfehlen ist auch das Setzen von Option Strict On zur Vermeidung impliziter Typkonvertierungen, die zu unvorhersehbaren Ergebnissen führen können.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    Dienstag, 31. Januar 2017 19:33
  • Hallo zusammen

    Ich habe das Forum hier vor ein paar Tagen zum ersten mal besucht, bin auch Anfänger , habe früher unter DOS viel QB45 gemacht, Bin jetzt im Ruhestand und versuche es noch mal, zum fitt bleiben :-). Die Denke von VS2015 ist etwas anders als unter QB45 und unter VB Office  :-) die beiden sind ziemlich ähnlich. Deinem Problem kann ich nicht ganz folgen. Ich versuche mal zusammen zufassen.

    Du hast eine oder mehrere Forms und Module und willst Variable und/oder  Felder über diese Module und Foms hinweg Global benutzen.  Ebenfalls erwähnst Du ein Buch "Einstieg in VB2015 Thomas Theis" denke ich ?

    Also in dem Buch ist ein Beispiel dazu auf Seite 138 Mehrere Formulare. Das solltest Du durcharbeiten. Hier kurz worauf es ankommt. Im Hauptformular die betreffenden Variablen mit Public dimensionieren, und zwar im allgemeinen Teil also vor dem ersten SUB Anweisung. Seite 140

    Public class Form 1

    public Px as Integer ( kann natürlich auch ein Feld sein Public Px(10) as Byte z.B )

    Private Sub .....

    Damit soll Px öffentlich für das ganze Projekt sein, so denkt man sich das.  Ich bin da auch erst drüber gestolpert,  und habe versucht in einer anderen Form die Variable Px so zu benutzen ging aber nicht, weil sie dort nicht bekannt ist.  Dazu muss man sich vorstellen was die einzelnen Forms und Module eigentlich sind , das steht oben immer drüber "Cass" also Objekte. Damit ist die Variable dann eigentlich eine Eigenschaft des Objektes Form1. und der Objektname muss mit dazu also Form1.Px wenn sie ausserhalb von Form1 benutzt wird.

    Auf der Seite 141 wird in dem Beispiel dann diese Variable Px  in der letzten SUB benutzt.

    Private Sub cmdAnzeige_Click(.... ) .....

         Form1.Px = Form1.Px +1

    Dann klappt das auch.

    in den beiden anderen Subs der Form2 wird das mit den Steuerelementen ebenfalls gemacht da ist einem das aber ehr klar z.B

    Form1.lblHauptformular.Text = txt.Unterformular.Text

    Das Buch finde ich eigentlich ganz gut, allerdings sollte man es systematisch durcharbeiten damit man es und auch VS2015 versteht. Zum üben zwischendurch immer mal selbst ein Beispiel überlegen und das Programm dazu dann selbst schreiben ohne die Zeilen einzeln aus dem Buch abzuschreiben. Leider kann man nur aus Fehlern lernen.

    Gruß aus dem Rheinland

    Heinz

    Dienstag, 31. Januar 2017 20:12
  • Hallo Ralf,

    die gesamte VB.NET Doku findest du in der MSDN: Visual Basic Language Reference

    Zum Nachgucken ist das meistens nicht schlecht, zum lernen finde ich aber Bücher besser. Durch diese lernt man (wie ich finde) besser die notwendigen Programmiertechniken.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Dienstag, 31. Januar 2017 23:06
    Moderator
  • Hallo Heinz,

    vielen Dank für Deine Antwort. Du kommst meinem Anliegen schon recht nah.

    Meine vielen Eingabefelder in einer UserForm (VS2015=Form1) sind z.B. Textboxen/chkboxen/Radioboxen und Comboboxen.

    Hier wird also eine Spezifikation für einen Artikel erstellt. Wenn alles eingegeben wurde, soll die Eingaben dieser Form eingelesen werden (die TextFelder lauten z.B. "txtSpezi1_1 bis _30 und txtSpezi2_1 bis _50", die chkBoxen dann "chkSpezi1_31 bis _40" und die Radiobtn dann "optSpezi1_51 bis _60 .

    Nun möchte ich die"Form1" als Variable deklarieren (z.B. UFX=Form1) und die Felder als String(z.B. BoxArt="txtSpezi1_8". Unter ExcelVBA konnte ich eine Schleife konstruieren, in der ich diese Felder gezielt außerhalb des UserFurm in einem Modul durchlaufen konnte und in einer Variablen ablegen und später in ein File speicher. z.B. so.

    MODUL Spezi_Read

    Dim UFX as Object

    Dim BoxArt as String, Spezi(8,300)     {soll bedeuten: bis zu 9 Spezis mit jeweils 300 Feldern in einem Array}

    Sub LeseDaten()

       Set UFX = UserForm1       

    For R1 = 1 To 8

       For R2=1 To 30

          Boxart= "txtSpezi" & R1 & "1_" & R2

          Spezi(1,R) = UFX.Controls(BoxArt).Text

       Next R2

       (Und so Weiter für die opt und chk und cmb Felder)

    Next R1

    End Sub

    Diese Art des Zugriffs auf eine Form (UserForm) mit [FormVariable.Controls(FeldVariable).Value] gibt es bei VS2015 VB nicht.

    Vielleicht kannst Du mir da helfen, wie man so etwas mit VS2015 VB realisiert.

    Liebe Grüße aus Berlin

    Ralf

    Samstag, 18. Februar 2017 15:36
  • Hallo Ralf

    ich bin etwas spät dran sorry. Für den Fall das Du da noch nicht weiter gekommen bist

    ich habs noch nicht ganz verstanden. Du benötigst eigentlich Controls die einen Index haben. Also eigentlich ein Feld von Textboxen ,  damit Du auf den Inhalt  ausserhalb der Form mit einer Schleife zugreien kannst ? Hab ich das richtig verstanden ? Mir ist auch nicht ganz klar wozu Du so viele Eingabefelder benötigst. Da blickt doch kein User mehr durch.

    ich glaube das wird nicht gehen.

    Du solltest Dir mal die Tabellen Controls ansehen da kann man die Daten über einen Index ansprechen (Zeile , Spalte ) über die man mit Hilfe einer Schleife drankommt.

    Auf der anderen Seite ist Deine Anwendung sicher ehr was für eine Datenbank mit verschiedenen Tabellen die miteinander über ID verknüpft sind. Eigentlich hast Du doch sicher derzeit die Daten auch in verscheidenen Excell Tabellenblättern um ane einen Art Struktur zu kommen.

    Heinz

    Donnerstag, 2. März 2017 18:18
  • Moin Heinz,

    erstmal Danke für Dein Interesse an mein Problem.

    Sicher geht das auch über Datenbanken. Ich wollte nun meine Routinen so wenig wie möglich NEU programmieren.

    Leider existieren bereits einige hundert "Spezifikationen" als *.xls Datei, die jeweils eine Spalte mit 300 Zellen haben.

    Auch die einzelnen "Bestellungen" sind jeweils als *.xls-Datei angelegt und haben rund 500 Zellen in einer Spalte.

    Mein Problem besteht eher darin, das ich diverse Subroutinen in Modulen habe, die von mehreren UserForms aufgerufen werden. Aus diesem Grund setze ich vor dem Aufruf der Subr. das
    OBJECT "UFX=Set UserFormXY" und ein "BYTE" UF=xy um in der Subr. das UserForm mit Select Case zu identifizieren.

    Nun kann die Subr.  durch den übergebenen Feldnamen (z.B. "txtSpezi_1_1") die Auswertung, 
    Neubelegung des Wertes, formatieren als Zahlenwert oder Währung usw., weiterverarbeiten.

    Da diese Variable (z.B. die Artikelnummer)  in verschiedenen UFs auch andere Feldnamen hat ("txtSpezi_1_1" oder "txtOrder_0_5" oder "txtVPE_1_10") funktionierte das sehr gut.

    Im "alten VB" gab es also die Möglichkeit, die Felder UND die UserForms über Variablen anzusprechen:

    Dim UFX as Objekt (für das UserForm: UserForm1 oder UserForm2 usw)

    Dim UF as Byte (zur Erkennung des UserForms

    Dim BoxArt as String (für den Feldnamen)

    Dim ArtIdx as Byte (ArtikelIndex für Array)

    Dim Order(10,300) as String (für die 10 Artikelgruppen a300 Felder in einer Bestellung)

    Aufruf war dann: Spezi(ArtIdx, 5) = UFX.Controls(Boxart).Value

    Meine Frage lautet daher: Kann ich das auch mit VisualStudio VB 2015 realisieren und wie lauten die Variablen und die Aufrufe dafür.

    Klingt ev. alles recht umständlich, läuft aber wunderbar im Excel-VBA.

    Schon mal Vorab ein DANKE

    Ich würde mich sehr über eine Hilfreiche Antwort freuen,
    falls Du noch Interesse an mein "BIG PROBLEM" hast.

    LG

    Ralf

    Sonntag, 19. März 2017 09:05