簡體   English   中英

使用 xlwings (pywin32) 排序

[英]Sorting with xlwings (pywin32)

我需要使用 python 按給定行對 Excel 電子表格進行排序。 為了測試,我使用了這個數據(在一個名為 xlwings sorting.xlsx 的文件中):

Numbers Letters Letters_2
7   A   L
6   B   K
5   C   M
4   D   J
3   E   N
2   F   I
1   G   H

應該歸類為:

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

有人會認為這是一項微不足道的任務,但在xlwings文檔或pywin32關於列排序的那些。

我在網上任何地方都能找到的最接近的東西是這個問題,它沒有答案,只是重定向到一個沒有解決方案的 github 錯誤線程。

盡管如此,我還是設法根據提問者的代碼拼湊了以下代碼:

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 的 ?? 功能,但它只是給了我<xlwings._xlwindows.COMRetryObjectWrapper object at 0x0000001375A459E8>沒有文檔字符串。 然后,我嘗試通過Sort()函數的 .py 文件實際使用 ctrl+F,但在大量 COM 包裝器列表中遇到了死胡同,無法追蹤包含該函數的實際模塊。

無論如何,即使我不知道測試用例是如何工作的; 所以下一步是將此函數放入一個包含excel工作簿和工作表的類中,以將該函數用作方法。 我重寫了代碼以用作方法並使用字符串而不是列號(新列經常添加到工作表的中間,因此數字會經常更改):

class Metrics:

    # self.sheet is a sheet object based on self.book opened with xlwings
    # a bunch of other methods and attributes

    def xl_col_sort(self,col):

        # +2 because excel starts at 1 (+1) and the dataframe self.df
        # uses a data column as the index (+1)
        col_num = np.where(self.df.columns == col)[0][0] + 2

        so = xw.constants.SortOrder

        self.sheet.range('a2').api.Sort(self.sheet.range((2,col_num)).api, so.xlAscending)
        return

我看不出這里有任何功能上的變化。 它仍然收到相同的參數,即使它們經過一個額外的步驟來創建。 然而嘗試運行它會產生MemoryError

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

有誰知道這個東西的語法是如何工作的,或者為什么它在放入方法中時會中斷?

結果證明這是一個非常微妙的錯誤,所以我想我會發布答案,以防有人在一年內用谷歌搜索嘗試做類似的事情。

簡而言之, sheet.range()方法只接受整數坐標,表達式:

col_num = np.where(self.df.columns == col)[0][0] + 2

產生一個浮點數。 為什么這會產生MemoryError而不是語法錯誤,這超出了我的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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM