|
本帖最后由 TuskAi 于 2022-12-14 11:59 编辑
经常看到根据Excel中一列的名称引用另一列对应图片的需求
图片为用户手动添加,实际位置可能会跨单元格
如果只是用循环图片对象判断TopLeftCell位置来确认,可能会导致提取错误
所以想到是否可以用判断图片与名称对应的单元格重合的比例来判断
单元格和图片都有Left,Top,Width,Height四个属性,即横坐标,纵坐标,宽度,高度
根据这四个属性可得到四个点的坐标
而单元格可以用range(cells(行1,列1),cells(行2,列2))的形式表示,刚好也需要四个参数
如果用图片和单元格的四个坐标分别表示两个单元格,再用intersect判断
若有交叉值,说明二者重合(也可能只是边界重合,可用重合单元格个数/(图片_单元格数+单元格_单元格数)来判断重合度)
如果重合度大于指定值,则认为图片在对应的单元格中
示例里的代码
- Sub test()
- Dim d As Object
- Dim rg As Range
- Dim sp As Shape
- Set d = CreateObject("Scripting.dictionary")
- For Each rg In Range("A2:A4") '将名称及对应的单元格存入字典
- d.Add rg.Value, rg.Offset(0, 1)
- Next rg
- For Each rg In Range("D2:D4") '循环输出区域名称
- For Each sp In Shapes '循环图片
- If 获取shape与range的重合度(d(rg.Value), sp, 0.6) = True Then '判断图片与输入区域单元格的重合度是否大于指定值
-
- '复制图片至输出单元格
- sp.Copy
- rg.Offset(0, 1).Select
- ActiveSheet.Paste
-
- '锁定纵横比,将图片调整到不大于输出单元格
- Selection.ShapeRange.LockAspectRatio = msoTrue
-
- If Selection.Height > rg.Offset(0, 1).Height Then Selection.Height = rg.Offset(0, 1).Height
- If Selection.Width > rg.Offset(0, 1).Width Then Selection.Width = rg.Offset(0, 1).Width
-
- GoTo flag1 '跳出图片循环
- End If
- Next sp
- flag1:
- Next rg
- End Sub
- Function 获取shape与range的重合度(rg As Range, sp As Shape, chd As Double) As Boolean
- Dim rg_rg As Range
- Dim rg_sp As Range
- 获取shape与range的重合度 = False
- '将单元格坐标与图片坐标转化为区域
- Set rg_rg = Range(Cells(rg.Top, rg.Left), Cells(rg.Top + rg.Height - 1, rg.Left + rg.Width - 1))
- Set rg_sp = Range(Cells(sp.Top, sp.Left), Cells(sp.Top + sp.Height - 1, sp.Left + sp.Width - 1))
-
- '判断区域重合度
- If Not Application.Intersect(rg_rg, rg_sp) Is Nothing Then
- If Application.Intersect(rg_rg, rg_sp).Count / rg_sp.Count >= chd Then
- 获取shape与range的重合度 = True
- End If
- End If
- End Function
复制代码
附件
VBA利用intersect判断Excel中图片位置并引用.zip
(175.23 KB, 下载次数: 33)
四年前发在知乎的文章
https://zhuanlan.zhihu.com/p/36094403
那时失业了,还想靠这招换一份外卖钱,结果没换到,现在又失业了
|
|