写了一个函数,基本的需求是把一个表格中的有用的部分转换成图片。自然想到了USED_RANGE,这个在VBA中很常见,但是有个问题,表格中不单纯的只是有文字就叫USED_RANGE,单元格的大小、字体、格式等等修过都都叫USED_RANGE,这样一来,用传统的方法直接COPY到剪切板,再把图片导出来的方法,很容易导致图片有大量的空白边框,很恶心。如果放到网页中直接使用就很难看。因此经历了一下午的研究,借助GPT的智慧写下了以下代码:
def xlsx_to_png(xlsx_name):
pythoncom.CoInitialize()
app = xw.App(visible=True, add_book=False)
try:
file_path = os.path.abspath(xlsx_name)
wb = app.books.open(file_path)
sheet = wb.sheets[0]
used_range = sheet.used_range
# 遍历列,检查一整列是否都是空单元格
empty_columns = []
for column in range(1, used_range.columns.count + 1):
is_empty_column = True
for row in range(used_range.row, used_range.last_cell.row + 1):
cell_value = sheet.cells(row, column).value
if cell_value is not None and str(cell_value).strip():
is_empty_column = False
break
if is_empty_column:
empty_columns.append(column)
# 遍历行,检查一整行是否都是空单元格
empty_rows = []
for row in range(used_range.row, used_range.last_cell.row + 1):
is_empty_row = True
for column in range(used_range.column, used_range.last_cell.column + 1):
cell_value = sheet.cells(row, column).value
if cell_value is not None and str(cell_value).strip():
is_empty_row = False
break
if is_empty_row:
empty_rows.append(row)
# 剔除空列和空行
first_row = used_range.row
last_row = used_range.last_cell.row
first_column = used_range.column
last_column = used_range.last_cell.column
for row in empty_rows:
if row <= last_row:
first_row += 1
else:
last_row -= 1
for column in empty_columns:
if column <= last_column:
first_column += 1
else:
last_column -= 1
used_range = sheet.range((first_row, first_column),
(last_row, last_column))
used_range.api.CopyPicture() # 复制图片区域
sheet.api.Paste() # 粘贴
pic = sheet.pictures[-1] # 当前图片
pic.api.Copy() # 复制图片
time.sleep(3) # 延迟一下操作,不然获取不到图片
img = ImageGrab.grabclipboard()
new_img = Image.new('RGB', img.size, (255, 255, 255)) # 创建新的 RGB 模式图像,并填充为白色
new_img.paste(img, mask=img.split()[3]) # 将剪贴板中的图像粘贴到新图像上,保留原始图像的透明度通道
test_pn= '../filestorage/test.png'
new_img.save(test_pn) # 保存图片
pic.delete() # 删除sheet上的图片
wb.close() # 不保存,直接关闭
app.quit() # 退出xlwings的app启动
pythoncom.CoUninitialize() # 关闭多线程
return 'success'
except Exception as e:
app.quit()
pythoncom.CoUninitialize() # 关闭多线程
return str(e)
GPT在总结算出empty_rows和empty_columns以后就开始各种犯混,又是清除格式又是删除行列,总之都不对,最后给了我这么一段代码
for row in empty_rows:
if row <= last_row:
last_row -= 1
for column in empty_columns:
if column <= last_column:
last_column -= 1
used_range = sheet.range((first_row, first_column), (last_row, last_column))
这段代码让我突然有了灵感,就写出了正确结果。
for row in empty_rows:
if row <= last_row:
first_row += 1
else:
last_row -= 1
for column in empty_columns:
if column <= last_column:
first_column += 1
else:
last_column -= 1
当空的那行比整个used_range小,说明空的在used_range上方,新used_range的第一行就要加1个;当空的那行比整个used_range大,说明空的在used_range下方,新的used_range的最后一行就要减1个。列也是同理。
由此解决了这个问题。