52028
Goto Top

Batch-Datei um Excel-Datei in Text-Datei zu wandeln

Hallo zusammen,

nach nun 3-stündiger Suche und vergeblichen Bemühungen trage ich mein Problem mal in die Öffentlichkeit.

Die Problemstellung sieht wie folgt aus. Ich habe eine Excel-Datei mit >30 Spalten und mehreren 1000 Einträgen. (Auch mehrere Tabellenblätter, die interessieren aber nicht!). Ich möchte nun gern die ersten 7 Spalten der Datei in ein pipe-getrenntes Text-File speichern.

Das ganze soll automatisch ablaufen, daher die Idee als Batch-Skript. (Falls es eine elegantere, bzw. weniger aufwändigere Lösung gibt, könnt ihr mir die auch gerne verraten!) ;)

Ich bin bereits darauf gestoßen, dass es schwierig wird das Excel-File direkt zu verarbeiten und habe auch schon den Weg über eine *.CVS-Datei gefunden. Damit wäre der erste Ansatzpunkt ja, das Excel-Sheet automatisch in eine Simikolon-getrennte *.CSV-Datei zu wandeln.

Danach möchte ich dann die CSV-Datei per batch-Verarbeitung in eine Textdatei wandeln. Mein Ansatz hierzu sieht in etwa so aus:

FOR /F "tokens=1-7 delims=;" %%a IN (meineCSV.csv) DO echo %%a >> meineTXT.txt  

Das Problem an dieser Stelle ist, dass
  • das Simikolon-Trennzeichen der CSV übernommen wird (Ich brauche eine Pipe)
  • nur die erste Spalte in die Textdatei geschrieben wird

Ich hoffe ich konnte mein Problem erläutern und das ihr mich auf den richtigen Weg bringt! face-smile

Content-Key: 66208

Url: https://administrator.de/contentid/66208

Printed on: April 19, 2024 at 03:04 o'clock

Member: Biber
Biber Aug 14, 2007 at 19:10:49 (UTC)
Goto Top
Moin MarcoS,

>
[code]
FOR /F "tokens=1-7 delims=;" %%a IN (meineCSV.csv) DO echo %%a >> meineTXT.txt
[/code]

Das Problem an dieser Stelle ist, dass
1. Das Simikolon-Trennzeichen der CSV übernommen wird (Ich brauche eine Pipe)
2. Nur die erste Spalte in die Textdatei geschrieben wird


"Problem" ist ein großes Wort...
In der FOR/F-Anweisung willst Du ja die ersten 7 Spalten "erhalten" (tokens 1-7).
Dann musst Du entsprechend auch die dynamischen Variablen %%a...%%g weiterreichen.
Das Trennzeichen "|" musst Du mit einem Caret ("^") maskieren, da es unter Batch eine Steuerzeichen-Bedeutung hat.

FOR /F "tokens=1-7 delims=;" %%a IN (meineCSV.csv) DO echo %%a^|%%b|%%c^|%%d^|%%e^|%%f^|%%g>>meineTXT.txt  

Grüße
Biber
Mitglied: 52028
52028 Aug 14, 2007 at 21:29:34 (UTC)
Goto Top
Super, Vielen Dank für die rasche Antwort. Ich habe jetzt gerade leider keine Möglichkeit das auszuprobieren. Gebe aber Rückmeldung sobald ich das getan habe.

Gibt es auch eine Möglichkeit Excel-Dateien direkt zu verarbeiten, oder ist der Zwischenschritt über eine CVS-Datei zwingend notwendig. Vielleicht gibt es kleine Freeware-Tools die diesen Schritt bewerkstelligen und die man einbinden kann.

Aber wie gesagt, ich habe leider keine Möglichkeit das gerade zu testen, sondern kann mich im Moment nur "schlau"-lesen! ;)

Ich habe bisher auch noch gar keine Erfahrung auf diesem Gebiet, kann mir jemand gute Literatur oder Quellen zeigen die sich mit dem Thema beschäftigen? Vor allem die grundsätzliche Syntax interessiert mich.

Viele Grüße!
Member: Biber
Biber Aug 14, 2007 at 23:12:25 (UTC)
Goto Top
Moin marcos,

klar gibt es mögliche Varianten und Wege der Verfeinerung und Automatisierung.
Wahrscheinlich ist allerdings Dein Sachverhalt doch so off road, dass es auch bei Zuhilfenahme eines Freeware-Utilities eher holprig bleibt.
Ich würde in dem Fall, dass Du (aus welchen Gründen auch immer)
  • die Daten in der Excel-Tabelle erzeugst, hast oder pflegst
  • und regelmäßig dieses Export-Format mit den "|"-Trennzeichen brauchst
---> dann drück die Daten über einen Excel-VBA-Makro raus.
So etwas wird hier im Forum meist in wenigen Stunden entwickelt....

