PyQt:如何对 excel 文件的 QTableView 列进行排序(字符串和数字以及日期类型)
PyQt: How to sort QTableView columns of a excel file(strings and numericals and datetype)
这是以下问题的后续问题:
现在我打算对 excel 个文件进行相同的排序
这是我的代码:
self.Upload = QtGui.QPushButton()
self.Upload.clicked.connect(self.showOpenDialog)
self.Table = QtGui.QPushButton()
self.table.clicked.connect(self.LoadTable)
def showOpenDialog(self):
fileName = QtGui.QFileDialog.getOpenFileName(self, 'Open file', '/home')
if (".xls" or ".xml" or ".xlsx" or ".xlsm") in fileName:
with open(fileName, 'rb') as drate:
self.Datas = pd.read_excel(drate, index_col=0)
self.Loaded_File.clear()
self.Loaded_File.append(fileName)
colll = self.Datas.dtypes.index
col_names = np.array(colll)
def LoadTable(self):
tab_table_view = QtGui.QWidget()
self.Tab.insertTab(0, tab_table_view, self.File_Name)
self.tableView = QtGui.QTableView(tab_table_view)
self.tableView.setGeometry(QtCore.QRect(0, 0, 721, 571))
self.model = QtGui.QStandardItemModel(self)
file_name_temp = self.File_Name
self.tableView.setModel(self.model)
colll = self.Datas.dtypes.index
col_names = np.array(colll)
col_names = np.insert(col_names, 0, self.Datas.index.name)
self.model.setHorizontalHeaderLabels(col_names)
self.tableView.hideRow(0)
self.tableView.setSortingEnabled(True)
if (".xls" or ".xml" or ".xlsx" or ".xlsm") in self.File_Name:
from itertools import chain
ii = 1
book = xlrd.open_workbook(self.File_Name)
sheet = book.sheet_by_index(0)
num_col = len(self.Datas.columns)
num_row = len(self.Datas)
print(num_col,num_row)
self.Matrix = [[0 for x in range(num_col+1)] for y in range(num_row)]
for i in range(num_row):
self.Matrix[i][0]=self.Datas.index.values[i]
for j in range(num_col):
self.Matrix[i][j+1] = self.Datas.iat[i,j]
print(self.Matrix)
for i in range(num_row):
items = []
for j in range(num_col):
field = self.Matrix[i][j]
item = QtGui.QStandardItem(field)
for numtype in (int, float):
try:
data = numtype(field)
break
except (ValueError, OverflowError):
pass
else:
print('Not a number: %r' % field)
data = field
item.setData(data, QtCore.Qt.UserRole)
items.append(item)
self.model.appendRow(items)
输出将是:
Not a number: 'Government'
Not a number: 'Canada'
Not a number: 'Carretera'
Not a number: 'None'
Traceback (most recent call last):
File "Main_File.py", line 1535, in loadTable
item = QtGui.QStandardItem(field)
TypeError: arguments did not match any overloaded call:
QStandardItem(): too many arguments
QStandardItem(str): argument 1 has unexpected type 'Timestamp'
QStandardItem(QIcon, str): argument 1 has unexpected type 'Timestamp'
QStandardItem(int, int columns=1): argument 1 has unexpected type 'Timestamp'
QStandardItem(QStandardItem): argument 1 has unexpected type 'Timestamp'
如果文件中的数据类型为 str(最多 "None")并且当第一个 int 或 float 出现时它会生成一些重载调用,这很好。
请有人帮助我。
下面是一个演示脚本,它可以读取 csv 和 excel 文件,并且应该正确地对日期、整数、浮点数和字符串进行排序。
import sys
import pandas as pd, numpy as np
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.model = QtGui.QStandardItemModel(self)
self.model.setSortRole(QtCore.Qt.UserRole)
self.tableView = QtGui.QTableView()
self.tableView.setSortingEnabled(True)
self.tableView.setModel(self.model)
self.button = QtGui.QPushButton('Open CSV', self)
self.button.clicked.connect(self.handleButton)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.tableView)
layout.addWidget(self.button)
def handleButton(self):
filters = (
'CSV files (*.csv *.txt)',
'Excel Files (*.xls *.xml *.xlsx *.xlsm)',
)
path, filter = QtGui.QFileDialog.getOpenFileNameAndFilter(
self, 'Open File', '', ';;'.join(filters))
if path:
csv = filter.startswith('CSV')
if csv:
dataframe = pd.read_csv(path)
else:
dataframe = pd.read_excel(path)
self.model.setRowCount(0)
dateformat = '%m/%d/%Y'
rows, columns = dataframe.shape
for row in range(rows):
items = []
for column in range(columns):
field = dataframe.iat[row, column]
if csv and isinstance(field, str):
try:
field = pd.to_datetime(field, format=dateformat)
except ValueError:
pass
if isinstance(field, pd.tslib.Timestamp):
text = field.strftime(dateformat)
data = field.timestamp()
else:
text = str(field)
if isinstance(field, np.number):
data = field.item()
else:
data = text
item = QtGui.QStandardItem(text)
item.setData(data, QtCore.Qt.UserRole)
items.append(item)
self.model.appendRow(items)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 150, 600, 400)
window.show()
sys.exit(app.exec_())
正如 Ekhumoro 所建议的,Excel 数据的排序最容易用 Pandas 完成。我用openpyxl试过类似的操作,但是太局限了。 Pandas 可以为您节省很多行代码。
一个小例子:
from PyQt4 import QtGui , QtCore
import pandas as pd
import numpy as np
import time
import sys
# open excel file
sales = pd.read_excel ("Sales.xlsx" , parse_dates=['Data'] )
# select columns
purchase_patterns = sales [['Total','Date']]
# choose date index
purchase_patterns = purchase_patterns.set_index("Date")
# regroup / resample by week and get subtotals by sum
resample = purchase_patterns.resample ('W' , how = sum)
这里有一些不错的链接:
这是以下问题的后续问题:
现在我打算对 excel 个文件进行相同的排序
这是我的代码:
self.Upload = QtGui.QPushButton()
self.Upload.clicked.connect(self.showOpenDialog)
self.Table = QtGui.QPushButton()
self.table.clicked.connect(self.LoadTable)
def showOpenDialog(self):
fileName = QtGui.QFileDialog.getOpenFileName(self, 'Open file', '/home')
if (".xls" or ".xml" or ".xlsx" or ".xlsm") in fileName:
with open(fileName, 'rb') as drate:
self.Datas = pd.read_excel(drate, index_col=0)
self.Loaded_File.clear()
self.Loaded_File.append(fileName)
colll = self.Datas.dtypes.index
col_names = np.array(colll)
def LoadTable(self):
tab_table_view = QtGui.QWidget()
self.Tab.insertTab(0, tab_table_view, self.File_Name)
self.tableView = QtGui.QTableView(tab_table_view)
self.tableView.setGeometry(QtCore.QRect(0, 0, 721, 571))
self.model = QtGui.QStandardItemModel(self)
file_name_temp = self.File_Name
self.tableView.setModel(self.model)
colll = self.Datas.dtypes.index
col_names = np.array(colll)
col_names = np.insert(col_names, 0, self.Datas.index.name)
self.model.setHorizontalHeaderLabels(col_names)
self.tableView.hideRow(0)
self.tableView.setSortingEnabled(True)
if (".xls" or ".xml" or ".xlsx" or ".xlsm") in self.File_Name:
from itertools import chain
ii = 1
book = xlrd.open_workbook(self.File_Name)
sheet = book.sheet_by_index(0)
num_col = len(self.Datas.columns)
num_row = len(self.Datas)
print(num_col,num_row)
self.Matrix = [[0 for x in range(num_col+1)] for y in range(num_row)]
for i in range(num_row):
self.Matrix[i][0]=self.Datas.index.values[i]
for j in range(num_col):
self.Matrix[i][j+1] = self.Datas.iat[i,j]
print(self.Matrix)
for i in range(num_row):
items = []
for j in range(num_col):
field = self.Matrix[i][j]
item = QtGui.QStandardItem(field)
for numtype in (int, float):
try:
data = numtype(field)
break
except (ValueError, OverflowError):
pass
else:
print('Not a number: %r' % field)
data = field
item.setData(data, QtCore.Qt.UserRole)
items.append(item)
self.model.appendRow(items)
输出将是:
Not a number: 'Government'
Not a number: 'Canada'
Not a number: 'Carretera'
Not a number: 'None'
Traceback (most recent call last):
File "Main_File.py", line 1535, in loadTable
item = QtGui.QStandardItem(field)
TypeError: arguments did not match any overloaded call:
QStandardItem(): too many arguments
QStandardItem(str): argument 1 has unexpected type 'Timestamp'
QStandardItem(QIcon, str): argument 1 has unexpected type 'Timestamp'
QStandardItem(int, int columns=1): argument 1 has unexpected type 'Timestamp'
QStandardItem(QStandardItem): argument 1 has unexpected type 'Timestamp'
如果文件中的数据类型为 str(最多 "None")并且当第一个 int 或 float 出现时它会生成一些重载调用,这很好。
请有人帮助我。
下面是一个演示脚本,它可以读取 csv 和 excel 文件,并且应该正确地对日期、整数、浮点数和字符串进行排序。
import sys
import pandas as pd, numpy as np
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.model = QtGui.QStandardItemModel(self)
self.model.setSortRole(QtCore.Qt.UserRole)
self.tableView = QtGui.QTableView()
self.tableView.setSortingEnabled(True)
self.tableView.setModel(self.model)
self.button = QtGui.QPushButton('Open CSV', self)
self.button.clicked.connect(self.handleButton)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.tableView)
layout.addWidget(self.button)
def handleButton(self):
filters = (
'CSV files (*.csv *.txt)',
'Excel Files (*.xls *.xml *.xlsx *.xlsm)',
)
path, filter = QtGui.QFileDialog.getOpenFileNameAndFilter(
self, 'Open File', '', ';;'.join(filters))
if path:
csv = filter.startswith('CSV')
if csv:
dataframe = pd.read_csv(path)
else:
dataframe = pd.read_excel(path)
self.model.setRowCount(0)
dateformat = '%m/%d/%Y'
rows, columns = dataframe.shape
for row in range(rows):
items = []
for column in range(columns):
field = dataframe.iat[row, column]
if csv and isinstance(field, str):
try:
field = pd.to_datetime(field, format=dateformat)
except ValueError:
pass
if isinstance(field, pd.tslib.Timestamp):
text = field.strftime(dateformat)
data = field.timestamp()
else:
text = str(field)
if isinstance(field, np.number):
data = field.item()
else:
data = text
item = QtGui.QStandardItem(text)
item.setData(data, QtCore.Qt.UserRole)
items.append(item)
self.model.appendRow(items)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 150, 600, 400)
window.show()
sys.exit(app.exec_())
正如 Ekhumoro 所建议的,Excel 数据的排序最容易用 Pandas 完成。我用openpyxl试过类似的操作,但是太局限了。 Pandas 可以为您节省很多行代码。
一个小例子:
from PyQt4 import QtGui , QtCore
import pandas as pd
import numpy as np
import time
import sys
# open excel file
sales = pd.read_excel ("Sales.xlsx" , parse_dates=['Data'] )
# select columns
purchase_patterns = sales [['Total','Date']]
# choose date index
purchase_patterns = purchase_patterns.set_index("Date")
# regroup / resample by week and get subtotals by sum
resample = purchase_patterns.resample ('W' , how = sum)
这里有一些不错的链接: