Python 使用xlwings(pywin32)进行排序

Python 使用xlwings(pywin32)进行排序,python,python-3.x,excel,pywin32,xlwings,Python,Python 3.x,Excel,Pywin32,Xlwings,我需要使用python按给定行对excel电子表格进行排序。对于测试,我使用以下数据(在一个名为xlwings sorting.xlsx的文件中): 其中应分为以下几类: Numbers Letters Letters_2 1 G H 2 F I 3 E N 4 D J 5 C M 6 B K 7 A L 有人会认为这是一项琐碎的任务,但在文档或关于列排序的文档中,似乎没有任何文档(如果有的话,它埋得太深了,以至于两天的阅读都没有发现)

我需要使用python按给定行对excel电子表格进行排序。对于测试,我使用以下数据(在一个名为xlwings sorting.xlsx的文件中):

其中应分为以下几类:

Numbers Letters Letters_2
1   G   H
2   F   I
3   E   N
4   D   J
5   C   M
6   B   K
7   A   L
有人会认为这是一项琐碎的任务,但在文档或关于列排序的文档中,似乎没有任何文档(如果有的话,它埋得太深了,以至于两天的阅读都没有发现)

我能在网上找到的最接近的东西是,它没有答案,只是重定向到一个没有解决方案的github bug线程

尽管如此,我还是根据提问者的回答拼凑出了以下代码:

import xlwings as xw
from xlwings.constants import SortOrder

bk = xw.Book(r'C:\Users\username\Documents\Test Files\xlwings sorting.xlsx')

sht = bk.sheets['Sheet1']

def xl_col_sort(sht,col_num):
    sht.range('a2').api.Sort(sht.range((2,col_num)).api,SortOrder.xlAscending)
    return

xl_col_sort(sht,1)
这可以运行,但我不知道语法是如何工作的。我甚至不知道为什么第一个
range('a2')
调用是必需的,但是如果我尝试直接调用
sht.api.Sort
,它会抛出一个异常。我试着用ipython的直接查看代码??功能,但它只提供了没有docstring的
。然后,我尝试在
Sort()
函数的.py文件中按ctrl+F组合键,但在大量COM包装程序中遇到了死胡同,无法找到包含该函数的实际模块

无论如何,即使我不知道测试用例是如何工作的;因此,下一步是将此函数放入包含excel工作簿和工作表的类中,以将此函数用作方法。我重写了代码,既可以用作方法,也可以采用字符串而不是列号(新列经常添加到工作表的中间,因此数字会经常更改):

我看不出在功能上有什么变化。它仍然接收相同的参数,即使它们经过了一个额外的创建步骤。但是,尝试运行此操作会产生一个
内存错误

In[1]:    metrics.xl_col_sort('Exp. Date')
---------------------------------------------------------------------------
MemoryError                               Traceback (most recent call last)
<ipython-input-3-f1de8b0e8e98> in <module>()
----> 1 metrics.xl_col_sort('Exp. Date')

C:\Users\username\Documents\Projects\PyBev\pyBev_0-3-1\pybev\metricsobj.py in xl_col_sort(self, col)
    146         so = xw.constants.SortOrder
    147 
--> 148         self.sheet.range('a2').api.Sort(self.sheet.range((2,col_num)).api, so.xlAscending)
    149         return
    150     # def monday_backup(self):
C:\Users\username\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\xlwings\main.py in range(self, cell1, cell2)
    818                 raise ValueError("Second range is not on this sheet")
    819             cell2 = cell2.impl
--> 820         return Range(impl=self.impl.range(cell1, cell2))
    821 
    822     @property
C:\Users\username\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\xlwings\_xlwindows.py in range(self, arg1, arg2)
    576             if 0 in arg1:
    577                 raise IndexError("Attempted to access 0-based Range. xlwings/Excel Ranges are 1-based.")
--> 578             xl1 = self.xl.Cells(arg1[0], arg1[1])
    579         elif isinstance(arg1, numbers.Number) and isinstance(arg2, numbers.Number):
    580             xl1 = self.xl.Cells(arg1, arg2)
C:\Users\username\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\xlwings\_xlwindows.py in __call__(self, *args, **kwargs)
    149         for i in range(N_COM_ATTEMPTS + 1):
    150             try:
--> 151                 v = self._inner(*args, **kwargs)
    152                 t = type(v)
    153                 if t is CDispatch:
