.csv Zeile mit batch ersetzen?
Heyo Freunde =)
Mit der Vorahnung, dass der Erzesel wieder die passende Lösung parat hat.. :D
Ich möchte mit meinem Batch script in meiner .csv Datei eine bestimmte Zeile ersetzen oder löschen. Die Datei sieht wie folgt aus:
b0200140 Status 2
b0200150 Status 1
b0200160 Status 2
b0200240 Status 2
b0200250 Status 2
b0200260 Status 2
b0200350 Status 2
b0200360 Status 2
b0200450 Status 2
b0200460 Status 2
Nun kann ich aus der Tabelle mit der Nummer den jeweiligen Datensatz direkt auswählen und über das Menü auch die History ansehen. Nun möchte ich aber auch den Status ändern. Es gibt 3 unterschiedliche Status Zahlen, Quasi Status 1, Status 2 und Status 3.
Hier erstmal das Menü dazu:
title %title% - Storage Settings
color %__@.backgroundcolor%%__@.fontcolor%
cls
echo ╔══════════════════════╦══════════════════════╦══════════════════════╦══════════════════════╗
echo ║ C - Create Storage ║ ║ ║ B - Back ║
echo ╠══════════════════════╩══════════════════════╩══════════════════════╩══════════════════════╣
echo !Table4.HeaderLine!
echo %Table4.HeadBottom%
for /f "skip=2 tokens=1-6 delims=[];" %%a in ('find /v /n "" "%appdata%\crs\storage.csv"') do (
call :replaceTableLineContent Table4.NewLine "%%~a" "%%~b" "%%~c" "%%~d"
echo !Table4.NewLine!
)
echo %Table4.Bottom%
echo.
echo Status 1: Blocked Status 2: Active Status 3: Damage
echo.
echo.
set /p "LineNo=Enter storage number:"
if %LineNo%==c goto CAT.HOME.SETTINGS.STORAGE.CREATE
if %LineNo%==b goto CAT.HOME.SETTINGS.ADMIN
set ColNo=1
set "line="
set /a LineNo-=1
for /f "delims=; tokens=%ColNo%" %%a in ('more/e +%LineNo% ^< %appdata%\crs\storage.csv') do (
if not defined line set "line=%%a"
)
set ColNo2=2
set "line2="
for /f "delims=; tokens=%ColNo2%" %%a in ('more/e +%LineNo% ^< %appdata%\crs\storage.csv') do (
if not defined line2 set "line2=%%a"
)
goto CAT.HOME.SETTINGS.STORAGE.FILTER
Damit kann ich einfach eine Nummer der Aufzählung eingeben und gelange auf eine Seite, auf der ich Details sehe, die Historie einsehen kann (wer was wann warum gemacht hat) und den Status ändern kann.
Wie kriege ich das wohl am besten hin, dass ich entweder nur die ausgewählte Zeile in der .csv überschreibe oder den Status überschreibe?
3 Antworten
Bei sowas kommst Du nicht ums komplette neuschreiben herum:
@echo off
set "FileToEdit=test.txt"
set "__tempFile=temp.txt"
set "searchWord=b0200260"
set "newStatus=666"
(call )>"%__tempFile%" &rem leere Datei
rem einlesen
for /f "usebackq tokens=1*" %%a in ("%FileToEdit%") do (
rem finde deine Nummer im ersten Token
echo "%%a"|find "%searchWord%" >nul &&(
rem wenn gefunden:
>>"%__tempFile%" echo %%a Status %newStatus%
)||(
rem sonst
>>"%__tempFile%" echo %%a %%b
)
)
rem verschiebe in Originaldatei
move "%__tempFile%" "%FileToEdit%" >nul
type "%FileToEdit%"
pause
Etwas Trickreicher ohne temporäre Datei. (der gesamte Inhalt des Originals wird in den Buffer von For/f gelesen und das Original zurückgesetzt )
@echo off
set "FileToEdit=test.txt"
set "searchWord=b0200260"
set "newStatus=0815"
for /f "tokens=1*" %%a in ('type "%FileToEdit%" ^& ^(call ^)^>"%FileToEdit%"') do (
echo "%%a"|find "%searchWord%" >nul &&(
>>"%FileToEdit%" echo %%a Status %newStatus%
)||(
>>"%FileToEdit%" echo %%a %%b
)
)
type "%FileToEdit%"
pause
Gibt es eine Möglichkeit die Tabelle von dir bei der Abfrage alle 30 Zeilen zu unterbrechen, sodass man auf die nächste Seite gehen kann und das im Endeffekt übersichtlicher hat?
Ich bastle hier keine neuen TabellenZeilen, das Prinzip sollte Klar sein... Das ganze ist lediglich eine Frage des Umgangs mit der DatenQuelle...
hier wieder der Oneliner zum Erzeugen eines schönen langen Demo.csv
powershell "1..95|foreach{ $_dummy=$_; (1..5|foreach{'Artikel {0} Feld {1}' -f $_dummy,$_}) -join ','}|out-file 'demo.csv' -enc ascii"
for/f hat den schönen skip -Filte, welcher die gewünschte Anzahl von von Zeilen überspringt. und find liefert die laufenden Zeilennummern.
Es reicht aus festzulegen wieviele Zeilen beim Einlesen des CSV übersprungen werden sollen und in der schleife zu prüfen bei welcher Zeilennummer abgebrochen werden soll...
@echo off
chcp 65001 >nul
setlocal enableDelayedExpansion
set "MaxRows=20
set "skipLines=2"
set /a "endLine=skipLines + MaxRows -2" &rem "-1" nur, weil wir wg. find mit 2 beginnen
:read
rem hatten wir nicht schon "skip"
rem es gibt kein Skip=0 !!! , desshalb sicherer den ganzen Filter in einer Variable halten und diese bei 0 löschen.
if %skipLines% gtr 0 (set "skipFilter=skip=%skipLines%") else (set "skipFilter=skip=")
for /f "%skipFilter% tokens=1-4 delims=[]," %%a in ('find /v /n "" "demo.csv"') do (
echo %%~a ## %%~b ## %%~c ## %%~d
rem einfach aus der Schleife springen, wenn Endbedingung erreicht ist...)
if %%a equ %endline% (
rem nächste Positionen berechnen.
set /a "skipLines=%%a +2, endLine=%%a + MaxRows"
goto :break
)
)
:break
echo Taste für nächste Seite...
pause >nul
goto :read
pause
Das erscheint billig, könnte aber teuer in der Weiterbehandlung werden und das sind mur 95 Zeilen... Der Nachteil ist dass jedesmal die komplette csv-Datei gelesen wird, denn skip und der Abbruchtest wirken erst, wenn die Datei schon lange gelesen ist.
Hier noch eine andere bessere Variante. diese erscheint erstmal aufwendiger, aber konvertiert nur einmal das csv in ein (pseudo)Array. Man muss später nicht jedes Mal die csv-Zeilen zerlegen.
@echo off
chcp 65001 >nul
setlocal enableDelayedExpansion
set "csvFile=demo.csv"
set "ArrayFile=%csvFile%.Array"
if exist "%csvArrayFile%" (
rem Array aus Datei laden (schneller)
for /f "usebackq tokens=*" %%a in ("%ArrayFile%") do (set "%%a")
goto :noArrayInit
)
rem csv komplet in ein 2dimmensionales(pseudo)Array lesen: ArrayName.Zeile.Spalte
for /f "skip=2 tokens=1-6 delims=[]," %%a in ('find /v /n "" "%csvFile%"') do (
rem ArrayName.Zeile.Spalte
set "DataArray.%%~a.1=%%~b"
set "DataArray.%%~a.2=%%~c"
set "DataArray.%%~a.3=%%~d"
set "DataArray.%%~a.4=%%~e"
set "DataArray.%%~a.5=%%~f"
set "DataArray.MaxLineIndex=%%a"
)
:noArrayInit
rem Bei Bedarf Array in Datei sichern
set "DataArray." >%ArrayFile%
:: hier beginnt die Arbeit mit den Daten
rem die CSVDatei wird nicht mehr angefasst
:: in Blöcken anzeigen:
rem so ein Array hast du im Speicher und musst nicht jedes Mal die CSV-Datei durchforsten (schnell)
rem jetzt kannst Du flink mit einem ZählLoop agieren ohne irgendwelche Eierrei
set "MaxRows=20"
set "startLine=1"
:next
call :showMyTablePart %startLine% %MaxRows%
set /a "startLine+=MaxRows"
if %startLine% leq %DataArray.MaxLineIndex% (
echo Taste für nächste Seite...
pause >nul
goto :next
)
echo fertsch^^! Das war der Tabellenteil ^^!
echo:
rem jetzt kannst Du die Daten in jetzt in den gewünschten Zeilen/Spalten änden wie es Dir beliebt
rem in dem Array lässt sich auch viel besser und schneller Arbeiten, als bei der direkten Wurstelei mit dem csv.
rem ändere ein bestimmtes Feld
set "DataArray.1.2=Hallo geändert 0815"
call :showMyTablePart 1 1
echo:
rem lösche ganze ArrayZeile
for /f "delims==" %%a in ('set "DataArray.55." 2^>nul') do (set "%%a=")
call :showMyTablePart 54 3
echo:
rem ändere gewünschte Zelle
echo was soll geändert werden?
set /p "__line=Zeile="
set /p "__column=Spalte="
echo Inhalt der Zelle: !DataArray.%__line%.%__column%!
set /p "DataArray.%__line%.%__column%=neuer Inhalt="
set "DataArray.%__line%.%__column%"
echo Inhalt der Zelle: !DataArray.%__line%.%__column%!
call :showMyTablePart %__line% 1
:: bis hier haben wir nur noch mit unserem Array gearbeitet
::damit wir das auch nach dem nächsten Start können, speichen wir es
set "DataArray." >%ArrayFile%
:: unser Array wieder zu einem CSV exportieren...
del "%csvFile%"
for /l %%a in (1,1,%DataArray.MaxLineIndex% ) do (
if defined DataArray.%%a.1 (
>>"%csvFile%" echo !DataArray.%%a.1!,!DataArray.%%a.2!,!DataArray.%%a.3!,!DataArray.%%a.4!,!DataArray.%%a.5!
)
)
echo:
echo Ende der Demo
pause
exit /b
:showMyTablePart
:: nur abgepeckt, (echt Tabelle hatten wir schon)
set /a "__endLine=%~1 + %~2 -1"
for /l %%a in (%~1,1,%__endLine%) do (
if defined DataArray.%%a.1 (
echo !DataArray.%%a.1! ## !DataArray.%%a.2! ## !DataArray.%%a.3! ## !DataArray.%%a.4! ## !DataArray.%%a.5!
)
)
exit /b
Das Array ist lediglich eine andere Form die Daten zu verwalten/speichern. Solange die ArrayDatei existiert, arbeitet die Batch automatisch mit dem Array weiter und synchronisiert am Ende lediglich die Daten. Das CSV existiert defakto lediglich als "Parallelwelt"...
da wirst du neu schreiben müssen, da das ändern so nciht funktioniert , den daten sind ja sequenzel angelegt und dann müsste man platz schaffen oder wegnehmen. und somit den rest ab änderung eh neu machen .
deswegen hat man dann sowas wie datenbanken entwickelt ;)
https://www.pcwelt-forum.de/threads/batch-file-um-text-a-durch-text-b-zu-ersetzen.478432/index.html
oder auch
Ich habe das Pproblem inzwischen anderweitig gelöst =)
Ich habe den Status von dem Platz/ storage getrennt und beim erstellen der plätze einzelnd in eine .dll gepackt, jeweils mit dem namen des platzes, hole mir den inhalt der .dll dann bei der abfrage aus der datei und setze es in eine variable um die anzuzeigen. so kann ich den inhalt der .dll einfach komplett überschreiben =)
Habs nun so gelöst:
set /p "location.barcode=Scan or enter new location:"
if %location.barcode%==b goto CAT.HOME.SETTINGS.ADMIN
cls
echo ╔══════════════════════╦══════════════════════╦══════════════════════╦══════════════════════╗
echo ║ ║ ║ ║ B - Back ║
echo ╚══════════════════════╩══════════════════════╩══════════════════════╩══════════════════════╝
echo - Create Storage - %Date% %time:~0,5%
echo.
echo Please select status for location: %location.barcode%:
echo.
echo [1] Blocked [2] Active [3] Damage
choice /c b123 >nul
set /a "__result=%errorlevel%-1"
if %errorlevel%==1 goto CAT.HOME.SETTINGS.ADMIN
if %errorlevel%==2 goto CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.1
if %errorlevel%==3 goto CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.2
if %errorlevel%==4 goto CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.3
:CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.1
set location.status=Status 1
goto CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.STATUS.CONFIRM
:CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.2
set location.status=Status 2
goto CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.STATUS.CONFIRM
:CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.3
set location.status=Status 3
goto CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.STATUS.CONFIRM
:CAT.HOME.SETTINGS.STORAGE.CREATE.STATUS.STATUS.CONFIRM
cls
echo ╔══════════════════════╦══════════════════════╦══════════════════════╦══════════════════════╗
echo ║ ║ ║ ║ B - Back ║
echo ╚══════════════════════╩══════════════════════╩══════════════════════╩══════════════════════╝
echo - Create Storage - %Date% %time:~0,5%
echo.
echo Caution: Created locations CANNOT be deleted.
echo Locations can only be blocked.
echo.
echo Confirm location creation:
echo.
echo Location: %location.barcode%
echo Status: %location.status%
echo.
echo [1] Confirm [2] Decline
choice /c b12 >nul
set /a "__result=%errorlevel%-1"
if %errorlevel%==1 goto CAT.HOME.SETTINGS.ADMIN
if %errorlevel%==2 goto CAT.HOME.SETTINGS.STORAGE.CREATE.CONFIRM
if %errorlevel%==3 goto CAT.HOME.SETTINGS.STORAGE.CREATE.DECLINE
goto CAT.HOME.SETTINGS.STORAGE
:CAT.HOME.SETTINGS.STORAGE.CREATE.CONFIRM
title %title% - Create Storage
color %__@.backgroundcolor%%__@.fontcolor%
cls
echo ╔══════════════════════╦══════════════════════╦══════════════════════╦══════════════════════╗
echo ║ ║ ║ ║ B - Back ║
echo ╚══════════════════════╩══════════════════════╩══════════════════════╩══════════════════════╝
echo - Create Storage - %Date% %time:~0,5%
echo.
echo %location.barcode%>>"%appdata%\crs\storage.csv"
echo %location.status% >"%appdata%\crs\storage\%location.barcode%.dll"
echo CREATE.STORAGE;OPERATOR_INTERVENTION;%username%;%Date%;%time:~0,5%;%location.barcode%;%location.status% >>"%appdata%\crs\log\logdata.csv"
echo Location %location.barcode% successful created in status %location.status% with user %username%.
timeout /t 3 >nul
goto CAT.HOME.SETTINGS.ADMIN
und ändern kann man es auch:
echo ╔══════════════════════╦══════════════════════╦══════════════════════╦══════════════════════╗
echo ║ C - Change Status ║ H - History ║ ║ B - Back ║
echo ╠══════════════════════╩══════════════════════╩══════════════════════╩══════════════════════╣
echo !Table4.HeaderLine!
echo %Table4.HeadBottom%
set /p storage.status=<"%appdata%\crs\storage\%line%.dll"
for /f "skip=2 tokens=1-6 delims=[];" %%a in ('find /v /n "" "%appdata%\crs\storage.csv"') do (
if "%%~b"=="%line%" (
call :replaceTableLineContent Table4.NewLine "%%~a" "%%~b" "%storage.status%"
echo !Table4.NewLine!
)
)
echo %Table4.Bottom%
echo.
echo Status 1: Blocked Status 2: Active Status 3: Damage
echo.
echo.
choice /c chb >nul
set /a "__result=%errorlevel%-1"
if %errorlevel%==1 goto CAT.HOME.SETTINGS.STORAGE.EDIT.STATUS
if %errorlevel%==2 goto CAT.HOME.SETTINGS.STORAGE.EDIT.HISTORY
if %errorlevel%==3 goto CAT.HOME.SETTINGS.STORAGE
:CAT.HOME.SETTINGS.STORAGE.EDIT.STATUS
title %title% - Storage Settings
color %__@.backgroundcolor%%__@.fontcolor%
cls
echo ╔══════════════════════╦══════════════════════╦══════════════════════╦══════════════════════╗
echo ║ ║ ║ ║ B - Back ║
echo ╠══════════════════════╩══════════════════════╩══════════════════════╩══════════════════════╣
echo !Table4.HeaderLine!
echo %Table4.HeadBottom%
for /f "skip=2 tokens=1-6 delims=[];" %%a in ('find /v /n "" "%appdata%\crs\storage.csv"') do (
if "%%~b"=="%line%" (
call :replaceTableLineContent Table4.NewLine "%%~a" "%%~b" "%storage.status%"
echo !Table4.NewLine!
)
)
echo %Table4.Bottom%
echo.
echo Choose new status for %line%
echo.
echo [1] Blocked [2] Active [3] Damage
choice /c b123 >nul
set /a "__result=%errorlevel%-1"
if %errorlevel%==1 goto CAT.HOME.SETTINGS.STORAGE.FILTER
if %errorlevel%==2 goto CAT.HOME.SETTINGS.STORAGE.EDIT.STATUS.BLOCKED
if %errorlevel%==3 goto CAT.HOME.SETTINGS.STORAGE.EDIT.STATUS.ACTIVE
if %errorlevel%==4 goto CAT.HOME.SETTINGS.STORAGE.EDIT.STATUS.DAMAGE
:CAT.HOME.SETTINGS.STORAGE.EDIT.STATUS.BLOCKED
set storage.status.1=Status 1
echo %storage.status.1% >"%appdata%\crs\storage\%line%.dll"
echo EDIT.STORAGE.STATUS;OPERATOR_INTERVENTION;%username%;%Date%;%time:~0,5%;%line%;%storage.status.1% >>"%appdata%\crs\log\logdata.csv"
echo Location %line% successful edited in status %storage.status.1% with user %username%.
timeout /t 6 >nul
goto CAT.HOME.SETTINGS.STORAGE.FILTER
:CAT.HOME.SETTINGS.STORAGE.EDIT.STATUS.ACTIVE
set storage.status.2=Status 2
echo %storage.status.2% >"%appdata%\crs\storage\%line%.dll"
echo EDIT.STORAGE.STATUS;OPERATOR_INTERVENTION;%username%;%Date%;%time:~0,5%;%line%;%storage.status.2% >>"%appdata%\crs\log\logdata.csv"
echo Location %line% successful edited in status %storage.status.2% with user %username%.
timeout /t 6 >nul
goto CAT.HOME.SETTINGS.STORAGE.FILTER
:CAT.HOME.SETTINGS.STORAGE.EDIT.STATUS.DAMAGE
set storage.status.3=Status 3
echo %storage.status.3% >"%appdata%\crs\storage\%line%.dll"
echo EDIT.STORAGE.STATUS;OPERATOR_INTERVENTION;%username%;%Date%;%time:~0,5%;%line%;%storage.status.3% >>"%appdata%\crs\log\logdata.csv"
echo Location %line% successful edited in status %storage.status.3% with user %username%.
timeout /t 6 >nul
goto CAT.HOME.SETTINGS.STORAGE.FILTER
Ich habe es nun mit den .dll Dateien ganz gut gelöst.
Wie bei den Lagerplätzen möchte ich auch die Produkte in der Übersicht auswählen können, aber bei zuviel Produkten müsste man ewig hochscrollen.
Gibt es eine Möglichkeit die Tabelle von dir bei der Abfrage alle 30 Zeilen zu unterbrechen, sodass man auf die nächste Seite gehen kann und das im Endeffekt übersichtlicher hat?