2013-08-28 9 views
15

Używam poniższe linie do compy modułów VBA z jednego skoroszytu do drugiego i nie wiem, czy istnieje prostszy sposób, ale oni pracują prawidłowo:Skopiuj kod VBA z arkusza w jednym skoroszycie do drugiego?

Set srcVba = srcWbk.VBProject 
Set srcModule = srcVba.VBComponents(moduleName) 

srcModule.Export (path) 'Export from source 
trgtVba.VBComponents.Remove VBComponent:=trgtVba.VBComponents.Item(moduleName) 'Remove from target 
trgtVba.VBComponents.Import (path) 'Import to target 

Jednak teraz muszę skopiować kod VBA, który znajduje się w arkuszu, a nie w module. Powyższa metoda nie działa w tym scenariuszu.

Jakiego kodu użyć do skopiowania kodu VBA z jednego skoroszytu do drugiego?

+1

Wystarczy skopiować arkusz. Kod będzie się z tym zgadzał. – RBarryYoung

+2

Nie chcę kopiować arkusza, chcę tylko skopiować kod VBA! – user1283776

+0

Zwykle kod w Arkuszu * musi * znajdować się w Arkuszu, jest po prostu napisany w ten sposób. (w przeciwnym razie dlaczego umieścić kod w arkuszu?) – RBarryYoung

Odpowiedz

27

Nie można usunąć i ponownie zaimportować VBComponent, ponieważ spowoduje to logiczne usunięcie całego arkusza roboczego. Zamiast tego trzeba użyć CodeModule manipulowanie tekstu w komponencie:

Dim src As CodeModule, dest As CodeModule 

Set src = ThisWorkbook.VBProject.VBComponents("Sheet1").CodeModule 
Set dest = Workbooks("Book3").VBProject.VBComponents("ThisWorkbook") _ 
    .CodeModule 

dest.DeleteLines 1, dest.CountOfLines 
dest.AddFromString src.Lines(1, src.CountOfLines) 
+1

To jest absolutnie genialne! Jak mogę stać się tak dobry w VBA, jak ty? Czy możesz powiedzieć mi swoje ulubione książki lub źródła, z których najbardziej się nauczyłeś? – user1283776

+8

To dopiero pochodzi z kilku tygodni rozproszonej pracy, próbującej rozwiązać ten sam dokładny problem. Jedyne, co mogłem zrobić, to szturchać i prod na obiektach rozszerzalności VBA, aż znalazłem kilka metod, które niejasno brzmiały jak to, czego potrzebowałem. – Chel

0

To jest skompilowany kod z różnych źródeł, jak również z tego samego jednego Post. Mój wkład to kod, który kopiuje WSZYSTKIE twoje kody z VBE (Arkusze/Thisworkbook/Userforms/Modules/Classes) do nowego skoroszytu.

Stworzyłem to, ponieważ mam skoroszyt skoroszytu i tworzenie kodu, aby odzyskać wszystko, co nie jest uszkodzone, w tym kod. (Ta część odzyskuje tylko kod + referencje):

'needs a reference to : Visual basic for Application Extensibility 5.3 , 
'or run this code : thisworkbook.VBProject.References.AddFromFile "C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" 
'from immediate window (ctrl+G) or create a small sub 

Option Explicit 

Sub CopyComponentsModules() 'copies sheets/Thisworkbook/Userforms/Modules/Classes to a new workbook 
Dim src As CodeModule, dest As CodeModule 
Dim i& 
Dim WB_Dest As Workbook 
'Dim sh As Worksheet 
Dim Comp As VBComponent 

'Set sh = ThisWorkbook.Sheets(1) 
'sh.Cells.Clear 

Set WB_Dest = Application.Workbooks.Add 
On Error Resume Next 'needed for testing if component already exists in destination WorkBook and for cross-references. 
For Each Comp In ThisWorkbook.VBProject.VBComponents 

      'i = i + 1 
      'sh.Cells(i, 1).Value = Comp.Name 

      'Set Source code module 
      Set src = Comp.CodeModule 'ThisWorkbook.VBProject.VBComponents("Sheet1").CodeModule 

      'test if destination component exists first 
      i = 0: i = Len(WB_Dest.VBProject.VBComponents(Comp.Name).Name) 
      If i <> 0 Then 'or: if err=0 then 
       Set dest =  WB_Dest.VBProject.VBComponents(Comp.Name).CodeModule 
      Else 'create component 
       With WB_Dest.VBProject.VBComponents.Add(Comp.Type) 
        .Name = Comp.Name 
        Set dest = .CodeModule 
       End With 
      End If 

      'copy module/Form/Sheet/Class 's code: 
      dest.DeleteLines 1, dest.CountOfLines 
      dest.AddFromString src.Lines(1, src.CountOfLines) 

Next Comp 

'Add references as well : 
Dim Ref As Reference 
For Each Ref In ThisWorkbook.VBProject.References 
    'Debug.Print Ref.Name 'Nom 
    WB_Dest.VBProject.References.AddFromFile Ref.FullPath 
    'Debug.Print Ref.FullPath 'Chemin complet 
    'Debug.Print Ref.Description 'Description de la référence 
    'Debug.Print Ref.IsBroken 'Indique si la référence est manquante 
    'Debug.Print Ref.Major & "." & Ref.Minor 'Version 
    'Debug.Print "---" 
Next Ref 

Err.Clear: On Error GoTo 0 

'WB_Dest.Activate 

Set Ref = Nothing 
Set src = Nothing 
Set dest = Nothing 
Set Comp = Nothing 
Set WB_Dest = Nothing 
End Sub 
1

czy ktoś wyląduje tutaj szukając VSTO równowartość odpowiedź chel, oto ona:

void CopyMacros(Workbook src, Workbook dest) 
{ 
    var srcModule = src.VBProject.VBComponents.Item(1).CodeModule; 
    var destModule = dest.VBProject.VBComponents.Add(Microsoft.Vbe.Interop.vbext_ComponentType.vbext_ct_StdModule); 

    destModule.CodeModule.AddFromString(srcModule.Lines[1, srcModule.CountOfLines]); 
} 

warte Uwaga:

  1. Aby to zrobić, należy dodać odniesienie do Microsoft.Vbe.Interop.
  2. Dodaję nowy moduł ogólny do skoroszytu docelowego, więc nie trzeba było dzwonić pod numer DeleteLines. YMMV.
+0

Każdy, kto chce to zrobić w .Net, może również spojrzeć na kod źródłowy mojego [narzędzia VBA Sync Tool] (https://github.com/chelh/VBASync) – Chel

Powiązane problemy