Batch XML Importer - Import von Dateien mittels Batch und xml-File
Hallo zusammen,
ich habe gerade folgendes Problem:
Ein Scanner scannt Dokumente in ein Verzeichnis C:\scans\auftraege
Er benennt jedes Dokument fortlaufend Dok_001.tif
Dazu gibts jeweils eine xml-Datei Dok_001.xml, die soetwas hier enthält:
Ich möchte folgendes tun:
Ein Batchscript, welches den Ordner C:\scans\auftraege durchsucht nach xml-Dateien.
Aus diesen xml-Dateien das zugehörige Dokument ( FileName="Dok_001.tif" ) anfasst und verschiebt.
Zielpfad soll sein: w:\auftraege\ %jahr% \ %auftragsnummer% \ Dok_001_%auftragsnummer%.tif
Das Quell xml und tif Dokument soll nach Verarbeitung aus dem Ordner scans entfernt werden.
Theoretisch eigentlich nicht schwer, nur steh ich da irgendwie aufm Schlauch.
Könnt ihr mir helfen?
Schöne Grüße
Daniel
Nachtrag:
Seitengescant="2" Seitengeloescht="1" Seitengespeichert="1"
Der Scanner kann leere Seiten entfernen, bzw auch mehrere Dateien einzeln ablegen, so dass eine xml-Datei für mehrere tifs verfügbar ist.
Das Ergebnis wären Dok_001_001 - Dok_001_%seitenanzahl%
Indikator für mehrere tif Dokumente zu einer xml ist der Parameter %seitengespeichert%
Ich werd den Scanner allerdings so einstellen, dass er zu jeder xml auch nur 1 tif-Dokument hat. Aber falls jemand auch für diesen Teil eine Lösung hat, ich wäre nicht böse.
ich habe gerade folgendes Problem:
Ein Scanner scannt Dokumente in ein Verzeichnis C:\scans\auftraege
Er benennt jedes Dokument fortlaufend Dok_001.tif
Dazu gibts jeweils eine xml-Datei Dok_001.xml, die soetwas hier enthält:
<?xml version="1.0" encoding="utf-16"?>
<ScanIndex ScanProfilName="Auftrag erfassen" FileName="Dok_001.tif" Seitengescant="2" Seitengeloescht="1" Seitengespeichert="1">
<ImagePropertys Path="C:\scans\auftraege" />
<FieldsInfo>
<feld_1 Feldtyp="Auswahl" Feldname="Jahr" Feldlaenge="4" Wert="2014" />
<feld_2 Feldtyp="Text" Feldname="Auftrags-Nr." Feldlaenge="20" Wert="44545" />
</FieldsInfo>
</ScanIndex>
Ich möchte folgendes tun:
Ein Batchscript, welches den Ordner C:\scans\auftraege durchsucht nach xml-Dateien.
Aus diesen xml-Dateien das zugehörige Dokument ( FileName="Dok_001.tif" ) anfasst und verschiebt.
Zielpfad soll sein: w:\auftraege\ %jahr% \ %auftragsnummer% \ Dok_001_%auftragsnummer%.tif
Das Quell xml und tif Dokument soll nach Verarbeitung aus dem Ordner scans entfernt werden.
Theoretisch eigentlich nicht schwer, nur steh ich da irgendwie aufm Schlauch.
Könnt ihr mir helfen?
Schöne Grüße
Daniel
Nachtrag:
Seitengescant="2" Seitengeloescht="1" Seitengespeichert="1"
Der Scanner kann leere Seiten entfernen, bzw auch mehrere Dateien einzeln ablegen, so dass eine xml-Datei für mehrere tifs verfügbar ist.
Das Ergebnis wären Dok_001_001 - Dok_001_%seitenanzahl%
Indikator für mehrere tif Dokumente zu einer xml ist der Parameter %seitengespeichert%
Ich werd den Scanner allerdings so einstellen, dass er zu jeder xml auch nur 1 tif-Dokument hat. Aber falls jemand auch für diesen Teil eine Lösung hat, ich wäre nicht böse.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 241712
Url: https://administrator.de/contentid/241712
Ausgedruckt am: 22.11.2024 um 20:11 Uhr
7 Kommentare
Neuester Kommentar
Hallo Daniel,
da Deine XML-Datei laut Header in UTF-16 kodiert ist, eignet sich Batchscript nicht zum Parsen der Datei. MS stellt für solche Zwecke aber glücklicherweise eine ActiveX-Komponente bereit, die sich von VB Script aus nutzen lässt. Die Arbeit damit ist außerdem viel bequemer. Deshalb hier mein Vorschlag in VB Script:
Den Code in eine Textdatei mit der Dateierweiterung
Die Zeilen 5 und 6 musst Du ggf. anpassen. Falls sich die Namen der Knoten in der XML-Datei ändern bzw. mit Deinen Angaben nicht übereinstimmen, musst Du die entsprechenden Stellen im Unterprogramm
Gruß
Friemler
da Deine XML-Datei laut Header in UTF-16 kodiert ist, eignet sich Batchscript nicht zum Parsen der Datei. MS stellt für solche Zwecke aber glücklicherweise eine ActiveX-Komponente bereit, die sich von VB Script aus nutzen lässt. Die Arbeit damit ist außerdem viel bequemer. Deshalb hier mein Vorschlag in VB Script:
Option Explicit
'Konfiguration
Const strSourceFolder = "C:\Scans\Auftraege"
Const strDestFolder = "W:\Auftraege"
'Deklaration der globalen Variablen
Dim objFSO, objXMLDoc, objFile
Dim strFilePath, strFileName, strPageCount, strJobNum, strYear
'Objekte erzeugen
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objXMLDoc = CreateObject("MSXML2.DOMDocument.6.0")
'Hauptprogramm
For Each objFile In objFSO.GetFolder(strSourceFolder).Files
If StrComp(objFSO.GetExtensionName(objFile.Path), "xml", vbTextCompare) = 0 Then
If LoadXMLFile(objFile.Path) Then
Call ParseXMLFile
If ProcessTask Then Call DeleteFile(objFile.Path)
Else
WScript.Echo "Fehler beim Laden der Datei" & vbCrLf & _
objFile.Path & vbCrLf & _
objXMLDoc.parseError.reason
End If
End If
Next
'******************** Unterprogramme *******************
Function LoadXMLFile(strFilePath)
objXMLDoc.async = False
objXMLDoc.validateOnParse = False
objXMLDoc.resolveExternals = False
Call objXMLDoc.load(strFilePath)
LoadXMLFile = (objXMLDoc.parseError.errorCode = 0)
End Function
Sub ParseXMLFile
Dim objScanIndex, objImgProps, objFieldsInfo, objFieldInfo
Dim strFieldName
'XML-Knoten ScanIndex einlesen und Attribute auswerten
Set objScanIndex = objXMLDoc.documentElement.selectSingleNode("//ScanIndex")
strFileName = objScanIndex.getAttribute("FileName")
strPageCount = objScanIndex.getAttribute("Seitengespeichert")
'XML-Knoten ImagePropertys einlesen und Attribute auswerten
Set objImgProps = objXMLDoc.documentElement.selectSingleNode("//ImagePropertys")
strFilePath = objImgProps.getAttribute("Path")
'XML-Knoten FieldsInfo einlesen...
Set objFieldsInfo = objXMLDoc.documentElement.selectSingleNode("//FieldsInfo")
'...und Attribute auswerten
For Each objFieldInfo In objFieldsInfo.childNodes
strFieldName = objFieldInfo.getAttribute("Feldname")
If strFieldName = "Jahr" Then
strYear = objFieldInfo.getAttribute("Wert")
ElseIf strFieldName = "Auftrags-Nr." Then
strJobNum = objFieldInfo.getAttribute("Wert")
End If
Next
End Sub
Function ProcessTask
On Error Resume Next
Dim intCnt, intFileCnt
Dim strSrcFileName, strSrcFilePath, strDstFileName, strDstFilePath
Dim arrFiles
intFileCnt = CInt(strPageCount)
arrFiles = Array()
For intCnt = 1 To intFileCnt
If intFileCnt = 1 Then
strSrcFilePath = objFSO.BuildPath(strFilePath, strFileName)
strDstFileName = objFSO.GetBaseName(strFileName) & "_" & strJobNum & "." & objFSO.GetExtensionName(strFileName)
strDstFilePath = objFSO.BuildPath(strDestFolder, strYear & "\" & strJobNum & "\" & strDstFileName)
Else
strSrcFileName = objFSO.GetBaseName(strFileName) & "_" & Right("00" & CStr(intCnt), 3) & "." & objFSO.GetExtensionName(strFileName)
strSrcFilePath = objFSO.BuildPath(strFilePath, strSrcFileName)
strDstFileName = objFSO.GetBaseName(strSrcFileName) & "_" & strJobNum & "." & objFSO.GetExtensionName(strSrcFileName)
strDstFilePath = objFSO.BuildPath(strDestFolder, strYear & "\" & strJobNum & "\" & strDstFileName)
End If
ProcessTask = CopyFile(strSrcFilePath, strDstFilePath)
If Not ProcessTask Then Exit For
ReDim Preserve arrFiles(UBound(arrFiles) + 1)
arrFiles(UBound(arrFiles)) = strSrcFilePath
Next
If ProcessTask Then Call DeleteImageFiles(arrFiles)
End Function
Function CopyFile(strSrcFilePath, strDstFilePath)
On Error Resume Next
Dim objShell, strDstPath
strDstPath = objFSO.GetParentFolderName(strDstFilePath)
If Not objFSO.FolderExists(strDstPath) Then
Set objShell = CreateObject("WScript.Shell")
Call objShell.Run("cmd /c mkdir """ & strDstPath & """", 0, True)
End If
Call objFSO.CopyFile(strSrcFilePath, strDstFilePath, False)
CopyFile = (Err.Number = 0)
Call TestError("Fehler beim Kopieren der Datei", strSrcFilePath)
End Function
Sub DeleteImageFiles(ByRef arrFiles)
On Error Resume Next
Dim intCnt
For intCnt = 0 To UBound(arrFiles)
Call DeleteFile(arrFiles(intCnt))
Next
End Sub
Sub DeleteFile(strFilePath)
On Error Resume Next
Call objFSO.DeleteFile(strFilePath, True)
Call TestError("Fehler beim Löschen der Datei", strFilePath)
End Sub
Sub TestError(strMessage, strFilePath)
If Err.Number <> 0 Then
WScript.Echo strMessage & vbCrLf & _
strFilePath & vbCrLf & _
Err.Description
Err.Clear
End If
End Sub
Den Code in eine Textdatei mit der Dateierweiterung
vbs
speichern. Du kannst das Script dann per Doppelklick starten.Die Zeilen 5 und 6 musst Du ggf. anpassen. Falls sich die Namen der Knoten in der XML-Datei ändern bzw. mit Deinen Angaben nicht übereinstimmen, musst Du die entsprechenden Stellen im Unterprogramm
ParseXMLFile
ändern.Gruß
Friemler
Hallo Daniel,
Grüße Uwe
p.s. eine alternative Lösung mit Powershell könnte so aussehen (Funktioniert ebenfalls für beide Varianten mit einer oder mehreren Files):
Beim Aufrufen einer Unterroutine (Sub) dürfen keine Klammern verwendet werden.
schreib es so:objFSO.MoveFile strSrcFilePath, strDstFilePath
p.s. eine alternative Lösung mit Powershell könnte so aussehen (Funktioniert ebenfalls für beide Varianten mit einer oder mehreren Files):
#------------------------------------------
$sourcePath ="C:\scans\auftraege"
$targetPath = "w:\auftraege"
# -----------------------------------------
$xml = new-object XML
$files = dir "$sourcePath\*.xml"
foreach($file in $files){
# XML-File laden
$xml.Load($file.FullName)
# Infos extrahieren
$strFName = $xml.ScanIndex.FileName
$strYear = $xml.ScanIndex.FieldsInfo.SelectSingleNode("*[@Feldname='Jahr']").Wert
$strJobNr = $xml.ScanIndex.FieldsInfo.SelectSingleNode("*[@Feldname='Auftrags-Nr.']").Wert
# Zielordner festlegen und erzeugen
$newFolder = "$targetPath\$strYear\$strJobNr"
if(!(Test-Path $newFolder)){md $newFolder -Force | out-null}
# Files verschieben
$finfo = [System.IO.FileInfo]"$strFName"
dir "$sourcePath\$($finfo.BaseName)*$($finfo.Extension)" | %{move-item $_.FullName "$newFolder\$($_.BaseName)_$strJobNr$($_.Extension)"}
# XML File löschen
del $file.FullName -Force
}
Anleitung: Wie starte ich Powershell-Scripte
- Zuerst speicherst man den Code in einer Textdatei mit der Endung .ps1.
- Wenn man zum ersten mal Powershell-Scripte ausführt, musst man einmalig vorher noch das Ausführen von Scripten im User-Account freischalten. Dazu öffnet man eine Powershell-Konsole und gibt dort den Befehl
Set-ExecutionPolicy RemoteSigned -Force
ein. Um diese Policy für alle User auf dem Rechner zu setzen muss man diesen Befehl in einer Powershell-Konsole mit Admin-Rechten starten. Noch ein Hinweis für 64-Bit-Systeme: Hier sollte sowohl für die 32bit und 64Bit Variante der Powershell die Policy in einer Admin-Konsole gesetzt werden:Set-ExecutionPolicy RemoteSigned -Force; start-job { Set-ExecutionPolicy RemoteSigned -Force } -RunAs32
- Jetzt kann das Powershell-Script in der Konsole mit Eingabe des Pfades der Scriptdatei, oder mit einem Rechtsklick auf die Script-Datei :Mit Powershell ausführen gestartet werden.