【问题标题】:Excel VBA Macro: Check content (of clipboard?) before pastingExcel VBA宏:粘贴前检查内容(剪贴板?)
【发布时间】:2015-02-24 03:18:56
【问题描述】:

我在将各种来源的数据粘贴到 Excel 时遇到了一些严重问题。 Excel 倾向于尝试变得聪明并进行各种愚蠢的格式化。我们需要文本形式的数据。

问题是我们有很多用户,而且他们中的许多人对计算机不是很熟悉,所以让他们每次都使用右键单击和“选择性粘贴”不是一种选择。

我在录制使用“选择性粘贴”和“文本”的宏并覆盖 ctrl-v 以使用此功能时找到了解决方案。它似乎工作得很好,直到我标记了一个单元格,复制了它,然后尝试粘贴它。宏崩溃了。

所以我需要一个函数来检查我是否尝试粘贴一些复制的文本,然后使用这一行:

 ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:= _
        False

如果我要粘贴标记的单元格,我想运行这一行(仅粘贴值):

Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False

我在为 Excel 编写 VBA 宏方面不是很有经验(我希望我永远不必如此),所以如果有人能提供一些指点,我将不胜感激。

【问题讨论】:

    标签: excel vba copy-paste


    【解决方案1】:

    对于剪贴板访问/操作,您需要在 Project->References 中添加对 Microsoft Forms 2.0 库的引用。然后,您可以使用具有(以及其他)GetFormat 方法的 MSForms.DataObject 类来检查剪贴板是否具有特定类型的数据。

    This 是使用DataObject 处理剪贴板的一个很好的介绍。

    【讨论】:

    • 我在 Win7(64 位)上的 Excel2013(64 位)没有列出 Microsoft Forms 2.0 库。我必须选择工具/参考/浏览...并选择 c:/windows/system32/FM20.DLL 文件。然后就可以使用数据对象类型了。
    【解决方案2】:
    Sub PasteAsText() ' Assign Keyboard Shortcut: Ctrl+v
        Application.ScreenUpdating = False
        Select Case Application.CutCopyMode
            Case Is = False
                    On Error Resume Next
                    ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
            Case Is = xlCopy
                If Not Range(GetClipboardRange).HasFormula Then
                    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
                Else
                    ActiveSheet.Paste
                End If
            Case Is = xlCut
                ActiveSheet.Paste
        End Select
        Application.CutCopyMode = False
        Application.ScreenUpdating = True
    End Sub
    
    Function GetClipboardRange() As String
        ' Edited from http://www.ozgrid.com/forum/showthread.php?t=66773
        Dim formats    'Check to make sure clipboard contains table data
        formats = Application.ClipboardFormats
        For Each fmt In formats
            If fmt = xlClipboardFormatCSV Then
                Application.ActiveSheet.Paste Link:=True  'Paste link
    
                Dim addr1, addr2 As String 'Parse formulas from selection
    
                addr1 = Application.Substitute(Selection.Cells(1, 1).Formula, "=", "")
                addr2 = Application.Substitute(Selection.Cells(Selection.Rows.Count, Selection.Columns.Count).Formula, "=", "")
    
                GetClipboardRange = addr1 & IIf(addr1 <> addr2, ":" & addr2, "")
                Exit For
            End If
        Next
    End Function
    

    【讨论】:

      【解决方案3】:

      这不是最好的解决方案,但它在技术上是可行的。 两个都试试。

      On Error Resume Next
      ActiveSheet.PasteSpecial Format:=Text, Link:=False, DisplayAsIcon:=False
      Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
      

      【讨论】:

        【解决方案4】:

        您是否考虑过使目标工作表中的单元格等于文本?当它们是一般时,Excel 会根据您的期望看到最好的猜测。

        另一方面,如果你真的想实现选择性粘贴...

        没有您可以捕捉到的“粘贴”事件 - 您可以捕捉到每个可能发生粘贴的地方。

        例如,如果您在工作簿启动 (Workbook_Open) 时发出以下代码,则可以捕获 CTRL-V 按键:

        Application.OnKey "^v", "DoMyPaste"
        

        这将调用您的函数而不是 Excel 粘贴函数。把这样的东西放在一个模块中:

        Public Sub DoMyPaste()
            If Selection.[is marked cell] Then
                Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
                :=False, Transpose:=False
            Else
                ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon _
                := False
            End If
        End Sub
        

        我没有测试过这个,这更像是一个粗略的草图。请注意,选择可能不止一个单元格,因此您的“检查标记的单元格”需要以某种方式检查整个范围。

        不过,这只是冰山一角。如果你想要一个完整的解决方案,你应该看看这篇文章,这是捕获所有粘贴调用的 OCD 版本:

        http://www.jkp-ads.com/Articles/CatchPaste.asp
        

        【讨论】:

          猜你喜欢
          • 2015-07-29
          • 2016-08-05
          • 1970-01-01
          • 2017-02-19
          • 2020-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多