vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Zippen wie die Profis!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: HTML/Internet/Netzwerk · HTML/Email   |   VB-Versionen: VB.NET21.06.04
VB .NET-Code in HTML darstellen

Wandelt VB.NET-Code nach HTML um und ermöglicht somit das farbige Darstellen von VB .NET-Code in HTML-Seiten.

Autor:   SnofBewertung:     [ Jetzt bewerten ]Views:  20.313 
ohne HomepageSystem:  Win9x, WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11 Beispielprojekt auf CD 

Wenn man seinen Code im Internet präsentieren möchte, hat man immer das Problem, dass der Code farblos ist. Größeren Code "per Hand" umzuwandeln ist viel zu aufwendig. Mit dieser Klasse ist es möglich bequem seinen Code in HTML-Code zu konvertieren.

Die Umwandlung selbst basiert auf einem rekursiven Algorithmus. Dabei wird der Code zuerst bei Zeilenumbrüchen aufgesplittet und Zeile für Zeile konvertiert. Jede einzelne Zeile wird solange aufgeteilt, bis weder Komentare noch Text in Anführungszeichen vorhanden sind. Als nächstes werden die Schlüsselwörte rausgesucht. Wurde eins gefunden, werden die Zeichen vor und hinter den Schlüsselwort überprüft. Sind diese korrekt, wird vor und nach dem Schlüsselwort der entsprechende HTML-Tag eingefügt.

Die Schlüsselwörter (in der MSDN aufgelistet) lädt das Programm aus einer XML-Datei, die in einen Stream geladen wird. Hierzu dient die GetStream-Funktion. Sie sollte an das Programm angepast werden, da es mehrere Möglichkeiten gibt, die Daten zu speichern.

Die HTML-Tags, welche vor und nach Schlüsselwörtern bzw. Kommentaren stehen können durch die CommentTags bzw. KeywordTags Eigenschaft angegeben werden. Dabei handelt es sich um ein String-Array mit zwei Elementen, dem öffnenden (Index: 0) und den schließenden (Index: 1) Tag. Sollte die Länge nicht zwei betragen wird eine Ausnahme ausgelöst.

Vier Dinge noch:

  1. Prinzipiell lässt sich der Algorithmus auch auf andere Sprachen übertragen, z.B. PHP (für die Darstellung von Code im VB.NET Forum).
  2. Der Code wurde mit dem .NET Framework 1.0 (VB .NET 2002) entwickelt.
  3. Der REM-Befehl für Kommentare wird nicht beachtet.
  4. Fehlerhafte Code wird natürlich auch fehlerhaft konvertiert.

Erstellen der XML-Datei mit den Keywords
Öffnen Sie den Windows-Editor und fügen nachfolgenden Text ein. Speichern Sie die Datei unter dem Namen keywords.xml in das VB.NET Projektverzeichnis.

