PDF-Tabelle einlesen

Hallo, ich habe eine Adressdatei im PDF-Format und möchte diese in SAS einlesen. Wie mache ich das?

Es geht leider nicht auf dem Umweg über eine Textdatei, da dann die Spalten mit Blanks getrennt sind, die Angaben in den Spalten aber auch Blanks enthalten können (Bsp.: "An der Tankstelle 4" aus Strasse).

VG Elfriede

Struktur der PDF?

Hallo,

können Sie die Daten aus der PDF herauskopieren? Wie sehen diese dann aus? Können Sie ein Beispiel einstellen? Direkt aus einer PDF auslesen ist in der Regel extrem umständlich.

Das Beispiel ist ein wenig

Das Beispiel ist ein wenig schwierig, da es sich um eine Adressdatei handelt. Habe es stark verfremdet, damit die Personen unkenntlich werden. Ich denke, das Problem erkennt man wohl trotzdem, oder?

nname vname strasse ort gebdat plz patid
Abdulara Iwona 28051993 Testenweg 18 44444 Txxxxx 12345
Aferlei Tim 09031971 Am Bahnberg 6 98763 Sxxxxx 54321
Abraham Lea Sophie 13072004 Rosental 53799 Oxxxxxxx 85232
Achterholt von Nela 19011955 Ernst-Herbert-Str. 13a 43190 Bad Exxxxxxxxx 82839

Insgesamt sind es ca 1500 Adressen, die so eingelesen werden sollen.Die Übertragung in ein Textfile ist kein Problem, dieses Textfile sieht dann so aus wie mein Beispiel.

Das folgende Programm scheitert, wenn ein Name oder Strassenname aus mehr als einem Wort besteht, also ein Leerzeichen enthält:

DATA test;
format nname vname strasse ort $25. gebdat $10. plz patid $8.;
INFILE 'C:\Dokumente und Einstellungen\Müller.STATISTIK\Uveitis\Adressen.txt';
INPUT Nname $ Vname $ GebDat $ Strasse $ Nr $ PLZ $ Ort $ patid $;
run;

Basteln

Hallo.

Das ist ein hartnäckiger Fall. Auf Grund der mehrfach vorkommenden Leerzeichen in Name, Vorname oder auch Ort denke ich, dass fast nichts anderes übrig bleibt, als eine Zeile einzulesen, zu untersuchen und nach Merkmalen aufzusplitten. Üblicherweise kann man Leerzeichen in einem Feld mit einem Ampersand (&) hinter der Variablen im INPUT Statement erschlagen. Da hier die Leerzeichen aber mal hier mal dort vorkommen, wird man mit Informaten und ähnlichem kaum weiterkommen. Mit einem double training @, (also @@) am Ende des Input Statments wird die jeweilige Zeile "festgehalten". Diese können Sie dann entsprechend untersuchen und in die gewünschten Felder einsortieren. Dazu muss natürlich eine Grundstruktur vorhanden sein, aber die erkenne ich auch in Ihrem Beispiel (z.B. nach Vorname kommt eine x-stellige Zahl etc.).
Für Details zum @@ schauen Sie in die SAS Hilfe unter SAS Produkte, Base SAS, SAS Language Dictionary, Dictionary of Language Elements, Statements, INPUT.

Viel Erfolg.
Dubravko Dolic

Anhand der Nummern aufsplitten

Hallo Elfriede,

das ist wirklich Bastelei. Meiner Meinung nach ist es am Besten den Text als eine Zeile einzulesen und anhand der Nummern im Text in Teiltexte zu zerlegen. Da die Nummern entweder eine feste Länge haben oder ganz hinten stehen, ist ein solches Vorgehen möglich.

data test;
length text $256;
infile cards length=laenge;
input text $varying. Laenge;
drop Beginn: Name Text;
BeginnGeb = PrxMatch("/ \d{8} /",Text)+1 ;
BeginnPLZ = PrxMatch("/ \d{5} .* \d{1,8}\s*/", Text)+1;
BeginnPatId = Length(text)-Length(scan(text,-1))-1;
Name = substr(text, 1, BeginnGeb - 1);
nname = scan(name, 1, " ");
vname = substr(name, length(nname)+1);
Gebdat = input(substr(Text, BeginnGeb, 8),ddmmyy8.);
Strasse = substr(text, BeginnGeb + 8, BeginnPLZ-BeginnGeb - 8);
PLZ = substr(text, BeginnPLZ , 5);
Ort = substr(text, BeginnPLZ + 5, BeginnPatId-BeginnPlz - 5);
Patid = Input(scan(Text,-1," "), best8.);
format Gebdat ddmmyyP10.;
cards;
Abdulara Iwona 28051993 Testenweg 18 44444 Txxxxx 12345
Aferlei Tim 09031971 Am Bahnberg 6 98763 Sxxxxx 54321
Abraham Lea Sophie 13072004 Rosental 53799 Oxxxxxxx 85232
Achterholt von Nela 19011955 Ernst-Herbert-Str. 13a 43190 Bad Exxxxxxxxx 82839
run;

Mit den Beispieldaten funktioniert es, aber es kann durchaus sein, dass man es noch anpassen oder einzelne Einträge von Hand korrigieren muss.

Schöne Grüße

Jan

Danke!

Oh, danke! Auf so eine Lösung wäre ich nie gekommen. Aber es funktioniert!

Unklar ist mir allerdings, was die Zeile "drop Beginn: Name Text;" bewirkt.

VG Elfriede

temporäre Variablen löschen

Hallo Elfriede,

um die Zahlspalten zu indentifizieren habe ich den Beginn der der jeweiligen Spalte in die drei Variablen Beginn... geschrieben.
Der Name wurde erst als Ganzes eingelesen und hinterher aufgesplittet in Vorname, Nachname.
Der Text ist die gesamte Zeile.
Diese Variablen braucht man nicht in der Ausgabedatei, daher werden sie nicht mit in die Ausgabedatei übernommen.

Schöne Grüße

Jan

Oh Klasse, langsam blick ich

Oh Klasse, langsam blick ich durch.

Jetzt ist nur noch die Bestimmung des Anfangs der Patid unklar:

"BeginnPatId = Length(text)-Length(scan(text,-1))-1;"

Der Beginn der Patid ist also die Textlänge minus ...... Ja, minus was eigentlich? Wozu dient die Scan-Funktion dort?

(Ich hoffe, meine Rückfragen nerven noch nicht!)

VG Elfriede

Unbekannte Länge der PatId

Hallo Elfriede,

ich wusste nicht genau, wie lang die PatId sein kann. In den Beispielen war die PatId immer 5 Zeichen lang, aber in deinem ersten Beispielprogramm war sie mit $8. formatiert. Da sie aber der letzte Eintrag in der Zeile ist, kann man sie trotzdem bestimmen.

Scan(text,-1) liest den 1 Eintrag von hinten, also den letzten.
Length(scan(text,-1)) bestimmt die Länge des letzten Eintrags.

Und dann ist da noch ein Fehler in dem Programm.
Statt - 1 muss es + 1 heißen. Die Addition ist nötig, da substr die Zählung bei 1 und nicht bei 0 beginnt.

BeginnPatId = Length(text)-Length(scan(text,-1)) + 1;

Schöne Grüße

Jan

Ah, jetzt hab ich es

Ah, jetzt hab ich es begriffen! Ich kannte einfach den Befehl scan(text,-1) nicht.

Danke für die ausführliche Erklärung! Hab wiedermal eine ganze Menge gelernt.

VG Elfriede