2009-01-20 49 views
5

tôi đã tự hỏi làm thế nào để tránh sử dụng Windows clipboard, khi bạn muốn "tái tạo" nhiều phần của một tài liệu Word (sử dụng VBA trong macro)copy Lời nội dung tài liệu mà không cần sử dụng clipboard (VBA)

Tại sao để tránh? Vì chúng tôi đang sử dụng Word trên máy chủ, trong môi trường đa người dùng (tôi biết rằng nó được chính thức cau mày)

Nếu không, điều này sẽ dễ dàng thực hiện với các phương pháp Selection.Copy và Selection.Paste.

Cảm ơn.

+0

tốt để làm, nhưng hãy để rõ ràng, nó không "chính thức cau mày" của nó hoàn toàn không được hỗ trợ và sẽ sớm hay muộn gây ra thành phần của bạn thất bại ... có lẽ khi bạn không muốn nó. –

+0

tôi đồng ý :) và có, nó gây ra cho chúng tôi rất nhiều vấn đề. nhưng bạn biết nó như thế nào - chúng tôi bị mắc kẹt với nó năm trước - và vẫn phải hỗ trợ nó ngay bây giờ - tất nhiên chúng tôi sẽ không thực hành cách tiếp cận tương tự trong tương lai –

Trả lời

3

Cuối cùng tôi đã quyết định sao chép từng chữ một. FormattedText dường như hoạt động khá tốt, cho đến khi từ cuối cùng (một số ký tự đặc biệt (rõ ràng), nơi đột nhiên ô mà tôi vừa điền với nội dung đã sao chép sẽ bị trống. Khi tôi tăng số lượng ô, các lỗi thời gian chạy khác sẽ xuất hiện, như bảng của bạn bị hỏng và các lỗi khác không rõ ràng. Bằng cách nào đó, các tế bào nguồn mà tôi đã sao chép từ luôn luôn dường như có những ký tự đặc biệt cuối cùng với mã ASCII 13 và 7. Tôi biết những gì 13 có nghĩa là, nhưng 7? Dù sao, tôi quyết định sao chép tất cả mọi thứ ngoài ký tự cuối cùng này với mã 7. Có vẻ như nó hoạt động tốt. Cả định dạng và trường đều được sao chép. Trong mọi trường hợp, toàn bộ câu chuyện đã chứng minh cho tôi một lần nữa rằng lập trình trong VBA chủ yếu là thử nghiệm và lỗi nghề nghiệp. Bạn không bao giờ chắc chắn khi có điều gì đó có thể phá vỡ .. trừ khi tôi thiếu thông tin cập nhật về một số khái niệm quan trọng ..

Đây là các đoạn mã tôi đã sử dụng. Ý tưởng là đầu tiên chúng tôi có một tài liệu với một bảng ô 1x1 duy nhất, với một số nội dung văn bản phong phú. Trong phần đầu tiên của mã (bên trong macro) Tôi nhân tế bào:

(Chú ý rằng tôi đặt // vào trước mỗi apostrophe loại VB comment để các bình luận sẽ được tô màu một cách chính xác)

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 

trong phần thứ hai của vĩ mô tôi cư mỗi ô trống với các nội dung của ô đầu tiên:

//' 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 

Dưới đây là những hình ảnh của các tài liệu Word trong câu hỏi. Hình ảnh đầu tiên là trước khi chạy macro, thứ hai là giữa đoạn mã đầu tiên và đoạn cuối cùng, trong khi hình ảnh thứ ba là tài liệu kết quả.

Image 1 Image 2 Image 3

Vậy là xong.

+0

+1 vì đó là mã sử thi. – user51498

+0

1. Vấn đề với các ô bảng được biết. Nếu bạn nhìn vào một bảng Word với màn hình hiển thị các ký tự không in được kích hoạt, bạn sẽ thấy một chút "mặt trời" ở cuối mỗi ô. Điều này kết hợp ANSI 13 (= đoạn mới trong Word) cộng với ANSI 7 (ký tự cuối cùng của ô). ANSI 7 mang tất cả thông tin cấu trúc/định dạng ô, vì vậy nếu bạn "sao chép" nó, kết quả là một ô bảng hợp lý. Đó là một kỹ thuật được biết rằng ký tự cuối cùng cần phải được loại bỏ khỏi Phạm vi trước khi bạn "sao chép". –

+0

2. Thông thường, điều đó được thực hiện bằng cách gán Phạm vi cho một đối tượng, sau đó di chuyển đầu của dãy trở lại bằng một ký tự: Dim rng dưới dạng Word.Range = Table.Cells (1) .Range: rng.MoveEnd (wdCharacter, - 1) –

-1

Sử dụng các Văn bản tài sản của đối tượng lựa chọn để đưa dữ liệu vào một chuỗi biến hơn là vào clipboard:

Dim strTemp như String

strTemp = Selection.Text

Bạn có thể sau đó chèn văn bản được lưu trữ trong biến ở nơi khác nếu cần.

+1

huh? những thứ khác, như hình ảnh ole, mã trường, v.v ...? nếu không thì tốt nếu tất cả những gì bạn muốn là văn bản –

1

Điều này không phải lúc nào cũng hoạt động, với trường văn bản, sơ đồ, hoặc nếu bạn cần sao chép nó sang tài liệu khác, nhưng tốt cho việc sao chép văn bản được định dạng đơn giản bên trong một tài liệu.

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

Để sao chép toàn bộ tài liệu để việc sử dụng tài liệu mới này:

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

Tôi chạy vào một vấn đề tương tự. Tôi muốn sao chép một bảng từ một tài liệu từ này sang tài liệu khác bằng cách sử dụng Powershell mà không cần sử dụng khay nhớ tạm. Vì người dùng đang sử dụng máy tính trong khi tập lệnh chạy có thể phá vỡ tập lệnh bằng cách sử dụng khay nhớ tạm. Giải pháp mà tôi đưa ra là:

  1. Mở tài liệu nguồn và đặt dấu trang bao gồm phạm vi những gì tôi muốn (trong trường hợp của tôi là một bảng).
  2. Lưu tài liệu nguồn có dấu trang ở một vị trí khác (để tránh thay đổi tài liệu nguồn).
  3. Mở tài liệu đích và tạo đối tượng phạm vi cho nơi tôi muốn đặt bảng.
  4. Đã sử dụng range.InsertFile với thông số đầu tiên của tệp nguồn có dấu trang của tôi và thông số thứ hai của tên dấu trang của tôi. Thao tác đơn này kéo toàn bộ bảng cộng với định dạng nguồn trực tiếp vào tài liệu đích.

Sau đó, tôi đã thêm mã dựa vào vị trí chèn đã được thực hiện và câu chuyện sẽ được chọn bao lâu để chọn bảng đã chèn để cho phép các thao tác tiếp theo trên đó.

Tôi đã thử nhiều phương pháp khác để di chuyển bảng và điều này là tốt nhất. Xin lỗi tôi không thể cung cấp mã VBA cho giải pháp này.

1

Trong Office 2007+ VSTO, bạn có thể xuất khối với Range.ExportFragment và sau đó chuyển đến tài liệu mới của bạn và nhập nó với Range.ImportFragment. Tôi đã không sử dụng này trong sản xuất, nhưng thử nghiệm với nó và nó có vẻ làm việc OK.

Một báo trước, tôi gặp lỗi khi cố gắng xuất dưới dạng .docx, nhưng RTF có vẻ hoạt động tốt.

Cả hai phương pháp đều tồn tại trong VBA, nhưng tôi chỉ thử nghiệm các phương pháp VSTO.

Các vấn đề liên quan