python - wxPython:如何免除(放弃)空的 CSV 列和行导入 wxGrid

标签 python csv wxpython wxwidgets

我有一个脚本将 CSV 文件导入到 wxGrid 中,现在用户可能会导入包含空列和行的 CSV 文件数据。我想排除所有完全空的列和行导入到网格中。 当 CSV 导入到 wxGrid 时,我希望删除完全空的列

我不知道如何解决这个问题,任何帮助将不胜感激。

csv1.py是GUI脚本

import wx


###########################################################################
## Class MyFrame3
###########################################################################

class MyFrame3 ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 900,600 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        Sizer1 = wx.BoxSizer( wx.HORIZONTAL )

        Sizer1.SetMinSize( wx.Size( 0,0 ) ) 
        self.Right_Panel = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        RightSizer = wx.BoxSizer( wx.VERTICAL )


        self.Right_Panel.SetSizer( RightSizer )
        self.Right_Panel.Layout()
        RightSizer.Fit( self.Right_Panel )
        Sizer1.Add( self.Right_Panel, 1, wx.EXPAND |wx.ALL, 5 )

        self.Left_Panel = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        LeftSizer = wx.BoxSizer( wx.VERTICAL )

        self.ImportButton = wx.Button( self.Left_Panel, wx.ID_ANY, u"Import CSV File", wx.DefaultPosition, wx.DefaultSize, 0 )
        LeftSizer.Add( self.ImportButton, 0, wx.ALL, 5 )


        self.Left_Panel.SetSizer( LeftSizer )
        self.Left_Panel.Layout()
        LeftSizer.Fit( self.Left_Panel )
        Sizer1.Add( self.Left_Panel, 0, wx.EXPAND |wx.ALL, 5 )


        self.SetSizer( Sizer1 )
        self.Layout()
        self.menubar = wx.MenuBar( 0 )
        self.fileMenu = wx.Menu()
        self.importMenu = wx.MenuItem( self.fileMenu, wx.ID_ANY, u"Import", wx.EmptyString, wx.ITEM_NORMAL )
        self.fileMenu.AppendItem( self.importMenu )

        self.menubar.Append( self.fileMenu, u"&File" ) 

        self.SetMenuBar( self.menubar )


        self.Centre( wx.BOTH )

        # Connect Events
        self.ImportButton.Bind( wx.EVT_BUTTON, self.ImportFunc )
        self.Bind( wx.EVT_MENU, self.ImportFunc, id = self.importMenu.GetId() )

csv2.py是运行脚本

#!/usr/bin/python
# -*- coding: utf-8 -*- 

import wx
import os
import sys, csv
import wx.grid
from csv1 import MyFrame3

