直接上代码:
from PIL import Image
import xlwings as xw
b1 = xw.Book()
sht = b1.sheets[0]
bg = Image.open("11.png")
bg = bg.convert("RGBA")
h = bg.size[0]
w = bg.size[1]
print(h,w)
for x in range(h):
for y in range(w):
#sht[y,x].value = bg.getpixel((x,y))[0]
if (bg.getpixel((x,y))[:3] != (255,255,255)):
sht[y,x].value = "%s, %s" % (x + 1, y + 1)
----------------------------------------------分隔线----------------------------------------------------
上面的方法可取但是出图速度比较慢,来个快的:
def get_desktop():#桌面路径
import winreg
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
return winreg.QueryValueEx(key,"Desktop")[0]
def get_rgb(rgb):
rgb = rgb[0] + (rgb[1] * 256) + (rgb[2] * 256 * 256)#RGB换算成VBA识别的color值
return rgb
def getV2C(shName):
from PIL import Image
import xlwings as xw
import numpy as np
b1 = xw.Book()
sht = b1.sheets[0]
sht.name = shName[:-4]
sht.range("A:XFD").api.ColumnWidth = 1.78 #设置所有的列宽为1.78(相当于26像素)与行高的初始值相同。
sht.range("A1").api.Application.ReferenceStyle = 2 #设置单元格的引用样式为R1C1(因为VAB对象结构是无限循环的,所以调用起来非常方便)
# sht.range("A1").api.Application.ActiveWindow.Zomm = 15 #这一方法放到VBA脚本里面去了,在此执行容易出错
bg = Image.open(shName)
bg = bg.convert("RGBA")
w = bg.size[0]
h = bg.size[1]
# print(w,h)#打印宽和高
ilist = np.zeros((h,w)) #新建一个多维数组,这也是调用np的唯一目的,方便快捷!
#注意这里先高后宽是因为图片像素坐标系统与list是不一样的,此处相当于行列互换。否则结果可能不是你想要的。
ilist = ilist.tolist() #将np对象转换为pytohn的list
# print(len(ilist))
for y in range(h):
for x in range(w):
rgb = get_rgb(bg.getpixel((x,y)))
transparency = bg.getpixel((x,y))[3]
# print(x,y,bg.getpixel((x,y)),rgb,transparency)
if bg.getpixel((x,y))[:3] != (255,255,255) and transparency >= 254:
# 白色的RGB值为(255,255,255),因为EXCEL默认单元格曾经背景就是白色,所以只要不是白色和纯透明的色就赋值rgb,否则赋空值
ilist[y][x] = rgb
else:
ilist[y][x] = None
sht.range("a1").value = ilist #直接给A1单元格填入ilist的值
sht.range("a1").api.SpecialCells(2, 23).NumberFormatLocal = ";;;"#为非空单元格设置单元格格式
try:
v2c = b1.app.macro("v2c.getcolor")#调用加载项中的SUB,模块名为 v2c ,sub名为 getcolor代码如下
"""
新建一个excel文件,打开VBA工程,插入模块,修改模块名为: v2c
输入以下代码,并另存为xla或xlam
再将此文件添加到EXCEL加载项中
Sub getcolor()
Dim Rngs As Range
Set Rngs = Range("a1").SpecialCells(2, 23)
For Each Rng In Rngs:
With Rng
.Interior.Color = .Value
End With
Next
ActiveWindow.Zoom = 15
End Sub
"""
v2c()#执行指向的vba过程,即getcolor()
except:
print("调用VBA模块失败")
else:
ipath = get_desktop()
b1.save("%s\\%s.xlsx" % (ipath, shName[:-4])) #保存到桌面
bg #显示目标图片,这是在一切操作完成之后执行,当完成用
#getV2C END
iName = "bunny girl.png"
#执行命令前手动打开一个空的excel实例(即双击EXCEK图标,新建一个空文档),否则会无法调用加载项。
getV2C(iName)
Sub getcolorz()
Dim Rngs As Range, mi As Range
Set mi = Range("xfd1")
Set Rngs = Range("a1").SpecialCells(2, 23)
For i = 0 To Rngs.Count
mi.Value = 9E+99
For Each Rng In Rngs:
With Rng
If .Value < mi.Value Then Set mi = Rng
End With
Next
If mi = 9E+99 Then
Exit For
Else
mi.Interior.Color = mi.Value
mi = Empty
End If
Next i
End Sub
这段代码可以实现手绘的效果
此方法是先将图片信息换算成EXCEL识别的color值后,写入ilist数组(ilist 数组从np得到),然后一次性写入EXCEL。
再调用excel加载项中的vba过程为单元格上色。
相比前者一个单元格一个单元格赋值调色 快指数级。