|
| 1 | +#!/usr/bin/python |
| 2 | +# -*- coding: UTF-8 -*- |
| 3 | + |
| 4 | +import re |
| 5 | +from openpyxl import load_workbook |
| 6 | +from openpyxl.cell import MergedCell |
| 7 | + |
| 8 | + |
| 9 | +class to_html(): |
| 10 | + def __init__(self, file, save_file, sheet_name): |
| 11 | + self.file = file # 文件路径 |
| 12 | + self.save_file = save_file # html保存路径 |
| 13 | + self.sheet_name = sheet_name # sheet名 |
| 14 | + |
| 15 | + def creat_html(self): |
| 16 | + wb = load_workbook(filename=self.file) |
| 17 | + sheet = wb[self.sheet_name] |
| 18 | + cell_dic = {} # 用于储存 所有合并单元格的左上单元格对象 |
| 19 | + col_width = {} # 用于储存 所有列的列宽,px |
| 20 | + row_height = {} # 用于储存 所有列的行高,px |
| 21 | + # 查询列宽 |
| 22 | + for col in sheet.columns: |
| 23 | + pat = r"[A-Z]+" |
| 24 | + pat = re.compile(pat) |
| 25 | + colname = pat.findall(col[0].coordinate)[0] # 分离字母 和数字,取出列字母名称 |
| 26 | + px = round(sheet.column_dimensions[colname].width * 5) # 读出列宽换算为像素 |
| 27 | + col_width[colname] = px |
| 28 | + # 查询行高 |
| 29 | + for row in sheet.rows: |
| 30 | + pat = r"[A-Z]+(\d+)" |
| 31 | + pat = re.compile(pat) |
| 32 | + rowid = int(pat.findall(row[0].coordinate)[0]) # 分离字母 和数字,取出行数字序号 |
| 33 | + px = sheet.row_dimensions[rowid].height # 读出行高换算为像素 |
| 34 | + if px == None: |
| 35 | + px = 13.5 |
| 36 | + row_height[str(rowid)] = px |
| 37 | + |
| 38 | + # 找出所有合并区域的行高,列宽,向右合并距离,向下合并距离 |
| 39 | + for merged_range in sheet.merged_cells.ranges: |
| 40 | + now_width = 0 # 定义列宽 |
| 41 | + now_height = 0 # 定义行高 |
| 42 | + for i in range(merged_range.min_col, merged_range.max_col + 1): |
| 43 | + coord = sheet.cell(row=1, column=i).coordinate # 位置标识,例如:A1 |
| 44 | + pat = r"[A-Z]+" |
| 45 | + pat = re.compile(pat) |
| 46 | + colname = pat.findall(coord)[0] # 分离字母 和数字,取出列字母名称 |
| 47 | + now_width = now_width + col_width[colname] |
| 48 | + for i in range(merged_range.min_row, merged_range.max_row + 1): |
| 49 | + coord = sheet.cell(row=i, column=1).coordinate # 位置标识,例如:A1 |
| 50 | + pat = r"[A-Z]+(\d+)" |
| 51 | + pat = re.compile(pat) |
| 52 | + colindex = pat.findall(coord)[0] # 分离字母 和数字,取出列数字名称 |
| 53 | + now_height = now_height + row_height[colindex] |
| 54 | + |
| 55 | + now_width = int(now_width) # 合并单元格列宽(所有子单元格相加) |
| 56 | + now_height = int(now_height) # 合并单元格行高(所有子单元格相加) |
| 57 | + |
| 58 | + cell = sheet.cell(row=merged_range.min_row, column=merged_range.min_col) # 选择合并区域左上单元格 |
| 59 | + colspan = merged_range.max_col - merged_range.min_col + 1 # 向右合并长度 |
| 60 | + rowspan = merged_range.max_row - merged_range.min_row + 1 # 向下合并长度 |
| 61 | + cell_dic[cell] = (now_height, now_width, colspan, rowspan) |
| 62 | + |
| 63 | + html = '''<table border="1">''' |
| 64 | + # 开始写入数据到table标签 |
| 65 | + for row in sheet.rows: |
| 66 | + tr = '''<tr>''' |
| 67 | + for cell in row: |
| 68 | + td = "" |
| 69 | + if cell in cell_dic: # 判断是否为合并单元格左上单元格 |
| 70 | + if cell.value == None: |
| 71 | + text = '' |
| 72 | + else: |
| 73 | + text = cell.value |
| 74 | + |
| 75 | + if cell.alignment.vertical != None: |
| 76 | + vertical = f'''vertical-align: {cell.alignment.vertical};''' # 水平位置 |
| 77 | + else: |
| 78 | + vertical = '' |
| 79 | + if cell.alignment.horizontal != None: |
| 80 | + horizontal = f'''text-align: {cell.alignment.horizontal};''' # 垂直位置 |
| 81 | + else: |
| 82 | + horizontal = '' |
| 83 | + |
| 84 | + font_size = str(int(cell.font.size) + 3) # 字体大小 |
| 85 | + font_weight = '700' if cell.font.b else '400' # 字体是否加粗 |
| 86 | + style = f'''"color: rgb(0, 0, 0); font-size: {font_size}px; font-weight: {font_weight}; font-style: normal;{vertical}{horizontal}"''' |
| 87 | + td = f'''<td height="{cell_dic[cell][0]}" width="{cell_dic[cell][1]}" colspan="{cell_dic[cell][2]}" rowspan="{cell_dic[cell][3]}">{text}</td>''' |
| 88 | + else: |
| 89 | + if not isinstance(cell, MergedCell): # 判断该单元格是否为合并单元格 |
| 90 | + if cell.alignment.vertical != None: |
| 91 | + vertical = f'''vertical-align: {cell.alignment.vertical};''' # 水平位置 |
| 92 | + else: |
| 93 | + vertical = '' |
| 94 | + if cell.alignment.horizontal != None: |
| 95 | + horizontal = f'''text-align: {cell.alignment.horizontal};''' # 垂直位置 |
| 96 | + else: |
| 97 | + horizontal = '' |
| 98 | + pat = r"([A-Z]+)(\d+)" |
| 99 | + pat = re.compile(pat) |
| 100 | + cell_name = pat.findall(cell.coordinate)[0][0] |
| 101 | + cell_index = pat.findall(cell.coordinate)[0][1] |
| 102 | + font_size = str(int(cell.font.size) + 3) # 字体大小 |
| 103 | + font_weight = '700' if cell.font.b else '400' # 字体是否加粗 |
| 104 | + style = f'''"color: rgb(0, 0, 0); font-size: {font_size}px; font-weight: {font_weight}; font-style: normal;{vertical}{horizontal}"''' |
| 105 | + if cell.value != None: |
| 106 | + td = f'''<td height="{row_height[cell_index]}" width="{col_width[cell_name]}">{cell.value}</td>''' |
| 107 | + else: |
| 108 | + td = f'''<td height="{row_height[cell_index]}" width="{col_width[cell_name]}"></td>''' |
| 109 | + tr = tr + td |
| 110 | + |
| 111 | + tr = tr + '''</tr>''' |
| 112 | + html = html + tr |
| 113 | + |
| 114 | + html = html + '''</table>''' |
| 115 | + with open(self.save_file, 'w', encoding='utf-8') as f: |
| 116 | + f.write(html) |
| 117 | + |
| 118 | + |
| 119 | +if __name__ == '__main__': |
| 120 | + data = to_html("E:\\test.xlsx", "E:\\test.html", "4612236756") |
| 121 | + data.creat_html() |
0 commit comments