Benutzer:BK~dewikibooks/todo
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.

CSV
[Bearbeiten]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
XML
[Bearbeiten]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