Question

Je suis en train d'écrire un code de conversion pour notre département de données pour convertir des fichiers en fichiers largeur fixe delmited. Normalement, nous utilisons importer le fichier dans Excel, utilisez l'assistant d'importation de texte pour définir les longueurs de terrain, et puis juste enregistrer comme un fichier CSV. Cependant, nous avons couru dans la limite où nous avons commencé à obtenir des fichiers qui sont des millions d'enregistrements long, et donc cant être importées dans Excel. Les fichiers ne sont pas toujours des espaces entre les champs, espicially donc entre les champs de valeur comme les numéros de téléphone ou des codes postaux. Les en-têtes sont souvent complètement remplis sans espaces.

Un échantillon d'un fichier largeur fixe typique que nous avons affaire à:

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

Les besoins du programme de fichier pause dans les champs délimités suivants:

Sequen
Sac et Pa
Nom complet
Intitulé du poste
Nom
Hosp Adresse de livraison
Autre adresse 1
Calculé Texte
POSTNET Bar

Chaque fichier comme une largeur légèrement différente de chaque champ en fonction du reste de la tâche. Qu'est-ce que je cherche est une interface graphique orientée delimiter un peu comme l'assistant d'importation Excel pour les fichiers à largeur fixe. Je vous écris cet outil en Python comme une partie d'un plus grand outil qui fait beaucoup d'autres opérations de fichiers tels que la rupture des fichiers en plusieurs haut, en inversant un fichier, conversion de délimité à largeur fixe et la vérification du chiffre de contrôle. J'utilise Tkinter pour le reste des outils et il serait idéal si l'utilisation de la solution ainsi.

Toute aide appréciée

Était-ce utile?

La solution

Si je comprends bien le problème (et il y a une bonne chance que je ne veux pas ...), la solution la plus simple serait d'utiliser un widget texte.

Faire la première ligne soit une série d'espaces de la même longueur que la rangée. Utilisez deux balises alternatives (par exemple: « même » et « impair ») pour donner chaque caractère une autre couleur afin qu'ils se distinguent les uns des autres. La deuxième ligne serait l'en-tête, et toutes les lignes restantes serait quelques lignes de données échantillon.

Ensuite, mettre en place des liaisons sur la première ligne pour convertir un espace dans un « x » lorsque l'utilisateur clique sur un personnage. S'ils cliquent sur un « x », reconvertir en un espace. Ils peuvent ensuite aller et cliquez sur le caractère qui est le début de chaque colonne. Lorsque l'utilisateur est fait, vous pouvez obtenir la première ligne du widget texte et il aura un « x » pour chaque colonne. Ensuite, vous avez juste besoin d'une petite fonction qui traduit que dans le format que vous avez besoin.

Il semble à peu près comme ça (bien évidemment les couleurs seraient différentes de ce qui apparaît sur ce site)

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

Voici un hack pour illustrer l'idée générale. Il est un peu bâclée, mais je pense qu'il illustre la technique. Lorsque vous exécutez, cliquez sur une zone dans la première rangée de définir ou d'effacer un marqueur. Cela entraînera l'en-tête à mettre en valeur dans des couleurs alternatives pour chaque marqueur.

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()

Autres conseils

modifier Je vois maintenant que vous êtes à la recherche d'une IUG. Je vais laisser cette mauvaise réponse pour la postérité.

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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top