Python Excel工具類封裝, 給excel表頭搞點顏色

米洛丶 發表於 2021-11-09
Python Excel

封裝Excel工具類

我們常用的excel工具類,讀有xlrd,寫有xlwt。有讀有寫,新一代庫有pandas,openpyxl等等。

大家用法都差不多,今天博主就介紹新手最愛,我也愛的xlrdxlwt。(不過xlwt似乎最多隻支援65535條資料,此乃一坑)

緣起

老闆給博主安排了一個匯出excel的任務,而這個新專案裡面還尚未編寫此類公共方法,於是就想來一波嘗試。

主要是想把xlwt和xlrd做一個整合,但並不是說要對一個檔案讀和寫,因為應用場景一般是匯入或者匯出

封裝ExcelHelper類

讀資料

我們需要先接受一個filename(檔案的全路徑),初始化helper物件,所以我們可以順手寫出這樣的程式碼:

class ExcelHelper(object):
    def __init__(self, filename):
        self.filename = filename

接著我們編寫xlrd的部分,雖然網上的例子一大把,但是有特色的還是少。我決定支援讀陣列,也支援讀json陣列。

啥子是json陣列,因為我們excel一般都是表頭+表資料組成,如果光給一條資料,你不知道他屬於哪一列,那還得往上找它的表頭,和之對應起來。

比如我們經常讀出的資料是:

data = [
   ['姓名', '電話'],
   ['三毛', '17800000000']
]

當列的資料比較多的時候,我們給你一個三毛,你知道它的表頭是姓名嗎?還是小名?

如果是這樣的資料呢?

data = [
   {"姓名": "三毛", "電話": "17800000000"}
]

兩種資料,不同的展示方式,其實內容相差無幾。

  • 編寫read_data方法
    def read_data(self):
        """
        獲取資料,不區分表頭
        :return:
        """
        book = xlrd.open_workbook(self.filename)
        sheets = book.sheets()
        for s in sheets:
            yield (s.row_values(i) for i in range(s.nrows))

這邊用了yield關鍵字,之所以不用list,還是考慮到資料表資料如果很多,那麼全部放到list,會佔用很大記憶體空間,所以用了yield節省記憶體空間

這裡如果有疑問,大家可以查下生成器相關資料。

  • 編寫read_json相關方法
    @staticmethod
    def read_json_item(sheet):
        """
        獲取json資料
        :param sheet:
        :return:
        """
        if sheet.nrows <= 1:
            return (sheet.row_values(i) for i in range(sheet.nrows))
        # 否則說明資料大於1行
        header = sheet.row_values(0)
        for i in range(1, sheet.nrows):
            row_data = dict()
            for j in range(sheet.ncols):
                row_data[header[j]] = sheet.cell_value(i, j)
            yield row_data

    def read_json_data(self):
        """
        獲取List[dict]資料,也就是JSON陣列
        :return:
        """
        book = xlrd.open_workbook(self.filename)
        sheets = book.sheets()
        for st in sheets:
            yield ExcelHelper.read_json_item(st)

比較常規,excel可能會有多個sheet,所以我們遍歷sheets。接著去每個sheet中拿到每行資料,由於要求json陣列模式,所以我們需要判斷下行數。

如果就1行,那就最多一個表頭,沒啥意義,所以我們直接切換到原生模式,一行一行讀資料。

寫資料

寫資料的demo比較簡單,考慮到傳入json陣列的時候,萬一有小可愛傳這樣的資料,其實我們是不太好支援的:

a = [
 {"名字": "張三", "稱號": "法外狂徒"},
 {"性格": "悶騷", "稱號": "秒殺光環"}
]

可以看到2條資料對不上~所以不打算支援這樣的資料。

  • 編寫write_data方法

    我們知道,表頭是個很重要的資料,我們要讓她與眾不同一點,所以我們可以設定下它的樣式。

    @staticmethod
    def get_style():
        style = xlwt.XFStyle()
        pattern = xlwt.Pattern()
        pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        pattern.pattern_fore_colour = xlwt.Style.colour_map['sky_blue']
        style.pattern = pattern
        return style

建立style,設定背景色為純潔的天藍色,最後返回style。

這個style有什麼用呢,我們在寫入資料的時候可以指定單元格的樣式。

接著編寫write方法:

    def write_excel_data(self, header, row_data, sheet_name="sheet1"):
        wb = xlwt.Workbook()
        ws = wb.add_sheet(sheet_name)
        # 寫入表頭
        for i, h in enumerate(header):
            ws.write(0, i, h, self.style)
        # 寫入資料
        for line, row in enumerate(row_data):
            for c, item in enumerate(row):
                ws.write(line + 1, c, str(item))
        wb.save(self.filename)

接受引數是表頭(陣列),row_data(二維陣列),寫入完畢後呼叫save方法。

如果有需要對多個sheet寫入,請自行改造。

本節總體來說,只是寫了一個excel的讀寫方法,亮點在於讀json陣列表頭搞顏色

顏色你們可以隨便定哈

下次聊聊FastApi下載檔案以及刪除下載後的檔案。


完整程式碼如下(其實是給我自己備份):

import xlrd
import xlwt


class ExcelHelper(object):
    def __init__(self, filename):
        self.filename = filename
        self.style = ExcelHelper.get_style()

    @staticmethod
    def get_style():
        style = xlwt.XFStyle()
        pattern = xlwt.Pattern()
        pattern.pattern = xlwt.Pattern.SOLID_PATTERN
        pattern.pattern_fore_colour = xlwt.Style.colour_map['sky_blue']
        style.pattern = pattern
        return style

    def read_data(self):
        """
        獲取資料,不區分表頭
        :return:
        """
        book = xlrd.open_workbook(self.filename)
        sheets = book.sheets()
        for s in sheets:
            yield (s.row_values(i) for i in range(s.nrows))

    @staticmethod
    def read_json_item(sheet):
        """
        獲取json資料
        :param sheet:
        :return:
        """
        if sheet.nrows <= 1:
            return (sheet.row_values(i) for i in range(sheet.nrows))
        # 否則說明資料大於1行
        header = sheet.row_values(0)
        for i in range(1, sheet.nrows):
            row_data = dict()
            for j in range(sheet.ncols):
                row_data[header[j]] = sheet.cell_value(i, j)
            yield row_data

    def read_json_data(self):
        """
        獲取List[dict]資料,也就是JSON陣列
        :return:
        """
        book = xlrd.open_workbook(self.filename)
        sheets = book.sheets()
        for st in sheets:
            yield ExcelHelper.read_json_item(st)

    def write_excel_data(self, header, row_data, sheet_name="sheet1"):
        wb = xlwt.Workbook()
        ws = wb.add_sheet(sheet_name)
        # 寫入表頭
        for i, h in enumerate(header):
            ws.write(0, i, h, self.style)
        # 寫入資料
        for line, row in enumerate(row_data):
            for c, item in enumerate(row):
                ws.write(line + 1, c, str(item))
        wb.save(self.filename)