1. Liebe Forumsgemeinde,

    aufgrund der Bestimmungen, die sich aus der DSGVO ergeben, müssten umfangreiche Anpassungen am Forum vorgenommen werden, die sich für uns nicht wirtschaftlich abbilden lassen. Daher haben wir uns entschlossen, das Forum in seiner aktuellen Form zu archivieren und online bereit zu stellen, jedoch keine Neuanmeldungen oder neuen Kommentare mehr zuzulassen. So ist sichergestellt, dass das gesammelte Wissen nicht verloren geht, und wir die Seite dennoch DSGVO-konform zur Verfügung stellen können.
    Dies wird in den nächsten Tagen umgesetzt.

    Ich danke allen, die sich in den letzten Jahren für Hilfesuchende und auch für das Forum selbst engagiert haben. Ich bin weiterhin für euch erreichbar unter tti(bei)pcwelt.de.
    Dismiss Notice

VBA.NET Problem mit Xml.XmlTextWriter

Discussion in 'Programmieren' started by scullhead, Mar 8, 2011.

Thread Status:
Not open for further replies.
  1. scullhead

    scullhead Byte

    Hallo,

    ich arbeite an einem kleinen Tool welches ich mit Visual Studio 2005 in VBA.NET erstelle. Das Programm funktioniert soweit einwandfrei. Ich habe es kürzlich um eine Klasse erweitert, die es mir ermöglicht die Programmeinstellungen in einem XML File zu speichern.

    Dazu benutze ich das Xml.XmlTextWriter Objekt. Lesen und Schreiben funktionieren auch einwandfrei. Nun habe ich aber folgendes Problem festgestellt:

    Sobald ich an einer anderen Stelle im Programm einen FileDialog einblende:

    Code:
        Public Sub getwlfilename()
            Dim dialog_ok As Byte = 0
    
            With Form1
                .DLG_MGN_openFile.Filter = "Textdateien (*.txt)|*.txt"
                dialog_ok = .DLG_MGN_openFile.ShowDialog()
                If dialog_ok = 1 Then
                    wordlistfilename = .DLG_MGN_openFile.FileName
                Else
                    wordlistfilename = ""
                End If
            End With
    
        End Sub
    
    Funktioniert das Schreiben in die XML Datei mit dem XMLTextWriter nicht mehr. Ich hab hier schon alles Step by Step im Debug Modus durchgeschaut...
    Die XML Klasse arbeitet ganz normal wie immer - mit dem einzigen Unterschied, dass nichts in die XML Datei geschrieben bzw. aktualisiert wurde wenn zuvor der OpenFileDialog benutzt wurde.

    Eine Google Suche brachte mich zu folgendem Beitrag in einem anderen Forum: Klick

    Ist offenbar eine Ähnliche Thematik in C# - aber hier gab es offenbar auch noch keine Lösung.

    Ich bin froh, dass ich nach ewigem Debuggen zumindest den FileDialog als Ursache einkreisen konnte. Allerdings komm ich hier nicht weiter.

    Hat jemand eine Idee woran es liegen könnte?

    p.S. Ich wollte den Link auf das andere Forum mit T i ny U R L Kürzen - wird hier aber irgentwie zensiert...?
     
    Last edited: Mar 8, 2011
  2. salim_aliya

    salim_aliya Halbes Megabyte

    Hallo,

    wie ich das aus deinem Quellcode lese, versuchst du den Dateipfad heruaszufinden, um sie dann weiterverwenden zu können.

    Hierzu ändere mal

    Code:
    wordlistfilename = .DLG_MGN_openFile.FileName
    
    in

    Code:
    wordlistfilename = .DLG_MGN_openFile.FileName.ToString()
    
    um und probiere es so noch einmal.

    Auf dieser Seite wird das Öffnen via Dialog in VB.NET veranschaulicht. Du arbeitest zwar unter VBA.NET, aber der von mir heruasgepickter Code wird denke ich dennoch funktionieren.

    Da ich selber mit VB.NET nicht arbeite, konnte ich den Code nicht testen.

    Die Funktion übrigens finde ich ein wenig komisch. Hier ist nicht ersichtlich, wie der Dateipfad für die XML Datei übernommen werden soll. Eine Art "return statement" fehlt in deiner Funktion.
     
    Last edited: Mar 8, 2011
  3. scullhead

    scullhead Byte

    Danke für die Rückmeldung, das ist aber nicht die Ursache. Die von mir gelistete Sub zum Anzeigen des OpenFileDialog zur Auswahl einer Datei funktioniert tadellos.
    Der Dateiname wird dann in der globalen Variable "wordlistfilename" gespeichert.

    Diese Sub steht auch in keinem direkten Zusammenhang mit der Verwendung des XMLTextWriter. Einzeln gesehen funktioniert beides.

    Sobald ich in der oben gelisteten Sub auch nur den Befehl
    Code:
    dialog_ok = .DLG_MGN_openFile.ShowDialog()
    ausführe (den Rest hatte ich zu Testzwecken auskommentiert) funktioniert der XMLTextWriter nicht mehr.
    Das ich habe auch das betroffene OpenFileDialog objekt aus dem Programm gelöscht und aus der Werkzeugleiste neu eingefügt .. kein Unterschied. Das gleiche passiert auch wenn ich einen andere OpenFileDialog im Programm aufrufe.

    Hier mal die Methode aus meiner selbst geschriebenen Klasse, welche das Speichern in die XML Datei übernimmt:
    Code:
        'Alle Settings in XML Datei schreiben
        Public Function saveToXML()
            Dim currSetting As setting
    
            If (XMLfileName <> "") Then
                'XML Writer Objekt erzeugen
                enc = New System.Text.UnicodeEncoding
                myXMLobj = New Xml.XmlTextWriter(XMLfileName, enc)
    
                Try
                    With myXMLobj
    
                        'Formatierung 4er Einzüge
                        .Formatting = Xml.Formatting.Indented
                        .Indentation = 4
    
                        'Anfang der Datei schreiben
                        .WriteStartDocument()
    
                        'Falls Kommentar gesetzt - in Datei schreiben
                        If (fileComment <> "") Then
                            .WriteComment(fileComment)
                        End If
    
                        'Hauptelement schreiben
                        .WriteStartElement(mainNodeName)
    
                        'alle Settings der Reihe nach in XML schreiben
                        For Each currSetting In settings
                            .WriteStartElement(elementName)
                            .WriteAttributeString("caption", currSetting.caption)
                            .WriteAttributeString("type", currSetting.type)
                            .WriteValue(currSetting.value)
                            .WriteEndElement()
                        Next
    
                        'Ende des Hauptelements
                        .WriteEndElement()
    
                        'XML Datei schließen
                        .Close()
                    End With
                    status = True
    
                Catch ex As Exception
                    'Im Fehlerfall Meldung ausgeben
                    statusmsg = "Fehler beim Speichern der Einstellungen: " & vbCrLf & ex.Message
                    status = False
                Finally
                    currSetting = Nothing
                    saveToXML = status
                    enc = Nothing
                    myXMLobj = Nothing
                End Try
    
            Else
                statusmsg = "Fehler beim Speichern der Einstellungen: " & vbCrLf & "kein Dateiname angegeben"
                saveToXML = status
            End If
        End Function
    
    Funktioniert wie gesagt einwandfrei ... bis man eben OpenFileDialog öffnet.
     
  4. salim_aliya

    salim_aliya Halbes Megabyte

    Nun fehlt mir jedoch der Zusammenhang zwischen den Code Abschnitt und der von Oben.

    Wie kommunizieren die Beiden Funktionen, dass ist nicht ganz ersichtlich.

    Vielleicht macht es Sinn, wenn du mal den kompletten Quellcode posten könntest.
     
  5. scullhead

    scullhead Byte

    Ok wenn es weiterhilft... hier mal der komplette Programmcode der XML Klasse:

    Code:
    Public Class XmlSettRW
        Public XMLfileName As String
        Public fileComment As String
        Public mainNodeName As String
        Public elementName As String
    
        Public statusmsg As String
        Public status As Boolean
    
        Private myXMLobj As Xml.XmlTextWriter
        Private XMLReader As Xml.XmlTextReader
        Private enc As System.Text.UnicodeEncoding
        Private xmlReadFlag As Boolean
    
        'Datentyp für Settings
        Private Structure setting
            Public caption As String
            Public type As String
            Public value As String
        End Structure
    
        'Arrays für Settings
        Private settings() As setting
        Private readsettings() As setting
    
        'Konstruktoraufrufe
        Public Sub New(ByVal filename As String)
            XMLfileName = filename
            fileComment = "undefined XML file"
            mainNodeName = "mainNode"
            elementName = "element"
            xmlReadFlag = False
            status = False
            statusmsg = ""
            ReDim settings(0)
            ReDim readsettings(0)
        End Sub
    
        ' Destruktor
        Protected Overrides Sub Finalize()
            XMLfileName = Nothing
            fileComment = Nothing
            mainNodeName = Nothing
            elementName = Nothing
            statusmsg = Nothing
            settings = Nothing
            readsettings = Nothing
        End Sub
    
        'Settings array leeren
        Public Function clearSettings()
            ReDim settings(0)
            Array.Clear(settings, 0, settings.Length)
            statusmsg = "Settings rückgesetzt"
            clearSettings = True
        End Function
        'Function, die Dateiname, Größe und Existenz der angegebenen XML Datei überprüft
        Public Function checkXML()
            Dim checkfile = False
            'Dateiname
            If XMLfileName = "" Then
                checkfile = False
                statusmsg = "Kein XML Dateiname angegeben"
            Else
                checkfile = True
            End If
            'Dateiexistenz
            If My.Computer.FileSystem.FileExists(XMLfileName) = False Then
                statusmsg = "Die angegebene Datei" & vbNewLine & Chr(34) & XMLfileName & Chr(34) & vbNewLine _
                                & "existiert nicht!"
                checkfile = False
            Else
                checkfile = True
    
                'Dateigröße ermitteln wenn Datei existiert
                If My.Computer.FileSystem.GetFileInfo(XMLfileName).Length = 0 Then
                    statusmsg = "Die angegebene Datei ist leer"
                    checkfile = False
                Else
                    checkfile = True
                End If
            End If
            checkXML = checkfile
        End Function
    
        'Setting hinzufügen
        Public Function addSetting(ByVal caption As String, ByVal value As Object, Optional ByVal type As String = "", Optional ByVal read As Boolean = False) As Boolean
            If caption <> "" Then
                If read = False Then
                    'Prüfen ob erstes Element leer ist 
                    If settings(0).caption = "" Then
                        settings(0).caption = caption
                        settings(0).value = value
                        'Datentyp bestimmen bzw. von Parameter übernehmen
                        If type <> "" Then
                            settings(0).type = type
                        Else
                            settings(0).type = TypeName(value)
                        End If
                    Else
                        'Array erweitern und Werte ablegen
                        ReDim Preserve settings((UBound(settings) + 1))
                        settings(UBound(settings)).caption = caption
                        settings(UBound(settings)).value = value.ToString
                        'Datentyp bestimmen bzw. von Parameter übernehmen
                        If type <> "" Then
                            settings(UBound(settings)).type = type
                        Else
                            settings(UBound(settings)).type = TypeName(value)
                        End If
                    End If
                Else
                    'Aus XML Datei Einlesen****************************************
                    'Prüfen ob erstes Element leer ist 
                    If readsettings(0).caption = "" Then
                        readsettings(0).caption = caption
                        readsettings(0).value = value
                        'Datentyp bestimmen bzw. von Parameter übernehmen
                        If type <> "" Then
                            readsettings(0).type = type
                        Else
                            readsettings(0).type = TypeName(value)
                        End If
                    Else
                        'Array erweitern und Werte ablegen
                        ReDim Preserve readsettings((UBound(readsettings) + 1))
                        readsettings(UBound(readsettings)).caption = caption
                        readsettings(UBound(readsettings)).value = value.ToString
                        'Datentyp bestimmen bzw. von Parameter übernehmen
                        If type <> "" Then
                            readsettings(UBound(readsettings)).type = type
                        Else
                            readsettings(UBound(readsettings)).type = TypeName(value)
                        End If
                    End If
                End If
                addSetting = True
                statusmsg = "Einstellung hinzugefügt"
            Else
                addSetting = False
                statusmsg = "Fehler beim Hinzufügen der Einstellung"
            End If
    
        End Function
    
        'Alle Settings in XML Datei schreiben
        Public Function saveToXML()
            Dim currSetting As setting
    
            If (XMLfileName <> "") Then
                'XML Writer Objekt erzeugen
                enc = New System.Text.UnicodeEncoding
                myXMLobj = New Xml.XmlTextWriter(XMLfileName, enc)
    
                Try
                    With myXMLobj
    
                        'Formatierung 4er Einzüge
                        .Formatting = Xml.Formatting.Indented
                        .Indentation = 4
    
                        'Anfang der Datei schreiben
                        .WriteStartDocument()
    
                        'Falls Kommentar gesetzt - in Datei schreiben
                        If (fileComment <> "") Then
                            .WriteComment(fileComment)
                        End If
    
                        'Hauptelement schreiben
                        .WriteStartElement(mainNodeName)
    
                        'alle Settings der Reihe nach in XML schreiben
                        For Each currSetting In settings
                            .WriteStartElement(elementName)
                            .WriteAttributeString("caption", currSetting.caption)
                            .WriteAttributeString("type", currSetting.type)
                            .WriteValue(currSetting.value)
                            .WriteEndElement()
                        Next
    
                        'Ende des Hauptelements
                        .WriteEndElement()
    
                        'XML Datei schließen
                        .Close()
                    End With
                    status = True
    
                Catch ex As Exception
                    'Im Fehlerfall Meldung ausgeben
                    statusmsg = "Fehler beim Speichern der Einstellungen: " & vbCrLf & ex.Message
                    status = False
                Finally
                    currSetting = Nothing
                    saveToXML = status
                    enc = Nothing
                    myXMLobj = Nothing
                End Try
    
            Else
                statusmsg = "Fehler beim Speichern der Einstellungen: " & vbCrLf & "kein Dateiname angegeben"
                saveToXML = status
            End If
        End Function
    
        'Settings aus XML Datei lesen - ACHTUNG: überschreibt zuvor Übergebene Settings!
        Public Function readFromXML()
            Dim currSetting As setting
            ReDim readsettings(0)
    
            If checkXML() Then
                XMLReader = New Xml.XmlTextReader(XMLfileName)
                With XMLReader
                    Try
                        While (.Read)
                            'Wenn Node ein Element ist dann zu den Attributen
                            If .NodeType = Xml.XmlNodeType.Element Then
                                If .Name = mainNodeName Then
    
                                    While (.Read())
                                        '.MoveToNextAttribute()
                                        .MoveToElement()
                                        'Wenn ein Eintrag gefunden wurde diesen einlesen
                                        If .Name = elementName Then
                                            currSetting.caption = .GetAttribute("caption")
                                            currSetting.type = .GetAttribute("type")
                                            currSetting.value = .ReadElementString
                                            addSetting(currSetting.caption, currSetting.value, currSetting.type, True)
                                        End If
                                    End While
                                End If
                            Else
                                .MoveToNextAttribute()
                            End If
                        End While
                        status = True
                        xmlReadFlag = True
                    Catch ex As Exception
                        statusmsg = "Fehler beim lesen der XML Datei: " & vbCrLf & ex.Message
                        status = False
                        xmlReadFlag = False
                    Finally
                        .Close()
                        readFromXML = status
                        XMLReader = Nothing
                    End Try
    
                End With
            Else
                readFromXML = status
                xmlReadFlag = False
            End If
        End Function
    
        'Setting abrufen (zuvor muss readfromXML ausgeführt werden)
        Public Function getSetting(ByVal caption As String)
            Dim currSetting As setting
            Dim status As Boolean = False
            Dim found As Boolean = False
            Dim ctr As Long = 0
            Dim retval 'nimmt den entsprechenden Datentyp an
            getSetting = Nothing
    
            If caption <> "" Then
                If xmlReadFlag = True Then
    
                    'Array durchlaufen und nach Bezeichner suchen   
                    Do
                        currSetting = readsettings(ctr)
                        If currSetting.caption = caption Then
                            found = True
                        Else
                            found = False
                        End If
                        ctr = ctr + 1
                    Loop Until (found = True Or (ctr > UBound(readsettings)))
    
                    If found = True Then
                        'Datentyp des Setting ermitteln und Wert konvertieren
                        Select Case currSetting.type.ToLower
                            Case "string"
                                retval = currSetting.value
                            Case "boolean"
                                retval = CBool(currSetting.value)
                            Case "integer"
                                retval = CInt(currSetting.value)
                            Case "double"
                                retval = CDbl(currSetting.value)
                                'Case "font"
                                '    retval = 
                            Case Else
                                'Wenn datentyp nicht zu ermitteln ist als String zurückgeben
                                retval = currSetting.value
                        End Select
                        'Wert ausgeben
                        status = True
                        statusmsg = "Setting gefunden"
                        getSetting = retval
                    Else
                        status = False
                        statusmsg = "Setting nicht gefunden"
                    End If
    
                Else
                    status = False
                    statusmsg = "XML Datei noch nicht eingelesen"
                End If
            Else
                status = False
                statusmsg = "keine Bezeichnung angegeben"
            End If
        End Function
    End Class
    
    
    Instanziert wird die Klasse dann über folgenden Aufruf:

    Code:
    Public ProgSettings As XmlSettRW
    
        'Aufrufe beim Programmstart***********************************************************************
        Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'Konfigurationsdatei initialisieren
            ProgSettings = New XmlSettRW("config.xml")
            ProgSettings.mainNodeName = "Settings"
            ProgSettings.elementName = "setting"
            ProgSettings.fileComment = "Programmeinstellungen fuer MailHelper - Datei nicht veraendern oder loeschen!"
          .
          .
          .
    
    
    Der Aufruf zum Speichern sieht dann so aus (gekürzt):

    Code:
    Public Sub savesettings()
            'Alte werte löschen bevor neue übergeben werden
            ProgSettings.clearSettings()
    
            With Form1
                'Ablageort für Mailvorlagen
                ProgSettings.addSetting("MGN_mailfolder", .TB_MG_template_path.Text)
    
                '... Die übrigen Einstellungen werden auf gleiche Weise hinzugefügt
                '    wurden zwecks Übersichtlichkeit entfernt
    
             
                ProgSettings.addSetting("MGN_insert_wordlistfile", MG_inserts.wordlistfilename)
             
               '...
               
               
            End With
            ProgSettings.saveToXML()
    
        End Sub
    
    Es besteht Zwischen den Programmteilen nur der "Zusammenhang", dass der Inhalt der Variable "Wordlistfile" auch mit in der XML gespeichert wird.
    Das gleiche Passiert wie gesagt auch wenn ich einen anderen OpenFileDialog im Programm aufrufe.

    Weiterhin habe ich die XML Klasse mal in ein komplett neu erstelltes Testprogrämmchen eingebunden und dort auch einen OpenFileDialog geöffnet - und dort funktioniert es ....

    Ich muss allerdings gestehen, dass das Komplette Programm mittlerweile über einen längern Zeitraum entstanden und gewachsen ist und teils nach Anleitungen teils nach dem "try and error Prinzip" entstanden ist.
    Beim Compilieren und währen der Laufzeit gibt es jedenfalls keine Fehlermeldungen oder exceptions.. Die sind mittlerweile alle ausgemerzt. Wenn man das Programm im Debug Modus Schritt für Schritt durchgeht sieht man auch wie alle Befehle in der XML Klasse korrekt durchgegangen werden. Nur dass eben nix in der XML Datei steht wenn zuvor einmal der OpenFileDialog aufgerufen wurde.
     
  6. salim_aliya

    salim_aliya Halbes Megabyte

    Dann würde es ja gar nichts bringen, wenn ich das Visual Studio Express herunterladen und dann dein Code testen würde.

    Eventuell ist das Problem komplett woanders in deinem Projekt zu suchen.

    Vielleicht liegt es ja nahe, dass du ein neues Projekt erstellst und dort deine einzelnen Quelltexte importierst?
     
  7. scullhead

    scullhead Byte

    Das ist es ja, - zwischen den Funktionen - also der Sub, die den OpenFileDialog benutzt und der XML Klasse gibt es in meinem Programm eben KEINEN funktionellen Zusammenhang.

    Das Speichern in die XML Datei hat wie gesagt nur in sofern mit der anderen Sub zu tun, weil der Dateiname der zurückgegeben wird u.A. auch in der XML landet. Das wird aus dem 2. Codebeispiel von mir ersichtlich.

    Das Spielt aber für das Verhalten keine Rolle, da in der Sub welche den Dateinamen in "Wordlistfilename" ablegt schon alles zu Testzwecken auskommentiert hatte. Das Verhalten tritt auf, wenn ich in meinem Programm irgent einen OpenFileDialog aufrufe. Egal an welcher stelle er steht.

    Den kompletten Quellcode des Programms möchte ich hier lieber nicht posten, da es ein Tool ist welches ich für meine Arbeit geschrieben habe. Nichts für ungut :-)

    Es könnte ja sein, dass Jemand das Verhalten kennt....

    Habe leider auch nicht sooo viel Zeit ständig daran zu arbeiten. Ich denke, dass ich den kompletten Programminhalt irgentwann mal in ein neu angelegtes VBS Projekt "stopfe".
     
  8. scullhead

    scullhead Byte

    Ich habe mir nun die Arbeit gemacht und den kompletten Programminhalt in ein neu angelegtes VB Projekt gepackt... jedoch tritt das Verhalten wider erwarten immernoch auf :aua:

    Nach nochmaligem Suchen im Netz bin ich auf folgenden Beitrag gestossen:
    http://www.daniweb.com/software-development/csharp/threads/325302

    Ich bin also offenbar nicht der einzige der ein solches Problem schon mal hatte. Allerdings hat man in diesem Forum auch noch keine Antwort gefunden.

    Langsam hab ich echt keine Ideen mehr..
     
Thread Status:
Not open for further replies.

Share This Page