首页 文章

如何锁定剪贴板或避免在MS Excel中使用它?

提问于
浏览
2

我正在Excel下编写一个程序,通过将一些数据从一个工作表复制/粘贴到另一个工作表来生成大量电子表格(例如:使用带有一些页眉/页脚单元格的“Layout”工作表,将其复制/粘贴到生成的工作表中) .

我的问题是,有时(不是每次),当运行我的“生成过程”时,Excel会生成此错误(抱歉这是我的法语Excel错误的英文翻译):

错误1004:'_ workheet'对象的'粘贴'方法失败

所以我假设剪贴板存在问题(我的计算机上的其他软件可能同时使用了剪贴板:/)

我首先试图找到一种方法来复制/粘贴我的单元格(和其他东西)而不使用剪贴板,代码如下:

ThisWorkbook.Sheets("Layout").Range("A1").Copy Destination:=ThisWorkbook.Sheets("Test").Range("A1")

或者那个

ThisWorkbook.Sheets("Test").Range("A1") = ThisWorkbook.Sheets("Layout").Range("A1")

但似乎我们只能复制文本或公式,而不是所有的东西(边框,颜色......),也不是图表对象(我有一些)!

所以我试着找到一种在复制/粘贴过程中锁定/解锁剪贴板的方法 . 我发现这个代码可以做到这一点:

Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Declare Function CloseClipboard Lib "user32" () As Long
Declare Function EmptyClipboard Lib "user32" () As Long

Public Sub Lockk()
    If OpenClipboard(0) = 0 Then
        MsgBox "cannot open clipboard."
    ElseIf EmptyClipboard() = 0 Then
        MsgBox "cannot clear clipboard."
    End If
End Sub

Public Sub Unlockk()
    CloseClipboard
End Sub

复制单元格似乎有效:我可以在excel下锁定剪贴板,转到另一个软件(例如记事本),并且不能将一些数据粘贴到该软件中;回到excel,我可以复制/粘贴数据(手动或使用宏) .

But:

  • 似乎粘贴一个单元格会解锁剪贴板(我可以锁定,转到记事本,记事本无法访问剪贴板,返回excel,复制/粘贴单元格,返回记事本,然后记事本可以访问到剪贴板;我没有明确解锁剪贴板) . 这对我来说不是一个真正的问题 .

  • 锁定剪贴板后,我们无法复制/通过Chart对象(手动或使用宏) . 使用宏,我得到与以前完全相同的错误) .

那么,有人想知道如何锁定/解锁剪贴板来复制图表对象吗?或者不使用剪贴板复制它们?

编辑:

用于复制/粘贴图形对象的代码:

Utils_Clipboard.Lockk
ThisWorkbook.Sheets("Layout").ChartObjects("CHART_TEMPLATE").Copy
DoEvents
worksheet_p.Paste Destination:=where_p
Utils_Clipboard.Unlockk

其中worksheet_p是一个Worksheet对象,adn where_p是一个范围 . 请注意,没有第一行和最后一行(Lockk剪贴板),它工作正常(除了一些时间) .

2 回答

  • 0

    好的,我找到了一个解决方案(也许不是最好的解决方案?)

    我可以使用我的Utils_Clipboard.Lockk和Utils_Clipboard.Unlockk来确保复制(复制/粘贴)单元格,合并单元格时,其他软件不会使用剪贴板......

    但似乎,当剪贴板被锁定时,我们无法复制/粘贴图表对象(通过按ctrl c和ctrl v键手动;或者使用metod Copy和Past of objects自动在vba中) .

    我的图表对象解决方案是使用Duplicate(http://msdn.microsoft.com/en-us/library/office/ff840956.aspx)和Move(http://msdn.microsoft.com/en-us)函数/library/office/ff840583.aspx)像这样(其中worksheet_p是我要放置图表对象的工作表):

    Utils_Clipboard.Lockk
    Dim newchart_l As Shape
    Set newchart_l = ThisWorkbook.Sheets("Layout").ChartObjects("CHART_TEMPLATE").Duplicate
    newchart_l.Chart.Location xlLocationAsObject, worksheet_p.Name
    Utils_Clipboard.Unlockk
    

    请注意,复制的对象是Shape而不是ChartObject(如果我们键入ChartObject,则在执行代码时会出错) .

    好吧它正常工作(我认为没有必要在这里锁定剪贴板),但图表对象不是我想要的(在工作表_p上的正确的顶部/左侧坐标) . 为此,我发现我们必须移动ChartArea(复制对象的父级),但我们无法直接操作“newchart_l”(似乎Excel在调用Duplicate后不会更新其所有内部变量) ,为什么???) . 所以我的解决方案是首先检索新的重复图表对象,使用:

    Dim ChartObject_m As Chart
    Set ChartObject_m = worksheet_p.ChartObjects(worksheet_p.ChartObjects.Count).Chart
    

    然后移动该对象的图表区域(其中'where_p'是我想要放置我的项目的范围/单元格):

    ChartObject_m.ChartArea.Left = where_p.Left
    ChartObject_m.ChartArea.Top = where_p.Top
    

    瞧瞧!

  • 0

    受您的解决方案的启发,我有一段我希望分享的改进代码 . 改进之处在于,它不依赖于诸如“ChartObjects-Collection中的图表顺序反映插入顺序”之类的假设:

    Private Function copyGraph(source As ChartObject, pos As Range) As ChartObject
        ' Copies a given graph to the given position and returns the resulting 
        ' ChartObject. The destination position is expected to be a cell in the desired 
        ' target worksheet. The resulting ChartObject will be aligned to the Top/Left-
        ' Border of the given cell. 
    
        Dim dup As Object
        Dim dstChart As Chart
    
        ' First just duplicate the graph. This operation leaves it on the original 
        ' worksheet.
        Set dup = source.Duplicate
    
        ' In case the duplication failed, ... 
        If (Not dup.HasChart) Then
            ' ... we remove the duplicated object and leave the copy function.
            ' This yields a Nothing-reference as return value to signal the error
            ' to the caller.
            dup.Delete
            set copyGraph = Nothing
            Exit Function
        End If
    
        ' Then we move the graph to the target worksheet passed as parameter. This
        ' gives us the new link to the moved chart.
        '
        ' Excel displays some weired behavior when using the reference returned by ChartObject.Duplicate.
        ' Namely it yields sporadic 1004 runtime errors without further specification. However it seems,
        ' that activating the chart and calling location for ActiveChart gets around this problem.
        '
        ' Therefor the original code:
        ' Set dstChart = dup.Chart.Location(xlLocationAsObject, pos.Parent.Name)
        ' has been replaced with the following
        dup.Chart.parent.Activate
        Set dstChart = ActiveChart.Location(xlLocationAsObject, pos.Parent.Name)
    
        ' As we relocated the chart as an object, the parent of the chart object is
        ' an instance of ChartObject. Hence we use it as the return value.
        Set copyGraph = dstChart.parent
    
        ' Finally we move the graph to the requested position passed by the pos 
        ' parameter.
        With copyGraph
            .Top = pos.Top
            .Left = pos.Left
        End With
    End Function
    

    我希望这可以帮助其他用户在这个问题上寻找一个简单的解决方案 .

相关问题