【问题标题】:copy Word document contents without using clipboard (VBA)不使用剪贴板复制 Word 文档内容 (VBA)
【发布时间】:2010-10-02 11:43:12
【问题描述】:

我想知道当您想“复制”Word 文档的多个部分(在宏中使用 VBA)时,如何避免使用 Windows 剪贴板

为什么要避免?因为我们在服务器上使用 Word,在多用户环境中(我知道它是官方不赞成的)

否则,这可以通过 Selection.Copy 和 Selection.Paste 方法轻松完成。

谢谢。

【问题讨论】:

  • 没问题,但让我们明确一点,它并不是“官方不赞成”它完全不受支持,迟早会导致您的组件失败......可能是当您不希望它发生时。跨度>
  • 我同意 :) 是的,它给我们带来了很多问题。但你知道它是怎么回事 - 我们多年前坚持使用它 - 现在仍然必须支持它 - 当然我们将来不会采用同样的方法

标签: vba ms-word


【解决方案1】:

我终于下定决心逐字复制。 FormattedText 似乎工作得相当好,直到最后一个单词(一些特殊(显然)字符),突然我刚刚填充复制内容的单元格变为空白。当我增加单元格的数量时,会弹出其他运行时错误,例如您的表已损坏,以及其他模棱两可的错误。不知何故,我从中复制的源单元格最后似乎总是有这些特殊的字符,ASCII 码为 13 和 7。我知道 13 是什么意思,但是 7? 无论如何,我决定用代码 7 复制除最后一个字符之外的所有内容。它似乎工作正常。格式和字段也被复制。 无论如何,整个故事再次向我证明,VBA 编程主要是反复试验的职业。你永远无法确定什么时候会出现问题……除非我错过了一些关键概念的更新……

这是我使用的代码块。这个想法是,首先我们有一个包含单个 1x1 单元格表的文档,其中包含一些富文本内容。在第一段代码(宏内部)中,我将单元格相乘:

Dim cur_width As Integer, i As Integer, max_cells As Integer, cur_row As Integer
Dim origin_width As Integer
   If ActiveDocument.Tables.Count = 1 _
      And ActiveDocument.Tables(1).Rows.Count = 1 _
      And ActiveDocument.Tables(1).Columns.Count = 1 _
   Then
      max_cells = 7   ' how many times we are going to "clone" the original content
      i = 2           ' current cell count - starting from 2 since the cell with the original content is cell number 1
      cur_width = -1  ' current width
      cur_row = 1     ' current row count
      origin_width = ActiveDocument.Tables(1).Rows(1).Cells(1).Width

      ' loop for each row
      While i <= max_cells

          ' adjust current width
          If cur_row = 1 Then
             cur_width = origin_width
          Else
             cur_width = 0
          End If

          ' loop for each cell - as long as we have space, add cells horizontally 
          While i <= max_cells And cur_width + origin_width < ActiveDocument.PageSetup.PageWidth 
              Dim col As Integer

              ' \ returns floor() of the result
              col = i \ ActiveDocument.Tables(1).Rows.Count 

              // 'add cell, if it is not already created (which happens when we add rows)
              If ActiveDocument.Tables(1).Rows(cur_row).Cells.Count < col Then
                 ActiveDocument.Tables(1).Rows(cur_row).Cells.Add
              End If

              // 'adjust new cell width (probably unnecessary
              With ActiveDocument.Tables(1).Rows(cur_row).Cells(col)
                .Width = origin_width
              End With

              // 'keep track of the current width
              cur_width = cur_width + origin_width
              i = i + 1
          Wend

          ' when we don't have any horizontal space left, add row
          If i <= max_cells Then
            ActiveDocument.Tables(1).Rows.Add
            cur_row = cur_row + 1
          End If

      Wend
   End If

在宏的第二部分,我用第一个单元格的内容填充每个空单元格:

   ' duplicate the contents of the first cell to other cells
   Dim r As Row
   Dim c As Cell
   Dim b As Boolean
   Dim w As Range
   Dim rn As Range
   b = False
   i = 1

   For Each r In ActiveDocument.Tables(1).Rows
       For Each c In r.Cells
            If i <= max_cells Then
                // ' don't copy first cell to itself
                If b = True Then

                    ' copy everything word by word
                    For Each w In ActiveDocument.Tables(1).Rows(1).Cells(1).Range.Words

                        ' get the last bit of formatted text in the destination cell, as range
                        ' do it first by getting the whole range of the cell, then collapsing it
                        ' so that it is now the very end of the cell, and moving it one character
                        ' before (because collapsing moves the range actually beyond the last character of the range)
                        Set rn = c.Range
                        rn.Collapse Direction:=wdCollapseEnd
                        rn.MoveEnd Unit:=wdCharacter, Count:=-1

                        ' somehow the last word of the contents of the cell is always Chr(13) & Chr(7)
                        ' and especially Chr(7) causes some very strange and murky problems
                        ' I end up avoiding them by not copying the last character, and by setting as a rule
                        ' that the contents of the first cell should always contain an empty line in the end
                        If c.Range.Words.Count <> ActiveDocument.Tables(1).Rows(1).Cells(1).Range.Words.Count Then
                            rn.FormattedText = w
                        Else
                            'MsgBox "The strange text is: " & w.Text
                            'the two byte values of this text (which obviously contains special characters with special
                            'meaning to Word can be found (and watched) with
                            'AscB(Mid(w.Text, 1, 1)) and  AscB(Mid(w.Text, 2, 1))
                            w.MoveEnd Unit:=WdUnits.wdCharacter, Count:=-1
                            rn.FormattedText = w
                        End If
                    Next w

                End If
                b = True
            End If

            i = i + 1
       Next c
   Next r

以下是相关 Word 文档的图片。第一张图片是在运行宏之前,第二张是在第一段代码和最后一段之间,第三张是生成的文档。

Image 1 Image 2 Image 3

就是这样。

【讨论】:

  • 1.表格单元格的问题是已知的。如果您查看激活了非打印字符显示的 Word 表格,您会在每个单元格的末尾看到一个小“太阳”。这结合了 ANSI 13(= Word 中的新段落)和 ANSI 7(单元格结尾字符)。 ANSI 7 携带所有单元格结构/格式信息,因此如果您“复制”它,结果在逻辑上是一个表格单元格。在“复制”之前,需要从 Range 中删除最后一个字符,这是一种已知的技术。
  • 2.通常,这是通过将 Range 分配给一个对象,然后将 Range 的末尾向后移动一个字符来完成的: Dim rng as Word.Range = Table.Cells(1).Range : rng.MoveEnd(wdCharacter, -1)
【解决方案2】:

在 Office 2007+ VSTO 中,您可以使用Range.ExportFragment 导出块,然后转到您的新文档并使用Range.ImportFragment 将其导入。我还没有在生产中使用它,但尝试过它,它似乎工作正常。

需要注意的是,我在尝试导出为 .docx 时出错,但 RTF 似乎可以正常工作。

VBA 中也存在这两种方法,但我只测试了 VSTO 方法。

【讨论】:

    【解决方案3】:

    这并不总是有效,例如文本字段、图表,或者如果您需要将其复制到另一个文档,但它适用于在一个文档中复制简单的格式化文本。

    'First select something, then do
    Word.WordBasic.CopyText
    'Then move somewhere
    Word.WordBasic.OK;
    

    要将整个文档复制到新文档,请使用以下命令:

    Word.Application.Documents.Add Word.ActiveDocument.FullName
    

    【讨论】:

      【解决方案4】:

      我遇到了类似的问题。我想在不使用剪贴板的情况下使用 Powershell 将表格从一个 word doc 复制到另一个。由于在脚本运行时使用计算机的用户可以使用剪贴板破坏脚本。我想出的解决方案是:

      1. 打开源文档并放置一个涵盖我想要的范围的书签(在我的例子中是一个表)。
      2. 将源文档及其书签保存在另一个位置(以避免更改源文档)。
      3. 打开目标文档并为我想要放置表格的位置创建了一个范围对象。
      4. range.InsertFile 与带有我的书签的源文件的第一个参数和我的书签名称的第二个参数一起使用。这个单一的操作将整个表格和源格式直接拉到目标文档中。

      然后,我根据插入的位置以及故事需要多长时间来添加代码,以选择插入的表以允许对其进行进一步操作。

      我尝试了许多其他方法来移动桌子,这是迄今为止最好的。抱歉,我无法为此解决方案提供 VBA 代码。

      【讨论】:

        【解决方案5】:

        使用 Selection 对象的 Text 属性将数据放入字符串变量而不是剪贴板:

        将 strTemp 调暗为字符串

        strTemp = Selection.Text

        然后,您可以根据需要将存储在变量中的文本插入到其他地方。

        【讨论】:

        • 嗯?其他东西呢,比如 ole 图像、域代码等?如果你想要的只是文本,否则很好
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多