【问题标题】:Copying and pasting an image in Excel locks the reference在 Excel 中复制和粘贴图像会锁定参考
【发布时间】:2021-05-27 15:27:46
【问题描述】:

我正在尝试使用 VBA 管理图片,但遇到了一些问题

我有一个 Excel 电子表格,其中的图片具有自定义名称“花”

当我复制和粘贴时,新图像保持相同的名称“花”

我添加了一个宏,当我点击图片时,它会告诉我点击的是哪张图片。

Sub ImageClicked()
' ImageClicked

    shapeID = ActiveSheet.Shapes(Application.Caller).ID 
    MsgBox (shapeID)
End Sub

但问题是当我点击两张图片时,输出是一样的,它显示相同的ID。

当我删除第一个原始图像并单击第二个图像时,显示的 ID 会发生变化。

我做错了什么吗?

附:我已经想通了,如果我原来的形状是“矩形 1”,那么复制出来的形状就是“矩形 2”,没有问题。

【问题讨论】:

  • 复制或复制粘贴时形状名称相同,这就是它在 Excel 中的发生方式。普通的。 ID行为是否正常,我不确定。从来没有玩过。
  • 您有 2 个选项 1. 如果您手动复制和粘贴,则创建并运行代码,按顺序重命名工作簿中的所有图像。这种变化可能是您选择一个图像并通过代码重命名它。 2. 如果要复制和粘贴图像,请在粘贴后立即重命名图像。
  • 这种行为只发生在复制/粘贴上,通常你不能用相同的名字命名 2 张图片。这显然是 Excel 中的一个错误,因为名称应该是唯一的。因此,您需要解决该错误并确保您的所有图片都有唯一的名称。
  • @FaneDuru 是的,它发生在同一张纸上,但前提是形状名称不是 Excel 创建的通用名称 Rectangle 1。复制Rectangle 1 会将其重命名为Rectangle 2,但如果您将该名称更改为SomeRectangle,如果您复制它们,您将拥有2 个具有该名称的形状。这是一个错误。
  • @Pᴇʜ:是的,我现在想起来了,这种奇怪的行为。复制后立即更改名称是很好的。新形状为sheet.Shapes(sheet.Shapes.Count)

标签: excel vba


【解决方案1】:

您实际遇到的问题是您的形状名称不是唯一的,VBA 现在会选择它找到的第一个具有该名称的形状。这是由于 Excel 中的一个错误,即如果您复制形状,它们的名称完全相同,但不能有重复的名称。

我多次遇到这个错误,所以我编写了一个代码来轻松修复它并确保形状名称是唯一的。有时您无法控制复制/粘贴过程,因为其他用户这样做了并且仍然需要唯一的名称。

您可以使用以下代码来确保活动工作表中的形状名称唯一。

Option Explicit

Public Sub MakeShapeNamesUniqueInActiveSheet()
    MakeShapeNamesUnique InWorksheet:=ActiveSheet
End Sub

Public Sub MakeShapeNamesUnique(ByVal InWorksheet As Worksheet)
    Dim Dict As Object
    Set Dict = CreateObject("Scripting.Dictionary")
    
    ' collect all shape names and how often they occur
    Dim Shp As Shape
    For Each Shp In InWorksheet.Shapes
        If Dict.Exists(Shp.Name) Then
            Dict(Shp.Name) = Dict(Shp.Name) + 1
        Else
            Dict.Add Shp.Name, 1
        End If
    Next Shp
    
    ' check which need to be renamed (duplicates) and rename them
    Dim Key As Variant
    For Each Key In Dict.keys
        If Dict(Key) > 1 Then  ' rename only if dupicate names exist
            Dim iCount As Long
            iCount = 1
            
            Dim iShp As Long
            For iShp = 1 To Dict(Key)
                Dim NewName As String
                NewName = Key & iCount
                
                ' make sure already existing new names get jumped
                Do While ShapeExists(NewName, InWorksheet)
                    iCount = iCount + 1
                    NewName = Key & iCount
                Loop
                
                InWorksheet.Shapes(Key).Name = NewName  ' rename the shape
                iCount = iCount + 1
            Next iShp
        End If
    Next Key
End Sub


Public Function ShapeExists(ByVal ShapeName As String, ByVal InWorksheet As Worksheet) As Boolean
' Test if a shape exists in a worksheet
    On Error Resume Next
    Dim Shp As Shape
    Set Shp = InWorksheet.Shapes(ShapeName)
    On Error GoTo 0
    
    ShapeExists = Not Shp Is Nothing
End Function

例如,如果您的工作表中有以下形状名称

Flower
Flower
Flower
Flower
Flower2
Bus
Car
Car
Car

使用代码后重命名为

Flower1
Flower3
Flower4
Flower5
Flower2
Bus
Car1
Car2
Car3

请注意,重命名算法会检测是否需要重命名。例如Bus 不需要重命名,因为它已经是唯一的。它还检测到 Flower2 已经存在并在重命名 4 个 Flower 形状时跳过该数字 2,因此您最终会得到 Flower1…5,否则您最终会得到 2 个 Flower2 形状。


以下代码sn-p可用于调试,列出所有形状名称并快速查看:

Public Sub ListAllShapeNamesInActiveSheet()
    ListAllShapeNames InWorksheet:=ActiveSheet
End Sub

Public Sub ListAllShapeNames(ByVal InWorksheet As Worksheet)
    Dim Shp As Shape
    For Each Shp In InWorksheet.Shapes
        Debug.Print Shp.Name
    Next Shp
End Sub

【讨论】:

  • 投了赞成票。如果复制后不立即更改名称,则可以仅重命名具有相同名称的名称
  • @FaneDuru 是的,实际上在复制之后直接重命名它会是一种更好的方法。但有时,如果您无法控制复制过程(例如,其他用户创建了工作表),那么让我发布类似的内容来修复它是很有用的。
  • 正确!对于这种情况,这是一个很好的解决方案。这就是我投票支持它的原因...... :)
猜你喜欢
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多