openpyxl处理excel封装

from openpyxl import load_workbook
from openpyxl.styles import Font
from openpyxl.styles.colors import BLACK


class ParseExcel(object):
    """解析excel文件"""

    def __init__(self, filename, sheet_name=''):
        """
        excel读取和写入
        :param filename:
        :param sheet_name:
        """
        try:
            self.sheet_name = sheet_name
            self.filename = filename
            self.__wb = load_workbook(self.filename)  # 打开excel
        except FileNotFoundError as e:
            self.__wb = Workbook()

    def get_max_row_num(self):
        """获取最大行号"""
        ws = self.get_ws_by_sheet()
        max_row_num = ws.max_row
        return max_row_num

       def get_max_column_num(self):
        """获取最大列号"""
        ws = self.get_ws_by_sheet()
        max_column = ws.max_column
        return max_column  

    def get_head(self):
        """
        获取表头
        :return:
        """
        ws = self.get_ws_by_sheet()
        head = next(ws.iter_rows(max_row=1, values_only=True))
        return head

    def get_cell_value(self, coordinate=None, row=None, column=None):
        ws = self.get_ws_by_sheet()
        """获取指定单元格的数据"""
        if coordinate is not None:
            try:
                return ws[coordinate].value
            except Exception as e:
                raise e
        elif coordinate is None and row is not None and column is not None:
            if isinstance(row, int) and isinstance(column, int):
                return ws.cell(row=row, column=column).value
            else:
                raise TypeError('row and column must be type int')
        else:
            raise Exception("Insufficient Coordinate of cell!")

    def get_row_value(self, row):
        """获取某一行的数据"""
        ws = self.get_ws_by_sheet()
        col_num = self.get_max_column_num()
        row_value = []
        if isinstance(row, int):
            for col in range(1, col_num + 1):
                values_row = ws.cell(row, col).value
                row_value.append(values_row)
            return row_value
        else:
            raise TypeError('row must be type int')

    def get_column_value(self, column):
        """获取某一列数据"""
        ws = self.get_ws_by_sheet()
        row_num = self.get_max_row_num()
        column_value = []
        if isinstance(column, int):
            for row in range(1, row_num + 1):
                values_column = ws.cell(row, column).value
                column_value.append(values_column)
            return column_value
        else:
            raise TypeError('column must be type int')

    def get_all_value(self, exclude_head=True):
        """
        获取指定表单的所有数据
        :param exclude_head:是否去掉表头
        :return:
        """
        ws = self.get_ws_by_sheet()
        min_row = 2 if exclude_head else 1
        row = ws.iter_rows(min_row=min_row, max_row=ws.max_row, values_only=True)
        values = []
        for row_tuple in row:
            if self.is_row_none(row_tuple):
                continue
            value_list = []
            for value in row_tuple:
                value_list.append(value)
            values.append(value_list)
        return values

    def is_row_none(self, row):
        """
        判断当前行是否全为None
        :param row:
        :return:
        """
        return not list(filter(None, row))

    def get_excel_title(self):
        """获取sheet表头"""
        ws = self.get_ws_by_sheet()
        title_key = tuple(ws.iter_rows(max_row=1, values_only=True))[0]
        return title_key

    def get_list_dict_all_value(self, exclude_head=True):
        """
        返回字典列表
        :param exclude_head:是否去掉表头
        :return:
        """
        head = self.get_head()
        all_values = self.get_all_value(exclude_head)
        value_list = []
        for value in all_values:
            value_list.append(dict(zip(head, value)))
        return value_list

    def write_cell_excel(self, row, column, value='', bold=True, color=BLACK):
        if isinstance(row, int) and isinstance(column, int):
            ws = self.get_ws_by_sheet()
            cell = ws.cell(row, column)
            cell.font = Font(color=color, bold=bold)
            cell.value = value
        else:
            raise TypeError('row and column must be type int')

    def get_ws_by_sheet(self):
        if self.sheet_name:
            ws = self.__wb[self.sheet_name]
        else:
            ws = self.__wb[self.__wb.sheetnames[0]]
        return ws

    def write_cell(self, row, column, value=None, bold=True, color=BLACK):
        ws = self.get_ws_by_sheet()
        if isinstance(row, int) and isinstance(column, int):
            try:
                cell_obj = ws.cell(row, column)
                cell_obj.font = Font(color=color, bold=bold)
                cell_obj.value = value
                self.__wb.save(self.filename)
            except Exception as e:
                raise e
        else:
            raise TypeError('row and column must be type int')
            
            
    def save_excel_io(self):
        """
        文件写入流
        :return:
        """
        xlsx_file = io.BytesIO()
        self.__wb.save(xlsx_file)
        return xlsx_file
        
    def auto_alignment(self, row, col):
        """
        自动换行
        :param row:
        :param col:
        :return:
        """
        ws = self.get_ws_by_sheet()
        ws.cell(row, col).alignment = Alignment(wrapText=True)
        
    def adjust_col_alignment(self, col):
        """
        自适应列宽
        :param col:
        :return:
        """
        max_length = 0
        ws = self.get_ws_by_sheet()
        for cell in ws[get_column_letter(col)]:
            length = 0
            for char in str(cell.value):
                if ord(char) > 255:
                    # 中文长度自增2
                    length += 2
                else:
                    length += 1.2
            if length > max_length:
                max_length = length
        # 调整列宽
        ws.column_dimensions[get_column_letter(col)].width = max_length

测试用例

from django.test import TestCase

from home_application.bo.excel import ParseExcel


class ModelTest(TestCase):
    # @unittest.skip
    def test_excel(self):
        from config import BASE_DIR
        file_name = BASE_DIR + '/home_application/demo.xlsx'
        pe = ParseExcel(file_name)
        column_row = pe.get_max_column_num()
        print('最大列号:', column_row)
        max_row = pe.get_max_row_num()
        print('最大行号:', max_row)
        cell_value_1 = pe.get_cell_value(row=2, column=3)
        print('第%d行, 第%d列的数据为: %s' % (2, 3, cell_value_1))
        cell_value_2 = pe.get_cell_value(coordinate='A5')  # coordinate单元格名称
        print('A5单元格的数据为: {}'.format(cell_value_2))
        value_row = pe.get_row_value(3)
        print('第{}行的数据为:{}'.format(3, value_row))
        value_column = pe.get_column_value(2)
        print('第{}列的数据为:{}'.format(2, value_column))
        values_1 = pe.get_all_value()
        print('获取所有数据\n', values_1)
        title = pe.get_excel_title()  # 显示所有的title
        print('表头为\n{}'.format(title))
        dict_value = pe.get_list_dict_all_value()
        print('所有数据组成的嵌套字典的列表:\n', dict_value)
        pe.write_cell(1, 2, '选择题')  # 更换excel中的title

运行结果
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值