Frage

Ich schreibe einen Konvertercode für unsere Datenabteilung, um Dateien mit fester Breite in Dateien mit Trennzeichen zu konvertieren.Normalerweise importieren wir die Datei in Excel, legen die Feldlängen mit dem Textimport-Assistenten fest und speichern sie dann einfach als CSV.Wir sind jedoch auf die Einschränkung gestoßen, dass wir Dateien erhalten, die Millionen von Datensätzen lang sind und daher nicht in Excel importiert werden können.Die Dateien enthalten nicht immer Leerzeichen zwischen den Feldern, insbesondere zwischen Wertfeldern wie Telefonnummern oder Postleitzahlen.Auch die Kopfzeilen sind oft vollständig ausgefüllt und enthalten keine Leerzeichen.

Ein Beispiel einer typischen Datei mit fester Breite, mit der wir es zu tun haben:

SequenSack and PaFull Name****************************]JOB TITLE****************]HOSP NAME******************************]Delivery Address***********************]Alternate 1 Address********************]Calculated Text**********************************]POSTNET Bar
000001T1  P1     Sample A Sample                                                                                         123 Any Street                                                                  Anytown 12345-6789                                12345678900
000002T1  P1     Sample A Sample                       Director of Medicine                                              123 Any Street                          Po Box 1234                             Anytown 12345-6789                                12345678900

Das Programm muss die Datei in die folgenden durch Trennzeichen getrennten Felder aufteilen:

Sequenz
Sack und Pa
Vollständiger Name
Berufsbezeichnung
Hosp-Name
Lieferadresse
Alternative Adresse 1
Berechneter Text
POSTNET-Leiste

Jede Datei hat je nach Rest des Auftrags eine leicht unterschiedliche Breite jedes Feldes.Was ich suche, ist ein GUI-orientiertes Trennzeichen, ähnlich dem Excel-Importassistenten für Dateien mit fester Breite.Ich schreibe dieses Tool in Python als Teil eines größeren Tools, das viele andere Dateioperationen ausführt, z. B. das Aufteilen von Dateien in mehrere Dateien, das Umkehren einer Datei, das Konvertieren von durch Trennzeichen in eine feste Breite und die Prüfung von Prüfziffern.Ich verwende Tkinter für die restlichen Tools und es wäre ideal, wenn die Lösung es auch verwenden würde.

Jede Hilfe wird geschätzt

War es hilfreich?

Lösung

Wenn ich das Problem richtig verstehe (und die Chancen stehen gut, dass ich es nicht verstehe), wäre die einfachste Lösung möglicherweise die Verwendung eines Text-Widgets.

Gestalten Sie die erste Zeile als eine Reihe von Leerzeichen mit der gleichen Länge wie die Zeile.Verwenden Sie ein paar abwechselnde Tags (z. B.:„gerade“ und „ungerade“), um jedem Zeichen eine andere Farbe zu geben, damit sie sich voneinander abheben.Die zweite Zeile wäre die Kopfzeile und alle verbleibenden Zeilen wären ein paar Zeilen mit Beispieldaten.

Richten Sie dann Bindungen in der ersten Zeile ein, um ein Leerzeichen in ein „x“ umzuwandeln, wenn der Benutzer auf ein Zeichen klickt.Wenn sie auf ein „x“ klicken, wandeln Sie es wieder in ein Leerzeichen um.Sie können dann auf das Zeichen klicken, das am Anfang jeder Spalte steht.Wenn der Benutzer fertig ist, können Sie die erste Zeile des Text-Widgets abrufen, in der für jede Spalte ein „x“ steht.Sie benötigen dann nur noch eine kleine Funktion, die das in das von Ihnen benötigte Format übersetzt.

Es würde ungefähr so ​​aussehen (obwohl die Farben natürlich anders wären als auf dieser Website dargestellt)

      x          x                                     x  ...
SequenSack and PaFull Name****************************]JOB...
000001T1  P1     Sample A Sample                          ...

Hier ist ein kurzer Hack, um die allgemeine Idee zu veranschaulichen.Es ist ein wenig schlampig, aber ich denke, es veranschaulicht die Technik.Wenn Sie es ausführen, klicken Sie auf einen Bereich in der ersten Zeile, um eine Markierung zu setzen oder zu löschen.Dadurch wird die Kopfzeile für jede Markierung in wechselnden Farben hervorgehoben.

import sys
import Tkinter as tk
import tkFont

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        header = "SequenSack and PaFull Name****************************]JOB TITLE****************]HOSP NAME******************************]Delivery Address***********************]Alternate 1 Address********************]Calculated Text**********************************]POSTNET Bar"
        sample = "000001T1  P1     Sample A Sample                                                                                         123 Any Street                                                                  Anytown 12345-6789                                12345678900"
        widget = DelimiterWidget(self, header, sample)
        hsb = tk.Scrollbar(orient="horizontal", command=widget.xview)
        widget.configure(xscrollcommand=hsb.set)
        hsb.pack(side="bottom", fill="x")
        widget.pack(side="top", fill="x")

class DelimiterWidget(tk.Text):
    def __init__(self, parent, header, samplerow):
        fixedFont = tkFont.nametofont("TkFixedFont")
        tk.Text.__init__(self, parent, wrap="none", height=3, font=fixedFont)
        self.configure(cursor="left_ptr")
        self.tag_configure("header", background="gray")
        self.tag_configure("even", background="#ffffff")
        self.tag_configure("header_even", background="bisque")
        self.tag_configure("header_odd", background="lightblue")
        self.tag_configure("odd", background="#eeeeee")
        markers = " "*len(header)
        for i in range(len(header)):
            tag = "even" if i%2==0 else "odd"
            self.insert("end", " ", (tag,))
        self.insert("end", "\n")
        self.insert("end", header+"\n", "header")
        self.insert("end", samplerow, "sample")
        self.configure(state="disabled")
        self.bind("<1>", self.on_click)
        self.bind("<Double-1>", self.on_click)
        self.bind("<Triple-1>", self.on_click)

    def on_click(self, event):
        '''Handle a click on a marker'''
        index = self.index("@%s,%s" % (event.x, event.y))
        current = self.get(index)
        self.configure(state="normal")
        self.delete(index)
        (line, column) = index.split(".")
        tag = "even" if int(column)%2 == 0 else "odd"
        char = " " if current == "x" else "x"
        self.insert(index, char, tag)
        self.configure(state="disabled")
        self.highlight_header()
        return "break"

    def highlight_header(self):
        '''Highlight the header based on marker positions'''
        self.tag_remove("header_even", 1.0, "end")
        self.tag_remove("header_odd", 1.0, "end")
        markers = self.get(1.0, "1.0 lineend")

        i = 0
        start = "2.0"
        tag = "header_even"
        while True:
            try:
                i = markers.index("x", i+1)
                end = "2.%s" % i
                self.tag_add(tag, start, end)
                start = self.index(end)
                tag = "header_even" if tag == "header_odd" else "header_odd"
            except ValueError:
                break

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

Andere Tipps

bearbeiten: Ich sehe jetzt, dass Sie nach einer GUI suchen. Ich werde diese falsche Antwort für die Nachwelt hinterlassen.

import csv

def fixedwidth2csv(fw_name, csv_name, field_info, headings=None):
    with open(fw_name, 'r') as fw_in:
        with open(csv_name, 'rb') as csv_out: # 'rb' => 'r' for python 3
            wtr = csv.writer(csv_out)
            if headings:
                wtr.writerow(headings)
            for line in fw_in:
                wtr.writerow(line[pos:pos+width].strip() for pos, width in field_info)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top