<?xml version="1.0" encoding="utf-8" ?>
<MainTag>
  <Keywords>
    <Keyword>AddHandler</Keyword>
    <Keyword>AddressOf</Keyword>
    <Keyword>Alias</Keyword>
    <Keyword>And</Keyword>
    <Keyword>AndAlso</Keyword>
    <Keyword>Ansi</Keyword>
    <Keyword>As</Keyword>
    <Keyword>Assembly</Keyword>
    <Keyword>Auto</Keyword>
    <Keyword>Boolean</Keyword>
    <Keyword>ByRef</Keyword>
    <Keyword>Byte</Keyword>
    <Keyword>ByVal</Keyword>
    <Keyword>Call</Keyword>
    <Keyword>Case</Keyword>
    <Keyword>Catch</Keyword>
    <Keyword>CBool</Keyword>
    <Keyword>CByte</Keyword>
    <Keyword>CChar</Keyword>
    <Keyword>CDate</Keyword>
    <Keyword>CDec</Keyword>
    <Keyword>CDbl</Keyword>
    <Keyword>Char</Keyword>
    <Keyword>CInt</Keyword>
    <Keyword>Class</Keyword>
    <Keyword>CLong</Keyword>
    <Keyword>CObj</Keyword>
    <Keyword>Compare</Keyword>
    <Keyword>Const</Keyword>
    <Keyword>CShort</Keyword>
    <Keyword>CSng</Keyword>
    <Keyword>CStr</Keyword>
    <Keyword>CType</Keyword>
    <Keyword>Date</Keyword>
    <Keyword>Decimal</Keyword>
    <Keyword>Declare</Keyword>
    <Keyword>Default</Keyword>
    <Keyword>Delegate</Keyword>
    <Keyword>Dim</Keyword>
    <Keyword>DirectCast</Keyword>
    <Keyword>Do</Keyword>
    <Keyword>Double</Keyword>
    <Keyword>Each</Keyword>
    <Keyword>Else</Keyword>
    <Keyword>ElseIf</Keyword>
    <Keyword>End</Keyword>
    <Keyword>Enum</Keyword>
    <Keyword>Erase</Keyword>
    <Keyword>Error</Keyword>
    <Keyword>Event</Keyword>
    <Keyword>Exit</Keyword>
    <Keyword>Explicit</Keyword>
    <Keyword>ExternalSource</Keyword>
    <Keyword>False</Keyword>
    <Keyword>Finally</Keyword>
    <Keyword>For</Keyword>
    <Keyword>Friend</Keyword>
    <Keyword>Function</Keyword>
    <Keyword>Get</Keyword>
    <Keyword>GetType</Keyword>
    <Keyword>GoTo</Keyword>
    <Keyword>Handles</Keyword>
    <Keyword>If</Keyword>
    <Keyword>Implements</Keyword>
    <Keyword>Imports</Keyword>
    <Keyword>In</Keyword>
    <Keyword>Inherits</Keyword>
    <Keyword>Integer</Keyword>
    <Keyword>Interface</Keyword>
    <Keyword>Is</Keyword>
    <Keyword>Let</Keyword>
    <Keyword>Lib</Keyword>
    <Keyword>Like</Keyword>
    <Keyword>Long</Keyword>
    <Keyword>Loop</Keyword>
    <Keyword>Me</Keyword>
    <Keyword>Mod</Keyword>
    <Keyword>Module</Keyword>
    <Keyword>MustInherit</Keyword>
    <Keyword>MustOverride</Keyword>
    <Keyword>MyBase</Keyword>
    <Keyword>MyClass</Keyword>
    <Keyword>Namespace</Keyword>
    <Keyword>New</Keyword>
    <Keyword>Next</Keyword>
    <Keyword>Not</Keyword>
    <Keyword>Nothing</Keyword>
    <Keyword>NotInheritable</Keyword>
    <Keyword>NotOverridable</Keyword>
    <Keyword>Object</Keyword>
    <Keyword>On</Keyword>
    <Keyword>Option</Keyword>
    <Keyword>Optional</Keyword>
    <Keyword>Or</Keyword>
    <Keyword>OrElse</Keyword>
    <Keyword>Overloads</Keyword>
    <Keyword>Overridable</Keyword>
    <Keyword>Overrides</Keyword>
    <Keyword>ParamArray</Keyword>
    <Keyword>Preserve</Keyword>
    <Keyword>Private</Keyword>
    <Keyword>Property</Keyword>
    <Keyword>Protected</Keyword>
    <Keyword>Public</Keyword>
    <Keyword>RaiseEvent</Keyword>
    <Keyword>ReadOnly</Keyword>
    <Keyword>ReDim</Keyword>
    <Keyword>Region</Keyword>
    <Keyword>RemoveHandler</Keyword>
    <Keyword>Resume</Keyword>
    <Keyword>Return</Keyword>
    <Keyword>Select</Keyword>
    <Keyword>Set</Keyword>
    <Keyword>Shadows</Keyword>
    <Keyword>Shared</Keyword>
    <Keyword>Short</Keyword>
    <Keyword>Single</Keyword>
    <Keyword>Static</Keyword>
    <Keyword>Step</Keyword>
    <Keyword>Stop</Keyword>
    <Keyword>Strict</Keyword>
    <Keyword>String</Keyword>
    <Keyword>Structure</Keyword>
    <Keyword>Sub</Keyword>
    <Keyword>SyncLock</Keyword>
    <Keyword>Then</Keyword>
    <Keyword>Throw</Keyword>
    <Keyword>To</Keyword>
    <Keyword>True</Keyword>
    <Keyword>Try</Keyword>
    <Keyword>TypeOf</Keyword>
    <Keyword>Unicode</Keyword>
    <Keyword>Until</Keyword>
    <Keyword>Variant</Keyword>
    <Keyword>When</Keyword>
    <Keyword>While</Keyword>
    <Keyword>With</Keyword>
    <Keyword>WithEvents</Keyword>
    <Keyword>WriteOnly</Keyword>
  </Keywords>
  <Chars>
    <CharBefor><NewLine></CharBefor>
    <CharBefor><Space></CharBefor>
    <CharBefor>&gt;</CharBefor>
    <CharBefor>&lt;</CharBefor>
    <CharBefor>#</CharBefor>
    <CharBefor>(</CharBefor>
    <CharBefor>)</CharBefor>
    <CharBefor>,</CharBefor>
    <CharAfter>(</CharAfter>
    <CharAfter>)</CharAfter>
    <CharAfter>,</CharAfter>
    <CharAfter>.</CharAfter>
    <CharAfter>:</CharAfter>
    <CharAfter><NewLine></CharAfter>
    <CharAfter><Space></CharAfter>
  </Chars>