Falls Du vorher dennoch selbst auf die Suche nach Utilities gehen willst - vielleicht gibt es ja einen Standalone XLSToCSV-Converter- dann suche nach "CSV" (Comma Separated Values).
Die Abkürzung CVS ist mittlerweile genauso bekannt unter IT-Entwicklern, bezeichnet aber der Quasi-Standard für ein "Concurrent Versions System", ein (Code-)Versionsverwaltungssystem.

Grüße
Biber
Member: bastla
bastla Aug 15, 2007 at 00:09:28 (UTC)
Goto Top
Hallo marcos und willkommen im Forum!

Um Biber's Versprechung (So etwas wird hier im Forum meist in wenigen Stunden entwickelt ...) zumindest in den Grundzügen einzulösen:
Sub SpaltenExport()

Const TABELLE As String = "Tabelle1"  'Zu exportierende Daten in "Tabelle1" ...  
Const ABZEILE As Integer = 2          '... beginnen in Zeile 2 ...  
Const ABSPALTE As Integer = 1         '... und Spalte A ...  
Const ANZSPALTEN As Integer = 7       '... und umfassen 7 zusammenhängende Spalten.  

Const DATEI As String = "D:\Test.csv" 'Zieldatei  
Const TRENN As String = "|"           'Trennzeichen  

Set oDatei = CreateObject("Scripting.FileSystemObject"). _  
    OpenTextFile(DATEI, 2, True) 'Datei immer neu erstellen  
    
iZeile = ABZEILE
With Worksheets(TABELLE)
    Do While .Cells(iZeile, ABSPALTE).Value <> ""  
        sZeile = .Cells(iZeile, ABSPALTE).Value
        For i = 2 To ANZSPALTEN
            sZeile = sZeile & TRENN & .Cells(iZeile, ABSPALTE + i - 1).Value
        Next
        oDatei.WriteLine sZeile
        iZeile = iZeile + 1
    Loop
End With

oDatei.Close
MsgBox "Datei " & DATEI & " erstellt."  
End Sub
Anmerkungen:
Aufgrund des gewünschten Trennzeichens nehme ich an, dass Text in der Zieldatei nicht unter Anführungszeichen zu stehen braucht.
Es werden solange Datenzeilen geschrieben, bis eine Zeile erreicht wird, in der die Zelle in der ersten Datenspalte (ABSPALTE) leer ist.
Zum Testen: Wenn Du auf dem Blattregister ("Tabelle1") per Rechtsklick "Code anzeigen" wählst, kannst Du denn Code in den (jetzt geöffneten) VBA-Editor kopieren und aus dem Tabellenblatt als "Makro" aufrufen.

Grüße
bastla
Mitglied: 52028
52028 Aug 15, 2007 at 09:16:15 (UTC)
Goto Top
Wow, ihr seit wirklich schnell! ;)

Ich bin die nächsten Tage nicht in der Stadt und kann das folglich nicht ausprobieren, werde mich aber zu WE hin auf jeden Fall melden und das ausprobieren!

Vielen Dank auf jeden Fall schonmal!
Mitglied: 52028
52028 Aug 18, 2007 at 12:15:40 (UTC)
Goto Top
So, da bin ich wieder!

Die Erstellung der Text-Datei funktioniert wunderbar. Das Makro funktioniert auch. Allerdings suche ich gerade noch nach der Möglichkeit es mittels batchjob direkt auszuführen. Habe schon versucht es mittels Auto_Open() automatisch starten zu lassen - klappt aber noch nicht. Aber probieren geht über studieren... ;)
Mitglied: 52028
52028 Aug 19, 2007 at 14:30:41 (UTC)
Goto Top
So, ich danke euch nochmal - alles läuft jetzt zu meiner Zufriedenheit.

Nur eine Frage habe ich noch. Ist es theoretisch möglich mit diesem Excel-Makro auch eine andere Datei auszulesen? Ich stell mir das so vor, dass mein Batchjob meine Excel-Datei inklusive Makro aufruft, Excel aber widerum das Makro auf eine ganz andere Datei anwendet, dessen Pfad ich im Makro angeben kann.

Geht sowas theoretisch? Oder sogar praktisch ganz einfach?

Viele Grüße!
Member: bastla
bastla Aug 19, 2007 at 20:09:17 (UTC)
Goto Top
Hallo marcos!

Wenn Du das Ganze über Batch starten willst, sollte die Steuerung von Excel per VBS erfolgen, also etwa in der Art:
'XLS2CSV.vbs  
Const TABELLE = "Tabelle1" 'Zu exportierende Daten in "Tabelle1" ...  
Const ABZEILE = 2          '... beginnen in Zeile 2 ...  
Const ABSPALTE = 1         '... und Spalte A ...  
Const ANZSPALTEN = 7       '... und umfassen 7 zusammenhängende Spalten.  

Const ZIELPFAD = "D:\Exp\" 'Zielpfad mit abschließendem \ angeben  
Const TRENN = "|"          'Trennzeichen  

Dim oDatei
Set fso = CreateObject("Scripting.FileSystemObject")  
If WScript.Arguments.Count < 1 Then
	WScript.Echo "Angabe der Excel-Datei erforderlich!"  
	WScript.Quit(1)