C:\Users\username\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\win32com\client\dynamic.py in __call__(self, *args)
    190                 if invkind is not None:
    191                         allArgs = (dispid,LCID,invkind,1) + args
--> 192                         return self._get_good_object_(self._oleobj_.Invoke(*allArgs),self._olerepr_.defaultDispatchName,None)
    193                 raise TypeError("This dispatch object does not define a default method")
    194 
MemoryError: CreatingSafeArray
[1]中的
:metrics.xl\u col\u sort('Exp.Date')
---------------------------------------------------------------------------
MemoryError回溯(上次最近调用)
在()
---->1.xl\u col\u排序('Exp.Date')
C:\Users\username\Documents\Projects\PyBev\PyBev\u 0-3-1\PyBev\metricsobj.py in xl\u col\u排序(self,col)
146 so=xw.constants.SortOrder
147
-->148 self.sheet.range('a2').api.Sort(self.sheet.range((2,col_num)).api,so.xl升序)
149返回
150#定义星期一#U备份(自):
C:\Users\username\AppData\Local\enthught\Canopy\edm\envs\User\lib\site packages\xlwings\main.py范围内(self、cell1、cell2)
818提升值错误(“第二个范围不在此表中”)
819 cell2=cell2.impl
-->820返回范围(impl=self.impl.Range(cell1、cell2))
821
822@property
C:\Users\username\AppData\Local\enthught\Canopy\edm\envs\User\lib\site packages\xlwings\u xlwindows.py范围内(self,arg1,arg2)
576如果arg1中为0:
577 raise IndexError(“试图访问基于0的范围。xlwings/Excel范围基于1。”)
-->578 xl1=self.xl.Cells(arg1[0],arg1[1])
579 elif isinstance(arg1,Number.Number)和isinstance(arg2,Number.Number):
580 xl1=self.xl.Cells(arg1,arg2)
C:\Users\username\AppData\Local\enthught\Canopy\edm\envs\User\lib\site packages\xlwings\u xlwindows.py in\uuuuuuuu call\uuuuuu(self,*args,**kwargs)
149适用于范围内的i(N_COM_尝试次数+1):
150试试:
-->151 v=自身内部(*args,**kwargs)
152 t=类型(v)
153如果t是CDispatch:
C:\Users\username\AppData\Local\enthught\Canopy\edm\envs\User\lib\site packages\win32com\client\dynamic.py in\uuuuuuuu调用(self,*args)
190如果invkind不是无:
191 allArgs=(dispid,LCID,invkind,1)+args
-->192返回self.\u get.\u good.\u object.\u(self.\u oleobj.\u调用(*allArgs),self.\u olerepr.\u默认DispatchName,无)
193 raise TypeError(“此分派对象未定义默认方法”)
194
MemoryError:创建安全数组

有人知道这个东西的语法是如何工作的,或者为什么它被放入这个方法时会被破坏吗?

这是一个非常微妙的错误,所以我想我会发布答案,以防有人在一年内用谷歌搜索这个东西试图做类似的事情

简而言之,
sheet.range()
方法只接受整数坐标,表达式为:

col_num = np.where(self.df.columns == col)[0][0] + 2
生成一个浮点数。我无法理解为什么这会产生
MemoryError
而不是语法错误,但可能是疏忽

此外,上述文档中未列出语法,因为它实际上是VBA代码,因为
Sort()
方法仅适用于
Range
对象,因此第一个
sht.Range()
调用要求

最后,如果有人想要一个简化的函数来封装所有这些废话:

import xlwings as xw


bk = xw.Book(file_path)
sheet = bk.sheets['Sheet1'] # or whatever the sheet is named

def xl_col_sort(sheet,col_num):
    sheet.range((2,col_num)).api.Sort(Key1=sheet.range((2,col_num)).api, Order1=1)
return

您好,我使用了您的方法,但结果是按升序排序列而不是按行排序,我能知道这是一个错误还是我遗漏了什么吗?
col_num = np.where(self.df.columns == col)[0][0] + 2
import xlwings as xw


bk = xw.Book(file_path)
sheet = bk.sheets['Sheet1'] # or whatever the sheet is named

def xl_col_sort(sheet,col_num):
    sheet.range((2,col_num)).api.Sort(Key1=sheet.range((2,col_num)).api, Order1=1)
return