Zum Inhalt springen

Benutzer:BK~dewikibooks/todo

Aus Wikibooks

Gambas: Form


Gambas: Dateiformate


Zurück zum Gambas-Inhaltsverzeichnis.

Im Kapitel Dateien haben wir gesehen, wie man unter Gambas einfach strukturierte Daten wie Texte in einer Datei speichert und wieder einließt. Im folgenden Kapitel wollen wir uns nun mit der Frage beschäftigen, wie man die etwas komplexeren Daten einer Tabelle mit variabler Zeilen und Spaltenzahl speichert und einließt. Um die Daten zu speichern, werden wir die beiden Standartdateiformate CSV und XML verwenden.

Vorarbeiten

[Bearbeiten]

Wir greifen an dieser Stelle unser Programm Wiki-Tabelle wieder auf und werden es im folgenden um die Funktionen zum Speichern und Laden der Daten ergänzen. Übernehmen Sie also – falls noch nicht geschehen – das Programm und ergänzen Sie es um zwei Buttons mit den Bezeichnungen btnSave und btnLoad. Denken Sie auch daran, die Funktion Form_Resize so zu erweitern, dass die beiden neuen Buttons mit angeordnet werden.

Wiki-Tabelle

CSV steht für Character Separated Values oder Comma Separated Values und ist ein verbreitetes Austauschfomat für einfache Tabellen, dass von vielen verschiedenen Programmen wie Microsoft Excel, OpenOffice Calc, KSpread, usw. importiert werden kann.

Da es keine allgemeine Definition gibt, welche Trennzeichen in einer CSV-Datei verwendet werden, legen wir für unser Programm die folgenden Trennzeichen fest:

  • Enthält eine Zelle einen Wert, wird er in doppelte Anführungszeichen eingeschlossen: "Zellwert"
  • Enthält der Zellwert selbst doppelte Anführungszeichen, so werden diese verdoppelt: Zelle "mit" Anführungszeichen wird zu "Zelle ""mit"" Anführungszeichen"
  • Die einzelnen Zellen einer Zeile werden durch ein Komma getrennt:
"Zellwert1","Zellwert2","Zellwert3","Zellwert4"
  • Die einzelnen Zeilen werden durch ein line feed "\n" getrennt:
"Zellwert11","Zellwert12","Zellwert13","Zellwert14"\n
"Zellwert21","Zellwert22","Zellwert23","Zellwert24"\n
"Zellwert31","Zellwert32","Zellwert33","Zellwert34"\n

Speichern

[Bearbeiten]
PUBLIC SUB btnSave_Click()
  DIM iRow AS Integer
  DIM iColumn AS Integer
  DIM sPath AS String
  DIM sFile AS String

  IF tbTableEdit.Visible = TRUE THEN TableEditSave

  Dialog.Path = System.Home
  Dialog.Title = "Datei speichern"
  Dialog.Filter = ["Wiki-Tabelle (*.csv)", "Alle Dateien (*.*)"]
  IF Dialog.SaveFile() THEN RETURN
  sPath = Dialog.Path
  IF Right$(sPath, 4) <> ".csv" THEN sPath = sPath & ".csv"

  INC Application.Busy

  FOR iRow = 0 TO $iRows - 1
    FOR iColumn = 0 TO $iColumns - 1
      IF $hTable[iRow][iColumn] <> "" THEN
        sFile = sFile & "\"" & Replace($hTable[iRow][iColumn],"\"","\"\"") & "\""
      ENDIF
      IF iColumn < $iColumns - 1 THEN sFile = sFile & ","
    NEXT
    sFile = sFile & "\n"
  NEXT
  File.Save(sPath, sFile)

FINALLY
  DEC Application.Busy

CATCH
  Message.Error("Datei konnte nicht gespeichert werden!", "OK")
  
END

Laden

[Bearbeiten]
FUNCTION CharCount(sString AS String, sChar AS String) AS Integer
  DIM iCount AS Integer
  DIM i AS Integer
  
  IF sString = "" OR sChar = "" THEN RETURN 0
  sChar = Left$(sChar, 1)
  
  iCount = 0
  FOR i = 1 TO Len(sString)
    IF Mid$(sString, i, 1) = sChar THEN INC iCount
  NEXT
  RETURN iCount
END
PUBLIC SUB btnLoad_Click()
  DIM iRow AS Integer
  DIM iColumn AS Integer
  DIM iPos AS Integer
  DIM sFile AS String
  DIM sLine AS String
  DIM sCell AS String

  IF tbTableEdit.Visible = TRUE THEN TableEditSave

  Dialog.Path = System.Home
  Dialog.Title = "Datei öffnen"
  Dialog.Filter = ["Wiki-Tabelle (*.csv)", "Alle Dateien (*.*)"]
  IF Dialog.OpenFile() THEN RETURN

  INC Application.Busy

  $iRows = 0
  $iColumns = 0
  TableMake
  
  sFile = File.Load(Dialog.Path)
  
  iRow = 0
  DO
    IF sFile = "" OR sFile = "\n" THEN BREAK
    
    iPos = 0
    DO
      iPos = Instr(sFile, "\n", iPos)
      IF CharCount(Left$(sFile, iPos), "\"") MOD 2 = 0 THEN BREAK
      INC iPos
    LOOP
    INC iRow
    $iRows = iRow
    TableMake
    sLine = If(Mid$(sFile, iPos, 1) = "\n", Left$(sFile, iPos - 1), Left$(sFile, iPos))
    sFile = Right$(sFile, iPos * -1)

    iColumn = 0
    DO
      IF sLine = "" AND iPos = 0 THEN BREAK
  
      iPos = 0
      DO
        iPos = Instr(sLine, ",", iPos)
        IF CharCount(Left$(sLine, iPos), "\"") MOD 2 = 0 THEN BREAK
        INC iPos
      LOOP
      INC iColumn
      IF iColumn > $iColumns THEN
        $iColumns = iColumn
        TableMake
      ENDIF
      IF iPos = 0 THEN
        sCell = sLine
      ELSE
        sCell = Left$(sLine, iPos - 1)
      ENDIF
      sLine = Right$(sLine, iPos * -1)
      
      IF sCell <> "" THEN
        IF Left$(sCell, 1) = "\"" AND Right$(sCell, 1) = "\"" THEN
          sCell = Replace$(Mid$(sCell, 2, Len(sCell) - 2), "\"\"", "\"")
        ELSE
          sCell = Replace$(sCell, "\"\"", "\"")
        ENDIF
      ENDIF
      $hTable[iRow - 1][iColumn - 1] = sCell
    LOOP
  LOOP
  tvTable.Refresh

FINALLY
  tvTable.SetFocus
  DEC Application.Busy

CATCH
  Message.Error("Datei konnte nicht geöffnet werden!", "OK")
  $iRows = 0
  $iColumns = 0
  TableMake
  $iRows = 5
  $iColumns = 3
  TableMake
  btnTBClear_Click
  
END

Speichern

[Bearbeiten]
PUBLIC SUB btnSave_Click()
  DIM Xml AS NEW XmlWriter
  DIM iColumn AS Integer
  DIM iRow AS Integer
  DIM sPath AS String

  IF tbTableEdit.Visible = TRUE THEN TableEditSave

  Dialog.Path = System.Home
  Dialog.Title = "Datei speichern"
  Dialog.Filter = ["Wiki-Tabelle (*.xml)", "Alle Dateien (*.*)"]
  IF Dialog.SaveFile() THEN RETURN
  sPath = Dialog.Path
  IF Right$(sPath, 4) <> ".xml" THEN sPath = sPath & ".xml"

  INC Application.Busy

  Xml.Open(sPath, TRUE, "UTF-8")
  Xml.StartElement("WikiTable", ["Name", File.BaseName(sPath)])
  Xml.Attribute("Rows", Str$($iRows))
  Xml.Attribute("Columns", Str$($iColumns))
  Xml.Attribute("FirstLine", Str$(If(cbFirstLine.Value, 1, 0)))
  Xml.Attribute("Short", Str$(If(cbShort.Value, 1, 0)))
  Xml.Attribute("Pretty", Str$(If(cbPretty.Value, 1, 0)))
  FOR iRow = 0 TO $iRows - 1
    Xml.StartElement("Row", ["ID", Str$(iRow)])
    FOR iColumn = 0 TO $iColumns - 1
      Xml.StartElement("Column", ["ID", Str$(iColumn)])
      Xml.Text($hTable[iRow][iColumn])
      Xml.EndElement()
    NEXT 
    Xml.EndElement()
  NEXT 
  Xml.EndElement()
  Xml.EndDocument()

FINALLY
  DEC Application.Busy

CATCH
  Message.Error("Datei konnte nicht gespeichert werden!", "OK")
  
END

Laden

[Bearbeiten]
PUBLIC SUB btnLoad_Click()
  DIM Xml AS NEW XmlReader
  DIM iRow AS Integer
  DIM iColumn AS Integer

  IF tbTableEdit.Visible = TRUE THEN TableEditSave

  Dialog.Path = System.Home
  Dialog.Title = "Datei öffnen"
  Dialog.Filter = ["Wiki-Tabelle (*.xml)", "Alle Dateien (*.*)"]
  IF Dialog.OpenFile() THEN RETURN

  INC Application.Busy

  $iRows = 0
  $iColumns = 0
  TableMake

  Xml.Open(Dialog.Path)
  DO UNTIL Xml.Eof

    SELECT CASE Xml.Node.Type
      CASE XmlReaderNodeType.Element
        SELECT Xml.Node.Name
          CASE "WikiTable"
            FOR EACH Xml.Node.Attributes
              SELECT Xml.Node.Name
                CASE "Rows"
                  $iRows = CInt(Xml.Node.Value)
                  TableMake
                CASE "Columns"
                  $iColumns = CInt(Xml.Node.Value)
                  TableMake
                CASE "FirstLine"
                  cbFirstLine.Value = If(Xml.Node.Value = "1", TRUE, FALSE)
                CASE "Short"
                  cbShort.Value = If(Xml.Node.Value = "1", TRUE, FALSE)
                CASE "Pretty"
                  cbPretty.Value = If(Xml.Node.Value = "1", TRUE, FALSE)
              END SELECT 
            NEXT
          
          CASE "Row"
            FOR EACH Xml.Node.Attributes
              IF Xml.Node.Name = "ID" THEN iRow = CInt(Xml.Node.Value)
            NEXT

          CASE "Column"
            FOR EACH Xml.Node.Attributes
              IF Xml.Node.Name = "ID" THEN iColumn = CInt(Xml.Node.Value)
            NEXT
        END SELECT 
          
      CASE XmlReaderNodeType.Text
        $hTable[iRow][iColumn] = Xml.Node.Value
        
    END SELECT

    Xml.Read()
  LOOP
  Xml.Close()

  tvTable.Refresh

FINALLY
  tvTable.SetFocus
  DEC Application.Busy

CATCH
  Message.Error("Datei konnte nicht geöffnet werden!", "OK")
  $iRows = 0
  $iColumns = 0
  TableMake
  $iRows = 5
  $iColumns = 3
  TableMake
  btnTBClear_Click
  
END