End If

Set oArgs = WScript.Arguments
sXLDat = oArgs(0)
If Not fso.FileExists(sXLDat) Then
	WScript.Echo sXLDat & " nicht gefunden!"  
	WScript.Quit(1)
End If

sXLSDatei = fso.GetFile(sXLDat).Path 'Vollständigen Dateinamen mit Pfad ermitteln  
If LCase(Right(sXLSDatei, 4)) <> ".xls" Then  
	WScript.Echo "Angabe einer Excel-Datei (Typ .xls) erforderlich!"  
	WScript.Quit(1)
End If

sXLSPfad = Left(sXLSDatei, InStrRev(sXLSDatei, "\")) 'Pfad mit abschließendem "\"  
sXLSName = Mid(sXLSDatei, InStrRev(sXLSDatei, "\") + 1)  
sDateiName = Left(sXLSName, Len(sXLSName) - 4) 'ohne ".xls"  

DATEI = sXLSPfad & sDateiName & ".csv" 'Zieldatei  
Set oDatei = fso.OpenTextFile(DATEI, 2, True) 'Datei immer neu erstellen  

On Error Resume Next
Set XL = WScript.CreateObject("Excel.Application")  
If Err.Number Then Fehler Err.Number, Err.Description
Set oWB = XL.Workbooks.Open(sXLSDatei)
If Err.Number Then Fehler Err.Number, Err.Description
   
iZeile = ABZEILE
With oWB.Worksheets(TABELLE)
	If Err.Number Then Fehler Err.Number, Err.Description
    Do While .Cells(iZeile, ABSPALTE).Value <> ""  
        sZeile = .Cells(iZeile, ABSPALTE).Value
        For i = 2 To ANZSPALTEN
            sZeile = sZeile & TRENN & .Cells(iZeile, ABSPALTE + i - 1).Value
        Next
        oDatei.WriteLine sZeile
		If Err.Number Then Fehler Err.Number, Err.Description
        iZeile = iZeile + 1
		If Zeile > 65536 Then Exit Do
    Loop
End With

oDatei.Close
oWB.Saved = True
XL.Application.Quit
WScript.Echo "OK"  

Sub Fehler(Fehlernummer, Fehlertext)
WScript.Echo "Fehler " & Fehlernummer & " (" & Fehlertext & ") aufgetreten!"  
oWB.Saved = True
XL.Application.Quit
WScript.Quit(Err.Number)
End Sub
Wenn Du das obige Script zB in "C:\Scripts\XLS2CSV.vbs" speicherst, kannst Du es in einer Batchdatei wie folgt aufrufen:
@echo off & setlocal
for /f "delims=" %%i in ('cscript //nologo "C:\Scripts\XLS2CSV.vbs" "D:\Test\Exceldatei.xls"') do set Erg=%%i  
If "%Erg%"=="OK" goto :Weiter  
If "%Erg%" neq "" echo %Erg%  
::Fehlermeldung lesen lassen ...
pause
goto :eof
:Weiter
echo Hier geht es nach der Konvertierung weiter ...
Das Script erwartet die Übergabe einer Exceldatei, für welche die Existenz und der Typ ".xls" geprüft wird. Bei dabei auftretenden Fehlern (oder bei abgefangenen Scriptfehlern), wird eine Fehlermeldung ausgegeben, ansonsten endet das Script mit der Ausgabe von "OK" (oder einem Abbruch wegen eines Scriptfehlers und Anzeige der VBS-Fehlermeldung). Diese Ausgaben werden dazu verwendet, nur bei erfolgreichem Ablauf der Konvertierung zur Marke ":Weiter" zu springen und anderenfalls nach einer "Pause" (zum Lesen der Fehlermeldung) den Batch zu beenden.

Die Ausgabedatei erhält den selben Namen mit Typ ".csv" und wird in den gleichen Ordner wie die Exceldatei geschrieben.

Als Alternative habe ich eine zweite "DATEI = ..."-Zeile für die Verwendung eines konstanten Zielpfades (aber weiterhin variablen Dateinamens) dargestellt. Eine ev bereits vorhandene Zieldatei wird in beiden Fällen ohne Rückfrage überschrieben.

Die wahrscheinlichsten Fehler, die während der Konvertierung auftreten könnten (zB "Tabelle1" nicht vorhanden), werden in der aktuellen Fassung des Scripts abgefangen, sodass der unschöne Nebeneffekt eines Script-Fehlers (nämlich, dass Excel im Hintergrund weiterhin laufen und die ".xls"-Datei geöffnet halten könnte und daher über den Taskmanager, Register "Prozesse", beendet werden müsste) - eigenlich nicht auftreten sollte. Die Konstanten am Beginn des Programms werden allerdings nicht geprüft, sodass eine falsche Zeilen- oder Spaltennummer den beschriebenen Effekt trotzdem herbeiführen könnte ...

Grüße
bastla

P.S.: Für die adäquate Beschreibung des Errorhandlings in VBS fehlen mir einmal mehr die (jugendfreien) Worte ...