</MainTag>

Die CodeConvert-Klasse
Fügen Sie Ihrem VB.NET Projekt ein neues Klassenmodul mit folgendem Code hinzu:

Imports System
Imports System.Collections
Imports System.Environment
Imports System.IO
Imports System.Reflection
Imports System.Text
Imports System.Xml
 
' Wandelt Visual Basic .NET Code in HTML-Code um.
Public Class CodeConverter
#Region " Deklaration "
 
  ' Konstante für einen Leerstring.
  Private Const NullString As String = ""
 
  ' Anführungszeichen.
  Private Const QuotationMark As String = """"
 
  ' Der orginal Quellcode.
  Private sbOrginalCode As StringBuilder
 
  ' Die HTML-Befehle für Kommentare
  Private strCommentTags As String()
 
  ' Die HTML-Befehler für Schlüsselwörter.
  Private strKeywordTags As String()
 
  ' Die Liste der Schlüsselwörter
  Private strKeywords As String()
 
  ' Die Zeichen, oder Strings, die vor einem Wort sein dürfen, 
  ' damit es als Schlüsselwort erkannt wird.
  Private strCharsBefor As String()
 
  ' Die Zeichen, oder Strings, die nach einem Wort sein dürfen, 
  ' damit es als Schlüsselwort erkannt wird.
  Private strCharsAfter As String()
 
#End Region
#Region " New-Funktionen "
 
  ' Initialisiert die Klasse.
  Public Sub New()
 
    ' Lädt die Schlüsselwörter.
    LoadKeywords()
 
    ' Setzt leere Strings für die Tags ein.
    Me.CommentTags = New String() {NullString, NullString}
    Me.KeywordTags = New String() {NullString, NullString}
 
  End Sub
 
  ' Initialisiert die Klasse
  Public Sub New(ByVal Path As String)
    Me.New()
 
    ' Ließt die Code-Datei.
    Dim SR As New StreamReader(Path, Encoding.Default)
    sbOrginalCode = New StringBuilder(SR.ReadToEnd)
    SR.Close()
 
  End Sub
 
#End Region
#Region " Eigenschaften "
 
  ' Der Orginal Quellcode
  Public Property OrginalCode() As String
    Get
      Return sbOrginalCode.ToString
    End Get
    Set(ByVal Value As String)
      sbOrginalCode = New StringBuilder(Value)
    End Set
  End Property
 
  ' Der HTML-Code
  Public ReadOnly Property HTMLCode() As String
    Get
      Return ConvertCode.ToString
    End Get
  End Property
 
  ' Die HTML-Befehle für Kommentare
  Public Property CommentTags() As String()
    Get
      Return strCommentTags
    End Get
    Set(ByVal Value As String())
      If Value.Length <> 2 Then
        ' Fehler auslösen.
        Throw New WrongNumberOfTagsException()
        Exit Property
      End If
 
      strCommentTags = Value
    End Set
  End Property
 
  ' Die HTML-Befehler für Schlüsselwörter.
  Public Property KeywordTags() As String()
    Get
      Return strKeywordTags
    End Get
    Set(ByVal Value As String())
      If Value.Length <> 2 Then
        ' Fehler auslösen.
        Throw New WrongNumberOfTagsException()
        Exit Property
      End If
 
      strKeywordTags = Value
    End Set
  End Property
 
#End Region
  ' Lädt die Schlüsselwörter.
  Private Sub LoadKeywords()
    Dim xmlDoc As New XmlDocument()
    Dim Node As XmlNode
 
    Dim Keywords As New ArrayList()
 
    xmlDoc.Load(GetStream("Keywords.xml"))
 
    ' Schlüsselwörter auslesen
    With xmlDoc.SelectSingleNode("descendant::Keywords")
      For Each Node In .SelectNodes("descendant::Keyword")
        Keywords.Add(Node.InnerText)
      Next
    End With
 
    ' "Speichert" die Schlüsselwörter.
    Keywords.Sort()
    strKeywords = Keywords.ToArray(GetType(String))
 
    ' Löscht die Liste
    Keywords.Clear()
 
    ' Zeichen vor einem Schlüssselwort
    With xmlDoc.SelectSingleNode("descendant::Chars")
      For Each Node In .SelectNodes("descendant::CharBefor")
        Dim Chr As String = Node.InnerText
        If Chr = "<NewLine>" Then
          Chr = NewLine
        ElseIf Chr = "<Space>" Then
          Chr = " "
        End If
        Keywords.Add(Chr)
      Next 
    End With
 
    ' "Speichert" die Schlüsselwörter.
    Keywords.Sort()
    strCharsBefor = Keywords.ToArray(GetType(String))
 
    ' Löscht die Liste
    Keywords.Clear()
 
    ' Zeichen nach einem Schlüssselwort auslesen
    With xmlDoc.SelectSingleNode("descendant::Chars")
      For Each Node In .SelectNodes("descendant::CharAfter")
        Dim Chr As String = Node.InnerText
        If Chr = "<NewLine>" Then
          Chr = NewLine
        ElseIf Chr = "<Space>" Then
          Chr = " "
        End If
        Keywords.Add(Chr)
      Next
    End With
 
    ' "Speichert" die Schlüsselwörter.
    Keywords.Sort()
    strCharsAfter = Keywords.ToArray(GetType(String))
 
  End Sub
  ' Lädt die XML-Datei mit den Schlüsselwörtern in einen Stream.
  Private Function GetStream(ByVal Name As String) As Stream
    ' Diese Funktion muss an das Programm angepasst werden.
    ' Möglich sind u.a. ...
 
    ' ... das laden aus den Ressourcen:
    ' ----------------------------------
    ' 
    ' Dim A As [Assembly] = [Assembly].GetExecutingAssembly
    ' Return A.GetManifestResourceStream(Name)
 
 
    ' ... das laden aus einer Datei:
    ' -------------------------------
    ' 
    Dim FS As New FileStream(Application.StartupPath & _
      "keywords.xml", FileMode.Open)
    Return FS
 
  End Function
  ' Konvertiert den Code in HTML-Code.
  Private Function ConvertCode() As StringBuilder
    ' Überprüft, ob Code übergen wurde.
    If sbOrginalCode.Length = 0 Then
      Return New StringBuilder(NullString)
    End If
 
    Dim Line As String
    Dim Lines As String()
 
    Dim sbHTMLCode As New StringBuilder(OrginalCode)
 
    ' Ersetzt Zeichen, die mit dem HTML-Code in Konflikt kommen können.
    sbHTMLCode.Replace("&", "&")
    sbHTMLCode.Replace("<", "<")
    sbHTMLCode.Replace(">", ">")
 
    Lines = sbHTMLCode.ToString.Split(NewLine)
 
    sbHTMLCode = New StringBuilder()
 
    For Each Line In Lines
      If Line.Substring(0, 1) = NewLine.Substring(1, 1) Then
        sbHTMLCode.Append(ConvertLine(Line.Substring(1)) & "<br>" & NewLine)
      Else
        sbHTMLCode.Append(ConvertLine(Line) & "<br>" & NewLine)
      End If
    Next
 
    sbHTMLCode.Replace("  ", "  ")
    sbHTMLCode.Replace("  ", "  ")
    sbHTMLCode.Replace("  ", "  ")
 
    Return sbHTMLCode
 
  End Function
  ' Konvertiert eine Zeile
  Private Function ConvertLine(ByVal Line As String) As String
    Dim L As New StringBuilder()
    Dim Ls As String()
 
    Dim REMPosition As Integer
    Dim StrPosition As Integer
 
    REMPosition = Line.IndexOf("'")
    StrPosition = Line.IndexOf(QuotationMark)
 
 
    ' Sowohl Anführungszeichen als auch Komentare in der Zeile.
    If (StrPosition <> -1) AndAlso (REMPosition <> -1) Then
      Dim i As Integer
 
      ' Der Komentar beginnt vor den Anführungszeichen
      If REMPosition < StrPosition Then
 
        L.Append(Line)
        L.Replace("'", strCommentTags(0) & "'", REMPosition, 1)
        L.Append(strCommentTags(1))
 
        Return L.ToString
 
      Else
        Dim Length As Integer
 
        Ls = Line.Split(QuotationMark)
 
        For i = 0 To Ls.Length - 1 Step 2
 
          Dim RP As Integer = Ls(i).IndexOf("'")
 
          ' Komentar beginnt in diesem Abschnitt
          If RP >= 0 Then
 
            ' Fügt konvertierten Code bis zum Komentar hinzu
            L.Append(ConvertLine(Ls(i).Substring(0, RP)))
 
            ' Fügt Kommentar-Tag ein.
            L.Append(strCommentTags(0))
 
            ' Fügt Rest des Abschnittes hinzu.
            L.Append(Ls(i).Substring(RP))
 
            Dim j As Integer
 
            ' Fügt die restlichen Abschnitte der Zeile hinzu.
            For j = i + 1 To Ls.Length - 1
              L.Append(QuotationMark & Ls(j))
            Next
 
            ' Fügt den Tab zum Beenden des Komentars hinzu
            L.Append(strCommentTags(1))
          Else
            ' Fügt den Convertierten Abschnitt hinzu.
            L.Append(ConvertLine(Ls(i)))
 
            ' Fügt den String hinzu
            If i + 1 < Ls.Length Then
              L.Append(QuotationMark & Ls(i + 1))
            End If
 
          End If
 
          L.Append(QuotationMark)
 
        Next
 
        Return L.ToString(0, L.Length - QuotationMark.Length)
 
      End If
    End If
 
    ' Nur Anführungszeichen enthalten
    If (StrPosition <> -1) AndAlso (REMPosition = -1) Then
      Dim i As Integer
 
      Ls = Line.Split(QuotationMark)
 
 
      For i = 0 To Ls.Length - 1 Step 2
        L.Append(ConvertLine(Ls(i)))
 
        ' Fügt den String hinzu.
        If i + 1 < Ls.Length Then
          L.Append(QuotationMark & Ls(i + 1))
        End If
 
        L.Append(QuotationMark)
      Next
 
      Return L.ToString(0, L.Length - QuotationMark.Length)
    End If
 
    ' Keine Strings, nur ein Komentar enthalten.
    If (StrPosition = -1) AndAlso (REMPosition <> -1) Then
      ' Fügt konvertierten Code bis zum Komentar hinzu
      L.Append(ConvertLine(Line.Substring(0, REMPosition)))
 
      ' Fügt Kommentar-Tag ein.
      L.Append(strCommentTags(0))
 
      ' Fügt Rest des Abschnittes hinzu.
      L.Append(Line.Substring(REMPosition))
 
      ' Schließt den Kommentar-Tag.
      L.Append(strCommentTags(1))
 
      Return L.ToString
    End If
 
    ' Weder Strings noch Komentare
    If (StrPosition = -1) AndAlso (REMPosition = -1) Then
      Dim KW As String
      Dim KeywordIndex As Integer
 
      L.Append(Line)
 
      For Each KW In strKeywords
        KeywordIndex = -1
        Do
          KeywordIndex = L.ToString.IndexOf(KW, KeywordIndex + 1)
 
          ' Wenn kein Schlüsselwort vorhanden: Schleife verlassen
          If KeywordIndex = -1 Then
            Exit Do
          End If
 
          Dim Chr As String
          Dim ChrB, ChrA As Boolean
 
          ChrB = False
          ChrA = False
 
          ' Überprüft, ob das Zeichen davor übereinstimmt.
          For Each Chr In strCharsBefor
            If KeywordIndex - Chr.Length < 0 Then
              ChrB = ChrB OrElse (KeywordIndex = 0)
            Else
              ChrB = ChrB OrElse (L.ToString.Substring(KeywordIndex - _
                Chr.Length, Chr.Length) = Chr)
            End If
          Next
 
          ' Überprüft, ob das Zeichen danach übereinstimmt.
          For Each Chr In strCharsAfter
            If KeywordIndex + KW.Length + Chr.Length > L.Length Then
              ChrA = ChrA Or (KeywordIndex + KW.Length = L.Length)
            Else
              ChrA = ChrA Or (L.ToString.Substring(KeywordIndex + KW.Length, _
                Chr.Length) = Chr)
            End If
          Next
 
          ' Wenn beide Zeichen über einstimmen.
          If ChrB And ChrA Then
            L.Replace(KW, strKeywordTags(0) & KW & strKeywordTags(1), _
              KeywordIndex, KW.Length)
            KeywordIndex += strKeywordTags(0).Length + strKeywordTags(1).Length
          End If
 
        Loop
 
      Next
 
      Return L.ToString
    End If
 
  End Function
 
End Class
' Wird ausgelößt, wenn die Anzahl der übergebenen Tags nicht stimmt.
Public Class WrongNumberOfTagsException
  Inherits Exception
 
  Public Sub New()
    MyBase.New("Die Anzahl der Tags muss 2 sein.")
  End Sub
 
  Public Sub New(ByVal Message As String)
    MyBase.New(Message)
  End Sub
 
End Class

Beispiel für den Einsatz der neuen CodeConverter-Klasse
Platzieren Sie auf die Form ein TextBox-Control mit der Eigenschaft MultiLine = True, sowie einen CommandButton. Beim Klick auf den CommandButton soll der VB.NET Code aus der TextBox in das HTML-Format konvertiert werden, temporär abgespeichert und im Standard-Browser angezeigt werden.

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
  Dim oConvert As New CodeConverter
 
  With oConvert
    ' VB.NET Code
    .OrginalCode = TextBox1.Text
 
    ' HTML-Tags für Kommentare
    .CommentTags = Split("<font color=green>;</font>", ";")
 
    ' HTML-Tag für Schlüsselwörter
    .KeywordTags = Split("<font color=blue>;</font>", ";")
  End With
 
  ' HTML-Code erzeugen...
  Dim sHTML As String = oConvert.HTMLCode
 
  ' ... temporär abspeichern...
  Dim oStream As New IO.StreamWriter(Application.StartupPath & "\vbcode.htm")
  oStream.Write(sHTML)
  oStream.Close()
 
  ' ... und im Standard-Browser anzeigen
  System.Diagnostics.Process.Start(Application.StartupPath & "\vbcode.htm")
End Sub