Excel VBA将单元格内容复制到InkEdit文本框并保留格式,包括颜色/粗体等

时间:2016-07-30 13:48:02

标签: excel vba excel-vba

我有一张表单,其中一些单元格有多色文本,并以粗体/下划线/斜体显示。

我需要能够拉出单元格内容并在表单上显示保持相同格式的信息。

我遇到了支持RichText的InkEdit控件,但我无法从单元格复制到此框。

请帮助

5 个答案:

答案 0 :(得分:7)

InkEdit控件支持粘贴富文本,因此您真正需要做的就是复制Range,然后将其粘贴到控件中。由于控件公开它的.hWnd,您需要做的就是使用SendMessage API函数发送WM_PASTE消息:

'UserForm1
Option Explicit

Private Declare Function SendMessage Lib "user32" Alias _
            "SendMessageW" (ByVal hwnd As Long, ByVal wMsg As Long, _
            ByVal wParam As Long, lParam As Any) As Long

Private Const WM_PASTE = &H302

Private Sub UserForm_Initialize()
    RangeToInkEdit ActiveSheet.Cells(1, 1), InkEdit1
    Application.CutCopyMode = False
End Sub

Sub RangeToInkEdit(source As Range, target As InkEdit)
    source.Copy
    SendMessage InkEdit1.hwnd, WM_PASTE, 0&, 0&
End Sub

Private Sub CommandButton1_Click()
    Unload Me
End Sub

请注意,此有一个类似于@ JohnColeman方法的轻微问题 - 它在拾取颜色时没有做那么好的工作。这似乎是Excel在RTF编码中发送到剪贴板的问题,而不是InkEdit控件本身的问题(您可以通过复制并粘贴到写字板(基本上是RTF编辑器)来确认)。有些颜色可以使用,有些颜色没有 - 所有颜色的颜色深度都会减少到基本上是RTF支持的最接近颜色。

End result

答案 1 :(得分:6)

问题似乎是Excel对象模型深深掩盖了单元格内容的RTF格式,并没有提供简单的方法来提取它。

这是一个似乎有点工作的kludge:

Sub CopyRichText(source As Range, target As InkEdit)
    Dim i As Long, n As Long
    target.Text = source.Text
    n = Len(target.Text)
    For i = 1 To n
        target.SelStart = i - 1
        target.SelLength = 1
        target.SelBold = source.Characters(i, 1).Font.Bold
        target.SelColor = source.Characters(i, 1).Font.Color
        target.SelFontName = source.Characters(i, 1).Font.FontStyle
        target.SelFontSize = source.Characters(i, 1).Font.Size
        target.SelItalic = source.Characters(i, 1).Font.Italic
        'target.SelUnderline = source.Characters(i, 1).Font.Underline '-- doesn't work as expected!
    Next i
    target.SelStart = n
    target.SelLength = 0
End Sub

像这样使用:

Private Sub UserForm_Initialize()
    CopyRichText Range("A1"), Me.InkEdit1
End Sub

例如,在A1中我有:

enter image description here

然后,当我显示userform时,它看起来像:

enter image description here

墨水编辑的SelUnderline方法似乎存在一个彻头彻尾的错误。取消注释该行以查看我的意思。也许有一些解决方法。

我怀疑上面的内容有些脆弱。我还没有测试过这么多。如果它适合你(也许适当调整) - 好。如果没有,我怀疑使用剪贴板有一种深刻的魔法方法。 InkEdit控件没有粘贴方法 - 但它确实有一个Hwnd方法,听起来它可以为Window粘贴提供目标。

答案 2 :(得分:4)

我提供了两个使用InkEdit Control的函数。

  • PasteToControl:使用API​​调用将数据从ClipBoard粘贴到InkEdit控件中
  • PutInClipBoard:这会将文本复制到ClipBoard中。此函数是必需的,因为如果您设置InkEdit文本属性(例如InkEdit.Text = InkEdit.Text&" Hello!"),您将丢失所有格式。 InkEdit.TextRTF也不会工作。

enter image description here

enter image description here

Private Declare Function PasteToControl Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, Optional ByVal wMsg As Long = &H302, Optional ByVal wParam As Long = 0, Optional lParam As Any = 0&) As Long

'http://www.devx.com/vb2themax/Tip/18632

Private Sub UserForm_Layout()
    InkEdit1.Text = vbCrLf

    Range("A6").Copy
    PasteToControl InkEdit1.hWnd

    PutInClipBoard vbCrLf & "How about Range?" & vbCrLf
    PasteToControl InkEdit1.hWnd
    Range("A2:G4").Copy
    PasteToControl InkEdit1.hWnd

    PutInClipBoard vbCrLf & "Can we do Tables?" & vbCrLf
    PasteToControl InkEdit1.hWnd
    Sheet4.ListObjects("Orders").Range.Copy
    PasteToControl InkEdit1.hWnd

    PutInClipBoard vbCrLf & "Pictures?"
    PasteToControl InkEdit1.hWnd
    Sheet4.Shapes("Picture 1").Copy
    PasteToControl InkEdit1.hWnd

    PutInClipBoard vbCrLf & "Charts?"
    PasteToControl InkEdit1.hWnd
    Sheet4.ChartObjects("Chart 4").Copy
    PasteToControl InkEdit1.hWnd

    PutInClipBoard vbCrLf & "Can we take a snapshot of a Range?" & vbCrLf
    PasteToControl InkEdit1.hWnd
    Range("A6:I12").CopyPicture
    PasteToControl InkEdit1.hWnd

End Sub

Sub PutInClipBoard(Text As String)
    Dim clip As DataObject
    Set clip = New DataObject
    clip.SetText Text
    clip.PutInClipBoard

End Sub

答案 3 :(得分:0)

您需要能够编辑文本吗?如果没有,那么我会尝试复制范围并将其粘贴为UserForm中的图片。查看Stephen Bullen的PastePicture示例代码。

答案 4 :(得分:0)

所以...前一段时间,我想在Excel的UserForms中使用markdown。我创建了一个名为SimpleDown的简单解析器和词法分析器。它有明显的局限性,因此效果非常好。当前,它使用MSForms.Frame作为基本容器,然后使用MSForms.Label(s)作为SimpleDown的每个元素。

下面是一个示例:

# Header Test|| 
---||
* Unordered List 1||
* Unordered List 2||
TESTING of stuff....

上面将产生如下内容:

HEADER


  • 无序列表1
  • 无序列表2

正在测试东西.....


查看科尔曼先生的代码后,我意识到实际上不需要使用Range,Cell或类似的东西。相反,我们可以执行以下操作:

过程:

  • 为要使用的每种特定样式的markdown /富文本/等创建子例程。
  • 创建一个解析器,当到达提供的文本/字符串的部分/部分时,该解析器可以标识要调用的子例程。
  • 在将文本添加到 inkbox 时,让词法分析器确定要为文本的每个子部分调用的子例程。向其传递 inkbox obj,start_pos和section_length。
是的...这应该工作。