Hellihello Vinzenz,
Zweitens: Ja, Du hast wenig Einfluß auf die Speicherung und gerade die Abhängigkeit von den Ländereinstellungen kann gewaltig nerven.
Das ist mir einmal in einem Access-Projekt passiert, dort hatte ich Formulare dynamisch generiert und angepasst. Ich musste alles auf Twips umstellen, um nie, nie, nie in Zeichenketten mit Kommazahlen arbeiten zu müssen. War lehrreich.
Interessant ist, dass Excel durchaus korrekte CSV-Dateien erzeugt, diese allerdings selbst nicht richtig einlesen kann (getestet mit Excel 2007)
Genau das fiel mir auch auf. Immerhin unterscheidet sich die SaveAs Methode abhängig davon, ob sie aus dem Marko/VBA oder übers Menü aufgerufen wird (einmal mit Kommas, kann Excel nicht lesen auf anhieb, einmal mit Semikolon).
Ach ja, noch was: CSV-Dateien solltest Du in Excel _nicht_ über "Datei öffnen" oder das Kontextmenü der Datei öffnen. Nein, Du solltest in einer Arbeitsmappe über Daten -> Importieren gehen. Dann kannst Du einige Parameter festlegen.
Nun ja, Excel hat die Daten ja, ist ja die Datenbasis.
Mit Zeilenumbrüchen in Inhalten kommt Excel jedoch nicht klar.
Kann ich nicht bestätigen. Meins kann das hier lesen:
title1;titel2;titel3
"""A2""";";B2;";"C2¶&chr(11)&aaa Zelle_as_CSV = check_convert_and_wrap(Zelleninhalt)
Debug.Print (Spaltennummer & ""-"")
Debug.Print Zelle_as_CSV"
A3;B3;C3
Mein CSV-ersteller (erstmal ohne Abspeichern und Aufruf einer Batchdatei zum Hochladen auf einen Server) sieht momentan so aus:
'Variablendeklaration verplichtend durch
Option Explicit
' Indiziere Arrays von 1 an, matched zum Zähler da unten ab 1
Option Base 1
'Globale Vars deklarieren (s.a. Funktion Wrapper)
'die Zuweisung durch chr() geht scheints nur im Sub
'eigentlich wäre das eine Const, aber das klappt durch die chr()-Zuweisung nicht
Dim Semikolon, CRLF, Anführungszeichen As String
Sub my_csv()
CRLF = Chr(13) & Chr(10)
Anführungszeichen = Chr(34)
Semikolon = Chr(59)
'Declaration
Dim UrsprungsZeile, UrsprungsSpalte As Object
Dim Zeilenanzahl, Spaltenanzahl, Zeilennummer, Spaltennummer As Integer
'Arrays
Dim Zeilen() As String
Dim Spalten() As String
Dim Zelleninhalt, Zelle_as_CSV, Zeile_as_CSV, Tabelle_as_CSV As String
'Rows- and Columns.Count for Use in Redimension of Arrays below
Zeilenanzahl = ActiveSheet.UsedRange.Rows.Count
Spaltenanzahl = ActiveSheet.UsedRange.Columns.Count
'Redimension des Arrays
ReDim Zeilen(Zeilenanzahl) As String
ReDim Spalten(Spaltenanzahl) As String
'initialize Ausgabestring
Tabelle_as_CSV = ""
'so, nun geh mal durch die Zeilen
For Zeilennummer = 1 To Zeilenanzahl Step 1
'Zeile als String initialiiseren
Zeile_as_CSV = ""
'so, nun geh mal durch die Spalten in der Zeile
For Spaltennummer = 1 To Spaltenanzahl Step 1
'hohl dir den Inhalt der Zelle, als *.value, weil mind. eine Zelle mehr als 1024 Zeichen haben kann
Zelleninhalt = ActiveSheet.UsedRange.Rows(Zeilennummer).Cells(Spaltennummer).Value
'lass den Wrapper ran
Zelle_as_CSV = check_convert_and_wrap(Zelleninhalt)
'stopf es ins Spaltenarray
Spalten(Spaltennummer) = Zelle_as_CSV
Next
'Spaltenarray in String mit Semikolon als Seperator zerlegen und ins Zeilenarray stopfen
Zeilen(Zeilennummer) = Join(Spalten, Semikolon)
'sollte hier das Spaltenarray geleert werden und wenn ja wie?
Next
'Zeilenarray in String mit CRLF als Seperator zerlegen - thats it
Tabelle_as_CSV = Join(Zeilen, CRLF)
Debug.Print Tabelle_as_CSV
End Sub
Function check_convert_and_wrap(Zelleninhalt)
'Soll ich nun wrappen?
Dim wrap As Boolean
wrap = False
'checked, ob Anführungszeichen im Zelleninhalt
If InStr(Zelleninhalt, Anführungszeichen) > 0 Then
'dann bitte 1. wrappen
wrap = True
'2. die Anführungszeichen im Zelleninhalt jeweils verdoppeln
Zelleninhalt = Replace(Zelleninhalt, Anführungszeichen, Anführungszeichen & Anführungszeichen)
'wenn keine Anführungszeichen, dann schauen, ob Semikolon oder Absatzmarke (CR&LF)
ElseIf (InStr(Zelleninhalt, Semikolon) > 0 Or InStr(Zelleninhalt, CRLF) > 0) Then
'wenn ja, dann wrappen
wrap = True
Debug.Print (Zelleninhalt & "aaaaaa")
End If
'wenn wrappen
If wrap Then
'dann setz die Rückgabe in Anführungszeichen
check_convert_and_wrap = Anführungszeichen & Zelleninhalt & Anführungszeichen
Else
'ansonsten bleibt alles, wies ist und wird dennoch zurückgegeben
check_convert_and_wrap = Zelleninhalt
End If
End Function
Ich hab das ganze ja jetzt so angepackt deinem Rat folgend, ein Standardformat lieber für Character-Delimited-Values zu nehmen, wobei ich nach wie vor mit den o.g. Problemen und der Frage YAGNI überlege, ob String-Delimited-Values nicht doch auch eine (proprietäre) Alternative wären.
Zudem möchte ich eigentlich im Folgeschritt vergleichen, welche Zeilen sich geändert haben. Mit PHP würde ich also jedes Zeilenarray eigentlich wieder Zerlegen mittels implode() und den String dann vergleichen mit der bisherigen Zeile. Sind sie gleich, ist kein update nötig. Das würde bei String-Demlimited-Values ein implode() sparen (;-).
Abgesehen würde ich das ganze gern portieren auf OpenOffice. StarBasic aber scheint etwas anders zu sein. So finde ich kein Debug.Print sondern nur Print und das öffnet immer eine kleine OK-Box. Auch fehlt mir der Bezeichner für "ActiveSheet" und "UsedRange" zB. Schön finde ich aber, dass hier auch Javascript oder Python nutzbar wäre. Hast Du damit Erfahrung? Vielleicht mach ich mal einen neuen Thread dazu, hier in den verschachtelten Tiefen scheints mir, sind wir beide grad allein.
Zu guter letzt sinniere ich auch über das Konzept, das auf den Server hochzuladen. Mit einem "ftp -s:ftp-script" hab ich schon einen Ansatz. Aber dann weiß der Server ja immer noch nicht, dass er die neue Datenbasis vergleichen und einarbeiten solle.
Rufe ich ein *.htm-Dokument auf, dann muss der User selbst die Datei zum Hochladen bestimmen, was lästig wäre. Nähme ich ein *.hta, könnte ich die Lösung nicht 1:1 auf Linux übertragen. Auch in neuem Thread vielleicht.
DankDank und GrußGruß,
frankx