Python Tkinter GUI将固定宽度文件转换为分隔文件
我正在为我们的数据部门编写一个转换代码,将固定宽度的文件转换为增量文件。通常我们使用将文件导入Excel,使用文本导入向导设置字段长度,然后保存为csv。但是,我们已经遇到了限制,我们已经开始获取数百万条记录长的文件,因此无法导入Excel。这些文件在字段之间并不总是有空格,尤其是在电话号码或邮政编码等值字段之间。标题通常也完全填充,没有空格 我们正在处理的典型固定宽度文件示例:Python Tkinter GUI将固定宽度文件转换为分隔文件,python,file,tkinter,fixed-width,delimited,Python,File,Tkinter,Fixed Width,Delimited,我正在为我们的数据部门编写一个转换代码,将固定宽度的文件转换为增量文件。通常我们使用将文件导入Excel,使用文本导入向导设置字段长度,然后保存为csv。但是,我们已经遇到了限制,我们已经开始获取数百万条记录长的文件,因此无法导入Excel。这些文件在字段之间并不总是有空格,尤其是在电话号码或邮政编码等值字段之间。标题通常也完全填充,没有空格 我们正在处理的典型固定宽度文件示例: SequenSack and PaFull Name****************************]JOB
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
程序需要将文件拆分为以下分隔字段:
顺序萨克和帕
全名
职务
医院名称
送货地址
备用地址1
计算文本
POSTNET栏
根据作业的其余部分,每个文件的每个字段的宽度略有不同。我要找的是一个面向GUI的分隔符,很像用于固定宽度文件的Excel导入向导。我正在用Python编写这个工具,作为一个较大工具的一部分,该工具可以执行许多其他文件操作,例如将文件拆分为多个文件、反转文件、从分隔宽度转换为固定宽度以及检查数字。我将Tkinter用于其他工具,如果解决方案也使用它,那将是理想的
感谢您提供的任何帮助编辑:我现在看到您正在寻找gui。我将把这个错误的答案留给子孙后代
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)
如果我正确地理解了这个问题(很有可能我没有…),最简单的解决方案可能是使用文本小部件 使第一行成为一系列与行长度相同的空格。使用两个交替标记(例如:“偶数”和“奇数”)为每个字符指定一个交替颜色,使它们彼此突出。第二行是标题,其余的行是两行示例数据 然后,在第一行设置绑定,以便在用户单击字符时将空格转换为“x”。如果他们单击“x”,则将其转换回空格。然后,他们可以去点击每列开头的字符。当用户完成后,您可以得到文本小部件的第一行,它的每一列都有一个“x”。然后,您只需要一个小函数,将其转换为您需要的任何格式 它看起来大概是这样的(虽然颜色明显不同于本网站上显示的颜色) 这里有一个简单的例子来说明这个想法。这有点草率,但我认为它说明了技术。运行时,单击第一行中的区域以设置或清除标记。这将导致每个标记的标题以交替颜色高亮显示
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()
导入系统
将Tkinter作为tk导入
导入tkFont
类SampleApp(tk.tk):
定义初始化(self,*args,**kwargs):
tk.tk.\uuuuu初始化(self,*args,**kwargs)
header=“SequenSack and PaFull Name***************************************]职务************************]HOSP Name***************************************************************************************************************************************************************其他1个地址*************************************************************************************************计算文本*************************************************************************************************************
样本=“000001T1 P1样本A样本123任何街道任何城镇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”)
类分隔符Widget(tk.Text):
定义初始化(自身、父项、标题、采样器行):
fixedFont=tkFont.nametofont(“TkFixedFont”)
tk.Text.\uuuu init\uuuuu(self,parent,wrap=“none”,height=3,font=fixedFont)
自我配置(cursor=“left\u ptr”)
self.tag\u configure(“header”,background=“gray”)
self.tag_configure(“偶数”,background=“#ffffff”)
self.tag\u configure(“header\u偶数”,background=“bisque”)
self.tag\u configure(“header\u odd”,background=“lightblue”)
self.tag_configure(“奇数”,background=“#eeeeee”)
markers=“”*len(标题)
对于范围内的i(len(header)):
tag=“偶数”如果i%2==0,则为“奇数”
self.insert(“结束”,“标记”)
self.insert(“结束”,“\n”)
self.insert(“结束”,标题+“\n”,“标题”)
自我插入(“结束”,采样器箭头,“样本”)
自我配置(state=“disabled”)
self.bind(“,self.on_单击)
self.bind(“,self.on_单击)
self.bind(“,self.on_单击)
单击时的def(自身,事件):
''处理对标记的单击''
index=self.index(“@%s,%s”%(event.x,event.y))
当前=self.get(索引)
自我配置(state=“normal”)
self.delete(索引)
(行、列)=索引拆分(“.”)
tag=“偶数”如果int(列)%2==0,则为“奇数”
char=”“如果当前==“x”否则为“x”
self.insert(索引、字符、标记)
自我配置(state=“disabled”)
self.highlight_header()
返回“中断”
def突出显示_收割台(自身):
''根据标记位置突出显示标题''
self.tag_remove(“页眉_偶数”,1.0,“结束”)
self.tag_remove(“页眉_奇数”,1.0,“结束”)
markers=self.get(1.0,“1.0 lineend”)
i=0
start=“2.0”
tag=“header\u偶数”
尽管如此:
尝试:
i=标记。索引(“x”,i+1)
end=“2.%s”%i
self.tag\u添加(标记、开始、结束)
开始=自索引(结束)
tag=“header\u偶数”如果tag==“header\u奇数”否则“header\u奇数”
除了弗吉尼亚州
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()