class MyFrame(MyFrame3):
    def __init__(self, parent, size = wx.Size(900,600)):
        MyFrame3.__init__ (self, parent)

        self.dirname = os.getcwd()



    # Import/Open CSV

    def ImportFunc( self, event ):

        dlg=wx.FileDialog(self, 'Choose a file', self.dirname, '','CSV files (*.csv)|*.csv',wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self.dirname=dlg.GetDirectory()
            self.filename=os.path.join(self.dirname,dlg.GetFilename())
            self.file=file(self.filename, 'r')

            #check for file format with sniffer
            dialect = csv.Sniffer().sniff(self.file.read(1024))
            self.file.seek(0)

            csvfile=csv.reader(self.file,dialect)
            filedata = [] #put contents of csvfile into a list
            filedata.extend(csvfile)
            self.file.seek(0)

            #grab a sample and see if there is a header
            sample=self.file.read(2048)
            self.file.seek(0)
            if csv.Sniffer().has_header(sample): #if there is a header
                colnames=csvfile.next() # label columns from first line
                datalist=[] # create a list without the header
                datalist.extend(filedata[1:len(filedata)]) #append data without header

            else:
                row1=csvfile.next() #if there is NO header
                colnames=[]
                for i in range(len(row1)):
                    colnames.append('col_%d' % i) # label columns as col_1, col_2, etc
                self.file.seek(0)
                datalist=filedata #append data to datalist

            self.file.close()
            self.createGrid(datalist, colnames)


            grid_sizer = wx.BoxSizer(wx.VERTICAL)
            grid_sizer.Add(self.grid, 1, wx.EXPAND)
            self.Right_Panel.SetSizer(grid_sizer)
            self.Right_Panel.Layout()



    #create the grid

    def createGrid(self, datalist, colnames):
        if getattr(self, 'grid', 0): self.grid.Destroy()
        self.grid=wx.grid.Grid(self.Right_Panel, 0)
        self.grid.CreateGrid(len(datalist), len(colnames)) #create grid, same size as file (rows, cols)

        #fill in headings
        for i in range(len(colnames)):
            self.grid.SetColLabelValue(i, colnames[i])

        #populate the grid
        for row in range(len(datalist)):
            for col in range(len(colnames)):
                try: 
                    self.grid.SetCellValue(row,col,datalist[row][col])
                except: 
                    pass


        self.grid.AutoSizeColumns(False) # size columns to data (from cvsomatic.py)
        self.twiddle()

    def twiddle(self): # from http://www.velocityreviews.com/forums/t330788-how-to-update-window-after-wxgrid-is-updated.html
        x,y = self.GetSize()
        self.SetSize((x, y+1))
        self.SetSize((x,y))

    def Exit(self, event):
        if getattr(self, 'file',0):
            self.file.close()
            self.Close(True)

# import wx.lib.mixins.inspection
app = wx.App(0)
Frame_02 = MyFrame(None)
Frame_02.Show()
# wx.lib.inspection.InspectionTool().Show()
app.MainLoop()

感谢您提前抽出时间。

最佳答案

这根本不是一个 wxPython 问题。事实上,您在 wxGrid 中显示 CSV 数据只是实现。您真正想要的是从 CSV 生成的列表中过滤掉空行/列。以下想法可以帮助您入门(但根本没有优化 - 我想展示各个基本步骤,您应该将其作为重新编写原始代码的想法):

# remove the empty row(s):
filedata = [row for row in filedata if not row.strip() and any(field.strip() for field in row)]

# remove the empty col(s):
not_empty_cols = set()
colcount = 0
for row in filedata:
    if colcount > 0 and len(colcount) == len(not_empty_cols):
        # no need to continue, there aren't any empty cols
        break
    if len(row) > 0:
        colcount = len(row)
    for idx, field in enumerate(row):
        if idx in not_empty_cols:
            continue
        if field.strip():
            not_empty_cols.add(idx)
all_cols = set(range(colcount))
empty_cols = sorted(list(all_cols.difference(not_empty_cols)))
for row in filedata:
    for col in empty_cols:
        row.pop(col)

抱歉,我没有测试以上内容。如果它不起作用,请将其视为伪代码。 :)

关于wxGrid,特别是当您的数据变得很大时,您应该研究创建虚拟网格(仅跟踪当前屏幕上的项目,而不是整个数据结构的网格)。

关于python - wxPython:如何免除(放弃)空的 CSV 列和行导入 wxGrid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24338975/

相关文章:

php - 使用 CSV 和 MySQL 时的最小公分母

python - 有没有一种简单的方法可以在 Python 或 wxPython 中捕获所有框架/窗口击键

python - 使用 python 2.7 在 centos 机器上安装 wxPython

Python-删除文本文件中的最后一个字符

python - 使用特定顺序的 ID 列表从 Django 数据库获取记录

Python3 连接被对等方重置

python - 为什么解压后 Python 不能立即识别 CSV 的文件大小?

Python CSV对字段中的数据求平方根

Python pandas to_csv 导致 OSError : [Errno 22] Invalid argument

python - 从 wxPython 中的 wxSlider 实时更新的不可编辑文本框